1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 22:53:14 -04:00
Files
egui/crates/egui_demo_lib/src/demo/code_example.rs
lampsitter f4697bc007 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`
2024-09-10 11:38:26 +02:00

174 lines
4.4 KiB
Rust

#[derive(Debug)]
pub struct CodeExample {
name: String,
age: u32,
}
impl Default for CodeExample {
fn default() -> Self {
Self {
name: "Arthur".to_owned(),
age: 42,
}
}
}
impl CodeExample {
fn samples_in_grid(&mut self, ui: &mut egui::Ui) {
// Note: we keep the code narrow so that the example fits on a mobile screen.
let Self { name, age } = self; // for brevity later on
show_code(ui, r#"ui.heading("Example");"#);
ui.heading("Example");
ui.end_row();
show_code(
ui,
r#"
ui.horizontal(|ui| {
ui.label("Name");
ui.text_edit_singleline(name);
});"#,
);
// Putting things on the same line using ui.horizontal:
ui.horizontal(|ui| {
ui.label("Name");
ui.text_edit_singleline(name);
});
ui.end_row();
show_code(
ui,
r#"
ui.add(
egui::DragValue::new(age)
.range(0..=120)
.suffix(" years"),
);"#,
);
ui.add(egui::DragValue::new(age).range(0..=120).suffix(" years"));
ui.end_row();
show_code(
ui,
r#"
if ui.button("Increment").clicked() {
*age += 1;
}"#,
);
if ui.button("Increment").clicked() {
*age += 1;
}
ui.end_row();
show_code(ui, r#"ui.label(format!("{name} is {age}"));"#);
ui.label(format!("{name} is {age}"));
ui.end_row();
}
fn code(&mut self, ui: &mut egui::Ui) {
show_code(
ui,
r"
pub struct CodeExample {
name: String,
age: u32,
}
impl CodeExample {
fn ui(&mut self, ui: &mut egui::Ui) {
// Saves us from writing `&mut self.name` etc
let Self { name, age } = self;",
);
ui.horizontal(|ui| {
let font_id = egui::TextStyle::Monospace.resolve(ui.style());
let indentation = 8.0 * ui.fonts(|f| f.glyph_width(&font_id, ' '));
let item_spacing = ui.spacing_mut().item_spacing;
ui.add_space(indentation - item_spacing.x);
egui::Grid::new("code_samples")
.striped(true)
.num_columns(2)
.show(ui, |ui| {
self.samples_in_grid(ui);
});
});
crate::rust_view_ui(ui, " }\n}");
}
}
impl crate::Demo for CodeExample {
fn name(&self) -> &'static str {
"🖮 Code Example"
}
fn show(&mut self, ctx: &egui::Context, open: &mut bool) {
use crate::View;
egui::Window::new(self.name())
.open(open)
.min_width(375.0)
.default_size([390.0, 500.0])
.scroll(false)
.resizable([true, false])
.show(ctx, |ui| self.ui(ui));
}
}
impl crate::View for CodeExample {
fn ui(&mut self, ui: &mut egui::Ui) {
ui.scope(|ui| {
ui.spacing_mut().item_spacing = egui::vec2(8.0, 8.0);
self.code(ui);
});
ui.separator();
crate::rust_view_ui(ui, &format!("{self:#?}"));
ui.separator();
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());
});
ui.separator();
ui.vertical_centered(|ui| {
ui.add(crate::egui_github_link_file!());
});
}
}
fn show_code(ui: &mut egui::Ui, code: &str) {
let code = remove_leading_indentation(code.trim_start_matches('\n'));
crate::rust_view_ui(ui, &code);
}
fn remove_leading_indentation(code: &str) -> String {
fn is_indent(c: &u8) -> bool {
matches!(*c, b' ' | b'\t')
}
let first_line_indent = code.bytes().take_while(is_indent).count();
let mut out = String::new();
let mut code = code;
while !code.is_empty() {
let indent = code.bytes().take_while(is_indent).count();
let start = first_line_indent.min(indent);
let end = code
.find('\n')
.map_or_else(|| code.len(), |endline| endline + 1);
out += &code[start..end];
code = &code[end..];
}
out
}