// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: MIT import { Animations } from "../styling/animations.slint"; import { MaterialPalette } from "../styling/material_palette.slint"; import { ToolTip } from "./tooltip.slint"; import { MaterialWindowAdapter } from "./material_window.slint"; export component Ripple { in property border_radius; in property pressed_x; in property pressed_y; in property color; in property clip_ripple: true; Rectangle { width: 100%; height: 100%; border_radius: root.border_radius; clip: root.clip_ripple; ripple := Rectangle { x: root.pressed_x - self.width / 2; y: root.pressed_y - self.height / 2; height: self.width; border_radius: self.width / 2; opacity: MaterialPalette.state_layer_opacity_press; background: root.color; init => { self.width = root.width * 2 * 1.4142; } animate width { duration: Animations.ripple_duration; easing: Animations.ripple_easing; } } } } export component StateLayer { in property background; in property border_radius; in property display_background: true; in property enabled; in property pressed; in property has_focus; in property has_hover; property state_layer_opacity; Rectangle { width: 100%; height: 100%; opacity: root.state_layer_opacity; background: root.background; border_radius: root.border_radius; } Rectangle { width: 100%; height: 100%; clip: true; border_radius: root.border_radius; @children } states [ disabled when !root.enabled && root.display_background : { root.state_layer_opacity: MaterialPalette.state_layer_opacity_focus; } focus when root.enabled && root.has_focus : { root.state_layer_opacity: MaterialPalette.state_layer_opacity_focus; } pressed when root.enabled && root.pressed : { root.state_layer_opacity: MaterialPalette.state_layer_opacity_press; } hover when root.enabled && root.has_hover && !MaterialWindowAdapter.disable_hover : { root.state_layer_opacity: MaterialPalette.state_layer_opacity_hover; } ] animate state_layer_opacity { duration: Animations.opacity_duration; easing: Animations.opacity_easing; } } export component FocusTouchArea inherits TouchArea { out property has_focus <=> focus_scope.has_focus; out property enter_pressed; in property tooltip; in property tooltip_offset; callback key_pressed(KeyEvent) -> EventResult; forward_focus: focus_scope; focus_scope := FocusScope { x: 0; width: 0px; enabled: root.enabled; key_pressed(event) => { if !root.enabled { return reject; } if (event.text == " " || event.text == "\n") && !root.enter_pressed { root.enter_pressed = true; root.clicked(); return accept; } root.key_pressed(event) } key_released(event) => { if !root.enabled { return reject; } if (event.text == " " || event.text == "\n") && root.enter_pressed { root.enter_pressed = false; return accept; } reject } } @children if root.tooltip != "" && root.has_hover && !MaterialWindowAdapter.disable_hover && !root.pressed : ToolTip { y: root.tooltip_offset; text: root.tooltip; } } export component StateLayerArea inherits FocusTouchArea { in property color; in property border_radius; in property transparent_background; in property display_background: true; in property clip_ripple: true; property popup_open; property has_h: root.mouse-x > 0 && root.mouse-x < root.width && root.mouse-y > 0 && root.mouse-y < root.height; if !root.enabled || (root.enabled && (root.has_focus || root.pressed || root.enter_pressed || root.has_hover)) : StateLayer { width: 100%; height: 100%; background: root.transparent_background ? transparent : root.color; border_radius: root.border_radius; enabled: root.enabled; pressed: root.pressed || root.enter_pressed; has_focus: root.has_focus; has_hover: root.has_hover; display_background: root.display_background; } // ripple if root.enabled && (root.pressed || root.enter_pressed) : Ripple { pressed_x: root.pressed_x; pressed_y: root.pressed_y; width: 100%; height: 100%; border_radius: root.border_radius; color: root.color; clip_ripple: root.clip_ripple; } @children }