1use crate::*;
2use alux_ext::ext;
3
4#[ext(name = ManagerMenuExt)]
6pub impl<This> This
7where
8 This: NavigationStateAlg
9 + QueueCatalogAlg
10 + DraftStateAlg
11 + InputDraftAlg
12 + OutputDraftAlg
13 + TextEditorStateAlg
14 + DetailSelectionAlg,
15 This::Entry: QueueEntryAlg + RequestOptionsAlg,
16 This::Id: Copy + Eq,
17{
18 fn action_availability(&self, action: ManagerAction) -> ActionAvailability {
20 let enabled = match action {
21 ManagerAction::Exit => true,
22 ManagerAction::Back => self.page() != ManagerPage::Collection,
23 ManagerAction::AddSources => self.page() == ManagerPage::Collection,
24 ManagerAction::Space => {
25 matches!(self.page(), ManagerPage::Collection | ManagerPage::Details(_))
26 && self
27 .selected_queue_id()
28 .and_then(|id| self.queue_entry(id))
29 .and_then(QueueEntryAlg::space_action)
30 .is_some()
31 }
32 ManagerAction::Remove => self.page() == ManagerPage::Collection && self.selected_queue_id().is_some(),
33 ManagerAction::Previous => self.cursor_can_move(false),
34 ManagerAction::Next => self.cursor_can_move(true),
35 ManagerAction::Activate => self.selection_can_activate(),
36 };
37 if enabled { ActionAvailability::Enabled } else { ActionAvailability::Disabled }
38 }
39
40 fn cursor_can_move(&self, forward: bool) -> bool {
42 match self.page() {
43 ManagerPage::Collection => self.queue_ids().take(2).count() > 1,
44 ManagerPage::AddSources | ManagerPage::Output(_) | ManagerPage::Input(_) => self
45 .active_text_editor()
46 .is_some_and(|(text, cursor)| if forward { cursor < text.len() } else { cursor > 0 }),
47 ManagerPage::Details(id) => self.queue_entry(id).is_some_and(|entry| !entry.detail_controls().is_empty()),
48 ManagerPage::Formats(id) => {
49 self.queue_entry(id).is_some_and(|entry| entry.selectable_choices().next().is_some())
50 }
51 ManagerPage::Log(_) | ManagerPage::Report(_) | ManagerPage::Command(_) => false,
53 }
54 }
55
56 fn selection_can_activate(&self) -> bool {
58 match self.page() {
59 ManagerPage::Collection => self.selected_queue_id().is_some(),
60 ManagerPage::AddSources => self.draft().lines().any(|line| !line.trim().is_empty()),
61 ManagerPage::Output(id) => {
62 self.queue_entry(id).is_some_and(QueueEntryAlg::is_editable) && !self.output_draft().trim().is_empty()
63 }
64 ManagerPage::Input(id) => {
65 self.queue_entry(id).is_some_and(QueueEntryAlg::is_editable) && !self.input_draft().trim().is_empty()
66 }
67 ManagerPage::Details(id) => self.queue_entry(id).is_some_and(|entry| {
68 self.selected_detail_control().is_none_or(|control| entry.detail_controls().contains(&control))
69 }),
70 ManagerPage::Formats(id) => {
71 self.queue_entry(id).is_some_and(|entry| entry.selectable_choices().next().is_some())
72 }
73 ManagerPage::Log(_) | ManagerPage::Report(_) | ManagerPage::Command(_) => false,
74 }
75 }
76}
77
78#[derive(Clone, Copy, Debug, PartialEq, Eq)]
80pub enum ManagerAction {
81 Previous,
83 Next,
85 Activate,
87 AddSources,
89 Space,
91 Remove,
93 Back,
95 Exit,
97}
98
99#[derive(Clone, Copy, Debug, PartialEq, Eq)]
101pub enum ActionAvailability {
102 Enabled,
104 Disabled,
106}
107
108impl ActionAvailability {
109 #[must_use]
111 pub const fn is_enabled(self) -> bool {
112 matches!(self, Self::Enabled)
113 }
114}