mirror of
https://github.com/emilk/egui.git
synced 2026-09-01 06:10:06 -04:00
checkbox & cleanup
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
use emath::Vec2;
|
|
||||||
use epaint::{Color32, FontId, Shadow, Stroke, text::TextWrapMode};
|
use epaint::{Color32, FontId, Shadow, Stroke, text::TextWrapMode};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -36,9 +35,9 @@ pub struct CheckboxStyle {
|
|||||||
pub frame: Frame,
|
pub frame: Frame,
|
||||||
/// Text next to it
|
/// Text next to it
|
||||||
pub text: TextVisuals,
|
pub text: TextVisuals,
|
||||||
/// Box size
|
/// Checkbox size
|
||||||
pub size: f32,
|
pub size: f32,
|
||||||
/// Check size
|
/// Checkmark size
|
||||||
pub check_size: f32,
|
pub check_size: f32,
|
||||||
/// Frame of the checkbox itself
|
/// Frame of the checkbox itself
|
||||||
pub checkbox_frame: Frame,
|
pub checkbox_frame: Frame,
|
||||||
@@ -46,30 +45,6 @@ pub struct CheckboxStyle {
|
|||||||
pub stroke: Stroke,
|
pub stroke: Stroke,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DragValueStyle {
|
|
||||||
/// Frame around
|
|
||||||
pub frame: Frame,
|
|
||||||
/// Text of the value
|
|
||||||
pub text: TextVisuals,
|
|
||||||
pub min_size: Vec2,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct HyperlinkStyle {
|
|
||||||
pub frame: Frame,
|
|
||||||
pub text: TextVisuals,
|
|
||||||
pub size: Vec2,
|
|
||||||
pub checkbox_frame: Frame,
|
|
||||||
pub stroke: Stroke,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ImageStyle {
|
|
||||||
pub frame: Frame,
|
|
||||||
pub text: TextVisuals,
|
|
||||||
pub size: Vec2,
|
|
||||||
pub checkbox_frame: Frame,
|
|
||||||
pub stroke: Stroke,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct LabelStyle {
|
pub struct LabelStyle {
|
||||||
/// Frame around
|
/// Frame around
|
||||||
pub frame: Frame,
|
pub frame: Frame,
|
||||||
@@ -79,32 +54,10 @@ pub struct LabelStyle {
|
|||||||
pub wrap_mode: TextWrapMode,
|
pub wrap_mode: TextWrapMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RadioButtonStyle {
|
|
||||||
pub frame: Frame,
|
|
||||||
pub text: TextVisuals,
|
|
||||||
pub size: Vec2,
|
|
||||||
pub checkbox_frame: Frame,
|
|
||||||
pub stroke: Stroke,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SeparatorStyle {
|
pub struct SeparatorStyle {
|
||||||
pub size: f32,
|
/// How much space is allocated in the layout direction
|
||||||
pub stroke: Stroke,
|
pub spacing: f32,
|
||||||
}
|
/// How to paint it
|
||||||
|
|
||||||
pub struct SliderStyle {
|
|
||||||
pub frame: Frame,
|
|
||||||
pub text: TextVisuals,
|
|
||||||
pub size: Vec2,
|
|
||||||
pub checkbox_frame: Frame,
|
|
||||||
pub stroke: Stroke,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SpinnerStyle {
|
|
||||||
pub frame: Frame,
|
|
||||||
pub text: TextVisuals,
|
|
||||||
pub size: Vec2,
|
|
||||||
pub checkbox_frame: Frame,
|
|
||||||
pub stroke: Stroke,
|
pub stroke: Stroke,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,22 +159,11 @@ impl Style {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drag_value_style(&self, state: WidgetState) -> DragValueStyle {
|
pub fn separator_style(&self, state: WidgetState) -> SeparatorStyle {
|
||||||
let ws = self.widget_style(state);
|
let visuals = self.visuals.widgets.state(state);
|
||||||
DragValueStyle {
|
SeparatorStyle {
|
||||||
frame: ws.frame.inner_margin(self.spacing.button_padding),
|
spacing: 0.0,
|
||||||
min_size: self.spacing.interact_size,
|
stroke: visuals.fg_stroke,
|
||||||
text: ws.text,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn hyperlink_style(&self, state: WidgetState) -> HyperlinkStyle {}
|
|
||||||
|
|
||||||
// pub fn image_style(&self, state: WidgetState) -> ImageStyle {}
|
|
||||||
|
|
||||||
// pub fn slider_style(&self, state: WidgetState) -> SliderStyle {}
|
|
||||||
|
|
||||||
// pub fn separator_style(&self, state: WidgetState) -> SeparatorStyle {}
|
|
||||||
|
|
||||||
// pub fn spinner_style(&self, state: WidgetState) -> SpinnerStyle {}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ impl<'a> Button<'a> {
|
|||||||
|
|
||||||
let text = layout.text().map(String::from);
|
let text = layout.text().map(String::from);
|
||||||
|
|
||||||
// Get the widget style by reading the rect from the previous pass
|
// Get the widget style by reading the response from the previous pass
|
||||||
let id = ui.next_auto_id();
|
let id = ui.next_auto_id();
|
||||||
let response: Option<Response> = ui.ctx().read_response(id);
|
let response: Option<Response> = ui.ctx().read_response(id);
|
||||||
let state = response.map(|r| r.widget_state()).unwrap_or_default();
|
let state = response.map(|r| r.widget_state()).unwrap_or_default();
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use emath::Rect;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Atom, AtomLayout, Atoms, Id, IntoAtoms, NumExt as _, Response, Sense, Shape, Ui, Vec2, Widget,
|
Atom, AtomLayout, Atoms, Id, IntoAtoms, NumExt as _, Response, Sense, Shape, Ui, Vec2, Widget,
|
||||||
WidgetInfo, WidgetType, epaint, pos2,
|
WidgetInfo, WidgetType, epaint, pos2,
|
||||||
@@ -55,7 +57,7 @@ impl Widget for Checkbox<'_> {
|
|||||||
indeterminate,
|
indeterminate,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
// Get the widget style by reading the rect from the previous pass
|
// Get the widget style by reading the response from the previous pass
|
||||||
let id = ui.next_auto_id();
|
let id = ui.next_auto_id();
|
||||||
let response: Option<Response> = ui.ctx().read_response(id);
|
let response: Option<Response> = ui.ctx().read_response(id);
|
||||||
let state = response.map(|r| r.widget_state()).unwrap_or_default();
|
let state = response.map(|r| r.widget_state()).unwrap_or_default();
|
||||||
@@ -109,7 +111,13 @@ impl Widget for Checkbox<'_> {
|
|||||||
let response = prepared.paint(ui);
|
let response = prepared.paint(ui);
|
||||||
|
|
||||||
if let Some(rect) = response.rect(rect_id) {
|
if let Some(rect) = response.rect(rect_id) {
|
||||||
let (small_icon_rect, big_icon_rect) = ui.spacing().icon_rectangles(rect);
|
let big_icon_rect = Rect::from_center_size(
|
||||||
|
pos2(rect.left() + icon_width / 2.0, rect.center().y),
|
||||||
|
Vec2::splat(style.size),
|
||||||
|
);
|
||||||
|
let small_icon_rect =
|
||||||
|
Rect::from_center_size(big_icon_rect.center(), Vec2::splat(style.check_size));
|
||||||
|
|
||||||
ui.painter().add(epaint::RectShape::new(
|
ui.painter().add(epaint::RectShape::new(
|
||||||
big_icon_rect,
|
big_icon_rect,
|
||||||
style.checkbox_frame.corner_radius,
|
style.checkbox_frame.corner_radius,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use std::{cmp::Ordering, ops::RangeInclusive};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Button, CursorIcon, Id, Key, MINUS_CHAR_STR, Modifiers, NumExt as _, Response, RichText, Sense,
|
Button, CursorIcon, Id, Key, MINUS_CHAR_STR, Modifiers, NumExt as _, Response, RichText, Sense,
|
||||||
TextEdit, TextWrapMode, Ui, Widget, WidgetInfo, emath, grid::State, text,
|
TextEdit, TextWrapMode, Ui, Widget, WidgetInfo, emath, text,
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -447,10 +447,6 @@ impl Widget for DragValue<'_> {
|
|||||||
let id = ui.next_auto_id();
|
let id = ui.next_auto_id();
|
||||||
let is_slow_speed = shift && ui.ctx().is_being_dragged(id);
|
let is_slow_speed = shift && ui.ctx().is_being_dragged(id);
|
||||||
|
|
||||||
let response = ui.ctx().read_response(id);
|
|
||||||
let state = response.map(|r| r.widget_state()).unwrap_or_default();
|
|
||||||
let style = ui.style().drag_value_style(state);
|
|
||||||
|
|
||||||
// The following ensures that when a `DragValue` receives focus,
|
// The following ensures that when a `DragValue` receives focus,
|
||||||
// it is immediately rendered in edit mode, rather than being rendered
|
// it is immediately rendered in edit mode, rather than being rendered
|
||||||
// in button mode for just one frame. This is important for
|
// in button mode for just one frame. This is important for
|
||||||
@@ -564,14 +560,13 @@ impl Widget for DragValue<'_> {
|
|||||||
.clip_text(false)
|
.clip_text(false)
|
||||||
.horizontal_align(ui.layout().horizontal_align())
|
.horizontal_align(ui.layout().horizontal_align())
|
||||||
.vertical_align(ui.layout().vertical_align())
|
.vertical_align(ui.layout().vertical_align())
|
||||||
.margin(style.frame.inner_margin)
|
.margin(ui.spacing().button_padding)
|
||||||
.min_size(style.min_size)
|
.min_size(ui.spacing().interact_size)
|
||||||
.id(id)
|
.id(id)
|
||||||
.desired_width(
|
.desired_width(
|
||||||
ui.spacing().interact_size.x - 2.0 * ui.spacing().button_padding.x,
|
ui.spacing().interact_size.x - 2.0 * ui.spacing().button_padding.x,
|
||||||
)
|
)
|
||||||
.text_color(style.text.color)
|
.font(text_style),
|
||||||
.font(style.text.font_id),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Select all text when the edit gains focus.
|
// Select all text when the edit gains focus.
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ impl Label {
|
|||||||
return (pos, galley, response);
|
return (pos, galley, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the widget style by reading the rect from the previous pass
|
// Get the widget style by reading the response from the previous pass
|
||||||
let id = ui.next_auto_id();
|
let id = ui.next_auto_id();
|
||||||
let response: Option<Response> = ui.ctx().read_response(id);
|
let response: Option<Response> = ui.ctx().read_response(id);
|
||||||
let state = response.map(|r| r.widget_state()).unwrap_or_default();
|
let state = response.map(|r| r.widget_state()).unwrap_or_default();
|
||||||
@@ -280,10 +280,6 @@ impl Widget for Label {
|
|||||||
let selectable = self.selectable;
|
let selectable = self.selectable;
|
||||||
let show_tooltip_when_elided = self.show_tooltip_when_elided;
|
let show_tooltip_when_elided = self.show_tooltip_when_elided;
|
||||||
|
|
||||||
// Get the widget style by reading the rect from the previous pass
|
|
||||||
// let id = ui.next_auto_id();
|
|
||||||
// let response: Option<Response> = ui.ctx().read_response(id);
|
|
||||||
|
|
||||||
let (galley_pos, galley, mut response) = self.layout_in_ui(ui);
|
let (galley_pos, galley, mut response) = self.layout_in_ui(ui);
|
||||||
response
|
response
|
||||||
.widget_info(|| WidgetInfo::labeled(WidgetType::Label, ui.is_enabled(), galley.text()));
|
.widget_info(|| WidgetInfo::labeled(WidgetType::Label, ui.is_enabled(), galley.text()));
|
||||||
@@ -309,11 +305,6 @@ impl Widget for Label {
|
|||||||
ui.style().visuals.text_color()
|
ui.style().visuals.text_color()
|
||||||
};
|
};
|
||||||
|
|
||||||
// let underline = if response.has_focus() || response.highlighted() {
|
|
||||||
// Stroke::new(1.0, response_color)
|
|
||||||
// } else {
|
|
||||||
// Stroke::NONE
|
|
||||||
// };
|
|
||||||
let underline = style.text.underline;
|
let underline = style.text.underline;
|
||||||
|
|
||||||
let selectable = selectable.unwrap_or_else(|| ui.style().interaction.selectable_labels);
|
let selectable = selectable.unwrap_or_else(|| ui.style().interaction.selectable_labels);
|
||||||
|
|||||||
@@ -88,11 +88,22 @@ impl Separator {
|
|||||||
impl Widget for Separator {
|
impl Widget for Separator {
|
||||||
fn ui(self, ui: &mut Ui) -> Response {
|
fn ui(self, ui: &mut Ui) -> Response {
|
||||||
let Self {
|
let Self {
|
||||||
spacing,
|
mut spacing,
|
||||||
grow,
|
grow,
|
||||||
is_horizontal_line,
|
is_horizontal_line,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
|
// Get the widget style by reading the response from the previous pass
|
||||||
|
let id = ui.next_auto_id();
|
||||||
|
let response: Option<Response> = ui.ctx().read_response(id);
|
||||||
|
let state = response.map(|r| r.widget_state()).unwrap_or_default();
|
||||||
|
let style = ui.style().separator_style(state);
|
||||||
|
|
||||||
|
// override the spacing if not set
|
||||||
|
if spacing == 0.0 && style.spacing != 0.0 {
|
||||||
|
spacing = style.spacing;
|
||||||
|
}
|
||||||
|
|
||||||
let is_horizontal_line = is_horizontal_line
|
let is_horizontal_line = is_horizontal_line
|
||||||
.unwrap_or_else(|| ui.is_grid() || !ui.layout().main_dir().is_horizontal());
|
.unwrap_or_else(|| ui.is_grid() || !ui.layout().main_dir().is_horizontal());
|
||||||
|
|
||||||
@@ -111,7 +122,7 @@ impl Widget for Separator {
|
|||||||
let (rect, response) = ui.allocate_at_least(size, Sense::hover());
|
let (rect, response) = ui.allocate_at_least(size, Sense::hover());
|
||||||
|
|
||||||
if ui.is_rect_visible(response.rect) {
|
if ui.is_rect_visible(response.rect) {
|
||||||
let stroke = ui.visuals().widgets.noninteractive.bg_stroke;
|
let stroke = style.stroke;
|
||||||
let painter = ui.painter();
|
let painter = ui.painter();
|
||||||
if is_horizontal_line {
|
if is_horizontal_line {
|
||||||
painter.hline(
|
painter.hline(
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||||
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
#![allow(rustdoc::missing_crate_level_docs)] // it's an example
|
||||||
|
|
||||||
use eframe::egui::{
|
use eframe::egui;
|
||||||
self, Atom, Checkbox, Color32, FontId, Label, RichText, Sense, Stroke, style::WidgetVisuals,
|
|
||||||
vec2,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn main() -> eframe::Result {
|
fn main() -> eframe::Result {
|
||||||
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
|
||||||
@@ -17,67 +14,20 @@ fn main() -> eframe::Result {
|
|||||||
// Our application state:
|
// Our application state:
|
||||||
let mut name = "Arthur".to_owned();
|
let mut name = "Arthur".to_owned();
|
||||||
let mut age = 42;
|
let mut age = 42;
|
||||||
let mut is_adult = age >= 18;
|
|
||||||
|
|
||||||
eframe::run_simple_native("My egui App", options, move |ctx, _frame| {
|
eframe::run_simple_native("My egui App", options, move |ctx, _frame| {
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
ui.ctx().style_mut(|s| {
|
ui.heading("My egui Application");
|
||||||
s.spacing.icon_width_inner = 8.0;
|
ui.horizontal(|ui| {
|
||||||
s.spacing.icon_width = 15.0;
|
let name_label = ui.label("Your name: ");
|
||||||
s.spacing.button_padding = vec2(5.0, 5.0);
|
ui.text_edit_singleline(&mut name)
|
||||||
// s.spacing.interact_size.y = 30.0;
|
.labelled_by(name_label.id);
|
||||||
s.visuals.widgets.inactive = WidgetVisuals {
|
|
||||||
fg_stroke: Stroke::new(1.0, Color32::LIGHT_GRAY),
|
|
||||||
bg_stroke: Stroke::new(1.0, Color32::LIGHT_GRAY),
|
|
||||||
..s.visuals.widgets.inactive
|
|
||||||
};
|
|
||||||
s.visuals.widgets.active = WidgetVisuals {
|
|
||||||
fg_stroke: Stroke::new(1.0, Color32::LIGHT_BLUE),
|
|
||||||
..s.visuals.widgets.inactive
|
|
||||||
};
|
|
||||||
s.visuals.widgets.hovered = WidgetVisuals {
|
|
||||||
fg_stroke: Stroke::new(3.0, Color32::LIGHT_YELLOW),
|
|
||||||
..s.visuals.widgets.inactive
|
|
||||||
};
|
|
||||||
s.visuals.widgets.noninteractive = WidgetVisuals {
|
|
||||||
fg_stroke: Stroke::new(1.0, Color32::RED),
|
|
||||||
..s.visuals.widgets.inactive
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
ui.add(egui::Slider::new(&mut age, 0..=120).text("age"));
|
||||||
// ui.heading("My egui Application");
|
if ui.button("Increment").clicked() {
|
||||||
// ui.horizontal(|ui| {
|
age += 1;
|
||||||
// let name_label = ui.label("Your name: ");
|
}
|
||||||
// ui.text_edit_singleline(&mut name)
|
ui.label(format!("Hello '{name}', age {age}"));
|
||||||
// .labelled_by(name_label.id);
|
|
||||||
// });
|
|
||||||
// ui.add(egui::Slider::new(&mut age, 0..=120).text("age"));
|
|
||||||
// if ui.button("Increment").clicked() {
|
|
||||||
// age += 1;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Button test
|
|
||||||
// ui.add(Button::new("no frame").frame(false));
|
|
||||||
// ui.add(Button::new("small").small());
|
|
||||||
// ui.add_enabled(false, Button::new("disabled"));
|
|
||||||
// ui.add(Button::new("no frame inactive").frame_when_inactive(false));
|
|
||||||
|
|
||||||
// ui.label("Normal text");
|
|
||||||
// // Should not be affected by WidgetStyle
|
|
||||||
// ui.label(
|
|
||||||
// RichText::new("Unaffected by style")
|
|
||||||
// .font(FontId::monospace(15.0))
|
|
||||||
// .color(Color32::KHAKI),
|
|
||||||
// );
|
|
||||||
|
|
||||||
// ui.add(Label::new("interaction click").sense(Sense::click()));
|
|
||||||
// ui.add(Label::new("focusable").sense(Sense::focusable_noninteractive()))
|
|
||||||
// .request_focus();
|
|
||||||
|
|
||||||
ui.add(Checkbox::new(&mut is_adult, "test"));
|
|
||||||
ui.add(Checkbox::new(&mut is_adult, "test"));
|
|
||||||
ui.add(Checkbox::new(&mut is_adult, Atom::default()));
|
|
||||||
ui.add(Checkbox::new(&mut is_adult, Atom::default()).indeterminate(true));
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user