summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlampsitter <96946613+lampsitter@users.noreply.github.com>2024-09-10 11:38:26 +0200
committerGitHub <noreply@github.com>2024-09-10 11:38:26 +0200
commitf4697bc007447c6c2674beb4e25f599fb7afa093 (patch)
tree866e759aa7c631ba2776f14070256e22c9b47e28
parent89b6055f9cc8954e0a27d17bae2d10f089592330 (diff)
Use Style's font size in egui_extras::syntax_highlighting (#5090)
<!-- Please read the "Making a PR" section of [`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md) before opening a Pull Request! * Keep your PR:s small and focused. * The PR title is what ends up in the changelog, so make it descriptive! * If applicable, add a screenshot or gif. * If it is a non-trivial addition, consider adding a demo for it to `egui_demo_lib`, or a new example. * Do NOT open PR:s from your `master` branch, as that makes it hard for maintainers to test and add commits to your PR. * Remember to run `cargo fmt` and `cargo clippy`. * Open the PR as a draft until you have self-reviewed it and run `./scripts/check.sh`. * When you have addressed a PR comment, mark it as resolved. Please be patient! I will review your PR, but my time is limited! --> * Closes https://github.com/emilk/egui/issues/3549 * [X] I have followed the instructions in the PR template The syntax highlighting font size was always hardcoded to 12 or 10 depending on what case it was hitting (so not consistent). This is particularly noticeable when you increase the font size to something larger for the rest of the ui. With this the default monospace font size is used by default. Since the issue is closely related to #3549 I decided to implement the ability to use override_font_id too. ## Visualized Default monospace is set to 15 in all the pictures Before/After without syntect: ![normal](https://github.com/user-attachments/assets/0d058720-47ff-49e7-af77-30d48f5e138c) Before/after _with_ syntect: ![syntect](https://github.com/user-attachments/assets/e5c380fe-ced1-40ee-b4b1-c26cec18a840) Font override after without/with syntect (monospace = 20): ![override](https://github.com/user-attachments/assets/efd1b759-3f97-4673-864a-5a18afc64099) ### Breaking changes - `CodeTheme::dark` and `CodeTheme::light` takes in the font size - `CodeTheme::from_memory` takes in `Style` - `highlight` function takes in `Style`
-rw-r--r--crates/egui_demo_app/src/apps/http_app.rs6
-rw-r--r--crates/egui_demo_lib/src/demo/code_editor.rs12
-rw-r--r--crates/egui_demo_lib/src/demo/code_example.rs3
-rw-r--r--crates/egui_demo_lib/src/lib.rs2
-rw-r--r--crates/egui_extras/src/syntax_highlighting.rs129
5 files changed, 118 insertions, 34 deletions
diff --git a/crates/egui_demo_app/src/apps/http_app.rs b/crates/egui_demo_app/src/apps/http_app.rs
index d6b57284..abc728fd 100644
--- a/crates/egui_demo_app/src/apps/http_app.rs
+++ b/crates/egui_demo_app/src/apps/http_app.rs
@@ -224,7 +224,11 @@ fn syntax_highlighting(
let extension = extension_and_rest.first()?;
let theme = egui_extras::syntax_highlighting::CodeTheme::from_style(&ctx.style());
Some(ColoredText(egui_extras::syntax_highlighting::highlight(
- ctx, &theme, text, extension,
+ ctx,
+ &ctx.style(),
+ &theme,
+ text,
+ extension,
)))
}
diff --git a/crates/egui_demo_lib/src/demo/code_editor.rs b/crates/egui_demo_lib/src/demo/code_editor.rs
index 4dad60d3..fe39e1be 100644
--- a/crates/egui_demo_lib/src/demo/code_editor.rs
+++ b/crates/egui_demo_lib/src/demo/code_editor.rs
@@ -67,7 +67,8 @@ impl crate::View for CodeEditor {
});
}
- let mut theme = egui_extras::syntax_highlighting::CodeTheme::from_memory(ui.ctx());
+ let mut theme =
+ egui_extras::syntax_highlighting::CodeTheme::from_memory(ui.ctx(), ui.style());
ui.collapsing("Theme", |ui| {
ui.group(|ui| {
theme.ui(ui);
@@ -76,8 +77,13 @@ impl crate::View for CodeEditor {
});
let mut layouter = |ui: &egui::Ui, string: &str, wrap_width: f32| {
- let mut layout_job =
- egui_extras::syntax_highlighting::highlight(ui.ctx(), &theme, string, language);
+ let mut layout_job = egui_extras::syntax_highlighting::highlight(
+ ui.ctx(),
+ ui.style(),
+ &theme,
+ string,
+ language,
+ );
layout_job.wrap.max_width = wrap_width;
ui.fonts(|f| f.layout_job(layout_job))
};
diff --git a/crates/egui_demo_lib/src/demo/code_example.rs b/crates/egui_demo_lib/src/demo/code_example.rs
index 18a25107..3db90ad3 100644
--- a/crates/egui_demo_lib/src/demo/code_example.rs
+++ b/crates/egui_demo_lib/src/demo/code_example.rs
@@ -130,7 +130,8 @@ impl crate::View for CodeExample {
ui.separator();
- let mut theme = egui_extras::syntax_highlighting::CodeTheme::from_memory(ui.ctx());
+ let mut theme =
+ egui_extras::syntax_highlighting::CodeTheme::from_memory(ui.ctx(), ui.style());
ui.collapsing("Theme", |ui| {
theme.ui(ui);
theme.store_in_memory(ui.ctx());
diff --git a/crates/egui_demo_lib/src/lib.rs b/crates/egui_demo_lib/src/lib.rs
index ce18e091..23c28bcb 100644
--- a/crates/egui_demo_lib/src/lib.rs
+++ b/crates/egui_demo_lib/src/lib.rs
@@ -21,7 +21,7 @@ pub use rendering_test::ColorTest;
/// View some Rust code with syntax highlighting and selection.
pub(crate) fn rust_view_ui(ui: &mut egui::Ui, code: &str) {
let language = "rs";
- let theme = egui_extras::syntax_highlighting::CodeTheme::from_memory(ui.ctx());
+ let theme = egui_extras::syntax_highlighting::CodeTheme::from_memory(ui.ctx(), ui.style());
egui_extras::syntax_highlighting::code_view_ui(ui, &theme, code, language);
}
diff --git a/crates/egui_extras/src/syntax_highlighting.rs b/crates/egui_extras/src/syntax_highlighting.rs
index 8ddd4606..e782677c 100644
--- a/crates/egui_extras/src/syntax_highlighting.rs
+++ b/crates/egui_extras/src/syntax_highlighting.rs
@@ -6,6 +6,7 @@
#![allow(clippy::mem_forget)] // False positive from enum_map macro
use egui::text::LayoutJob;
+use egui::TextStyle;
/// View some code with syntax highlighting and selection.
pub fn code_view_ui(
@@ -14,29 +15,53 @@ pub fn code_view_ui(
code: &str,
language: &str,
) -> egui::Response {
- let layout_job = highlight(ui.ctx(), theme, code, language);
+ let layout_job = highlight(ui.ctx(), ui.style(), theme, code, language);
ui.add(egui::Label::new(layout_job).selectable(true))
}
/// Add syntax highlighting to a code string.
///
/// The results are memoized, so you can call this every frame without performance penalty.
-pub fn highlight(ctx: &egui::Context, theme: &CodeTheme, code: &str, language: &str) -> LayoutJob {
- impl egui::util::cache::ComputerMut<(&CodeTheme, &str, &str), LayoutJob> for Highlighter {
- fn compute(&mut self, (theme, code, lang): (&CodeTheme, &str, &str)) -> LayoutJob {
- self.highlight(theme, code, lang)
+pub fn highlight(
+ ctx: &egui::Context,
+ style: &egui::Style,
+ theme: &CodeTheme,
+ code: &str,
+ language: &str,
+) -> LayoutJob {
+ // We take in both context and style so that in situations where ui is not available such as when
+ // performing it at a separate thread (ctx, ctx.style()) can be used and when ui is available
+ // (ui.ctx(), ui.style()) can be used
+
+ impl egui::util::cache::ComputerMut<(&egui::FontId, &CodeTheme, &str, &str), LayoutJob>
+ for Highlighter
+ {
+ fn compute(
+ &mut self,
+ (font_id, theme, code, lang): (&egui::FontId, &CodeTheme, &str, &str),
+ ) -> LayoutJob {
+ self.highlight(font_id.clone(), theme, code, lang)
}
}
type HighlightCache = egui::util::cache::FrameCache<LayoutJob, Highlighter>;
+ let font_id = style
+ .override_font_id
+ .clone()
+ .unwrap_or_else(|| TextStyle::Monospace.resolve(style));
+
ctx.memory_mut(|mem| {
mem.caches
.cache::<HighlightCache>()
- .get((theme, code, language))
+ .get((&font_id, theme, code, language))
})
}
+fn monospace_font_size(style: &egui::Style) -> f32 {
+ TextStyle::Monospace.resolve(style).size
+}
+
// ----------------------------------------------------------------------------
#[cfg(not(feature = "syntect"))]
@@ -128,6 +153,8 @@ pub struct CodeTheme {
#[cfg(feature = "syntect")]
syntect_theme: SyntectTheme,
+ #[cfg(feature = "syntect")]
+ font_id: egui::FontId,
#[cfg(not(feature = "syntect"))]
formats: enum_map::EnumMap<TokenType, egui::TextFormat>,
@@ -135,40 +162,75 @@ pub struct CodeTheme {
impl Default for CodeTheme {
fn default() -> Self {
- Self::dark()
+ Self::dark(12.0)
}
}
impl CodeTheme {
/// Selects either dark or light theme based on the given style.
pub fn from_style(style: &egui::Style) -> Self {
+ let font_id = style
+ .override_font_id
+ .clone()
+ .unwrap_or_else(|| TextStyle::Monospace.resolve(style));
+
if style.visuals.dark_mode {
- Self::dark()
+ Self::dark_with_font_id(font_id)
} else {
- Self::light()
+ Self::light_with_font_id(font_id)
}
}
+ /// ### Example
+ ///
+ /// ```
+ /// # egui::__run_test_ui(|ui| {
+ /// use egui_extras::syntax_highlighting::CodeTheme;
+ /// let theme = CodeTheme::dark(12.0);
+ /// # });
+ /// ```
+ pub fn dark(font_size: f32) -> Self {
+ Self::dark_with_font_id(egui::FontId::monospace(font_size))
+ }
+
+ /// ### Example
+ ///
+ /// ```
+ /// # egui::__run_test_ui(|ui| {
+ /// use egui_extras::syntax_highlighting::CodeTheme;
+ /// let theme = CodeTheme::light(12.0);
+ /// # });
+ /// ```
+ pub fn light(font_size: f32) -> Self {
+ Self::light_with_font_id(egui::FontId::monospace(font_size))
+ }
+
/// Load code theme from egui memory.
///
/// There is one dark and one light theme stored at any one time.
- pub fn from_memory(ctx: &egui::Context) -> Self {
+ pub fn from_memory(ctx: &egui::Context, style: &egui::Style) -> Self {
#![allow(clippy::needless_return)]
- let (id, default) = if ctx.style().visuals.dark_mode {
- (egui::Id::new("dark"), Self::dark as fn() -> Self)
+ let (id, default) = if style.visuals.dark_mode {
+ (egui::Id::new("dark"), Self::dark as fn(f32) -> Self)
} else {
- (egui::Id::new("light"), Self::light as fn() -> Self)
+ (egui::Id::new("light"), Self::light as fn(f32) -> Self)
};
#[cfg(feature = "serde")]
{
- return ctx.data_mut(|d| d.get_persisted(id).unwrap_or_else(default));
+ return ctx.data_mut(|d| {
+ d.get_persisted(id)
+ .unwrap_or_else(|| default(monospace_font_size(style)))
+ });
}
#[cfg(not(feature = "serde"))]
{
- return ctx.data_mut(|d| d.get_temp(id).unwrap_or_else(default));
+ return ctx.data_mut(|d| {
+ d.get_temp(id)
+ .unwrap_or_else(|| default(monospace_font_size(style)))
+ });
}
}
@@ -192,17 +254,19 @@ impl CodeTheme {
#[cfg(feature = "syntect")]
impl CodeTheme {
- pub fn dark() -> Self {
+ fn dark_with_font_id(font_id: egui::FontId) -> Self {
Self {
dark_mode: true,
syntect_theme: SyntectTheme::Base16MochaDark,
+ font_id,
}
}
- pub fn light() -> Self {
+ fn light_with_font_id(font_id: egui::FontId) -> Self {
Self {
dark_mode: false,
syntect_theme: SyntectTheme::SolarizedLight,
+ font_id,
}
}
@@ -220,8 +284,10 @@ impl CodeTheme {
#[cfg(not(feature = "syntect"))]
impl CodeTheme {
- pub fn dark() -> Self {
- let font_id = egui::FontId::monospace(10.0);
+ // The syntect version takes it by value. This could be avoided by specializing the from_style
+ // function, but at the cost of more code duplication.
+ #[allow(clippy::needless_pass_by_value)]
+ fn dark_with_font_id(font_id: egui::FontId) -> Self {
use egui::{Color32, TextFormat};
Self {
dark_mode: true,
@@ -236,8 +302,9 @@ impl CodeTheme {
}
}
- pub fn light() -> Self {
- let font_id = egui::FontId::monospace(10.0);
+ // The syntect version takes it by value
+ #[allow(clippy::needless_pass_by_value)]
+ fn light_with_font_id(font_id: egui::FontId) -> Self {
use egui::{Color32, TextFormat};
Self {
dark_mode: false,
@@ -291,9 +358,9 @@ impl CodeTheme {
});
let reset_value = if self.dark_mode {
- Self::dark()
+ Self::dark(monospace_font_size(ui.style()))
} else {
- Self::light()
+ Self::light(monospace_font_size(ui.style()))
};
if ui
@@ -348,12 +415,18 @@ impl Default for Highlighter {
impl Highlighter {
#[allow(clippy::unused_self, clippy::unnecessary_wraps)]
- fn highlight(&self, theme: &CodeTheme, code: &str, lang: &str) -> LayoutJob {
+ fn highlight(
+ &self,
+ font_id: egui::FontId,
+ theme: &CodeTheme,
+ code: &str,
+ lang: &str,
+ ) -> LayoutJob {
self.highlight_impl(theme, code, lang).unwrap_or_else(|| {
// Fallback:
LayoutJob::simple(
code.into(),
- egui::FontId::monospace(12.0),
+ font_id,
if theme.dark_mode {
egui::Color32::LIGHT_GRAY
} else {
@@ -377,8 +450,8 @@ impl Highlighter {
.find_syntax_by_name(language)
.or_else(|| self.ps.find_syntax_by_extension(language))?;
- let theme = theme.syntect_theme.syntect_key_name();
- let mut h = HighlightLines::new(syntax, &self.ts.themes[theme]);
+ let syn_theme = theme.syntect_theme.syntect_key_name();
+ let mut h = HighlightLines::new(syntax, &self.ts.themes[syn_theme]);
use egui::text::{LayoutSection, TextFormat};
@@ -402,7 +475,7 @@ impl Highlighter {
leading_space: 0.0,
byte_range: as_byte_range(text, range),
format: TextFormat {
- font_id: egui::FontId::monospace(12.0),
+ font_id: theme.font_id.clone(),
color: text_color,
italics,
underline,