mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-04 18:58:36 +00:00
parent
3797ed79bc
commit
e5289af154
22 changed files with 135 additions and 21 deletions
|
@ -189,9 +189,16 @@ component MenuItem {
|
|||
//-disallow_global_types_as_child_elements
|
||||
//-is_non_item_type
|
||||
}
|
||||
|
||||
component MenuSeparator {
|
||||
//-disallow_global_types_as_child_elements
|
||||
//-is_non_item_type
|
||||
}
|
||||
|
||||
component Menu {
|
||||
in property <string> title;
|
||||
MenuItem {}
|
||||
MenuSeparator {}
|
||||
Menu {}
|
||||
//-disallow_global_types_as_child_elements
|
||||
//-is_non_item_type
|
||||
|
|
|
@ -85,6 +85,7 @@ use crate::expression_tree::{BuiltinFunction, Callable, Expression, NamedReferen
|
|||
use crate::langtype::{ElementType, Type};
|
||||
use crate::object_tree::*;
|
||||
use core::cell::RefCell;
|
||||
use i_slint_common::MENU_SEPARATOR_PLACEHOLDER_TITLE;
|
||||
use smol_str::{format_smolstr, SmolStr};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::{Rc, Weak};
|
||||
|
@ -531,7 +532,18 @@ fn lower_menu_items(
|
|||
));
|
||||
element.borrow_mut().enclosing_component = component_weak.clone();
|
||||
element.borrow_mut().geometry_props = None;
|
||||
// Menu -> MenuItem
|
||||
if element.borrow().base_type.type_name() == Some("MenuSeparator") {
|
||||
element.borrow_mut().bindings.insert(
|
||||
"title".into(),
|
||||
RefCell::new(
|
||||
Expression::StringLiteral(SmolStr::new_static(
|
||||
MENU_SEPARATOR_PLACEHOLDER_TITLE,
|
||||
))
|
||||
.into(),
|
||||
),
|
||||
);
|
||||
}
|
||||
// Menu/MenuSeparator -> MenuItem
|
||||
element.borrow_mut().base_type = components.menu_item_element.clone();
|
||||
}
|
||||
false
|
||||
|
@ -593,15 +605,22 @@ fn generate_menu_entries(
|
|||
state: &mut GenMenuState,
|
||||
) -> Vec<Expression> {
|
||||
let mut entries = Vec::new();
|
||||
let mut last_is_separator = false;
|
||||
|
||||
for item in menu_items {
|
||||
let mut borrow_mut = item.borrow_mut();
|
||||
let base_name = borrow_mut.base_type.type_name().unwrap();
|
||||
let is_sub_menu = base_name == "Menu";
|
||||
if !is_sub_menu {
|
||||
let is_separator = base_name == "MenuSeparator";
|
||||
if !is_sub_menu && !is_separator {
|
||||
assert_eq!(base_name, "MenuItem");
|
||||
}
|
||||
|
||||
if is_separator && (last_is_separator || entries.is_empty()) {
|
||||
continue;
|
||||
}
|
||||
last_is_separator = is_separator;
|
||||
|
||||
borrow_mut
|
||||
.enclosing_component
|
||||
.upgrade()
|
||||
|
@ -613,10 +632,14 @@ fn generate_menu_entries(
|
|||
assert!(borrow_mut.repeated.is_none());
|
||||
|
||||
let mut values = HashMap::<SmolStr, Expression>::new();
|
||||
for prop in ["title"] {
|
||||
if let Some(binding) = borrow_mut.bindings.remove(prop) {
|
||||
values.insert(SmolStr::new_static(prop), binding.into_inner().expression);
|
||||
if !is_separator {
|
||||
for prop in ["title"] {
|
||||
if let Some(binding) = borrow_mut.bindings.remove(prop) {
|
||||
values.insert(SmolStr::new_static(prop), binding.into_inner().expression);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
values.insert(SmolStr::new_static("is_separator"), Expression::BoolLiteral(true));
|
||||
}
|
||||
|
||||
state.id += 1;
|
||||
|
@ -641,6 +664,9 @@ fn generate_menu_entries(
|
|||
|
||||
entries.push(mk_struct(state.menu_entry.clone(), values));
|
||||
}
|
||||
if last_is_separator {
|
||||
entries.pop();
|
||||
}
|
||||
|
||||
entries
|
||||
}
|
||||
|
|
|
@ -27,9 +27,25 @@ export component A {
|
|||
col: 45;
|
||||
// ^error{Unknown property col in MenuItem}
|
||||
}
|
||||
|
||||
MenuSeparator {
|
||||
entries: [];
|
||||
// ^error{Unknown property entries in MenuSeparator}
|
||||
title: "ok";
|
||||
// ^error{Unknown property title in MenuSeparator}
|
||||
width: 45px;
|
||||
// ^error{Unknown property width in MenuSeparator}
|
||||
MenuItem {}
|
||||
// ^error{MenuSeparator cannot have children elements}
|
||||
Rectangle {}
|
||||
// ^error{MenuSeparator cannot have children elements}
|
||||
}
|
||||
}
|
||||
MenuItem {}
|
||||
// ^error{Unknown element 'MenuItem'}
|
||||
|
||||
MenuSeparator {}
|
||||
// ^error{Unknown element 'MenuSeparator'}
|
||||
}
|
||||
|
||||
TouchArea {
|
||||
|
|
|
@ -28,7 +28,7 @@ export component A inherits Window {
|
|||
opacity: 0.4;
|
||||
// ^error{Unknown property opacity in Menu}
|
||||
Rectangle {
|
||||
// ^error{Rectangle is not allowed within Menu. Only Menu MenuItem are valid children}
|
||||
// ^error{Rectangle is not allowed within Menu. Only Menu MenuItem MenuSeparator are valid children}
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
|
@ -45,6 +45,9 @@ export component A inherits Window {
|
|||
|
||||
MenuItem {}
|
||||
// ^error{MenuItem is not allowed within MenuBar. Only Menu are valid children}
|
||||
|
||||
MenuSeparator {}
|
||||
// ^error{MenuSeparator is not allowed within MenuBar. Only Menu are valid children}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
|
|
|
@ -96,6 +96,7 @@ export component MenuItemBase {
|
|||
in property <brush> default-background;
|
||||
in property <brush> current-foreground;
|
||||
in property <brush> current-background;
|
||||
in property <brush> separator-color;
|
||||
in property <length> font-size <=> label.font-size;
|
||||
in property <int> font-weight <=> label.font-weight;
|
||||
in property <length> border-radius <=> background-layer.border-radius;
|
||||
|
@ -113,6 +114,8 @@ export component MenuItemBase {
|
|||
background: root.default-background;
|
||||
|
||||
touch-area := TouchArea {
|
||||
visible: !entry.is-separator;
|
||||
|
||||
layout := HorizontalLayout {
|
||||
padding-top: root.padding-top;
|
||||
padding-bottom: root.padding-bottom;
|
||||
|
@ -153,6 +156,11 @@ export component MenuItemBase {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if entry.is-separator: Rectangle {
|
||||
height: 1px;
|
||||
background: root.separator-color;
|
||||
}
|
||||
}
|
||||
|
||||
states [
|
||||
|
|
|
@ -67,17 +67,21 @@ export component PopupMenuImpl inherits Window {
|
|||
open-sub-menu-after-timeout.running = false;
|
||||
|
||||
if event.text == Key.UpArrow {
|
||||
if current-highlight >= 1 {
|
||||
current-highlight -= 1;
|
||||
} else {
|
||||
if current-highlight < 1 {
|
||||
current-highlight = entries.length - 1;
|
||||
} else if entries[current-highlight - 1].is_separator {
|
||||
current-highlight -= 2;
|
||||
} else {
|
||||
current-highlight -= 1;
|
||||
}
|
||||
return accept;
|
||||
} else if event.text == Key.DownArrow {
|
||||
if current-highlight < entries.length - 1 {
|
||||
current-highlight += 1;
|
||||
} else {
|
||||
if current-highlight >= entries.length - 1 {
|
||||
current-highlight = 0;
|
||||
} else if entries[current-highlight + 1].is_separator {
|
||||
current-highlight += 2;
|
||||
} else {
|
||||
current-highlight += 1;
|
||||
}
|
||||
return accept;
|
||||
} else if event.text == Key.Return {
|
||||
|
|
|
@ -61,6 +61,7 @@ export component MenuItem {
|
|||
default-foreground: CosmicPalette.foreground;
|
||||
current-foreground: CosmicPalette.foreground;
|
||||
current-background: CosmicPalette.state-hover;
|
||||
separator-color: CosmicPalette.border;
|
||||
font-size: CosmicFontSettings.body.font-size;
|
||||
font-weight: CosmicFontSettings.body.font-weight;
|
||||
padding-left: 16px;
|
||||
|
|
|
@ -62,6 +62,7 @@ export component MenuItem {
|
|||
default-foreground: CupertinoPalette.foreground;
|
||||
current-foreground: CupertinoPalette.accent-foreground;
|
||||
current-background: CupertinoPalette.accent-background;
|
||||
separator-color: CupertinoPalette.border;
|
||||
font-size: CupertinoFontSettings.body.font-size;
|
||||
font-weight: CupertinoFontSettings.body.font-weight;
|
||||
border-radius: 5px;
|
||||
|
|
|
@ -64,6 +64,7 @@ export component MenuItem {
|
|||
default-foreground: FluentPalette.foreground;
|
||||
current-foreground: FluentPalette.foreground;
|
||||
current-background: FluentPalette.subtle-secondary;
|
||||
separator-color: FluentPalette.border;
|
||||
font-size: FluentFontSettings.body.font-size;
|
||||
font-weight: FluentFontSettings.body.font-weight;
|
||||
border-radius: 4px;
|
||||
|
|
|
@ -63,6 +63,7 @@ export component MenuItem {
|
|||
default-foreground: MaterialPalette.foreground;
|
||||
current-foreground: MaterialPalette.foreground;
|
||||
current-background: MaterialPalette.surface-container-highest;
|
||||
separator-color: MaterialPalette.border;
|
||||
font-size: MaterialFontSettings.body-large.font-size;
|
||||
font-weight: MaterialFontSettings.body-large.font-weight;
|
||||
padding-left: 12px;
|
||||
|
|
|
@ -61,6 +61,7 @@ export component MenuItem {
|
|||
default-foreground: NativePalette.foreground;
|
||||
current-foreground: NativePalette.accent-foreground;
|
||||
current-background: NativePalette.accent-background;
|
||||
separator-color: NativePalette.border;
|
||||
font-size: NativeStyleMetrics.default-font-size;
|
||||
font-weight: 300;
|
||||
border-radius: 4px;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue