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!(
26 self.page(),
27 ManagerPage::Collection | ManagerPage::Details(_)
28 ) && self
29 .selected_queue_id()
30 .and_then(|id| self.queue_entry(id))
31 .and_then(QueueEntryAlg::space_action)
32 .is_some()
33 }
34 ManagerAction::Remove => {
35 self.page() == ManagerPage::Collection && self.selected_queue_id().is_some()
36 }
37 ManagerAction::Previous => self.cursor_can_move(false),
38 ManagerAction::Next => self.cursor_can_move(true),
39 ManagerAction::Activate => self.selection_can_activate(),
40 };
41 if enabled {
42 ActionAvailability::Enabled
43 } else {
44 ActionAvailability::Disabled
45 }
46 }
47
48 fn cursor_can_move(&self, forward: bool) -> bool {
50 match self.page() {
51 ManagerPage::Collection => self.queue_ids().take(2).count() > 1,
52 ManagerPage::AddSources | ManagerPage::Output(_) | ManagerPage::Input(_) => {
53 self.active_text_editor().is_some_and(|(text, cursor)| {
54 if forward {
55 cursor < text.len()
56 } else {
57 cursor > 0
58 }
59 })
60 }
61 ManagerPage::Details(id) => self
62 .queue_entry(id)
63 .is_some_and(|entry| !entry.detail_controls().is_empty()),
64 ManagerPage::Formats(id) => self
65 .queue_entry(id)
66 .is_some_and(|entry| entry.selectable_choices().next().is_some()),
67 ManagerPage::Log(_) | ManagerPage::Report(_) | ManagerPage::Command(_) => false,
69 }
70 }
71
72 fn selection_can_activate(&self) -> bool {
74 match self.page() {
75 ManagerPage::Collection => self.selected_queue_id().is_some(),
76 ManagerPage::AddSources => self.draft().lines().any(|line| !line.trim().is_empty()),
77 ManagerPage::Output(id) => {
78 self.queue_entry(id).is_some_and(QueueEntryAlg::is_editable)
79 && !self.output_draft().trim().is_empty()
80 }
81 ManagerPage::Input(id) => {
82 self.queue_entry(id).is_some_and(QueueEntryAlg::is_editable)
83 && !self.input_draft().trim().is_empty()
84 }
85 ManagerPage::Details(id) => self.queue_entry(id).is_some_and(|entry| {
86 self.selected_detail_control()
87 .is_none_or(|control| entry.detail_controls().contains(&control))
88 }),
89 ManagerPage::Formats(id) => self
90 .queue_entry(id)
91 .is_some_and(|entry| entry.selectable_choices().next().is_some()),
92 ManagerPage::Log(_) | ManagerPage::Report(_) | ManagerPage::Command(_) => false,
93 }
94 }
95}
96
97#[derive(Clone, Copy, Debug, PartialEq, Eq)]
99pub enum ManagerAction {
100 Previous,
102 Next,
104 Activate,
106 AddSources,
108 Space,
110 Remove,
112 Back,
114 Exit,
116}
117
118#[derive(Clone, Copy, Debug, PartialEq, Eq)]
120pub enum ActionAvailability {
121 Enabled,
123 Disabled,
125}
126
127impl ActionAvailability {
128 #[must_use]
130 pub const fn is_enabled(self) -> bool {
131 matches!(self, Self::Enabled)
132 }
133}