diff --git a/advotracker/src/data/constants.rs b/advotracker/src/data/constants.rs index 5eb23c1..52fbe4d 100644 --- a/advotracker/src/data/constants.rs +++ b/advotracker/src/data/constants.rs @@ -29,6 +29,8 @@ pub static ID_LOCALIZATION_LABEL_LANGUAGE_NAME: &str = "localization_label_langu pub static ID_LOCALIZATION_LANGUAGE_NAME: &str = "localization_language_name"; pub static ID_MENU_POPUP: &str = "menu_popup"; +pub static ID_MENU_STACK: &str = "menu_stack"; +pub static ID_MENU_BUTTON: &str = "menu_button"; pub static ID_MENU_GRID: &str = "menu_grid"; pub static ID_MENU_LABEL_ACCOUNT: &str = "menu_label_account"; pub static ID_MENU_LABEL_QUIT: &str = "menu_label_quit"; diff --git a/advotracker/src/widgets/main_view.rs b/advotracker/src/widgets/main_view.rs index b9b21fe..8057a3e 100644 --- a/advotracker/src/widgets/main_view.rs +++ b/advotracker/src/widgets/main_view.rs @@ -12,6 +12,7 @@ use crate::{ widgets::policycheck::policycheck_view::PolicycheckView, widgets::localization::localization_view::LocalizationView, widgets::configuration::configuration_view::ConfigurationView, + widgets::menu::menu_view::MenuView, }; // [START] views @@ -57,6 +58,7 @@ impl Template for MainView { .tab("Policynumber check", policycheck_view) .tab("Localization", LocalizationView::new().build(ctx)) .tab("Configuration", ConfigurationView::new().build(ctx)) + .tab("Menu", MenuView::new().build(ctx)) .build(ctx), ) //.child(policycheck_view) diff --git a/advotracker/src/widgets/menu/menu_state.rs b/advotracker/src/widgets/menu/menu_state.rs index 98e744a..7b61404 100644 --- a/advotracker/src/widgets/menu/menu_state.rs +++ b/advotracker/src/widgets/menu/menu_state.rs @@ -13,32 +13,73 @@ use std::process; use crate::{ data::constants::*, - widgets::policycheck::policycheck_view::PolicycheckView, - widgets::policycheck::policycheck_state::{PolicycheckAction, PolicycheckState}, + widgets::menu::menu_view::MenuView, + //widgets::policycheck::policycheck_view::PolicycheckView, }; -/// Valid `actions` that are handled as state changes in the `Policycheck` widget. +/// Valid `actions` that are handled as state changes in the `Menu` widget. #[derive(Debug, Clone, Copy)] pub enum MenuAction { - CreateMenuPopup(Entity), - RemoveMenuPopup(Entity), - SetThemeToggle(Entity), + CreateMenu, + CreateMenuToggleTheme(Entity), + RemoveMenu, + RemoveMenuToggleTheme(Entity), + SetTheme } /// Valid `structures` that are handled inside the state of the `Menu` widget. #[derive(AsAny, Default)] pub struct MenuState { - action: Option, + action: Option, menu: Entity, - menu_toggle_theme: Entity, + menu_toggle_theme: Entity } /// Method definitions, that react on any given state change inside the `Menu` widget. impl MenuState { + /// Set a menu holding all valid menu elements + /// The elements are ordered compontents inside a stack + pub fn create_menu(&mut self, ctx: &mut Context<'_>) { + // create a stack as a child of the given component + let stack = ctx + .entity_of_child(ID_MENU_BUTTON) + .expect("PolicycheckState: Can't find entity of resource 'ID_MENU_BUTTON'."); + //.entity_of_child(ID_MENU_BUTTON) + //.expect("PolicycheckState: Can't find entity of resource 'ID_POLICY_CHECK_POPUP_MENU'."); + let current_entity = ctx.entity(); + let build_context = &mut ctx.build_context(); + + // create a new popup menu overlay + self.menu = create_menu_popup(current_entity, build_context); + + // create a menu_popup widget as a child of entity "ID_POLICY_CHECK_BUTTON_MENU" + build_context.append_child(stack, self.menu); + + println!("Popup Menu created: {:?}", self.menu); + } + + /// Set a toggle_theme menu + /// Select the active theme from a `ComboBox` offering a list of valid `themes`` + fn create_menu_toggle_theme(&mut self, ctx: &mut Context<'_>) { + let stack = ctx + .entity_of_child(ID_MENU_LABEL_TOGGLE_THEME) + .expect("MenuState: Can't find entity of resource 'ID_MENU_LABEL_TOGGLE_THEME'."); + let current_entity = ctx.entity(); + let build_context = &mut ctx.build_context(); + + // create a new menu overlay + self.menu_toggle_theme = create_menu_toggle_theme_popup(current_entity, build_context); + + // create a menu_popup widget as a child of entity "ID_POPUP_MENU" + build_context.append_child(stack, self.menu_toggle_theme); + + println!("Popup Menu Toggle Theme created: {:?}", self.menu_toggle_theme); + } + /// Remove the menu popup box - fn remove_menu(&mut self, id: Entity, ctx: &mut Context<'_>) { - ctx.remove_child(self.menu); - println!("Popup {:?} removed !", id); + fn remove_menu(&mut self, ctx: &mut Context<'_>) { + ctx.remove_child(ctx.entity()); + println!("Popup {:?} removed !", ctx.entity()); } /// Remove the menu popup box @@ -51,49 +92,17 @@ impl MenuState { pub fn set_action(&mut self, action: MenuAction) { self.action = action.into(); } - - /// Set a menu using a stack that holds all valid menu elements - /// The elements are ordered in a stack - fn set_menu(&mut self, ctx: &mut Context<'_>) { - let stack = ctx - .entity_of_child(ID_POLICY_CHECK_BUTTON_MENU) - .expect("PolicycheckState: Can't find entity of resource 'ID_POLICY_CHECK_POPUP_MENU'."); - let current_entity = ctx.entity(); - let build_context = &mut ctx.build_context(); - - // create a new popup menu overlay - self.menu = new_menu(current_entity, build_context); - - // create a menu_popup widget as a child of entity "ID_POLICY_CHECK_BUTTON_MENU" - build_context.append_child(stack, self.menu); - - println!("Popup Menu created: {:?}", self.menu); - } - - /// Set a toggle_theme menu - /// Select the active theme from a `ComboBox` offering a list of valid `themes`` - fn set_menu_toggle_theme(&mut self, ctx: &mut Context<'_>) { - let stack = ctx - .entity_of_child(ID_MENU_LABEL_TOGGLE_THEME) - .expect("MenuState: Can't find entity of resource 'ID_MENU_LABEL_TOGGLE_THEME'."); - let current_entity = ctx.entity(); - let build_context = &mut ctx.build_context(); - - // create a new menu overlay - self.menu_toggle_theme = new_menu_toggle_theme(current_entity, build_context); - - // create a menu_popup widget as a child of entity "ID_POPUP_MENU" - build_context.append_child(stack, self.menu_toggle_theme); - - println!("Popup Menu Toggle Theme created: {:?}", self.menu_toggle_theme); - } } /// Supported methods handled inside the `MenuState` impl State for MenuState { /// Initialize the state of widgets inside `MenuState` - fn init(&mut self, _: &mut Registry, ctx: &mut Context<'_>) { - } + fn init(&mut self, _: &mut Registry, _ctx: &mut Context<'_>) { + // Initialize required entities + // let menu_button = ctx + // .entity_of_child(ID_MENU_STACK) + // .expect("MenuState.init: Can't find resource entity 'PolicycheckView::ID_POLICY_CHECK_BUTTON_MENU'."); +} /// Handle messages for the `MenuState` fn messages( @@ -104,8 +113,8 @@ impl State for MenuState { ) { for message in messages.read::() { match message { - MenuAction::ChangeTheme() => { - let theme_index = *PolicycheckView::selected_index_ref(&ctx.widget()); + MenuAction::SetTheme => { + let theme_index = *MenuView::selected_index_ref(&ctx.widget()); cfg_if! { if #[cfg(windows)] { @@ -136,33 +145,35 @@ impl State for MenuState { fn update(&mut self, _registry: &mut Registry, ctx: &mut Context<'_>) { if let Some(action) = self.action { match action { - MenuAction::RemoveMenu(_entity) => { + MenuAction::CreateMenu => { + println!("MenuAction::CreateMenu(_entity)"); + self.create_menu(ctx); + } + MenuAction::CreateMenuToggleTheme(_entity) => { + self.create_menu_toggle_theme(ctx); + } + MenuAction::RemoveMenu => { self.remove_menu(ctx); } - MenuAction::RemoveMenuToggleTheme(_entity) => { - self.remove_menu_toggle_theme(ctx); - } - MenuAction::SetMenu(_entity) => { - self.set_menu(ctx); - } - MenuAction::SetMenuToggleTheme(_entity) => { - self.set_menu_toggle_theme(ctx); + MenuAction::RemoveMenuToggleTheme(entity) => { + self.remove_menu_toggle_theme(entity, ctx); } + _ => (), } } } } -/// Create a new menu popup -pub fn new_menu(menu: Entity, ctx: &mut BuildContext<'_>) -> Entity { +/// Create a new popup presenting the menu components +pub fn create_menu_popup(id: Entity, ctx: &mut BuildContext<'_>) -> Entity { Popup::new() .id(ID_MENU_POPUP) .style("container_menu") - .target(menu) + .target(id) .open(true) .width(280) .height(140) - .on_key_down(move | _ctx, key_event | { + .on_key_down(move | ctx, key_event | { match key_event.key { Key::Q(..) => { //if is_ctrl_home_down(ctx) @@ -172,8 +183,8 @@ pub fn new_menu(menu: Entity, ctx: &mut BuildContext<'_>) -> Entity { }, Key::Escape => { println!("KeyHandler: got Escape"); - //ctx.get::(menu) - // .set_action(PolicycheckAction::RemoveMenu(menu)); + ctx.get_mut::(id) + .set_action(MenuAction::RemoveMenu); }, _ => { println!("KeyHandler: got {:?}", key_event.key); @@ -218,11 +229,11 @@ pub fn new_menu(menu: Entity, ctx: &mut BuildContext<'_>) -> Entity { .attach(Grid::column_span(2)) .icon(material_icons_font::MD_EDIT) .text("Toggle theme") - .on_click(move |states, _| { - states.get_mut::(menu) - .set_action(MenuAction::SetToggleTheme(menu)); - true - }) + // .on_click(move |ctx, _| { + // ctx.get_mut::(id) + // .set_action(MenuAction::SetTheme(id)); + // true + // }) .build(ctx), ) .child( @@ -257,11 +268,14 @@ pub fn new_menu(menu: Entity, ctx: &mut BuildContext<'_>) -> Entity { } /// Create a new popup submenu to toogle the active theme -pub fn new_menu_toggle_theme(menu_toggle_theme: Entity, ctx: &mut BuildContext<'_>) -> Entity { +pub fn create_menu_toggle_theme_popup(id: Entity, ctx: &mut BuildContext<'_>) -> Entity { + //let themes_count = themes.len(); + //ProgressBar::val_set(&mut ctx.child(ID_POLICY_CHECK_PROGRESS_BAR), new_width); + Popup::new() .id(ID_MENU_TOGGLE_THEME) .style("container_menu") - .target(menu_toggle_theme) + .target(id) .open(true) .width(280) .height(140) @@ -269,17 +283,17 @@ pub fn new_menu_toggle_theme(menu_toggle_theme: Entity, ctx: &mut BuildContext<' ComboBox::new() .attach(Grid::column(2)) .attach(Grid::row(6)) - .count(themes_count) + //.count(themes_count) .items_builder(move |build_ctx, index| { let theme_name = - PolicycheckView::themes_ref(&build_ctx.get_widget(menu_toggle_theme))[index].clone(); + MenuView::themes_ref(&build_ctx.get_widget(id))[index].clone(); TextBlock::new().v_align("center").text(theme_name).build(build_ctx) }) .on_changed("selected_index", move |ctx, _| { - ctx.send_message(MenuAction::ChangeTheme, menu_toggle_theme); + ctx.send_message(MenuAction::SetTheme, id); println!("changed theme."); }) - .selected_index(menu_toggle_theme) + .selected_index(id) .build(ctx), ) .build(ctx) diff --git a/advotracker/src/widgets/menu/menu_view.rs b/advotracker/src/widgets/menu/menu_view.rs index 8a1fc7b..c6d9ca3 100644 --- a/advotracker/src/widgets/menu/menu_view.rs +++ b/advotracker/src/widgets/menu/menu_view.rs @@ -7,31 +7,26 @@ use cfg_if::cfg_if; use orbtk::prelude::*; -use orbtk::shell::event::Key; -use std::process; - -use crate::{ - data::constants::*, - //widgets::policycheck::policycheck_view::PolicycheckView, - widgets::menu::menu_state::{MenuAction, MenuState}, -}; +use crate::data::constants::*; +use crate::widgets::menu::menu_state::{MenuAction, MenuState}; type List = Vec; // Macro that initializes the widget structures/variables for the menu view widget!( MenuView { + //menu_stack: Entity, + //button_menu: Entity, selected_index: i32, - themes: List, - themes_count: i32 + themes: List } ); /// The template implementation of the menu view /// All GUI elements are styled using the "style" attribute referencing to a ron based css impl Template for MenuView { - fn template(self, id: Entity, ctx: &mut BuildContext) -> Self { + fn template(self, id: Entity, ctx: &mut BuildContext<'_>) -> Self { cfg_if! { if #[cfg(windows)] { // define the list of supported themes @@ -52,9 +47,36 @@ impl Template for MenuView { } } - let themes_count = themes.len(); - + //self.themes(themes).child(MenuState::create_menu(ID_MENU_POPUP, ctx)) self.themes(themes).child( + Stack::new() + .id(ID_MENU_STACK) + .child( + TextBlock::new() + .style("header") + .attach(Grid::row(0)) + .attach(Grid::column(0)) + .style("small_text") + .text("Select theme") + .build(ctx), + ) + .child( + Button::new() + //.id("button_menu") + .id(ID_MENU_BUTTON) + .style("button_single_content") + .icon(material_icons_font::MD_MENU) + .attach(Grid::column(2)) + .h_align("end") + .on_click(move |ctx, _| { + println!("WIP: open menu popup from MenuView"); + ctx.get_mut::(id) + .set_action(MenuAction::CreateMenu); + true + }) + .build(ctx), + ) + .build(ctx), ) } }