Skip to content

Commit

Permalink
feat: icon theme abstraction for certain icons
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Brue <[email protected]>
  • Loading branch information
ryanabx committed Sep 22, 2024
1 parent 32ee116 commit 51f6f31
Show file tree
Hide file tree
Showing 10 changed files with 137 additions and 77 deletions.
4 changes: 2 additions & 2 deletions src/app_tray/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{collections::HashMap, rc::Rc};

use super::desktop_entry::DesktopEntryCache;
use super::freedesktop::desktop_entry::DesktopEntryCache;
use cctk::wayland_client::protocol::wl_seat::WlSeat;
use compositor::{
CompositorBackend, CompositorToplevelInfo, ToplevelHandle, WaylandIncoming, WaylandOutgoing,
Expand All @@ -11,7 +11,7 @@ use crate::{
component_theme::{button_style, PANEL_SIZE},
components::app_tray_button,
config::AppTrayConfig,
desktop_entry::EntryInfo,
freedesktop::desktop_entry::EntryInfo,
};

pub mod compositor;
Expand Down
16 changes: 15 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use std::{

use serde::{Deserialize, Serialize};

use crate::freedesktop::icons::IconTheme;

#[derive(Debug, thiserror::Error)]
pub enum ConfigError {
#[error("IO: {0}")]
Expand All @@ -14,9 +16,21 @@ pub enum ConfigError {
Serde(#[from] serde_json::Error),
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PanelConfig {
pub app_tray: AppTrayConfig,
pub icon_theme: IconTheme,
pub use_winit: bool,
}

impl Default for PanelConfig {
fn default() -> Self {
Self {
app_tray: Default::default(),
icon_theme: Default::default(),
use_winit: Default::default(),
}
}
}

impl PanelConfig {
Expand Down
36 changes: 6 additions & 30 deletions src/desktop_entry.rs → src/freedesktop/desktop_entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use freedesktop_desktop_entry::{
default_paths, get_languages_from_env, DesktopEntry, Iter, Locale, PathSource,
};

use super::icons::{default_icon_path, IconTheme};

#[derive(Clone, Debug)]
pub struct DesktopEntryCache<'a>(pub HashMap<String, EntryInfo<'a>>);

Expand All @@ -15,7 +17,7 @@ pub struct EntryInfo<'a> {
}

impl<'a> EntryInfo<'a> {
pub fn new(desktop_entry: DesktopEntry<'a>) -> Self {
pub fn new(desktop_entry: DesktopEntry<'a>, icon_theme: &IconTheme) -> Self {
let invisible = desktop_entry.no_display()
|| desktop_entry.name(&get_languages_from_env()).is_none()
|| desktop_entry.terminal()
Expand All @@ -29,7 +31,7 @@ impl<'a> EntryInfo<'a> {
.with_theme("hicolor")
.with_cache()
.find()
.or_else(default_icon_path)
.or_else(|| default_icon_path(&icon_theme))
})
};
Self {
Expand All @@ -40,22 +42,16 @@ impl<'a> EntryInfo<'a> {
}
}

impl<'a> Default for DesktopEntryCache<'a> {
fn default() -> Self {
Self::new()
}
}

impl<'a> DesktopEntryCache<'a> {
pub fn new() -> Self {
pub fn new(icon_theme: &IconTheme) -> Self {
let locales = get_languages_from_env();
log::debug!("{:?}", default_paths());
let entries = Iter::new(default_paths())
.filter_map(|path| {
let path_src = PathSource::guess_from(&path);
if let Ok(entry) = DesktopEntry::from_path(path.clone(), &locales) {
log::debug!("{:?}::{}", path_src, &entry.appid);
return Some((entry.appid.to_string(), EntryInfo::new(entry)));
return Some((entry.appid.to_string(), EntryInfo::new(entry, &icon_theme)));
}
None
})
Expand Down Expand Up @@ -89,23 +85,3 @@ impl<'a> DesktopEntryCache<'a> {
.cloned() // TODO: Can I make this more efficient?
}
}

pub fn default_icon_path() -> Option<PathBuf> {
freedesktop_icons::lookup("wayland")
.with_theme("breeze")
.with_cache()
.find()
}

pub fn start_menu_icon() -> Option<PathBuf> {
freedesktop_icons::lookup("applications-all")
.with_theme("breeze")
.with_cache()
.find()
.or_else(|| {
freedesktop_icons::lookup("applications-office")
.with_theme("Cosmic")
.with_cache()
.find()
})
}
52 changes: 52 additions & 0 deletions src/freedesktop/icons.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use std::{env, path::PathBuf};

use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum IconTheme {
Breeze,
Cosmic,
None,
}

impl Default for IconTheme {
fn default() -> Self {
// guess icon theme
let current_desktop = env::var_os("XDG_CURRENT_DESKTOP")
.map(|x| x.to_ascii_lowercase().to_string_lossy().to_string());
match current_desktop.as_deref() {
Some("kde") => Self::Breeze,
Some("cosmic") => Self::Cosmic,
Some(_) => Self::None, // Don't know what desktop this is
None => Self::None,
}
}
}

pub fn default_icon_path(theme: &IconTheme) -> Option<PathBuf> {
match theme {
IconTheme::Breeze => freedesktop_icons::lookup("wayland")
.with_theme("breeze")
.with_cache()
.find(),
IconTheme::Cosmic => freedesktop_icons::lookup("application-default")
.with_theme("Cosmic")
.with_cache()
.find(),
IconTheme::None => None,
}
}

pub fn start_menu_icon(theme: &IconTheme) -> Option<PathBuf> {
match theme {
IconTheme::Breeze => freedesktop_icons::lookup("applications-all")
.with_theme("breeze")
.with_cache()
.find(),
IconTheme::Cosmic => freedesktop_icons::lookup("applications-office")
.with_theme("Cosmic")
.with_cache()
.find(),
IconTheme::None => None,
}
}
2 changes: 2 additions & 0 deletions src/freedesktop/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod desktop_entry;
pub mod icons;
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ use panel::Panel;
pub mod app_tray;
pub mod component_theme;
pub mod components;
pub mod freedesktop;

mod config;
pub mod desktop_entry;
mod panel;
mod settings_tray;
pub mod start_menu;
Expand Down
74 changes: 39 additions & 35 deletions src/panel.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{env, rc::Rc};
use std::rc::Rc;

use iced::{
border::Radius,
Expand All @@ -19,7 +19,7 @@ use crate::{
app_tray::{AppTray, AppTrayMessage},
component_theme::PANEL_SIZE,
config::PanelConfig,
desktop_entry::DesktopEntryCache,
freedesktop::{desktop_entry::DesktopEntryCache, icons::IconTheme},
settings_tray::{SettingsTray, SettingsTrayMessage},
start_menu::{StartMenu, StartMenuMessage},
};
Expand All @@ -30,6 +30,7 @@ pub struct Panel<'a> {
settings_tray: SettingsTray,
main_window: window::Id,
popup_window: Option<(window::Id, PopupType)>,
icon_theme: IconTheme,
}

#[derive(Clone, Debug)]
Expand All @@ -40,46 +41,46 @@ pub enum PopupType {

impl<'a> Panel<'a> {
pub fn new(config: PanelConfig) -> (Self, Task<Message>) {
let (id, open) =
if env::var("RBSHELL_USE_WINIT").is_ok_and(|val| val.to_lowercase() == "true") {
let (id, open) = window::open(window::Settings {
size: (1280.0, 48.0).into(),
..Default::default()
});
(id, open.map(|_| Message::None))
} else {
let id = Id::unique();
let open: Task<Message> = get_layer_surface(SctkLayerSurfaceSettings {
id,
layer: smithay_client_toolkit::shell::wlr_layer::Layer::Top,
// keyboard_interactivity: todo!(),
pointer_interactivity: true,
anchor: Anchor::BOTTOM.union(Anchor::LEFT).union(Anchor::RIGHT),
output: IcedOutput::Active,
// namespace: todo!(),
// margin: IcedMargin {
// top: 5,
// right: 5,
// left: 5,
// bottom: 5,
// },
// size: Some((None, Some(48))),
size: Some((None, Some(PANEL_SIZE))),
exclusive_zone: PANEL_SIZE as i32,
// size_limits: todo!(),
..Default::default()
});
(id, open)
};
let (id, open) = if config.use_winit {
let (id, open) = window::open(window::Settings {
size: (1280.0, 48.0).into(),
..Default::default()
});
(id, open.map(|_| Message::None))
} else {
let id = Id::unique();
let open: Task<Message> = get_layer_surface(SctkLayerSurfaceSettings {
id,
layer: smithay_client_toolkit::shell::wlr_layer::Layer::Top,
// keyboard_interactivity: todo!(),
pointer_interactivity: true,
anchor: Anchor::BOTTOM.union(Anchor::LEFT).union(Anchor::RIGHT),
output: IcedOutput::Active,
// namespace: todo!(),
// margin: IcedMargin {
// top: 5,
// right: 5,
// left: 5,
// bottom: 5,
// },
// size: Some((None, Some(48))),
size: Some((None, Some(PANEL_SIZE))),
exclusive_zone: PANEL_SIZE as i32,
// size_limits: todo!(),
..Default::default()
});
(id, open)
};
log::info!("Window requested open {:?}", id);
let desktop_entry_cache = Rc::new(DesktopEntryCache::new());
let desktop_entry_cache = Rc::new(DesktopEntryCache::new(&config.icon_theme));
(
Self {
start_menu: StartMenu::new(desktop_entry_cache.clone()),
app_tray: AppTray::new(config.app_tray, desktop_entry_cache.clone()),
settings_tray: SettingsTray::new(),
main_window: id,
popup_window: None,
icon_theme: config.icon_theme,
},
open,
)
Expand Down Expand Up @@ -172,6 +173,7 @@ impl<'a> Panel<'a> {
let panel_items = row![
self.start_menu
.view(
&self.icon_theme,
self.popup_window
.as_ref()
.is_some_and(|(_, popup_type)| matches!(
Expand All @@ -181,7 +183,9 @@ impl<'a> Panel<'a> {
)
.map(Message::StartMenu),
self.app_tray.view().map(Message::AppTray),
self.settings_tray.view().map(Message::SettingsTray)
self.settings_tray
.view(&self.icon_theme)
.map(Message::SettingsTray)
]
.padding(Padding {
right: 16.0,
Expand Down
6 changes: 4 additions & 2 deletions src/settings_tray/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use clock::{Clock, ClockMessage};
use iced::{widget::row, Length, Task};
use status_icons::StatusIcons;

use crate::freedesktop::icons::IconTheme;

mod clock;
mod status_icons;

Expand Down Expand Up @@ -33,9 +35,9 @@ impl SettingsTray {
}
}

pub fn view(&self) -> iced::Element<SettingsTrayMessage> {
pub fn view(&self, icon_theme: &IconTheme) -> iced::Element<SettingsTrayMessage> {
iced::widget::container(row![
self.status_icons.view(),
self.status_icons.view(icon_theme),
self.clock.view().map(SettingsTrayMessage::Clock),
])
.center_y(Length::Fill)
Expand Down
9 changes: 6 additions & 3 deletions src/settings_tray/status_icons.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use crate::{components::app_icon, desktop_entry::default_icon_path};
use crate::{
components::app_icon,
freedesktop::icons::{default_icon_path, IconTheme},
};

use super::SettingsTrayMessage;

Expand All @@ -10,12 +13,12 @@ impl StatusIcons {
Self {}
}

pub fn view(&self) -> iced::Element<'static, SettingsTrayMessage> {
pub fn view(&self, icon_theme: &IconTheme) -> iced::Element<'static, SettingsTrayMessage> {
let icon_path = freedesktop_icons::lookup("network-wireless")
.with_theme("AdwaitaLegacy")
.with_cache()
.find()
.or_else(default_icon_path);
.or_else(|| default_icon_path(icon_theme));
iced::widget::row![app_icon(&icon_path.unwrap())].into()
}
}
13 changes: 10 additions & 3 deletions src/start_menu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ use iced::{
use crate::{
component_theme::{button_style, PANEL_SIZE},
components::{app_icon, app_tray_button},
desktop_entry::{start_menu_icon, DesktopEntryCache, EntryInfo},
freedesktop::{
desktop_entry::{DesktopEntryCache, EntryInfo},
icons::{start_menu_icon, IconTheme},
},
};

#[derive(Clone, Debug)]
Expand All @@ -31,8 +34,12 @@ impl<'a> StartMenu<'a> {
Self { de_cache }
}

pub fn view(&self, start_menu_opened: bool) -> iced::Element<StartMenuMessage> {
let start_menu_icon_path = start_menu_icon();
pub fn view(
&self,
icon_theme: &IconTheme,
start_menu_opened: bool,
) -> iced::Element<StartMenuMessage> {
let start_menu_icon_path = start_menu_icon(icon_theme);
iced::widget::container(
app_tray_button(start_menu_icon_path.as_deref(), start_menu_opened, 0, true)
.on_press(StartMenuMessage::MenuToggle)
Expand Down

0 comments on commit 51f6f31

Please sign in to comment.