From 99306cbf1b1e17f55c6f610418c118917f3c9d08 Mon Sep 17 00:00:00 2001 From: Daniel Yoon <101683475+Koranir@users.noreply.github.com> Date: Wed, 16 Oct 2024 10:22:25 +1100 Subject: [PATCH] initial commit --- src/mounter/gvfs.rs | 1 + src/mouse_area.rs | 38 ++++++++++++++++- src/tab.rs | 100 ++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 129 insertions(+), 10 deletions(-) diff --git a/src/mounter/gvfs.rs b/src/mounter/gvfs.rs index 62a6004..c36191e 100644 --- a/src/mounter/gvfs.rs +++ b/src/mounter/gvfs.rs @@ -133,6 +133,7 @@ fn network_scan(uri: &str, sizes: IconSizes) -> Result, String> { pos_opt: Cell::new(None), rect_opt: Cell::new(None), selected: false, + highlighted: false, overlaps_drag_rect: false, }); } diff --git a/src/mouse_area.rs b/src/mouse_area.rs index 30054d1..1393bca 100644 --- a/src/mouse_area.rs +++ b/src/mouse_area.rs @@ -47,6 +47,8 @@ pub struct MouseArea<'a, Message> { on_forward_press: Option) -> Message + 'a>>, on_forward_release: Option) -> Message + 'a>>, on_scroll: Option Option + 'a>>, + on_enter: Option Message + 'a>>, + on_exit: Option Message + 'a>>, show_drag_rect: bool, } @@ -169,6 +171,20 @@ impl<'a, Message> MouseArea<'a, Message> { self } + /// The message to emit when a mouse enters the area. + #[must_use] + pub fn on_enter(mut self, message: impl Fn() -> Message + 'a) -> Self { + self.on_enter = Some(Box::new(message)); + self + } + + /// The message to emit when a mouse exits the area. + #[must_use] + pub fn on_exit(mut self, message: impl Fn() -> Message + 'a) -> Self { + self.on_exit = Some(Box::new(message)); + self + } + #[must_use] pub fn show_drag_rect(mut self, show_drag_rect: bool) -> Self { self.show_drag_rect = show_drag_rect; @@ -186,7 +202,7 @@ impl<'a, Message> MouseArea<'a, Message> { /// Local state of the [`MouseArea`]. #[derive(Default)] struct State { - // TODO: Support on_mouse_enter and on_mouse_exit + last_position: Option, drag_initiated: Option, modifiers: Modifiers, prev_click: Option<(mouse::Click, Instant)>, @@ -260,6 +276,8 @@ impl<'a, Message> MouseArea<'a, Message> { on_back_release: None, on_forward_press: None, on_forward_release: None, + on_enter: None, + on_exit: None, on_scroll: None, show_drag_rect: false, } @@ -474,6 +492,24 @@ fn update( } } + if let Event::Mouse(mouse::Event::CursorMoved { position }) = event { + let position_in = cursor.position_in(layout_bounds); + match (position_in, state.last_position) { + (None, Some(last)) => { + if let Some(message) = widget.on_exit.as_ref() { + shell.publish(message()) + } + } + (Some(new), None) => { + if let Some(message) = widget.on_enter.as_ref() { + shell.publish(message()) + } + } + _ => {} + } + state.last_position = position_in; + } + if state.drag_initiated.is_none() && !cursor.is_over(layout_bounds) { return event::Status::Ignored; } diff --git a/src/tab.rs b/src/tab.rs index b59e483..3bae75c 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -118,6 +118,7 @@ static SPECIAL_DIRS: Lazy> = Lazy::new(|| { fn button_appearance( theme: &theme::Theme, selected: bool, + highlighted: bool, focused: bool, accent: bool, condensed_radius: bool, @@ -133,6 +134,14 @@ fn button_appearance( } else { appearance.background = Some(Color::from(cosmic.bg_component_color()).into()); } + } else if highlighted { + if accent { + appearance.background = Some(Color::from(cosmic.bg_component_color()).into()); + appearance.icon_color = Some(Color::from(cosmic.on_bg_component_color())); + appearance.text_color = Some(Color::from(cosmic.on_bg_component_color())); + } else { + appearance.background = Some(Color::from(cosmic.bg_component_color()).into()); + } } else if desktop { appearance.background = Some(Color::from(cosmic.bg_color()).into()); appearance.icon_color = Some(Color::from(cosmic.on_bg_color())); @@ -154,6 +163,7 @@ fn button_appearance( fn button_style( selected: bool, + highlighted: bool, accent: bool, condensed_radius: bool, desktop: bool, @@ -161,16 +171,48 @@ fn button_style( //TODO: move to libcosmic? theme::Button::Custom { active: Box::new(move |focused, theme| { - button_appearance(theme, selected, focused, accent, condensed_radius, desktop) + button_appearance( + theme, + selected, + highlighted, + focused, + accent, + condensed_radius, + desktop, + ) }), disabled: Box::new(move |theme| { - button_appearance(theme, selected, false, accent, condensed_radius, desktop) + button_appearance( + theme, + selected, + highlighted, + false, + accent, + condensed_radius, + desktop, + ) }), hovered: Box::new(move |focused, theme| { - button_appearance(theme, selected, focused, accent, condensed_radius, desktop) + button_appearance( + theme, + selected, + highlighted, + focused, + accent, + condensed_radius, + desktop, + ) }), pressed: Box::new(move |focused, theme| { - button_appearance(theme, selected, focused, accent, condensed_radius, desktop) + button_appearance( + theme, + selected, + highlighted, + focused, + accent, + condensed_radius, + desktop, + ) }), } } @@ -444,6 +486,7 @@ pub fn item_from_entry( pos_opt: Cell::new(None), rect_opt: Cell::new(None), selected: false, + highlighted: false, overlaps_drag_rect: false, } } @@ -672,6 +715,7 @@ pub fn scan_trash(sizes: IconSizes) -> Vec { pos_opt: Cell::new(None), rect_opt: Cell::new(None), selected: false, + highlighted: false, overlaps_drag_rect: false, }); } @@ -854,6 +898,7 @@ pub fn scan_desktop( pos_opt: Cell::new(None), rect_opt: Cell::new(None), selected: false, + highlighted: false, overlaps_drag_rect: false, }) } @@ -1022,6 +1067,8 @@ pub enum Message { WindowToggleMaximize, ZoomIn, ZoomOut, + HighlightDeactivate(usize), + HighlightActivate(usize), } #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -1247,6 +1294,7 @@ pub struct Item { pub pos_opt: Cell>, pub rect_opt: Cell>, pub selected: bool, + pub highlighted: bool, pub overlaps_drag_rect: bool, } @@ -2592,6 +2640,16 @@ impl Tab { } } } + Message::HighlightDeactivate(i) => { + if let Some(item) = self.items_opt.as_mut().and_then(|f| f.get_mut(i)) { + item.highlighted = false; + } + } + Message::HighlightActivate(i) => { + if let Some(item) = self.items_opt.as_mut().and_then(|f| f.get_mut(i)) { + item.highlighted = true; + } + } Message::Scroll(viewport) => { self.scroll_opt = Some(viewport.absolute_offset()); @@ -3554,7 +3612,13 @@ impl Tab { .size(icon_sizes.grid()), ) .padding(space_xxxs) - .class(button_style(item.selected, false, false, false)) + .class(button_style( + item.selected, + item.highlighted, + false, + false, + false, + )) .into(), widget::tooltip( widget::button::custom(widget::text::body(&item.display_name)) @@ -3562,6 +3626,7 @@ impl Tab { .padding([0, space_xxxs]) .class(button_style( item.selected, + item.highlighted, true, true, matches!(self.mode, Mode::Desktop), @@ -3606,7 +3671,9 @@ impl Tab { .on_press(move |_| Message::Click(Some(i))) .on_double_click(move |_| Message::DoubleClick(Some(i))) .on_release(move |_| Message::ClickRelease(Some(i))) - .on_middle_press(move |_| Message::MiddleClick(i)); + .on_middle_press(move |_| Message::MiddleClick(i)) + .on_enter(move || Message::HighlightActivate(i)) + .on_exit(move || Message::HighlightDeactivate(i)); //TODO: error if the row or col is already set? while grid_elements.len() <= row { @@ -3703,6 +3770,7 @@ impl Tab { .padding(space_xxxs) .class(button_style( item.selected, + item.highlighted, false, false, false, @@ -3711,7 +3779,13 @@ impl Tab { .id(item.button_id.clone()) .on_press(Message::Click(Some(*i))) .padding([0, space_xxxs]) - .class(button_style(item.selected, true, true, false)), + .class(button_style( + item.selected, + item.highlighted, + true, + true, + false, + )), ]; let mut column = widget::column::with_capacity(buttons.len()) @@ -3922,12 +3996,20 @@ impl Tab { .width(Length::Fill) .id(item.button_id.clone()) .padding([0, space_xxs]) - .class(button_style(item.selected, true, false, false)), + .class(button_style( + item.selected, + item.highlighted, + true, + false, + false, + )), ) .on_press(move |_| Message::Click(Some(i))) .on_double_click(move |_| Message::DoubleClick(Some(i))) .on_release(move |_| Message::ClickRelease(Some(i))) - .on_middle_press(move |_| Message::MiddleClick(i)); + .on_middle_press(move |_| Message::MiddleClick(i)) + .on_enter(move || Message::HighlightActivate(i)) + .on_exit(move || Message::HighlightDeactivate(i)); if self.context_menu.is_some() { mouse_area