// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 import { Button, Palette, ScrollView, VerticalBox, GroupBox, LineEdit } from "std-widgets.slint"; export struct ComponentItem { name: string, defined_at: string, is_user_defined: bool, is_currently_shown: bool, } export struct ComponentListItem { category: string, components: [ComponentItem] } export component ComponentList { in property <[ComponentListItem]> known-components; in property preview-area-position-x; in property preview-area-position-y; in property preview-area-width; in property preview-area-height; private property list-spacing: 6px; out property over-target; pure callback can-drop(string/* component_type */, length/* x */, length/* y */, bool/* on-drop-area */) -> bool; callback drop(string/* component_type */, length/* x */, length/* y */); callback add_new_component(); callback rename_component(string/* old_name */, string/* defined_at */, string/* new_name */); callback show_preview_for(string/* name */, string/*url*/); private property preview-visible: preview-area-width > 0px && preview-area-height > 0px; private property editing-in-category: -1; function start-edit-in-category(category-index: int) { self.editing-in-category = category-index; } VerticalBox { Text { text: @tr("Library"); horizontal-alignment: center; font-size: 1.4rem; font-weight: 800; } ScrollView { VerticalLayout { spacing: root.list-spacing; for cli[index] in root.known-components: category := VerticalLayout { private property my-category-index: index; private property editing-component-index: -1; function edit-component(component-index: int) { root.start-edit-in-category(self.my-category-index); self.editing-component-index = component-index; } Rectangle { height: title.preferred-height + 10px; background: Palette.alternate-background; title := Text { font-size: 1.2rem; font-weight: 800; text: cli.category; } } for ci[index] in cli.components: component := TouchArea { private property drop-x: self.absolute-position.x + self.mouse-x - root.preview-area-position-x; private property drop-y: self.absolute-position.y + self.mouse-y - root.preview-area-position-y; private property on-drop-area: drop-x >= 0 && drop-x <= root.preview-area-width && drop-y >= 0 && drop-y <= root.preview-area-height; private property can-drop-here: !self.data.is-currently-shown && root.can-drop(self.data.name, drop-x, drop-y, on-drop-area); private property data: ci; private property my-index: index; enabled: root.preview-visible; width: 100%; private property edit-me: self.data.is-user-defined && root.editing-in-category == category.my-category-index && category.editing-component-index == self.my-index; VerticalLayout { if component.edit-me: LineEdit { horizontal-alignment: center; text: component.data.name; width: 100%; accepted(name) => { category.edit-component(-1); root.rename_component(component.data.name, component.data.defined_at, name); } } if !component.edit-me: Rectangle { t := Text { text: component.data.name; } height: t.preferred-height + 2 * root.list-spacing; width: 100%; } } if ci.is_user_defined && !ci.is-currently-shown: preview-button := Button { x: parent.x + parent.width - self.width - 4px; text: "P"; width: self.min-width; height: self.min-height; clicked() => { root.show_preview_for(component.data.name, component.data.defined_at) } } pointer-event(event) => { if (self.can-drop-here && event.kind == PointerEventKind.up && event.button == PointerEventButton.left) { root.drop(self.data.name, drop-x, drop-y); } } clicked => { category.edit-component(self.my-index); } states [ dragging-no-drop when self.pressed && !self.can-drop-here: { mouse-cursor: MouseCursor.no-drop; } dragging-can-drop when self.pressed && self.can-drop-here: { mouse-cursor: MouseCursor.copy; } normal when !self.pressed: { mouse-cursor: MouseCursor.default; } ] } if cli.category == "User Defined": Button { height: self.min-height; text: "Add Component"; clicked => { root.add_new_component(); } } } } } } }