// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 import { MaterialPalette, MaterialFontSettings, Icons } from "styling.slint"; import { SpinBoxBase } from "../common/spinbox-base.slint"; component SpinBoxButton inherits Rectangle { in-out property pressed: self.enabled && touch-area.pressed; in-out property enabled <=> touch-area.enabled; in-out property icon-opacity: 1; in-out property icon-fill: MaterialPalette.accent-foreground; callback clicked <=> touch-area.clicked; states [ disabled when !root.enabled : { background.background: MaterialPalette.control-foreground; background.opacity: 0.12; icon-opacity: 0.38; icon-fill: MaterialPalette.control-foreground; } pressed when touch-area.pressed : { state-layer.opacity: 0.12; } hover when touch-area.has-hover : { state-layer.opacity: 0.08; } ] background := Rectangle { width: 100%; height: 100%; border-radius: max(self.width, self.height) / 2; background: MaterialPalette.accent-background; } state-layer := Rectangle { x: 0; y: 0; opacity: 0; width: background.width; height: background.height; border-radius: background.border-radius; background: MaterialPalette.accent-foreground; animate opacity { duration: 250ms; easing: ease; } } Rectangle { width: 100%; height: 100%; @children } touch-area := TouchArea { } } // Increment and decrement a value in the given range. export component SpinBox { in property minimum <=> base.minimum; in property maximum <=> base.maximum; in property enabled <=> base.enabled; in property step-size <=> base.step-size; in property horizontal-alignment <=> base.horizontal-alignment; out property has-focus <=> base.has-focus; in-out property value <=> base.value; callback edited <=> base.edited; forward-focus: base; horizontal-stretch: 1; vertical-stretch: 0; min-width: layout.min-width; min-height: max(56px, layout.min-height); accessible-role: spinbox; accessible-enabled: root.enabled; accessible-value: root.value; accessible-value-minimum: root.minimum; accessible-value-maximum: root.maximum; accessible-value-step: (root.maximum - root.minimum) / 100; accessible-action-set-value(v) => { if v.is-float() { base.update-value(v.to-float()); } } accessible-action-increment => { base.increment(); } accessible-action-decrement => { base.decrement(); } states [ disabled when !root.enabled : { background.border-color: MaterialPalette.control-foreground; background.opacity: 0.38; base.opacity: 0.38; } focused when root.has-focus : { background.border-width: 2px; background.border-color: MaterialPalette.accent-background; base.color: MaterialPalette.accent-background; } ] background := Rectangle { border-radius: 4px; border-width: 1px; border-color: MaterialPalette.border; layout := HorizontalLayout { padding-top: 8px; padding-bottom: 8px; padding-left: 16px; padding-right: 12px; spacing: 16px; Rectangle { clip: true; horizontal-stretch: 1; base := SpinBoxBase { width: 100%; color: MaterialPalette.control-foreground; font-size: MaterialFontSettings.body-large.font-size; font-weight: MaterialFontSettings.body-large.font-weight; } } VerticalLayout { spacing: 4px; width: (base.min-height.max(56px - layout.padding-top - layout.padding-bottom) - self.spacing) / 2; SpinBoxButton { enabled: root.enabled; Image { x: (parent.width - self.width) / 2; y: (parent.height - self.height) / 2; source: Icons.arrow-drop-up; opacity: parent.icon-opacity; colorize: parent.icon-fill; accessible-role: none; } clicked => { base.increment(); } } SpinBoxButton { enabled: root.enabled; Image { x: (parent.width - self.width) / 2; y: (parent.height - self.height) / 2; source: Icons.arrow-drop-down; opacity: parent.icon-opacity; colorize: parent.icon-fill; accessible-role: none; } clicked => { base.decrement(); } } } } } }