mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-27 12:29:41 +00:00
249 lines
7.9 KiB
Text
249 lines
7.9 KiB
Text
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.0 OR LicenseRef-Slint-commercial
|
|
|
|
import { LineEditInner } from "../common/common.slint";
|
|
import { Palette, ScrollView } from "std-widgets-impl.slint";
|
|
|
|
component TableViewColumn inherits Rectangle {
|
|
callback clicked <=> touch-area.clicked;
|
|
callback adjust_size(length);
|
|
|
|
in property <SortOrder> sort-order: SortOrder.unsorted;
|
|
|
|
touch-area := TouchArea {
|
|
width: parent.width - 11px;
|
|
}
|
|
|
|
HorizontalLayout {
|
|
padding-left: 16px;
|
|
padding-right: 16px;
|
|
spacing: 2px;
|
|
|
|
HorizontalLayout {
|
|
@children
|
|
}
|
|
|
|
Path {
|
|
visible: root.sort-order != SortOrder.unsorted;
|
|
width: 12px;
|
|
height: 12px;
|
|
y: (parent.height - self.height) / 2;
|
|
commands: root.sort-order == SortOrder.ascending ?
|
|
"M6 10.5C6.27614 10.5 6.5 10.2761 6.5 10V3.20711L9.14645 5.85355C9.34171 6.04882 9.65829 6.04882 9.85355 5.85355C10.0488 5.65829 10.0488 5.34171 9.85355 5.14645L6.35355 1.64645C6.15829 1.45118 5.84171 1.45118 5.64645 1.64645L2.14645 5.14645C1.95118 5.34171 1.95118 5.65829 2.14645 5.85355C2.34171 6.04882 2.65829 6.04882 2.85355 5.85355L5.5 3.20711V10C5.5 10.2761 5.72386 10.5 6 10.5Z" :
|
|
"M6 1.5C6.27614 1.5 6.5 1.72386 6.5 2V8.79289L9.14645 6.14645C9.34171 5.95118 9.65829 5.95118 9.85355 6.14645C10.0488 6.34171 10.0488 6.65829 9.85355 6.85355L6.35355 10.3536C6.15829 10.5488 5.84171 10.5488 5.64645 10.3536L2.14645 6.85355C1.95118 6.65829 1.95118 6.34171 2.14645 6.14645C2.34171 5.95118 2.65829 5.95118 2.85355 6.14645L5.5 8.79289V2C5.5 1.72386 5.72386 1.5 6 1.5Z";
|
|
fill: Palette.neutralDark;
|
|
}
|
|
}
|
|
|
|
// border
|
|
Rectangle {
|
|
y: parent.height - self.height;
|
|
width: 100%;
|
|
height: 1px;
|
|
background: Palette.neutralLight;
|
|
}
|
|
|
|
Rectangle {
|
|
width: 1px;
|
|
x: parent.width - 1px;
|
|
background: movable-ta.has-hover ? Palette.neutralTertiary : transparent;
|
|
animate background { duration: 250ms; }
|
|
movable-ta := TouchArea {
|
|
width: 10px;
|
|
moved => {
|
|
if (self.pressed) {
|
|
adjust_size(self.mouse-x - self.pressed-x);
|
|
}
|
|
}
|
|
mouse-cursor: ew-resize;
|
|
}
|
|
}
|
|
|
|
states [
|
|
pressed when touch-area.pressed : {
|
|
background: Palette.neutralLight;
|
|
}
|
|
hover when touch-area.has-hover : {
|
|
background: Palette.neutralLighter;
|
|
}
|
|
]
|
|
}
|
|
|
|
component TableViewCell inherits Rectangle {
|
|
clip: true;
|
|
|
|
HorizontalLayout {
|
|
padding-left: 16px;
|
|
padding-right: 16px;
|
|
|
|
@children
|
|
}
|
|
|
|
// border
|
|
Rectangle {
|
|
y: parent.height - self.height;
|
|
width: 100%;
|
|
height: 1px;
|
|
background: Palette.neutralLight;
|
|
}
|
|
}
|
|
|
|
component TableViewRow inherits Rectangle {
|
|
callback clicked <=> touch-area.clicked;
|
|
|
|
in property<bool> selected;
|
|
|
|
min-height: 42px;
|
|
|
|
touch-area := TouchArea {}
|
|
|
|
HorizontalLayout {
|
|
@children
|
|
}
|
|
|
|
states [
|
|
selected when root.selected : {
|
|
background: Palette.neutralLighter;
|
|
}
|
|
hover when touch-area.has-hover : {
|
|
background: Palette.neutralLighter;
|
|
}
|
|
]
|
|
}
|
|
|
|
export component StandardTableView {
|
|
private property <length> item-height: scroll-view.viewport-height / rows.length;
|
|
private property <length> current-item-y: scroll-view.viewport-y + current-row * item-height;
|
|
|
|
callback sort-ascending(int);
|
|
callback sort-descending(int);
|
|
|
|
private property <length> min-header-height: 42px;
|
|
out property <int> current-sort-column: -1;
|
|
in-out property <[TableColumn]> columns;
|
|
in property <[[StandardListViewItem]]> rows;
|
|
in-out property<int> current-row: -1;
|
|
|
|
min-width: 400px;
|
|
min-height: 200px;
|
|
horizontal-stretch: 1;
|
|
vertical-stretch: 1;
|
|
|
|
public function set-current-row(index: int) {
|
|
if(index < 0 || index >= rows.length) {
|
|
return;
|
|
}
|
|
|
|
current-row = index;
|
|
|
|
if(current-item-y < 0) {
|
|
scroll-view.viewport-y += 0 - current-item-y;
|
|
}
|
|
|
|
if(current-item-y + item-height > scroll-view.visible-height) {
|
|
scroll-view.viewport-y -= current-item-y + item-height - scroll-view.visible-height;
|
|
}
|
|
}
|
|
|
|
function sort(index: int) {
|
|
if (root.current-sort-column != index) {
|
|
root.columns[root.current-sort-column].sort-order = SortOrder.unsorted;
|
|
}
|
|
|
|
if(root.columns[index].sort-order == SortOrder.ascending) {
|
|
root.columns[index].sort-order = SortOrder.descending;
|
|
root.sort-descending(index);
|
|
} else {
|
|
root.columns[index].sort-order = SortOrder.ascending;
|
|
root.sort-ascending(index);
|
|
}
|
|
|
|
root.current-sort-column = index;
|
|
}
|
|
|
|
VerticalLayout {
|
|
Rectangle {
|
|
clip: true;
|
|
vertical-stretch: 0;
|
|
min-height: header-layout.min-height;
|
|
|
|
header-layout := HorizontalLayout {
|
|
width: max(self.preferred-width, parent.width);
|
|
x: scroll-view.viewport-x;
|
|
padding-right: 20px;
|
|
min-height: root.min-header-height;
|
|
|
|
for column[index] in root.columns : TableViewColumn {
|
|
sort-order: column.sort-order;
|
|
horizontal-stretch: column.horizontal-stretch;
|
|
min-width: max(column.min-width, column.width);
|
|
preferred-width: self.min-width;
|
|
max-width: (index < columns.length && column.width >= 1px) ? max(column.min-width, column.width) : 100000px;
|
|
|
|
Text {
|
|
vertical-alignment: center;
|
|
text: column.title;
|
|
font-weight: 900;
|
|
overflow: elide;
|
|
}
|
|
|
|
clicked => {
|
|
root.sort(index);
|
|
}
|
|
adjust-size(diff) => {
|
|
column.width = max(1px, self.width + diff);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
scroll-view := ScrollView {
|
|
vertical-stretch: 1;
|
|
|
|
VerticalLayout {
|
|
alignment: start;
|
|
|
|
for row[idx] in root.rows : TableViewRow {
|
|
selected: idx == root.current-row;
|
|
|
|
for cell[index] in row : TableViewCell {
|
|
private property <bool> has_inner_focus;
|
|
|
|
horizontal-stretch: root.columns[index].horizontal-stretch;
|
|
min-width: max(columns[index].min-width, columns[index].width);
|
|
preferred-width: self.min-width;
|
|
max-width: (index < columns.length && columns[index].width >= 1px) ? max(columns[index].min-width, columns[index].width) : 100000px;
|
|
|
|
Rectangle {
|
|
Text {
|
|
width: 100%;
|
|
height: 100%;
|
|
overflow: elide;
|
|
vertical-alignment: center;
|
|
text: cell.text;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
clicked => {
|
|
root.set-current-row(idx);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
FocusScope {
|
|
key-pressed(event) => {
|
|
if (event.text == Key.UpArrow) {
|
|
root.set-current-row(root.current-row - 1);
|
|
return accept;
|
|
} else if (event.text == Key.DownArrow) {
|
|
root.set-current-row(root.current-row + 1);
|
|
return accept;
|
|
}
|
|
reject
|
|
}
|
|
}
|
|
}
|