system settings
git clone https://git.lucas.co/cce-system-interface.git
Refactor layouts using VStack on system_info, notifications, storage, packages, and processes pages
src/pages/notifications.rs | 21 ++++++------
src/pages/packages.rs | 84 ++++++++++++++++++++++------------------------
src/pages/processes.rs | 82 ++++++++++++++++++++------------------------
src/pages/storage.rs | 9 +++--
src/pages/system_info.rs | 23 ++++++-------
5 files changed, 103 insertions(+), 116 deletions(-)
diff --git a/src/pages/notifications.rs b/src/pages/notifications.rs
index 9c75266..f7c32ee 100644
--- a/src/pages/notifications.rs
+++ b/src/pages/notifications.rs
@@ -232,9 +232,10 @@ impl AppPage for NotificationsState {
let mut builder = PageLayoutBuilder::new(layout, cx, cy, cw, ch, sec_w).with_section_count(1);
builder.add_section(&mut final_pc, "Notifications Settings", sec_focused.first().copied().unwrap_or(false), |sec| {
- let sec_w = sec.cw;
+ let mut stack = sec.vstack(8.0);
+ let sec_w = stack.context.cw;
self.enable_toggle.set_toggled(self.enable);
- sec.widget_full(&mut self.enable_toggle, cce_ui::layout::toggle_height(), ctx);
+ stack.add_widget(&mut self.enable_toggle, sec_w - 28.0, cce_ui::layout::toggle_height(), ctx);
let selected_idx = match self.bell.as_str() {
"none" => 0,
@@ -244,24 +245,24 @@ impl AppPage for NotificationsState {
_ => 0,
};
self.bell_menu.selected = selected_idx;
- sec.widget(&mut self.bell_menu, 14.0, sec_w - 28.0, 44.0, ctx);
+ self.bell_menu.set_row_rect(stack.context.left + 14.0, sec_w - 28.0);
+ stack.add_widget(&mut self.bell_menu, sec_w - 28.0, 44.0, ctx);
self.duration_spinbox.value = self.duration;
self.duration_spinbox.set_label("Notification Duration");
- sec.widget(&mut self.duration_spinbox, 14.0, sec_w - 28.0, 44.0, ctx);
+ self.duration_spinbox.set_row_rect(stack.context.left + 14.0, sec_w - 28.0);
+ stack.add_widget(&mut self.duration_spinbox, sec_w - 28.0, 44.0, ctx);
let btn_h = 32.0;
- let btn_y = sec.ay();
let white_color = [1.0, 1.0, 1.0, 1.0];
let btn_bg = [0.20, 0.40, 0.65, 1.0];
let btn_hover = [0.28, 0.50, 0.78, 1.0];
- let cols = sec.row_layout(1, 0.0);
- if let Some(&(x, w)) = cols.first() {
- sec.button(
+ stack.add_row(1, 0.0, btn_h, |ctx, _, x, w| {
+ ctx.button(
"Send Test Notification",
x,
- btn_y,
+ ctx.ay(),
w,
btn_h,
btn_bg,
@@ -269,7 +270,7 @@ impl AppPage for NotificationsState {
white_color,
AppAction::Notifications(NotificationsMessage::SendTestNotification),
);
- }
+ });
});
final_pc
diff --git a/src/pages/packages.rs b/src/pages/packages.rs
index a497042..3ef981b 100644
--- a/src/pages/packages.rs
+++ b/src/pages/packages.rs
@@ -337,9 +337,8 @@ pub fn view(
sec.text("Loading package lists...", 12.0, 0.0, 12.0, TEXT_DIM);
} else {
// Tab header: Installed, Updates
- let tab_w = (sec_w - 24.0 - 8.0) / 2.0;
+ let mut stack = sec.vstack(8.0);
let tab_h = 28.0;
- let tab_y = sec.ay();
let active_bg = [0.20, 0.40, 0.65, 0.4];
let inactive_bg = [0.10, 0.10, 0.16, 0.3];
let hover_bg = [0.20, 0.20, 0.25, 0.15];
@@ -347,42 +346,43 @@ pub fn view(
let label1 = "Installed";
let label2 = "Updates";
- let tab_x1 = sec.left + 12.0;
- let tab_x2 = sec.left + 12.0 + tab_w + 8.0;
-
- sec.pc.button(
- label1,
- tab_x1,
- tab_y,
- tab_w,
- tab_h,
- if state.active_tab == PackageTab::Installed { active_bg } else { inactive_bg },
- hover_bg,
- [0.90, 0.90, 0.95, 1.0],
- AppAction::Packages(PackagesMessage::SetTab(PackageTab::Installed)),
- );
-
- sec.pc.button(
- label2,
- tab_x2,
- tab_y,
- tab_w,
- tab_h,
- if state.active_tab == PackageTab::Updates { active_bg } else { inactive_bg },
- hover_bg,
- [0.90, 0.90, 0.95, 1.0],
- AppAction::Packages(PackagesMessage::SetTab(PackageTab::Updates)),
- );
- sec.content_y += tab_h + 12.0;
+ stack.add_row(2, 8.0, tab_h, |ctx, i, x, w| {
+ if i == 0 {
+ ctx.button(
+ label1,
+ x,
+ ctx.ay(),
+ w,
+ tab_h,
+ if state.active_tab == PackageTab::Installed { active_bg } else { inactive_bg },
+ hover_bg,
+ [0.90, 0.90, 0.95, 1.0],
+ AppAction::Packages(PackagesMessage::SetTab(PackageTab::Installed)),
+ );
+ } else {
+ ctx.button(
+ label2,
+ x,
+ ctx.ay(),
+ w,
+ tab_h,
+ if state.active_tab == PackageTab::Updates { active_bg } else { inactive_bg },
+ hover_bg,
+ [0.90, 0.90, 0.95, 1.0],
+ AppAction::Packages(PackagesMessage::SetTab(PackageTab::Updates)),
+ );
+ }
+ });
+
+ stack.context.spacing(4.0);
// Search box
- let search_y = sec.ay();
let search_w = sec_w - 24.0;
let search_h = 46.0;
- state.search_box.set_row_rect(sec.left + 12.0, search_w);
- render_widget(sec.pc, &mut state.search_box, sec.left + 12.0, search_y, search_w, search_h, ctx);
- sec.content_y += search_h + 16.0;
+ state.search_box.set_row_rect(stack.context.left + 12.0, search_w);
+ stack.add_widget(&mut state.search_box, search_w, search_h, ctx);
+ stack.context.spacing(8.0);
// List area
let list_box_x = sec.left + 12.0;
@@ -540,17 +540,16 @@ pub fn view(
}
if state.active_tab == PackageTab::Installed {
+ let mut stack = subsec.vstack(8.0);
let btn_h = 32.0;
- let btn_y = subsec.ay();
let (btn_lbl, bg, hover, action) = if state.uninstalling {
("Uninstalling...", TOGGLE_OFF, TOGGLE_OFF, AppAction::Packages(PackagesMessage::StartUninstall(pkg_name.clone())))
} else {
("Uninstall Package", RED, BTN_HOVER, AppAction::Packages(PackagesMessage::StartUninstall(pkg_name.clone())))
};
- let cols = subsec.row_layout(1, 0.0);
- if let Some(&(x, w)) = cols.first() {
- subsec.button(btn_lbl, x, btn_y, w, btn_h, bg, hover, WHITE, action);
- }
+ stack.add_row(1, 0.0, btn_h, |ctx, _, x, w| {
+ ctx.button(btn_lbl, x, ctx.ay(), w, btn_h, bg, hover, WHITE, action.clone());
+ });
}
} else {
subsec.text("No details available.", 12.0, 0.0, 12.0, TEXT_DIM);
@@ -597,8 +596,8 @@ pub fn view(
}
}
+ let mut stack = sec2.vstack(8.0);
let btn_h = 32.0;
- let btn_y = sec2.ay();
let (btn_lbl, bg, hover, action) = if state.updating {
("Updating...", TOGGLE_OFF, TOGGLE_OFF, AppAction::Packages(PackagesMessage::StartUpdate))
@@ -606,10 +605,9 @@ pub fn view(
("Update System", TOGGLE_ON, BTN_HOVER, AppAction::Packages(PackagesMessage::StartUpdate))
};
- let cols = sec2.row_layout(1, 0.0);
- if let Some(&(x, w)) = cols.first() {
- sec2.button(btn_lbl, x, btn_y, w, btn_h, bg, hover, WHITE, action);
- }
+ stack.add_row(1, 0.0, btn_h, |ctx, _, x, w| {
+ ctx.button(btn_lbl, x, ctx.ay(), w, btn_h, bg, hover, WHITE, action.clone());
+ });
}
});
diff --git a/src/pages/processes.rs b/src/pages/processes.rs
index 8533316..588bed5 100644
--- a/src/pages/processes.rs
+++ b/src/pages/processes.rs
@@ -1,4 +1,4 @@
-use crate::app::{AppAction, PageContent};
+use crate::app::{AppAction, PageContent, SectionContextExt};
use cce_ui::layout::{render_widget, PageLayoutBuilder, LayoutStrategy, RenderTarget};
use cce_ui::widget::{List, TextBox, StatusDot, DotStatus, InteractiveListItem, Element};
@@ -177,60 +177,52 @@ pub fn view(state: &mut ProcessesState, cx: f32, cy: f32, cw: f32, ch: f32, root
sec.text("Loading systemd services...", 12.0, 0.0, 12.0, TEXT_DIM);
} else {
// Tab header buttons: System Services, User Services
- let tab_w = (sec_w - 24.0 - 8.0) / 2.0;
+ let mut stack = sec.vstack(8.0);
let tab_h = 28.0;
- let tab_y = sec.ay();
let active_bg = [0.20, 0.40, 0.65, 0.4];
let inactive_bg = [0.10, 0.10, 0.16, 0.3];
let hover_bg = [0.20, 0.20, 0.25, 0.15];
- let label1 = if tab_w < 110.0 { "System" } else { "System Services" };
- let label2 = if tab_w < 110.0 { "User" } else { "User Services" };
-
- let tab_x1 = sec.left + 12.0;
- let tab_x2 = sec.left + 12.0 + tab_w + 8.0;
-
- sec.pc.button(
- label1,
- tab_x1,
- tab_y,
- tab_w,
- tab_h,
- if state.services_active_tab == ServiceTab::System { active_bg } else { inactive_bg },
- hover_bg,
- [0.90, 0.90, 0.95, 1.0],
- crate::app::AppAction::Processes(ProcessesMessage::ServicesSetTab(ServiceTab::System)),
- );
-
- sec.pc.button(
- label2,
- tab_x2,
- tab_y,
- tab_w,
- tab_h,
- if state.services_active_tab == ServiceTab::User { active_bg } else { inactive_bg },
- hover_bg,
- [0.90, 0.90, 0.95, 1.0],
- crate::app::AppAction::Processes(ProcessesMessage::ServicesSetTab(ServiceTab::User)),
- );
- sec.content_y += tab_h + 12.0;
+ let label1 = if stack.context.cw < 250.0 { "System" } else { "System Services" };
+ let label2 = if stack.context.cw < 250.0 { "User" } else { "User Services" };
+
+ stack.add_row(2, 8.0, tab_h, |ctx, i, x, w| {
+ if i == 0 {
+ ctx.button(
+ label1,
+ x,
+ ctx.ay(),
+ w,
+ tab_h,
+ if state.services_active_tab == ServiceTab::System { active_bg } else { inactive_bg },
+ hover_bg,
+ [0.90, 0.90, 0.95, 1.0],
+ crate::app::AppAction::Processes(ProcessesMessage::ServicesSetTab(ServiceTab::System)),
+ );
+ } else {
+ ctx.button(
+ label2,
+ x,
+ ctx.ay(),
+ w,
+ tab_h,
+ if state.services_active_tab == ServiceTab::User { active_bg } else { inactive_bg },
+ hover_bg,
+ [0.90, 0.90, 0.95, 1.0],
+ crate::app::AppAction::Processes(ProcessesMessage::ServicesSetTab(ServiceTab::User)),
+ );
+ }
+ });
+
+ stack.context.spacing(4.0);
// Search textbox
- let search_y = sec.ay();
let search_w = sec_w - 24.0;
let search_h = 46.0;
- state.services_search_box.set_row_rect(sec.left + 12.0, search_w);
- render_widget(
- sec.pc,
- &mut state.services_search_box,
- sec.left + 12.0,
- search_y,
- search_w,
- search_h,
- ctx,
- );
- sec.content_y += search_h + 16.0;
+ state.services_search_box.set_row_rect(stack.context.left + 12.0, search_w);
+ stack.add_widget(&mut state.services_search_box, search_w, search_h, ctx);
+ stack.context.spacing(8.0);
// Scroll box list
let list_box_x = sec.left + 12.0;
diff --git a/src/pages/storage.rs b/src/pages/storage.rs
index 2089f3a..87a9bb2 100644
--- a/src/pages/storage.rs
+++ b/src/pages/storage.rs
@@ -259,8 +259,8 @@ pub fn view(state: &StorageState, cx: f32, cy: f32, cw: f32, ch: f32, layout: &m
}
// Action Button
+ let mut stack = sec.vstack(8.0);
let btn_h = 32.0;
- let yt = sec.ay();
let (btn_label, bg, hover, action) = if state.backup_in_progress {
("Backing up...", BTN_DISABLED, BTN_DISABLED, AppAction::Storage(StorageMessage::StartBackup))
@@ -268,10 +268,9 @@ pub fn view(state: &StorageState, cx: f32, cy: f32, cw: f32, ch: f32, layout: &m
("Run Backup", BTN_BG, BTN_HOVER, AppAction::Storage(StorageMessage::StartBackup))
};
- let cols = sec.row_layout(1, 0.0);
- if let Some(&(x, w)) = cols.first() {
- sec.button(btn_label, x, yt, w, btn_h, bg, hover, WHITE, action.clone());
- }
+ stack.add_row(1, 0.0, btn_h, |ctx, _, x, w| {
+ ctx.button(btn_label, x, ctx.ay(), w, btn_h, bg, hover, WHITE, action.clone());
+ });
}
});
diff --git a/src/pages/system_info.rs b/src/pages/system_info.rs
index cba5d90..fff00fb 100644
--- a/src/pages/system_info.rs
+++ b/src/pages/system_info.rs
@@ -564,38 +564,35 @@ pub fn view(state: &mut SystemState, cx: f32, cy: f32, cw: f32, ch: f32, _root_f
// ── 2. System Actions Section ──
builder.add_section(&mut final_pc, "System Actions", false, |sec| {
- let yt = sec.ay();
+ let mut stack = sec.vstack(8.0);
let act_btn_h = 32.0;
- let cols = sec.row_layout(4, 8.0);
- for (i, &(x, w)) in cols.iter().enumerate() {
+ stack.add_row(4, 8.0, act_btn_h, |ctx, i, x, w| {
match i {
0 => {
- sec.button("Suspend", x, yt, w, act_btn_h,
+ ctx.button("Suspend", x, ctx.ay(), w, act_btn_h,
SAFE_BG, BTN_HOVER, WHITE, AppAction::SystemInfo(SystemMessage::Suspend));
}
1 => {
- sec.button("Hibernate", x, yt, w, act_btn_h,
+ ctx.button("Hibernate", x, ctx.ay(), w, act_btn_h,
SAFE_BG, BTN_HOVER, WHITE, AppAction::SystemInfo(SystemMessage::Hibernate));
}
2 => {
- sec.button("Reboot", x, yt, w, act_btn_h,
+ ctx.button("Reboot", x, ctx.ay(), w, act_btn_h,
DANGER_BG, BTN_HOVER, WHITE, AppAction::SystemInfo(SystemMessage::Reboot));
}
3 => {
- sec.button("Power Off", x, yt, w, act_btn_h,
+ ctx.button("Power Off", x, ctx.ay(), w, act_btn_h,
DANGER_BG, BTN_HOVER, WHITE, AppAction::SystemInfo(SystemMessage::PowerOff));
}
_ => {}
}
- }
+ });
- let yt2 = yt + act_btn_h + 8.0;
- let cols2 = sec.row_layout(1, 0.0);
- if let Some(&(x, w)) = cols2.first() {
- sec.button("Force Shutdown", x, yt2, w, act_btn_h,
+ stack.add_row(1, 0.0, act_btn_h, |ctx, _, x, w| {
+ ctx.button("Force Shutdown", x, ctx.ay(), w, act_btn_h,
DANGER_BG, BTN_HOVER, WHITE, AppAction::SystemInfo(SystemMessage::ForceShutdown));
- }
+ });
});
// ── 3. CPU Section ──