wip: example applet

This commit is contained in:
Ashley Wulber 2022-11-11 05:06:54 +01:00
parent 45ccc8c3d2
commit b1c3a52589
No known key found for this signature in database
GPG key ID: 5216D4F46A90A820
18 changed files with 525 additions and 103 deletions

View file

@ -62,6 +62,4 @@ branch = "sctk-cosmic"
[workspace]
members = [
"examples/*",
"gtk4",
"gtk4/widgets"
]

View file

@ -0,0 +1,14 @@
[package]
name = "cosmic-applet-graphics"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
zbus = "3.4"
libcosmic = { path = "../..", default-features = false, features = ["debug", "wayland"] }
# cosmic-panel-config = {git = "https://github.com/pop-os/cosmic-panel" }
cosmic-panel-config = { path = "../../../cosmic-panel/cosmic-panel-config", default-features = false }
iced_sctk = { git = "https://github.com/pop-os/iced-sctk" }
sctk = { package = "smithay-client-toolkit", git = "https://github.com/Smithay/client-toolkit" }

View file

@ -0,0 +1,12 @@
[Desktop Entry]
Name=Cosmic Applet Graphics
Comment=Write a GTK + Rust application
Type=Application
Exec=cosmic-applet-graphics
Terminal=false
Categories=GNOME;GTK;
Keywords=Gnome;GTK;
# Translators: Do NOT translate or transliterate this text (this is an icon file name)!
Icon=com.system76.CosmicAppletGraphics.svg
StartupNotify=true
NoDisplay=true

