mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-03 10:23:32 +00:00

These are two different concept, and it is confusing to keep them in the same enum We want to support component without any base element, and Void is already used for global component, so do this refactoring before
87 lines
2.9 KiB
Rust
87 lines
2.9 KiB
Rust
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
|
|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
|
|
|
/*! re-order the children by their z-order
|
|
*/
|
|
|
|
use std::rc::Rc;
|
|
|
|
use crate::diagnostics::BuildDiagnostics;
|
|
use crate::expression_tree::{Expression, Unit};
|
|
use crate::langtype::ElementType;
|
|
use crate::object_tree::{Component, ElementRc};
|
|
|
|
pub fn reorder_by_z_order(root_component: &Rc<Component>, diag: &mut BuildDiagnostics) {
|
|
crate::object_tree::recurse_elem_including_sub_components(
|
|
root_component,
|
|
&(),
|
|
&mut |elem: &ElementRc, _| {
|
|
reorder_children_by_zorder(elem, diag);
|
|
},
|
|
)
|
|
}
|
|
|
|
fn reorder_children_by_zorder(
|
|
elem: &Rc<std::cell::RefCell<crate::object_tree::Element>>,
|
|
diag: &mut BuildDiagnostics,
|
|
) {
|
|
// maps indexes to their z order
|
|
let mut children_z_order = vec![];
|
|
for (idx, child_elm) in elem.borrow().children.iter().enumerate() {
|
|
let z = child_elm
|
|
.borrow_mut()
|
|
.bindings
|
|
.remove("z")
|
|
.and_then(|e| eval_const_expr(&e.borrow().expression, "z", &*e.borrow(), diag));
|
|
let z =
|
|
z.or_else(|| {
|
|
child_elm.borrow().repeated.as_ref()?;
|
|
if let ElementType::Component(c) = &child_elm.borrow().base_type {
|
|
c.root_element.borrow_mut().bindings.remove("z").and_then(|e| {
|
|
eval_const_expr(&e.borrow().expression, "z", &*e.borrow(), diag)
|
|
})
|
|
} else {
|
|
None
|
|
}
|
|
});
|
|
|
|
if let Some(z) = z {
|
|
if children_z_order.is_empty() {
|
|
for i in 0..idx {
|
|
children_z_order.push((i, 0.));
|
|
}
|
|
}
|
|
children_z_order.push((idx, z));
|
|
} else if !children_z_order.is_empty() {
|
|
children_z_order.push((idx, 0.));
|
|
}
|
|
}
|
|
|
|
if !children_z_order.is_empty() {
|
|
children_z_order.sort_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap());
|
|
|
|
let new_children = children_z_order
|
|
.into_iter()
|
|
.map(|(idx, _)| elem.borrow().children[idx].clone())
|
|
.collect();
|
|
elem.borrow_mut().children = new_children;
|
|
}
|
|
}
|
|
|
|
fn eval_const_expr(
|
|
expression: &Expression,
|
|
name: &str,
|
|
span: &dyn crate::diagnostics::Spanned,
|
|
diag: &mut BuildDiagnostics,
|
|
) -> Option<f64> {
|
|
match expression {
|
|
Expression::NumberLiteral(v, Unit::None) => Some(*v),
|
|
Expression::Cast { from, .. } => eval_const_expr(from, name, span, diag),
|
|
Expression::UnaryOp { sub, op: '-' } => eval_const_expr(sub, name, span, diag).map(|v| -v),
|
|
Expression::UnaryOp { sub, op: '+' } => eval_const_expr(sub, name, span, diag),
|
|
_ => {
|
|
diag.push_error(format!("'{}' must be an number literal", name), span);
|
|
None
|
|
}
|
|
}
|
|
}
|