Widget operations for multi-window.
This commit is contained in:
parent
367fea5dc8
commit
64e0e817c2
4 changed files with 169 additions and 113 deletions
|
|
@ -12,6 +12,7 @@ use iced::{Color, Command, Element, Length, Settings, Size, Subscription};
|
||||||
use iced_lazy::responsive;
|
use iced_lazy::responsive;
|
||||||
use iced_native::{event, subscription, Event};
|
use iced_native::{event, subscription, Event};
|
||||||
|
|
||||||
|
use iced_native::widget::scrollable::{Properties, RelativeOffset};
|
||||||
use iced_native::window::Id;
|
use iced_native::window::Id;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
|
@ -56,6 +57,7 @@ enum WindowMessage {
|
||||||
CloseFocused,
|
CloseFocused,
|
||||||
SelectedWindow(pane_grid::Pane, SelectableWindow),
|
SelectedWindow(pane_grid::Pane, SelectableWindow),
|
||||||
CloseWindow,
|
CloseWindow,
|
||||||
|
SnapToggle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Example {
|
impl Application for Example {
|
||||||
|
|
@ -94,6 +96,25 @@ impl Application for Example {
|
||||||
fn update(&mut self, message: Message) -> Command<Message> {
|
fn update(&mut self, message: Message) -> Command<Message> {
|
||||||
let Message::Window(id, message) = message;
|
let Message::Window(id, message) = message;
|
||||||
match message {
|
match message {
|
||||||
|
WindowMessage::SnapToggle => {
|
||||||
|
let window = self.windows.get_mut(&id).unwrap();
|
||||||
|
|
||||||
|
if let Some(focused) = &window.focus {
|
||||||
|
let pane = window.panes.get_mut(focused).unwrap();
|
||||||
|
|
||||||
|
let cmd = scrollable::snap_to(
|
||||||
|
pane.scrollable_id.clone(),
|
||||||
|
if pane.snapped {
|
||||||
|
RelativeOffset::START
|
||||||
|
} else {
|
||||||
|
RelativeOffset::END
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
pane.snapped = !pane.snapped;
|
||||||
|
return cmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
WindowMessage::Split(axis, pane) => {
|
WindowMessage::Split(axis, pane) => {
|
||||||
let window = self.windows.get_mut(&id).unwrap();
|
let window = self.windows.get_mut(&id).unwrap();
|
||||||
let result = window.panes.split(
|
let result = window.panes.split(
|
||||||
|
|
@ -311,7 +332,13 @@ impl Application for Example {
|
||||||
});
|
});
|
||||||
|
|
||||||
pane_grid::Content::new(responsive(move |size| {
|
pane_grid::Content::new(responsive(move |size| {
|
||||||
view_content(id, total_panes, pane.is_pinned, size)
|
view_content(
|
||||||
|
id,
|
||||||
|
pane.scrollable_id.clone(),
|
||||||
|
total_panes,
|
||||||
|
pane.is_pinned,
|
||||||
|
size,
|
||||||
|
)
|
||||||
}))
|
}))
|
||||||
.title_bar(title_bar)
|
.title_bar(title_bar)
|
||||||
.style(if is_focused {
|
.style(if is_focused {
|
||||||
|
|
@ -403,24 +430,29 @@ impl std::fmt::Display for SelectableWindow {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Pane {
|
struct Pane {
|
||||||
id: usize,
|
id: usize,
|
||||||
|
pub scrollable_id: scrollable::Id,
|
||||||
pub axis: pane_grid::Axis,
|
pub axis: pane_grid::Axis,
|
||||||
pub is_pinned: bool,
|
pub is_pinned: bool,
|
||||||
pub is_moving: bool,
|
pub is_moving: bool,
|
||||||
|
pub snapped: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pane {
|
impl Pane {
|
||||||
fn new(id: usize, axis: pane_grid::Axis) -> Self {
|
fn new(id: usize, axis: pane_grid::Axis) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
|
scrollable_id: scrollable::Id::new(format!("{:?}", id)),
|
||||||
axis,
|
axis,
|
||||||
is_pinned: false,
|
is_pinned: false,
|
||||||
is_moving: false,
|
is_moving: false,
|
||||||
|
snapped: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_content<'a>(
|
fn view_content<'a>(
|
||||||
pane: pane_grid::Pane,
|
pane: pane_grid::Pane,
|
||||||
|
scrollable_id: scrollable::Id,
|
||||||
total_panes: usize,
|
total_panes: usize,
|
||||||
is_pinned: bool,
|
is_pinned: bool,
|
||||||
size: Size,
|
size: Size,
|
||||||
|
|
@ -445,7 +477,8 @@ fn view_content<'a>(
|
||||||
button(
|
button(
|
||||||
"Split vertically",
|
"Split vertically",
|
||||||
WindowMessage::Split(pane_grid::Axis::Vertical, pane),
|
WindowMessage::Split(pane_grid::Axis::Vertical, pane),
|
||||||
)
|
),
|
||||||
|
button("Snap", WindowMessage::SnapToggle,)
|
||||||
]
|
]
|
||||||
.spacing(5)
|
.spacing(5)
|
||||||
.max_width(150);
|
.max_width(150);
|
||||||
|
|
@ -462,15 +495,22 @@ fn view_content<'a>(
|
||||||
controls,
|
controls,
|
||||||
]
|
]
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
|
.height(Length::Units(800))
|
||||||
.spacing(10)
|
.spacing(10)
|
||||||
.align_items(Alignment::Center);
|
.align_items(Alignment::Center);
|
||||||
|
|
||||||
container(scrollable(content))
|
Element::from(
|
||||||
|
container(
|
||||||
|
scrollable(content)
|
||||||
|
.vertical_scroll(Properties::new())
|
||||||
|
.id(scrollable_id),
|
||||||
|
)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
.padding(5)
|
.padding(5)
|
||||||
.center_y()
|
.center_y(),
|
||||||
.into()
|
)
|
||||||
|
.explain(Color::default())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_controls<'a>(
|
fn view_controls<'a>(
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ use std::num::NonZeroU32;
|
||||||
|
|
||||||
#[cfg(feature = "tracing")]
|
#[cfg(feature = "tracing")]
|
||||||
use tracing::{info_span, instrument::Instrument};
|
use tracing::{info_span, instrument::Instrument};
|
||||||
|
use iced_native::widget::operation;
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
const ONE: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(1) };
|
const ONE: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(1) };
|
||||||
|
|
@ -294,7 +295,7 @@ where
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(feature = "tracing")]
|
#[cfg(feature = "tracing")]
|
||||||
let run_instance =
|
let run_instance =
|
||||||
run_instance.instrument(info_span!("Application", "LOOP"));
|
run_instance.instrument(info_span!("Application", "LOOP"));
|
||||||
|
|
||||||
run_instance
|
run_instance
|
||||||
|
|
@ -380,7 +381,7 @@ async fn run_instance<A, E, C>(
|
||||||
|
|
||||||
let mut clipboard =
|
let mut clipboard =
|
||||||
Clipboard::connect(windows.values().next().expect("No window found"));
|
Clipboard::connect(windows.values().next().expect("No window found"));
|
||||||
let mut cache = user_interface::Cache::default();
|
let mut caches = HashMap::new();
|
||||||
let mut current_context_window = None;
|
let mut current_context_window = None;
|
||||||
let mut window_ids: HashMap<_, _> = windows
|
let mut window_ids: HashMap<_, _> = windows
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -422,23 +423,20 @@ async fn run_instance<A, E, C>(
|
||||||
let _ = interfaces.insert(id, user_interface);
|
let _ = interfaces.insert(id, user_interface);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
run_command(
|
||||||
let state = states.values().next().expect("No state found.");
|
&application,
|
||||||
|
&mut caches,
|
||||||
|
&states,
|
||||||
|
&mut renderer,
|
||||||
|
init_command,
|
||||||
|
&mut runtime,
|
||||||
|
&mut clipboard,
|
||||||
|
&mut proxy,
|
||||||
|
&mut debug,
|
||||||
|
&windows,
|
||||||
|
|| compositor.fetch_information(),
|
||||||
|
);
|
||||||
|
|
||||||
run_command(
|
|
||||||
&application,
|
|
||||||
&mut cache,
|
|
||||||
state,
|
|
||||||
&mut renderer,
|
|
||||||
init_command,
|
|
||||||
&mut runtime,
|
|
||||||
&mut clipboard,
|
|
||||||
&mut proxy,
|
|
||||||
&mut debug,
|
|
||||||
&windows,
|
|
||||||
|| compositor.fetch_information(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
runtime.track(application.subscription().map(Event::Application));
|
runtime.track(application.subscription().map(Event::Application));
|
||||||
|
|
||||||
let mut mouse_interaction = mouse::Interaction::default();
|
let mut mouse_interaction = mouse::Interaction::default();
|
||||||
|
|
@ -501,8 +499,7 @@ async fn run_instance<A, E, C>(
|
||||||
user_interface::State::Outdated
|
user_interface::State::Outdated
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
let state = &mut states.get_mut(&id).unwrap();
|
let user_interfaces: HashMap<_, _> =
|
||||||
let pure_states: HashMap<_, _> =
|
|
||||||
ManuallyDrop::into_inner(interfaces)
|
ManuallyDrop::into_inner(interfaces)
|
||||||
.drain()
|
.drain()
|
||||||
.map(|(id, interface)| {
|
.map(|(id, interface)| {
|
||||||
|
|
@ -513,8 +510,8 @@ async fn run_instance<A, E, C>(
|
||||||
// Update application
|
// Update application
|
||||||
update(
|
update(
|
||||||
&mut application,
|
&mut application,
|
||||||
&mut cache,
|
&mut caches,
|
||||||
state,
|
&states,
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
&mut runtime,
|
&mut runtime,
|
||||||
&mut clipboard,
|
&mut clipboard,
|
||||||
|
|
@ -526,7 +523,7 @@ async fn run_instance<A, E, C>(
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update window
|
// Update window
|
||||||
state.synchronize(
|
states.get_mut(&id).unwrap().synchronize(
|
||||||
&application,
|
&application,
|
||||||
id,
|
id,
|
||||||
windows.get(&id).expect("No window found with ID."),
|
windows.get(&id).expect("No window found with ID."),
|
||||||
|
|
@ -539,7 +536,7 @@ async fn run_instance<A, E, C>(
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
&mut debug,
|
&mut debug,
|
||||||
&states,
|
&states,
|
||||||
pure_states,
|
user_interfaces,
|
||||||
));
|
));
|
||||||
|
|
||||||
if should_exit {
|
if should_exit {
|
||||||
|
|
@ -590,7 +587,8 @@ async fn run_instance<A, E, C>(
|
||||||
event::Event::UserEvent(event) => match event {
|
event::Event::UserEvent(event) => match event {
|
||||||
Event::Application(message) => messages.push(message),
|
Event::Application(message) => messages.push(message),
|
||||||
Event::WindowCreated(id, window) => {
|
Event::WindowCreated(id, window) => {
|
||||||
let state = multi_window::State::new(&application, id, &window);
|
let state =
|
||||||
|
multi_window::State::new(&application, id, &window);
|
||||||
let user_interface = multi_window::build_user_interface(
|
let user_interface = multi_window::build_user_interface(
|
||||||
&application,
|
&application,
|
||||||
user_interface::Cache::default(),
|
user_interface::Cache::default(),
|
||||||
|
|
@ -768,7 +766,10 @@ async fn run_instance<A, E, C>(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::error!("Window state not found for id: {:?}", window_id);
|
log::error!(
|
||||||
|
"Window state not found for id: {:?}",
|
||||||
|
window_id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::error!("Window not found for id: {:?}", window_id);
|
log::error!("Window not found for id: {:?}", window_id);
|
||||||
|
|
@ -786,8 +787,8 @@ async fn run_instance<A, E, C>(
|
||||||
/// resulting [`Command`], and tracking its [`Subscription`].
|
/// resulting [`Command`], and tracking its [`Subscription`].
|
||||||
pub fn update<A: Application, E: Executor>(
|
pub fn update<A: Application, E: Executor>(
|
||||||
application: &mut A,
|
application: &mut A,
|
||||||
cache: &mut user_interface::Cache,
|
caches: &mut HashMap<window::Id, user_interface::Cache>,
|
||||||
state: &multi_window::State<A>,
|
states: &HashMap<window::Id, multi_window::State<A>>,
|
||||||
renderer: &mut A::Renderer,
|
renderer: &mut A::Renderer,
|
||||||
runtime: &mut Runtime<E, Proxy<Event<A::Message>>, Event<A::Message>>,
|
runtime: &mut Runtime<E, Proxy<Event<A::Message>>, Event<A::Message>>,
|
||||||
clipboard: &mut Clipboard,
|
clipboard: &mut Clipboard,
|
||||||
|
|
@ -797,6 +798,7 @@ pub fn update<A: Application, E: Executor>(
|
||||||
windows: &HashMap<window::Id, winit::window::Window>,
|
windows: &HashMap<window::Id, winit::window::Window>,
|
||||||
graphics_info: impl FnOnce() -> iced_graphics::compositor::Information + Copy,
|
graphics_info: impl FnOnce() -> iced_graphics::compositor::Information + Copy,
|
||||||
) where
|
) where
|
||||||
|
A: Application + 'static,
|
||||||
<A::Renderer as crate::Renderer>::Theme: StyleSheet,
|
<A::Renderer as crate::Renderer>::Theme: StyleSheet,
|
||||||
{
|
{
|
||||||
for message in messages.drain(..) {
|
for message in messages.drain(..) {
|
||||||
|
|
@ -808,8 +810,8 @@ pub fn update<A: Application, E: Executor>(
|
||||||
|
|
||||||
run_command(
|
run_command(
|
||||||
application,
|
application,
|
||||||
cache,
|
caches,
|
||||||
state,
|
&states,
|
||||||
renderer,
|
renderer,
|
||||||
command,
|
command,
|
||||||
runtime,
|
runtime,
|
||||||
|
|
@ -828,8 +830,8 @@ pub fn update<A: Application, E: Executor>(
|
||||||
/// Runs the actions of a [`Command`].
|
/// Runs the actions of a [`Command`].
|
||||||
pub fn run_command<A, E>(
|
pub fn run_command<A, E>(
|
||||||
application: &A,
|
application: &A,
|
||||||
cache: &mut user_interface::Cache,
|
caches: &mut HashMap<window::Id, user_interface::Cache>,
|
||||||
state: &multi_window::State<A>,
|
states: &HashMap<window::Id, multi_window::State<A>>,
|
||||||
renderer: &mut A::Renderer,
|
renderer: &mut A::Renderer,
|
||||||
command: Command<A::Message>,
|
command: Command<A::Message>,
|
||||||
runtime: &mut Runtime<E, Proxy<Event<A::Message>>, Event<A::Message>>,
|
runtime: &mut Runtime<E, Proxy<Event<A::Message>>, Event<A::Message>>,
|
||||||
|
|
@ -839,7 +841,7 @@ pub fn run_command<A, E>(
|
||||||
windows: &HashMap<window::Id, winit::window::Window>,
|
windows: &HashMap<window::Id, winit::window::Window>,
|
||||||
_graphics_info: impl FnOnce() -> iced_graphics::compositor::Information + Copy,
|
_graphics_info: impl FnOnce() -> iced_graphics::compositor::Information + Copy,
|
||||||
) where
|
) where
|
||||||
A: Application,
|
A: Application + 'static,
|
||||||
E: Executor,
|
E: Executor,
|
||||||
<A::Renderer as crate::Renderer>::Theme: StyleSheet,
|
<A::Renderer as crate::Renderer>::Theme: StyleSheet,
|
||||||
{
|
{
|
||||||
|
|
@ -967,38 +969,42 @@ pub fn run_command<A, E>(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
command::Action::Widget(action) => {
|
command::Action::Widget(action) => {
|
||||||
use crate::widget::operation;
|
let mut current_caches = std::mem::take(caches);
|
||||||
|
|
||||||
let mut current_cache = std::mem::take(cache);
|
|
||||||
let mut current_operation = Some(action.into_operation());
|
let mut current_operation = Some(action.into_operation());
|
||||||
|
|
||||||
let mut user_interface = multi_window::build_user_interface(
|
let mut user_interfaces = multi_window::build_user_interfaces(
|
||||||
application,
|
application,
|
||||||
current_cache,
|
|
||||||
renderer,
|
renderer,
|
||||||
state.logical_size(),
|
|
||||||
debug,
|
debug,
|
||||||
window::Id::MAIN, // TODO(derezzedex): run the operation on every widget tree
|
states,
|
||||||
|
current_caches,
|
||||||
);
|
);
|
||||||
|
|
||||||
while let Some(mut operation) = current_operation.take() {
|
while let Some(mut operation) = current_operation.take() {
|
||||||
user_interface.operate(renderer, operation.as_mut());
|
for user_interface in user_interfaces.values_mut() {
|
||||||
|
user_interface.operate(renderer, operation.as_mut());
|
||||||
|
|
||||||
match operation.finish() {
|
match operation.finish() {
|
||||||
operation::Outcome::None => {}
|
operation::Outcome::None => {}
|
||||||
operation::Outcome::Some(message) => {
|
operation::Outcome::Some(message) => {
|
||||||
proxy
|
proxy
|
||||||
.send_event(Event::Application(message))
|
.send_event(Event::Application(message))
|
||||||
.expect("Send message to event loop");
|
.expect("Send message to event loop");
|
||||||
}
|
}
|
||||||
operation::Outcome::Chain(next) => {
|
operation::Outcome::Chain(next) => {
|
||||||
current_operation = Some(next);
|
current_operation = Some(next);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
current_cache = user_interface.into_cache();
|
let user_interfaces: HashMap<_, _> = user_interfaces
|
||||||
*cache = current_cache;
|
.drain()
|
||||||
|
.map(|(id, interface)| (id, interface.into_cache()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
current_caches = user_interfaces;
|
||||||
|
*caches = current_caches;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1010,7 +1016,7 @@ pub fn build_user_interfaces<'a, A>(
|
||||||
renderer: &mut A::Renderer,
|
renderer: &mut A::Renderer,
|
||||||
debug: &mut Debug,
|
debug: &mut Debug,
|
||||||
states: &HashMap<window::Id, multi_window::State<A>>,
|
states: &HashMap<window::Id, multi_window::State<A>>,
|
||||||
mut pure_states: HashMap<window::Id, user_interface::Cache>,
|
mut user_interfaces: HashMap<window::Id, user_interface::Cache>,
|
||||||
) -> HashMap<
|
) -> HashMap<
|
||||||
window::Id,
|
window::Id,
|
||||||
iced_winit::UserInterface<
|
iced_winit::UserInterface<
|
||||||
|
|
@ -1025,7 +1031,7 @@ where
|
||||||
{
|
{
|
||||||
let mut interfaces = HashMap::new();
|
let mut interfaces = HashMap::new();
|
||||||
|
|
||||||
for (id, pure_state) in pure_states.drain() {
|
for (id, pure_state) in user_interfaces.drain() {
|
||||||
let state = &states.get(&id).unwrap();
|
let state = &states.get(&id).unwrap();
|
||||||
|
|
||||||
let user_interface = multi_window::build_user_interface(
|
let user_interface = multi_window::build_user_interface(
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ pub use user_attention::UserAttention;
|
||||||
|
|
||||||
use crate::subscription::{self, Subscription};
|
use crate::subscription::{self, Subscription};
|
||||||
use crate::time::Instant;
|
use crate::time::Instant;
|
||||||
|
use crate::window;
|
||||||
|
|
||||||
/// Subscribes to the frames of the window of the running application.
|
/// Subscribes to the frames of the window of the running application.
|
||||||
///
|
///
|
||||||
|
|
@ -42,6 +43,8 @@ pub fn frames() -> Subscription<Frame> {
|
||||||
/// The returned `Frame` for a framerate subscription.
|
/// The returned `Frame` for a framerate subscription.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Frame {
|
pub struct Frame {
|
||||||
|
/// The `window::Id` that the `Frame` was produced in.
|
||||||
pub id: Id,
|
pub id: Id,
|
||||||
|
/// The `Instant` at which the frame was produced.
|
||||||
pub at: Instant,
|
pub at: Instant,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ mod state;
|
||||||
pub use state::State;
|
pub use state::State;
|
||||||
|
|
||||||
use crate::clipboard::{self, Clipboard};
|
use crate::clipboard::{self, Clipboard};
|
||||||
use crate::conversion;
|
|
||||||
use crate::mouse;
|
use crate::mouse;
|
||||||
use crate::renderer;
|
use crate::renderer;
|
||||||
use crate::settings;
|
use crate::settings;
|
||||||
use crate::widget::operation;
|
use crate::widget::operation;
|
||||||
use crate::window;
|
use crate::window;
|
||||||
|
use crate::{conversion, multi_window};
|
||||||
use crate::{
|
use crate::{
|
||||||
Command, Debug, Element, Error, Executor, Proxy, Renderer, Runtime,
|
Command, Debug, Element, Error, Executor, Proxy, Renderer, Runtime,
|
||||||
Settings, Size, Subscription,
|
Settings, Size, Subscription,
|
||||||
|
|
@ -254,7 +254,7 @@ where
|
||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(feature = "trace")]
|
#[cfg(feature = "trace")]
|
||||||
let run_instance =
|
let run_instance =
|
||||||
run_instance.instrument(info_span!("Application", "LOOP"));
|
run_instance.instrument(info_span!("Application", "LOOP"));
|
||||||
|
|
||||||
run_instance
|
run_instance
|
||||||
|
|
@ -335,7 +335,7 @@ async fn run_instance<A, E, C>(
|
||||||
|
|
||||||
let mut clipboard =
|
let mut clipboard =
|
||||||
Clipboard::connect(windows.values().next().expect("No window found"));
|
Clipboard::connect(windows.values().next().expect("No window found"));
|
||||||
let mut cache = user_interface::Cache::default();
|
let mut caches = HashMap::new();
|
||||||
let mut window_ids: HashMap<_, _> = windows
|
let mut window_ids: HashMap<_, _> = windows
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(&id, window)| (window.id(), id))
|
.map(|(&id, window)| (window.id(), id))
|
||||||
|
|
@ -368,26 +368,23 @@ async fn run_instance<A, E, C>(
|
||||||
let _ = states.insert(id, state);
|
let _ = states.insert(id, state);
|
||||||
let _ = surfaces.insert(id, surface);
|
let _ = surfaces.insert(id, surface);
|
||||||
let _ = interfaces.insert(id, user_interface);
|
let _ = interfaces.insert(id, user_interface);
|
||||||
|
let _ = caches.insert(id, user_interface::Cache::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
run_command(
|
||||||
// TODO(derezzedex)
|
&application,
|
||||||
let state = states.values().next().expect("No state found");
|
&mut caches,
|
||||||
|
&states,
|
||||||
|
&mut renderer,
|
||||||
|
init_command,
|
||||||
|
&mut runtime,
|
||||||
|
&mut clipboard,
|
||||||
|
&mut proxy,
|
||||||
|
&mut debug,
|
||||||
|
&windows,
|
||||||
|
|| compositor.fetch_information(),
|
||||||
|
);
|
||||||
|
|
||||||
run_command(
|
|
||||||
&application,
|
|
||||||
&mut cache,
|
|
||||||
state,
|
|
||||||
&mut renderer,
|
|
||||||
init_command,
|
|
||||||
&mut runtime,
|
|
||||||
&mut clipboard,
|
|
||||||
&mut proxy,
|
|
||||||
&mut debug,
|
|
||||||
&windows,
|
|
||||||
|| compositor.fetch_information(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
runtime.track(application.subscription().map(Event::Application));
|
runtime.track(application.subscription().map(Event::Application));
|
||||||
|
|
||||||
let mut mouse_interaction = mouse::Interaction::default();
|
let mut mouse_interaction = mouse::Interaction::default();
|
||||||
|
|
@ -455,8 +452,7 @@ async fn run_instance<A, E, C>(
|
||||||
user_interface::State::Outdated,
|
user_interface::State::Outdated,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
let state = states.get_mut(&id).unwrap();
|
let user_interfaces: HashMap<_, _> =
|
||||||
let pure_states: HashMap<_, _> =
|
|
||||||
ManuallyDrop::into_inner(interfaces)
|
ManuallyDrop::into_inner(interfaces)
|
||||||
.drain()
|
.drain()
|
||||||
.map(
|
.map(
|
||||||
|
|
@ -472,8 +468,8 @@ async fn run_instance<A, E, C>(
|
||||||
// Update application
|
// Update application
|
||||||
update(
|
update(
|
||||||
&mut application,
|
&mut application,
|
||||||
&mut cache,
|
&mut caches,
|
||||||
state,
|
&states,
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
&mut runtime,
|
&mut runtime,
|
||||||
&mut clipboard,
|
&mut clipboard,
|
||||||
|
|
@ -485,7 +481,7 @@ async fn run_instance<A, E, C>(
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update window
|
// Update window
|
||||||
state.synchronize(
|
states.get_mut(&id).unwrap().synchronize(
|
||||||
&application,
|
&application,
|
||||||
id,
|
id,
|
||||||
windows.get(&id).expect("No window found with ID."),
|
windows.get(&id).expect("No window found with ID."),
|
||||||
|
|
@ -498,7 +494,7 @@ async fn run_instance<A, E, C>(
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
&mut debug,
|
&mut debug,
|
||||||
&states,
|
&states,
|
||||||
pure_states,
|
user_interfaces,
|
||||||
));
|
));
|
||||||
|
|
||||||
if should_exit {
|
if should_exit {
|
||||||
|
|
@ -579,6 +575,7 @@ async fn run_instance<A, E, C>(
|
||||||
let _ = interfaces.insert(id, user_interface);
|
let _ = interfaces.insert(id, user_interface);
|
||||||
let _ = window_ids.insert(window.id(), id);
|
let _ = window_ids.insert(window.id(), id);
|
||||||
let _ = windows.insert(id, window);
|
let _ = windows.insert(id, window);
|
||||||
|
let _ = caches.insert(id, user_interface::Cache::default());
|
||||||
}
|
}
|
||||||
Event::CloseWindow(id) => {
|
Event::CloseWindow(id) => {
|
||||||
if let Some(window) = windows.get(&id) {
|
if let Some(window) = windows.get(&id) {
|
||||||
|
|
@ -764,7 +761,10 @@ async fn run_instance<A, E, C>(
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::error!("No window state found for id: {:?}", window_id);
|
log::error!(
|
||||||
|
"No window state found for id: {:?}",
|
||||||
|
window_id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::error!("No window found with id: {:?}", window_id);
|
log::error!("No window found with id: {:?}", window_id);
|
||||||
|
|
@ -840,8 +840,8 @@ where
|
||||||
/// resulting [`Command`], and tracking its [`Subscription`].
|
/// resulting [`Command`], and tracking its [`Subscription`].
|
||||||
pub fn update<A: Application, E: Executor>(
|
pub fn update<A: Application, E: Executor>(
|
||||||
application: &mut A,
|
application: &mut A,
|
||||||
cache: &mut user_interface::Cache,
|
caches: &mut HashMap<window::Id, user_interface::Cache>,
|
||||||
state: &State<A>,
|
states: &HashMap<window::Id, State<A>>,
|
||||||
renderer: &mut A::Renderer,
|
renderer: &mut A::Renderer,
|
||||||
runtime: &mut Runtime<E, Proxy<Event<A::Message>>, Event<A::Message>>,
|
runtime: &mut Runtime<E, Proxy<Event<A::Message>>, Event<A::Message>>,
|
||||||
clipboard: &mut Clipboard,
|
clipboard: &mut Clipboard,
|
||||||
|
|
@ -851,6 +851,7 @@ pub fn update<A: Application, E: Executor>(
|
||||||
windows: &HashMap<window::Id, winit::window::Window>,
|
windows: &HashMap<window::Id, winit::window::Window>,
|
||||||
graphics_info: impl FnOnce() -> compositor::Information + Copy,
|
graphics_info: impl FnOnce() -> compositor::Information + Copy,
|
||||||
) where
|
) where
|
||||||
|
A: Application + 'static,
|
||||||
<A::Renderer as crate::Renderer>::Theme: StyleSheet,
|
<A::Renderer as crate::Renderer>::Theme: StyleSheet,
|
||||||
{
|
{
|
||||||
for message in messages.drain(..) {
|
for message in messages.drain(..) {
|
||||||
|
|
@ -867,8 +868,8 @@ pub fn update<A: Application, E: Executor>(
|
||||||
|
|
||||||
run_command(
|
run_command(
|
||||||
application,
|
application,
|
||||||
cache,
|
caches,
|
||||||
state,
|
states,
|
||||||
renderer,
|
renderer,
|
||||||
command,
|
command,
|
||||||
runtime,
|
runtime,
|
||||||
|
|
@ -887,8 +888,8 @@ pub fn update<A: Application, E: Executor>(
|
||||||
/// Runs the actions of a [`Command`].
|
/// Runs the actions of a [`Command`].
|
||||||
pub fn run_command<A, E>(
|
pub fn run_command<A, E>(
|
||||||
application: &A,
|
application: &A,
|
||||||
cache: &mut user_interface::Cache,
|
caches: &mut HashMap<window::Id, user_interface::Cache>,
|
||||||
state: &State<A>,
|
states: &HashMap<window::Id, State<A>>,
|
||||||
renderer: &mut A::Renderer,
|
renderer: &mut A::Renderer,
|
||||||
command: Command<A::Message>,
|
command: Command<A::Message>,
|
||||||
runtime: &mut Runtime<E, Proxy<Event<A::Message>>, Event<A::Message>>,
|
runtime: &mut Runtime<E, Proxy<Event<A::Message>>, Event<A::Message>>,
|
||||||
|
|
@ -898,7 +899,7 @@ pub fn run_command<A, E>(
|
||||||
windows: &HashMap<window::Id, winit::window::Window>,
|
windows: &HashMap<window::Id, winit::window::Window>,
|
||||||
_graphics_info: impl FnOnce() -> compositor::Information + Copy,
|
_graphics_info: impl FnOnce() -> compositor::Information + Copy,
|
||||||
) where
|
) where
|
||||||
A: Application,
|
A: Application + 'static,
|
||||||
E: Executor,
|
E: Executor,
|
||||||
<A::Renderer as crate::Renderer>::Theme: StyleSheet,
|
<A::Renderer as crate::Renderer>::Theme: StyleSheet,
|
||||||
{
|
{
|
||||||
|
|
@ -1024,36 +1025,42 @@ pub fn run_command<A, E>(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
command::Action::Widget(action) => {
|
command::Action::Widget(action) => {
|
||||||
let mut current_cache = std::mem::take(cache);
|
let mut current_caches = std::mem::take(caches);
|
||||||
let mut current_operation = Some(action.into_operation());
|
let mut current_operation = Some(action.into_operation());
|
||||||
|
|
||||||
let mut user_interface = build_user_interface(
|
let mut user_interfaces = build_user_interfaces(
|
||||||
application,
|
application,
|
||||||
current_cache,
|
|
||||||
renderer,
|
renderer,
|
||||||
state.logical_size(),
|
|
||||||
debug,
|
debug,
|
||||||
window::Id::MAIN, // TODO(derezzedex): run the operation on every widget tree
|
states,
|
||||||
|
current_caches,
|
||||||
);
|
);
|
||||||
|
|
||||||
while let Some(mut operation) = current_operation.take() {
|
while let Some(mut operation) = current_operation.take() {
|
||||||
user_interface.operate(renderer, operation.as_mut());
|
for user_interface in user_interfaces.values_mut() {
|
||||||
|
user_interface.operate(renderer, operation.as_mut());
|
||||||
|
|
||||||
match operation.finish() {
|
match operation.finish() {
|
||||||
operation::Outcome::None => {}
|
operation::Outcome::None => {}
|
||||||
operation::Outcome::Some(message) => {
|
operation::Outcome::Some(message) => {
|
||||||
proxy
|
proxy
|
||||||
.send_event(Event::Application(message))
|
.send_event(Event::Application(message))
|
||||||
.expect("Send message to event loop");
|
.expect("Send message to event loop");
|
||||||
}
|
}
|
||||||
operation::Outcome::Chain(next) => {
|
operation::Outcome::Chain(next) => {
|
||||||
current_operation = Some(next);
|
current_operation = Some(next);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
current_cache = user_interface.into_cache();
|
let user_interfaces: HashMap<_, _> = user_interfaces
|
||||||
*cache = current_cache;
|
.drain()
|
||||||
|
.map(|(id, interface)| (id, interface.into_cache()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
current_caches = user_interfaces;
|
||||||
|
*caches = current_caches;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1065,7 +1072,7 @@ pub fn build_user_interfaces<'a, A>(
|
||||||
renderer: &mut A::Renderer,
|
renderer: &mut A::Renderer,
|
||||||
debug: &mut Debug,
|
debug: &mut Debug,
|
||||||
states: &HashMap<window::Id, State<A>>,
|
states: &HashMap<window::Id, State<A>>,
|
||||||
mut pure_states: HashMap<window::Id, user_interface::Cache>,
|
mut cached_user_interfaces: HashMap<window::Id, user_interface::Cache>,
|
||||||
) -> HashMap<
|
) -> HashMap<
|
||||||
window::Id,
|
window::Id,
|
||||||
UserInterface<
|
UserInterface<
|
||||||
|
|
@ -1080,12 +1087,12 @@ where
|
||||||
{
|
{
|
||||||
let mut interfaces = HashMap::new();
|
let mut interfaces = HashMap::new();
|
||||||
|
|
||||||
for (id, pure_state) in pure_states.drain() {
|
for (id, cache) in cached_user_interfaces.drain() {
|
||||||
let state = &states.get(&id).unwrap();
|
let state = &states.get(&id).unwrap();
|
||||||
|
|
||||||
let user_interface = build_user_interface(
|
let user_interface = build_user_interface(
|
||||||
application,
|
application,
|
||||||
pure_state,
|
cache,
|
||||||
renderer,
|
renderer,
|
||||||
state.logical_size(),
|
state.logical_size(),
|
||||||
debug,
|
debug,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue