[refactor] break up Style into Spacing, Interaction and Visuals
Also make sliders fixed-width
This commit is contained in:
parent
fe50f39590
commit
413ed6999e
15 changed files with 464 additions and 271 deletions
|
@ -182,15 +182,15 @@ impl CollapsingHeader {
|
||||||
let id = ui.make_unique_child_id_full(id_source, Some(title));
|
let id = ui.make_unique_child_id_full(id_source, Some(title));
|
||||||
|
|
||||||
let available = ui.available_finite();
|
let available = ui.available_finite();
|
||||||
let text_pos = available.min + vec2(ui.style().indent, 0.0);
|
let text_pos = available.min + vec2(ui.style().spacing.indent, 0.0);
|
||||||
let galley = label.layout_width(ui, available.width() - ui.style().indent);
|
let galley = label.layout_width(ui, available.width() - ui.style().spacing.indent);
|
||||||
let text_max_x = text_pos.x + galley.size.x;
|
let text_max_x = text_pos.x + galley.size.x;
|
||||||
let desired_width = text_max_x - available.left();
|
let desired_width = text_max_x - available.left();
|
||||||
let desired_width = desired_width.max(available.width());
|
let desired_width = desired_width.max(available.width());
|
||||||
|
|
||||||
let size = vec2(
|
let size = vec2(
|
||||||
desired_width,
|
desired_width,
|
||||||
galley.size.y + 2.0 * ui.style().button_padding.y,
|
galley.size.y + 2.0 * ui.style().spacing.button_padding.y,
|
||||||
);
|
);
|
||||||
|
|
||||||
let rect = ui.allocate_space(size);
|
let rect = ui.allocate_space(size);
|
||||||
|
@ -205,9 +205,9 @@ impl CollapsingHeader {
|
||||||
let bg_index = ui.painter().add(PaintCmd::Noop);
|
let bg_index = ui.painter().add(PaintCmd::Noop);
|
||||||
|
|
||||||
{
|
{
|
||||||
let (mut icon_rect, _) = ui.style().icon_rectangles(response.rect);
|
let (mut icon_rect, _) = ui.style().spacing.icon_rectangles(response.rect);
|
||||||
icon_rect.set_center(pos2(
|
icon_rect.set_center(pos2(
|
||||||
response.rect.left() + ui.style().indent / 2.0,
|
response.rect.left() + ui.style().spacing.indent / 2.0,
|
||||||
response.rect.center().y,
|
response.rect.center().y,
|
||||||
));
|
));
|
||||||
let icon_response = Response {
|
let icon_response = Response {
|
||||||
|
|
|
@ -15,10 +15,10 @@ pub struct Frame {
|
||||||
impl Frame {
|
impl Frame {
|
||||||
pub fn window(style: &Style) -> Self {
|
pub fn window(style: &Style) -> Self {
|
||||||
Self {
|
Self {
|
||||||
margin: style.window_padding,
|
margin: style.spacing.window_padding,
|
||||||
corner_radius: style.window.corner_radius,
|
corner_radius: style.visuals.window_corner_radius,
|
||||||
fill: Some(style.background_fill),
|
fill: Some(style.visuals.background_fill),
|
||||||
outline: style.interact.inactive.bg_outline, // because we can resize windows
|
outline: style.visuals.interacted.inactive.bg_outline, // because we can resize windows
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,16 +35,16 @@ impl Frame {
|
||||||
Self {
|
Self {
|
||||||
margin: Vec2::splat(1.0),
|
margin: Vec2::splat(1.0),
|
||||||
corner_radius: 2.0,
|
corner_radius: 2.0,
|
||||||
fill: Some(style.background_fill),
|
fill: Some(style.visuals.background_fill),
|
||||||
outline: Some(LineStyle::new(1.0, Srgba::gray(128))),
|
outline: Some(LineStyle::new(1.0, Srgba::gray(128))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn popup(style: &Style) -> Self {
|
pub fn popup(style: &Style) -> Self {
|
||||||
Self {
|
Self {
|
||||||
margin: style.window_padding,
|
margin: style.spacing.window_padding,
|
||||||
corner_radius: 5.0,
|
corner_radius: 5.0,
|
||||||
fill: Some(style.background_fill),
|
fill: Some(style.visuals.background_fill),
|
||||||
outline: Some(LineStyle::new(1.0, Srgba::gray(128))),
|
outline: Some(LineStyle::new(1.0, Srgba::gray(128))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,7 +145,7 @@ impl Resize {
|
||||||
|
|
||||||
let corner_response = if self.resizable {
|
let corner_response = if self.resizable {
|
||||||
// Resize-corner:
|
// Resize-corner:
|
||||||
let corner_size = Vec2::splat(ui.style().resize_corner_size);
|
let corner_size = Vec2::splat(ui.style().visuals.resize_corner_size);
|
||||||
let corner_rect =
|
let corner_rect =
|
||||||
Rect::from_min_size(position + state.desired_size - corner_size, corner_size);
|
Rect::from_min_size(position + state.desired_size - corner_size, corner_size);
|
||||||
let corner_response = ui.interact(corner_rect, id.with("corner"), Sense::drag());
|
let corner_response = ui.interact(corner_rect, id.with("corner"), Sense::drag());
|
||||||
|
@ -169,7 +169,7 @@ impl Resize {
|
||||||
|
|
||||||
let inner_rect = Rect::from_min_size(position, state.desired_size);
|
let inner_rect = Rect::from_min_size(position, state.desired_size);
|
||||||
|
|
||||||
let mut content_clip_rect = inner_rect.expand(ui.style().clip_rect_margin);
|
let mut content_clip_rect = inner_rect.expand(ui.style().visuals.clip_rect_margin);
|
||||||
|
|
||||||
// If we pull the resize handle to shrink, we want to TRY to shrink it.
|
// If we pull the resize handle to shrink, we want to TRY to shrink it.
|
||||||
// After laying out the contents, we might be much bigger.
|
// After laying out the contents, we might be much bigger.
|
||||||
|
@ -177,7 +177,9 @@ impl Resize {
|
||||||
// then we will clip the contents of the region even thought the result gets larger. This is simply ugly!
|
// then we will clip the contents of the region even thought the result gets larger. This is simply ugly!
|
||||||
// So we use the memory of last_content_size to make the clip rect large enough.
|
// So we use the memory of last_content_size to make the clip rect large enough.
|
||||||
content_clip_rect.max = content_clip_rect.max.max(
|
content_clip_rect.max = content_clip_rect.max.max(
|
||||||
inner_rect.min + state.last_content_size + Vec2::splat(ui.style().clip_rect_margin),
|
inner_rect.min
|
||||||
|
+ state.last_content_size
|
||||||
|
+ Vec2::splat(ui.style().visuals.clip_rect_margin),
|
||||||
);
|
);
|
||||||
|
|
||||||
content_clip_rect = content_clip_rect.intersect(ui.clip_rect()); // Respect parent region
|
content_clip_rect = content_clip_rect.intersect(ui.clip_rect()); // Respect parent region
|
||||||
|
@ -236,7 +238,7 @@ impl Resize {
|
||||||
rect,
|
rect,
|
||||||
corner_radius: 3.0,
|
corner_radius: 3.0,
|
||||||
fill: None,
|
fill: None,
|
||||||
outline: Some(ui.style().thin_outline),
|
outline: Some(ui.style().visuals.thin_outline),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +252,7 @@ impl Resize {
|
||||||
|
|
||||||
ui.memory().resize.insert(id, state);
|
ui.memory().resize.insert(id, state);
|
||||||
|
|
||||||
if ui.ctx().style().debug_resize {
|
if ui.ctx().style().visuals.debug_resize {
|
||||||
ui.ctx().debug_painter().debug_rect(
|
ui.ctx().debug_painter().debug_rect(
|
||||||
Rect::from_min_size(content_ui.top_left(), state.desired_size),
|
Rect::from_min_size(content_ui.top_left(), state.desired_size),
|
||||||
color::GREEN,
|
color::GREEN,
|
||||||
|
|
|
@ -99,7 +99,7 @@ impl ScrollArea {
|
||||||
inner_rect.min - state.offset,
|
inner_rect.min - state.offset,
|
||||||
vec2(inner_size.x, f32::INFINITY),
|
vec2(inner_size.x, f32::INFINITY),
|
||||||
));
|
));
|
||||||
let mut content_clip_rect = inner_rect.expand(ui.style().clip_rect_margin);
|
let mut content_clip_rect = inner_rect.expand(ui.style().visuals.clip_rect_margin);
|
||||||
content_clip_rect = content_clip_rect.intersect(ui.clip_rect());
|
content_clip_rect = content_clip_rect.intersect(ui.clip_rect());
|
||||||
content_clip_rect.max.x = ui.clip_rect().max.x - current_scroll_bar_width; // Nice handling of forced resizing beyond the possible
|
content_clip_rect.max.x = ui.clip_rect().max.x - current_scroll_bar_width; // Nice handling of forced resizing beyond the possible
|
||||||
content_ui.set_clip_rect(content_clip_rect);
|
content_ui.set_clip_rect(content_clip_rect);
|
||||||
|
@ -175,7 +175,7 @@ impl Prepared {
|
||||||
if current_scroll_bar_width > 0.0 {
|
if current_scroll_bar_width > 0.0 {
|
||||||
let animation_t = current_scroll_bar_width / max_scroll_bar_width;
|
let animation_t = current_scroll_bar_width / max_scroll_bar_width;
|
||||||
// margin between contents and scroll bar
|
// margin between contents and scroll bar
|
||||||
let margin = animation_t * ui.style().item_spacing.x;
|
let margin = animation_t * ui.style().spacing.item_spacing.x;
|
||||||
let left = inner_rect.right() + margin;
|
let left = inner_rect.right() + margin;
|
||||||
let right = outer_rect.right();
|
let right = outer_rect.right();
|
||||||
let corner_radius = (right - left) / 2.0;
|
let corner_radius = (right - left) / 2.0;
|
||||||
|
@ -243,7 +243,7 @@ impl Prepared {
|
||||||
ui.painter().add(paint::PaintCmd::Rect {
|
ui.painter().add(paint::PaintCmd::Rect {
|
||||||
rect: outer_scroll_rect,
|
rect: outer_scroll_rect,
|
||||||
corner_radius,
|
corner_radius,
|
||||||
fill: Some(ui.style().dark_bg_color),
|
fill: Some(ui.style().visuals.dark_bg_color),
|
||||||
outline: None,
|
outline: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -274,5 +274,5 @@ impl Prepared {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn max_scroll_bar_width_with_margin(ui: &Ui) -> f32 {
|
fn max_scroll_bar_width_with_margin(ui: &Ui) -> f32 {
|
||||||
ui.style().item_spacing.x + 16.0
|
ui.style().spacing.item_spacing.x + 16.0
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,7 +202,7 @@ impl<'open> Window<'open> {
|
||||||
let last_frame_outer_rect = area.state().rect();
|
let last_frame_outer_rect = area.state().rect();
|
||||||
let interaction = if possible.movable || possible.resizable {
|
let interaction = if possible.movable || possible.resizable {
|
||||||
let title_bar_height =
|
let title_bar_height =
|
||||||
title_label.font_height(ctx.fonts()) + 1.0 * ctx.style().item_spacing.y; // this could be better
|
title_label.font_height(ctx.fonts()) + 1.0 * ctx.style().spacing.item_spacing.y; // this could be better
|
||||||
let margins = 2.0 * frame.margin + vec2(0.0, title_bar_height);
|
let margins = 2.0 * frame.margin + vec2(0.0, title_bar_height);
|
||||||
|
|
||||||
window_interaction(
|
window_interaction(
|
||||||
|
@ -255,7 +255,7 @@ impl<'open> Window<'open> {
|
||||||
.add_contents(&mut frame.content_ui, collapsing_id, |ui| {
|
.add_contents(&mut frame.content_ui, collapsing_id, |ui| {
|
||||||
resize.show(ui, |ui| {
|
resize.show(ui, |ui| {
|
||||||
// Add some spacing between title and content:
|
// Add some spacing between title and content:
|
||||||
ui.allocate_space(ui.style().item_spacing);
|
ui.allocate_space(ui.style().spacing.item_spacing);
|
||||||
|
|
||||||
if let Some(scroll) = scroll {
|
if let Some(scroll) = scroll {
|
||||||
scroll.show(ui, add_contents)
|
scroll.show(ui, add_contents)
|
||||||
|
@ -294,14 +294,14 @@ impl<'open> Window<'open> {
|
||||||
&mut area_content_ui,
|
&mut area_content_ui,
|
||||||
outer_rect,
|
outer_rect,
|
||||||
interaction,
|
interaction,
|
||||||
ctx.style().interact.active,
|
ctx.style().visuals.interacted.active,
|
||||||
);
|
);
|
||||||
} else if let Some(hover_interaction) = hover_interaction {
|
} else if let Some(hover_interaction) = hover_interaction {
|
||||||
paint_frame_interaction(
|
paint_frame_interaction(
|
||||||
&mut area_content_ui,
|
&mut area_content_ui,
|
||||||
outer_rect,
|
outer_rect,
|
||||||
hover_interaction,
|
hover_interaction,
|
||||||
ctx.style().interact.hovered,
|
ctx.style().visuals.interacted.hovered,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,7 +312,7 @@ impl<'open> Window<'open> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint_resize_corner(ui: &mut Ui, outer_rect: Rect, frame_outline: Option<LineStyle>) {
|
fn paint_resize_corner(ui: &mut Ui, outer_rect: Rect, frame_outline: Option<LineStyle>) {
|
||||||
let corner_size = Vec2::splat(ui.style().resize_corner_size);
|
let corner_size = Vec2::splat(ui.style().visuals.resize_corner_size);
|
||||||
let handle_offset = -Vec2::splat(2.0);
|
let handle_offset = -Vec2::splat(2.0);
|
||||||
let corner_rect =
|
let corner_rect =
|
||||||
Rect::from_min_size(outer_rect.max - corner_size + handle_offset, corner_size);
|
Rect::from_min_size(outer_rect.max - corner_size + handle_offset, corner_size);
|
||||||
|
@ -468,32 +468,32 @@ fn resize_hover(
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let side_interact_radius = ctx.style().resize_interact_radius_side;
|
let side_grab_radius = ctx.style().interaction.resize_grab_radius_side;
|
||||||
let corner_interact_radius = ctx.style().resize_interact_radius_corner;
|
let corner_grab_radius = ctx.style().interaction.resize_grab_radius_corner;
|
||||||
if rect.expand(side_interact_radius).contains(mouse_pos) {
|
if rect.expand(side_grab_radius).contains(mouse_pos) {
|
||||||
let (mut left, mut right, mut top, mut bottom) = Default::default();
|
let (mut left, mut right, mut top, mut bottom) = Default::default();
|
||||||
if possible.resizable {
|
if possible.resizable {
|
||||||
right = (rect.right() - mouse_pos.x).abs() <= side_interact_radius;
|
right = (rect.right() - mouse_pos.x).abs() <= side_grab_radius;
|
||||||
bottom = (rect.bottom() - mouse_pos.y).abs() <= side_interact_radius;
|
bottom = (rect.bottom() - mouse_pos.y).abs() <= side_grab_radius;
|
||||||
|
|
||||||
if rect.right_bottom().distance(mouse_pos) < corner_interact_radius {
|
if rect.right_bottom().distance(mouse_pos) < corner_grab_radius {
|
||||||
right = true;
|
right = true;
|
||||||
bottom = true;
|
bottom = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if possible.movable {
|
if possible.movable {
|
||||||
left = (rect.left() - mouse_pos.x).abs() <= side_interact_radius;
|
left = (rect.left() - mouse_pos.x).abs() <= side_grab_radius;
|
||||||
top = (rect.top() - mouse_pos.y).abs() <= side_interact_radius;
|
top = (rect.top() - mouse_pos.y).abs() <= side_grab_radius;
|
||||||
|
|
||||||
if rect.right_top().distance(mouse_pos) < corner_interact_radius {
|
if rect.right_top().distance(mouse_pos) < corner_grab_radius {
|
||||||
right = true;
|
right = true;
|
||||||
top = true;
|
top = true;
|
||||||
}
|
}
|
||||||
if rect.left_top().distance(mouse_pos) < corner_interact_radius {
|
if rect.left_top().distance(mouse_pos) < corner_grab_radius {
|
||||||
left = true;
|
left = true;
|
||||||
top = true;
|
top = true;
|
||||||
}
|
}
|
||||||
if rect.left_bottom().distance(mouse_pos) < corner_interact_radius {
|
if rect.left_bottom().distance(mouse_pos) < corner_grab_radius {
|
||||||
left = true;
|
left = true;
|
||||||
bottom = true;
|
bottom = true;
|
||||||
}
|
}
|
||||||
|
@ -530,9 +530,9 @@ fn paint_frame_interaction(
|
||||||
ui: &mut Ui,
|
ui: &mut Ui,
|
||||||
rect: Rect,
|
rect: Rect,
|
||||||
interaction: WindowInteraction,
|
interaction: WindowInteraction,
|
||||||
style: style::WidgetStyle,
|
visuals: style::WidgetVisuals,
|
||||||
) {
|
) {
|
||||||
let cr = ui.style().window.corner_radius;
|
let cr = ui.style().visuals.window_corner_radius;
|
||||||
let Rect { min, max } = rect;
|
let Rect { min, max } = rect;
|
||||||
|
|
||||||
let mut path = Path::default();
|
let mut path = Path::default();
|
||||||
|
@ -567,7 +567,7 @@ fn paint_frame_interaction(
|
||||||
path,
|
path,
|
||||||
closed: false,
|
closed: false,
|
||||||
fill: None,
|
fill: None,
|
||||||
outline: style.bg_outline,
|
outline: visuals.bg_outline,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,8 +591,8 @@ fn show_title_bar(
|
||||||
let title_bar_and_rect = ui.horizontal_centered(|ui| {
|
let title_bar_and_rect = ui.horizontal_centered(|ui| {
|
||||||
ui.set_desired_height(title_label.font_height(ui.fonts()));
|
ui.set_desired_height(title_label.font_height(ui.fonts()));
|
||||||
|
|
||||||
let item_spacing = ui.style().item_spacing;
|
let item_spacing = ui.style().spacing.item_spacing;
|
||||||
let button_size = ui.style().start_icon_width;
|
let button_size = ui.style().spacing.icon_width;
|
||||||
|
|
||||||
if collapsible {
|
if collapsible {
|
||||||
// TODO: make clickable radius larger
|
// TODO: make clickable radius larger
|
||||||
|
@ -668,10 +668,10 @@ impl TitleBar {
|
||||||
// paint separator between title and content:
|
// paint separator between title and content:
|
||||||
let left = outer_rect.left();
|
let left = outer_rect.left();
|
||||||
let right = outer_rect.right();
|
let right = outer_rect.right();
|
||||||
let y = content_rect.top() + ui.style().item_spacing.y * 0.5;
|
let y = content_rect.top() + ui.style().spacing.item_spacing.y * 0.5;
|
||||||
ui.painter().line_segment(
|
ui.painter().line_segment(
|
||||||
[pos2(left, y), pos2(right, y)],
|
[pos2(left, y), pos2(right, y)],
|
||||||
ui.style().interact.inactive.bg_outline.unwrap(),
|
ui.style().visuals.interacted.inactive.bg_outline.unwrap(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -686,10 +686,10 @@ impl TitleBar {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close_button_ui(&self, ui: &mut Ui) -> Response {
|
fn close_button_ui(&self, ui: &mut Ui) -> Response {
|
||||||
let button_size = ui.style().start_icon_width;
|
let button_size = ui.style().spacing.icon_width;
|
||||||
let button_rect = Rect::from_min_size(
|
let button_rect = Rect::from_min_size(
|
||||||
pos2(
|
pos2(
|
||||||
self.rect.right() - ui.style().item_spacing.x - button_size,
|
self.rect.right() - ui.style().spacing.item_spacing.x - button_size,
|
||||||
self.rect.center().y - 0.5 * button_size,
|
self.rect.center().y - 0.5 * button_size,
|
||||||
),
|
),
|
||||||
Vec2::splat(button_size),
|
Vec2::splat(button_size),
|
||||||
|
|
|
@ -337,8 +337,8 @@ impl Context {
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
pub fn layer_at(&self, pos: Pos2) -> Option<Layer> {
|
pub fn layer_at(&self, pos: Pos2) -> Option<Layer> {
|
||||||
let resize_interact_radius_side = self.style().resize_interact_radius_side;
|
let resize_grab_radius_side = self.style().interaction.resize_grab_radius_side;
|
||||||
self.memory().layer_at(pos, resize_interact_radius_side)
|
self.memory().layer_at(pos, resize_grab_radius_side)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains_mouse(&self, layer: Layer, clip_rect: Rect, rect: Rect) -> bool {
|
pub fn contains_mouse(&self, layer: Layer, clip_rect: Rect, rect: Rect) -> bool {
|
||||||
|
@ -359,7 +359,7 @@ impl Context {
|
||||||
interaction_id: Option<Id>,
|
interaction_id: Option<Id>,
|
||||||
sense: Sense,
|
sense: Sense,
|
||||||
) -> Response {
|
) -> Response {
|
||||||
let interact_rect = rect.expand2(0.5 * self.style().item_spacing); // make it easier to click. TODO: nice way to do this
|
let interact_rect = rect.expand2(0.5 * self.style().spacing.item_spacing); // make it easier to click. TODO: nice way to do this
|
||||||
let hovered = self.contains_mouse(layer, clip_rect, interact_rect);
|
let hovered = self.contains_mouse(layer, clip_rect, interact_rect);
|
||||||
let has_kb_focus = interaction_id
|
let has_kb_focus = interaction_id
|
||||||
.map(|id| self.memory().has_kb_focus(id))
|
.map(|id| self.memory().has_kb_focus(id))
|
||||||
|
|
|
@ -473,7 +473,7 @@ impl Default for Widgets {
|
||||||
impl Widgets {
|
impl Widgets {
|
||||||
pub fn ui(&mut self, ui: &mut Ui) {
|
pub fn ui(&mut self, ui: &mut Ui) {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.style_mut().item_spacing.x = 0.0;
|
ui.style_mut().spacing.item_spacing.x = 0.0;
|
||||||
ui.add(label!("Text can have ").text_color(srgba(110, 255, 110, 255)));
|
ui.add(label!("Text can have ").text_color(srgba(110, 255, 110, 255)));
|
||||||
ui.add(label!("color ").text_color(srgba(128, 140, 255, 255)));
|
ui.add(label!("color ").text_color(srgba(128, 140, 255, 255)));
|
||||||
ui.add(label!("and tooltips")).tooltip_text(
|
ui.add(label!("and tooltips")).tooltip_text(
|
||||||
|
@ -520,7 +520,7 @@ impl Widgets {
|
||||||
{
|
{
|
||||||
ui.label("An angle stored as radians, but edited in degrees:");
|
ui.label("An angle stored as radians, but edited in degrees:");
|
||||||
ui.horizontal_centered(|ui| {
|
ui.horizontal_centered(|ui| {
|
||||||
ui.style_mut().item_spacing.x = 0.0;
|
ui.style_mut().spacing.item_spacing.x = 0.0;
|
||||||
ui.drag_angle(&mut self.angle);
|
ui.drag_angle(&mut self.angle);
|
||||||
ui.label(format!(" = {} radians", self.angle));
|
ui.label(format!(" = {} radians", self.angle));
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::{paint::PaintCmd, *};
|
||||||
// iOS style toggle switch
|
// iOS style toggle switch
|
||||||
pub fn toggle(ui: &mut Ui, on: &mut bool) -> Response {
|
pub fn toggle(ui: &mut Ui, on: &mut bool) -> Response {
|
||||||
// First we must reserve some space to use:
|
// First we must reserve some space to use:
|
||||||
let desired_size = vec2(2.0, 1.0) * ui.style().clickable_diameter;
|
let desired_size = vec2(2.0, 1.0) * ui.style().spacing.clickable_diameter;
|
||||||
let rect = ui.allocate_space(desired_size);
|
let rect = ui.allocate_space(desired_size);
|
||||||
|
|
||||||
// Now that we have an area, we want to check for clicks.
|
// Now that we have an area, we want to check for clicks.
|
||||||
|
|
|
@ -184,7 +184,7 @@ impl Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor_change.x += child_size.x;
|
cursor_change.x += child_size.x;
|
||||||
cursor_change.x += style.item_spacing.x; // Where to put next thing, if there is a next thing
|
cursor_change.x += style.spacing.item_spacing.x; // Where to put next thing, if there is a next thing
|
||||||
} else {
|
} else {
|
||||||
if let Some(align) = self.align {
|
if let Some(align) = self.align {
|
||||||
child_move.x += match align {
|
child_move.x += match align {
|
||||||
|
@ -197,7 +197,7 @@ impl Layout {
|
||||||
child_size.x = child_size.x.max(available_size.x);
|
child_size.x = child_size.x.max(available_size.x);
|
||||||
};
|
};
|
||||||
cursor_change.y += child_size.y;
|
cursor_change.y += child_size.y;
|
||||||
cursor_change.y += style.item_spacing.y; // Where to put next thing, if there is a next thing
|
cursor_change.y += style.spacing.item_spacing.y; // Where to put next thing, if there is a next thing
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.is_reversed() {
|
if self.is_reversed() {
|
||||||
|
|
|
@ -61,17 +61,17 @@ pub fn bar<R>(ui: &mut Ui, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Rect)
|
||||||
ui.horizontal_centered(|ui| {
|
ui.horizontal_centered(|ui| {
|
||||||
Frame::menu_bar(ui.style()).show(ui, |ui| {
|
Frame::menu_bar(ui.style()).show(ui, |ui| {
|
||||||
let mut style = ui.style().clone();
|
let mut style = ui.style().clone();
|
||||||
style.button_padding = vec2(2.0, 0.0);
|
style.spacing.button_padding = vec2(2.0, 0.0);
|
||||||
// style.interact.active.bg_fill = None;
|
// style.visuals.interacted.active.bg_fill = None;
|
||||||
style.interact.active.bg_outline = None;
|
style.visuals.interacted.active.bg_outline = None;
|
||||||
// style.interact.hovered.bg_fill = None;
|
// style.visuals.interacted.hovered.bg_fill = None;
|
||||||
style.interact.hovered.bg_outline = None;
|
style.visuals.interacted.hovered.bg_outline = None;
|
||||||
style.interact.inactive.bg_fill = None;
|
style.visuals.interacted.inactive.bg_fill = None;
|
||||||
style.interact.inactive.bg_outline = None;
|
style.visuals.interacted.inactive.bg_outline = None;
|
||||||
ui.set_style(style);
|
ui.set_style(style);
|
||||||
|
|
||||||
// Take full width and fixed height:
|
// Take full width and fixed height:
|
||||||
let height = ui.style().menu_bar.height;
|
let height = ui.style().spacing.menu_bar_height;
|
||||||
ui.set_desired_height(height);
|
ui.set_desired_height(height);
|
||||||
ui.expand_to_size(vec2(ui.available().width(), height));
|
ui.expand_to_size(vec2(ui.available().width(), height));
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ fn menu_impl<'c>(
|
||||||
let mut button = Button::new(title);
|
let mut button = Button::new(title);
|
||||||
|
|
||||||
if bar_state.open_menu == Some(menu_id) {
|
if bar_state.open_menu == Some(menu_id) {
|
||||||
button = button.fill(Some(ui.style().interact.active.main_fill));
|
button = button.fill(Some(ui.style().visuals.interacted.active.main_fill));
|
||||||
}
|
}
|
||||||
|
|
||||||
let button_response = ui.add(button);
|
let button_response = ui.add(button);
|
||||||
|
@ -127,13 +127,13 @@ fn menu_impl<'c>(
|
||||||
frame.show(ui, |ui| {
|
frame.show(ui, |ui| {
|
||||||
resize.show(ui, |ui| {
|
resize.show(ui, |ui| {
|
||||||
let mut style = ui.style().clone();
|
let mut style = ui.style().clone();
|
||||||
style.button_padding = vec2(2.0, 0.0);
|
style.spacing.button_padding = vec2(2.0, 0.0);
|
||||||
// style.interact.active.bg_fill = None;
|
// style.visuals.interacted.active.bg_fill = None;
|
||||||
style.interact.active.bg_outline = None;
|
style.visuals.interacted.active.bg_outline = None;
|
||||||
// style.interact.hovered.bg_fill = None;
|
// style.visuals.interacted.hovered.bg_fill = None;
|
||||||
style.interact.hovered.bg_outline = None;
|
style.visuals.interacted.hovered.bg_outline = None;
|
||||||
style.interact.inactive.bg_fill = None;
|
style.visuals.interacted.inactive.bg_fill = None;
|
||||||
style.interact.inactive.bg_outline = None;
|
style.visuals.interacted.inactive.bg_outline = None;
|
||||||
ui.set_style(style);
|
ui.set_style(style);
|
||||||
ui.set_layout(Layout::justified(Direction::Vertical));
|
ui.set_layout(Layout::justified(Direction::Vertical));
|
||||||
add_contents(ui)
|
add_contents(ui)
|
||||||
|
|
|
@ -2,43 +2,86 @@
|
||||||
|
|
||||||
use crate::{color::*, math::*, paint::LineStyle, types::*};
|
use crate::{color::*, math::*, paint::LineStyle, types::*};
|
||||||
|
|
||||||
// TODO: split into Spacing and Style?
|
|
||||||
/// Specifies the look and feel of a `Ui`.
|
/// Specifies the look and feel of a `Ui`.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct Style {
|
pub struct Style {
|
||||||
|
pub spacing: Spacing,
|
||||||
|
pub interaction: Interaction,
|
||||||
|
pub visuals: Visuals,
|
||||||
|
|
||||||
|
/// How many seconds a typical animation should last
|
||||||
|
pub animation_time: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Style {
|
||||||
|
// TODO: rename style.interact() to maybe... `style.response_visuals` ?
|
||||||
|
/// Use this style for interactive things
|
||||||
|
pub fn interact(&self, response: &Response) -> &WidgetVisuals {
|
||||||
|
self.visuals.interacted.style(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
|
pub struct Spacing {
|
||||||
|
/// Horizontal and vertical spacing between widgets
|
||||||
|
pub item_spacing: Vec2,
|
||||||
|
|
||||||
/// Horizontal and vertical padding within a window frame.
|
/// Horizontal and vertical padding within a window frame.
|
||||||
pub window_padding: Vec2,
|
pub window_padding: Vec2,
|
||||||
|
|
||||||
/// Button size is text size plus this on each side
|
/// Button size is text size plus this on each side
|
||||||
pub button_padding: Vec2,
|
pub button_padding: Vec2,
|
||||||
|
|
||||||
/// Horizontal and vertical spacing between widgets
|
|
||||||
pub item_spacing: Vec2,
|
|
||||||
|
|
||||||
/// Indent collapsing regions etc by this much.
|
/// Indent collapsing regions etc by this much.
|
||||||
pub indent: f32,
|
pub indent: f32,
|
||||||
|
|
||||||
/// Anything clickable is (at least) this wide.
|
/// Anything clickable is (at least) this wide.
|
||||||
pub clickable_diameter: f32,
|
pub clickable_diameter: f32,
|
||||||
|
|
||||||
|
/// Total width of a slider
|
||||||
|
pub slider_width: f32,
|
||||||
|
|
||||||
/// Checkboxes, radio button and collapsing headers have an icon at the start.
|
/// Checkboxes, radio button and collapsing headers have an icon at the start.
|
||||||
/// The text starts after this many pixels.
|
/// The text starts after this many pixels.
|
||||||
pub start_icon_width: f32,
|
pub icon_width: f32,
|
||||||
|
|
||||||
|
pub menu_bar_height: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Spacing {
|
||||||
|
/// Returns small icon rectangle and big icon rectangle
|
||||||
|
pub fn icon_rectangles(&self, rect: Rect) -> (Rect, Rect) {
|
||||||
|
let box_side = self.icon_width;
|
||||||
|
let big_icon_rect = Rect::from_center_size(
|
||||||
|
pos2(rect.left() + box_side / 2.0, rect.center().y),
|
||||||
|
vec2(box_side, box_side),
|
||||||
|
);
|
||||||
|
|
||||||
|
let small_rect_side = 8.0; // TODO: make a parameter
|
||||||
|
let small_icon_rect =
|
||||||
|
Rect::from_center_size(big_icon_rect.center(), Vec2::splat(small_rect_side));
|
||||||
|
|
||||||
|
(small_icon_rect, big_icon_rect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
|
pub struct Interaction {
|
||||||
/// Mouse must be the close to the side of a window to resize
|
/// Mouse must be the close to the side of a window to resize
|
||||||
pub resize_interact_radius_side: f32,
|
pub resize_grab_radius_side: f32,
|
||||||
|
|
||||||
/// Mouse must be the close to the corner of a window to resize
|
/// Mouse must be the close to the corner of a window to resize
|
||||||
pub resize_interact_radius_corner: f32,
|
pub resize_grab_radius_corner: f32,
|
||||||
|
}
|
||||||
|
|
||||||
pub resize_corner_size: f32,
|
#[derive(Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
|
pub struct Visuals {
|
||||||
|
pub interacted: Interacted,
|
||||||
|
|
||||||
// -----------------------------------------------
|
|
||||||
// Purely visual:
|
|
||||||
pub interact: Interact,
|
|
||||||
|
|
||||||
// TODO: an WidgetStyle ?
|
|
||||||
pub text_color: Srgba,
|
pub text_color: Srgba,
|
||||||
|
|
||||||
/// For stuff like check marks in check boxes.
|
/// For stuff like check marks in check boxes.
|
||||||
|
@ -52,18 +95,14 @@ pub struct Style {
|
||||||
/// e.g. the background of the slider or text edit
|
/// e.g. the background of the slider or text edit
|
||||||
pub dark_bg_color: Srgba,
|
pub dark_bg_color: Srgba,
|
||||||
|
|
||||||
|
pub window_corner_radius: f32,
|
||||||
|
|
||||||
|
pub resize_corner_size: f32,
|
||||||
|
|
||||||
/// Blink text cursor by this frequency. If None, always show the cursor.
|
/// Blink text cursor by this frequency. If None, always show the cursor.
|
||||||
pub cursor_blink_hz: Option<f32>,
|
pub cursor_blink_hz: Option<f32>,
|
||||||
pub text_cursor_width: f32,
|
pub text_cursor_width: f32,
|
||||||
|
|
||||||
// TODO: add ability to disable animations!
|
|
||||||
/// How many seconds a typical animation should last
|
|
||||||
pub animation_time: f32,
|
|
||||||
|
|
||||||
pub window: Window,
|
|
||||||
|
|
||||||
pub menu_bar: MenuBar,
|
|
||||||
|
|
||||||
/// Allow child widgets to be just on the border and still have an outline with some thickness
|
/// Allow child widgets to be just on the border and still have an outline with some thickness
|
||||||
pub clip_rect_margin: f32,
|
pub clip_rect_margin: f32,
|
||||||
|
|
||||||
|
@ -73,86 +112,17 @@ pub struct Style {
|
||||||
pub debug_resize: bool,
|
pub debug_resize: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Style {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
window_padding: vec2(6.0, 6.0),
|
|
||||||
button_padding: vec2(4.0, 1.0),
|
|
||||||
item_spacing: vec2(8.0, 4.0),
|
|
||||||
indent: 21.0,
|
|
||||||
clickable_diameter: 22.0,
|
|
||||||
start_icon_width: 14.0,
|
|
||||||
resize_interact_radius_side: 5.0,
|
|
||||||
resize_interact_radius_corner: 10.0,
|
|
||||||
resize_corner_size: 16.0,
|
|
||||||
interact: Default::default(),
|
|
||||||
text_color: Srgba::gray(160),
|
|
||||||
line_width: 1.0,
|
|
||||||
thin_outline: LineStyle::new(0.5, GRAY),
|
|
||||||
background_fill: Rgba::luminance_alpha(0.013, 0.95).into(),
|
|
||||||
dark_bg_color: Srgba::black_alpha(140),
|
|
||||||
cursor_blink_hz: None, // Some(1.0)
|
|
||||||
text_cursor_width: 2.0,
|
|
||||||
animation_time: 1.0 / 15.0,
|
|
||||||
window: Window::default(),
|
|
||||||
menu_bar: MenuBar::default(),
|
|
||||||
clip_rect_margin: 3.0,
|
|
||||||
debug_widget_rects: false,
|
|
||||||
debug_resize: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct Interact {
|
pub struct Interacted {
|
||||||
pub active: WidgetStyle,
|
pub active: WidgetVisuals,
|
||||||
pub hovered: WidgetStyle,
|
pub hovered: WidgetVisuals,
|
||||||
pub inactive: WidgetStyle,
|
pub inactive: WidgetVisuals,
|
||||||
pub disabled: WidgetStyle,
|
pub disabled: WidgetVisuals,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Interact {
|
impl Interacted {
|
||||||
fn default() -> Self {
|
pub fn style(&self, response: &Response) -> &WidgetVisuals {
|
||||||
Self {
|
|
||||||
active: WidgetStyle {
|
|
||||||
bg_fill: Some(Srgba::black_alpha(128)),
|
|
||||||
bg_outline: Some(LineStyle::new(2.0, WHITE)),
|
|
||||||
corner_radius: 0.0,
|
|
||||||
main_fill: srgba(120, 120, 200, 255),
|
|
||||||
stroke_color: WHITE,
|
|
||||||
stroke_width: 2.0,
|
|
||||||
},
|
|
||||||
hovered: WidgetStyle {
|
|
||||||
bg_fill: None,
|
|
||||||
bg_outline: Some(LineStyle::new(1.0, WHITE)),
|
|
||||||
corner_radius: 2.0,
|
|
||||||
main_fill: srgba(100, 100, 150, 255),
|
|
||||||
stroke_color: Srgba::gray(240),
|
|
||||||
stroke_width: 1.5,
|
|
||||||
},
|
|
||||||
inactive: WidgetStyle {
|
|
||||||
bg_fill: None,
|
|
||||||
bg_outline: Some(LineStyle::new(1.0, Srgba::gray(128))),
|
|
||||||
corner_radius: 4.0,
|
|
||||||
main_fill: srgba(60, 60, 80, 255),
|
|
||||||
stroke_color: Srgba::gray(200), // Mustn't look grayed out!
|
|
||||||
stroke_width: 1.0,
|
|
||||||
},
|
|
||||||
disabled: WidgetStyle {
|
|
||||||
bg_fill: None,
|
|
||||||
bg_outline: Some(LineStyle::new(0.5, Srgba::gray(128))),
|
|
||||||
corner_radius: 4.0,
|
|
||||||
main_fill: srgba(50, 50, 50, 255),
|
|
||||||
stroke_color: Srgba::gray(128), // Should look grayed out
|
|
||||||
stroke_width: 0.5,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Interact {
|
|
||||||
pub fn style(&self, response: &Response) -> &WidgetStyle {
|
|
||||||
if response.active || response.has_kb_focus {
|
if response.active || response.has_kb_focus {
|
||||||
&self.active
|
&self.active
|
||||||
} else if response.sense == Sense::nothing() {
|
} else if response.sense == Sense::nothing() {
|
||||||
|
@ -167,7 +137,7 @@ impl Interact {
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub struct WidgetStyle {
|
pub struct WidgetVisuals {
|
||||||
/// Background color of widget
|
/// Background color of widget
|
||||||
pub bg_fill: Option<Srgba>,
|
pub bg_fill: Option<Srgba>,
|
||||||
|
|
||||||
|
@ -189,82 +159,306 @@ pub struct WidgetStyle {
|
||||||
pub stroke_width: f32,
|
pub stroke_width: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WidgetStyle {
|
impl WidgetVisuals {
|
||||||
pub fn line_style(&self) -> LineStyle {
|
pub fn line_style(&self) -> LineStyle {
|
||||||
LineStyle::new(self.stroke_width, self.stroke_color)
|
LineStyle::new(self.stroke_width, self.stroke_color)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
// ----------------------------------------------------------------------------
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
|
||||||
pub struct Window {
|
|
||||||
pub corner_radius: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for Window {
|
impl Default for Style {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
corner_radius: 10.0,
|
spacing: Spacing::default(),
|
||||||
|
interaction: Interaction::default(),
|
||||||
|
visuals: Visuals::default(),
|
||||||
|
animation_time: 1.0 / 15.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
impl Default for Spacing {
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
|
||||||
pub struct MenuBar {
|
|
||||||
pub height: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for MenuBar {
|
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self { height: 16.0 }
|
Self {
|
||||||
|
item_spacing: vec2(8.0, 4.0),
|
||||||
|
window_padding: vec2(6.0, 6.0),
|
||||||
|
button_padding: vec2(4.0, 1.0),
|
||||||
|
indent: 21.0,
|
||||||
|
clickable_diameter: 22.0,
|
||||||
|
slider_width: 140.0,
|
||||||
|
icon_width: 14.0,
|
||||||
|
menu_bar_height: 16.0,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Style {
|
impl Default for Interaction {
|
||||||
// TODO: rename style.interact() to something better
|
fn default() -> Self {
|
||||||
/// Use this style for interactive things
|
Self {
|
||||||
pub fn interact(&self, response: &Response) -> &WidgetStyle {
|
resize_grab_radius_side: 5.0,
|
||||||
self.interact.style(response)
|
resize_grab_radius_corner: 10.0,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns small icon rectangle and big icon rectangle
|
|
||||||
pub fn icon_rectangles(&self, rect: Rect) -> (Rect, Rect) {
|
|
||||||
let box_side = self.start_icon_width;
|
|
||||||
let big_icon_rect = Rect::from_center_size(
|
|
||||||
pos2(rect.left() + box_side / 2.0, rect.center().y),
|
|
||||||
vec2(box_side, box_side),
|
|
||||||
);
|
|
||||||
|
|
||||||
let small_rect_side = 8.0; // TODO: make a parameter
|
|
||||||
let small_icon_rect =
|
|
||||||
Rect::from_center_size(big_icon_rect.center(), Vec2::splat(small_rect_side));
|
|
||||||
|
|
||||||
(small_icon_rect, big_icon_rect)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Visuals {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
interacted: Default::default(),
|
||||||
|
text_color: Srgba::gray(160),
|
||||||
|
line_width: 1.0,
|
||||||
|
thin_outline: LineStyle::new(0.5, GRAY),
|
||||||
|
background_fill: Rgba::luminance_alpha(0.013, 0.95).into(),
|
||||||
|
dark_bg_color: Srgba::black_alpha(140),
|
||||||
|
window_corner_radius: 10.0,
|
||||||
|
resize_corner_size: 16.0,
|
||||||
|
cursor_blink_hz: None, // Some(1.0)
|
||||||
|
text_cursor_width: 2.0,
|
||||||
|
clip_rect_margin: 3.0,
|
||||||
|
debug_widget_rects: false,
|
||||||
|
debug_resize: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Interacted {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
active: WidgetVisuals {
|
||||||
|
bg_fill: Some(Srgba::black_alpha(128)),
|
||||||
|
bg_outline: Some(LineStyle::new(2.0, WHITE)),
|
||||||
|
corner_radius: 0.0,
|
||||||
|
main_fill: srgba(120, 120, 200, 255),
|
||||||
|
stroke_color: WHITE,
|
||||||
|
stroke_width: 2.0,
|
||||||
|
},
|
||||||
|
hovered: WidgetVisuals {
|
||||||
|
bg_fill: None,
|
||||||
|
bg_outline: Some(LineStyle::new(1.0, WHITE)),
|
||||||
|
corner_radius: 2.0,
|
||||||
|
main_fill: srgba(100, 100, 150, 255),
|
||||||
|
stroke_color: Srgba::gray(240),
|
||||||
|
stroke_width: 1.5,
|
||||||
|
},
|
||||||
|
inactive: WidgetVisuals {
|
||||||
|
bg_fill: None,
|
||||||
|
bg_outline: Some(LineStyle::new(1.0, Srgba::gray(128))),
|
||||||
|
corner_radius: 4.0,
|
||||||
|
main_fill: srgba(60, 60, 80, 255),
|
||||||
|
stroke_color: Srgba::gray(200), // Mustn't look grayed out!
|
||||||
|
stroke_width: 1.0,
|
||||||
|
},
|
||||||
|
disabled: WidgetVisuals {
|
||||||
|
bg_fill: None,
|
||||||
|
bg_outline: Some(LineStyle::new(0.5, Srgba::gray(128))),
|
||||||
|
corner_radius: 4.0,
|
||||||
|
main_fill: srgba(50, 50, 50, 255),
|
||||||
|
stroke_color: Srgba::gray(128), // Should look grayed out
|
||||||
|
stroke_width: 0.5,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
use crate::{widgets::*, Ui};
|
||||||
|
|
||||||
impl Style {
|
impl Style {
|
||||||
#[rustfmt::skip]
|
|
||||||
pub fn ui(&mut self, ui: &mut crate::Ui) {
|
pub fn ui(&mut self, ui: &mut crate::Ui) {
|
||||||
use crate::{widgets::*};
|
if ui.add(Button::new("Reset")).clicked {
|
||||||
if ui.add(Button::new("Reset style")).clicked {
|
|
||||||
*self = Default::default();
|
*self = Default::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.add(Checkbox::new(&mut self.debug_widget_rects, "Paint debug rectangles around widgets"));
|
let Self {
|
||||||
ui.add(Checkbox::new(&mut self.debug_resize, "Debug Resize"));
|
spacing,
|
||||||
|
interaction,
|
||||||
ui.add(Slider::f32(&mut self.item_spacing.x, 0.0..=10.0).text("item_spacing.x"));
|
visuals,
|
||||||
ui.add(Slider::f32(&mut self.item_spacing.y, 0.0..=10.0).text("item_spacing.y"));
|
animation_time,
|
||||||
ui.add(Slider::f32(&mut self.window_padding.x, 0.0..=10.0).text("window_padding.x"));
|
} = self;
|
||||||
ui.add(Slider::f32(&mut self.window_padding.y, 0.0..=10.0).text("window_padding.y"));
|
ui.collapsing("Spacing", |ui| spacing.ui(ui));
|
||||||
ui.add(Slider::f32(&mut self.indent, 0.0..=100.0).text("indent"));
|
ui.collapsing("Interaction", |ui| interaction.ui(ui));
|
||||||
ui.add(Slider::f32(&mut self.button_padding.x, 0.0..=20.0).text("button_padding.x"));
|
ui.collapsing("Visuals", |ui| visuals.ui(ui));
|
||||||
ui.add(Slider::f32(&mut self.button_padding.y, 0.0..=20.0).text("button_padding.y"));
|
ui.add(Slider::f32(animation_time, 0.0..=1.0).text("animation_time"));
|
||||||
ui.add(Slider::f32(&mut self.clickable_diameter, 0.0..=60.0).text("clickable_diameter"));
|
|
||||||
ui.add(Slider::f32(&mut self.start_icon_width, 0.0..=60.0).text("start_icon_width"));
|
|
||||||
ui.add(Slider::f32(&mut self.line_width, 0.0..=10.0).text("line_width"));
|
|
||||||
ui.add(Slider::f32(&mut self.animation_time, 0.0..=1.0).text("animation_time"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Spacing {
|
||||||
|
pub fn ui(&mut self, ui: &mut crate::Ui) {
|
||||||
|
if ui.add(Button::new("Reset")).clicked {
|
||||||
|
*self = Default::default();
|
||||||
|
}
|
||||||
|
|
||||||
|
let Self {
|
||||||
|
item_spacing,
|
||||||
|
window_padding,
|
||||||
|
button_padding,
|
||||||
|
indent,
|
||||||
|
clickable_diameter,
|
||||||
|
slider_width,
|
||||||
|
icon_width,
|
||||||
|
menu_bar_height,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
ui_slider_vec2(ui, item_spacing, 0.0..=20.0, "item_spacing");
|
||||||
|
ui_slider_vec2(ui, window_padding, 0.0..=20.0, "window_padding");
|
||||||
|
ui_slider_vec2(ui, button_padding, 0.0..=20.0, "button_padding");
|
||||||
|
ui.add(Slider::f32(indent, 0.0..=100.0).text("indent"));
|
||||||
|
ui.add(Slider::f32(clickable_diameter, 0.0..=40.0).text("clickable_diameter"));
|
||||||
|
ui.add(Slider::f32(slider_width, 0.0..=1000.0).text("slider_width"));
|
||||||
|
ui.add(Slider::f32(icon_width, 0.0..=40.0).text("icon_width"));
|
||||||
|
ui.add(Slider::f32(menu_bar_height, 0.0..=40.0).text("menu_bar_height"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Interaction {
|
||||||
|
pub fn ui(&mut self, ui: &mut crate::Ui) {
|
||||||
|
if ui.add(Button::new("Reset")).clicked {
|
||||||
|
*self = Default::default();
|
||||||
|
}
|
||||||
|
|
||||||
|
let Self {
|
||||||
|
resize_grab_radius_side,
|
||||||
|
resize_grab_radius_corner,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
ui.add(Slider::f32(resize_grab_radius_side, 0.0..=20.0).text("resize_grab_radius_side"));
|
||||||
|
ui.add(
|
||||||
|
Slider::f32(resize_grab_radius_corner, 0.0..=20.0).text("resize_grab_radius_corner"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Interacted {
|
||||||
|
pub fn ui(&mut self, ui: &mut crate::Ui) {
|
||||||
|
if ui.add(Button::new("Reset")).clicked {
|
||||||
|
*self = Default::default();
|
||||||
|
}
|
||||||
|
|
||||||
|
let Self {
|
||||||
|
active,
|
||||||
|
hovered,
|
||||||
|
inactive,
|
||||||
|
disabled,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
ui.collapsing("active", |ui| active.ui(ui));
|
||||||
|
ui.collapsing("hovered", |ui| hovered.ui(ui));
|
||||||
|
ui.collapsing("inactive", |ui| inactive.ui(ui));
|
||||||
|
ui.collapsing("disabled", |ui| disabled.ui(ui));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WidgetVisuals {
|
||||||
|
pub fn ui(&mut self, ui: &mut crate::Ui) {
|
||||||
|
let Self {
|
||||||
|
bg_fill,
|
||||||
|
bg_outline,
|
||||||
|
corner_radius,
|
||||||
|
main_fill,
|
||||||
|
stroke_color,
|
||||||
|
stroke_width,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
let _ = bg_fill; // ui_color(ui, bg_fill, "bg_fill"); // TODO
|
||||||
|
let _ = bg_outline; // bg_outline.ui(ui, "bg_outline");// TODO
|
||||||
|
ui.add(Slider::f32(corner_radius, 0.0..=10.0).text("corner_radius"));
|
||||||
|
ui_color(ui, main_fill, "main_fill");
|
||||||
|
ui_color(ui, stroke_color, "stroke_color");
|
||||||
|
ui.add(Slider::f32(stroke_width, 0.0..=10.0).text("stroke_width"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Visuals {
|
||||||
|
pub fn ui(&mut self, ui: &mut crate::Ui) {
|
||||||
|
if ui.add(Button::new("Reset")).clicked {
|
||||||
|
*self = Default::default();
|
||||||
|
}
|
||||||
|
|
||||||
|
let Self {
|
||||||
|
interacted,
|
||||||
|
text_color,
|
||||||
|
line_width,
|
||||||
|
thin_outline,
|
||||||
|
background_fill,
|
||||||
|
dark_bg_color,
|
||||||
|
window_corner_radius,
|
||||||
|
resize_corner_size,
|
||||||
|
cursor_blink_hz,
|
||||||
|
text_cursor_width,
|
||||||
|
clip_rect_margin,
|
||||||
|
debug_widget_rects,
|
||||||
|
debug_resize,
|
||||||
|
} = self;
|
||||||
|
|
||||||
|
ui.collapsing("interacted", |ui| interacted.ui(ui));
|
||||||
|
ui_color(ui, text_color, "text_color");
|
||||||
|
ui.add(Slider::f32(line_width, 0.0..=10.0).text("line_width"));
|
||||||
|
thin_outline.ui(ui, "thin_outline");
|
||||||
|
ui_color(ui, background_fill, "background_fill");
|
||||||
|
ui_color(ui, dark_bg_color, "dark_bg_color");
|
||||||
|
ui.add(Slider::f32(window_corner_radius, 0.0..=20.0).text("window_corner_radius"));
|
||||||
|
ui.add(Slider::f32(resize_corner_size, 0.0..=20.0).text("resize_corner_size"));
|
||||||
|
let _ = cursor_blink_hz; // TODO
|
||||||
|
ui.add(Slider::f32(text_cursor_width, 0.0..=2.0).text("text_cursor_width"));
|
||||||
|
ui.add(Slider::f32(clip_rect_margin, 0.0..=20.0).text("clip_rect_margin"));
|
||||||
|
|
||||||
|
ui.add(Checkbox::new(
|
||||||
|
debug_widget_rects,
|
||||||
|
"Paint debug rectangles around widgets",
|
||||||
|
));
|
||||||
|
ui.add(Checkbox::new(debug_resize, "Debug Resize"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LineStyle {
|
||||||
|
pub fn ui(&mut self, ui: &mut crate::Ui, text: &str) {
|
||||||
|
let Self { width, color } = self;
|
||||||
|
ui.horizontal_centered(|ui| {
|
||||||
|
ui.label(format!("{}: ", text));
|
||||||
|
ui.add(Slider::f32(width, 0.0..=10.0));
|
||||||
|
ui_color(ui, color, "color");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: improve and standardize ui_slider_vec2
|
||||||
|
fn ui_slider_vec2(ui: &mut Ui, value: &mut Vec2, range: std::ops::RangeInclusive<f32>, text: &str) {
|
||||||
|
ui.horizontal_centered(|ui| {
|
||||||
|
ui.label(format!("{}: ", text));
|
||||||
|
ui.add(Slider::f32(&mut value.x, range.clone()))
|
||||||
|
.tooltip_text("x");
|
||||||
|
ui.add(Slider::f32(&mut value.y, range)).tooltip_text("y");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: improve color picker
|
||||||
|
fn ui_color(ui: &mut Ui, srgba: &mut Srgba, text: &str) {
|
||||||
|
ui.horizontal_centered(|ui| {
|
||||||
|
// TODO: DragValue::u8
|
||||||
|
// ui.label(format!("{} sRGBA: ", text));
|
||||||
|
// ui.add(DragValue::u8(&mut srgba.r).speed(1))
|
||||||
|
// .tooltip_text("r");
|
||||||
|
// ui.add(DragValue::u8(&mut srgba.g).speed(1))
|
||||||
|
// .tooltip_text("g");
|
||||||
|
// ui.add(DragValue::u8(&mut srgba.b).speed(1))
|
||||||
|
// .tooltip_text("b");
|
||||||
|
// ui.add(DragValue::u8(&mut srgba.a).speed(1))
|
||||||
|
// .tooltip_text("a");
|
||||||
|
|
||||||
|
ui.label(format!("{} RGBA: ", text));
|
||||||
|
let mut rgba = Rgba::from(*srgba);
|
||||||
|
ui.add(DragValue::f32(&mut rgba.r).speed(0.003))
|
||||||
|
.tooltip_text("r");
|
||||||
|
ui.add(DragValue::f32(&mut rgba.g).speed(0.003))
|
||||||
|
.tooltip_text("g");
|
||||||
|
ui.add(DragValue::f32(&mut rgba.b).speed(0.003))
|
||||||
|
.tooltip_text("b");
|
||||||
|
ui.add(DragValue::f32(&mut rgba.a).speed(0.003))
|
||||||
|
.tooltip_text("a");
|
||||||
|
if rgba != Rgba::from(*srgba) {
|
||||||
|
*srgba = Srgba::from(rgba);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -38,8 +38,8 @@ pub struct Ui {
|
||||||
/// Where the next widget will be put.
|
/// Where the next widget will be put.
|
||||||
/// Progresses along self.dir.
|
/// Progresses along self.dir.
|
||||||
/// Initially set to rect.min
|
/// Initially set to rect.min
|
||||||
/// If something has already been added, this will point ot style.item_spacing beyond the latest child.
|
/// If something has already been added, this will point ot style.spacing.item_spacing beyond the latest child.
|
||||||
/// The cursor can thus be style.item_spacing pixels outside of the child_bounds.
|
/// The cursor can thus be style.spacing.item_spacing pixels outside of the child_bounds.
|
||||||
cursor: Pos2, // TODO: move into Layout?
|
cursor: Pos2, // TODO: move into Layout?
|
||||||
|
|
||||||
/// How many children has been added to us?
|
/// How many children has been added to us?
|
||||||
|
@ -54,7 +54,7 @@ impl Ui {
|
||||||
|
|
||||||
pub fn new(ctx: Arc<Context>, layer: Layer, id: Id, rect: Rect) -> Self {
|
pub fn new(ctx: Arc<Context>, layer: Layer, id: Id, rect: Rect) -> Self {
|
||||||
let style = ctx.style();
|
let style = ctx.style();
|
||||||
let clip_rect = rect.expand(style.clip_rect_margin);
|
let clip_rect = rect.expand(style.visuals.clip_rect_margin);
|
||||||
Ui {
|
Ui {
|
||||||
id,
|
id,
|
||||||
painter: Painter::new(ctx, layer, clip_rect),
|
painter: Painter::new(ctx, layer, clip_rect),
|
||||||
|
@ -75,7 +75,7 @@ impl Ui {
|
||||||
painter: self.painter.clone(),
|
painter: self.painter.clone(),
|
||||||
desired_rect: child_rect,
|
desired_rect: child_rect,
|
||||||
child_bounds: Rect::from_min_size(child_rect.min, Vec2::zero()), // TODO: Rect::nothing() ?
|
child_bounds: Rect::from_min_size(child_rect.min, Vec2::zero()), // TODO: Rect::nothing() ?
|
||||||
style: self.style.clone(),
|
style: self.style().clone(),
|
||||||
layout: self.layout,
|
layout: self.layout,
|
||||||
cursor: child_rect.min,
|
cursor: child_rect.min,
|
||||||
child_count: 0,
|
child_count: 0,
|
||||||
|
@ -366,7 +366,7 @@ impl Ui {
|
||||||
|
|
||||||
let rect = self.reserve_space_impl(desired_size);
|
let rect = self.reserve_space_impl(desired_size);
|
||||||
|
|
||||||
if self.style().debug_widget_rects {
|
if self.style().visuals.debug_widget_rects {
|
||||||
self.painter.rect_outline(rect, 0.0, (1.0, LIGHT_BLUE));
|
self.painter.rect_outline(rect, 0.0, (1.0, LIGHT_BLUE));
|
||||||
|
|
||||||
let color = color::srgba(200, 0, 0, 255);
|
let color = color::srgba(200, 0, 0, 255);
|
||||||
|
@ -535,7 +535,7 @@ impl Ui {
|
||||||
self.layout().dir() == Direction::Vertical,
|
self.layout().dir() == Direction::Vertical,
|
||||||
"You can only indent vertical layouts"
|
"You can only indent vertical layouts"
|
||||||
);
|
);
|
||||||
let indent = vec2(self.style.indent, 0.0);
|
let indent = vec2(self.style().spacing.indent, 0.0);
|
||||||
let child_rect = Rect::from_min_max(self.cursor + indent, self.bottom_right());
|
let child_rect = Rect::from_min_max(self.cursor + indent, self.bottom_right());
|
||||||
let mut child_ui = Ui {
|
let mut child_ui = Ui {
|
||||||
id: self.id.with(id_source),
|
id: self.id.with(id_source),
|
||||||
|
@ -550,7 +550,7 @@ impl Ui {
|
||||||
let line_end = pos2(line_start.x, line_start.y + size.y - 2.0);
|
let line_end = pos2(line_start.x, line_start.y + size.y - 2.0);
|
||||||
self.painter.line_segment(
|
self.painter.line_segment(
|
||||||
[line_start, line_end],
|
[line_start, line_end],
|
||||||
(self.style.line_width, Srgba::gray(150)),
|
(self.style().visuals.line_width, Srgba::gray(150)),
|
||||||
);
|
);
|
||||||
|
|
||||||
(ret, self.allocate_space(indent + size))
|
(ret, self.allocate_space(indent + size))
|
||||||
|
@ -631,7 +631,7 @@ impl Ui {
|
||||||
F: FnOnce(&mut [Self]) -> R,
|
F: FnOnce(&mut [Self]) -> R,
|
||||||
{
|
{
|
||||||
// TODO: ensure there is space
|
// TODO: ensure there is space
|
||||||
let spacing = self.style.item_spacing.x;
|
let spacing = self.style().spacing.item_spacing.x;
|
||||||
let total_spacing = spacing * (num_columns as f32 - 1.0);
|
let total_spacing = spacing * (num_columns as f32 - 1.0);
|
||||||
let column_width = (self.available().width() - total_spacing) / (num_columns as f32);
|
let column_width = (self.available().width() - total_spacing) / (num_columns as f32);
|
||||||
|
|
||||||
|
|
|
@ -107,7 +107,9 @@ impl Label {
|
||||||
// This should be the easiest method of putting text anywhere.
|
// This should be the easiest method of putting text anywhere.
|
||||||
|
|
||||||
pub fn paint_galley(&self, ui: &mut Ui, pos: Pos2, galley: font::Galley) {
|
pub fn paint_galley(&self, ui: &mut Ui, pos: Pos2, galley: font::Galley) {
|
||||||
let text_color = self.text_color.unwrap_or_else(|| ui.style().text_color);
|
let text_color = self
|
||||||
|
.text_color
|
||||||
|
.unwrap_or_else(|| ui.style().visuals.text_color);
|
||||||
ui.painter()
|
ui.painter()
|
||||||
.galley(pos, galley, self.text_style, text_color);
|
.galley(pos, galley, self.text_style, text_color);
|
||||||
}
|
}
|
||||||
|
@ -201,7 +203,7 @@ impl Widget for Hyperlink {
|
||||||
let max_x = pos.x + line.max_x();
|
let max_x = pos.x + line.max_x();
|
||||||
ui.painter().line_segment(
|
ui.painter().line_segment(
|
||||||
[pos2(min_x, y), pos2(max_x, y)],
|
[pos2(min_x, y), pos2(max_x, y)],
|
||||||
(ui.style().line_width, color),
|
(ui.style().visuals.line_width, color),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,9 +283,9 @@ impl Widget for Button {
|
||||||
let id = ui.make_position_id();
|
let id = ui.make_position_id();
|
||||||
let font = &ui.fonts()[text_style];
|
let font = &ui.fonts()[text_style];
|
||||||
let galley = font.layout_multiline(text, ui.available().width());
|
let galley = font.layout_multiline(text, ui.available().width());
|
||||||
let padding = ui.style().button_padding;
|
let padding = ui.style().spacing.button_padding;
|
||||||
let mut size = galley.size + 2.0 * padding;
|
let mut size = galley.size + 2.0 * padding;
|
||||||
size.y = size.y.max(ui.style().clickable_diameter);
|
size.y = size.y.max(ui.style().spacing.clickable_diameter);
|
||||||
let rect = ui.allocate_space(size);
|
let rect = ui.allocate_space(size);
|
||||||
let response = ui.interact(rect, id, sense);
|
let response = ui.interact(rect, id, sense);
|
||||||
let text_cursor = response.rect.left_center() + vec2(padding.x, -0.5 * galley.size.y);
|
let text_cursor = response.rect.left_center() + vec2(padding.x, -0.5 * galley.size.y);
|
||||||
|
@ -340,18 +342,19 @@ impl<'a> Widget for Checkbox<'a> {
|
||||||
let text_style = TextStyle::Button;
|
let text_style = TextStyle::Button;
|
||||||
let font = &ui.fonts()[text_style];
|
let font = &ui.fonts()[text_style];
|
||||||
let galley = font.layout_single_line(text);
|
let galley = font.layout_single_line(text);
|
||||||
let size = ui.style().button_padding
|
let size = ui.style().spacing.button_padding
|
||||||
+ vec2(ui.style().start_icon_width, 0.0)
|
+ vec2(ui.style().spacing.icon_width, 0.0)
|
||||||
+ galley.size
|
+ galley.size
|
||||||
+ ui.style().button_padding;
|
+ ui.style().spacing.button_padding;
|
||||||
let rect = ui.allocate_space(size);
|
let rect = ui.allocate_space(size);
|
||||||
let response = ui.interact(rect, id, Sense::click());
|
let response = ui.interact(rect, id, Sense::click());
|
||||||
let text_cursor =
|
let text_cursor = response.rect.min
|
||||||
response.rect.min + ui.style().button_padding + vec2(ui.style().start_icon_width, 0.0);
|
+ ui.style().spacing.button_padding
|
||||||
|
+ vec2(ui.style().spacing.icon_width, 0.0);
|
||||||
if response.clicked {
|
if response.clicked {
|
||||||
*checked = !*checked;
|
*checked = !*checked;
|
||||||
}
|
}
|
||||||
let (small_icon_rect, big_icon_rect) = ui.style().icon_rectangles(response.rect);
|
let (small_icon_rect, big_icon_rect) = ui.style().spacing.icon_rectangles(response.rect);
|
||||||
ui.painter().add(PaintCmd::Rect {
|
ui.painter().add(PaintCmd::Rect {
|
||||||
rect: big_icon_rect,
|
rect: big_icon_rect,
|
||||||
corner_radius: ui.style().interact(&response).corner_radius,
|
corner_radius: ui.style().interact(&response).corner_radius,
|
||||||
|
@ -369,7 +372,7 @@ impl<'a> Widget for Checkbox<'a> {
|
||||||
pos2(small_icon_rect.right(), small_icon_rect.top()),
|
pos2(small_icon_rect.right(), small_icon_rect.top()),
|
||||||
]),
|
]),
|
||||||
closed: false,
|
closed: false,
|
||||||
outline: Some(LineStyle::new(ui.style().line_width, stroke_color)),
|
outline: Some(LineStyle::new(ui.style().visuals.line_width, stroke_color)),
|
||||||
fill: None,
|
fill: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -417,19 +420,20 @@ impl Widget for RadioButton {
|
||||||
let text_style = TextStyle::Button;
|
let text_style = TextStyle::Button;
|
||||||
let font = &ui.fonts()[text_style];
|
let font = &ui.fonts()[text_style];
|
||||||
let galley = font.layout_multiline(text, ui.available().width());
|
let galley = font.layout_multiline(text, ui.available().width());
|
||||||
let size = ui.style().button_padding
|
let size = ui.style().spacing.button_padding
|
||||||
+ vec2(ui.style().start_icon_width, 0.0)
|
+ vec2(ui.style().spacing.icon_width, 0.0)
|
||||||
+ galley.size
|
+ galley.size
|
||||||
+ ui.style().button_padding;
|
+ ui.style().spacing.button_padding;
|
||||||
let rect = ui.allocate_space(size);
|
let rect = ui.allocate_space(size);
|
||||||
let response = ui.interact(rect, id, Sense::click());
|
let response = ui.interact(rect, id, Sense::click());
|
||||||
let text_cursor =
|
let text_cursor = response.rect.min
|
||||||
response.rect.min + ui.style().button_padding + vec2(ui.style().start_icon_width, 0.0);
|
+ ui.style().spacing.button_padding
|
||||||
|
+ vec2(ui.style().spacing.icon_width, 0.0);
|
||||||
|
|
||||||
let bg_fill = ui.style().interact(&response).bg_fill;
|
let bg_fill = ui.style().interact(&response).bg_fill;
|
||||||
let stroke_color = ui.style().interact(&response).stroke_color;
|
let stroke_color = ui.style().interact(&response).stroke_color;
|
||||||
|
|
||||||
let (small_icon_rect, big_icon_rect) = ui.style().icon_rectangles(response.rect);
|
let (small_icon_rect, big_icon_rect) = ui.style().spacing.icon_rectangles(response.rect);
|
||||||
|
|
||||||
let painter = ui.painter();
|
let painter = ui.painter();
|
||||||
|
|
||||||
|
@ -507,7 +511,7 @@ impl Widget for Separator {
|
||||||
color,
|
color,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
let line_width = line_width.unwrap_or_else(|| ui.style().line_width);
|
let line_width = line_width.unwrap_or_else(|| ui.style().visuals.line_width);
|
||||||
|
|
||||||
let available_space = ui.available_finite().size();
|
let available_space = ui.available_finite().size();
|
||||||
|
|
||||||
|
|
|
@ -126,7 +126,7 @@ impl<'a> Slider<'a> {
|
||||||
/// Just the slider, no text
|
/// Just the slider, no text
|
||||||
fn allocate_slide_space(&self, ui: &mut Ui, height: f32) -> Response {
|
fn allocate_slide_space(&self, ui: &mut Ui, height: f32) -> Response {
|
||||||
let id = self.id.unwrap_or_else(|| ui.make_position_id());
|
let id = self.id.unwrap_or_else(|| ui.make_position_id());
|
||||||
let desired_size = vec2(ui.available().width(), height);
|
let desired_size = vec2(ui.style().spacing.slider_width, height);
|
||||||
let rect = ui.allocate_space(desired_size);
|
let rect = ui.allocate_space(desired_size);
|
||||||
ui.interact(rect, id, Sense::click_and_drag())
|
ui.interact(rect, id, Sense::click_and_drag())
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ impl<'a> Slider<'a> {
|
||||||
ui.painter().add(PaintCmd::Rect {
|
ui.painter().add(PaintCmd::Rect {
|
||||||
rect: rail_rect,
|
rect: rail_rect,
|
||||||
corner_radius: rail_radius,
|
corner_radius: rail_radius,
|
||||||
fill: Some(ui.style().background_fill),
|
fill: Some(ui.style().visuals.background_fill),
|
||||||
outline: Some(LineStyle::new(1.0, Srgba::gray(200))), // TODO
|
outline: Some(LineStyle::new(1.0, Srgba::gray(200))), // TODO
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -182,10 +182,12 @@ impl<'a> Slider<'a> {
|
||||||
|
|
||||||
/// Just the text label
|
/// Just the text label
|
||||||
fn text_ui(&mut self, ui: &mut Ui, x_range: RangeInclusive<f32>) {
|
fn text_ui(&mut self, ui: &mut Ui, x_range: RangeInclusive<f32>) {
|
||||||
let text_color = self.text_color.unwrap_or_else(|| ui.style().text_color);
|
let text_color = self
|
||||||
|
.text_color
|
||||||
|
.unwrap_or_else(|| ui.style().visuals.text_color);
|
||||||
|
|
||||||
if let Some(label_text) = self.text.as_deref() {
|
if let Some(label_text) = self.text.as_deref() {
|
||||||
ui.style_mut().item_spacing.x = 0.0;
|
ui.style_mut().spacing.item_spacing.x = 0.0;
|
||||||
ui.add(
|
ui.add(
|
||||||
Label::new(format!("{}: ", label_text))
|
Label::new(format!("{}: ", label_text))
|
||||||
.multiline(false)
|
.multiline(false)
|
||||||
|
@ -258,30 +260,21 @@ impl<'a> Widget for Slider<'a> {
|
||||||
fn ui(mut self, ui: &mut Ui) -> Response {
|
fn ui(mut self, ui: &mut Ui) -> Response {
|
||||||
let text_style = TextStyle::Button;
|
let text_style = TextStyle::Button;
|
||||||
let font = &ui.fonts()[text_style];
|
let font = &ui.fonts()[text_style];
|
||||||
let height = font.line_spacing().max(ui.style().clickable_diameter);
|
let height = font
|
||||||
|
.line_spacing()
|
||||||
|
.max(ui.style().spacing.clickable_diameter);
|
||||||
|
|
||||||
if let Some(text) = &self.text {
|
if let Some(text) = &self.text {
|
||||||
self.id = self.id.or_else(|| Some(ui.make_unique_child_id(text)));
|
self.id = self.id.or_else(|| Some(ui.make_unique_child_id(text)));
|
||||||
|
|
||||||
ui.columns(2, |columns| {
|
ui.horizontal_centered(|ui| {
|
||||||
let slider_ui = &mut columns[0];
|
let slider_response = self.allocate_slide_space(ui, height);
|
||||||
let slider_response = self.allocate_slide_space(slider_ui, height);
|
self.slider_ui(ui, &slider_response);
|
||||||
self.slider_ui(slider_ui, &slider_response);
|
|
||||||
let x_range = x_range(&slider_response.rect);
|
let x_range = x_range(&slider_response.rect);
|
||||||
|
|
||||||
// Place the text in line with the slider on the left:
|
|
||||||
let text_ui = &mut columns[1];
|
|
||||||
text_ui.set_desired_height(slider_response.rect.height());
|
|
||||||
text_ui.inner_layout(
|
|
||||||
Layout::horizontal(Align::Center),
|
|
||||||
text_ui.available().size(),
|
|
||||||
|ui| {
|
|
||||||
self.text_ui(ui, x_range);
|
self.text_ui(ui, x_range);
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
slider_response
|
slider_response
|
||||||
})
|
})
|
||||||
|
.0
|
||||||
} else {
|
} else {
|
||||||
let response = self.allocate_slide_space(ui, height);
|
let response = self.allocate_slide_space(ui, height);
|
||||||
self.slider_ui(ui, &response);
|
self.slider_ui(ui, &response);
|
||||||
|
|
|
@ -183,13 +183,13 @@ impl<'t> Widget for TextEdit<'t> {
|
||||||
painter.add(PaintCmd::Rect {
|
painter.add(PaintCmd::Rect {
|
||||||
rect: bg_rect,
|
rect: bg_rect,
|
||||||
corner_radius: ui.style().interact(&response).corner_radius,
|
corner_radius: ui.style().interact(&response).corner_radius,
|
||||||
fill: Some(ui.style().dark_bg_color),
|
fill: Some(ui.style().visuals.dark_bg_color),
|
||||||
outline: ui.style().interact(&response).bg_outline,
|
outline: ui.style().interact(&response).bg_outline,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ui.memory().has_kb_focus(id) {
|
if ui.memory().has_kb_focus(id) {
|
||||||
let cursor_blink_hz = ui.style().cursor_blink_hz;
|
let cursor_blink_hz = ui.style().visuals.cursor_blink_hz;
|
||||||
let show_cursor = if let Some(cursor_blink_hz) = cursor_blink_hz {
|
let show_cursor = if let Some(cursor_blink_hz) = cursor_blink_hz {
|
||||||
ui.ctx().request_repaint(); // TODO: only when cursor blinks on or off
|
ui.ctx().request_repaint(); // TODO: only when cursor blinks on or off
|
||||||
(ui.input().time * cursor_blink_hz as f64 * 3.0).floor() as i64 % 3 != 0
|
(ui.input().time * cursor_blink_hz as f64 * 3.0).floor() as i64 % 3 != 0
|
||||||
|
@ -202,7 +202,7 @@ impl<'t> Widget for TextEdit<'t> {
|
||||||
let cursor_pos = response.rect.min + galley.char_start_pos(cursor);
|
let cursor_pos = response.rect.min + galley.char_start_pos(cursor);
|
||||||
painter.line_segment(
|
painter.line_segment(
|
||||||
[cursor_pos, cursor_pos + vec2(0.0, line_spacing)],
|
[cursor_pos, cursor_pos + vec2(0.0, line_spacing)],
|
||||||
(ui.style().text_cursor_width, color::WHITE),
|
(ui.style().visuals.text_cursor_width, color::WHITE),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue