refactor: replace standard sliders with PlainSlider for better UI consistency
This commit is contained in:
@@ -2,8 +2,9 @@
|
||||
|
||||
use crate::app::Message;
|
||||
use crate::theme::ThemeColors;
|
||||
use iced::widget::{button, column, horizontal_rule, row, slider, text};
|
||||
use iced::{Element, Length};
|
||||
use crate::widgets::plain_slider::plain_slider;
|
||||
use iced::widget::{column, horizontal_rule, row, text};
|
||||
use iced::Element;
|
||||
|
||||
/// Build the Brightness/Contrast adjustment dialog.
|
||||
pub fn brightness_contrast_view(
|
||||
@@ -11,30 +12,35 @@ pub fn brightness_contrast_view(
|
||||
contrast: f32,
|
||||
colors: ThemeColors,
|
||||
) -> Element<'static, Message> {
|
||||
let brightness_slider = slider(-100.0..=100.0, brightness, |v| Message::AdjBrightness(v))
|
||||
.step(1.0)
|
||||
.width(Length::Fill);
|
||||
let brightness_slider = plain_slider(
|
||||
"Brightness",
|
||||
brightness,
|
||||
-100.0..=100.0,
|
||||
1.0,
|
||||
"",
|
||||
0,
|
||||
|v| Message::AdjBrightness(v),
|
||||
);
|
||||
|
||||
let contrast_slider = slider(-100.0..=100.0, contrast, |v| Message::AdjContrast(v))
|
||||
.step(1.0)
|
||||
.width(Length::Fill);
|
||||
let contrast_slider = plain_slider(
|
||||
"Contrast",
|
||||
contrast,
|
||||
-100.0..=100.0,
|
||||
1.0,
|
||||
"",
|
||||
0,
|
||||
|v| Message::AdjContrast(v),
|
||||
);
|
||||
|
||||
let apply_btn = button(text("Apply").size(11))
|
||||
.on_press(Message::AdjApply)
|
||||
.padding([6, 12]);
|
||||
|
||||
let cancel_btn = button(text("Cancel").size(11))
|
||||
.on_press(Message::DialogClose)
|
||||
.padding([6, 12]);
|
||||
let apply_btn = super::primary_btn("Apply", Message::AdjApply, colors);
|
||||
let cancel_btn = super::secondary_btn("Cancel", Message::DialogClose, colors);
|
||||
|
||||
let dialog = column![
|
||||
text("Brightness / Contrast")
|
||||
.size(14)
|
||||
.font(iced::Font::MONOSPACE),
|
||||
horizontal_rule(1),
|
||||
text(format!("Brightness: {:.0}", brightness)).size(11),
|
||||
brightness_slider,
|
||||
text(format!("Contrast: {:.0}", contrast)).size(11),
|
||||
contrast_slider,
|
||||
horizontal_rule(1),
|
||||
row![apply_btn, cancel_btn].spacing(12),
|
||||
@@ -53,36 +59,28 @@ pub fn hsl_view(
|
||||
lightness: f32,
|
||||
colors: ThemeColors,
|
||||
) -> Element<'static, Message> {
|
||||
let hue_slider = slider(-180.0..=180.0, hue, |v| Message::AdjHue(v))
|
||||
.step(1.0)
|
||||
.width(Length::Fill);
|
||||
let hue_slider = plain_slider("Hue", hue, -180.0..=180.0, 1.0, "°", 0, |v| {
|
||||
Message::AdjHue(v)
|
||||
});
|
||||
|
||||
let sat_slider = slider(-100.0..=100.0, saturation, |v| Message::AdjSaturation(v))
|
||||
.step(1.0)
|
||||
.width(Length::Fill);
|
||||
let sat_slider = plain_slider("Saturation", saturation, -100.0..=100.0, 1.0, "", 0, |v| {
|
||||
Message::AdjSaturation(v)
|
||||
});
|
||||
|
||||
let light_slider = slider(-100.0..=100.0, lightness, |v| Message::AdjLightness(v))
|
||||
.step(1.0)
|
||||
.width(Length::Fill);
|
||||
let light_slider = plain_slider("Lightness", lightness, -100.0..=100.0, 1.0, "", 0, |v| {
|
||||
Message::AdjLightness(v)
|
||||
});
|
||||
|
||||
let apply_btn = button(text("Apply").size(11))
|
||||
.on_press(Message::AdjApply)
|
||||
.padding([6, 12]);
|
||||
|
||||
let cancel_btn = button(text("Cancel").size(11))
|
||||
.on_press(Message::DialogClose)
|
||||
.padding([6, 12]);
|
||||
let apply_btn = super::primary_btn("Apply", Message::AdjApply, colors);
|
||||
let cancel_btn = super::secondary_btn("Cancel", Message::DialogClose, colors);
|
||||
|
||||
let dialog = column![
|
||||
text("Hue / Saturation / Lightness")
|
||||
.size(14)
|
||||
.font(iced::Font::MONOSPACE),
|
||||
horizontal_rule(1),
|
||||
text(format!("Hue: {:.0}°", hue)).size(11),
|
||||
hue_slider,
|
||||
text(format!("Saturation: {:.0}", saturation)).size(11),
|
||||
sat_slider,
|
||||
text(format!("Lightness: {:.0}", lightness)).size(11),
|
||||
light_slider,
|
||||
horizontal_rule(1),
|
||||
row![apply_btn, cancel_btn].spacing(12),
|
||||
|
||||
@@ -2,24 +2,17 @@
|
||||
|
||||
use crate::app::Message;
|
||||
use crate::theme::ThemeColors;
|
||||
use iced::widget::{button, column, horizontal_rule, row, slider, text};
|
||||
use iced::{Element, Length};
|
||||
use crate::widgets::plain_slider::plain_slider;
|
||||
use iced::widget::{column, horizontal_rule, row, text};
|
||||
use iced::Element;
|
||||
|
||||
/// Build a confirmation dialog with save/discard/cancel.
|
||||
pub fn close_confirm_view(doc_name: &str, colors: ThemeColors) -> Element<'static, Message> {
|
||||
let msg = format!("\"{}\" has unsaved changes.", doc_name);
|
||||
|
||||
let save_btn = button(text("Save").size(12))
|
||||
.on_press(Message::DialogCloseSave)
|
||||
.padding([8, 16]);
|
||||
|
||||
let discard_btn = button(text("Discard").size(12))
|
||||
.on_press(Message::DialogCloseDiscard)
|
||||
.padding([8, 16]);
|
||||
|
||||
let cancel_btn = button(text("Cancel").size(12))
|
||||
.on_press(Message::DialogClose)
|
||||
.padding([8, 16]);
|
||||
let save_btn = super::primary_btn("Save", Message::DialogCloseSave, colors);
|
||||
let discard_btn = super::secondary_btn("Discard", Message::DialogCloseDiscard, colors);
|
||||
let cancel_btn = super::secondary_btn("Cancel", Message::DialogClose, colors);
|
||||
|
||||
let dialog = column![
|
||||
text("Unsaved Changes").size(16).font(iced::Font::MONOSPACE),
|
||||
@@ -44,22 +37,16 @@ pub fn selection_op_view(
|
||||
colors: ThemeColors,
|
||||
) -> Element<'static, Message> {
|
||||
let op_owned = op_name.to_string();
|
||||
let value_slider = slider(min..=max, value, |v| Message::SelectionOpValue(v))
|
||||
.step(1.0)
|
||||
.width(Length::Fill);
|
||||
let value_slider = plain_slider("Value", value, min..=max, 1.0, "", 0, |v| {
|
||||
Message::SelectionOpValue(v)
|
||||
});
|
||||
|
||||
let apply_btn = button(text("Apply").size(11))
|
||||
.on_press(Message::SelectionOpApply)
|
||||
.padding([6, 12]);
|
||||
|
||||
let cancel_btn = button(text("Cancel").size(11))
|
||||
.on_press(Message::DialogClose)
|
||||
.padding([6, 12]);
|
||||
let apply_btn = super::primary_btn("Apply", Message::SelectionOpApply, colors);
|
||||
let cancel_btn = super::secondary_btn("Cancel", Message::DialogClose, colors);
|
||||
|
||||
let dialog = column![
|
||||
text(op_owned).size(14).font(iced::Font::MONOSPACE),
|
||||
horizontal_rule(1),
|
||||
text(format!("Value: {:.0}", value)).size(11),
|
||||
value_slider,
|
||||
horizontal_rule(1),
|
||||
row![apply_btn, cancel_btn].spacing(12),
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
use crate::app::Message;
|
||||
use crate::theme::ThemeColors;
|
||||
use iced::widget::container;
|
||||
use iced::{Element, Length};
|
||||
use iced::widget::{button, container, text};
|
||||
use iced::{Border, Element, Length};
|
||||
|
||||
pub mod about;
|
||||
pub mod adjustments;
|
||||
@@ -55,3 +55,85 @@ pub fn modal<'a>(
|
||||
.height(Length::Fill)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Blend a color with white by a factor (0.0 = no blend, 1.0 = full white).
|
||||
fn lighten(c: iced::Color, factor: f32) -> iced::Color {
|
||||
iced::Color::new(
|
||||
c.r + (1.0 - c.r) * factor,
|
||||
c.g + (1.0 - c.g) * factor,
|
||||
c.b + (1.0 - c.b) * factor,
|
||||
c.a,
|
||||
)
|
||||
}
|
||||
|
||||
/// Blend a color with black by a factor (0.0 = no blend, 1.0 = full black).
|
||||
fn darken(c: iced::Color, factor: f32) -> iced::Color {
|
||||
iced::Color::new(
|
||||
c.r * (1.0 - factor),
|
||||
c.g * (1.0 - factor),
|
||||
c.b * (1.0 - factor),
|
||||
c.a,
|
||||
)
|
||||
}
|
||||
|
||||
/// Modern theme-compatible primary button (accent fill).
|
||||
pub fn primary_btn(
|
||||
label: &str,
|
||||
msg: Message,
|
||||
colors: ThemeColors,
|
||||
) -> Element<'static, Message> {
|
||||
let l = label.to_string();
|
||||
let c = colors;
|
||||
button(text(l).size(12).style(move |_theme: &iced::Theme| iced::widget::text::Style {
|
||||
color: Some(iced::Color::WHITE),
|
||||
}))
|
||||
.on_press(msg)
|
||||
.padding([8, 16])
|
||||
.style(move |_theme, status| {
|
||||
let bg = match status {
|
||||
iced::widget::button::Status::Hovered => lighten(c.accent, 0.15),
|
||||
iced::widget::button::Status::Pressed => darken(c.accent, 0.15),
|
||||
_ => c.accent,
|
||||
};
|
||||
iced::widget::button::Style {
|
||||
background: Some(iced::Background::Color(bg)),
|
||||
text_color: iced::Color::WHITE,
|
||||
border: Border::default().rounded(6),
|
||||
..Default::default()
|
||||
}
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Modern theme-compatible secondary button (bordered ghost).
|
||||
pub fn secondary_btn(
|
||||
label: &str,
|
||||
msg: Message,
|
||||
colors: ThemeColors,
|
||||
) -> Element<'static, Message> {
|
||||
let l = label.to_string();
|
||||
let c = colors;
|
||||
button(text(l).size(12).style(move |_theme: &iced::Theme| iced::widget::text::Style {
|
||||
color: Some(c.text_primary),
|
||||
}))
|
||||
.on_press(msg)
|
||||
.padding([8, 16])
|
||||
.style(move |_theme, status| {
|
||||
let bg = match status {
|
||||
iced::widget::button::Status::Hovered => {
|
||||
let mut h = c.bg_hover;
|
||||
h.a *= 0.5;
|
||||
h
|
||||
}
|
||||
iced::widget::button::Status::Pressed => c.bg_hover,
|
||||
_ => iced::Color::TRANSPARENT,
|
||||
};
|
||||
iced::widget::button::Style {
|
||||
background: Some(iced::Background::Color(bg)),
|
||||
text_color: c.text_primary,
|
||||
border: Border::default().rounded(6).color(c.border_high).width(1),
|
||||
..Default::default()
|
||||
}
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
|
||||
use crate::app::Message;
|
||||
use crate::theme::ThemeColors;
|
||||
use crate::widgets::plain_slider::plain_slider;
|
||||
use iced::widget::{
|
||||
button, checkbox, column, horizontal_rule, row, scrollable, slider, text, text_input,
|
||||
button, checkbox, column, horizontal_rule, row, scrollable, text, text_input,
|
||||
};
|
||||
use iced::{Element, Length};
|
||||
|
||||
@@ -70,16 +71,25 @@ pub fn view(
|
||||
.on_input(|s| Message::DialogNewImageName(s))
|
||||
.width(Length::Fill);
|
||||
|
||||
let width_text = text(format!("Width: {}", width)).size(11);
|
||||
let height_text = text(format!("Height: {}", height)).size(11);
|
||||
let width_slider = plain_slider(
|
||||
"Width",
|
||||
width as f32,
|
||||
1.0..=4096.0,
|
||||
1.0,
|
||||
"px",
|
||||
0,
|
||||
|v| Message::DialogNewImageWidth(v as u32),
|
||||
);
|
||||
|
||||
let width_slider = slider(1_u32..=4096, width, |v| Message::DialogNewImageWidth(v))
|
||||
.step(1_u32)
|
||||
.width(Length::Fill);
|
||||
|
||||
let height_slider = slider(1_u32..=4096, height, |v| Message::DialogNewImageHeight(v))
|
||||
.step(1_u32)
|
||||
.width(Length::Fill);
|
||||
let height_slider = plain_slider(
|
||||
"Height",
|
||||
height as f32,
|
||||
1.0..=4096.0,
|
||||
1.0,
|
||||
"px",
|
||||
0,
|
||||
|v| Message::DialogNewImageHeight(v as u32),
|
||||
);
|
||||
|
||||
let transparent_check = checkbox("Transparent background", transparent)
|
||||
.on_toggle(|v| Message::DialogNewImageTransparent(v));
|
||||
@@ -96,22 +106,15 @@ pub fn view(
|
||||
presets_col = presets_col.push(preset_btn);
|
||||
}
|
||||
|
||||
let create_btn = button(text("Create").size(12))
|
||||
.on_press(Message::DialogNewImageCreate)
|
||||
.padding([8, 16]);
|
||||
|
||||
let cancel_btn = button(text("Cancel").size(12))
|
||||
.on_press(Message::DialogClose)
|
||||
.padding([8, 16]);
|
||||
let create_btn = super::primary_btn("Create", Message::DialogNewImageCreate, colors);
|
||||
let cancel_btn = super::secondary_btn("Cancel", Message::DialogClose, colors);
|
||||
|
||||
let dialog = column![
|
||||
text("New Image").size(16).font(iced::Font::MONOSPACE),
|
||||
horizontal_rule(1),
|
||||
text("Name:").size(11),
|
||||
name_input,
|
||||
width_text,
|
||||
width_slider,
|
||||
height_text,
|
||||
height_slider,
|
||||
transparent_check,
|
||||
horizontal_rule(1),
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
|
||||
use crate::app::Message;
|
||||
use crate::theme::ThemeColors;
|
||||
use crate::widgets::plain_slider::plain_slider;
|
||||
use hcie_engine_api::FilterType;
|
||||
use iced::widget::{column, container, row, slider, text};
|
||||
use iced::widget::{column, container, row, text};
|
||||
use iced::{Element, Length};
|
||||
use serde_json::json;
|
||||
|
||||
@@ -35,11 +36,11 @@ fn param_str<'a>(params: &'a serde_json::Value, key: &str, default: &'a str) ->
|
||||
params.get(key).and_then(|v| v.as_str()).unwrap_or(default)
|
||||
}
|
||||
|
||||
/// Build a labeled float slider row.
|
||||
/// Build a labeled float slider row with keyboard editing.
|
||||
///
|
||||
/// Returns a row with label, slider, and numeric display. The slider
|
||||
/// Returns a column with label and keyboard-editable slider. The slider
|
||||
/// emits `Message::FilterParamChanged(filter_id, json!({key: new_value}))`
|
||||
/// when the user drags it.
|
||||
/// when the user drags or types a value.
|
||||
fn float_slider(
|
||||
label: &str,
|
||||
key: &str,
|
||||
@@ -50,30 +51,28 @@ fn float_slider(
|
||||
step: f64,
|
||||
_colors: ThemeColors,
|
||||
) -> Element<'static, Message> {
|
||||
let val = value as f32;
|
||||
let min_f = min as f32;
|
||||
let max_f = max as f32;
|
||||
let step_f = step as f32;
|
||||
let key_owned = key.to_string();
|
||||
let filter_owned = filter_id.to_string();
|
||||
let label_owned = label.to_string();
|
||||
let step_f = step as f32;
|
||||
|
||||
let lbl = text(label_owned).size(11).width(Length::Fixed(80.0));
|
||||
let display = text(format!("{:.1}", value))
|
||||
.size(11)
|
||||
.width(Length::Fixed(40.0));
|
||||
|
||||
let s = slider(min_f..=max_f, val, move |v| {
|
||||
let rounded = (v as f64 / step).round() * step;
|
||||
Message::FilterParamChanged(filter_owned.clone(), json!({ key_owned.clone(): rounded }))
|
||||
})
|
||||
.step(step_f)
|
||||
.width(Length::Fill);
|
||||
|
||||
row![lbl, s, display].spacing(4).into()
|
||||
plain_slider(
|
||||
label,
|
||||
value as f32,
|
||||
(min as f32)..=(max as f32),
|
||||
step_f,
|
||||
"",
|
||||
1,
|
||||
move |v| {
|
||||
let rounded = (v as f64 / step).round() * step;
|
||||
Message::FilterParamChanged(
|
||||
filter_owned.clone(),
|
||||
json!({ key_owned.clone(): rounded }),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Build a labeled integer slider row.
|
||||
/// Build a labeled integer slider row with keyboard editing.
|
||||
fn int_slider(
|
||||
label: &str,
|
||||
key: &str,
|
||||
@@ -83,28 +82,23 @@ fn int_slider(
|
||||
max: u64,
|
||||
_colors: ThemeColors,
|
||||
) -> Element<'static, Message> {
|
||||
let val = value as f32;
|
||||
let min_f = min as f32;
|
||||
let max_f = max as f32;
|
||||
let key_owned = key.to_string();
|
||||
let filter_owned = filter_id.to_string();
|
||||
let label_owned = label.to_string();
|
||||
|
||||
let lbl = text(label_owned).size(11).width(Length::Fixed(80.0));
|
||||
let display = text(format!("{}", value))
|
||||
.size(11)
|
||||
.width(Length::Fixed(40.0));
|
||||
|
||||
let s = slider(min_f..=max_f, val, move |v| {
|
||||
Message::FilterParamChanged(
|
||||
filter_owned.clone(),
|
||||
json!({ key_owned.clone(): v.round() as u64 }),
|
||||
)
|
||||
})
|
||||
.step(1.0)
|
||||
.width(Length::Fill);
|
||||
|
||||
row![lbl, s, display].spacing(4).into()
|
||||
plain_slider(
|
||||
label,
|
||||
value as f32,
|
||||
(min as f32)..=(max as f32),
|
||||
1.0,
|
||||
"",
|
||||
0,
|
||||
move |v| {
|
||||
Message::FilterParamChanged(
|
||||
filter_owned.clone(),
|
||||
json!({ key_owned.clone(): v.round() as u64 }),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Build a section header for a group of parameters.
|
||||
|
||||
@@ -12,9 +12,10 @@ use crate::panels::styles;
|
||||
use crate::panels::thumbnails;
|
||||
use crate::panels::typography::BODY;
|
||||
use crate::theme::ThemeColors;
|
||||
use crate::widgets::plain_slider::plain_slider;
|
||||
use hcie_engine_api::{BlendMode, LayerInfo, LayerType};
|
||||
use iced::widget::{
|
||||
button, column, container, horizontal_rule, pick_list, row, scrollable, slider, text, Space,
|
||||
button, column, container, horizontal_rule, pick_list, row, scrollable, text, Space,
|
||||
};
|
||||
use iced::{Element, Length};
|
||||
|
||||
@@ -129,10 +130,10 @@ fn layer_thumbnail<'a>(
|
||||
colors: ThemeColors,
|
||||
) -> Element<'a, Message> {
|
||||
if entry.is_group {
|
||||
return container(text("\u{1F4C1}").size(13))
|
||||
.width(28)
|
||||
.height(20)
|
||||
.center_y(Length::Fixed(20.0))
|
||||
return container(text("\u{1F4C1}").size(16))
|
||||
.width(50)
|
||||
.height(38)
|
||||
.center_y(Length::Fixed(38.0))
|
||||
.into();
|
||||
}
|
||||
|
||||
@@ -140,15 +141,15 @@ fn layer_thumbnail<'a>(
|
||||
let thumb = engine
|
||||
.get_layer_pixels(info.id)
|
||||
.filter(|px| !px.is_empty() && info.width > 0 && info.height > 0)
|
||||
.map(|px| thumbnails::generate_thumbnail(&px, info.width, info.height, 28));
|
||||
.map(|px| thumbnails::generate_thumbnail(&px, info.width, info.height, 48));
|
||||
|
||||
if let Some(pixels) = thumb {
|
||||
let handle = iced::widget::image::Handle::from_rgba(28, 20, pixels);
|
||||
let img = iced::widget::Image::new(handle).width(28).height(20);
|
||||
let handle = iced::widget::image::Handle::from_rgba(48, 36, pixels);
|
||||
let img = iced::widget::Image::new(handle).width(48).height(36);
|
||||
return container(img)
|
||||
.width(30)
|
||||
.height(22)
|
||||
.center_y(Length::Fixed(22.0))
|
||||
.width(50)
|
||||
.height(38)
|
||||
.center_y(Length::Fixed(38.0))
|
||||
.padding(1)
|
||||
.style(move |_theme| iced::widget::container::Style {
|
||||
border: iced::Border::default().color(colors.border_high).width(1),
|
||||
@@ -165,15 +166,15 @@ fn layer_thumbnail<'a>(
|
||||
_ => ("\u{25A3}", colors.text_secondary),
|
||||
};
|
||||
|
||||
container(text(icon_char).size(10).style(move |_theme: &iced::Theme| {
|
||||
container(text(icon_char).size(12).style(move |_theme: &iced::Theme| {
|
||||
iced::widget::text::Style {
|
||||
color: Some(icon_color),
|
||||
}
|
||||
}))
|
||||
.width(30)
|
||||
.height(22)
|
||||
.center_x(Length::Fixed(30.0))
|
||||
.center_y(Length::Fixed(22.0))
|
||||
.width(50)
|
||||
.height(38)
|
||||
.center_x(Length::Fixed(50.0))
|
||||
.center_y(Length::Fixed(38.0))
|
||||
.style(move |_theme| iced::widget::container::Style {
|
||||
background: Some(iced::Background::Color(iced::Color::from_rgba(
|
||||
1.0, 1.0, 1.0, 0.05,
|
||||
@@ -222,18 +223,17 @@ pub fn view<'a>(
|
||||
.width(Length::Fill)
|
||||
.text_size(BODY);
|
||||
|
||||
let opacity_label = text(format!("{}%", (active_opacity * 100.0) as u32))
|
||||
.size(BODY)
|
||||
.width(Length::Fixed(32.0));
|
||||
let opacity_slider = slider(0.0..=1.0, active_opacity, move |v| {
|
||||
Message::LayerSetOpacity(active_layer_id, v)
|
||||
})
|
||||
.step(0.01)
|
||||
.width(Length::Fill);
|
||||
let opacity_slider = plain_slider(
|
||||
"Opacity",
|
||||
active_opacity,
|
||||
0.0..=1.0,
|
||||
0.01,
|
||||
"%",
|
||||
0,
|
||||
move |v| Message::LayerSetOpacity(active_layer_id, v),
|
||||
);
|
||||
|
||||
let opacity_row = row![text("Op").size(BODY), opacity_slider, opacity_label]
|
||||
.spacing(3)
|
||||
.align_y(iced::Alignment::Center);
|
||||
let opacity_row = opacity_slider;
|
||||
|
||||
let lock_icon = if active_locked {
|
||||
"\u{1F512}"
|
||||
@@ -293,14 +293,14 @@ pub fn view<'a>(
|
||||
Space::with_width(Length::Fixed(12.0)).into()
|
||||
};
|
||||
|
||||
// Visibility toggle
|
||||
let vis_char = if info.visible { "\u{25CF}" } else { "\u{25CB}" };
|
||||
// Visibility toggle (eye icon)
|
||||
let vis_char = if info.visible { "\u{1F441}" } else { "\u{1F441}" };
|
||||
let vis_color = if info.visible {
|
||||
colors.text_primary
|
||||
} else {
|
||||
colors.text_secondary
|
||||
iced::Color { a: colors.text_secondary.a * 0.4, ..colors.text_secondary }
|
||||
};
|
||||
let vis_btn = button(text(vis_char).size(10).style(move |_theme: &iced::Theme| {
|
||||
let vis_btn = button(text(vis_char).size(11).style(move |_theme: &iced::Theme| {
|
||||
iced::widget::text::Style {
|
||||
color: Some(vis_color),
|
||||
}
|
||||
|
||||
@@ -15,9 +15,10 @@ use crate::app::{Message, ToolState};
|
||||
use crate::panels::styles;
|
||||
use crate::settings::AppSettings;
|
||||
use crate::theme::ThemeColors;
|
||||
use crate::widgets::plain_slider::plain_slider;
|
||||
use hcie_engine_api::Tool;
|
||||
use iced::widget::{
|
||||
button, column, container, horizontal_rule, row, scrollable, slider, text, text_input,
|
||||
button, column, container, horizontal_rule, row, scrollable, text, text_input,
|
||||
};
|
||||
use iced::{Element, Length};
|
||||
|
||||
@@ -462,19 +463,7 @@ fn prop_slider<F>(
|
||||
where
|
||||
F: Fn(f32) -> Message + 'static,
|
||||
{
|
||||
let l = label.to_string();
|
||||
let label_text = text(l).size(10).width(Length::Fixed(70.0));
|
||||
let val_text = text(format!("{:.1}", value))
|
||||
.size(10)
|
||||
.width(Length::Fixed(40.0));
|
||||
let sl = slider(min..=max, value, msg_fn)
|
||||
.step(0.1)
|
||||
.width(Length::Fill);
|
||||
|
||||
row![label_text, sl, val_text]
|
||||
.spacing(4)
|
||||
.align_y(iced::Alignment::Center)
|
||||
.into()
|
||||
plain_slider(label, value, min..=max, 0.1, "", 1, msg_fn)
|
||||
}
|
||||
|
||||
fn color_row(label: &str, color: [u8; 4], _c: ThemeColors) -> Element<'static, Message> {
|
||||
|
||||
Reference in New Issue
Block a user