tree: split container tasks
This commit is contained in:
parent
16c402825f
commit
7d9ee6e696
2 changed files with 161 additions and 148 deletions
|
|
@ -1,3 +1,7 @@
|
||||||
|
mod tasks;
|
||||||
|
|
||||||
|
pub use tasks::{container_layout, container_render_positions, container_tab_render_textures};
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
backend::ButtonState,
|
backend::ButtonState,
|
||||||
|
|
@ -11,9 +15,7 @@ use {
|
||||||
},
|
},
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
renderer::Renderer,
|
renderer::Renderer,
|
||||||
scale::Scale,
|
|
||||||
state::State,
|
state::State,
|
||||||
text::TextTexture,
|
|
||||||
tree::{
|
tree::{
|
||||||
ContainingNode, Direction, FindTreeResult, FindTreeUsecase, FloatNode, FoundNode, Node,
|
ContainingNode, Direction, FindTreeResult, FindTreeUsecase, FloatNode, FoundNode, Node,
|
||||||
NodeId, NodeLayerLink, NodeLocation, OutputNode, TddType, TileDragDestination,
|
NodeId, NodeLayerLink, NodeLocation, OutputNode, TddType, TileDragDestination,
|
||||||
|
|
@ -25,12 +27,10 @@ use {
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
clonecell::CloneCell,
|
clonecell::CloneCell,
|
||||||
errorfmt::ErrorFmt,
|
|
||||||
event_listener::LazyEventSource,
|
event_listener::LazyEventSource,
|
||||||
hash_map_ext::HashMapExt,
|
hash_map_ext::HashMapExt,
|
||||||
linkedlist::{LinkedList, LinkedNode, NodeRef},
|
linkedlist::{LinkedList, LinkedNode, NodeRef},
|
||||||
numcell::NumCell,
|
numcell::NumCell,
|
||||||
on_drop_event::OnDropEvent,
|
|
||||||
rc_eq::rc_eq,
|
rc_eq::rc_eq,
|
||||||
threshold_counter::ThresholdCounter,
|
threshold_counter::ThresholdCounter,
|
||||||
},
|
},
|
||||||
|
|
@ -1769,150 +1769,6 @@ enum SeatOpKind {
|
||||||
Resize { dist_left: i32, dist_right: i32 },
|
Resize { dist_left: i32, dist_right: i32 },
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn container_layout(state: Rc<State>) {
|
|
||||||
loop {
|
|
||||||
let first = state.pending_container_layout.pop().await;
|
|
||||||
let mut containers = vec![first];
|
|
||||||
while let Some(container) = state.pending_container_layout.try_pop() {
|
|
||||||
containers.push(container);
|
|
||||||
}
|
|
||||||
let mut animated = vec![];
|
|
||||||
let mut immediate = vec![];
|
|
||||||
for container in containers {
|
|
||||||
if !container.layout_scheduled.get() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let animate = container.animate_next_layout.replace(false)
|
|
||||||
&& !state.suppress_animations_for_next_layout.get();
|
|
||||||
if animate {
|
|
||||||
animated.push(container);
|
|
||||||
} else {
|
|
||||||
immediate.push(container);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !animated.is_empty() {
|
|
||||||
let prev_active = state.layout_animations_active.replace(true);
|
|
||||||
state.begin_layout_animation_batch();
|
|
||||||
for container in animated {
|
|
||||||
container.perform_layout();
|
|
||||||
}
|
|
||||||
state.finish_layout_animation_batch();
|
|
||||||
state.layout_animations_active.set(prev_active);
|
|
||||||
}
|
|
||||||
if !immediate.is_empty() {
|
|
||||||
let prev_active = state.layout_animations_active.replace(false);
|
|
||||||
for container in immediate {
|
|
||||||
container.perform_layout();
|
|
||||||
}
|
|
||||||
state.layout_animations_active.set(prev_active);
|
|
||||||
}
|
|
||||||
state.suppress_animations_for_next_layout.set(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn container_render_positions(state: Rc<State>) {
|
|
||||||
loop {
|
|
||||||
let container = state.pending_container_render_positions.pop().await;
|
|
||||||
if container.compute_render_positions_scheduled.get() {
|
|
||||||
container.compute_render_positions();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn container_tab_render_textures(state: Rc<State>) {
|
|
||||||
loop {
|
|
||||||
let container = state.pending_container_tab_render_textures.pop().await;
|
|
||||||
container.update_tab_textures_scheduled.set(false);
|
|
||||||
let (event, textures) = container.update_tab_textures_phase1();
|
|
||||||
event.triggered().await;
|
|
||||||
container.update_tab_textures_phase2(&textures);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ContainerNode {
|
|
||||||
fn update_tab_textures_phase1(
|
|
||||||
self: &Rc<Self>,
|
|
||||||
) -> (
|
|
||||||
Rc<crate::utils::asyncevent::AsyncEvent>,
|
|
||||||
Vec<Rc<RefCell<Option<TextTexture>>>>,
|
|
||||||
) {
|
|
||||||
let on_completed = Rc::new(OnDropEvent::default());
|
|
||||||
let (entries, bar_height, render_scale) = {
|
|
||||||
let tab_bar = self.tab_bar.borrow();
|
|
||||||
let Some(tb) = tab_bar.as_ref() else {
|
|
||||||
return (on_completed.event(), vec![]);
|
|
||||||
};
|
|
||||||
let entries: Vec<_> = tb
|
|
||||||
.entries
|
|
||||||
.iter()
|
|
||||||
.map(|e| {
|
|
||||||
(
|
|
||||||
e.title.clone(),
|
|
||||||
TabBar::entry_colors(&self.state, e),
|
|
||||||
e.title_texture.clone(),
|
|
||||||
e.width.get(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
(entries, tb.height, tb.render_scale)
|
|
||||||
};
|
|
||||||
let Some(ctx) = self.state.render_ctx.get() else {
|
|
||||||
log::warn!("tab text phase1: no render context");
|
|
||||||
return (on_completed.event(), vec![]);
|
|
||||||
};
|
|
||||||
let font = self.state.theme.title_font();
|
|
||||||
let scale = if render_scale != Scale::from_int(1) {
|
|
||||||
Some(render_scale.to_f64())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let mut texture_height = bar_height;
|
|
||||||
if let Some(s) = scale {
|
|
||||||
texture_height = (bar_height as f64 * s).round() as _;
|
|
||||||
}
|
|
||||||
let mut texture_refs = Vec::new();
|
|
||||||
let text_padding = self.state.theme.sizes.tab_bar_text_padding.get();
|
|
||||||
let border_width = self.state.theme.sizes.tab_bar_border_width.get();
|
|
||||||
for (title, (_, _, text_color), title_texture, tab_width) in &entries {
|
|
||||||
let max_width = (*tab_width - 2 * (text_padding + border_width)).max(0);
|
|
||||||
let max_width = if let Some(s) = scale {
|
|
||||||
(max_width as f64 * s).round() as i32
|
|
||||||
} else {
|
|
||||||
max_width
|
|
||||||
};
|
|
||||||
if max_width <= 0 {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let mut tex_ref = title_texture.borrow_mut();
|
|
||||||
let tex = tex_ref.get_or_insert_with(|| TextTexture::new(&self.state, &ctx));
|
|
||||||
tex.schedule_render_fitting_or_ellipsized(
|
|
||||||
on_completed.clone(),
|
|
||||||
Some(texture_height),
|
|
||||||
max_width,
|
|
||||||
&font,
|
|
||||||
title,
|
|
||||||
*text_color,
|
|
||||||
false,
|
|
||||||
scale,
|
|
||||||
);
|
|
||||||
texture_refs.push(title_texture.clone());
|
|
||||||
}
|
|
||||||
(on_completed.event(), texture_refs)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_tab_textures_phase2(&self, textures: &[Rc<RefCell<Option<TextTexture>>>]) {
|
|
||||||
for title_texture in textures {
|
|
||||||
let tex_ref = title_texture.borrow();
|
|
||||||
if let Some(tex) = tex_ref.as_ref() {
|
|
||||||
if let Err(e) = tex.flip() {
|
|
||||||
log::warn!("Could not render tab text: {}", ErrorFmt(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.damage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Node for ContainerNode {
|
impl Node for ContainerNode {
|
||||||
fn node_id(&self) -> NodeId {
|
fn node_id(&self) -> NodeId {
|
||||||
self.id.into()
|
self.id.into()
|
||||||
|
|
|
||||||
157
src/tree/container/tasks.rs
Normal file
157
src/tree/container/tasks.rs
Normal file
|
|
@ -0,0 +1,157 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
scale::Scale,
|
||||||
|
state::State,
|
||||||
|
text::TextTexture,
|
||||||
|
tree::tab_bar::TabBar,
|
||||||
|
utils::{errorfmt::ErrorFmt, on_drop_event::OnDropEvent},
|
||||||
|
},
|
||||||
|
std::{cell::RefCell, rc::Rc},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::ContainerNode;
|
||||||
|
|
||||||
|
pub async fn container_layout(state: Rc<State>) {
|
||||||
|
loop {
|
||||||
|
let first = state.pending_container_layout.pop().await;
|
||||||
|
let mut containers = vec![first];
|
||||||
|
while let Some(container) = state.pending_container_layout.try_pop() {
|
||||||
|
containers.push(container);
|
||||||
|
}
|
||||||
|
let mut animated = vec![];
|
||||||
|
let mut immediate = vec![];
|
||||||
|
for container in containers {
|
||||||
|
if !container.layout_scheduled.get() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let animate = container.animate_next_layout.replace(false)
|
||||||
|
&& !state.suppress_animations_for_next_layout.get();
|
||||||
|
if animate {
|
||||||
|
animated.push(container);
|
||||||
|
} else {
|
||||||
|
immediate.push(container);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !animated.is_empty() {
|
||||||
|
let prev_active = state.layout_animations_active.replace(true);
|
||||||
|
state.begin_layout_animation_batch();
|
||||||
|
for container in animated {
|
||||||
|
container.perform_layout();
|
||||||
|
}
|
||||||
|
state.finish_layout_animation_batch();
|
||||||
|
state.layout_animations_active.set(prev_active);
|
||||||
|
}
|
||||||
|
if !immediate.is_empty() {
|
||||||
|
let prev_active = state.layout_animations_active.replace(false);
|
||||||
|
for container in immediate {
|
||||||
|
container.perform_layout();
|
||||||
|
}
|
||||||
|
state.layout_animations_active.set(prev_active);
|
||||||
|
}
|
||||||
|
state.suppress_animations_for_next_layout.set(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn container_render_positions(state: Rc<State>) {
|
||||||
|
loop {
|
||||||
|
let container = state.pending_container_render_positions.pop().await;
|
||||||
|
if container.compute_render_positions_scheduled.get() {
|
||||||
|
container.compute_render_positions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn container_tab_render_textures(state: Rc<State>) {
|
||||||
|
loop {
|
||||||
|
let container = state.pending_container_tab_render_textures.pop().await;
|
||||||
|
container.update_tab_textures_scheduled.set(false);
|
||||||
|
let (event, textures) = container.update_tab_textures_phase1();
|
||||||
|
event.triggered().await;
|
||||||
|
container.update_tab_textures_phase2(&textures);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ContainerNode {
|
||||||
|
fn update_tab_textures_phase1(
|
||||||
|
self: &Rc<Self>,
|
||||||
|
) -> (
|
||||||
|
Rc<crate::utils::asyncevent::AsyncEvent>,
|
||||||
|
Vec<Rc<RefCell<Option<TextTexture>>>>,
|
||||||
|
) {
|
||||||
|
let on_completed = Rc::new(OnDropEvent::default());
|
||||||
|
let (entries, bar_height, render_scale) = {
|
||||||
|
let tab_bar = self.tab_bar.borrow();
|
||||||
|
let Some(tb) = tab_bar.as_ref() else {
|
||||||
|
return (on_completed.event(), vec![]);
|
||||||
|
};
|
||||||
|
let entries: Vec<_> = tb
|
||||||
|
.entries
|
||||||
|
.iter()
|
||||||
|
.map(|e| {
|
||||||
|
(
|
||||||
|
e.title.clone(),
|
||||||
|
TabBar::entry_colors(&self.state, e),
|
||||||
|
e.title_texture.clone(),
|
||||||
|
e.width.get(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
(entries, tb.height, tb.render_scale)
|
||||||
|
};
|
||||||
|
let Some(ctx) = self.state.render_ctx.get() else {
|
||||||
|
log::warn!("tab text phase1: no render context");
|
||||||
|
return (on_completed.event(), vec![]);
|
||||||
|
};
|
||||||
|
let font = self.state.theme.title_font();
|
||||||
|
let scale = if render_scale != Scale::from_int(1) {
|
||||||
|
Some(render_scale.to_f64())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let mut texture_height = bar_height;
|
||||||
|
if let Some(s) = scale {
|
||||||
|
texture_height = (bar_height as f64 * s).round() as _;
|
||||||
|
}
|
||||||
|
let mut texture_refs = Vec::new();
|
||||||
|
let text_padding = self.state.theme.sizes.tab_bar_text_padding.get();
|
||||||
|
let border_width = self.state.theme.sizes.tab_bar_border_width.get();
|
||||||
|
for (title, (_, _, text_color), title_texture, tab_width) in &entries {
|
||||||
|
let max_width = (*tab_width - 2 * (text_padding + border_width)).max(0);
|
||||||
|
let max_width = if let Some(s) = scale {
|
||||||
|
(max_width as f64 * s).round() as i32
|
||||||
|
} else {
|
||||||
|
max_width
|
||||||
|
};
|
||||||
|
if max_width <= 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut tex_ref = title_texture.borrow_mut();
|
||||||
|
let tex = tex_ref.get_or_insert_with(|| TextTexture::new(&self.state, &ctx));
|
||||||
|
tex.schedule_render_fitting_or_ellipsized(
|
||||||
|
on_completed.clone(),
|
||||||
|
Some(texture_height),
|
||||||
|
max_width,
|
||||||
|
&font,
|
||||||
|
title,
|
||||||
|
*text_color,
|
||||||
|
false,
|
||||||
|
scale,
|
||||||
|
);
|
||||||
|
texture_refs.push(title_texture.clone());
|
||||||
|
}
|
||||||
|
(on_completed.event(), texture_refs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_tab_textures_phase2(&self, textures: &[Rc<RefCell<Option<TextTexture>>>]) {
|
||||||
|
for title_texture in textures {
|
||||||
|
let tex_ref = title_texture.borrow();
|
||||||
|
if let Some(tex) = tex_ref.as_ref() {
|
||||||
|
if let Err(e) = tex.flip() {
|
||||||
|
log::warn!("Could not render tab text: {}", ErrorFmt(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.damage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue