Files
asusctl/rog-control-center/ui/main_window.slint
mihai2mn 3d0caa39e1 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>
2026-01-15 20:09:40 +01:00

316 lines
9.7 KiB
Plaintext

import { Button, VerticalBox } from "std-widgets.slint";
import { AppSize } from "globals.slint";
import { PageSystem, SystemPageData, AttrMinMax } from "pages/system.slint";
import { SideBar } from "widgets/sidebar.slint";
import { PageAbout } from "pages/about.slint";
import { PageFans } from "pages/fans.slint";
import { PageSlash, SlashPageData } from "pages/slash.slint";
import { PageSupergfx, SupergfxPageData } from "pages/supergfx.slint";
import { PageScreenpad, ScreenpadPageData } from "pages/screenpad.slint";
import { PageAnime, AnimePageData } from "pages/anime.slint";
import { RogItem } from "widgets/common.slint";
import { PageAura } from "pages/aura.slint";
import { Node } from "widgets/graph.slint";
export { Node }
import { FanPageData, FanType, Profile } from "types/fan_types.slint";
export { FanPageData, FanType, Profile }
import { AuraPageData, AuraDevType, LaptopAuraPower, AuraPowerState, PowerZones, AuraEffect } from "types/aura_types.slint";
export { AuraPageData, AuraDevType, LaptopAuraPower, AuraPowerState, PowerZones, AuraEffect }
import { PageAppSettings, AppSettingsPageData } from "pages/app_settings.slint";
import { StatusBar, SystemStatus } from "widgets/status_bar.slint";
import { TrayTooltip } from "windows/tray_tooltip.slint";
export { TrayTooltip }
import { RogPalette } from "themes/rog_theme.slint";
export { AppSize, AttrMinMax, SystemPageData, AnimePageData, AppSettingsPageData, SystemStatus, SlashPageData, SupergfxPageData, ScreenpadPageData }
export global SomeError {
in property <string> error_message: "";
in property <string> error_help: "";
}
export component MainWindow inherits Window {
title: "ROG Control";
always-on-top: true;
default-font-family: "Noto Sans";
default-font-size: 14px;
default-font-weight: 400;
icon: @image-url("../data/rog-control-center.png");
in property <[bool]> sidebar_items_avilable: [true, true, true, true, true, true, true, true, true];
private property <bool> show_notif;
private property <bool> fade_cover;
private property <bool> toast: false;
private property <string> toast_text: "I show when something is waiting";
callback show_toast(string);
callback start_toast_timer();
callback hide_toast();
hide_toast() => {
toast = false;
}
show_toast(text) => {
toast = text != "";
toast_text = text;
if (toast) {
start_toast_timer();
}
}
callback exit-app();
callback show_notification(bool);
show_notification(yes) => {
show_notif = yes;
fade_cover = yes;
}
callback external_colour_change();
external_colour_change() => {
aura.external_colour_change();
aura.external_colour_change();
}
min-height: AppSize.height;
min-width: AppSize.width;
background: RogPalette.background;
VerticalLayout {
HorizontalLayout {
padding: 0px;
// Left Column: Sidebar + Quit Button
VerticalLayout {
side-bar := SideBar {
title: @tr("ROG");
model: [
@tr("Menu1" => "System Control"),
@tr("Menu2" => "Keyboard Aura"),
@tr("Menu3" => "AniMe Matrix"),
@tr("Menu7" => "Slash Lighting"),
@tr("Menu8" => "Graphics Control"),
@tr("Menu9" => "Screenpad Control"),
@tr("Menu4" => "Fan Curves"),
@tr("Menu5" => "App Settings"),
@tr("Menu6" => "About"),
];
available: root.sidebar_items_avilable;
}
Rectangle {
max-height: 40px;
width: side-bar.width;
background: RogPalette.control-background;
Text {
vertical-alignment: center;
horizontal-alignment: center;
text: @tr("Quit App");
color: RogPalette.text-primary;
}
TouchArea {
clicked => {
root.exit-app();
}
}
}
}
// Right Column: Content Pages
Rectangle {
background: RogPalette.background;
if(side-bar.current-item == 0): page := PageSystem {
width: root.width - side-bar.width;
height: root.height + 12px;
}
aura := PageAura {
width: root.width - side-bar.width;
visible: side-bar.current-item == 1;
}
if(side-bar.current-item == 2): PageAnime {
width: root.width - side-bar.width;
}
if(side-bar.current-item == 3): PageSlash {
width: root.width - side-bar.width;
}
if(side-bar.current-item == 4): PageSupergfx {
width: root.width - side-bar.width;
}
if(side-bar.current-item == 5): PageScreenpad {
width: root.width - side-bar.width;
}
fans := PageFans {
width: root.width - side-bar.width;
visible: side-bar.current-item == 6;
}
if(side-bar.current-item == 7): PageAppSettings {
width: root.width - side-bar.width;
}
if(side-bar.current-item == 8): PageAbout {
width: root.width - side-bar.width;
}
}
}
// Bottom: Status Bar
StatusBar {}
}
if fade_cover: Rectangle {
x: 0px;
y: 0px;
width: root.width;
height: root.height;
background: Colors.rgba(0,0,0,0.7);
opacity: 0.7;
TouchArea {
height: 100%;
width: 100%;
clicked => {
// toolbar-dropdown.close();
if (show_notif) {
show_notif = false;
}
fade_cover = false;
}
}
}
// Modern floating toast/snackbar notification
// Shows at the bottom center, non-intrusive
Rectangle {
visible: self.opacity > 0;
opacity: root.toast ? 1 : 0;
animate opacity { duration: 300ms; }
x: (root.width - 400px) / 2; // Center horizontally
y: root.height - 80px; // Bottom padding
width: 400px;
height: 48px;
border-radius: RogPalette.border-radius;
border-width: 1px;
border-color: RogPalette.accent;
background: RogPalette.control-background;
drop-shadow-blur: 10px;
drop-shadow-color: Colors.black;
TouchArea {
height: 100%;
width: 100%;
clicked => {
toast = false;
}
}
HorizontalLayout {
padding-left: 16px;
padding-right: 16px;
alignment: space-between;
Text {
vertical-alignment: center;
color: RogPalette.text-primary;
text: root.toast_text;
overflow: elide;
}
Text {
vertical-alignment: center;
text: "Dismiss";
color: RogPalette.text-secondary;
font-size: 12px;
}
}
}
// // TODO: or use Dialogue
if show_notif: Rectangle {
x: root.width / 8;
y: root.height / 8;
height: (root.height / 8) * 6;
width: (root.width / 8) * 6;
TouchArea {
height: 100%;
width: 100%;
clicked => {
show_notif = false;
exit-app();
}
}
Rectangle {
height: 100%;
width: 100%;
background: RogPalette.control-background;
border-radius: 8px;
VerticalLayout {
alignment: center;
Text {
horizontal-alignment: center;
text: "Click here to exit";
color: RogPalette.text-primary;
font-size: 16px;
}
}
}
}
if SomeError.error_message != "": Rectangle {
x: 0px;
y: 0px;
width: root.width;
height: root.height;
background: RogPalette.background;
border-color: RogPalette.accent;
border-width: 2px;
border-radius: 8px;
VerticalBox {
padding: 20px;
spacing: 15px;
alignment: center;
Text {
text: "Error";
font-size: 22px;
font-weight: 700;
color: RogPalette.accent;
horizontal-alignment: center;
}
Rectangle {
background: RogPalette.control-background;
border-radius: 8px;
min-height: 60px;
Text {
text <=> SomeError.error_message;
font-size: 16px;
color: RogPalette.text-primary;
horizontal-alignment: center;
vertical-alignment: center;
}
}
Text {
text <=> SomeError.error_help;
color: RogPalette.text-secondary;
horizontal-alignment: center;
vertical-alignment: center;
}
}
}
}