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>,
|
pub bool_shape_a: Option<usize>,
|
||||||
/// Boolean operation shape B selector index (geometry panel).
|
/// Boolean operation shape B selector index (geometry panel).
|
||||||
pub bool_shape_b: Option<usize>,
|
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.
|
/// A recently opened file entry.
|
||||||
@@ -779,6 +781,9 @@ pub enum Message {
|
|||||||
ViewerPrev,
|
ViewerPrev,
|
||||||
ViewerNext,
|
ViewerNext,
|
||||||
ViewerEnter,
|
ViewerEnter,
|
||||||
|
|
||||||
|
// ── Toolbox expand/collapse ─────────────────────────
|
||||||
|
SidebarToggleExpanded,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a FilterType enum to the engine's string filter ID.
|
/// Convert a FilterType enum to the engine's string filter ID.
|
||||||
@@ -1113,6 +1118,7 @@ impl HcieIcedApp {
|
|||||||
vector_drag_last: None,
|
vector_drag_last: None,
|
||||||
bool_shape_a: None,
|
bool_shape_a: None,
|
||||||
bool_shape_b: None,
|
bool_shape_b: None,
|
||||||
|
sidebar_expanded: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Apply saved settings to tool state
|
// Apply saved settings to tool state
|
||||||
@@ -5147,6 +5153,10 @@ impl HcieIcedApp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Message::SidebarToggleExpanded => {
|
||||||
|
self.sidebar_expanded = !self.sidebar_expanded;
|
||||||
|
}
|
||||||
|
|
||||||
Message::NoOp => {}
|
Message::NoOp => {}
|
||||||
|
|
||||||
Message::TabletTouch { x, y, pressed } => {
|
Message::TabletTouch { x, y, pressed } => {
|
||||||
@@ -5257,7 +5267,7 @@ impl HcieIcedApp {
|
|||||||
self.active_menu,
|
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(
|
let toolbox = crate::sidebar::view(
|
||||||
&self.tool_state,
|
&self.tool_state,
|
||||||
&self.fg_color,
|
&self.fg_color,
|
||||||
@@ -5266,6 +5276,7 @@ impl HcieIcedApp {
|
|||||||
self.active_tool_slot,
|
self.active_tool_slot,
|
||||||
self.sub_tools_open,
|
self.sub_tools_open,
|
||||||
&self.slot_last_used,
|
&self.slot_last_used,
|
||||||
|
self.sidebar_expanded,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Merged toolbar: icon buttons + tool options in one row
|
// 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>(
|
pub fn view<'a>(
|
||||||
tool_state: &'a ToolState,
|
tool_state: &'a ToolState,
|
||||||
fg_color: &'a [u8; 4],
|
fg_color: &'a [u8; 4],
|
||||||
@@ -72,13 +75,31 @@ pub fn view<'a>(
|
|||||||
active_slot: usize,
|
active_slot: usize,
|
||||||
sub_tools_open: bool,
|
sub_tools_open: bool,
|
||||||
slot_last_used: &'a [usize],
|
slot_last_used: &'a [usize],
|
||||||
|
expanded: bool,
|
||||||
) -> Element<'a, Message> {
|
) -> 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);
|
let mut tool_list = column![].spacing(1);
|
||||||
|
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() {
|
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);
|
let btn = tool_button(slot, tool_state, colors, idx, active_slot, sub_tools_open, slot_last_used);
|
||||||
tool_list = tool_list.push(btn);
|
tool_list = tool_list.push(btn);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Color swatches at bottom (Photopea-style: diagonal overlapping)
|
// Color swatches at bottom (Photopea-style: diagonal overlapping)
|
||||||
// Foreground (top-left), Background (bottom-right), overlapping diagonally
|
// Foreground (top-left), Background (bottom-right), overlapping diagonally
|
||||||
@@ -173,7 +194,7 @@ pub fn view<'a>(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
.padding([4, 2])
|
.padding([4, 2])
|
||||||
.width(36)
|
.width(sidebar_width)
|
||||||
.height(32);
|
.height(32);
|
||||||
|
|
||||||
// Separator line
|
// Separator line
|
||||||
@@ -182,13 +203,37 @@ pub fn view<'a>(
|
|||||||
..Default::default()
|
..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![
|
let sidebar = column![
|
||||||
container(tool_list).padding([2, 0]),
|
container(tool_list).padding([2, 0]),
|
||||||
container(text("").height(1)).width(Length::Fill).style(sep_style),
|
container(text("").height(1)).width(Length::Fill).style(sep_style),
|
||||||
color_section,
|
color_section,
|
||||||
container(reset_btn).padding([2, 4]),
|
container(reset_btn).padding([2, 4]),
|
||||||
|
container(toggle_btn).padding([2, 0]),
|
||||||
]
|
]
|
||||||
.width(36)
|
.width(sidebar_width)
|
||||||
.spacing(0);
|
.spacing(0);
|
||||||
|
|
||||||
container(sidebar)
|
container(sidebar)
|
||||||
|
|||||||
Reference in New Issue
Block a user