mirror of
				https://github.com/slint-ui/slint.git
				synced 2025-11-03 21:24:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			177 lines
		
	
	
	
		
			6 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
	
		
			6 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 { HorizontalBox, Palette, ScrollView } from "std-widgets.slint";
 | 
						|
import { ComponentListItem, ComponentItem } from "../api.slint";
 | 
						|
import { StateLayer } from "./state-layer.slint";
 | 
						|
import { EditorSizeSettings, EditorAnimationSettings, Icons } from "./styling.slint";
 | 
						|
import { BodyText } from "./body-text.slint";
 | 
						|
import { BodyStrongText } from "./body-strong-text.slint";
 | 
						|
import { StatusLineApi } from "status-line.slint";
 | 
						|
 | 
						|
component HeaderItemTemplate {
 | 
						|
    in property <bool> enabled: true;
 | 
						|
    in property <string> text;
 | 
						|
    out property <bool> open: true;
 | 
						|
    out property <length> offset: icon-image.width + content-layer.spacing;
 | 
						|
 | 
						|
    min-width: content-layer.min-width;
 | 
						|
    min-height: max(EditorSizeSettings.item-height, content-layer.min-height);
 | 
						|
 | 
						|
    touch-area := TouchArea {
 | 
						|
        clicked => {
 | 
						|
            root.open = !root.open;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    state-layer := StateLayer {
 | 
						|
        width: 100%;
 | 
						|
        height: 100%;
 | 
						|
        has-hover: touch-area.has-hover;
 | 
						|
        pressed: touch-area.pressed;
 | 
						|
    }
 | 
						|
 | 
						|
    content-layer := HorizontalBox {
 | 
						|
        icon-image := Image {
 | 
						|
            width: EditorSizeSettings.default-icon-width;
 | 
						|
            colorize: Palette.foreground;
 | 
						|
            source: Icons.chevron-down;
 | 
						|
            rotation-origin-x: self.width / 2;
 | 
						|
            rotation-origin-y: self.height / 2;
 | 
						|
            states [
 | 
						|
                closed when !root.open: {
 | 
						|
                    rotation-angle: -0.25turn;
 | 
						|
                }
 | 
						|
            ]
 | 
						|
 | 
						|
            animate rotation-angle { duration: EditorAnimationSettings.rotation-duration; }
 | 
						|
        }
 | 
						|
 | 
						|
        BodyText {
 | 
						|
            text: root.text;
 | 
						|
            opacity: 0.7;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    states [
 | 
						|
        disabled when !root.enabled: {
 | 
						|
            root.opacity: 0.5;
 | 
						|
        }
 | 
						|
    ]
 | 
						|
}
 | 
						|
 | 
						|
component ItemTemplate {
 | 
						|
    in property <bool> enabled: true;
 | 
						|
    in property <string> text;
 | 
						|
    in property <bool> can-drop-here;
 | 
						|
    in property <length> offset;
 | 
						|
    out property <length> absolute-mouse-x: touch-area.mouse-x - touch-area.x + touch-area.absolute-position.x;
 | 
						|
    out property <length> absolute-mouse-y: touch-area.mouse-y - touch-area.y + touch-area.absolute-position.y;
 | 
						|
    out property <bool> pressed <=> touch-area.pressed;
 | 
						|
 | 
						|
    callback clicked <=> touch-area.clicked;
 | 
						|
    callback pointer-event <=> touch-area.pointer-event;
 | 
						|
 | 
						|
    min-width: content-layer.min-width;
 | 
						|
    min-height: max(EditorSizeSettings.item-height, content-layer.min-height);
 | 
						|
 | 
						|
    touch-area := TouchArea {
 | 
						|
        states [
 | 
						|
            dragging-no-drop when self.pressed && !root.can-drop-here: {
 | 
						|
                mouse-cursor: MouseCursor.no-drop;
 | 
						|
            }
 | 
						|
            dragging-can-drop when self.pressed && root.can-drop-here: {
 | 
						|
                mouse-cursor: MouseCursor.copy;
 | 
						|
            }
 | 
						|
            normal when !self.pressed: {
 | 
						|
                mouse-cursor: MouseCursor.default;
 | 
						|
            }
 | 
						|
        ]
 | 
						|
 | 
						|
        changed has-hover => {
 | 
						|
            if self.has-hover {
 | 
						|
                StatusLineApi.help-text = @tr("Drag onto canvas to add {}", text);
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    state-layer := StateLayer {
 | 
						|
        width: 100%;
 | 
						|
        height: 100%;
 | 
						|
        has-hover: touch-area.has-hover;
 | 
						|
        pressed: touch-area.pressed;
 | 
						|
    }
 | 
						|
 | 
						|
    content-layer := HorizontalBox {
 | 
						|
        padding-left: self.padding + root.offset;
 | 
						|
        BodyText {
 | 
						|
            text: root.text;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    states [
 | 
						|
        disabled when !root.enabled: {
 | 
						|
            root.opacity: 0.5;
 | 
						|
        }
 | 
						|
    ]
 | 
						|
}
 | 
						|
 | 
						|
export component ExpandableListView inherits ScrollView {
 | 
						|
    in property <[ComponentListItem]> known-components;
 | 
						|
 | 
						|
    in property <bool> preview-is-current;
 | 
						|
    in property <length> preview-area-position-x;
 | 
						|
    in property <length> preview-area-position-y;
 | 
						|
    in property <length> preview-area-width;
 | 
						|
    in property <length> preview-area-height;
 | 
						|
    in-out property <ComponentItem> visible-component: {
 | 
						|
        name: "",
 | 
						|
        defined-at: "",
 | 
						|
        pretty-location: "",
 | 
						|
        is-user-defined: false,
 | 
						|
        is-currently-shown: false,
 | 
						|
    };
 | 
						|
 | 
						|
    pure callback can-drop(index: int, x: length, y: length, on-drop-area: bool) -> bool;
 | 
						|
    callback drop(index: int, x: length, y: length);
 | 
						|
    callback show-preview-for(name: string, defined-at: string);
 | 
						|
 | 
						|
    property <bool> preview-visible: preview-area-width > 0px && preview-area-height > 0px;
 | 
						|
    property <length> list-spacing: 10px;
 | 
						|
 | 
						|
    VerticalLayout {
 | 
						|
        alignment: start;
 | 
						|
        for cli[index] in root.known-components: VerticalLayout {
 | 
						|
            property <int> my-category-index: index;
 | 
						|
            header-item := HeaderItemTemplate {
 | 
						|
                text: cli.category;
 | 
						|
            }
 | 
						|
 | 
						|
            if header-item.open: VerticalLayout {
 | 
						|
                for ci[index] in cli.components: ItemTemplate {
 | 
						|
                    property <length> drop-x: self.absolute-mouse-x - root.preview-area-position-x;
 | 
						|
                    property <length> drop-y: self.absolute-mouse-y - root.preview-area-position-y;
 | 
						|
                    property <bool> on-drop-area:
 | 
						|
                            drop-x >= 0 && drop-x <= root.preview-area-width && drop-y >= 0 && drop-y <= root.preview-area-height;
 | 
						|
                    property <ComponentItem> data: ci;
 | 
						|
 | 
						|
                    can-drop-here: root.preview-is-current && !self.data.is-currently-shown && root.can-drop(self.data.index, drop-x, drop-y, on-drop-area);
 | 
						|
                    enabled: root.preview-visible;
 | 
						|
                    text: ci.name;
 | 
						|
                    offset: header-item.offset;
 | 
						|
                    height: self.min-height;
 | 
						|
 | 
						|
                    pointer-event(event) => {
 | 
						|
                        if self.can-drop-here && event.kind == PointerEventKind.up && event.button == PointerEventButton.left {
 | 
						|
                            root.drop(self.data.index, drop-x, drop-y);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    init() => {
 | 
						|
                        root.visible-component = ci;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 |