View file

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="128px" height="128px" viewBox="0 0 128 128" version="1.1">
<defs>
<filter id="alpha" filterUnits="objectBoundingBox" x="0%" y="0%" width="100%" height="100%">
<feColorMatrix type="matrix" in="SourceGraphic" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
</filter>
<mask id="mask0">
<g filter="url(#alpha)">
<rect x="0" y="0" width="128" height="128" style="fill:rgb(0%,0%,0%);fill-opacity:0.1;stroke:none;"/>
</g>
</mask>
<clipPath id="clip1">
<rect x="0" y="0" width="192" height="152"/>
</clipPath>
<g id="surface10632" clip-path="url(#clip1)">
<path style="fill:none;stroke-width:0.99;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.99,0.99;stroke-miterlimit:4;" d="M 123.503906 236 C 123.503906 268.863281 96.863281 295.503906 64 295.503906 C 31.136719 295.503906 4.496094 268.863281 4.496094 236 C 4.496094 203.136719 31.136719 176.496094 64 176.496094 C 96.863281 176.496094 123.503906 203.136719 123.503906 236 Z M 123.503906 236 " transform="matrix(1,0,0,1,8,-156)"/>
</g>
<mask id="mask1">
<g filter="url(#alpha)">
<rect x="0" y="0" width="128" height="128" style="fill:rgb(0%,0%,0%);fill-opacity:0.1;stroke:none;"/>
</g>
</mask>
<clipPath id="clip2">
<rect x="0" y="0" width="192" height="152"/>
</clipPath>
<g id="surface10635" clip-path="url(#clip2)">
<path style="fill:none;stroke-width:0.99;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.99,0.99;stroke-miterlimit:4;" d="M 29.195312 180.496094 L 98.804688 180.496094 C 103.609375 180.496094 107.503906 184.046875 107.503906 188.425781 L 107.503906 283.574219 C 107.503906 287.953125 103.609375 291.503906 98.804688 291.503906 L 29.195312 291.503906 C 24.390625 291.503906 20.496094 287.953125 20.496094 283.574219 L 20.496094 188.425781 C 20.496094 184.046875 24.390625 180.496094 29.195312 180.496094 Z M 29.195312 180.496094 " transform="matrix(1,0,0,1,8,-156)"/>
</g>
<mask id="mask2">
<g filter="url(#alpha)">
<rect x="0" y="0" width="128" height="128" style="fill:rgb(0%,0%,0%);fill-opacity:0.1;stroke:none;"/>
</g>
</mask>
<clipPath id="clip3">
<rect x="0" y="0" width="192" height="152"/>
</clipPath>
<g id="surface10638" clip-path="url(#clip3)">
<path style="fill:none;stroke-width:0.99;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.99,0.99;stroke-miterlimit:4;" d="M 20.417969 184.496094 L 107.582031 184.496094 C 111.957031 184.496094 115.503906 188.042969 115.503906 192.417969 L 115.503906 279.582031 C 115.503906 283.957031 111.957031 287.503906 107.582031 287.503906 L 20.417969 287.503906 C 16.042969 287.503906 12.496094 283.957031 12.496094 279.582031 L 12.496094 192.417969 C 12.496094 188.042969 16.042969 184.496094 20.417969 184.496094 Z M 20.417969 184.496094 " transform="matrix(1,0,0,1,8,-156)"/>
</g>
<mask id="mask3">
<g filter="url(#alpha)">
<rect x="0" y="0" width="128" height="128" style="fill:rgb(0%,0%,0%);fill-opacity:0.1;stroke:none;"/>
</g>
</mask>
<clipPath id="clip4">
<rect x="0" y="0" width="192" height="152"/>
</clipPath>
<g id="surface10641" clip-path="url(#clip4)">
<path style="fill:none;stroke-width:0.99;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(0%,0%,0%);stroke-opacity:1;stroke-dasharray:0.99,0.99;stroke-miterlimit:4;" d="M 16.425781 200.496094 L 111.574219 200.496094 C 115.953125 200.496094 119.503906 204.390625 119.503906 209.195312 L 119.503906 278.804688 C 119.503906 283.609375 115.953125 287.503906 111.574219 287.503906 L 16.425781 287.503906 C 12.046875 287.503906 8.496094 283.609375 8.496094 278.804688 L 8.496094 209.195312 C 8.496094 204.390625 12.046875 200.496094 16.425781 200.496094 Z M 16.425781 200.496094 " transform="matrix(1,0,0,1,8,-156)"/>
</g>
</defs>
<g id="surface10578">
<rect x="0" y="0" width="128" height="128" style="fill:rgb(94.117647%,94.117647%,94.117647%);fill-opacity:1;stroke:none;"/>
<use xlink:href="#surface10632" transform="matrix(1,0,0,1,-8,-16)" mask="url(#mask0)"/>
<use xlink:href="#surface10635" transform="matrix(1,0,0,1,-8,-16)" mask="url(#mask1)"/>
<use xlink:href="#surface10638" transform="matrix(1,0,0,1,-8,-16)" mask="url(#mask2)"/>
<use xlink:href="#surface10641" transform="matrix(1,0,0,1,-8,-16)" mask="url(#mask3)"/>
<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(38.431373%,62.7451%,91.764706%);stroke-opacity:1;stroke-miterlimit:4;" d="M 0 289 L 128 289 " transform="matrix(1,0,0,1,0,-172)"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/com/System76/CosmicDockAppList/">
<!-- see https://gtk-rs.org/gtk4-rs/git/docs/gtk4/struct.Application.html#automatic-resources -->
</gresource>
</gresources>

View file

@ -0,0 +1,90 @@
// SPDX-License-Identifier: GPL-3.0-or-later
//! # DBus interface proxy for: `com.system76.PowerDaemon`
//!
//! This code was generated by `zbus-xmlgen` `3.0.0` from DBus introspection data.
//! Source: `Interface '/com/system76/PowerDaemon' from service 'com.system76.PowerDaemon' on system bus`.
//!
//! You may prefer to adapt it, instead of using it verbatim.
//!
//! More information can be found in the
//! [Writing a client proxy](https://dbus.pages.freedesktop.org/zbus/client.html)
//! section of the zbus documentation.
//!
//! This DBus object implements
//! [standard DBus interfaces](https://dbus.freedesktop.org/doc/dbus-specification.html),
//! (`org.freedesktop.DBus.*`) for which the following zbus proxies can be used:
//!
//! * [`zbus::fdo::IntrospectableProxy`]
//!
//! …consequently `zbus-xmlgen` did not generate code for the above interfaces.
use zbus::{dbus_proxy, Connection};
#[dbus_proxy(interface = "com.system76.PowerDaemon", default_path = "/com/system76/PowerDaemon")]
trait PowerDaemon {
/// Balanced method
fn balanced(&self) -> zbus::Result<()>;
/// Battery method
fn battery(&self) -> zbus::Result<()>;
/// GetChargeProfiles method
fn get_charge_profiles(
&self,
) -> zbus::Result<Vec<std::collections::HashMap<String, zbus::zvariant::OwnedValue>>>;
/// GetChargeThresholds method
fn get_charge_thresholds(&self) -> zbus::Result<(u8, u8)>;
/// GetDefaultGraphics method
fn get_default_graphics(&self) -> zbus::Result<String>;
/// GetExternalDisplaysRequireDGPU method
fn get_external_displays_require_dgpu(&self) -> zbus::Result<bool>;
/// GetGraphics method
fn get_graphics(&self) -> zbus::Result<String>;
/// GetGraphicsPower method
fn get_graphics_power(&self) -> zbus::Result<bool>;
/// GetProfile method
fn get_profile(&self) -> zbus::Result<String>;
/// GetSwitchable method
fn get_switchable(&self) -> zbus::Result<bool>;
/// Performance method
fn performance(&self) -> zbus::Result<()>;
/// SetChargeThresholds method
fn set_charge_thresholds(&self, thresholds: &(u8, u8)) -> zbus::Result<()>;
/// SetGraphics method
fn set_graphics(&self, vendor: &str) -> zbus::Result<()>;
/// SetGraphicsPower method
fn set_graphics_power(&self, power: bool) -> zbus::Result<()>;
/// HotPlugDetect signal
#[dbus_proxy(signal)]
fn hot_plug_detect(&self, port: u64) -> zbus::Result<()>;
/// PowerProfileSwitch signal
#[dbus_proxy(signal)]
fn power_profile_switch(&self, profile: &str) -> zbus::Result<()>;
}
pub async fn init() -> Option<(Connection, PowerDaemonProxy<'static>)> {
let conn = match Connection::system().await {
Ok(conn) => conn,
_ => return None,
};
let proxy = match PowerDaemonProxy::new(&conn).await {
Ok(p) => p,
_ => return None,
};
Some((conn, proxy))
}

View file

@ -0,0 +1,32 @@
// SPDX-License-Identifier: GPL-3.0-or-later
use crate::dbus::PowerDaemonProxy;
use zbus::Result;
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum Graphics {
Integrated,
Hybrid,
Nvidia,
Compute,
}
pub async fn get_current_graphics(daemon: PowerDaemonProxy<'_>) -> Result<Graphics> {
let graphics = daemon.get_graphics().await?;
match graphics.as_str() {
"integrated" => Ok(Graphics::Integrated),
"hybrid" => Ok(Graphics::Hybrid),
"nvidia" => Ok(Graphics::Nvidia),
"compute" => Ok(Graphics::Compute),
_ => panic!("Unknown graphics profile: {}", graphics),
}
}
pub async fn set_graphics(daemon: PowerDaemonProxy<'_>, graphics: Graphics) -> Result<()> {
let graphics_str = match graphics {
Graphics::Integrated => "integrated",
Graphics::Hybrid => "hybrid",
Graphics::Nvidia => "nvidia",
Graphics::Compute => "compute",
};
daemon.set_graphics(graphics_str).await
}

View file

