diff --git a/AUTHORS b/AUTHORS index fe1d88a3d7..e3e542afaa 100644 --- a/AUTHORS +++ b/AUTHORS @@ -7,3 +7,4 @@ Google LLC Raph Levien Hilmar Gústafsson Dmitry Borodin +Kaiyin Zhong diff --git a/CHANGELOG.md b/CHANGELOG.md index 296ca51ddf..8a49ec5ed3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -134,6 +134,7 @@ This means that druid no longer requires cairo on macOS and uses Core Graphics i - Removed references to cairo on macOS. ([#943] by [@xStrom]) - Updated screenshots in `README.md`. ([#967] by [@xStrom]) - Added a section about dependencies to `CONTRIBUTING.md`. ([#990] by [@xStrom]) +- Fixed menu inconsistency across multiple windows in the multiwin example. ([#926] by [@kindlychung]) ### Maintenance @@ -216,6 +217,7 @@ This means that druid no longer requires cairo on macOS and uses Core Graphics i [#920]: https://github.com/xi-editor/druid/pull/920 [#924]: https://github.com/xi-editor/druid/pull/924 [#925]: https://github.com/xi-editor/druid/pull/925 +[#926]: https://github.com/xi-editor/druid/pull/926 [#928]: https://github.com/xi-editor/druid/pull/928 [#930]: https://github.com/xi-editor/druid/pull/930 [#931]: https://github.com/xi-editor/druid/pull/931 diff --git a/druid/examples/multiwin.rs b/druid/examples/multiwin.rs index 6144e21cf1..acb51b4fdf 100644 --- a/druid/examples/multiwin.rs +++ b/druid/examples/multiwin.rs @@ -18,11 +18,11 @@ use druid::widget::prelude::*; use druid::widget::{ Align, BackgroundBrush, Button, Controller, ControllerHost, Flex, Label, Padding, }; +use druid::Target::Global; use druid::{ commands as sys_cmds, AppDelegate, AppLauncher, Application, Color, Command, ContextMenu, Data, DelegateCtx, LocalizedString, MenuDesc, MenuItem, Selector, Target, WindowDesc, WindowId, }; - use log::info; const MENU_COUNT_ACTION: Selector = Selector::new("menu-count-action"); @@ -46,7 +46,9 @@ pub fn main() { LocalizedString::new("multiwin-demo-window-title").with_placeholder("Many windows!"), ); AppLauncher::with_window(main_window) - .delegate(Delegate) + .delegate(Delegate { + windows: Vec::new(), + }) .launch(State::default()) .expect("launch failed"); } @@ -55,14 +57,10 @@ fn ui_builder() -> impl Widget { let text = LocalizedString::new("hello-counter") .with_arg("count", |data: &State, _env| data.menu_count.into()); let label = Label::new(text); - let inc_button = Button::::new("Add menu item").on_click(|ctx, data, _env| { - data.menu_count += 1; - ctx.set_menu(make_menu::(data)); - }); - let dec_button = Button::::new("Remove menu item").on_click(|ctx, data, _env| { - data.menu_count = data.menu_count.saturating_sub(1); - ctx.set_menu(make_menu::(data)); - }); + let inc_button = Button::::new("Add menu item") + .on_click(|ctx, _data, _env| ctx.submit_command(MENU_INCREMENT_ACTION, Global)); + let dec_button = Button::::new("Remove menu item") + .on_click(|ctx, _data, _env| ctx.submit_command(MENU_DECREMENT_ACTION, Global)); let new_button = Button::::new("New window").on_click(|ctx, _data, _env| { ctx.submit_command(sys_cmds::NEW_FILE, Target::Global); }); @@ -132,6 +130,9 @@ impl> Widget for Glow { } struct ContextMenuController; +struct Delegate { + windows: Vec, +} impl> Controller for ContextMenuController { fn event(&mut self, child: &mut W, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) { @@ -145,46 +146,50 @@ impl> Controller for ContextMenuController { } } -struct Delegate; - impl AppDelegate for Delegate { fn command( &mut self, ctx: &mut DelegateCtx, - target: Target, + _target: Target, cmd: &Command, data: &mut State, _env: &Env, ) -> bool { - match (target, &cmd.selector) { - (_, &sys_cmds::NEW_FILE) => { - let window = WindowDesc::new(ui_builder) + match cmd.selector { + sys_cmds::NEW_FILE => { + let new_win = WindowDesc::new(ui_builder) .menu(make_menu(data)) .window_size((data.selected as f64 * 100.0 + 300.0, 500.0)); - ctx.new_window(window); + ctx.new_window(new_win); false } - (Target::Window(id), &MENU_COUNT_ACTION) => { + MENU_COUNT_ACTION => { data.selected = *cmd.get_object().unwrap(); let menu = make_menu::(data); - ctx.set_menu(menu, id); + for id in &self.windows { + ctx.set_menu(menu.clone(), *id); + } false } // wouldn't it be nice if a menu (like a button) could just mutate state // directly if desired? - (Target::Window(id), &MENU_INCREMENT_ACTION) => { + MENU_INCREMENT_ACTION => { data.menu_count += 1; let menu = make_menu::(data); - ctx.set_menu(menu, id); + for id in &self.windows { + ctx.set_menu(menu.clone(), *id); + } false } - (Target::Window(id), &MENU_DECREMENT_ACTION) => { + MENU_DECREMENT_ACTION => { data.menu_count = data.menu_count.saturating_sub(1); let menu = make_menu::(data); - ctx.set_menu(menu, id); + for id in &self.windows { + ctx.set_menu(menu.clone(), *id); + } false } - (_, &MENU_SWITCH_GLOW_ACTION) => { + MENU_SWITCH_GLOW_ACTION => { data.glow_hot = !data.glow_hot; false } @@ -200,7 +205,9 @@ impl AppDelegate for Delegate { _ctx: &mut DelegateCtx, ) { info!("Window added, id: {:?}", id); + self.windows.push(id); } + fn window_removed( &mut self, id: WindowId, @@ -209,6 +216,9 @@ impl AppDelegate for Delegate { _ctx: &mut DelegateCtx, ) { info!("Window removed, id: {:?}", id); + if let Some(pos) = self.windows.iter().position(|x| *x == id) { + self.windows.remove(pos); + } } }