mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-25 17:38:06 +00:00
211 lines
7.5 KiB
Text
211 lines
7.5 KiB
Text
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
import { Drawer, ModalDrawer, DrawerHeader } from "./drawer.slint";
|
|
import { NavigationItem, NavigationGroup } from "../items/navigation_item.slint";
|
|
import { HorizontalDivider } from "./divider.slint";
|
|
import { StateLayerArea } from "./state_layer.slint";
|
|
import { MaterialPalette } from "../styling/material_palette.slint";
|
|
import { Icon } from "./icon.slint";
|
|
import { MaterialText } from "./material_text.slint";
|
|
import { Typography } from "../styling/typography.slint";
|
|
import { MaterialStyleMetrics } from "../styling/material_style_metrics.slint";
|
|
import { Animations } from "../styling/animations.slint";
|
|
import { BaseNavigationItemTemplate } from "./base_navigation.slint";
|
|
|
|
component NavigationItemTempalte inherits BaseNavigationItemTemplate {
|
|
property <bool> has_icon: root.icon.width > 0 && root.icon.height > 0;
|
|
property <bool> has_selected_icon: root.selected_icon.width > 0 || root.selected_icon.height > 0;
|
|
property <color> color: MaterialPalette.on_surface_variant;
|
|
|
|
min_height: max(MaterialStyleMetrics.size_56, layout.min_height);
|
|
|
|
background_layer := Rectangle {
|
|
border_radius: self.height / 2;
|
|
|
|
state_layer := StateLayerArea {
|
|
border_radius: parent.border_radius;
|
|
color: root.selected ? transparent : root.color;
|
|
|
|
layout := HorizontalLayout {
|
|
padding_left: MaterialStyleMetrics.padding_16;
|
|
padding_right: MaterialStyleMetrics.padding_24;
|
|
padding_top: MaterialStyleMetrics.padding_16;
|
|
padding_bottom: self.padding_top;
|
|
spacing: MaterialStyleMetrics.spacing_12;
|
|
|
|
VerticalLayout {
|
|
alignment: center;
|
|
|
|
if !root.has_icon && !root.has_selected_icon : Rectangle {
|
|
width: MaterialStyleMetrics.icon_size_24;
|
|
height: self.width;
|
|
|
|
Rectangle {
|
|
width: 12px;
|
|
height: self.width;
|
|
border_radius: self.width / 2;
|
|
background: root.color;
|
|
}
|
|
}
|
|
|
|
if root.has_icon || root.has_selected_icon : Icon {
|
|
source: root.icon;
|
|
colorize: root.color;
|
|
|
|
states [
|
|
selected when root.selected && root.has_selected_icon : {
|
|
source: root.selected_icon;
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
MaterialText {
|
|
horizontal_stretch: 1;
|
|
text: root.text;
|
|
style: Typography.label_large;
|
|
color: root.color;
|
|
vertical_alignment: center;
|
|
}
|
|
|
|
if root.badge != "" : MaterialText {
|
|
text: root.badge;
|
|
style: Typography.label_large;
|
|
color: root.color;
|
|
vertical_alignment: center;
|
|
}
|
|
}
|
|
|
|
clicked => {
|
|
root.clicked();
|
|
}
|
|
|
|
pointer_event(event) => {
|
|
root.pointer_event(event, {
|
|
x: self.mouse_x,
|
|
y: self.mouse_y,
|
|
});
|
|
}
|
|
}
|
|
|
|
animate background { duration: Animations.opacity_duration; easing: Animations.opacity_easing; }
|
|
}
|
|
|
|
states [
|
|
selected when root.selected : {
|
|
background_layer.background: MaterialPalette.secondary_container;
|
|
root.color: MaterialPalette.on_secondary_container;
|
|
}
|
|
]
|
|
|
|
animate color { duration: Animations.opacity_duration; easing: Animations.opacity_easing; }
|
|
}
|
|
|
|
component NavigationGroupTemplate {
|
|
in property <string> title;
|
|
in property <[NavigationItem]> items;
|
|
in property <int> current_index: -1;
|
|
in property <bool> has_divider;
|
|
|
|
callback select(index: int);
|
|
callback item_pointer_event(index: int, event: PointerEvent, position: Point);
|
|
|
|
VerticalLayout {
|
|
alignment: start;
|
|
|
|
if root.title != 0 : DrawerHeader {
|
|
title: root.title;
|
|
}
|
|
|
|
for item[index] in root.items : NavigationItemTempalte {
|
|
icon: item.icon;
|
|
selected_icon: item.selected_icon;
|
|
text: item.text;
|
|
badge: item.badge;
|
|
selected: index == root.current_index;
|
|
index: index;
|
|
|
|
clicked => {
|
|
root.select(index);
|
|
}
|
|
pointer_event(event, position) => {
|
|
root.item_pointer_event(index, event, {
|
|
x: self.x + position.x,
|
|
y: self.y + position.y,
|
|
});
|
|
}
|
|
}
|
|
|
|
if root.has_divider : HorizontalDivider {}
|
|
}
|
|
}
|
|
|
|
export component NavigationDrawer inherits Drawer {
|
|
callback selected(group-index: int, item_index: int);
|
|
callback item_pointer_event(group_index: int, item_index: int, event: PointerEvent, position: Point);
|
|
in property <[NavigationGroup]> groups;
|
|
in_out property <int> current_group;
|
|
in_out property <int> current_index;
|
|
|
|
accessible-role: tab-list;
|
|
// accessible-delegate-focus: root.current-focused >= 0 ? root.current-focused : root.current-index;
|
|
// accessible-label: root.title;
|
|
accessible-item-count: root.groups.length;
|
|
|
|
for group[group_index] in root.groups : NavigationGroupTemplate {
|
|
title: group.title;
|
|
items: group.items;
|
|
current_index: group_index == root.current_group ? root.current_index : -1;
|
|
has_divider: root.groups.length > 1 && group_index < root.groups.length - 1;
|
|
|
|
select(index) => {
|
|
root.select(group_index, index);
|
|
}
|
|
item_pointer_event(index, event, position) => {
|
|
root.item_pointer_event(group_index, index, event, { x: self.x + position.x, y: self.y + position.y });
|
|
}
|
|
}
|
|
|
|
function select(group_index: int, item_index: int) {
|
|
if group_index < 0 || group_index >= root.groups.length || item_index < 0 || item_index >= root.groups[group_index].items.length {
|
|
return;
|
|
}
|
|
|
|
root.current_group = group_index;
|
|
root.current_index = item_index;
|
|
root.selected(group_index, item_index);
|
|
}
|
|
}
|
|
|
|
export component ModalNavigationDrawer inherits ModalDrawer {
|
|
in property <[NavigationGroup]> groups;
|
|
in_out property <int> current_group;
|
|
in_out property <int> current_index;
|
|
|
|
accessible-role: tab-list;
|
|
// accessible-delegate-focus: root.current-focused >= 0 ? root.current-focused : root.current-index;
|
|
// accessible-label: root.title;
|
|
accessible-item-count: root.groups.length;
|
|
|
|
for group[group_index] in root.groups : NavigationGroupTemplate {
|
|
title: group.title;
|
|
items: group.items;
|
|
current_index: group_index == root.current_group ? root.current_index : -1;
|
|
has_divider: root.groups.length > 1 && group_index < root.groups.length - 1;
|
|
|
|
select(index) => {
|
|
root.select(group_index, index);
|
|
}
|
|
}
|
|
|
|
function select(group_index: int, item_index: int) {
|
|
if group_index < 0 || group_index >= root.groups.length || item_index < 0 || item_index >= root.groups[group_index].items.length {
|
|
return;
|
|
}
|
|
|
|
root.current_group = group_index;
|
|
root.current_index = item_index;
|
|
root.close();
|
|
}
|
|
}
|