oxedyne/fe2o3/fe2o3_tui/src/lib_tui/cfg/window.rs
13.4 KiB, 58 runs
created by r1870400018:1169, which is this file's identity for as long as the history lasts, whatever it is later renamed to
download · who wrote it · its history
| 1 | use crate::lib_tui::{ |
| 2 | action::Action, |
| 3 | cfg::style::StyleLibrary, |
| 4 | draw::{ |
| 5 | tab::{ |
| 6 | TabStripConfig, |
| 7 | TabbedTextBox, |
| 8 | TabbedTextManager, |
| 9 | TabbedTile, |
| 10 | }, |
| 11 | tbox::TextBox, |
| 12 | window::{ |
| 13 | TextBoxesState, |
| 14 | WindowConfig, |
| 15 | WindowId, |
| 16 | WindowStateInit, |
| 17 | WindowType, |
| 18 | }, |
| 19 | }, |
| 20 | style::{ |
| 21 | Colour, |
| 22 | Style, |
| 23 | Symbol, |
| 24 | }, |
| 25 | text::{ |
| 26 | nav::Navigator, |
| 27 | typ::{ |
| 28 | ContentType, |
| 29 | HighlightType, |
| 30 | TextType, |
| 31 | TextViewType, |
| 32 | }, |
| 33 | view::TextView, |
| 34 | }, |
| 35 | window::{ |
| 36 | MenuList, |
| 37 | WindowManagerConfig, |
| 38 | }, |
| 39 | }; |
| 40 | |
| 41 | use oxedyne_fe2o3_core::prelude::*; |
| 42 | use oxedyne_fe2o3_geom::{ |
| 43 | dim::{ |
| 44 | Coord, |
| 45 | Dim, |
| 46 | FlexDim, |
| 47 | }, |
| 48 | rect::{ |
| 49 | AbsSize, |
| 50 | Position, |
| 51 | RelativePosition, |
| 52 | RelRect, |
| 53 | RelSize, |
| 54 | RectView, |
| 55 | }, |
| 56 | }; |
| 57 | use oxedyne_fe2o3_text::{ |
| 58 | Text, |
| 59 | access::AccessibleText, |
| 60 | lines::TextLines, |
| 61 | }; |
| 62 | |
| 63 | use std::{ |
| 64 | rc::Rc, |
| 65 | sync::{ |
| 66 | Arc, |
| 67 | RwLock, |
| 68 | }, |
| 69 | }; |
| 70 | |
| 71 | |
| 72 | impl StyleLibrary { |
| 73 | |
| 74 | pub fn default_help_window( |
| 75 | &self, |
| 76 | cfg: &WindowManagerConfig, |
| 77 | ) |
| 78 | -> Outcome<( |
| 79 | WindowId, |
| 80 | WindowConfig, |
| 81 | RectView, |
| 82 | WindowStateInit, |
| 83 | )> |
| 84 | { |
| 85 | let id = WindowId::Help; |
| 86 | let view = RectView::InitiallyRelative(RelRect::FixSize { |
| 87 | top_left: Position::Relative(RelativePosition::Centre), |
| 88 | size: AbsSize::new((Dim(80), Dim(50))), |
| 89 | }); |
| 90 | let cfg = WindowConfig { |
| 91 | typ: WindowType::Fixed, |
| 92 | canvas: self.canvas_colour(None, None), |
| 93 | outlines: self.default_window_outlines(), |
| 94 | header: Some(self.standard_header_config(Some(Colour::White), Some(Colour::Magenta))), |
| 95 | footer: Some(self.standard_footer_config(Some(Colour::White), Some(Colour::Green))), |
| 96 | min_size: cfg.window_min_size(), |
| 97 | menu_text: None, |
| 98 | }; |
| 99 | let help_txt = [ |
| 100 | Text::from("Ironic is a modal text user interface. Initially you begin in Window Navigation mode."), |
| 101 | Text::from("You can enter modes or commands in one of two ways, either directly using the keys"), |
| 102 | Text::from("below, or else via the menu window (numbered 0). The menu tab of the menu window"), |
| 103 | Text::from("provides a list of actions that changes depending upon the context."), |
| 104 | Text::from("ALL MODES"), |
| 105 | Text::from(" Esc: Exit the current mode, returning to Window Navigation mode."), |
| 106 | Text::from(" Shift + Page Up/Down: Move the menu window menu tab action focus up/down."), |
| 107 | Text::from(" Home: Perform the current menu window menu tab action."), |
| 108 | Text::from("WINDOW NAVIGATION MODE"), |
| 109 | Text::from(" Tab: Move the window focus."), |
| 110 | Text::from(" Space: Enter Window Management mode for the current window."), |
| 111 | Text::from(" Enter: Enter Window Interaction mode for the current window."), |
| 112 | Text::from("WINDOW MANAGEMENT MODE"), |
| 113 | Text::from(" Arrow keys: Slide the window around the screen."), |
| 114 | Text::from(" Space again: Enter the window size editor. Pressing the space bar again"), |
| 115 | Text::from(" moves the focus to the next window border. Use the arrow keys"), |
| 116 | Text::from(" to resize."), |
| 117 | Text::from("WINDOW INTERACTION MODE"), |
| 118 | Text::from(" Tab: Move the tab focus."), |
| 119 | Text::from(" i: Enter text Insert mode."), |
| 120 | Text::from(" r: Enter text Replace mode."), |
| 121 | Text::from(" m: Enter text Modify mode."), |
| 122 | Text::from(" Arrow keys: Move the cursor."), |
| 123 | Text::from(" Shift + Arrow: Pan the text view."), |
| 124 | ]; |
| 125 | let state = WindowStateInit { |
| 126 | header: Some(self.status_strip_labels(Some(id.title()), &id.label())), |
| 127 | footer: None, |
| 128 | text_boxes: Some(TextBoxesState::Tabbed(res!(TabbedTextManager::new( |
| 129 | res!(self.standard_tab_styles()), |
| 130 | vec![ |
| 131 | TabbedTextBox { |
| 132 | tbox: res!(TextBox::new( |
| 133 | self.navigable_text_box(), |
| 134 | res!(TextView::new( |
| 135 | ContentType::Text, |
| 136 | TextViewType::Static(Navigator::default()), |
| 137 | AccessibleText::Shared(Rc::new(RwLock::new( |
| 138 | TextLines::new( |
| 139 | Self::DEFAULT_SPLASH.lines() |
| 140 | .map(|s| |
| 141 | Text::new(fmt!("{}{}", " ".repeat(10), s), None) |
| 142 | ).collect::<Vec<_>>(), |
| 143 | None, |
| 144 | ), |
| 145 | ))), |
| 146 | )), |
| 147 | )), |
| 148 | tab: self.tab_with_label(Some(Symbol::Info), "About"), |
| 149 | }, |
| 150 | TabbedTextBox { |
| 151 | tbox: res!(TextBox::new( |
| 152 | self.navigable_text_box(), |
| 153 | res!(TextView::new( |
| 154 | ContentType::Text, |
| 155 | TextViewType::Static(Navigator::default()), |
| 156 | AccessibleText::Shared(Rc::new(RwLock::new( |
| 157 | TextLines::from(help_txt) |
| 158 | ))), |
| 159 | )), |
| 160 | )), |
| 161 | tab: self.tab_with_label(Some(Symbol::Keyboard), "Keys"), |
| 162 | }, |
| 163 | TabbedTextBox { |
| 164 | tbox: res!(self.file_tree_text_box()), |
| 165 | tab: self.tab_with_label(Some(Symbol::FileTree), "File Tree"), |
| 166 | }, |
| 167 | ], |
| 168 | Some(vec![ |
| 169 | TabbedTile { |
| 170 | index: 0, |
| 171 | ..Default::default() |
| 172 | }, |
| 173 | TabbedTile { |
| 174 | index: 2, |
| 175 | ..Default::default() |
| 176 | }, |
| 177 | ]), |
| 178 | Some(0), |
| 179 | )))), |
| 180 | }; |
| 181 | Ok(( |
| 182 | id, |
| 183 | cfg, |
| 184 | view, |
| 185 | state, |
| 186 | )) |
| 187 | } |
| 188 | |
| 189 | pub fn default_log_window( |
| 190 | &self, |
| 191 | cfg: &WindowManagerConfig, |
| 192 | log: Arc<RwLock<TextLines<TextType, HighlightType>>>, |
| 193 | ) |
| 194 | -> Outcome<( |
| 195 | WindowId, |
| 196 | WindowConfig, |
| 197 | RectView, |
| 198 | WindowStateInit, |
| 199 | )> |
| 200 | { |
| 201 | let id = WindowId::Log; |
| 202 | let view = RectView::AlwaysRelative(RelRect::RelSize(RelSize::new(( |
| 203 | FlexDim::PadFillPad(Dim(0), Dim(0)), |
| 204 | FlexDim::FillFixedPad(Dim(20), Dim(0)), |
| 205 | )))); |
| 206 | let cfg = WindowConfig { |
| 207 | typ: WindowType::Fixed, |
| 208 | canvas: self.canvas_colour(Some(Colour::White), None), |
| 209 | outlines: self.default_window_outlines(), |
| 210 | header: Some(self.standard_header_config(Some(Colour::Black), Some(Colour::LightBlue))), |
| 211 | footer: None, |
| 212 | min_size: cfg.window_min_size(), |
| 213 | menu_text: None, |
| 214 | }; |
| 215 | let state = WindowStateInit { |
| 216 | header: Some(self.status_strip_labels(Some(id.title()), &id.label())), |
| 217 | footer: None, |
| 218 | text_boxes: Some(TextBoxesState::Single(res!(TextBox::new( |
| 219 | self.passive_text_box(), |
| 220 | res!(TextView::new( |
| 221 | ContentType::Log, |
| 222 | TextViewType::Static(Navigator::default()), |
| 223 | AccessibleText::ThreadShared(log), |
| 224 | )), |
| 225 | )))), |
| 226 | }; |
| 227 | Ok(( |
| 228 | id, |
| 229 | cfg, |
| 230 | view, |
| 231 | state, |
| 232 | )) |
| 233 | } |
| 234 | |
| 235 | pub fn default_menu_window( |
| 236 | &self, |
| 237 | cfg: &WindowManagerConfig, |
| 238 | window_list: Rc<RwLock<TextLines<TextType, HighlightType>>>, |
| 239 | menu_text: Arc<RwLock<TextLines<TextType, HighlightType>>>, |
| 240 | ) |
| 241 | -> Outcome<( |
| 242 | WindowId, |
| 243 | WindowConfig, |
| 244 | RectView, |
| 245 | WindowStateInit, |
| 246 | )> |
| 247 | { |
| 248 | let id = WindowId::Menu; |
| 249 | let view = RectView::InitiallyRelative(RelRect::FixSize { |
| 250 | top_left: Position::Relative(RelativePosition::TopLeft), |
| 251 | size: AbsSize::new((Dim(50), Dim(50))), |
| 252 | }); |
| 253 | let cfg = WindowConfig { |
| 254 | typ: WindowType::Fixed, |
| 255 | canvas: self.canvas_colour(Some(Colour::White), Some(Colour::LightBlue)), |
| 256 | outlines: self.default_window_outlines(), |
| 257 | header: Some(self.standard_header_config(Some(Colour::Blue), Some(Colour::Cyan))), |
| 258 | footer: Some(self.standard_footer_config(Some(Colour::White), Some(Colour::Blue))), |
| 259 | min_size: cfg.window_min_size(), |
| 260 | menu_text: None, |
| 261 | }; |
| 262 | let state = WindowStateInit { |
| 263 | header: Some(self.status_strip_labels(Some(id.title()), &id.label())), |
| 264 | footer: None, |
| 265 | text_boxes: Some(TextBoxesState::Tabbed(res!(TabbedTextManager::new( |
| 266 | res!(TabStripConfig::new(vec![ |
| 267 | Style::new(Some(Colour::White), Some(Colour::Blue), None), |
| 268 | Style::new(Some(Colour::White), Some(Colour::Green), None), |
| 269 | Style::new(Some(Colour::White), Some(Colour::Red), None), |
| 270 | Style::new(Some(Colour::Black), Some(Colour::Yellow), None), |
| 271 | Style::new(Some(Colour::LightRed), Some(Colour::Black), None), |
| 272 | ])), |
| 273 | vec![ |
| 274 | TabbedTextBox { |
| 275 | tbox: res!(TextBox::new( |
| 276 | self.menu_text_box(), |
| 277 | res!(TextView::new( |
| 278 | ContentType::Menu, |
| 279 | TextViewType::Menu(Navigator::new(None)), |
| 280 | AccessibleText::ThreadShared(menu_text), |
| 281 | )), |
| 282 | )), |
| 283 | tab: self.tab_with_label(Some(Symbol::Menu), "Menu"), |
| 284 | }, |
| 285 | TabbedTextBox { |
| 286 | tbox: res!(TextBox::new( |
| 287 | self.menu_text_box(), |
| 288 | res!(TextView::new( |
| 289 | ContentType::Menu, |
| 290 | TextViewType::WindowList(Navigator::new(None)), |
| 291 | AccessibleText::Shared(window_list), |
| 292 | )), |
| 293 | )), |
| 294 | tab: self.tab_with_label(Some(Symbol::Windows), "Windows"), |
| 295 | }, |
| 296 | ], |
| 297 | None, |
| 298 | None, |
| 299 | )))), |
| 300 | }; |
| 301 | Ok(( |
| 302 | id, |
| 303 | cfg, |
| 304 | view, |
| 305 | state, |
| 306 | )) |
| 307 | } |
| 308 | |
| 309 | pub fn default_new_window( |
| 310 | &self, |
| 311 | cfg: &WindowManagerConfig, |
| 312 | id: &WindowId, |
| 313 | top_left: Coord, |
| 314 | ) |
| 315 | -> Outcome<( |
| 316 | WindowConfig, |
| 317 | RectView, |
| 318 | WindowStateInit, |
| 319 | )> |
| 320 | { |
| 321 | let view = RectView::InitiallyRelative(RelRect::RelSize(RelSize::new(( |
| 322 | FlexDim::PadFixedFill(top_left.x, Dim(60)), |
| 323 | FlexDim::PadFixedFill(top_left.y, Dim(40)), |
| 324 | )))); |
| 325 | let cfg = WindowConfig { |
| 326 | typ: WindowType::Fixed, |
| 327 | canvas: self.canvas_colour(None, None), |
| 328 | outlines: self.default_window_outlines(), |
| 329 | header: Some(self.standard_header_config( |
| 330 | Some(Colour::White), |
| 331 | Some(Colour::Magenta), |
| 332 | )), |
| 333 | footer: Some(self.standard_footer_config( |
| 334 | Some(Colour::White), |
| 335 | Some(Colour::Blue), |
| 336 | )), |
| 337 | min_size: cfg.window_min_size(), |
| 338 | menu_text: Some(res!(MenuList::from(vec![ |
| 339 | ( |
| 340 | TextType::new_menu_heading( "Create new tab "), |
| 341 | None, |
| 342 | ), |
| 343 | ( |
| 344 | TextType::new_menu_item( " Create new text tab "), |
| 345 | Some(Action::CreateNewTextTab), |
| 346 | ), |
| 347 | ]).text_lines())), |
| 348 | }; |
| 349 | let ctyp = ContentType::FileTree; |
| 350 | let state = WindowStateInit { |
| 351 | header: Some(self.status_strip_labels_with_mode( |
| 352 | Some(id.title()), |
| 353 | &id.label(), |
| 354 | )), |
| 355 | footer: Some(self.status_strip_cursor(None::<&str>)), |
| 356 | text_boxes: Some(TextBoxesState::Tabbed(res!(TabbedTextManager::new( |
| 357 | res!(self.standard_tab_styles()), |
| 358 | vec![ |
| 359 | res!(self.tabbed_text_box(ctyp)), |
| 360 | ], |
| 361 | None, |
| 362 | None, |
| 363 | )))), |
| 364 | }; |
| 365 | Ok(( |
| 366 | cfg, |
| 367 | view, |
| 368 | state, |
| 369 | )) |
| 370 | } |
| 371 | } |