@ -0,0 +1,37 @@
mod dbus;
mod graphics;
mod window;
use cosmic::{
iced::{sctk_settings::InitialSurface, Application},
iced_native::window::Settings,
iced_winit::command::platform_specific::wayland::window::SctkWindowSettings,
settings,
};
use cosmic_panel_config::PanelSize;
use window::*;
pub fn main() -> cosmic::iced::Result {
let mut settings = settings();
let pixels = std::env::var("COSMIC_PANEL_SIZE")
.ok()
.and_then(|size| match size.parse::<PanelSize>() {
Ok(PanelSize::XL) => Some(64),
Ok(PanelSize::L) => Some(48),
Ok(PanelSize::M) => Some(36),
Ok(PanelSize::S) => Some(24),
Ok(PanelSize::XS) => Some(18),
Err(_) => Some(36),
})
.unwrap_or(36);
settings.initial_surface = InitialSurface::XdgWindow(SctkWindowSettings {
iced_settings: Settings {
size: (pixels + 32, pixels + 16),
min_size: Some((pixels + 32, pixels + 16)),
max_size: Some((pixels + 32, pixels + 16)),
..Default::default()
},
..Default::default()
});
Window::run(settings)
}

View file

@ -0,0 +1,218 @@
use crate::dbus::{self, PowerDaemonProxy};
use crate::graphics::{get_current_graphics, Graphics};
use cosmic::widget::{expander, icon, nav_bar, nav_bar_page, nav_bar_section};
use cosmic::{
iced::widget::{
checkbox, column, container, horizontal_space, pick_list, progress_bar, radio, row, slider,
text,
},
iced::{self, Alignment, Application, Color, Command, Length},
iced_lazy::responsive,
iced_native::window,
iced_winit::window::{drag, maximize, minimize},
list_view, list_view_item, list_view_row, list_view_section, scrollable,
theme::{self, Theme},
widget::{button, header_bar, list_box, list_row, list_view::*, toggler},
Element,
};
use cosmic::{iced_native, separator};
use cosmic_panel_config::PanelSize;
use iced_sctk::alignment::Horizontal;
use iced_sctk::command::platform_specific::wayland::popup::{SctkPopupSettings, SctkPositioner};
use iced_sctk::commands::popup::{destroy_popup, get_popup};
use iced_sctk::{Point, Rectangle, Size};
use sctk::reexports::protocols::xdg::shell::client::xdg_positioner::{Anchor, Gravity};
use zbus::Connection;
#[derive(Default)]
pub struct Window {
popup: Option<window::Id>,
graphics_mode: Option<Graphics>,
id_ctr: u32,
icon_size: u16,
theme: Theme,
dbus: Option<(Connection, PowerDaemonProxy<'static>)>,
}
#[allow(dead_code)]
#[derive(Clone, Debug)]
pub enum Message {
CurrentGraphics(Option<Graphics>),
DBusInit(Option<(Connection, PowerDaemonProxy<'static>)>),
SelectGraphicsMode(Graphics),
TogglePopup,
}
impl Application for Window {
type Executor = iced::executor::Default;
type Flags = ();
type Message = Message;
type Theme = Theme;
fn new(_flags: ()) -> (Self, Command<Self::Message>) {
let mut window = Window::default();
let pixels = std::env::var("COSMIC_PANEL_SIZE")
.ok()
.and_then(|size| match size.parse::<PanelSize>() {
Ok(PanelSize::XL) => Some(64),
Ok(PanelSize::L) => Some(36),
Ok(PanelSize::M) => Some(24),
Ok(PanelSize::S) => Some(16),
Ok(PanelSize::XS) => Some(12),
Err(_) => Some(12),
})
.unwrap_or(16);
window.icon_size = pixels;
(
window,
Command::perform(dbus::init(), |dbus_init| Message::DBusInit(dbus_init)),
)
}
fn title(&self) -> String {
String::from("Cosmic Graphics Applet")
}
fn update(&mut self, message: Message) -> iced::Command<Self::Message> {
match message {
Message::SelectGraphicsMode(_) => {}
Message::TogglePopup => {
if let Some(p) = self.popup.take() {
return destroy_popup(p);
} else {
self.id_ctr += 1;
let new_id = window::Id::new(self.id_ctr);
self.popup.replace(new_id);
let mut commands = Vec::new();
if let Some((_, proxy)) = self.dbus.as_ref() {
commands.push(Command::perform(
get_current_graphics(proxy.clone()),
|cur_graphics| Message::CurrentGraphics(cur_graphics.ok()),
));
}
commands.push(Command::batch(vec![get_popup(SctkPopupSettings {
parent: window::Id::new(0),
id: new_id,
positioner: SctkPositioner {
size: (200, 200),
anchor_rect: Rectangle {
x: 0,
y: 0,
width: 32 + self.icon_size as i32,
height: 16 + self.icon_size as i32,
},
anchor: Anchor::Bottom,
gravity: Gravity::Bottom,
reactive: true,
..Default::default()
},
parent_size: None,
grab: true,
})]));
return Command::batch(commands);
}
}
Message::DBusInit(dbus) => {
self.dbus = dbus;
return Command::perform(
get_current_graphics(self.dbus.as_ref().unwrap().1.clone()),
|cur_graphics| {
Message::CurrentGraphics(match cur_graphics {
Ok(g) => Some(g),
Err(err) => {
dbg!(err);
None
},
})
},
);
}
Message::CurrentGraphics(g) => {
if let Some(g) = g {
self.graphics_mode.replace(g);
}
}
}
Command::none()
}
fn view_popup(&self, _: window::Id) -> Element<Message> {
let content = column(vec![
text("Graphics Mode")
.width(Length::Fill)
.horizontal_alignment(Horizontal::Center)
.size(24)
.into(),
separator!(1).into(),
column(vec![
radio(
"Integrated Graphics",
Graphics::Integrated,
self.graphics_mode,
|g| Message::SelectGraphicsMode(g),
)
.into(),
radio(
"Nvidia Graphics",
Graphics::Nvidia,
self.graphics_mode,
|g| Message::SelectGraphicsMode(g),
)
.into(),
radio(
"Hybrid Graphics",
Graphics::Hybrid,
self.graphics_mode,
|g| Message::SelectGraphicsMode(g),
)
.into(),
radio(
"Compute Graphics",
Graphics::Compute,
self.graphics_mode,
|g| Message::SelectGraphicsMode(g),
)
.into(),
])
.padding([8, 0])
.spacing(8)
.into(),
])
.padding(4)
.spacing(4)
.into();
content
}
fn view_layer_surface(
&self,
_: cosmic::iced_native::window::Id,
) -> iced::Element<'_, Self::Message, iced::Renderer<Self::Theme>> {
unimplemented!()
}
fn close_window_requested(&self, _: cosmic::iced_native::window::Id) -> Self::Message {
unimplemented!()
}
fn popup_done(&self, _: cosmic::iced_native::window::Id) -> Self::Message {
unimplemented!()
}
fn layer_surface_done(&self, _: cosmic::iced_native::window::Id) -> Self::Message {
unimplemented!()
}
fn view_window(&self, id: window::Id) -> Element<Message> {
// TODO use panel config crate after resolving version mismatch
button!(icon("input-gaming-symbolic", self.icon_size).style(theme::Svg::Accent))
.on_press(Message::TogglePopup)
.into()
}
fn should_exit(&self) -> bool {
false
}
fn theme(&self) -> Theme {
self.theme
}
}

View file

@ -1,4 +1,7 @@
use cosmic::{iced::{Application, sctk_settings::InitialSurface}, settings};
use cosmic::{
iced::{sctk_settings::InitialSurface, Application},
settings,
};
mod window;
pub use window::*;

View file

@ -6,8 +6,8 @@ use cosmic::{
},
iced::{self, Alignment, Application, Color, Command, Length},
iced_lazy::responsive,
iced_winit::window::{drag, maximize, minimize},
iced_native::window,
iced_winit::window::{drag, maximize, minimize},
list_view, list_view_item, list_view_row, list_view_section, scrollable,
theme::{self, Theme},
widget::{button, header_bar, list_box, list_row, list_view::*, toggler},
@ -15,7 +15,6 @@ use cosmic::{
};
use std::collections::BTreeMap;
#[derive(Default)]
pub struct Window {
page: u8,
@ -112,8 +111,8 @@ impl Application for Window {
unimplemented!()
}
fn view_layer_surface(
&self,
window: cosmic::iced_native::window::Id,
&self,
window: cosmic::iced_native::window::Id,
) -> iced::Element<'_, Self::Message, iced::Renderer<Self::Theme>> {
unimplemented!()
}
@ -184,9 +183,7 @@ impl Application for Window {
vec![nav_bar_page("Wi-Fi")],
),
(
nav_bar_section()
.title("Bluetooth")
.icon("cs-bluetooth"),
nav_bar_section().title("Bluetooth").icon("cs-bluetooth"),
vec![nav_bar_page("Devices")],
),
(
@ -213,9 +210,7 @@ impl Application for Window {
vec![nav_bar_page("Keyboard")],
),
(
nav_bar_section()
.title("Power & Battery")
.icon("battery"),
nav_bar_section().title("Power & Battery").icon("battery"),
vec![nav_bar_page("Status")],
),
(

View file

@ -6,8 +6,8 @@ use cosmic::{
},
iced::{self, Alignment, Application, Color, Command, Length},
iced_lazy::responsive,
iced_winit::window::{drag, maximize, minimize},
iced_native::window,
iced_winit::window::{drag, maximize, minimize},
list_view, list_view_item, list_view_row, list_view_section, scrollable,
theme::{self, Theme},
widget::{button, header_bar, list_box, list_row, list_view::*, toggler},
@ -165,9 +165,7 @@ impl Application for Window {
vec![nav_bar_page("Wi-Fi")],
),
(
nav_bar_section()
.title("Bluetooth")
.icon("cs-bluetooth"),
nav_bar_section().title("Bluetooth").icon("cs-bluetooth"),
vec![nav_bar_page("Devices")],
),
(
@ -194,9 +192,7 @@ impl Application for Window {
vec![nav_bar_page("Keyboard")],
),
(
nav_bar_section()
.title("Power & Battery")
.icon("battery"),
nav_bar_section().title("Power & Battery").icon("battery"),
vec![nav_bar_page("Status")],
),
(

View file

@ -174,11 +174,7 @@ impl Default for Checkbox {
impl checkbox::StyleSheet for Theme {
type Style = Checkbox;
fn active(
&self,
style: &Self::Style,
is_checked: bool,
) -> checkbox::Appearance {
fn active(&self, style: &Self::Style, is_checked: bool) -> checkbox::Appearance {
let palette = self.extended_palette();
match style {
@ -209,11 +205,7 @@ impl checkbox::StyleSheet for Theme {
}
}
fn hovered(
&self,
style: &Self::Style,
is_checked: bool,
) -> checkbox::Appearance {
fn hovered(&self, style: &Self::Style, is_checked: bool) -> checkbox::Appearance {
let palette = self.extended_palette();
match style {
@ -252,11 +244,7 @@ fn checkbox_appearance(
is_checked: bool,
) -> checkbox::Appearance {
checkbox::Appearance {
background: Background::Color(if is_checked {
accent.color
} else {
base.color
}),
background: Background::Color(if is_checked { accent.color } else { base.color }),
checkmark_color,
border_radius: 4.0,
border_width: if is_checked { 0.0 } else { 1.0 },
@ -355,21 +343,17 @@ impl slider::StyleSheet for Theme {
Color::TRANSPARENT,
),
handle: slider::Handle {
shape: slider::HandleShape::Circle {
radius: 10.0,
},
shape: slider::HandleShape::Circle { radius: 10.0 },
color: cosmic.accent.base.into(),
border_color: Color::TRANSPARENT,
border_width: 0.0,
}
},
}
}
fn hovered(&self, style: &Self::Style) -> slider::Appearance {
let mut style = self.active(&style);
style.handle.shape = slider::HandleShape::Circle {
radius: 16.0
};
style.handle.shape = slider::HandleShape::Circle { radius: 16.0 };
style.handle.border_width = 6.0;
style.handle.border_color = match self {
Theme::Dark => Color::from_rgba8(0xFF, 0xFF, 0xFF, 0.1),
@ -475,11 +459,7 @@ impl radio::StyleSheet for Theme {
impl toggler::StyleSheet for Theme {
type Style = ();
fn active(
&self,
_style: &Self::Style,
is_active: bool,
) -> toggler::Appearance {
fn active(&self, _style: &Self::Style, is_active: bool) -> toggler::Appearance {
let palette = self.palette();
toggler::Appearance {
@ -502,14 +482,10 @@ impl toggler::StyleSheet for Theme {
}
}
fn hovered(
&self,
style: &Self::Style,
is_active: bool,
) -> toggler::Appearance {
fn hovered(&self, style: &Self::Style, is_active: bool) -> toggler::Appearance {
//TODO: grab colors from palette
match self {
Theme::Dark => toggler::Appearance {
Theme::Dark => toggler::Appearance {
background: if is_active {
Color::from_rgb8(0x9f, 0xed, 0xed)
} else {
@ -517,14 +493,14 @@ impl toggler::StyleSheet for Theme {
},
..self.active(&style, is_active)
},
Theme::Light => toggler::Appearance {
Theme::Light => toggler::Appearance {
background: if is_active {
Color::from_rgb8(0x00, 0x42, 0x62)
} else {
Color::from_rgb8(0x54, 0x54, 0x54)
},
..self.active(&style, is_active)
}
},
}
}
}
@ -666,7 +642,6 @@ impl scrollable::StyleSheet for Theme {
}
}
#[derive(Default, Clone, Copy)]
pub enum Svg {
Custom(fn(&Theme) -> svg::Appearance),
@ -715,7 +690,7 @@ impl text::StyleSheet for Theme {
fn appearance(&self, style: Self::Style) -> text::Appearance {
match style {
Text::Accent => text::Appearance {
color: Some(self.cosmic().accent.base.into())
color: Some(self.cosmic().accent.base.into()),
},
Text::Default => Default::default(),
Text::Color(c) => text::Appearance { color: Some(c) },

View file

@ -46,7 +46,7 @@ impl Palette {
background: Color::from_rgb(
0x1e as f32 / 255.0,
0x1e as f32 / 255.0,
0x1e as f32 / 255.0
0x1e as f32 / 255.0,
),
text: Color::from_rgb(
0xe4 as f32 / 255.0,
@ -80,8 +80,7 @@ pub struct Extended {
}
lazy_static! {
pub static ref EXTENDED_LIGHT: Extended =
Extended::generate(Palette::LIGHT);
pub static ref EXTENDED_LIGHT: Extended = Extended::generate(Palette::LIGHT);
pub static ref EXTENDED_DARK: Extended = Extended::generate(Palette::DARK);
}
@ -89,22 +88,10 @@ impl Extended {
pub fn generate(palette: Palette) -> Self {
Self {
background: Background::new(palette.background, palette.text),
primary: Primary::generate(
palette.primary,
palette.background,
palette.text,
),
primary: Primary::generate(palette.primary, palette.background, palette.text),
secondary: Secondary::generate(palette.background, palette.text),
success: Success::generate(
palette.success,
palette.background,
palette.text,
),
danger: Danger::generate(
palette.danger,
palette.background,
palette.text,
),
success: Success::generate(palette.success, palette.background, palette.text),
danger: Danger::generate(palette.danger, palette.background, palette.text),
}
}
}

View file

@ -1,8 +1,8 @@
use crate::{theme, Element, Renderer};
use apply::Apply;
use derive_setters::*;
use iced::{self, alignment::Vertical, widget, Length};
use iced_lazy::Component;
use crate::{theme, Element, Renderer};
#[derive(Setters)]
pub struct HeaderBar<Message> {

View file

@ -1,5 +1,5 @@
pub use iced::{widget, Background, Color};
pub use crate::Theme;
pub use iced::{widget, Background, Color};
pub mod list_view {
#[macro_export]
@ -82,8 +82,8 @@ pub mod list_view {
}
use crate::widget::{Background, Color};
use iced::widget;
use crate::Theme;
use iced::widget;
pub use list_view;
pub use list_view_item;

View file

@ -1,6 +1,6 @@
pub mod nav_bar {
use iced::{widget, Background, Color};
use crate::Theme;
use iced::{widget, Background, Color};
#[macro_export]
macro_rules! nav_button {

View file

@ -98,7 +98,7 @@ where
<<Renderer as iced_native::Renderer>::Theme as container::StyleSheet>::Style:
From<theme::Container>,
<<Renderer as iced_native::Renderer>::Theme as text::StyleSheet>::Style: From<theme::Text>,
Renderer::Theme: iced_native::svg::StyleSheet
Renderer::Theme: iced_native::svg::StyleSheet,
{
type State = NavBarState;
type Event = NavBarEvent;
@ -146,11 +146,13 @@ where
.height(Length::Units(50))
.align_items(Alignment::Center),
)
.style(if *section == state.selected_section && state.section_active {
theme::Button::Primary.into()
} else {
theme::Button::Text.into()
})
.style(
if *section == state.selected_section && state.section_active {
theme::Button::Primary.into()
} else {
theme::Button::Text.into()
},
)
.on_press(NavBarEvent::SectionSelected(section.clone()))
.into(),
);
@ -159,17 +161,15 @@ where
pages.push(
button(row![text(&page.title).size(16).width(Length::Fill)])
.padding(10)
.style(
if let Some(selected_page) = &state.selected_page {
if state.page_active && page == selected_page {
theme::Button::Primary.into()
} else {
theme::Button::Text.into()
}
.style(if let Some(selected_page) = &state.selected_page {
if state.page_active && page == selected_page {
theme::Button::Primary.into()
} else {
theme::Button::Text.into()
}
)
} else {
theme::Button::Text.into()
})
.on_press(NavBarEvent::PageSelected(section.clone(), page.clone()))
.into(),
);
@ -180,13 +180,13 @@ where
let nav_bar: Element<Self::Event, Renderer> =
container(if self.condensed && state.selected_page.is_some() {
row![container(scrollable!(column(pages)
.spacing(10)
.padding(10)
.max_width(200)
.width(Length::Units(200))
.height(Length::Shrink)))
.height(Length::Fill)
.style(theme::Container::Custom(nav_bar_pages_style))]
.spacing(10)
.padding(10)
.max_width(200)
.width(Length::Units(200))
.height(Length::Shrink)))
.height(Length::Fill)
.style(theme::Container::Custom(nav_bar_pages_style))]
} else if !state.section_active || self.condensed && state.selected_page.is_none() {
row![scrollable!(column(sections)
.spacing(10)
@ -222,8 +222,7 @@ where
}
}
impl<'a, Message: 'a, Renderer> From<NavBar<'a, Message>>
for Element<'a, Message, Renderer>
impl<'a, Message: 'a, Renderer> From<NavBar<'a, Message>> for Element<'a, Message, Renderer>
where
Renderer: iced_native::text::Renderer + iced_native::svg::Renderer + 'a,
<Renderer as iced_native::Renderer>::Theme:
@ -232,7 +231,7 @@ where
<<Renderer as iced_native::Renderer>::Theme as container::StyleSheet>::Style:
From<theme::Container>,
<<Renderer as iced_native::Renderer>::Theme as text::StyleSheet>::Style: From<theme::Text>,
Renderer::Theme: iced_native::svg::StyleSheet
Renderer::Theme: iced_native::svg::StyleSheet,
{
fn from(nav_bar: NavBar<'a, Message>) -> Self {
iced_lazy::component(nav_bar)