Skip to content

Track window creation and deletion: Take 2 #286

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions druid/examples/multiwin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ use druid::menu::{ContextMenu, MenuDesc, MenuItem};
use druid::widget::{Align, Button, Column, Label, Padding, Row};
use druid::{
AppDelegate, AppLauncher, Command, Data, DelegateCtx, Env, Event, EventCtx, LocalizedString,
Selector, Widget, WindowDesc,
Selector, Widget, WindowDesc, WindowId,
};
use druid_shell::window::WinCtx;

use log::info;

const MENU_COUNT_ACTION: Selector = Selector::new("menu-count-action");
const MENU_INCREMENT_ACTION: Selector = Selector::new("menu-increment-action");
Expand Down Expand Up @@ -52,7 +55,7 @@ impl EventCtxExt for EventCtx<'_, '_> {
}
}

impl EventCtxExt for DelegateCtx<'_, '_> {
impl EventCtxExt for DelegateCtx<'_> {
fn set_menu<T: 'static>(&mut self, menu: MenuDesc<T>) {
let cmd = Command::new(druid::command::sys::SET_MENU, menu);
self.submit_command(cmd, None);
Expand Down Expand Up @@ -90,6 +93,7 @@ impl AppDelegate<State> for Delegate {
data: &mut State,
_env: &Env,
ctx: &mut DelegateCtx,
_win_ctx: &mut dyn WinCtx,
) -> Option<Event> {
match event {
Event::Command(ref cmd) if cmd.selector == druid::command::sys::NEW_FILE => {
Expand Down Expand Up @@ -126,6 +130,24 @@ impl AppDelegate<State> for Delegate {
other => Some(other),
}
}
fn window_added(
&mut self,
id: WindowId,
_data: &mut State,
_env: &Env,
_ctx: &mut DelegateCtx,
) {
info!("Window added, id: {:?}", id);
}
fn window_removed(
&mut self,
id: WindowId,
_data: &mut State,
_env: &Env,
_ctx: &mut DelegateCtx,
) {
info!("Window removed, id: {:?}", id);
}
}

#[allow(unused_assignments)]
Expand Down
29 changes: 16 additions & 13 deletions druid/src/app_delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,13 @@ use std::collections::VecDeque;
use crate::{Command, Data, Env, Event, WinCtx, WindowId};

/// A context passed in to [`AppDelegate`] functions.
pub struct DelegateCtx<'a, 'b> {
pub struct DelegateCtx<'a> {
pub(crate) source_id: WindowId,
pub(crate) command_queue: &'a mut VecDeque<(WindowId, Command)>,
pub(crate) win_ctx: &'a mut dyn WinCtx<'b>,
// pub(crate) win_ctx: &'a mut dyn WinCtx<'b>,
}

impl<'a, 'b> DelegateCtx<'a, 'b> {
/// Get the [`WinCtx`].
///
/// [`WinCtx`] trait.WinCtx.html
pub fn win_ctx(&self) -> &dyn WinCtx<'b> {
self.win_ctx
}

impl<'a> DelegateCtx<'a> {
/// Submit a [`Command`] to be run after this event is handled.
///
/// Commands are run in the order they are submitted; all commands
Expand All @@ -49,27 +42,37 @@ impl<'a, 'b> DelegateCtx<'a, 'b> {

/// A type that provides hooks for handling and modifying top-level events.
///
/// The `AppDelegate` is a struct that is allowed to handle and modify
/// The `AppDelegate` is a trait that is allowed to handle and modify
/// events before they are passed down the widget tree.
///
/// It is a natural place for things like window and menu management.
///
/// You customize the `AppDelegate` by passing closures during creation.
/// You customize the `AppDelegate` by implementing its methods on your own type.
#[allow(unused)]
pub trait AppDelegate<T: Data> {
/// The `AppDelegate`'s event handler. This function receives all events,
/// before they are passed down the tree.
///
/// The return value of this function will be passed down the tree. This can
/// be the even that was passed in, a different event, or no event. In all cases,
/// the `update` method will be called as usual.
#[allow(unused)]
fn event(
&mut self,
event: Event,
data: &mut T,
env: &Env,
ctx: &mut DelegateCtx,
win_ctx: &mut dyn WinCtx,
) -> Option<Event> {
Some(event)
}

/// The handler for window creation events.
/// This function is called after a window has been added,
/// allowing you to customize the window creation behavior of your app.
fn window_added(&mut self, id: WindowId, data: &mut T, env: &Env, ctx: &mut DelegateCtx) {}

/// The handler for window deletion events.
/// This function is called after a window has been removed.
fn window_removed(&mut self, id: WindowId, data: &mut T, env: &Env, ctx: &mut DelegateCtx) {}
}
33 changes: 30 additions & 3 deletions druid/src/win_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,16 +308,44 @@ impl<T: Data + 'static> AppState<T> {
.and_then(|w| w.get_menu_cmd(cmd_id))
}

fn with_delegate(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool, glad this worked 👍

&mut self,
id: WindowId,
f: impl Fn(&mut Box<dyn AppDelegate<T>>, &mut T, &Env, &mut DelegateCtx),
) {
let AppState {
ref mut delegate,
ref mut command_queue,
ref mut data,
ref env,
..
} = self;
let mut ctx = DelegateCtx {
source_id: id,
command_queue,
};
if let Some(delegate) = delegate {
f(delegate, data, env, &mut ctx);
}
}

fn connect(&mut self, id: WindowId, handle: WindowHandle) {
self.windows.connect(id, handle);
self.with_delegate(id, |del, data, env, ctx| {
del.window_added(id, data, env, ctx)
});
}

pub(crate) fn add_window(&mut self, id: WindowId, window: Window<T>) {
self.windows.add(id, window);
}

fn remove_window(&mut self, id: WindowId) -> Option<WindowHandle> {
self.windows.remove(id)
let res = self.windows.remove(id);
self.with_delegate(id, |del, data, env, ctx| {
del.window_added(id, data, env, ctx)
});
res
}

fn assemble_window_state(&mut self, window_id: WindowId) -> Option<SingleWindowState<'_, T>> {
Expand Down Expand Up @@ -414,9 +442,8 @@ impl<T: Data + 'static> AppState<T> {
let mut ctx = DelegateCtx {
source_id,
command_queue,
win_ctx,
};
delegate.event(event, data, env, &mut ctx)
delegate.event(event, data, env, &mut ctx, win_ctx)
}
None => Some(event),
}
Expand Down