fix(iced): improve menu fonts, fix dropdown positioning, add theme switcher

This commit is contained in:
2026-07-16 13:02:43 +03:00
parent 98afa63752
commit baf77632dc
3 changed files with 33 additions and 9 deletions
@@ -744,6 +744,7 @@ pub enum Message {
WindowMaximize,
WindowClose,
WindowId(iced::window::Id),
ThemeChanged(crate::theme::ThemePreset),
// ── Dock Profiles ───────────────────────────────────
DockProfileSave(String),
@@ -4976,6 +4977,13 @@ impl HcieIcedApp {
(7, 8) => self.dock.reopen_pane(PaneType::Script),
(7, 9) => self.dock.reopen_pane(PaneType::LayerDetails),
(7, 10) => self.dock.reopen_pane(PaneType::AiScript),
// (7, 11) = separator
(7, 12) => return Task::perform(async {}, |_| Message::ThemeChanged(crate::theme::ThemePreset::Photopea)),
(7, 13) => return Task::perform(async {}, |_| Message::ThemeChanged(crate::theme::ThemePreset::Photoshop)),
(7, 14) => return Task::perform(async {}, |_| Message::ThemeChanged(crate::theme::ThemePreset::ProDark)),
(7, 15) => return Task::perform(async {}, |_| Message::ThemeChanged(crate::theme::ThemePreset::Amoled)),
(7, 16) => return Task::perform(async {}, |_| Message::ThemeChanged(crate::theme::ThemePreset::PhotoshopLight)),
(7, 17) => return Task::perform(async {}, |_| Message::ThemeChanged(crate::theme::ThemePreset::ProLight)),
// ══════════════════════════════════════════
// More menu (8) — Photopea-style
@@ -5037,6 +5045,9 @@ impl HcieIcedApp {
Message::WindowId(id) => {
self.window_id = Some(id);
}
Message::ThemeChanged(preset) => {
self.theme_state.set_preset(preset);
}
// ── Image Viewer ─────────────────────────────────
Message::ViewerToggle => {
@@ -285,6 +285,13 @@ fn all_menus(recent_files: &[crate::app::RecentFileEntry]) -> Vec<MenuDef> {
MenuItem::new("Script"),
MenuItem::new("Layer Details"),
MenuItem::new("AI Script Generator"),
MenuItem::separator(),
MenuItem::new("Theme: Photopea"),
MenuItem::new("Theme: Photoshop"),
MenuItem::new("Theme: ProDark (Monokai)"),
MenuItem::new("Theme: Amoled (Dracula)"),
MenuItem::new("Theme: PhotoshopLight (Solarized)"),
MenuItem::new("Theme: ProLight (Nord)"),
],
},
// ── More menu (Photopea-style) ──
@@ -346,7 +353,7 @@ pub fn dropdown_overlay(
} else if item.label == "Open Recent" {
let lbl = item.label.clone();
let disabled_item = container(
text(lbl).size(11)
text(lbl).size(13)
)
.width(Length::Fill)
.padding([4, 16])
@@ -360,7 +367,7 @@ pub fn dropdown_overlay(
let lbl = item.label.clone();
let c = colors;
let btn = iced::widget::button(
container(text(lbl).size(11)).width(Length::Fill).padding([4, 16])
container(text(lbl).size(13)).width(Length::Fill).padding([4, 16])
)
.on_press(Message::OpenRecentFile(file_idx))
.padding(0)
@@ -385,7 +392,7 @@ pub fn dropdown_overlay(
let lbl = item.label.clone();
let c = colors;
let btn = iced::widget::button(
container(text(lbl).size(11)).width(Length::Fill).padding([4, 16])
container(text(lbl).size(13)).width(Length::Fill).padding([4, 16])
)
.on_press(Message::ClearRecentFiles)
.padding(0)
@@ -414,12 +421,12 @@ pub fn dropdown_overlay(
// Photopea-style: label left, shortcut right in gray, submenu arrow ">" if needed
let label_row: Element<'static, Message> = {
let mut row_items = vec![];
row_items.push(text(lbl).size(11).width(Length::Fill).into());
row_items.push(text(lbl).size(13).width(Length::Fill).into());
if !sht.is_empty() {
row_items.push(text(sht).size(10).color(iced::Color::from_rgba(0.4, 0.4, 0.4, 1.0)).into());
row_items.push(text(sht).size(12).color(iced::Color::from_rgba(0.4, 0.4, 0.4, 1.0)).into());
}
if has_sub {
row_items.push(text(">").size(10).color(iced::Color::from_rgba(0.4, 0.4, 0.4, 1.0)).into());
row_items.push(text(">").size(12).color(iced::Color::from_rgba(0.4, 0.4, 0.4, 1.0)).into());
}
row(row_items).spacing(16).into()
};
@@ -488,8 +495,14 @@ pub fn dropdown_overlay(
});
// Position dropdown below the clicked menu item.
// Each menu item is approximately 60px wide (text + padding).
let left_offset = (menu_idx as f32) * 60.0 + 4.0;
// Compute the x-offset by summing the approximate widths of preceding menu
// bar items. Each button = label_chars * 7px (at 13px font) + 16px padding,
// plus the 4px initial left padding from the title bar.
const MENU_LABELS: &[&str] = &["File", "Edit", "Image", "Layer", "Select", "Filter", "View", "Window", "More"];
let mut left_offset: f32 = 4.0;
for i in 0..menu_idx.min(MENU_LABELS.len()) {
left_offset += MENU_LABELS[i].len() as f32 * 7.0 + 16.0;
}
let overlay = mouse_area(
container(dropdown)
.padding(iced::Padding {
@@ -36,7 +36,7 @@ pub fn view<'a>(
for (idx, &label) in MENU_LABELS.iter().enumerate() {
let is_open = active_menu == Some(idx);
let c = colors;
let btn = button(text(label).size(12))
let btn = button(text(label).size(13).font(iced::Font { weight: iced::font::Weight::Semibold, ..iced::Font::default() }))
.on_press(Message::MenuOpen(idx))
.padding([3, 8])
.style(move |_theme: &iced::Theme, status: iced::widget::button::Status| {