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)
|
||||
.align_items(Alignment::Center);
|
||||
|
||||
Element::from(
|
||||
container(
|
||||
scrollable(content)
|
||||
.height(Length::Fill)
|
||||
.vertical_scroll(Properties::new())
|
||||
.id(scrollable_id),
|
||||
)
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.padding(5)
|
||||
.center_y(),
|
||||
)
|
||||
.explain(Color::default())
|
||||
.center_y()
|
||||
.into()
|
||||
}
|
||||
|
||||
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>(
|
||||
&mut self,
|
||||
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::time::Instant;
|
||||
use crate::window;
|
||||
|
||||
/// Subscribes to the frames of the window of the running application.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use crate::renderer;
|
|||
use crate::settings;
|
||||
use crate::widget::operation;
|
||||
use crate::window;
|
||||
use crate::{conversion, multi_window};
|
||||
use crate::conversion;
|
||||
use crate::{
|
||||
Command, Debug, Element, Error, Executor, Proxy, Renderer, Runtime,
|
||||
Settings, Size, Subscription,
|
||||
|
|
@ -237,7 +237,8 @@ where
|
|||
|
||||
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 run_instance = run_instance::<A, E, C>(
|
||||
|
|
@ -247,7 +248,8 @@ where
|
|||
runtime,
|
||||
proxy,
|
||||
debug,
|
||||
receiver,
|
||||
event_receiver,
|
||||
control_sender,
|
||||
init_command,
|
||||
windows,
|
||||
settings.exit_on_close_request,
|
||||
|
|
@ -299,13 +301,19 @@ where
|
|||
};
|
||||
|
||||
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);
|
||||
|
||||
*control_flow = match poll {
|
||||
task::Poll::Pending => ControlFlow::Wait,
|
||||
task::Poll::Ready(_) => ControlFlow::Exit,
|
||||
match poll {
|
||||
task::Poll::Pending => {
|
||||
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 proxy: winit::event_loop::EventLoopProxy<Event<A::Message>>,
|
||||
mut debug: Debug,
|
||||
mut receiver: mpsc::UnboundedReceiver<
|
||||
mut event_receiver: mpsc::UnboundedReceiver<
|
||||
winit::event::Event<'_, Event<A::Message>>,
|
||||
>,
|
||||
mut control_sender: mpsc::UnboundedSender<winit::event_loop::ControlFlow>,
|
||||
init_command: Command<A::Message>,
|
||||
mut windows: HashMap<window::Id, winit::window::Window>,
|
||||
_exit_on_close_request: bool,
|
||||
|
|
@ -332,6 +341,7 @@ async fn run_instance<A, E, C>(
|
|||
{
|
||||
use iced_futures::futures::stream::StreamExt;
|
||||
use winit::event;
|
||||
use winit::event_loop::ControlFlow;
|
||||
|
||||
let mut clipboard =
|
||||
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 events = Vec::new();
|
||||
let mut messages = Vec::new();
|
||||
let mut redraw_pending = false;
|
||||
|
||||
debug.startup_finished();
|
||||
|
||||
'main: while let Some(event) = receiver.next().await {
|
||||
'main: while let Some(event) = event_receiver.next().await {
|
||||
match event {
|
||||
event::Event::NewEvents(start_cause) => {
|
||||
redraw_pending = matches!(
|
||||
start_cause,
|
||||
event::StartCause::Init
|
||||
| event::StartCause::Poll
|
||||
| event::StartCause::ResumeTimeReached { .. }
|
||||
);
|
||||
}
|
||||
event::Event::MainEventsCleared => {
|
||||
for id in states.keys().copied().collect::<Vec<_>>() {
|
||||
let (filtered, remaining): (Vec<_>, Vec<_>) =
|
||||
|
|
@ -408,29 +427,27 @@ async fn run_instance<A, E, C>(
|
|||
);
|
||||
|
||||
events.retain(|el| remaining.contains(el));
|
||||
let mut filtered: Vec<_> = filtered
|
||||
let window_events: Vec<_> = filtered
|
||||
.into_iter()
|
||||
.map(|(_id, event)| event)
|
||||
.collect();
|
||||
filtered.push(iced_native::Event::Window(
|
||||
id,
|
||||
window::Event::RedrawRequested(Instant::now()),
|
||||
));
|
||||
|
||||
let cursor_position =
|
||||
states.get(&id).unwrap().cursor_position();
|
||||
let window = windows.get(&id).unwrap();
|
||||
|
||||
if filtered.is_empty() && messages.is_empty() {
|
||||
if !redraw_pending
|
||||
&& window_events.is_empty()
|
||||
&& messages.is_empty()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
debug.event_processing_started();
|
||||
|
||||
let cursor_position =
|
||||
states.get(&id).unwrap().cursor_position();
|
||||
|
||||
let (interface_state, statuses) = {
|
||||
let user_interface = interfaces.get_mut(&id).unwrap();
|
||||
user_interface.update(
|
||||
&filtered,
|
||||
&window_events,
|
||||
cursor_position,
|
||||
&mut renderer,
|
||||
&mut clipboard,
|
||||
|
|
@ -440,7 +457,8 @@ async fn run_instance<A, E, C>(
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
@ -487,8 +505,6 @@ async fn run_instance<A, E, C>(
|
|||
windows.get(&id).expect("No window found with ID."),
|
||||
);
|
||||
|
||||
let should_exit = application.should_exit();
|
||||
|
||||
interfaces = ManuallyDrop::new(build_user_interfaces(
|
||||
&application,
|
||||
&mut renderer,
|
||||
|
|
@ -497,17 +513,35 @@ async fn run_instance<A, E, C>(
|
|||
user_interfaces,
|
||||
));
|
||||
|
||||
if should_exit {
|
||||
if application.should_exit() {
|
||||
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();
|
||||
let new_mouse_interaction = {
|
||||
let user_interface = interfaces.get_mut(&id).unwrap();
|
||||
let state = states.get(&id).unwrap();
|
||||
|
||||
user_interface.draw(
|
||||
interfaces.get_mut(&id).unwrap().draw(
|
||||
&mut renderer,
|
||||
state.theme(),
|
||||
&renderer::Style {
|
||||
|
|
@ -518,6 +552,8 @@ async fn run_instance<A, E, C>(
|
|||
};
|
||||
debug.draw_finished();
|
||||
|
||||
let window = windows.get(&id).unwrap();
|
||||
|
||||
if new_mouse_interaction != mouse_interaction {
|
||||
window.set_cursor_icon(conversion::mouse_interaction(
|
||||
new_mouse_interaction,
|
||||
|
|
@ -528,6 +564,28 @@ async fn run_instance<A, E, C>(
|
|||
|
||||
for window in windows.values() {
|
||||
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