Port SettingsEntry from cosmic-settings
This commit is contained in:
parent
9ed29eab94
commit
9da2b030d7
4 changed files with 230 additions and 15 deletions
|
|
@ -5,6 +5,7 @@ extern crate relm4_macros;
|
||||||
|
|
||||||
pub mod task;
|
pub mod task;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
|
pub mod widgets;
|
||||||
|
|
||||||
use gtk4::{gio::ApplicationFlags, prelude::*, Orientation};
|
use gtk4::{gio::ApplicationFlags, prelude::*, Orientation};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,22 @@
|
||||||
use gtk4::{prelude::*, Align, Label, Orientation, Separator, Switch};
|
use crate::widgets::SettingsEntry;
|
||||||
|
use gtk4::{prelude::*, Orientation, Separator, Switch};
|
||||||
|
|
||||||
pub fn add_toggles(target: >k4::Box) {
|
pub fn add_toggles(target: >k4::Box) {
|
||||||
view! {
|
view! {
|
||||||
airplane_mode_box = gtk4::Box {
|
airplane_mode = SettingsEntry {
|
||||||
append: airplane_mode_label = &Label {
|
set_title_markup: "<b>Airplane Mode</b>",
|
||||||
set_markup: "<b>Airplane Mode</b>",
|
set_child: airplane_mode_switch = &Switch {}
|
||||||
set_halign: Align::Start
|
|
||||||
},
|
|
||||||
append: airplane_mode_switch = &Switch {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
view! {
|
view! {
|
||||||
wifi_box = gtk4::Box {
|
wifi = SettingsEntry {
|
||||||
append: wifi_label = &Label {
|
set_title_markup: "<b>WiFi</b>",
|
||||||
set_markup: "<b>WiFi</b>",
|
set_child: wifi_switch = &Switch {}
|
||||||
set_halign: Align::Start
|
|
||||||
},
|
|
||||||
append: wifi_switch = &Switch {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
target.append(&airplane_mode_box);
|
target.append(&airplane_mode);
|
||||||
target.append(&Separator::new(Orientation::Horizontal));
|
target.append(&Separator::new(Orientation::Horizontal));
|
||||||
target.append(&wifi_box);
|
target.append(&wifi);
|
||||||
target.append(&Separator::new(Orientation::Horizontal));
|
target.append(&Separator::new(Orientation::Horizontal));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5
applets/cosmic-applet-network/src/widgets.rs
Normal file
5
applets/cosmic-applet-network/src/widgets.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
mod settings_entry;
|
||||||
|
|
||||||
|
pub use settings_entry::SettingsEntry;
|
||||||
214
applets/cosmic-applet-network/src/widgets/settings_entry.rs
Normal file
214
applets/cosmic-applet-network/src/widgets/settings_entry.rs
Normal file
|
|
@ -0,0 +1,214 @@
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
use gtk4::{
|
||||||
|
glib::{self, Object},
|
||||||
|
prelude::*,
|
||||||
|
subclass::prelude::*,
|
||||||
|
Label,
|
||||||
|
};
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
pub struct SettingsEntry(ObjectSubclass<SettingsEntryImp>)
|
||||||
|
@extends gtk4::Widget,
|
||||||
|
@implements gtk4::Accessible;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SettingsEntry {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_child<'a, Widget, IntoWidget>(&self, child: IntoWidget)
|
||||||
|
where
|
||||||
|
Widget: IsA<gtk4::Widget>,
|
||||||
|
IntoWidget: Into<Option<&'a Widget>>,
|
||||||
|
{
|
||||||
|
let imp = self.inner();
|
||||||
|
let child = child.into().map(AsRef::as_ref);
|
||||||
|
let child_box_ref = imp.child_box.borrow();
|
||||||
|
let child_box: >k4::Box = child_box_ref.as_ref().expect("child_box not created??");
|
||||||
|
if let Some(new_child) = child {
|
||||||
|
new_child.set_halign(gtk4::Align::End);
|
||||||
|
child_box.append(new_child);
|
||||||
|
}
|
||||||
|
if let Some(old_child) = imp.child.replace(child.cloned()) {
|
||||||
|
child_box.remove(&old_child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_child_label<A: AsRef<str>>(&self, label: A) {
|
||||||
|
let label = label.as_ref();
|
||||||
|
let child = Label::builder()
|
||||||
|
.label(label)
|
||||||
|
.css_classes(vec!["settings-entry-text".into()])
|
||||||
|
.build();
|
||||||
|
self.set_child(&child);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn align_child(&self, alignment: gtk4::Align) {
|
||||||
|
let imp = self.inner();
|
||||||
|
let child_box = imp.child_box.borrow();
|
||||||
|
let child_box = child_box.as_ref().expect("child_box not created??");
|
||||||
|
let child = imp.child.borrow();
|
||||||
|
let child = child.as_ref().expect("child not set");
|
||||||
|
let title_desc_box = imp.title_desc_box.borrow();
|
||||||
|
let title_desc_box = title_desc_box
|
||||||
|
.as_ref()
|
||||||
|
.expect("title_desc_box not created?");
|
||||||
|
match alignment {
|
||||||
|
gtk4::Align::Start => {
|
||||||
|
child_box.reorder_child_after(title_desc_box, Some(child));
|
||||||
|
}
|
||||||
|
gtk4::Align::End => {
|
||||||
|
child_box.reorder_child_after(child, Some(title_desc_box));
|
||||||
|
}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_title(&self, title: &str) {
|
||||||
|
let inner = self.inner();
|
||||||
|
let title_ref = inner.title.borrow_mut();
|
||||||
|
match &*title_ref {
|
||||||
|
Some(label) => label.set_label(title),
|
||||||
|
None => {
|
||||||
|
let title = gtk4::Label::builder()
|
||||||
|
.label(title)
|
||||||
|
.css_classes(vec!["settings-entry-title".into()])
|
||||||
|
.halign(gtk4::Align::Start)
|
||||||
|
.build();
|
||||||
|
let title_desc_box = inner.title_desc_box.borrow();
|
||||||
|
let title_desc_box = title_desc_box
|
||||||
|
.as_ref()
|
||||||
|
.expect("title_desc_box not created?");
|
||||||
|
if inner.desc.borrow().is_some() {
|
||||||
|
title_desc_box.prepend(&title);
|
||||||
|
} else {
|
||||||
|
title_desc_box.append(&title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_title_markup(&self, title: &str) {
|
||||||
|
let inner = self.inner();
|
||||||
|
let title_ref = inner.title.borrow_mut();
|
||||||
|
match &*title_ref {
|
||||||
|
Some(label) => label.set_markup(title),
|
||||||
|
None => {
|
||||||
|
let title = gtk4::Label::builder()
|
||||||
|
.label(title)
|
||||||
|
.use_markup(true)
|
||||||
|
.css_classes(vec!["settings-entry-title".into()])
|
||||||
|
.halign(gtk4::Align::Start)
|
||||||
|
.build();
|
||||||
|
let title_desc_box = inner.title_desc_box.borrow();
|
||||||
|
let title_desc_box = title_desc_box
|
||||||
|
.as_ref()
|
||||||
|
.expect("title_desc_box not created?");
|
||||||
|
if inner.desc.borrow().is_some() {
|
||||||
|
title_desc_box.prepend(&title);
|
||||||
|
} else {
|
||||||
|
title_desc_box.append(&title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_description(&self, description: &str) {
|
||||||
|
let inner = self.inner();
|
||||||
|
let desc_ref = inner.desc.borrow_mut();
|
||||||
|
match &*desc_ref {
|
||||||
|
Some(label) => label.set_label(description),
|
||||||
|
None => {
|
||||||
|
let desc = gtk4::Label::builder()
|
||||||
|
.label(description)
|
||||||
|
.css_classes(vec!["settings-entry-desc".into()])
|
||||||
|
.halign(gtk4::Align::Start)
|
||||||
|
.build();
|
||||||
|
let title_desc_box = inner.title_desc_box.borrow();
|
||||||
|
let title_desc_box = title_desc_box
|
||||||
|
.as_ref()
|
||||||
|
.expect("title_desc_box not created?");
|
||||||
|
title_desc_box.append(&desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inner(&self) -> &SettingsEntryImp {
|
||||||
|
SettingsEntryImp::from_instance(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for SettingsEntry {
|
||||||
|
fn default() -> Self {
|
||||||
|
Object::new(&[]).expect("Failed to create `SettingsEntry`.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct SettingsEntryImp {
|
||||||
|
title: RefCell<Option<gtk4::Label>>,
|
||||||
|
desc: RefCell<Option<gtk4::Label>>,
|
||||||
|
title_desc_box: RefCell<Option<gtk4::Box>>,
|
||||||
|
child_box: RefCell<Option<gtk4::Box>>,
|
||||||
|
child: RefCell<Option<gtk4::Widget>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for SettingsEntryImp {
|
||||||
|
const NAME: &'static str = "SettingsEntry";
|
||||||
|
type Type = SettingsEntry;
|
||||||
|
type ParentType = gtk4::Widget;
|
||||||
|
type Interfaces = ();
|
||||||
|
type Instance = glib::subclass::basic::InstanceStruct<Self>;
|
||||||
|
type Class = glib::subclass::basic::ClassStruct<Self>;
|
||||||
|
|
||||||
|
fn class_init(klass: &mut Self::Class) {
|
||||||
|
// The layout manager determines how child widgets are laid out.
|
||||||
|
klass.set_layout_manager_type::<gtk4::BinLayout>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ObjectImpl for SettingsEntryImp {
|
||||||
|
fn constructed(&self, obj: &Self::Type) {
|
||||||
|
self.parent_constructed(obj);
|
||||||
|
let child = gtk4::Box::builder()
|
||||||
|
.css_classes(vec!["settings-entry".into()])
|
||||||
|
.orientation(gtk4::Orientation::Horizontal)
|
||||||
|
.hexpand(true)
|
||||||
|
.margin_start(24)
|
||||||
|
.margin_end(24)
|
||||||
|
.margin_top(8)
|
||||||
|
.margin_bottom(8)
|
||||||
|
.spacing(16)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let title_and_desc = gtk4::Box::builder()
|
||||||
|
.css_classes(vec!["settings-entry-info".into()])
|
||||||
|
.orientation(gtk4::Orientation::Vertical)
|
||||||
|
.spacing(4)
|
||||||
|
.hexpand(true)
|
||||||
|
.valign(gtk4::Align::Center)
|
||||||
|
.build();
|
||||||
|
child.append(&title_and_desc);
|
||||||
|
*self.title_desc_box.borrow_mut() = Some(title_and_desc);
|
||||||
|
if let Some(entry_child) = self.child.borrow().as_ref() {
|
||||||
|
child.append(entry_child);
|
||||||
|
}
|
||||||
|
child.set_parent(obj);
|
||||||
|
*self.child_box.borrow_mut() = Some(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dispose(&self, _obj: &Self::Type) {
|
||||||
|
if let Some(child) = self.child.borrow_mut().take() {
|
||||||
|
child.unparent();
|
||||||
|
}
|
||||||
|
if let Some(child_box) = self.child_box.borrow_mut().take() {
|
||||||
|
child_box.unparent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WidgetImpl for SettingsEntryImp {}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue