mirror of
				https://github.com/slint-ui/slint.git
				synced 2025-10-30 11:37:12 +00:00 
			
		
		
		
	 2f57a4df35
			
		
	
	
		2f57a4df35
		
	
	
	
	
		
			
			Currently, the min-with don't account for the text. That means that, for example, the switch on the top bar of the gallery, get the text to overflow which doesn't look good by default
		
			
				
	
	
		
			137 lines
		
	
	
	
		
			4.6 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
	
		
			4.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 { FluentFontSettings, FluentPalette } from "styling.slint";
 | |
| import { FocusBorder } from "components.slint";
 | |
| 
 | |
| export component Switch {
 | |
|     in property <bool> enabled: true;
 | |
|     in property <string> text;
 | |
|     in-out property <bool> checked;
 | |
|     out property <bool> has-focus: focus-scope.has-focus;
 | |
| 
 | |
|     callback toggled;
 | |
| 
 | |
|     private property <color> text-color: FluentPalette.foreground;
 | |
| 
 | |
|     function toggle-checked() {
 | |
|         if(!root.enabled) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         root.checked = !root.checked;
 | |
|         root.toggled();
 | |
|     }
 | |
| 
 | |
|     min-width: max(40px, layout.min-width);
 | |
|     min-height: max(20px, layout.min-height);
 | |
|     vertical-stretch: 0;
 | |
|     horizontal-stretch: 0;
 | |
|     accessible-enabled: root.enabled;
 | |
|     accessible-label: root.text;
 | |
|     accessible-checkable: true;
 | |
|     accessible-checked <=> root.checked;
 | |
|     accessible-role: switch;
 | |
|     accessible-action-default => {
 | |
|         root.checked = !root.checked;
 | |
|         root.toggled();
 | |
|     }
 | |
|     forward-focus: focus-scope;
 | |
| 
 | |
|     states [
 | |
|         disabled when !root.enabled : {
 | |
|             rail.background: root.checked ? FluentPalette.accent-disabled : transparent;
 | |
|             rail.border-color: FluentPalette.control-strong-stroke-disabled;
 | |
|             thumb.background: FluentPalette.text-disabled;
 | |
|             root.text-color: FluentPalette.text-disabled;
 | |
|             thumb.background: root.checked ? FluentPalette.text-accent-foreground-disabled : FluentPalette.text-secondary;
 | |
|         }
 | |
|         pressed when touch-area.pressed : {
 | |
|             rail.background: root.checked ? FluentPalette.tertiary-accent-background : FluentPalette.control-alt-quartiary;
 | |
|             thumb.width: 17px;
 | |
|             thumb.height: 14px;
 | |
|             thumb.border-width: root.checked ? 1px : 0;
 | |
|             thumb.background: root.checked ? FluentPalette.accent-foreground : FluentPalette.text-secondary;
 | |
|         }
 | |
|         hover when touch-area.has-hover : {
 | |
|             rail.background:  root.checked ? FluentPalette.secondary-accent-background : FluentPalette.control-alt-tertiary;
 | |
|             thumb.width: 14px;
 | |
|             thumb.border-width: root.checked ? 1px : 0;
 | |
|             thumb.background: root.checked ? FluentPalette.accent-foreground : FluentPalette.text-secondary;
 | |
|         }
 | |
|         selected when root.checked : {
 | |
|             rail.background: FluentPalette.accent-background;
 | |
|             thumb.border-width: 1px;
 | |
|             thumb.border-color: FluentPalette.circle-border;
 | |
|             thumb.background: FluentPalette.accent-foreground;
 | |
|         }
 | |
|     ]
 | |
| 
 | |
|     layout := HorizontalLayout {
 | |
|         spacing: 12px;
 | |
| 
 | |
|         VerticalLayout {
 | |
|             alignment: center;
 | |
| 
 | |
|            Rectangle {
 | |
|                 width: 40px;
 | |
|                 height: 20px;
 | |
| 
 | |
|                 rail := Rectangle {
 | |
|                     border-radius: 10px;
 | |
|                     border-width: root.checked ? 0 : 1px;
 | |
|                     border-color: FluentPalette.control-strong-stroke;
 | |
|                     background: FluentPalette.control-alt-secondary;
 | |
|                 }
 | |
| 
 | |
|                 thumb := Rectangle {
 | |
|                     x: root.checked ? parent.width - self.width - 4px : 4px;
 | |
|                     y: (parent.height - self.height) / 2;
 | |
|                     width: 12px;
 | |
|                     height: self.width;
 | |
|                     border-radius: self.height / 2;
 | |
|                     background: FluentPalette.text-secondary;
 | |
|                     border-color: FluentPalette.circle-border;
 | |
| 
 | |
|                     animate background, width { duration: 150ms; easing: linear; }
 | |
|                 }
 | |
| 
 | |
|                 // focus border
 | |
|                 if root.has-focus && root.enabled : FocusBorder {
 | |
|                     border-radius: rail.border-radius;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (root.text != "") : Text {
 | |
|             text: root.text;
 | |
|             color: root.text-color;
 | |
|             font-size: FluentFontSettings.body.font-size;
 | |
|             font-weight: FluentFontSettings.body.font-weight;
 | |
|             vertical-alignment: center;
 | |
|             horizontal-alignment: left;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     touch-area := TouchArea {
 | |
|         enabled <=> root.enabled;
 | |
| 
 | |
|         clicked => {
 | |
|             root.toggle-checked();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     focus-scope := FocusScope {
 | |
|         x:0;
 | |
|         width: 0px; // Do not react on clicks
 | |
|         enabled <=> root.enabled;
 | |
| 
 | |
|         key-pressed(event) => {
 | |
|             if (event.text == " " || event.text == "\n") {
 | |
|                  root.toggle-checked();
 | |
|                  return accept;
 | |
|             }
 | |
|             return reject;
 | |
|         }
 | |
|     }
 | |
| }
 |