mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2026-08-17 16:34:54 -05:00
feat: improve pstates UI (#896)
* move state_row to dedicated component * remove selectable behavior * highlight active pstate * hide checkboxes when not configurable use monospace for text * hide pstates table when there is no data * prevents container width jumps when active row change * add page_section_expander and wrap PowerStatesFrame into it * move active indicator to the beginning and use opacity instead of visilibity to keep layout stable * improve listbox captions styles * remove states_expanded state from PowerStatesFrame * remove no longer relevant styles * improve margins * move SelectionMode to view, kinda * clean up * align expaner label * organize imports * hide active p-state indicator if non is active * use bindings for configurable update label * fix PowerStateRow props visibility * move bindings inits * fix set_sensitive on enable-pstate-config checkbox
This commit is contained in:
@@ -180,7 +180,7 @@ mem-pstate-clock-voltage = VRAM P-State {$pstate} Voltage (mV)
|
||||
pstates = Power States
|
||||
gpu-pstates = GPU Power States
|
||||
vram-pstates = VRAM Power States
|
||||
pstates-manual-needed = Note: performance level must be set to 'manual' to toggle power states
|
||||
pstates-manual-needed = Performance level must be set to 'manual' to toggle power states
|
||||
enable-pstate-config = Enable power state configuration
|
||||
|
||||
show-historical-charts = Show Historical Charts
|
||||
|
||||
@@ -9,6 +9,7 @@ mod info_row_level;
|
||||
pub(crate) mod msg;
|
||||
mod overdrive_dialog;
|
||||
mod page_section;
|
||||
mod page_section_expander;
|
||||
pub(crate) mod pages;
|
||||
mod process_monitor;
|
||||
pub(crate) mod styles;
|
||||
|
||||
@@ -118,6 +118,8 @@ impl Default for InfoRow {
|
||||
}
|
||||
|
||||
mod imp {
|
||||
use std::{cell::RefCell, str::FromStr};
|
||||
|
||||
use glib::Properties;
|
||||
use gtk::{
|
||||
Label, glib,
|
||||
@@ -126,7 +128,6 @@ mod imp {
|
||||
subclass::{prelude::*, widget::WidgetImpl},
|
||||
};
|
||||
use relm4::{RelmWidgetExt, css, view};
|
||||
use std::{cell::RefCell, str::FromStr};
|
||||
|
||||
#[derive(Default, Properties)]
|
||||
#[properties(wrapper_type = super::InfoRow)]
|
||||
|
||||
@@ -24,11 +24,13 @@ impl Default for InfoRowLevel {
|
||||
}
|
||||
|
||||
mod imp {
|
||||
use crate::app::info_row::{InfoRow, InfoRowExt};
|
||||
use std::cell::RefCell;
|
||||
|
||||
use glib::Properties;
|
||||
use gtk::{LevelBar, glib, prelude::*, subclass::prelude::*};
|
||||
use relm4::view;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use crate::app::info_row::{InfoRow, InfoRowExt};
|
||||
|
||||
#[derive(Default, Properties)]
|
||||
#[properties(wrapper_type = super::InfoRowLevel)]
|
||||
|
||||
@@ -32,6 +32,8 @@ impl PageSection {
|
||||
unsafe impl<T: ObjectSubclass + BoxImpl> IsSubclassable<T> for PageSection {}
|
||||
|
||||
mod imp {
|
||||
use std::cell::RefCell;
|
||||
|
||||
use glib::Properties;
|
||||
use gtk::{
|
||||
Label,
|
||||
@@ -40,7 +42,6 @@ mod imp {
|
||||
subclass::{prelude::*, widget::WidgetImpl},
|
||||
};
|
||||
use relm4::{RelmWidgetExt, css, view};
|
||||
use std::cell::RefCell;
|
||||
|
||||
#[derive(Default, Properties)]
|
||||
#[properties(wrapper_type = super::PageSection)]
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
use cairo::glib::subclass::types::ObjectSubclassIsExt;
|
||||
use gtk::prelude::*;
|
||||
use gtk::{
|
||||
glib::{
|
||||
self, Object,
|
||||
subclass::types::{IsSubclassable, ObjectSubclass},
|
||||
},
|
||||
subclass::box_::BoxImpl,
|
||||
};
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct PageSectionExpander(ObjectSubclass<imp::PageSectionExpander>)
|
||||
@extends gtk::Box, gtk::Widget,
|
||||
@implements gtk::Orientable, gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget;
|
||||
}
|
||||
|
||||
impl PageSectionExpander {
|
||||
pub fn new(name: &str) -> Self {
|
||||
Object::builder().property("name", name).build()
|
||||
}
|
||||
|
||||
pub fn append_header(&self, widget: &impl IsA<gtk::Widget>) {
|
||||
self.imp().header_box.append(widget);
|
||||
}
|
||||
|
||||
pub fn append_expandable(&self, widget: &impl IsA<gtk::Widget>) {
|
||||
self.imp().children_box.append(widget);
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: ObjectSubclass + BoxImpl> IsSubclassable<T> for PageSectionExpander {}
|
||||
|
||||
mod imp {
|
||||
use std::cell::RefCell;
|
||||
|
||||
use glib::Properties;
|
||||
use gtk::{
|
||||
Label,
|
||||
glib::{self},
|
||||
prelude::*,
|
||||
subclass::{prelude::*, widget::WidgetImpl},
|
||||
};
|
||||
use relm4::{RelmWidgetExt, view};
|
||||
|
||||
#[derive(Default, Properties)]
|
||||
#[properties(wrapper_type = super::PageSectionExpander)]
|
||||
pub struct PageSectionExpander {
|
||||
section_label: Label,
|
||||
pub(super) header_box: gtk::Box,
|
||||
pub(super) content_box: gtk::Box,
|
||||
pub(super) children_box: gtk::Box,
|
||||
pub(super) expander: gtk::Expander,
|
||||
|
||||
#[property(get, set)]
|
||||
name: RefCell<String>,
|
||||
|
||||
#[property(get, set)]
|
||||
expanded: std::cell::Cell<bool>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for PageSectionExpander {
|
||||
const NAME: &'static str = "PageSectionExpander";
|
||||
type Type = super::PageSectionExpander;
|
||||
type ParentType = gtk::Box;
|
||||
}
|
||||
|
||||
#[glib::derived_properties]
|
||||
impl ObjectImpl for PageSectionExpander {
|
||||
fn constructed(&self) {
|
||||
self.parent_constructed();
|
||||
let obj = self.obj();
|
||||
|
||||
let section_label = &self.section_label;
|
||||
let header_box = &self.header_box;
|
||||
let content_box = &self.content_box;
|
||||
let children_box = &self.children_box;
|
||||
let expander = &self.expander;
|
||||
|
||||
view! {
|
||||
#[local_ref]
|
||||
obj {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
set_spacing: 10,
|
||||
|
||||
#[local_ref]
|
||||
append = expander {
|
||||
set_child: Some(content_box),
|
||||
set_label_widget : Some(header_box),
|
||||
},
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
header_box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_spacing: 10,
|
||||
|
||||
#[local_ref]
|
||||
append = section_label {
|
||||
set_use_markup: true,
|
||||
set_halign: gtk::Align::Start,
|
||||
set_margin_vertical: 5,
|
||||
// align label with normal PageSection
|
||||
set_margin_start: -1,
|
||||
set_margin_end: 1,
|
||||
},
|
||||
},
|
||||
|
||||
#[local_ref]
|
||||
content_box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
|
||||
#[local_ref]
|
||||
append = children_box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
set_spacing: 10,
|
||||
set_margin_all: 10,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
obj.bind_property("name", &self.section_label, "label")
|
||||
.transform_to(|_, value: String| {
|
||||
Some(format!("<span font_desc='13'><b>{value}</b></span>"))
|
||||
})
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
impl WidgetImpl for PageSectionExpander {}
|
||||
impl BoxImpl for PageSectionExpander {}
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
pub mod power_states_frame;
|
||||
mod power_states_list;
|
||||
mod power_states_row;
|
||||
|
||||
@@ -3,6 +3,7 @@ use crate::{
|
||||
APP_BROKER, I18N,
|
||||
app::{
|
||||
msg::AppMsg,
|
||||
page_section_expander::PageSectionExpander,
|
||||
pages::oc_page::power_states::power_states_list::{
|
||||
PowerStatesListMsg, PowerStatesListOptions,
|
||||
},
|
||||
@@ -17,8 +18,9 @@ use i18n_embed_fl::fl;
|
||||
use indexmap::IndexMap;
|
||||
use lact_schema::{DeviceStats, PowerStates};
|
||||
use relm4::{
|
||||
Component, ComponentController, ComponentParts, ComponentSender, RelmObjectExt, RelmWidgetExt,
|
||||
binding::BoolBinding,
|
||||
Component, ComponentController, ComponentParts, ComponentSender, RelmObjectExt,
|
||||
binding::{Binding, BoolBinding},
|
||||
css,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -27,7 +29,6 @@ pub struct PowerStatesFrame {
|
||||
vram_states_list: relm4::Controller<PowerStatesList>,
|
||||
states_configurable: BoolBinding,
|
||||
states_configured: BoolBinding,
|
||||
states_expanded: BoolBinding,
|
||||
performance_level: Option<PerformanceLevel>,
|
||||
configured_signal: SignalHandlerId,
|
||||
vram_clock_ratio: f64,
|
||||
@@ -43,6 +44,7 @@ pub enum PowerStatesFrameMsg {
|
||||
PerformanceLevel(Option<PerformanceLevel>),
|
||||
VramClockRatio(f64),
|
||||
Configurable(bool),
|
||||
InternalConfigurableChanged(bool),
|
||||
}
|
||||
|
||||
#[relm4::component(pub)]
|
||||
@@ -52,20 +54,14 @@ impl relm4::SimpleComponent for PowerStatesFrame {
|
||||
type Output = ();
|
||||
|
||||
view! {
|
||||
gtk::Expander {
|
||||
set_label: Some(&fl!(I18N, "pstates")),
|
||||
add_binding: (&model.states_expanded, "expanded"),
|
||||
set_margin_horizontal: 20,
|
||||
|
||||
gtk::Box {
|
||||
PageSectionExpander::new(&fl!(I18N, "pstates")) {
|
||||
append_expandable = >k::Box {
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
set_margin_all: 10,
|
||||
set_spacing: 5,
|
||||
add_binding: (&model.states_configurable, "sensitive"),
|
||||
|
||||
gtk::Label {
|
||||
set_label: &fl!(I18N, "pstates-manual-needed"),
|
||||
set_margin_horizontal: 10,
|
||||
add_css_class: css::DIM_LABEL,
|
||||
set_halign: gtk::Align::Start,
|
||||
#[watch]
|
||||
set_visible: model.performance_level.is_some_and(|level| level != PerformanceLevel::Manual),
|
||||
@@ -76,15 +72,25 @@ impl relm4::SimpleComponent for PowerStatesFrame {
|
||||
add_binding: (&model.states_configured, "active"),
|
||||
#[watch]
|
||||
set_visible: model.performance_level.is_some(),
|
||||
#[watch]
|
||||
set_sensitive: model.performance_level.is_some_and(|level| level == PerformanceLevel::Manual),
|
||||
},
|
||||
|
||||
gtk::Box {
|
||||
set_spacing: 10,
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
add_binding: (&model.states_configured, "sensitive"),
|
||||
|
||||
append = model.core_states_list.widget(),
|
||||
append = model.vram_states_list.widget(),
|
||||
gtk::Box {
|
||||
#[watch]
|
||||
set_visible: !model.core_states_list.model().is_empty(),
|
||||
append = model.core_states_list.widget(),
|
||||
},
|
||||
|
||||
gtk::Box {
|
||||
#[watch]
|
||||
set_visible: !model.vram_states_list.model().is_empty(),
|
||||
append = model.vram_states_list.widget(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -93,7 +99,7 @@ impl relm4::SimpleComponent for PowerStatesFrame {
|
||||
fn init(
|
||||
_: Self::Init,
|
||||
root: Self::Root,
|
||||
_sender: ComponentSender<Self>,
|
||||
sender: ComponentSender<Self>,
|
||||
) -> ComponentParts<Self> {
|
||||
let core_states_list = PowerStatesList::builder()
|
||||
.launch(PowerStatesListOptions {
|
||||
@@ -110,7 +116,10 @@ impl relm4::SimpleComponent for PowerStatesFrame {
|
||||
|
||||
let states_configured = BoolBinding::new(false);
|
||||
|
||||
let configured_signal = states_configured.connect_value_notify(|_| {
|
||||
let configured_signal = states_configured.connect_value_notify(move |states_configured| {
|
||||
sender.input(PowerStatesFrameMsg::InternalConfigurableChanged(
|
||||
states_configured.get(),
|
||||
));
|
||||
APP_BROKER.send(AppMsg::SettingsChanged);
|
||||
});
|
||||
|
||||
@@ -120,7 +129,6 @@ impl relm4::SimpleComponent for PowerStatesFrame {
|
||||
states_configurable: BoolBinding::new(false),
|
||||
states_configured,
|
||||
configured_signal,
|
||||
states_expanded: BoolBinding::new(false),
|
||||
performance_level: None,
|
||||
vram_clock_ratio: 1.0,
|
||||
};
|
||||
@@ -163,6 +171,11 @@ impl relm4::SimpleComponent for PowerStatesFrame {
|
||||
|| !self.vram_states_list.model().is_empty());
|
||||
self.states_configurable.set_value(value);
|
||||
|
||||
self.core_states_list
|
||||
.emit(PowerStatesListMsg::Configurable(value));
|
||||
self.vram_states_list
|
||||
.emit(PowerStatesListMsg::Configurable(value));
|
||||
|
||||
if !value {
|
||||
self.states_configured.block_signal(&self.configured_signal);
|
||||
self.states_configured.set_value(false);
|
||||
@@ -173,6 +186,12 @@ impl relm4::SimpleComponent for PowerStatesFrame {
|
||||
PowerStatesFrameMsg::PerformanceLevel(level) => {
|
||||
self.performance_level = level;
|
||||
}
|
||||
PowerStatesFrameMsg::InternalConfigurableChanged(configurable) => {
|
||||
self.core_states_list
|
||||
.emit(PowerStatesListMsg::Configurable(configurable));
|
||||
self.vram_states_list
|
||||
.emit(PowerStatesListMsg::Configurable(configurable));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
use gtk::prelude::{BoxExt, CheckButtonExt, FrameExt, OrientableExt, WidgetExt};
|
||||
use crate::app::pages::oc_page::power_states::power_states_row::{
|
||||
PowerStateRow, PowerStateRowMsg, PowerStateRowOptions,
|
||||
};
|
||||
use gtk::prelude::{FrameExt, WidgetExt};
|
||||
use lact_schema::PowerState;
|
||||
use relm4::{
|
||||
ComponentParts, ComponentSender, RelmObjectExt, binding::BoolBinding, prelude::FactoryVecDeque,
|
||||
ComponentParts, ComponentSender, RelmWidgetExt, binding::BoolBinding, css,
|
||||
prelude::FactoryVecDeque,
|
||||
};
|
||||
|
||||
use crate::{APP_BROKER, app::msg::AppMsg};
|
||||
|
||||
pub struct PowerStatesList {
|
||||
states: FactoryVecDeque<PowerStateRow>,
|
||||
value_suffix: String,
|
||||
is_active_indicator_visible: BoolBinding,
|
||||
configurable: BoolBinding,
|
||||
}
|
||||
|
||||
pub struct PowerStatesListOptions {
|
||||
@@ -20,6 +24,7 @@ pub struct PowerStatesListOptions {
|
||||
pub enum PowerStatesListMsg {
|
||||
PowerStates(Vec<PowerState>, f64),
|
||||
ActiveState(Option<usize>),
|
||||
Configurable(bool),
|
||||
}
|
||||
|
||||
#[relm4::component(pub)]
|
||||
@@ -31,8 +36,16 @@ impl relm4::SimpleComponent for PowerStatesList {
|
||||
view! {
|
||||
gtk::Frame {
|
||||
set_hexpand: true,
|
||||
set_label: Some(&opts.title),
|
||||
set_child: Some(model.states.widget()),
|
||||
#[wrap(Some)]
|
||||
set_label_widget = >k::Label {
|
||||
set_label: &opts.title,
|
||||
set_margin_horizontal: 5,
|
||||
add_css_class: css::CAPTION_HEADING,
|
||||
},
|
||||
#[local_ref]
|
||||
states_widget -> gtk::ListBox {
|
||||
set_selection_mode: gtk::SelectionMode::None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,8 +59,12 @@ impl relm4::SimpleComponent for PowerStatesList {
|
||||
let model = Self {
|
||||
states,
|
||||
value_suffix: opts.value_suffix,
|
||||
is_active_indicator_visible: BoolBinding::new(false),
|
||||
configurable: BoolBinding::new(true),
|
||||
};
|
||||
|
||||
let states_widget = model.states.widget();
|
||||
|
||||
let widgets = view_output!();
|
||||
|
||||
ComponentParts { widgets, model }
|
||||
@@ -65,20 +82,27 @@ impl relm4::SimpleComponent for PowerStatesList {
|
||||
power_state,
|
||||
value_suffix: self.value_suffix.clone(),
|
||||
active: false,
|
||||
show_active_indicator: self.is_active_indicator_visible.clone(),
|
||||
configurable: self.configurable.clone(),
|
||||
};
|
||||
states.push_back(opts);
|
||||
}
|
||||
}
|
||||
PowerStatesListMsg::ActiveState(active_idx) => {
|
||||
self.is_active_indicator_visible
|
||||
.set_value(active_idx.is_some());
|
||||
for (i, row) in self.states.iter().enumerate() {
|
||||
let is_active = row
|
||||
.power_state
|
||||
.index
|
||||
.is_some_and(|index| Some(usize::from(index)) == active_idx);
|
||||
|
||||
self.states.send(i, is_active);
|
||||
self.states.send(i, PowerStateRowMsg::Active(is_active));
|
||||
}
|
||||
}
|
||||
PowerStatesListMsg::Configurable(configurable) => {
|
||||
self.configurable.set_value(configurable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,69 +120,3 @@ impl PowerStatesList {
|
||||
self.states.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
struct PowerStateRow {
|
||||
active: BoolBinding,
|
||||
enabled: BoolBinding,
|
||||
power_state: PowerState,
|
||||
value_suffix: String,
|
||||
}
|
||||
|
||||
pub struct PowerStateRowOptions {
|
||||
pub power_state: PowerState,
|
||||
pub value_suffix: String,
|
||||
pub active: bool,
|
||||
}
|
||||
|
||||
#[relm4::factory]
|
||||
impl relm4::factory::FactoryComponent for PowerStateRow {
|
||||
type ParentWidget = gtk::ListBox;
|
||||
type CommandOutput = ();
|
||||
type Input = bool;
|
||||
type Output = ();
|
||||
type Init = PowerStateRowOptions;
|
||||
|
||||
view! {
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_spacing: 5,
|
||||
|
||||
append = >k::CheckButton {
|
||||
set_hexpand: true,
|
||||
add_binding: (&self.enabled, "active"),
|
||||
set_label: {
|
||||
let value_text = match self.power_state.min_value {
|
||||
Some(min) if min != self.power_state.value => format!("{min}-{}", self.power_state.value),
|
||||
_ => self.power_state.value.to_string(),
|
||||
};
|
||||
Some(format!("{}: {value_text} {}", index.current_index(), self.value_suffix))
|
||||
}.as_deref(),
|
||||
},
|
||||
|
||||
append: image = >k::Image {
|
||||
set_icon_name: Some("pan-start-symbolic"),
|
||||
add_binding: (&self.active, "visible"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn init_model(
|
||||
opts: Self::Init,
|
||||
_index: &Self::Index,
|
||||
_sender: relm4::FactorySender<Self>,
|
||||
) -> Self {
|
||||
let enabled = BoolBinding::new(opts.power_state.enabled);
|
||||
enabled.connect_value_notify(|_| APP_BROKER.send(AppMsg::SettingsChanged));
|
||||
|
||||
Self {
|
||||
enabled,
|
||||
active: BoolBinding::new(opts.active),
|
||||
power_state: opts.power_state,
|
||||
value_suffix: opts.value_suffix,
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, active: Self::Input, _: relm4::FactorySender<Self>) {
|
||||
self.active.set_value(active);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
use crate::{APP_BROKER, app::msg::AppMsg};
|
||||
use gtk::prelude::{BoxExt, OrientableExt, WidgetExt};
|
||||
use lact_schema::PowerState;
|
||||
use relm4::{RelmObjectExt, RelmWidgetExt, binding::BoolBinding, css};
|
||||
|
||||
pub struct PowerStateRow {
|
||||
active: BoolBinding,
|
||||
pub(super) enabled: BoolBinding,
|
||||
pub(super) power_state: PowerState,
|
||||
value_suffix: String,
|
||||
configurable: BoolBinding,
|
||||
show_active_indicator: BoolBinding,
|
||||
}
|
||||
|
||||
pub struct PowerStateRowOptions {
|
||||
pub power_state: PowerState,
|
||||
pub value_suffix: String,
|
||||
pub active: bool,
|
||||
pub show_active_indicator: BoolBinding,
|
||||
pub configurable: BoolBinding,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum PowerStateRowMsg {
|
||||
Active(bool),
|
||||
}
|
||||
|
||||
#[relm4::factory(pub)]
|
||||
impl relm4::factory::FactoryComponent for PowerStateRow {
|
||||
type ParentWidget = gtk::ListBox;
|
||||
type CommandOutput = ();
|
||||
type Input = PowerStateRowMsg;
|
||||
type Output = ();
|
||||
type Init = PowerStateRowOptions;
|
||||
|
||||
view! {
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_spacing: 5,
|
||||
set_margin_vertical: 2,
|
||||
set_margin_horizontal: 5,
|
||||
|
||||
append: image = >k::Image {
|
||||
set_icon_name: Some("pan-end-symbolic"),
|
||||
add_binding: (&self.show_active_indicator, "visible"),
|
||||
#[watch]
|
||||
set_opacity: if self.active.value() { 1.0 } else { 0.0 },
|
||||
},
|
||||
|
||||
append = >k::CheckButton {
|
||||
add_binding: (&self.enabled, "active"),
|
||||
add_binding: (&self.configurable, "visible"),
|
||||
},
|
||||
|
||||
append = >k::Label {
|
||||
add_css_class: css::MONOSPACE,
|
||||
#[watch]
|
||||
set_class_active: (css::DIM_LABEL, !self.active.value()),
|
||||
set_label: &{
|
||||
let value_text = match self.power_state.min_value {
|
||||
Some(min) if min != self.power_state.value => format!("{min}-{}", self.power_state.value),
|
||||
_ => self.power_state.value.to_string(),
|
||||
};
|
||||
format!("{}: {value_text} {}", index.current_index(), self.value_suffix)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn init_model(
|
||||
opts: Self::Init,
|
||||
_index: &Self::Index,
|
||||
_sender: relm4::FactorySender<Self>,
|
||||
) -> Self {
|
||||
let enabled = BoolBinding::new(opts.power_state.enabled);
|
||||
enabled.connect_value_notify(|_| APP_BROKER.send(AppMsg::SettingsChanged));
|
||||
|
||||
Self {
|
||||
enabled,
|
||||
active: BoolBinding::new(opts.active),
|
||||
power_state: opts.power_state,
|
||||
value_suffix: opts.value_suffix,
|
||||
configurable: opts.configurable,
|
||||
show_active_indicator: opts.show_active_indicator,
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, msg: Self::Input, _: relm4::FactorySender<Self>) {
|
||||
let PowerStateRowMsg::Active(active) = msg;
|
||||
self.active.set_value(active);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user