Skip to content

Commit

Permalink
Implement ability for list to be unfocused. Action panel list is unfo…
Browse files Browse the repository at this point in the history
…cused by default if panel is opened using mouse click
  • Loading branch information
Exidex committed Oct 6, 2024
1 parent 3945189 commit e02e993
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 60 deletions.
35 changes: 20 additions & 15 deletions rust/client/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,13 @@ pub enum AppMsg {
FontLoaded(Result<(), font::Error>),
ShowWindow,
HideWindow,
ToggleActionPanel,
OnEntrypointAction(UiWidgetId),
ToggleActionPanel {
keyboard: bool
},
OnEntrypointAction {
keyboard: bool,
widget_id: UiWidgetId
},
ShowPreferenceRequiredView {
plugin_id: PluginId,
entrypoint_id: EntrypointId,
Expand Down Expand Up @@ -507,7 +512,7 @@ impl Application for AppModel {
MainViewState::None => {
match physical_key_model(physical_key, modifiers) {
Some(PhysicalShortcut { physical_key: PhysicalKey::KeyK, modifier_shift: false, modifier_control: false, modifier_alt: true, modifier_meta: false }) => {
Command::perform(async {}, |_| AppMsg::ToggleActionPanel)
Command::perform(async {}, |_| AppMsg::ToggleActionPanel { keyboard: true })
}
Some(PhysicalShortcut { physical_key, modifier_shift, modifier_control, modifier_alt, modifier_meta }) => {
if let Some(search_item) = focused_search_result.get(&self.search_results) {
Expand All @@ -534,7 +539,7 @@ impl Application for AppModel {
MainViewState::ActionPanel { .. } => {
match physical_key_model(physical_key, modifiers) {
Some(PhysicalShortcut { physical_key: PhysicalKey::KeyK, modifier_shift: false, modifier_control: false, modifier_alt: true, modifier_meta: false }) => {
Command::perform(async {}, |_| AppMsg::ToggleActionPanel)
Command::perform(async {}, |_| AppMsg::ToggleActionPanel { keyboard: true })
}
Some(PhysicalShortcut { physical_key, modifier_shift, modifier_control, modifier_alt, modifier_meta }) => {
if let Some(search_item) = focused_search_result.get(&self.search_results) {
Expand Down Expand Up @@ -564,7 +569,7 @@ impl Application for AppModel {
GlobalState::PluginView { .. } => {
match physical_key_model(physical_key, modifiers) {
Some(PhysicalShortcut { physical_key: PhysicalKey::KeyK, modifier_shift: false, modifier_control: false, modifier_alt: true, modifier_meta: false }) => {
Command::perform(async {}, |_| AppMsg::ToggleActionPanel)
Command::perform(async {}, |_| AppMsg::ToggleActionPanel { keyboard: true })
}
Some(PhysicalShortcut { physical_key, modifier_shift, modifier_control, modifier_alt, modifier_meta }) => {
self.handle_plugin_view_keyboard_event(physical_key, modifier_shift, modifier_control, modifier_alt, modifier_meta)
Expand Down Expand Up @@ -760,14 +765,14 @@ impl Application for AppModel {
#[cfg(not(target_os = "linux"))]
window::close(window::Id::MAIN)
}
AppMsg::ToggleActionPanel => {
AppMsg::ToggleActionPanel { keyboard } => {
match &mut self.global_state {
GlobalState::MainView { sub_state, focused_search_result, .. } => {
match sub_state {
MainViewState::None => {
if let Some(search_item) = focused_search_result.get(&self.search_results) {
if search_item.entrypoint_actions.len() > 0 {
MainViewState::action_panel(sub_state);
MainViewState::action_panel(sub_state, keyboard);
}
}
}
Expand All @@ -784,7 +789,7 @@ impl Application for AppModel {

match sub_state {
PluginViewState::None => {
PluginViewState::action_panel(sub_state)
PluginViewState::action_panel(sub_state, keyboard)
}
PluginViewState::ActionPanel { .. } => {
PluginViewState::initial(sub_state)
Expand All @@ -795,7 +800,7 @@ impl Application for AppModel {

Command::none()
}
AppMsg::OnEntrypointAction(widget_id) => {
AppMsg::OnEntrypointAction { keyboard, widget_id} => {
match &mut self.global_state {
GlobalState::MainView { focused_search_result, sub_state, .. } => {
match sub_state {
Expand Down Expand Up @@ -843,7 +848,7 @@ impl Application for AppModel {
let render_location = UiRenderLocation::View;

Command::batch([
Command::perform(async {}, |_| AppMsg::ToggleActionPanel),
Command::perform(async {}, move |_| AppMsg::ToggleActionPanel { keyboard }),
Command::perform(async {}, move |_| AppMsg::WidgetEvent { widget_event, plugin_id, render_location })
])
}
Expand Down Expand Up @@ -1182,8 +1187,8 @@ impl Application for AppModel {
action_panel,
None::<&ScrollHandle<SearchResultEntrypointAction>>,
"".to_string(),
|| AppMsg::ToggleActionPanel,
AppMsg::OnEntrypointAction
|| AppMsg::ToggleActionPanel { keyboard: false },
|widget_id| AppMsg::OnEntrypointAction { widget_id, keyboard: false }
)
}
MainViewState::ActionPanel { focused_action_item, .. } => {
Expand All @@ -1196,8 +1201,8 @@ impl Application for AppModel {
action_panel,
Some(focused_action_item),
"".to_string(),
|| AppMsg::ToggleActionPanel,
AppMsg::OnEntrypointAction
|| AppMsg::ToggleActionPanel { keyboard: false },
|widget_id| AppMsg::OnEntrypointAction { widget_id, keyboard: false }
)
}
};
Expand Down Expand Up @@ -1436,7 +1441,7 @@ impl AppModel {
match event {
UiViewEvent::View { widget_id, event_name, event_arguments } => {
let msg = match widget_event {
ComponentWidgetEvent::ActionClick { .. } => AppMsg::ToggleActionPanel,
ComponentWidgetEvent::ActionClick { .. } => AppMsg::ToggleActionPanel { keyboard: false },
_ => AppMsg::Noop
};

Expand Down
67 changes: 48 additions & 19 deletions rust/client/src/ui/scroll_handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,68 @@ use iced::widget::scrollable;
use iced::widget::scrollable::{scroll_to, AbsoluteOffset};
use crate::ui::AppMsg;

// TODO this size of item for main view list, incorrect for actions,
// but amount of actions is usually small so it is not that noticeable
const ESTIMATED_ITEM_SIZE: f32 = 38.8;

#[derive(Clone, Debug)]
pub struct ScrollHandle<T> {
phantom: PhantomData<T>,
pub scrollable_id: scrollable::Id,
pub index: usize,
pub offset: usize,
pub index: Option<usize>,
offset: usize,
}

impl<T> ScrollHandle<T> {
pub fn new() -> ScrollHandle<T> {
pub fn new(first_focused: bool) -> ScrollHandle<T> {
ScrollHandle {
phantom: PhantomData,
scrollable_id: scrollable::Id::unique(),
index: 0,
index: if first_focused { Some(0) } else { None },
offset: 0,
}
}

pub fn reset(&mut self) {
self.index = 0;
self.index = None;
self.offset = 0;
}

pub fn get<'a>(&self, search_results: &'a [T]) -> Option<&'a T> {
search_results.get(self.index)
match self.index {
None => None,
Some(index) => search_results.get(index)
}
}

pub fn focus_next(&mut self, item_amount: usize) -> Command<AppMsg> {
pub fn focus_next(&mut self, total_item_amount: usize) -> Command<AppMsg> {
self.offset = if self.offset < 8 {
self.offset + 1
} else {
8
};

if self.index < item_amount - 1 {
self.index = self.index + 1;
match self.index.as_mut() {
None => {
if total_item_amount > 0 {
self.index = Some(0);

let pos_y = self.index as f32 * ESTIMATED_ITEM_SIZE - (self.offset as f32 * ESTIMATED_ITEM_SIZE);
self.scroll_to(0)
} else {
Command::none()
}
}
Some(index) => {
if *index < total_item_amount - 1 {
*index = *index + 1;

scroll_to(self.scrollable_id.clone(), AbsoluteOffset { x: 0.0, y: pos_y })
} else {
Command::none()
let index = *index;

self.scroll_to(index)
} else {
Command::none()
}
}
}
}

Expand All @@ -58,14 +76,25 @@ impl<T> ScrollHandle<T> {
1
};

if self.index > 0 {
self.index = self.index - 1;
match self.index.as_mut() {
None => Command::none(),
Some(index) => {
if *index > 0 {
*index = *index - 1;

let pos_y = self.index as f32 * ESTIMATED_ITEM_SIZE - (self.offset as f32 * ESTIMATED_ITEM_SIZE);
let index = *index;

scroll_to(self.scrollable_id.clone(), AbsoluteOffset { x: 0.0, y: pos_y })
} else {
Command::none()
self.scroll_to(index)
} else {
Command::none()
}
}
}
}

fn scroll_to<Message: 'static>(&self, index: usize) -> Command<Message> {
let pos_y = index as f32 * ESTIMATED_ITEM_SIZE - (self.offset as f32 * ESTIMATED_ITEM_SIZE);

scroll_to(self.scrollable_id.clone(), AbsoluteOffset { x: 0.0, y: pos_y })
}
}
17 changes: 11 additions & 6 deletions rust/client/src/ui/search_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::ui::theme::text::TextStyle;

pub struct SearchList<'a, Message> {
on_select: Box<dyn Fn(SearchResult) -> Message>,
focused_search_result: usize,
focused_search_result: Option<usize>,
search_results: &'a[SearchResult],
}

Expand All @@ -35,7 +35,7 @@ pub struct SelectItemEvent(SearchResult);
impl<'a, Message> SearchList<'a, Message> {
pub fn new(
search_results: &'a[SearchResult],
focused_search_result: usize,
focused_search_result: Option<usize>,
on_open_view: impl Fn(SearchResult) -> Message + 'static,
) -> Self {
Self {
Expand Down Expand Up @@ -105,10 +105,15 @@ impl<'a, Message> Component<Message, GauntletTheme> for SearchList<'a, Message>
.align_items(Alignment::Center)
.into();

let style = if self.focused_search_result == index {
ButtonStyle::MainListItemFocused
} else {
ButtonStyle::MainListItem
let style = match self.focused_search_result {
None => ButtonStyle::MainListItem,
Some(focused_index) => {
if focused_index == index {
ButtonStyle::MainListItemFocused
} else {
ButtonStyle::MainListItem
}
}
};

button(button_content)
Expand Down
13 changes: 8 additions & 5 deletions rust/client/src/ui/state/main_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ impl MainViewState {
*prev_state = Self::None
}

pub fn action_panel(prev_state: &mut MainViewState) {
pub fn action_panel(prev_state: &mut MainViewState, focus_first: bool) {
*prev_state = Self::ActionPanel {
focused_action_item: ScrollHandle::new(),
focused_action_item: ScrollHandle::new(focus_first),
}
}
}
Expand All @@ -35,9 +35,12 @@ impl Focus<SearchResultEntrypointAction> for MainViewState {
panic!("invalid state")
}
MainViewState::ActionPanel { focused_action_item } => {
let widget_id = focused_action_item.index;

Command::perform(async {}, move |_| AppMsg::OnEntrypointAction(widget_id))
match focused_action_item.index {
None => Command::none(),
Some(widget_id) => {
Command::perform(async {}, move |_| AppMsg::OnEntrypointAction { widget_id, keyboard: true })
}
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion rust/client/src/ui/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl GlobalState {
GlobalState::MainView {
search_field_id,
prompt: "".to_string(),
focused_search_result: ScrollHandle::new(),
focused_search_result: ScrollHandle::new(true),
sub_state: MainViewState::new(),
pending_plugin_view_data: None,
}
Expand Down
12 changes: 6 additions & 6 deletions rust/client/src/ui/state/plugin_view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ impl PluginViewState {
*prev_state = Self::None
}

pub fn action_panel(prev_state: &mut PluginViewState) {
pub fn action_panel(prev_state: &mut PluginViewState, focus_first: bool) {
*prev_state = Self::ActionPanel {
focused_action_item: ScrollHandle::new(),
focused_action_item: ScrollHandle::new(focus_first),
}
}
}
Expand All @@ -35,15 +35,15 @@ impl Focus<UiWidgetId> for PluginViewState {
PluginViewState::None => {
if let Some(widget_id) = focus_list.get(0) {
let widget_id = *widget_id;
Command::perform(async {}, move |_| AppMsg::OnEntrypointAction(widget_id))
Command::perform(async {}, move |_| AppMsg::OnEntrypointAction { widget_id, keyboard: true })
} else {
Command::none()
}
},
PluginViewState::ActionPanel { focused_action_item, .. } => {
if let Some(widget_id) = focused_action_item.get(focus_list) {
let widget_id = *widget_id;
Command::perform(async {}, move |_| AppMsg::OnEntrypointAction(widget_id))
Command::perform(async {}, move |_| AppMsg::OnEntrypointAction { widget_id, keyboard: true })
} else {
Command::none()
}
Expand All @@ -56,7 +56,7 @@ impl Focus<UiWidgetId> for PluginViewState {
PluginViewState::None => {
if let Some(widget_id) = focus_list.get(1) {
let widget_id = *widget_id;
Command::perform(async {}, move |_| AppMsg::OnEntrypointAction(widget_id))
Command::perform(async {}, move |_| AppMsg::OnEntrypointAction { widget_id, keyboard: true })
} else {
Command::none()
}
Expand All @@ -74,7 +74,7 @@ impl Focus<UiWidgetId> for PluginViewState {
panic!("invalid state")
}
PluginViewState::ActionPanel { .. } => {
Command::perform(async {}, |_| AppMsg::ToggleActionPanel)
Command::perform(async {}, |_| AppMsg::ToggleActionPanel { keyboard: true })
}
}
}
Expand Down
Loading

0 comments on commit e02e993

Please sign in to comment.