feat(iced): make toolbox expandable/collapsible to 2 columns
This commit is contained in:
@@ -264,6 +264,8 @@ pub struct HcieIcedApp {
|
||||
pub bool_shape_a: Option<usize>,
|
||||
/// Boolean operation shape B selector index (geometry panel).
|
||||
pub bool_shape_b: Option<usize>,
|
||||
/// Whether the toolbox is expanded to 2 columns (false = single column 36px, true = 2 columns 72px).
|
||||
pub sidebar_expanded: bool,
|
||||
}
|
||||
|
||||
/// A recently opened file entry.
|
||||
@@ -779,6 +781,9 @@ pub enum Message {
|
||||
ViewerPrev,
|
||||
ViewerNext,
|
||||
ViewerEnter,
|
||||
|
||||
// ── Toolbox expand/collapse ─────────────────────────
|
||||
SidebarToggleExpanded,
|
||||
}
|
||||
|
||||
/// Convert a FilterType enum to the engine's string filter ID.
|
||||
@@ -1113,6 +1118,7 @@ impl HcieIcedApp {
|
||||
vector_drag_last: None,
|
||||
bool_shape_a: None,
|
||||
bool_shape_b: None,
|
||||
sidebar_expanded: false,
|
||||
};
|
||||
|
||||
// Apply saved settings to tool state
|
||||
@@ -5147,6 +5153,10 @@ impl HcieIcedApp {
|
||||
}
|
||||
}
|
||||
|
||||
Message::SidebarToggleExpanded => {
|
||||
self.sidebar_expanded = !self.sidebar_expanded;
|
||||
}
|
||||
|
||||
Message::NoOp => {}
|
||||
|
||||
Message::TabletTouch { x, y, pressed } => {
|
||||
@@ -5257,7 +5267,7 @@ impl HcieIcedApp {
|
||||
self.active_menu,
|
||||
);
|
||||
|
||||
// Toolbox — fixed 36px strip on the left edge (outside dock)
|
||||
// Toolbox — 36px strip (single column) or 72px (2 columns) on the left edge
|
||||
let toolbox = crate::sidebar::view(
|
||||
&self.tool_state,
|
||||
&self.fg_color,
|
||||
@@ -5266,6 +5276,7 @@ impl HcieIcedApp {
|
||||
self.active_tool_slot,
|
||||
self.sub_tools_open,
|
||||
&self.slot_last_used,
|
||||
self.sidebar_expanded,
|
||||
);
|
||||
|
||||
// Merged toolbar: icon buttons + tool options in one row
|
||||
|
||||
@@ -63,7 +63,10 @@ pub const TOOL_SLOTS: &[ToolSlot] = &[
|
||||
},
|
||||
];
|
||||
|
||||
/// Build the Photopea-style fixed 36px sidebar element.
|
||||
/// Build the Photopea-style sidebar element.
|
||||
///
|
||||
/// When `expanded` is false, renders a single 36px column (default).
|
||||
/// When `expanded` is true, renders a 2-column grid (72px) showing more tools.
|
||||
pub fn view<'a>(
|
||||
tool_state: &'a ToolState,
|
||||
fg_color: &'a [u8; 4],
|
||||
@@ -72,12 +75,30 @@ pub fn view<'a>(
|
||||
active_slot: usize,
|
||||
sub_tools_open: bool,
|
||||
slot_last_used: &'a [usize],
|
||||
expanded: bool,
|
||||
) -> Element<'a, Message> {
|
||||
// Tool buttons — single column, with sub-tools popup support
|
||||
let sidebar_width = if expanded { 72 } else { 36 };
|
||||
|
||||
// Tool buttons — single column or 2-column grid depending on expanded state
|
||||
let mut tool_list = column![].spacing(1);
|
||||
for (idx, slot) in TOOL_SLOTS.iter().enumerate() {
|
||||
let btn = tool_button(slot, tool_state, colors, idx, active_slot, sub_tools_open, slot_last_used);
|
||||
tool_list = tool_list.push(btn);
|
||||
if expanded {
|
||||
// 2-column layout: show tools in pairs
|
||||
let mut row_children = iced::widget::Row::new().spacing(1);
|
||||
for (idx, slot) in TOOL_SLOTS.iter().enumerate() {
|
||||
let btn = tool_button(slot, tool_state, colors, idx, active_slot, sub_tools_open, slot_last_used);
|
||||
row_children = row_children.push(btn);
|
||||
// Every 2 tools, start a new row
|
||||
if idx % 2 == 1 || idx == TOOL_SLOTS.len() - 1 {
|
||||
tool_list = tool_list.push(row_children);
|
||||
row_children = iced::widget::Row::new().spacing(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Single column layout (default)
|
||||
for (idx, slot) in TOOL_SLOTS.iter().enumerate() {
|
||||
let btn = tool_button(slot, tool_state, colors, idx, active_slot, sub_tools_open, slot_last_used);
|
||||
tool_list = tool_list.push(btn);
|
||||
}
|
||||
}
|
||||
|
||||
// Color swatches at bottom (Photopea-style: diagonal overlapping)
|
||||
@@ -173,7 +194,7 @@ pub fn view<'a>(
|
||||
)
|
||||
)
|
||||
.padding([4, 2])
|
||||
.width(36)
|
||||
.width(sidebar_width)
|
||||
.height(32);
|
||||
|
||||
// Separator line
|
||||
@@ -182,13 +203,37 @@ pub fn view<'a>(
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// Toggle expand/collapse button (arrow icon)
|
||||
let toggle_label = if expanded { "◀" } else { "▶" };
|
||||
let toggle_btn = button(text(toggle_label).size(10).color(colors.text_secondary))
|
||||
.on_press(Message::SidebarToggleExpanded)
|
||||
.padding(2)
|
||||
.width(sidebar_width)
|
||||
.style(move |_theme: &iced::Theme, status: iced::widget::button::Status| {
|
||||
match status {
|
||||
iced::widget::button::Status::Hovered => iced::widget::button::Style {
|
||||
background: Some(iced::Background::Color(colors.bg_hover)),
|
||||
text_color: colors.text_primary,
|
||||
border: iced::Border::default(),
|
||||
..Default::default()
|
||||
},
|
||||
_ => iced::widget::button::Style {
|
||||
background: Some(iced::Background::Color(iced::Color::from_rgba(0.0, 0.0, 0.0, 0.0))),
|
||||
text_color: colors.text_secondary,
|
||||
border: iced::Border::default(),
|
||||
..Default::default()
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
let sidebar = column![
|
||||
container(tool_list).padding([2, 0]),
|
||||
container(text("").height(1)).width(Length::Fill).style(sep_style),
|
||||
color_section,
|
||||
container(reset_btn).padding([2, 4]),
|
||||
container(toggle_btn).padding([2, 0]),
|
||||
]
|
||||
.width(36)
|
||||
.width(sidebar_width)
|
||||
.spacing(0);
|
||||
|
||||
container(sidebar)
|
||||
|
||||
Reference in New Issue
Block a user