mirror of
https://github.com/emilk/egui.git
synced 2026-09-02 23:00:04 -04:00
fix features
This commit is contained in:
@@ -30,7 +30,7 @@ pub struct WidgetStyle {
|
|||||||
|
|
||||||
pub struct ButtonStyle {
|
pub struct ButtonStyle {
|
||||||
pub frame: Frame,
|
pub frame: Frame,
|
||||||
pub text: TextVisuals,
|
pub text_style: TextVisuals,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CheckboxStyle {
|
pub struct CheckboxStyle {
|
||||||
@@ -38,10 +38,10 @@ pub struct CheckboxStyle {
|
|||||||
pub frame: Frame,
|
pub frame: Frame,
|
||||||
|
|
||||||
/// Text next to it
|
/// Text next to it
|
||||||
pub text: TextVisuals,
|
pub text_style: TextVisuals,
|
||||||
|
|
||||||
/// Checkbox size
|
/// Checkbox size
|
||||||
pub size: f32,
|
pub checkbox_size: f32,
|
||||||
|
|
||||||
/// Checkmark size
|
/// Checkmark size
|
||||||
pub check_size: f32,
|
pub check_size: f32,
|
||||||
@@ -50,7 +50,7 @@ pub struct CheckboxStyle {
|
|||||||
pub checkbox_frame: Frame,
|
pub checkbox_frame: Frame,
|
||||||
|
|
||||||
/// Checkmark stroke
|
/// Checkmark stroke
|
||||||
pub stroke: Stroke,
|
pub check_stroke: Stroke,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LabelStyle {
|
pub struct LabelStyle {
|
||||||
@@ -148,7 +148,7 @@ impl Style {
|
|||||||
.into(),
|
.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
text: ws.text,
|
text_style: ws.text,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,16 +157,16 @@ impl Style {
|
|||||||
let ws = self.widget_style(state);
|
let ws = self.widget_style(state);
|
||||||
CheckboxStyle {
|
CheckboxStyle {
|
||||||
frame: Frame::new(),
|
frame: Frame::new(),
|
||||||
size: self.spacing.icon_width,
|
checkbox_size: self.spacing.icon_width,
|
||||||
check_size: self.spacing.icon_width_inner,
|
check_size: self.spacing.icon_width_inner,
|
||||||
checkbox_frame: Frame {
|
checkbox_frame: Frame {
|
||||||
fill: visuals.weak_bg_fill,
|
fill: visuals.bg_fill,
|
||||||
corner_radius: visuals.corner_radius,
|
corner_radius: visuals.corner_radius,
|
||||||
stroke: visuals.bg_stroke,
|
stroke: visuals.bg_stroke,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
text: ws.text,
|
text_style: ws.text,
|
||||||
stroke: ws.stroke,
|
check_stroke: ws.stroke,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
use std::sync::Arc;
|
use std::{mem, sync::Arc};
|
||||||
|
|
||||||
use epaint::Margin;
|
use epaint::Margin;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Atom, AtomExt as _, AtomKind, AtomLayout, AtomLayoutResponse, Color32, CornerRadius, Frame,
|
Atom, AtomExt as _, AtomKind, AtomLayout, AtomLayoutResponse, Color32, CornerRadius, Frame,
|
||||||
Image, IntoAtoms, NumExt as _, Response, RichText, Sense, Stroke, TextStyle, TextWrapMode, Ui,
|
Image, IntoAtoms, NumExt as _, Response, RichText, Sense, Stroke, TextStyle, TextWrapMode, Ui,
|
||||||
Vec2, Widget, WidgetInfo, WidgetText, WidgetType, style_trait::WidgetState,
|
Vec2, Widget, WidgetInfo, WidgetText, WidgetType,
|
||||||
|
style_trait::{ButtonStyle, WidgetState},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Clickable button with text.
|
/// Clickable button with text.
|
||||||
@@ -293,16 +294,16 @@ impl<'a> Button<'a> {
|
|||||||
|
|
||||||
let text = layout.text().map(String::from);
|
let text = layout.text().map(String::from);
|
||||||
|
|
||||||
|
let has_frame_margin = frame.unwrap_or_else(|| ui.visuals().button_frame);
|
||||||
|
|
||||||
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();
|
||||||
|
|
||||||
let style = ui.style().button_style(state, selected);
|
let ButtonStyle { frame, text_style } = ui.style().button_style(state, selected);
|
||||||
|
|
||||||
let has_frame_margin = frame.unwrap_or_else(|| ui.visuals().button_frame);
|
|
||||||
|
|
||||||
let mut button_padding = if has_frame_margin {
|
let mut button_padding = if has_frame_margin {
|
||||||
style.frame.inner_margin
|
frame.inner_margin
|
||||||
} else {
|
} else {
|
||||||
Margin::ZERO
|
Margin::ZERO
|
||||||
};
|
};
|
||||||
@@ -313,7 +314,7 @@ impl<'a> Button<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Override global style by local style
|
// Override global style by local style
|
||||||
let mut frame = style.frame;
|
let mut frame = frame;
|
||||||
if let Some(fill) = fill {
|
if let Some(fill) = fill {
|
||||||
frame = frame.fill(fill);
|
frame = frame.fill(fill);
|
||||||
}
|
}
|
||||||
@@ -331,31 +332,34 @@ impl<'a> Button<'a> {
|
|||||||
layout.map_texts(|t| match t {
|
layout.map_texts(|t| match t {
|
||||||
WidgetText::Text(text) => {
|
WidgetText::Text(text) => {
|
||||||
let rich_text = RichText::new(text.clone())
|
let rich_text = RichText::new(text.clone())
|
||||||
.font(style.text.font_id.clone())
|
.font(text_style.font_id.clone())
|
||||||
.color(style.text.color);
|
.color(text_style.color);
|
||||||
WidgetText::RichText(Arc::new(rich_text))
|
WidgetText::RichText(Arc::new(rich_text))
|
||||||
}
|
}
|
||||||
|
WidgetText::RichText(mut text) => {
|
||||||
|
let text_mut = Arc::make_mut(&mut text);
|
||||||
|
*text_mut = mem::take(text_mut).font(text_style.font_id.clone());
|
||||||
|
WidgetText::RichText(text)
|
||||||
|
}
|
||||||
w => w,
|
w => w,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Retrocompatibility with button settings
|
// Retrocompatibility with button settings
|
||||||
let mut prepared =
|
layout = if has_frame_margin && (state != WidgetState::Inactive || frame_when_inactive) {
|
||||||
if has_frame_margin && (state != WidgetState::Inactive || frame_when_inactive) {
|
layout.frame(frame)
|
||||||
layout.frame(frame).min_size(min_size).allocate(ui)
|
} else {
|
||||||
} else {
|
layout.frame(Frame::new().inner_margin(frame.inner_margin))
|
||||||
layout
|
};
|
||||||
.frame(Frame::new().inner_margin(frame.inner_margin))
|
|
||||||
.min_size(min_size)
|
let mut prepared = layout.min_size(min_size).allocate(ui);
|
||||||
.allocate(ui)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get AtomLayoutResponse, empty if not visible
|
// Get AtomLayoutResponse, empty if not visible
|
||||||
let response = if ui.is_rect_visible(prepared.response.rect) {
|
let response = if ui.is_rect_visible(prepared.response.rect) {
|
||||||
if image_tint_follows_text_color {
|
if image_tint_follows_text_color {
|
||||||
prepared.map_images(|image| image.tint(style.text.color));
|
prepared.map_images(|image| image.tint(text_style.color));
|
||||||
}
|
}
|
||||||
|
|
||||||
prepared.fallback_text_color = style.text.color;
|
prepared.fallback_text_color = text_style.color;
|
||||||
|
|
||||||
prepared.paint(ui)
|
prepared.paint(ui)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ 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, style_trait::CheckboxStyle,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO(emilk): allow checkbox without a text label
|
// TODO(emilk): allow checkbox without a text label
|
||||||
@@ -61,16 +61,22 @@ impl Widget for Checkbox<'_> {
|
|||||||
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();
|
||||||
let style = ui.style().checkbox_style(state);
|
|
||||||
|
|
||||||
let icon_width = style.size;
|
let CheckboxStyle {
|
||||||
|
check_size,
|
||||||
|
checkbox_frame,
|
||||||
|
checkbox_size,
|
||||||
|
frame,
|
||||||
|
check_stroke,
|
||||||
|
text_style,
|
||||||
|
} = ui.style().checkbox_style(state);
|
||||||
|
|
||||||
// interact_size or size ?
|
// interact_size or size ?
|
||||||
let mut min_size = Vec2::splat(ui.spacing().interact_size.y);
|
let mut min_size = Vec2::splat(ui.spacing().interact_size.y);
|
||||||
min_size.y = min_size.y.at_least(icon_width);
|
min_size.y = min_size.y.at_least(checkbox_size);
|
||||||
|
|
||||||
// In order to center the checkbox based on min_size we set the icon height to at least min_size.y
|
// In order to center the checkbox based on min_size we set the icon height to at least min_size.y
|
||||||
let mut icon_size = Vec2::splat(icon_width);
|
let mut icon_size = Vec2::splat(checkbox_size);
|
||||||
icon_size.y = icon_size.y.at_least(min_size.y);
|
icon_size.y = icon_size.y.at_least(min_size.y);
|
||||||
let rect_id = Id::new("egui::checkbox");
|
let rect_id = Id::new("egui::checkbox");
|
||||||
atoms.push_left(Atom::custom(rect_id, icon_size));
|
atoms.push_left(Atom::custom(rect_id, icon_size));
|
||||||
@@ -80,7 +86,7 @@ impl Widget for Checkbox<'_> {
|
|||||||
let mut prepared = AtomLayout::new(atoms)
|
let mut prepared = AtomLayout::new(atoms)
|
||||||
.sense(Sense::click())
|
.sense(Sense::click())
|
||||||
.min_size(min_size)
|
.min_size(min_size)
|
||||||
.frame(style.frame)
|
.frame(frame)
|
||||||
.allocate(ui);
|
.allocate(ui);
|
||||||
|
|
||||||
if prepared.response.clicked() {
|
if prepared.response.clicked() {
|
||||||
@@ -105,23 +111,22 @@ impl Widget for Checkbox<'_> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if ui.is_rect_visible(prepared.response.rect) {
|
if ui.is_rect_visible(prepared.response.rect) {
|
||||||
// let visuals = ui.style().interact_selectable(&response, *checked); // too colorful
|
prepared.fallback_text_color = text_style.color;
|
||||||
prepared.fallback_text_color = style.text.color;
|
|
||||||
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 big_icon_rect = Rect::from_center_size(
|
let big_icon_rect = Rect::from_center_size(
|
||||||
pos2(rect.left() + icon_width / 2.0, rect.center().y),
|
pos2(rect.left() + checkbox_size / 2.0, rect.center().y),
|
||||||
Vec2::splat(style.size),
|
Vec2::splat(checkbox_size),
|
||||||
);
|
);
|
||||||
let small_icon_rect =
|
let small_icon_rect =
|
||||||
Rect::from_center_size(big_icon_rect.center(), Vec2::splat(style.check_size));
|
Rect::from_center_size(big_icon_rect.center(), Vec2::splat(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,
|
checkbox_frame.corner_radius,
|
||||||
style.checkbox_frame.fill,
|
checkbox_frame.fill,
|
||||||
style.checkbox_frame.stroke,
|
checkbox_frame.stroke,
|
||||||
epaint::StrokeKind::Inside,
|
epaint::StrokeKind::Inside,
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -130,7 +135,7 @@ impl Widget for Checkbox<'_> {
|
|||||||
ui.painter().add(Shape::hline(
|
ui.painter().add(Shape::hline(
|
||||||
small_icon_rect.x_range(),
|
small_icon_rect.x_range(),
|
||||||
small_icon_rect.center().y,
|
small_icon_rect.center().y,
|
||||||
style.stroke,
|
check_stroke,
|
||||||
));
|
));
|
||||||
} else if *checked {
|
} else if *checked {
|
||||||
// Check mark:
|
// Check mark:
|
||||||
@@ -140,7 +145,7 @@ impl Widget for Checkbox<'_> {
|
|||||||
pos2(small_icon_rect.center().x, small_icon_rect.bottom()),
|
pos2(small_icon_rect.center().x, small_icon_rect.bottom()),
|
||||||
pos2(small_icon_rect.right(), small_icon_rect.top()),
|
pos2(small_icon_rect.right(), small_icon_rect.top()),
|
||||||
],
|
],
|
||||||
style.stroke,
|
check_stroke,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use crate::{Response, Sense, Ui, Vec2, Widget, vec2};
|
|||||||
/// ```
|
/// ```
|
||||||
#[must_use = "You should put this widget in a ui with `ui.add(widget);`"]
|
#[must_use = "You should put this widget in a ui with `ui.add(widget);`"]
|
||||||
pub struct Separator {
|
pub struct Separator {
|
||||||
spacing: f32,
|
spacing: Option<f32>,
|
||||||
grow: f32,
|
grow: f32,
|
||||||
is_horizontal_line: Option<bool>,
|
is_horizontal_line: Option<bool>,
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@ pub struct Separator {
|
|||||||
impl Default for Separator {
|
impl Default for Separator {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
spacing: 6.0,
|
spacing: None,
|
||||||
grow: 0.0,
|
grow: 0.0,
|
||||||
is_horizontal_line: None,
|
is_horizontal_line: None,
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,7 @@ impl Separator {
|
|||||||
/// this is the width of the separator widget.
|
/// this is the width of the separator widget.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn spacing(mut self, spacing: f32) -> Self {
|
pub fn spacing(mut self, spacing: f32) -> Self {
|
||||||
self.spacing = spacing;
|
self.spacing = Some(spacing);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ 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 {
|
||||||
mut spacing,
|
spacing,
|
||||||
grow,
|
grow,
|
||||||
is_horizontal_line,
|
is_horizontal_line,
|
||||||
} = self;
|
} = self;
|
||||||
@@ -100,9 +100,7 @@ impl Widget for Separator {
|
|||||||
let style = ui.style().separator_style(state);
|
let style = ui.style().separator_style(state);
|
||||||
|
|
||||||
// override the spacing if not set
|
// override the spacing if not set
|
||||||
if spacing == 0.0 && style.spacing != 0.0 {
|
let spacing = spacing.unwrap_or(style.spacing);
|
||||||
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());
|
||||||
|
|||||||
Reference in New Issue
Block a user