mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-31 20:08:35 +00:00
322 lines
11 KiB
Text
322 lines
11 KiB
Text
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
|
|
|
|
import { Palette, Button, LineEdit, CheckBox, ScrollView, VerticalBox } from "std-widgets.slint";
|
|
import { Api, ColorData, ElementInformation, PreviewData, PreviewDataKind, PropertyDeclaration, PropertyGroup, PropertyInformation, PropertyValue, PropertyValueKind, PropertyValueTable } from "../api.slint";
|
|
import { EditorSizeSettings, Icons, EditorAnimationSettings, EditorSpaceSettings, EditorSizeSettings, EditorFontSettings, EditorPalette } from "../components/styling.slint";
|
|
import { PropertyValueWidget } from "../components/property-widgets.slint";
|
|
|
|
export struct CellData {
|
|
id: string,
|
|
value: PropertyValue,
|
|
row: int,
|
|
col: int,
|
|
x: length,
|
|
y: length,
|
|
width: length,
|
|
height: length
|
|
}
|
|
|
|
export component EditWindow inherits Rectangle {
|
|
in property <CellData> current-cell;
|
|
drop-shadow-blur: 10px;
|
|
drop-shadow-color: black.transparentize(0.5);
|
|
drop-shadow-offset-x: 0;
|
|
drop-shadow-offset-y: 0;
|
|
border-radius: EditorSizeSettings.radius;
|
|
width: self.preferred-width;
|
|
height: self.preferred-height;
|
|
background: Palette.alternate-background;
|
|
callback save(string);
|
|
callback close-editor();
|
|
HorizontalLayout {
|
|
padding: EditorSpaceSettings.default-padding;
|
|
padding-left: EditorSpaceSettings.default-padding + 15px;
|
|
spacing: EditorSpaceSettings.default-spacing;
|
|
PropertyValueWidget {
|
|
property-value: current-cell.value;
|
|
visible: true;
|
|
property-name: current-cell.id;
|
|
enabled: true;
|
|
}
|
|
}
|
|
}
|
|
|
|
component RowMarker inherits Rectangle {
|
|
in property <int> value;
|
|
in property <bool> header: false;
|
|
in property <bool> hovered;
|
|
width: 30px;
|
|
if (value > 0): Rectangle {
|
|
height: 30px;
|
|
background: header ? transparent : Palette.alternate-background;
|
|
VerticalLayout {
|
|
HorizontalLayout {
|
|
Text {
|
|
vertical-alignment: center;
|
|
horizontal-alignment: right;
|
|
text: value;
|
|
}
|
|
|
|
VerticalLayout {
|
|
alignment: LayoutAlignment.center;
|
|
padding: EditorSpaceSettings.default-padding / 4;
|
|
indicator := Image {
|
|
visible: hovered;
|
|
colorize: Palette.foreground;
|
|
source: Icons.chevron-down;
|
|
width: 10px;
|
|
height: 10px;
|
|
}
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
height: 1px;
|
|
background: Palette.border;
|
|
width: 100%;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
component Cell inherits Rectangle {
|
|
in property <CellData> cell-data;
|
|
in property <string> id;
|
|
in property <bool> is-header: false;
|
|
in property <bool> is-writeable: false;
|
|
in-out property <bool> is-editing: false;
|
|
in property <length> cell-width: 100px;
|
|
property <bool> cell-clicked: false;
|
|
in property <string> text: "";
|
|
in-out property <color> bg-color: cell-clicked ? Palette.accent-background.transparentize(0.8) : transparent;
|
|
callback edit-clicked(CellData);
|
|
|
|
width: cell-width;
|
|
height: 30px;
|
|
border-width: 1px;
|
|
border-color: Palette.border;
|
|
background: is-header ? Palette.foreground.transparentize(0.9) : bg-color;
|
|
|
|
HorizontalLayout {
|
|
Rectangle {
|
|
width: EditorSpaceSettings.default-padding / 2;
|
|
}
|
|
|
|
Text {
|
|
font-weight: is-header ? 700 : 400;
|
|
width: root.width - EditorSpaceSettings.default-padding;
|
|
height: root.height;
|
|
horizontal-alignment: TextHorizontalAlignment.left;
|
|
vertical-alignment: center;
|
|
overflow: TextOverflow.elide;
|
|
text: root.text;
|
|
}
|
|
}
|
|
|
|
if is-writeable: TouchArea {
|
|
clicked => {
|
|
root.edit-clicked({ id: root.id, value: cell-data.value, row: 0, col: 0 });
|
|
}
|
|
}
|
|
}
|
|
|
|
export component Spreadsheet inherits ScrollView {
|
|
in property <PreviewData> preview-data: {
|
|
name: "Addresses",
|
|
has-getter: true,
|
|
has-setter: true,
|
|
kind: PreviewDataKind.Table,
|
|
};
|
|
in property <PropertyValueTable> current-table: {
|
|
is-array: true,
|
|
headers: ["type", "street", "city", "state", "zip", "favorite","color"],
|
|
values: [
|
|
[
|
|
{
|
|
kind: PropertyValueKind.string,
|
|
value-string: "home"
|
|
}, {
|
|
kind: PropertyValueKind.string,
|
|
value-string: "123 Oak Lane"
|
|
}, {
|
|
kind: PropertyValueKind.string,
|
|
value-string: "Richmond"
|
|
}, {
|
|
kind: PropertyValueKind.string,
|
|
value-string: "VA"
|
|
}, {
|
|
kind: PropertyValueKind.string,
|
|
value-string: "23226"
|
|
}, {
|
|
kind: PropertyValueKind.boolean,
|
|
value-bool: true,
|
|
value-string: "True"
|
|
}, {
|
|
kind: PropertyValueKind.color,
|
|
value-string: "#ff0000"
|
|
}
|
|
], [
|
|
{
|
|
kind: PropertyValueKind.string,
|
|
value-string: "work"
|
|
}, {
|
|
kind: PropertyValueKind.string,
|
|
value-string: "456 Corporate Blvd"
|
|
}, {
|
|
kind: PropertyValueKind.string,
|
|
value-string: "Richmond"
|
|
}, {
|
|
kind: PropertyValueKind.string,
|
|
value-string: "VA"
|
|
}, {
|
|
kind: PropertyValueKind.string,
|
|
value-string: "23219"
|
|
}, {
|
|
kind: PropertyValueKind.boolean,
|
|
value-bool: false,
|
|
value-string: "False"
|
|
}
|
|
], [
|
|
{
|
|
kind: PropertyValueKind.string,
|
|
value-string: "history"
|
|
}, {
|
|
kind: PropertyValueKind.string,
|
|
value-string: "123 Oak Lane"
|
|
}, {
|
|
kind: PropertyValueKind.string,
|
|
value-string: "Richmond"
|
|
}, {
|
|
kind: PropertyValueKind.string,
|
|
value-string: "VA"
|
|
}, {
|
|
kind: PropertyValueKind.string,
|
|
value-string: "23226"
|
|
}, {
|
|
kind: PropertyValueKind.boolean,
|
|
value-bool: false,
|
|
value-string: "False"
|
|
}, {
|
|
kind: PropertyValueKind.color,
|
|
value-string: "#aaff00"
|
|
}
|
|
], [
|
|
{
|
|
kind: PropertyValueKind.string,
|
|
value-string: "world"
|
|
}, {
|
|
kind: PropertyValueKind.string,
|
|
value-string: "456 Corporate Blvd"
|
|
}, {
|
|
kind: PropertyValueKind.string,
|
|
value-string: "Richmond"
|
|
}, {
|
|
kind: PropertyValueKind.string,
|
|
value-string: "VA"
|
|
}, {
|
|
kind: PropertyValueKind.string,
|
|
value-string: "23219"
|
|
}, {
|
|
kind: PropertyValueKind.boolean,
|
|
value-bool: false,
|
|
value-string: "False"
|
|
}, {
|
|
kind: PropertyValueKind.color,
|
|
value-string: "#ff0000"
|
|
}
|
|
]
|
|
],
|
|
|
|
};
|
|
|
|
property <CellData> current-cell;
|
|
property <bool> edit-window-visible: false;
|
|
private property <length> selection-x;
|
|
private property <length> selection-y;
|
|
|
|
public function edit-in-spreadsheet(container-name: string, preview-data: PreviewData) {
|
|
debug("Setting up Spreadsheet:", container-name, preview-data);
|
|
}
|
|
|
|
VerticalLayout {
|
|
HorizontalLayout {
|
|
RowMarker { }
|
|
|
|
for header in root.current-table.headers: Cell {
|
|
is-header: true;
|
|
text: header;
|
|
}
|
|
}
|
|
|
|
for data-row[row] in root.current-table.values: HorizontalLayout {
|
|
RowMarker {
|
|
value: row + 1;
|
|
hovered: ta.has-hover ? true : false;
|
|
ta := TouchArea {
|
|
clicked => {
|
|
root.selection-x = self.x;
|
|
root.selection-y = self.y;
|
|
row_menu.show({x:self.mouse-x + ta.absolute-position.x - row_menu.absolute-position.x,y:self.mouse-y + ta.absolute-position.y - row_menu.absolute-position.y});
|
|
}
|
|
}
|
|
}
|
|
|
|
for value[col] in data-row: Cell {
|
|
text: value.value-string;
|
|
is-writeable: true;
|
|
edit-clicked(data) => {
|
|
root.current-cell = {
|
|
id: data.id,
|
|
value: value, // Now passing the properly typed CellValue
|
|
row: row,
|
|
col: col,
|
|
x: self.x,
|
|
y: parent.y,
|
|
width: self.width,
|
|
height: self.height
|
|
};
|
|
root.edit-window-visible = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (edit-window-visible): ew := EditWindow {
|
|
x: current-cell.x > 15px ? current-cell.x - EditorSpaceSettings.default-padding - 15px : 0; // TODO the end needs to be windowWidth - current-cell.x < current.cell.width * 2;
|
|
y: current-cell.y - EditorSpaceSettings.default-padding;
|
|
current-cell: current-cell;
|
|
save(new-value) => {
|
|
// Update the specific field based on col index
|
|
// if (current-cell.col == 0) {
|
|
// addresses[current-cell.row].type = new-value;
|
|
// } else if (current-cell.col == 1) {
|
|
// addresses[current-cell.row].street = new-value;
|
|
// } else if (current-cell.col == 2) {
|
|
// addresses[current-cell.row].city = new-value;
|
|
// } else if (current-cell.col == 3) {
|
|
// addresses[current-cell.row].state = new-value;
|
|
// } else if (current-cell.col == 4) {
|
|
// addresses[current-cell.row].zip = new-value;
|
|
// }
|
|
root.edit-window-visible = false;
|
|
}
|
|
close-editor => {
|
|
root.edit-window-visible = false;
|
|
}
|
|
}
|
|
row_menu:= ContextMenuArea {
|
|
in property <int> position;
|
|
Menu {
|
|
MenuItem {
|
|
title: "Add Row Above";
|
|
}
|
|
MenuItem {
|
|
title: "Add Row Below";
|
|
}
|
|
MenuItem {
|
|
title: "Remove Row";
|
|
}
|
|
}
|
|
}
|
|
}
|