Fixed widget animations implementation
This commit is contained in:
parent
3c095aa3f0
commit
8da098330b
4 changed files with 95 additions and 39 deletions
|
|
@ -499,18 +499,17 @@ fn view_content<'a>(
|
||||||
.spacing(10)
|
.spacing(10)
|
||||||
.align_items(Alignment::Center);
|
.align_items(Alignment::Center);
|
||||||
|
|
||||||
Element::from(
|
container(
|
||||||
container(
|
scrollable(content)
|
||||||
scrollable(content)
|
.height(Length::Fill)
|
||||||
.vertical_scroll(Properties::new())
|
.vertical_scroll(Properties::new())
|
||||||
.id(scrollable_id),
|
.id(scrollable_id),
|
||||||
)
|
|
||||||
.width(Length::Fill)
|
|
||||||
.height(Length::Fill)
|
|
||||||
.padding(5)
|
|
||||||
.center_y(),
|
|
||||||
)
|
)
|
||||||
.explain(Color::default())
|
.width(Length::Fill)
|
||||||
|
.height(Length::Fill)
|
||||||
|
.padding(5)
|
||||||
|
.center_y()
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_controls<'a>(
|
fn view_controls<'a>(
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ impl Tree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reconciliates the children of the tree with the provided list of widgets.
|
/// Reconciles the children of the tree with the provided list of widgets.
|
||||||
pub fn diff_children<'a, Message, Renderer>(
|
pub fn diff_children<'a, Message, Renderer>(
|
||||||
&mut self,
|
&mut self,
|
||||||
new_children: &[impl Borrow<dyn Widget<Message, Renderer> + 'a>],
|
new_children: &[impl Borrow<dyn Widget<Message, Renderer> + 'a>],
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ 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.
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ 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::conversion;
|
||||||
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,
|
||||||
|
|
@ -237,7 +237,8 @@ where
|
||||||
|
|
||||||
let (compositor, renderer) = C::new(compositor_settings, Some(&window))?;
|
let (compositor, renderer) = C::new(compositor_settings, Some(&window))?;
|
||||||
|
|
||||||
let (mut sender, receiver) = mpsc::unbounded();
|
let (mut event_sender, event_receiver) = mpsc::unbounded();
|
||||||
|
let (control_sender, mut control_receiver) = mpsc::unbounded();
|
||||||
|
|
||||||
let mut instance = Box::pin({
|
let mut instance = Box::pin({
|
||||||
let run_instance = run_instance::<A, E, C>(
|
let run_instance = run_instance::<A, E, C>(
|
||||||
|
|
@ -247,7 +248,8 @@ where
|
||||||
runtime,
|
runtime,
|
||||||
proxy,
|
proxy,
|
||||||
debug,
|
debug,
|
||||||
receiver,
|
event_receiver,
|
||||||
|
control_sender,
|
||||||
init_command,
|
init_command,
|
||||||
windows,
|
windows,
|
||||||
settings.exit_on_close_request,
|
settings.exit_on_close_request,
|
||||||
|
|
@ -299,13 +301,19 @@ where
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(event) = event {
|
if let Some(event) = event {
|
||||||
sender.start_send(event).expect("Send event");
|
event_sender.start_send(event).expect("Send event");
|
||||||
|
|
||||||
let poll = instance.as_mut().poll(&mut context);
|
let poll = instance.as_mut().poll(&mut context);
|
||||||
|
|
||||||
*control_flow = match poll {
|
match poll {
|
||||||
task::Poll::Pending => ControlFlow::Wait,
|
task::Poll::Pending => {
|
||||||
task::Poll::Ready(_) => ControlFlow::Exit,
|
if let Ok(Some(flow)) = control_receiver.try_next() {
|
||||||
|
*control_flow = flow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
task::Poll::Ready(_) => {
|
||||||
|
*control_flow = ControlFlow::Exit;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -318,9 +326,10 @@ async fn run_instance<A, E, C>(
|
||||||
mut runtime: Runtime<E, Proxy<Event<A::Message>>, Event<A::Message>>,
|
mut runtime: Runtime<E, Proxy<Event<A::Message>>, Event<A::Message>>,
|
||||||
mut proxy: winit::event_loop::EventLoopProxy<Event<A::Message>>,
|
mut proxy: winit::event_loop::EventLoopProxy<Event<A::Message>>,
|
||||||
mut debug: Debug,
|
mut debug: Debug,
|
||||||
mut receiver: mpsc::UnboundedReceiver<
|
mut event_receiver: mpsc::UnboundedReceiver<
|
||||||
winit::event::Event<'_, Event<A::Message>>,
|
winit::event::Event<'_, Event<A::Message>>,
|
||||||
>,
|
>,
|
||||||
|
mut control_sender: mpsc::UnboundedSender<winit::event_loop::ControlFlow>,
|
||||||
init_command: Command<A::Message>,
|
init_command: Command<A::Message>,
|
||||||
mut windows: HashMap<window::Id, winit::window::Window>,
|
mut windows: HashMap<window::Id, winit::window::Window>,
|
||||||
_exit_on_close_request: bool,
|
_exit_on_close_request: bool,
|
||||||
|
|
@ -332,6 +341,7 @@ async fn run_instance<A, E, C>(
|
||||||
{
|
{
|
||||||
use iced_futures::futures::stream::StreamExt;
|
use iced_futures::futures::stream::StreamExt;
|
||||||
use winit::event;
|
use winit::event;
|
||||||
|
use winit::event_loop::ControlFlow;
|
||||||
|
|
||||||
let mut clipboard =
|
let mut clipboard =
|
||||||
Clipboard::connect(windows.values().next().expect("No window found"));
|
Clipboard::connect(windows.values().next().expect("No window found"));
|
||||||
|
|
@ -390,11 +400,20 @@ async fn run_instance<A, E, C>(
|
||||||
let mut mouse_interaction = mouse::Interaction::default();
|
let mut mouse_interaction = mouse::Interaction::default();
|
||||||
let mut events = Vec::new();
|
let mut events = Vec::new();
|
||||||
let mut messages = Vec::new();
|
let mut messages = Vec::new();
|
||||||
|
let mut redraw_pending = false;
|
||||||
|
|
||||||
debug.startup_finished();
|
debug.startup_finished();
|
||||||
|
|
||||||
'main: while let Some(event) = receiver.next().await {
|
'main: while let Some(event) = event_receiver.next().await {
|
||||||
match event {
|
match event {
|
||||||
|
event::Event::NewEvents(start_cause) => {
|
||||||
|
redraw_pending = matches!(
|
||||||
|
start_cause,
|
||||||
|
event::StartCause::Init
|
||||||
|
| event::StartCause::Poll
|
||||||
|
| event::StartCause::ResumeTimeReached { .. }
|
||||||
|
);
|
||||||
|
}
|
||||||
event::Event::MainEventsCleared => {
|
event::Event::MainEventsCleared => {
|
||||||
for id in states.keys().copied().collect::<Vec<_>>() {
|
for id in states.keys().copied().collect::<Vec<_>>() {
|
||||||
let (filtered, remaining): (Vec<_>, Vec<_>) =
|
let (filtered, remaining): (Vec<_>, Vec<_>) =
|
||||||
|
|
@ -408,29 +427,27 @@ async fn run_instance<A, E, C>(
|
||||||
);
|
);
|
||||||
|
|
||||||
events.retain(|el| remaining.contains(el));
|
events.retain(|el| remaining.contains(el));
|
||||||
let mut filtered: Vec<_> = filtered
|
let window_events: Vec<_> = filtered
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_id, event)| event)
|
.map(|(_id, event)| event)
|
||||||
.collect();
|
.collect();
|
||||||
filtered.push(iced_native::Event::Window(
|
|
||||||
id,
|
|
||||||
window::Event::RedrawRequested(Instant::now()),
|
|
||||||
));
|
|
||||||
|
|
||||||
let cursor_position =
|
if !redraw_pending
|
||||||
states.get(&id).unwrap().cursor_position();
|
&& window_events.is_empty()
|
||||||
let window = windows.get(&id).unwrap();
|
&& messages.is_empty()
|
||||||
|
{
|
||||||
if filtered.is_empty() && messages.is_empty() {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.event_processing_started();
|
debug.event_processing_started();
|
||||||
|
|
||||||
|
let cursor_position =
|
||||||
|
states.get(&id).unwrap().cursor_position();
|
||||||
|
|
||||||
let (interface_state, statuses) = {
|
let (interface_state, statuses) = {
|
||||||
let user_interface = interfaces.get_mut(&id).unwrap();
|
let user_interface = interfaces.get_mut(&id).unwrap();
|
||||||
user_interface.update(
|
user_interface.update(
|
||||||
&filtered,
|
&window_events,
|
||||||
cursor_position,
|
cursor_position,
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
&mut clipboard,
|
&mut clipboard,
|
||||||
|
|
@ -440,7 +457,8 @@ async fn run_instance<A, E, C>(
|
||||||
|
|
||||||
debug.event_processing_finished();
|
debug.event_processing_finished();
|
||||||
|
|
||||||
for event in filtered.into_iter().zip(statuses.into_iter())
|
for event in
|
||||||
|
window_events.into_iter().zip(statuses.into_iter())
|
||||||
{
|
{
|
||||||
runtime.broadcast(event);
|
runtime.broadcast(event);
|
||||||
}
|
}
|
||||||
|
|
@ -487,8 +505,6 @@ async fn run_instance<A, E, C>(
|
||||||
windows.get(&id).expect("No window found with ID."),
|
windows.get(&id).expect("No window found with ID."),
|
||||||
);
|
);
|
||||||
|
|
||||||
let should_exit = application.should_exit();
|
|
||||||
|
|
||||||
interfaces = ManuallyDrop::new(build_user_interfaces(
|
interfaces = ManuallyDrop::new(build_user_interfaces(
|
||||||
&application,
|
&application,
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
|
|
@ -497,17 +513,35 @@ async fn run_instance<A, E, C>(
|
||||||
user_interfaces,
|
user_interfaces,
|
||||||
));
|
));
|
||||||
|
|
||||||
if should_exit {
|
if application.should_exit() {
|
||||||
break 'main;
|
break 'main;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Avoid redrawing all the time by forcing widgets to
|
||||||
|
// request redraws on state changes
|
||||||
|
//
|
||||||
|
// Then, we can use the `interface_state` here to decide if a redraw
|
||||||
|
// is needed right away, or simply wait until a specific time.
|
||||||
|
let redraw_event = iced_native::Event::Window(
|
||||||
|
id,
|
||||||
|
window::Event::RedrawRequested(Instant::now()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let (interface_state, _) =
|
||||||
|
interfaces.get_mut(&id).unwrap().update(
|
||||||
|
&[redraw_event.clone()],
|
||||||
|
cursor_position,
|
||||||
|
&mut renderer,
|
||||||
|
&mut clipboard,
|
||||||
|
&mut messages,
|
||||||
|
);
|
||||||
|
|
||||||
debug.draw_started();
|
debug.draw_started();
|
||||||
let new_mouse_interaction = {
|
let new_mouse_interaction = {
|
||||||
let user_interface = interfaces.get_mut(&id).unwrap();
|
|
||||||
let state = states.get(&id).unwrap();
|
let state = states.get(&id).unwrap();
|
||||||
|
|
||||||
user_interface.draw(
|
interfaces.get_mut(&id).unwrap().draw(
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
state.theme(),
|
state.theme(),
|
||||||
&renderer::Style {
|
&renderer::Style {
|
||||||
|
|
@ -518,6 +552,8 @@ async fn run_instance<A, E, C>(
|
||||||
};
|
};
|
||||||
debug.draw_finished();
|
debug.draw_finished();
|
||||||
|
|
||||||
|
let window = windows.get(&id).unwrap();
|
||||||
|
|
||||||
if new_mouse_interaction != mouse_interaction {
|
if new_mouse_interaction != mouse_interaction {
|
||||||
window.set_cursor_icon(conversion::mouse_interaction(
|
window.set_cursor_icon(conversion::mouse_interaction(
|
||||||
new_mouse_interaction,
|
new_mouse_interaction,
|
||||||
|
|
@ -528,6 +564,28 @@ async fn run_instance<A, E, C>(
|
||||||
|
|
||||||
for window in windows.values() {
|
for window in windows.values() {
|
||||||
window.request_redraw();
|
window.request_redraw();
|
||||||
|
|
||||||
|
runtime.broadcast((
|
||||||
|
redraw_event.clone(),
|
||||||
|
crate::event::Status::Ignored,
|
||||||
|
));
|
||||||
|
|
||||||
|
let _ =
|
||||||
|
control_sender.start_send(match interface_state {
|
||||||
|
user_interface::State::Updated {
|
||||||
|
redraw_request: Some(redraw_request),
|
||||||
|
} => match redraw_request {
|
||||||
|
window::RedrawRequest::NextFrame => {
|
||||||
|
ControlFlow::Poll
|
||||||
|
}
|
||||||
|
window::RedrawRequest::At(at) => {
|
||||||
|
ControlFlow::WaitUntil(at)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => ControlFlow::Wait,
|
||||||
|
});
|
||||||
|
|
||||||
|
redraw_pending = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue