mirror of
https://gitlab.com/asus-linux/asusctl.git
synced 2026-02-06 00:15:04 +01:00
feat(rog-control-center): Major UI/UX improvements and new features
- Add software RGB animations for static-only keyboards (rainbow, color cycle) - Add custom fan curve control via direct sysfs for unsupported laptops - Add real-time system status bar (CPU/GPU temps, fan speeds, power draw) - Add tray icon tooltip with live system stats - Add power profile change notifications (Fn+F5) - Add dGPU status notifications - Add ROG theme with dark palette and accent colors - Add Screenpad, Slash, and SuperGFX page stubs - Improve fan curve graph UI - Various UI refinements and fixes Co-Authored-By: Gemini <noreply@google.com>
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
import { Palette, VerticalBox, HorizontalBox, GroupBox } from "std-widgets.slint";
|
||||
import { VerticalBox, HorizontalBox, GroupBox } from "std-widgets.slint";
|
||||
import { SystemToggleVert, SystemDropdown } from "common.slint";
|
||||
import { PowerZones } from "../types/aura_types.slint";
|
||||
import { RogPalette } from "../themes/rog_theme.slint";
|
||||
|
||||
export component AuraPowerGroup inherits Rectangle {
|
||||
min-width: row.min-width;
|
||||
border-radius: 20px;
|
||||
background: Palette.alternate-background;
|
||||
opacity: 0.9;
|
||||
border-radius: 8px;
|
||||
background: RogPalette.control-background;
|
||||
border-width: 1px;
|
||||
border-color: RogPalette.control-border;
|
||||
in-out property <string> group-title;
|
||||
in-out property <bool> boot_checked;
|
||||
in-out property <bool> awake_checked;
|
||||
@@ -20,7 +22,7 @@ export component AuraPowerGroup inherits Rectangle {
|
||||
spacing: 10px;
|
||||
Text {
|
||||
font-size: 18px;
|
||||
color: Palette.alternate-foreground;
|
||||
color: RogPalette.text-primary;
|
||||
horizontal-alignment: TextHorizontalAlignment.center;
|
||||
text <=> root.group-title;
|
||||
}
|
||||
@@ -72,9 +74,10 @@ export component AuraPowerGroup inherits Rectangle {
|
||||
|
||||
export component AuraPowerGroupOld inherits Rectangle {
|
||||
min-width: row.min-width;
|
||||
border-radius: 20px;
|
||||
background: Palette.alternate-background;
|
||||
opacity: 0.9;
|
||||
border-radius: 8px;
|
||||
background: RogPalette.control-background;
|
||||
border-width: 1px;
|
||||
border-color: RogPalette.control-border;
|
||||
in-out property <int> current_zone;
|
||||
in-out property <[int]> zones;
|
||||
in-out property <[string]> zone_strings;
|
||||
@@ -90,7 +93,7 @@ export component AuraPowerGroupOld inherits Rectangle {
|
||||
spacing: 10px;
|
||||
Text {
|
||||
font-size: 18px;
|
||||
color: Palette.alternate-foreground;
|
||||
color: RogPalette.text-primary;
|
||||
horizontal-alignment: TextHorizontalAlignment.center;
|
||||
text <=> root.group-title;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { Palette, VerticalBox , StandardButton, Button, HorizontalBox, ComboBox, Switch, Slider} from "std-widgets.slint";
|
||||
import { VerticalBox , StandardButton, Button, HorizontalBox, ComboBox, Switch, Slider} from "std-widgets.slint";
|
||||
import { RogPalette } from "../themes/rog_theme.slint";
|
||||
|
||||
export component RogItem inherits Rectangle {
|
||||
background: Palette.control-background;
|
||||
border-color: Palette.border;
|
||||
border-width: 3px;
|
||||
border-radius: 10px;
|
||||
in property <bool> enabled: true;
|
||||
background: root.enabled ? RogPalette.control-background : RogPalette.control-background.darker(0.5);
|
||||
border-color: root.enabled ? RogPalette.control-border : RogPalette.control-border.darker(0.3);
|
||||
border-width: 1px; // Thinner border for modern look
|
||||
border-radius: RogPalette.border-radius;
|
||||
min-height: 48px;
|
||||
max-height: 56px;
|
||||
opacity: root.enabled ? 1.0 : 0.6;
|
||||
}
|
||||
|
||||
export component SystemSlider inherits RogItem {
|
||||
@@ -18,7 +21,6 @@ export component SystemSlider inherits RogItem {
|
||||
callback released(float);
|
||||
|
||||
in property <string> help_text;
|
||||
in property <bool> enabled: true;
|
||||
in property <bool> has_reset: false;
|
||||
callback cb_do_reset();
|
||||
|
||||
@@ -32,7 +34,7 @@ export component SystemSlider inherits RogItem {
|
||||
Text {
|
||||
font-size: 16px;
|
||||
vertical-alignment: TextVerticalAlignment.center;
|
||||
color: Palette.control-foreground;
|
||||
color: RogPalette.text-primary;
|
||||
text: root.text;
|
||||
}
|
||||
|
||||
@@ -40,7 +42,7 @@ export component SystemSlider inherits RogItem {
|
||||
font-size: 16px;
|
||||
horizontal-alignment: TextHorizontalAlignment.right;
|
||||
vertical-alignment: TextVerticalAlignment.center;
|
||||
color: Palette.control-foreground;
|
||||
color: RogPalette.accent;
|
||||
text: "\{Math.round(root.value)}";
|
||||
}
|
||||
}
|
||||
@@ -64,10 +66,11 @@ export component SystemSlider inherits RogItem {
|
||||
y: help.y - self.height + help.height - 10px;
|
||||
Rectangle {
|
||||
drop-shadow-blur: 10px;
|
||||
drop-shadow-color: black;
|
||||
border-radius: 10px;
|
||||
border-color: Palette.accent-background;
|
||||
background: Palette.background;
|
||||
drop-shadow-color: Colors.black;
|
||||
border-radius: RogPalette.border-radius;
|
||||
border-width: 1px;
|
||||
border-color: RogPalette.accent;
|
||||
background: RogPalette.control-background;
|
||||
Dialog {
|
||||
title: root.title;
|
||||
VerticalBox {
|
||||
@@ -77,12 +80,12 @@ export component SystemSlider inherits RogItem {
|
||||
wrap: TextWrap.word-wrap;
|
||||
horizontal-alignment: TextHorizontalAlignment.center;
|
||||
text: root.title;
|
||||
color: RogPalette.text-primary;
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
height: 1px;
|
||||
border-color: black;
|
||||
border-width: 1px;
|
||||
background: RogPalette.control-border;
|
||||
}
|
||||
|
||||
Text {
|
||||
@@ -90,6 +93,7 @@ export component SystemSlider inherits RogItem {
|
||||
font-size: 16px;
|
||||
wrap: TextWrap.word-wrap;
|
||||
text: root.help_text;
|
||||
color: RogPalette.text-secondary;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,16 +118,18 @@ export component SystemSlider inherits RogItem {
|
||||
y: reset.y - self.height + reset.height;
|
||||
Rectangle {
|
||||
drop-shadow-blur: 10px;
|
||||
drop-shadow-color: black;
|
||||
border-radius: 10px;
|
||||
border-color: Palette.accent-background;
|
||||
background: Palette.background;
|
||||
drop-shadow-color: Colors.black;
|
||||
border-radius: RogPalette.border-radius;
|
||||
border-width: 1px;
|
||||
border-color: RogPalette.accent;
|
||||
background: RogPalette.control-background;
|
||||
Dialog {
|
||||
Text {
|
||||
max-width: 420px;
|
||||
font-size: 16px;
|
||||
wrap: TextWrap.word-wrap;
|
||||
text: @tr("confirm_reset" => "Are you sure you want to reset this?");
|
||||
color: RogPalette.text-primary;
|
||||
}
|
||||
|
||||
StandardButton {
|
||||
@@ -164,7 +170,7 @@ export component SystemToggle inherits RogItem {
|
||||
Text {
|
||||
font-size: 16px;
|
||||
vertical-alignment: TextVerticalAlignment.center;
|
||||
color: Palette.control-foreground;
|
||||
color: RogPalette.text-primary;
|
||||
text: root.text;
|
||||
}
|
||||
}
|
||||
@@ -195,7 +201,7 @@ export component SystemToggleInt inherits RogItem {
|
||||
Text {
|
||||
font-size: 16px;
|
||||
vertical-alignment: TextVerticalAlignment.center;
|
||||
color: Palette.control-foreground;
|
||||
color: RogPalette.text-primary;
|
||||
text: root.text;
|
||||
}
|
||||
}
|
||||
@@ -226,7 +232,7 @@ export component SystemToggleVert inherits RogItem {
|
||||
font-size: 16px;
|
||||
vertical-alignment: TextVerticalAlignment.bottom;
|
||||
horizontal-alignment: TextHorizontalAlignment.center;
|
||||
color: Palette.control-foreground;
|
||||
color: RogPalette.text-primary;
|
||||
text: root.text;
|
||||
}
|
||||
|
||||
@@ -256,7 +262,7 @@ export component SystemDropdown inherits RogItem {
|
||||
Text {
|
||||
font-size: 16px;
|
||||
vertical-alignment: TextVerticalAlignment.center;
|
||||
color: Palette.control-foreground;
|
||||
color: RogPalette.text-primary;
|
||||
text: root.text;
|
||||
}
|
||||
}
|
||||
@@ -288,9 +294,9 @@ export component PopupNotification {
|
||||
height: root.height;
|
||||
// TODO: add properties to display
|
||||
Rectangle {
|
||||
border-width: 2px;
|
||||
border-color: Palette.accent-background;
|
||||
background: Palette.background;
|
||||
border-width: 1px;
|
||||
border-color: RogPalette.accent;
|
||||
background: RogPalette.background;
|
||||
// TODO: drop shadows slow
|
||||
// drop-shadow-offset-x: 7px;
|
||||
// drop-shadow-offset-y: 7px;
|
||||
@@ -302,14 +308,14 @@ export component PopupNotification {
|
||||
alignment: start;
|
||||
Text {
|
||||
text: heading;
|
||||
color: Palette.control-foreground;
|
||||
color: RogPalette.text-primary;
|
||||
font-size: 32px;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
Text {
|
||||
text: content;
|
||||
color: Palette.control-foreground;
|
||||
color: RogPalette.text-secondary;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Palette } from "std-widgets.slint";
|
||||
import { RogPalette } from "../themes/rog_theme.slint";
|
||||
|
||||
export struct Node { x: length, y: length}
|
||||
|
||||
@@ -44,7 +45,7 @@ export component Graph inherits Rectangle {
|
||||
for n in 11: Path {
|
||||
viewbox-width: self.width / 1px;
|
||||
viewbox-height: self.height / 1px;
|
||||
stroke: Palette.alternate-foreground.darker(200%);
|
||||
stroke: RogPalette.control-border;
|
||||
stroke-width: 1px;
|
||||
MoveTo {
|
||||
x: scale_x_to_graph(n * 10px) / 1px;
|
||||
@@ -60,7 +61,7 @@ export component Graph inherits Rectangle {
|
||||
}
|
||||
|
||||
for n in 11: Text {
|
||||
color: Palette.accent-background;
|
||||
color: RogPalette.text-secondary;
|
||||
font-size <=> root.axis_font_size;
|
||||
text: "\{n * 10}c";
|
||||
x: scale_x_to_graph(n * 10px) - self.width / 3;
|
||||
@@ -70,7 +71,7 @@ export component Graph inherits Rectangle {
|
||||
for n in 11: Path {
|
||||
viewbox-width: self.width / 1px;
|
||||
viewbox-height: self.height / 1px;
|
||||
stroke: Palette.alternate-foreground.darker(200%);
|
||||
stroke: RogPalette.control-border;
|
||||
stroke-width: 1px;
|
||||
MoveTo {
|
||||
x: 0;
|
||||
@@ -86,7 +87,7 @@ export component Graph inherits Rectangle {
|
||||
}
|
||||
|
||||
for n in 11: Text {
|
||||
color: Palette.accent-background;
|
||||
color: RogPalette.text-secondary;
|
||||
font-size <=> root.axis_font_size;
|
||||
text: "\{n * 10}%";
|
||||
x: - self.width;
|
||||
@@ -97,7 +98,7 @@ export component Graph inherits Rectangle {
|
||||
if idx + 1 != nodes.length: Path {
|
||||
viewbox-width: self.width / 1px;
|
||||
viewbox-height: self.height / 1px;
|
||||
stroke: Palette.control-foreground;
|
||||
stroke: RogPalette.accent;
|
||||
stroke-width: 2px;
|
||||
MoveTo {
|
||||
x: scale_x_to_graph(nodes[idx].x) / 1px;
|
||||
@@ -114,19 +115,19 @@ export component Graph inherits Rectangle {
|
||||
for n[idx] in nodes: Rectangle {
|
||||
states [
|
||||
pressed when touch.pressed: {
|
||||
point.background: Palette.selection-background;
|
||||
tip.background: Palette.selection-background;
|
||||
point.background: RogPalette.accent;
|
||||
tip.background: RogPalette.accent;
|
||||
tip.opacity: 1.0;
|
||||
}
|
||||
hover when touch.has-hover: {
|
||||
point.background: Palette.accent-background;
|
||||
tip.background: Palette.accent-background;
|
||||
point.background: RogPalette.accent;
|
||||
tip.background: RogPalette.accent;
|
||||
tip.opacity: 1.0;
|
||||
}
|
||||
]
|
||||
//
|
||||
point := Rectangle {
|
||||
background: Palette.control-foreground;
|
||||
background: RogPalette.text-primary;
|
||||
x: scale_x_to_graph(n.x) - self.width / 2;
|
||||
y: graph.height - scale_y_to_graph(n.y) - self.height / 2;
|
||||
width: 18px;
|
||||
@@ -142,10 +143,14 @@ export component Graph inherits Rectangle {
|
||||
} else if n.x + scale_x_to_node(self.mouse-x - self.pressed-x) < nodes[idx - 1].x {
|
||||
n.x = nodes[idx - 1].x + pad;
|
||||
}
|
||||
|
||||
// Y-Axis: Monotonic Non-Decreasing
|
||||
if n.y + scale_y_to_node(self.height - self.mouse-y - self.pressed-y) > nodes[idx + 1].y {
|
||||
n.y = nodes[idx + 1].y - pad;
|
||||
n.y = nodes[idx + 1].y; // Allow equality
|
||||
} else if n.y + scale_y_to_node(self.height - self.mouse-y - self.pressed-y) < nodes[idx - 1].y {
|
||||
n.y = nodes[idx - 1].y + pad;
|
||||
n.y = nodes[idx - 1].y; // Allow equality
|
||||
} else if n.y + scale_y_to_node(self.height - self.mouse-y - self.pressed-y) < 0.0 {
|
||||
n.y = 0px;
|
||||
}
|
||||
} else if idx == 0 {
|
||||
if n.x + scale_x_to_node(self.mouse-x - self.pressed-x) < 0.0 {
|
||||
@@ -153,10 +158,12 @@ export component Graph inherits Rectangle {
|
||||
} else if n.x + scale_x_to_node(self.mouse-x - self.pressed-x) > nodes[idx + 1].x {
|
||||
n.x = nodes[idx + 1].x - pad;
|
||||
}
|
||||
|
||||
// Y-Axis: <= Next Point
|
||||
if n.y - scale_y_to_node(self.mouse-y - self.pressed-y) < 0.0 {
|
||||
n.y = 1px;
|
||||
n.y = 0px; // Allow 0 RPM
|
||||
} else if n.y + scale_y_to_node(self.height - self.mouse-y - self.pressed-y) > nodes[idx + 1].y {
|
||||
n.y = nodes[idx + 1].y - pad;
|
||||
n.y = nodes[idx + 1].y; // Allow equality
|
||||
}
|
||||
} else if idx == nodes.length - 1 {
|
||||
if n.x + scale_x_to_node(self.mouse-x - self.pressed-x) > scale_x_to_node(graph.width) {
|
||||
@@ -164,10 +171,14 @@ export component Graph inherits Rectangle {
|
||||
} else if n.x + scale_x_to_node(self.mouse-x - self.pressed-x) < nodes[idx - 1].x {
|
||||
n.x = nodes[idx - 1].x + pad;
|
||||
}
|
||||
|
||||
// Y-Axis: >= Previous Point
|
||||
if n.y - scale_y_to_node(self.mouse-y - self.pressed-y) > scale_y_to_node(graph.height) {
|
||||
n.y = scale_y_to_node(graph.height - 1px);
|
||||
n.y = scale_y_to_node(graph.height);
|
||||
} else if n.y + scale_y_to_node(self.height - self.mouse-y - self.pressed-y) < nodes[idx - 1].y {
|
||||
n.y = nodes[idx - 1].y + pad;
|
||||
n.y = nodes[idx - 1].y; // Allow equality
|
||||
} else if n.y + scale_y_to_node(self.height - self.mouse-y - self.pressed-y) < 0.0 {
|
||||
n.y = 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,7 +200,7 @@ export component Graph inherits Rectangle {
|
||||
}
|
||||
|
||||
tip := Rectangle {
|
||||
background: Palette.control-foreground;
|
||||
background: RogPalette.control-background;
|
||||
opacity: 0.3;
|
||||
x: final_x_pos();
|
||||
y: final_y_pos();
|
||||
@@ -224,7 +235,7 @@ export component Graph inherits Rectangle {
|
||||
}
|
||||
//
|
||||
label := Text {
|
||||
color: Palette.accent-foreground;
|
||||
color: RogPalette.text-primary;
|
||||
font-size: 16px;
|
||||
text: "\{Math.floor(n.x / 1px)}c, \{fan_pct()}%";
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { Palette, HorizontalBox, VerticalBox } from "std-widgets.slint";
|
||||
import { HorizontalBox, VerticalBox } from "std-widgets.slint";
|
||||
import { RogPalette } from "../themes/rog_theme.slint";
|
||||
|
||||
component SideBarItem inherits Rectangle {
|
||||
// padding only has effect on layout elements
|
||||
@@ -28,12 +29,21 @@ component SideBarItem inherits Rectangle {
|
||||
]
|
||||
state := Rectangle {
|
||||
opacity: 0;
|
||||
border-width: 2px;
|
||||
border-radius: 10px;
|
||||
border-color: Palette.accent-background;
|
||||
background: Palette.alternate-background;
|
||||
border-width: 0px; // Modern look: no full border, maybe just a left bar?
|
||||
// Or keep the ROG style border
|
||||
border-color: RogPalette.accent;
|
||||
background: root.selected ? RogPalette.control-background : RogPalette.alternate-background;
|
||||
|
||||
// Add a red indicator line on the left for selected items
|
||||
Rectangle {
|
||||
x: 0;
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
background: root.selected ? RogPalette.accent : Colors.transparent;
|
||||
}
|
||||
|
||||
animate opacity { duration: 150ms; }
|
||||
animate border-width { duration: 150ms; }
|
||||
// animate border-width { duration: 150ms; }
|
||||
height: l.preferred-height;
|
||||
}
|
||||
|
||||
@@ -41,9 +51,10 @@ component SideBarItem inherits Rectangle {
|
||||
y: (parent.height - self.height) / 2;
|
||||
spacing: 0px;
|
||||
label := Text {
|
||||
color: Palette.foreground;
|
||||
color: root.selected ? RogPalette.accent : RogPalette.text-primary;
|
||||
vertical-alignment: center;
|
||||
font-size: 14px;
|
||||
font-weight: root.selected ? 700 : 400;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,10 +77,10 @@ export component SideBar inherits Rectangle {
|
||||
accessible-role: tab;
|
||||
accessible-delegate-focus: root.current-focused >= 0 ? root.current-focused : root.current-item;
|
||||
Rectangle {
|
||||
border-width: 2px;
|
||||
border-color: Palette.accent-background;
|
||||
border-width: 0px;
|
||||
// border-color: RogPalette.accent;
|
||||
border-radius: 0px;
|
||||
background: Palette.background.darker(0.2);
|
||||
background: RogPalette.alternate-background; // Darker sidebar
|
||||
fs := FocusScope {
|
||||
key-pressed(event) => {
|
||||
if (event.text == "\n") {
|
||||
@@ -104,12 +115,19 @@ export component SideBar inherits Rectangle {
|
||||
spacing: 4px;
|
||||
alignment: start;
|
||||
label := Text {
|
||||
font-size: 16px;
|
||||
font-size: 24px; // Larger brand text
|
||||
font-weight: 800;
|
||||
horizontal-alignment: center;
|
||||
color: RogPalette.accent; // ROG Red brand text
|
||||
}
|
||||
|
||||
// Spacer after brand text
|
||||
Rectangle {
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
navigation := VerticalLayout {
|
||||
spacing: -6px;
|
||||
spacing: 4px; // Spacing between items
|
||||
alignment: start;
|
||||
vertical-stretch: 0;
|
||||
for item[index] in root.model: SideBarItem {
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { RogPalette } from "../themes/rog_theme.slint";
|
||||
|
||||
export global SystemStatus {
|
||||
in property <int> cpu_temp: 0;
|
||||
in property <int> gpu_temp: 0;
|
||||
in property <int> cpu_fan: 0;
|
||||
in property <int> gpu_fan: 0;
|
||||
in property <string> power_w: "--";
|
||||
in property <string> power_avg_w: "--";
|
||||
}
|
||||
|
||||
component StatusItem inherits Rectangle {
|
||||
in property <string> label;
|
||||
in property <string> value;
|
||||
in property <string> unit;
|
||||
|
||||
HorizontalLayout {
|
||||
spacing: 5px;
|
||||
Text { text: label; color: RogPalette.text-secondary; font-weight: 700; vertical-alignment: center; }
|
||||
Text { text: value; color: RogPalette.text-primary; vertical-alignment: center; }
|
||||
Text { text: unit; color: RogPalette.text-secondary; font-size: 12px; vertical-alignment: center; }
|
||||
}
|
||||
}
|
||||
|
||||
export component StatusBar inherits Rectangle {
|
||||
background: RogPalette.control-background;
|
||||
height: 30px;
|
||||
|
||||
// Simulated top border
|
||||
Rectangle {
|
||||
y: 0px;
|
||||
x: 0px;
|
||||
width: parent.width;
|
||||
height: 1px;
|
||||
background: RogPalette.control-border;
|
||||
}
|
||||
|
||||
HorizontalLayout {
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
spacing: 20px;
|
||||
alignment: space-between;
|
||||
|
||||
HorizontalLayout {
|
||||
spacing: 20px;
|
||||
StatusItem { label: "CPU"; value: SystemStatus.cpu_temp; unit: "°C"; }
|
||||
StatusItem { label: "GPU"; value: SystemStatus.gpu_temp; unit: "°C"; }
|
||||
}
|
||||
|
||||
HorizontalLayout {
|
||||
spacing: 20px;
|
||||
StatusItem { label: "PWR"; value: SystemStatus.power_w; unit: "W"; }
|
||||
StatusItem { label: "AVG"; value: SystemStatus.power_avg_w; unit: "W"; }
|
||||
StatusItem { label: "CPU Fan"; value: SystemStatus.cpu_fan; unit: "RPM"; }
|
||||
StatusItem { label: "GPU Fan"; value: SystemStatus.gpu_fan; unit: "RPM"; }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user