2023-12-03 11:06:42 +00:00
|
|
|
import { Button, VerticalBox , HorizontalBox, TabWidget, ListView, StandardListView, StandardTableView, CheckBox, ScrollView} from "std-widgets.slint";
|
|
|
|
import {TypeOfOpenedItem} from "common.slint";
|
|
|
|
import {ColorPalette} from "color_palette.slint";
|
|
|
|
import {MainListModel} from "common.slint";
|
|
|
|
import {Callabler} from "callabler.slint";
|
|
|
|
import {GuiState} from "gui_state.slint";
|
|
|
|
|
|
|
|
export component SelectableTableView inherits Rectangle {
|
|
|
|
callback item_opened(string);
|
|
|
|
in property <[string]> columns;
|
|
|
|
in-out property <[MainListModel]> values: [
|
2024-02-10 22:57:52 +00:00
|
|
|
{checked: false, selected_row: false, header_row: true, val_str: ["kropkarz", "/Xd1", "24.10.2023"], val_int: []} ,
|
|
|
|
{checked: false, selected_row: false, header_row: false, val_str: ["witasphere", "/Xd1/Imagerren2", "25.11.1991"], val_int: []} ,
|
|
|
|
{checked: false, selected_row: false, header_row: false, val_str: ["witasphere", "/Xd1/Imagerren2", "25.11.1991"], val_int: []} ,
|
|
|
|
{checked: true, selected_row: false, header_row: false, val_str: ["lokkaler", "/Xd1/Vide2", "01.23.1911"], val_int: []}
|
2023-12-03 11:06:42 +00:00
|
|
|
];
|
|
|
|
in-out property <[length]> column_sizes: [30px, 80px, 150px, 160px];
|
|
|
|
private property <int> column_number: column-sizes.length + 1;
|
|
|
|
// This idx, starts from zero, but since first is always a checkbox, and is not in model.val values, remove 1 from idx
|
|
|
|
in-out property <int> parentPathIdx;
|
|
|
|
in-out property <int> fileNameIdx;
|
|
|
|
in-out property <int> selected_item: -1;
|
|
|
|
out property <length> list_view_width: max(self.width - 20px, column_sizes[0] + column_sizes[1] + column_sizes[2] + column_sizes[3] + column_sizes[4] + column_sizes[5] + column_sizes[6] + column_sizes[7] + column_sizes[8] + column_sizes[9] + column_sizes[10] + column_sizes[11]);
|
|
|
|
|
|
|
|
VerticalBox {
|
|
|
|
padding: 0px;
|
|
|
|
ScrollView {
|
|
|
|
height: 30px;
|
|
|
|
viewport-x <=> list_view.viewport-x;
|
|
|
|
vertical-stretch: 0;
|
|
|
|
|
|
|
|
HorizontalLayout {
|
|
|
|
spacing: 5px;
|
|
|
|
for title [idx] in root.columns: HorizontalLayout {
|
|
|
|
width: root.column-sizes[idx];
|
|
|
|
Text {
|
|
|
|
overflow: elide;
|
|
|
|
text: title;
|
|
|
|
}
|
|
|
|
|
|
|
|
Rectangle {
|
|
|
|
width: 1px;
|
|
|
|
background: gray;
|
|
|
|
TouchArea {
|
|
|
|
width: 5px;
|
|
|
|
x: (parent.width - self.width) / 2;
|
|
|
|
property <length> cached;
|
|
|
|
pointer-event(event) => {
|
|
|
|
if (event.button == PointerEventButton.left && event.kind == PointerEventKind.down) {
|
|
|
|
self.cached = root.column_sizes[idx];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
moved => {
|
|
|
|
if (self.pressed) {
|
|
|
|
root.column_sizes[idx] += (self.mouse-x - self.pressed-x);
|
|
|
|
if (root.column_sizes[idx] < 20px) {
|
|
|
|
root.column_sizes[idx] = 20px;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mouse-cursor: ew-resize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
list_view := ListView {
|
|
|
|
padding: 0px;
|
|
|
|
min-width: 100px;
|
|
|
|
for r [idx] in root.values: Rectangle {
|
|
|
|
width: list_view_width;
|
|
|
|
|
|
|
|
border-radius: 5px;
|
|
|
|
height: 20px;
|
|
|
|
background: r.header-row ? ColorPalette.list_view_normal_header_color : (touch-area.has-hover ? (r.selected_row ? ColorPalette.list-view-normal-selected-header : ColorPalette.list_view_normal_color) : (r.selected_row ? ColorPalette.list-view-normal-selected-header : ColorPalette.list_view_normal_color));
|
|
|
|
touch_area := TouchArea {
|
2024-01-13 12:57:51 +00:00
|
|
|
function clicked_manual() {
|
2023-12-03 11:06:42 +00:00
|
|
|
if (!r.header_row) {
|
|
|
|
if (root.selected-item == -1) {
|
2024-01-13 12:57:51 +00:00
|
|
|
r.selected_row = !r.selected_row;
|
2023-12-03 11:06:42 +00:00
|
|
|
root.selected-item = idx;
|
|
|
|
} else {
|
2024-01-13 12:57:51 +00:00
|
|
|
if (!r.selected_row && root.selected-item != idx) {
|
|
|
|
r.selected_row = !r.selected_row;
|
2023-12-03 11:06:42 +00:00
|
|
|
root.values[root.selected-item].selected_row = false;
|
|
|
|
root.selected-item = idx;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (root.selected_item != -1) {
|
2024-02-10 22:57:52 +00:00
|
|
|
Callabler.load_image_preview(r.val_str[root.parentPathIdx - 1] + "/" + r.val_str[root.fileNameIdx - 1]);
|
2023-12-03 11:06:42 +00:00
|
|
|
} else {
|
|
|
|
GuiState.preview_visible = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-01-13 12:57:51 +00:00
|
|
|
double-clicked => {
|
2024-02-10 22:57:52 +00:00
|
|
|
Callabler.item_opened(r.val_str[root.parentPathIdx - 1] + "/" + r.val_str[root.fileNameIdx - 1])
|
2024-01-13 12:57:51 +00:00
|
|
|
}
|
2023-12-03 11:06:42 +00:00
|
|
|
pointer-event(event) => {
|
2024-01-13 12:57:51 +00:00
|
|
|
// TODO this should be clicked by double-click - https://github.com/slint-ui/slint/issues/4235
|
2023-12-03 11:06:42 +00:00
|
|
|
if (event.button == PointerEventButton.right && event.kind == PointerEventKind.up) {
|
2024-02-10 22:57:52 +00:00
|
|
|
Callabler.item_opened(r.val_str[root.parentPathIdx - 1])
|
2024-01-13 12:57:51 +00:00
|
|
|
} else if (event.button == PointerEventButton.left && event.kind == PointerEventKind.up) {
|
|
|
|
clicked_manual();
|
2023-12-03 11:06:42 +00:00
|
|
|
}
|
2024-01-13 12:57:51 +00:00
|
|
|
//else if (event.button == PointerEventButton.middle && event.kind == PointerEventKind.up) {
|
2024-02-10 22:57:52 +00:00
|
|
|
// Callabler.item_opened(r.val_str[root.parentPathIdx - 1] + "/" + r.val_str[root.fileNameIdx - 1])
|
2024-01-13 12:57:51 +00:00
|
|
|
//}
|
2023-12-03 11:06:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
HorizontalLayout {
|
|
|
|
CheckBox {
|
|
|
|
visible: !r.header-row;
|
|
|
|
checked: r.checked && !r.header-row;
|
|
|
|
width: root.column-sizes[0];
|
|
|
|
toggled => {
|
|
|
|
r.checked = self.checked;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
HorizontalLayout {
|
|
|
|
spacing: 5px;
|
2024-02-10 22:57:52 +00:00
|
|
|
for f [idx] in r.val_str: Text {
|
2023-12-03 11:06:42 +00:00
|
|
|
width: root.column-sizes[idx + 1];
|
|
|
|
text: f;
|
|
|
|
font-size: 12px;
|
|
|
|
vertical-alignment: center;
|
|
|
|
overflow: elide;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function deselect_selected_item() {
|
|
|
|
if (root.selected_item != -1) {
|
|
|
|
root.values[root.selected-item].selected_row = false;
|
|
|
|
root.selected-item = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO this should work with multiple selection and shift and control key - problably logic will need to be set in global state
|
|
|
|
public function released_key(event: KeyEvent) {
|
|
|
|
if (event.text == " ") {
|
|
|
|
if (root.selected_item != -1) {
|
|
|
|
root.values[root.selected_item].checked = !root.values[root.selected_item].checked;
|
|
|
|
}
|
|
|
|
} else if (event.text == Key.DownArrow) {
|
|
|
|
if (root.selected_item != -1) {
|
|
|
|
if (root.values.length - 1 == root.selected_item) {
|
|
|
|
// Last element, so unselect it
|
|
|
|
root.values[root.selected_item].selected_row = false;
|
|
|
|
root.selected_item = -1;
|
|
|
|
} else {
|
|
|
|
// Select next item, if next item is header row, then select second
|
|
|
|
// This should be safe, because header row should never be last item
|
|
|
|
root.values[root.selected_item].selected_row = false;
|
|
|
|
if (root.values[root.selected_item + 1].header_row) {
|
|
|
|
root.selected_item += 2;
|
|
|
|
} else {
|
|
|
|
root.selected_item += 1;
|
|
|
|
}
|
|
|
|
root.values[root.selected_item].selected_row = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Select last item if nothing is selected
|
|
|
|
if (root.values.length > 0) {
|
|
|
|
if (root.values[0].header_row) {
|
|
|
|
root.selected_item = 1;
|
|
|
|
} else {
|
|
|
|
root.selected_item = 0;
|
|
|
|
}
|
|
|
|
root.values[root.selected_item].selected_row = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (event.text == Key.UpArrow) {
|
|
|
|
if (root.selected_item != -1) {
|
|
|
|
if (root.selected_item == 0) {
|
|
|
|
// First element, so unselect it
|
|
|
|
root.values[root.selected_item].selected_row = false;
|
|
|
|
root.selected_item = -1;
|
|
|
|
} else {
|
|
|
|
root.values[root.selected_item].selected_row = false;
|
|
|
|
// Select previous item, if previous item is header row, then select second previous item
|
|
|
|
// This is safe, because if there is non header row upper, then can be easily selected,
|
|
|
|
// but otherwise is done -2 which for 1 (smallest possible item to set with header row) gives -1, so gives
|
|
|
|
// this non selected row
|
|
|
|
if (root.values[root.selected_item - 1].header_row) {
|
|
|
|
root.selected_item -= 2;
|
|
|
|
} else {
|
|
|
|
root.selected_item -= 1;
|
|
|
|
}
|
|
|
|
if (root.selected_item != -1) {
|
|
|
|
root.values[root.selected_item].selected_row = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Select last item if nothing is selected
|
|
|
|
if (root.values.length > 0) {
|
|
|
|
root.selected_item = root.values.length - 1;
|
|
|
|
root.values[root.selected_item].selected_row = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|