1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-31 05:40:03 -04:00
Files
egui/egui_demo_lib/src/apps/demo/widgets.rs
Cristian Dinu ba12f9e81f Implement tabs as spaces
When we load a string in `TextEdit` we keep the tabs as they are.

Now depending on `tab_as_spaces` and `tab_size` properties of the
`TextEdit` we have the following situations:

- When `tab_as_spaces` is false, then when we press `TAB` a `TAB`
  char in added to the string.

- When `tab_as_spaces` is true, then when we press `TAB` a chunck
  of `tab_size` spaces is added to the string.

To config `tab_as_spaces` and `tab_size` to the values we want we
can use the folliwing helper functions:

- `TextEdit::tab_as_spaces()`
- `TextEdit::tab_size()`

Example usage:

```rust
ui.add(egui::TextEdit::multiline(&mut self.multiline_text_input)
    .tab_as_spaces(self.tab_as_spaces)
    .tab_size(self.tab_size));
```

Demo:
A better demo of this new functionality was implemented in the
misc widgets demo

What's left to do:
- Render actual `TAB` as a rect the size of `tab_size` spaces.

- Without default parameters values it seems a pain to implement.

  I need to think if it is possible to avoid API breaking changes
  for the font system. From my checks so far I need to pass at
  least `tab_size` to the fonts system to know how big the glyph
  for `TAB` will be.
2021-03-23 19:44:49 +02:00

166 lines
5.6 KiB
Rust

use egui::{color::*, *};
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
enum Enum {
First,
Second,
Third,
}
impl Default for Enum {
fn default() -> Self {
Enum::First
}
}
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "persistence", serde(default))]
pub struct Widgets {
group_enabled: bool,
count: usize,
radio: Enum,
angle: f32,
color: Color32,
single_line_text_input: String,
tab_size: usize,
tab_as_spaces: bool,
multiline_text_input: String,
}
impl Default for Widgets {
fn default() -> Self {
Self {
group_enabled: true,
radio: Enum::First,
count: 0,
angle: std::f32::consts::TAU / 3.0,
color: (Rgba::from_rgb(0.0, 1.0, 0.5) * 0.75).into(),
single_line_text_input: "Hello World!".to_owned(),
tab_size: 4,
tab_as_spaces: true,
multiline_text_input: r#"Text can both be so wide that it needs a line break, but you can also add manual line break by pressing enter, creating new paragraphs.
This is the start of the next paragraph.
Existing tabs are kept as tabs.
Use the configs above to set how new tabs should be handled and test by pressing Tab.
Click me to edit me!"#.to_owned(),
}
}
}
impl Widgets {
pub fn ui(&mut self, ui: &mut Ui) {
ui.vertical_centered(|ui| {
ui.add(crate::__egui_github_link_file_line!());
});
ui.horizontal_wrapped(|ui| {
// Trick so we don't have to add spaces in the text below:
ui.spacing_mut().item_spacing.x = ui.fonts()[TextStyle::Body].glyph_width(' ');
ui.add(Label::new("Text can have").text_color(Color32::from_rgb(110, 255, 110)));
ui.colored_label(Color32::from_rgb(128, 140, 255), "color"); // Shortcut version
ui.label("and tooltips.").on_hover_text(
"This is a multiline tooltip that demonstrates that you can easily add tooltips to any element.\nThis is the second line.\nThis is the third.",
);
ui.label("You can mix in other widgets into text, like");
let _ = ui.small_button("this button");
ui.label(".");
ui.label("The default font supports all latin and cyrillic characters (ИÅđ…), common math symbols (∫√∞²⅓…), and many emojis (💓🌟🖩…).")
.on_hover_text("There is currently no support for right-to-left languages.");
ui.label("See the 🔤 Font Book for more!");
ui.monospace("There is also a monospace font.");
});
let tooltip_ui = |ui: &mut Ui| {
ui.heading("The name of the tooltip");
ui.horizontal(|ui| {
ui.label("This tooltip was created with");
ui.monospace(".on_hover_ui(...)");
});
let _ = ui.button("A button you can never press");
};
ui.label("Tooltips can be more than just simple text.")
.on_hover_ui(tooltip_ui);
ui.group(|ui| {
ui.checkbox(&mut self.group_enabled, "Group enabled");
ui.set_enabled(self.group_enabled);
ui.horizontal(|ui| {
ui.radio_value(&mut self.radio, Enum::First, "First");
ui.radio_value(&mut self.radio, Enum::Second, "Second");
ui.radio_value(&mut self.radio, Enum::Third, "Third");
});
egui::combo_box_with_label(ui, "Combo Box", format!("{:?}", self.radio), |ui| {
ui.selectable_value(&mut self.radio, Enum::First, "First");
ui.selectable_value(&mut self.radio, Enum::Second, "Second");
ui.selectable_value(&mut self.radio, Enum::Third, "Third");
});
});
ui.horizontal(|ui| {
if ui
.button("Click me")
.on_hover_text("This will just increase a counter.")
.clicked()
{
self.count += 1;
}
ui.label(format!("The button has been clicked {} times.", self.count));
});
ui.separator();
ui.horizontal(|ui| {
ui.label("An angle:");
ui.drag_angle(&mut self.angle);
ui.label(format!("{:.3}τ", self.angle / std::f32::consts::TAU))
.on_hover_text("Each τ represents one turn (τ = 2π)");
})
.response
.on_hover_text("The angle is stored in radians, but presented in degrees");
ui.separator();
ui.horizontal(|ui| {
ui.colored_label(self.color, "Click to select a different text color: ");
ui.color_edit_button_srgba(&mut self.color);
});
ui.separator();
ui.horizontal(|ui| {
ui.label("Single line text input:");
let response = ui.text_edit_singleline(&mut self.single_line_text_input);
if response.lost_focus() && ui.input().key_pressed(egui::Key::Enter) {
// …
}
});
ui.horizontal(|ui| {
ui.label("Multiline text input:");
ui.separator();
ui.add(egui::Slider::usize(&mut self.tab_size, 2..=8).text("Tab size"));
ui.separator();
ui.checkbox(&mut self.tab_as_spaces, "Tabs as spaces");
});
ui.add(
egui::TextEdit::multiline(&mut self.multiline_text_input)
.tab_as_spaces(self.tab_as_spaces)
.tab_size(self.tab_size),
);
}
}