slint/tools/updater/experiments/geometry_changes.rs
Simon Hausmann 629c7ed80e Remove undocumented and dysfunctional PathLayout
This type is poorly implemented and not documented. Let's remove it for now.
It shall remain available in the git history in the event of a resurrection.
2023-01-21 13:10:19 +01:00

103 lines
3.8 KiB
Rust

// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
use crate::Cli;
use i_slint_compiler::expression_tree::Expression;
use i_slint_compiler::langtype::Type;
use i_slint_compiler::object_tree::ElementRc;
use i_slint_compiler::parser::{SyntaxKind, SyntaxNode};
use std::io::Write;
pub(crate) fn fold_node(
node: &SyntaxNode,
file: &mut impl Write,
state: &mut crate::State,
args: &Cli,
) -> std::io::Result<bool> {
let kind = node.kind();
if kind == SyntaxKind::Element {
if state.lookup_change.scope.len() >= 2 {
let elem = &state.lookup_change.scope[state.lookup_change.scope.len() - 1];
let parent = &state.lookup_change.scope[state.lookup_change.scope.len() - 2];
if !is_layout_base(parent) && !is_path(elem) && elem.borrow().is_legacy_syntax {
let extend = elem.borrow().builtin_type().map_or(false, |b| {
b.default_size_binding
!= i_slint_compiler::langtype::DefaultSizeBinding::ImplicitSize
});
let new_props = format!(
"{}{}",
new_geometry_binding(elem, "x", "width", extend),
new_geometry_binding(elem, "y", "height", extend)
);
if !new_props.is_empty() {
let mut seen_brace = false;
for c in node.children_with_tokens() {
if seen_brace {
if c.kind() == SyntaxKind::Whitespace {
crate::visit_node_or_token(c.clone(), file, state, args)?;
}
write!(file, "{new_props}")?;
seen_brace = false;
} else if c.kind() == SyntaxKind::LBrace {
seen_brace = true;
}
crate::visit_node_or_token(c, file, state, args)?;
}
return Ok(true);
}
}
}
}
Ok(false)
}
fn new_geometry_binding(elem: &ElementRc, pos_prop: &str, size_prop: &str, extend: bool) -> String {
if elem.borrow().lookup_property(pos_prop).property_type != Type::LogicalLength {
return String::default();
}
if elem.borrow().is_binding_set(pos_prop, false) {
return String::default();
}
if extend && !elem.borrow().is_binding_set(size_prop, false) {
return String::default();
}
if let Some(b) = elem.borrow().bindings.get(size_prop) {
if let Expression::Uncompiled(x) = &b.borrow().expression {
let s = x.to_string();
if s.trim() == "100%;" || s.trim() == format!("parent.{size_prop};") {
return String::default();
}
}
}
format!("{pos_prop}:0;")
}
fn is_layout_base(elem: &ElementRc) -> bool {
match &elem.borrow().base_type {
i_slint_compiler::langtype::ElementType::Builtin(b) => {
return matches!(
b.name.as_str(),
"GridLayout" | "HorizontalLayout" | "VerticalLayout" | "Row" | "Path" | "Dialog"
);
}
i_slint_compiler::langtype::ElementType::Component(c) => {
if c.id == "ListView" {
return true;
}
if let Some(ins) = &*c.child_insertion_point.borrow() {
return is_layout_base(&ins.0);
} else {
return is_layout_base(&c.root_element);
}
}
_ => return false,
};
}
fn is_path(elem: &ElementRc) -> bool {
// Path's children are still considered in the Path for some reason, so just don't touch path
elem.borrow().base_type.to_string() == "Path"
}