[MIRROR] https://codeberg.org/naomi/nanel

Compare changes

Choose any two refs to compare.

+14 -29
examples/default.ron
··· 1 1 ( 2 - position: Bottom, 3 - monitor: All, 4 - theme: Dark, 5 - floating: false, 6 - modules: ( 7 - left: [ 8 - StartMenu, 9 - Workspaces, 10 - Taskbar( 11 - merge_windows: true, 12 - merge_pinned: true 13 - ), 14 - ], 15 - middle: [], 16 - right: [ 17 - SystemTray(hidden: true), 18 - QuickSettings( 19 - show_connection: true, 20 - show_volume: true, 21 - show_power: false, 22 - ), 23 - DateTime( 24 - calendar: true, 25 - upper_format: "%H:%M", // https://docs.rs/chrono/latest/chrono/format/strftime/index.html 26 - lower_format: "%d/%m/%Y", 27 - ), 28 - NotificationTray, 29 - ViewDesktop(show_on_hover: true, thin: true) 30 - ] 2 + hidden_icon_menu: true, 3 + taskbar_items: ( 4 + search: Hide, 5 + task_view: true, 6 + widgets: false, 7 + ), 8 + taskbar_behaviours: ( 9 + position: Bottom, 10 + alignment: Left, 11 + auto_hide: false, 12 + show_badges: true, 13 + all_displays: true, 14 + desktop_corner: true, 15 + hide_labels: Always, 31 16 ) 32 17 )
+56 -227
src/config.rs
··· 1 - use clap::ValueEnum; 2 - use iced::{color, theme::palette}; 3 1 use serde::Deserialize; 4 2 5 - use crate::modules::Module; 6 - 7 3 pub const BUTTON_SIZE: f32 = 40.0; 8 4 pub const BUTTON_PADDING: u16 = 6; 9 5 pub const GAP: u16 = 4; 10 6 pub const CORNER_RADIUS: u16 = 8; 11 7 12 - #[derive(Default, Deserialize, Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, ValueEnum)] 8 + #[derive(Deserialize, Debug)] 9 + pub enum SearchType { 10 + Hide, 11 + IconOnly, 12 + IconAndLabel, 13 + SearchBox, 14 + } 15 + 16 + #[derive(Deserialize, Debug)] 17 + pub struct TaskbarItems { 18 + pub search: SearchType, 19 + pub task_view: bool, 20 + pub widgets: bool, 21 + } 22 + 23 + #[derive(Deserialize, Debug)] 13 24 pub enum Position { 14 25 Top, 15 - #[default] 16 26 Bottom, 17 27 Left, 18 28 Right, 19 29 } 20 30 21 - #[derive(Default, Deserialize, Debug)] 22 - pub enum Monitor { 23 - Single(String), 24 - // Multiple(Vec<String>), 25 - #[default] 26 - All, 31 + #[derive(Deserialize, Debug)] 32 + pub enum Alignment { 33 + Left, 34 + Center, 27 35 } 28 36 29 - #[derive(Default, Deserialize, Debug)] 30 - pub struct Modules { 31 - pub left: Vec<Module>, 32 - pub middle: Vec<Module>, 33 - pub right: Vec<Module>, 37 + #[derive(Deserialize, Debug)] 38 + pub enum HideLabels { 39 + Always, 40 + WhenFull, 41 + Never, 34 42 } 35 43 36 - #[derive(Default, Deserialize, Debug)] 37 - pub struct Config { 44 + #[derive(Deserialize, Debug)] 45 + pub struct TaskbarBehaviours { 38 46 pub position: Position, 39 - pub monitor: Monitor, 40 - pub theme: Theme, 41 - pub floating: bool, 42 - pub modules: Modules, 47 + pub alignment: Alignment, 48 + pub auto_hide: bool, 49 + pub show_badges: bool, 50 + pub all_displays: bool, 51 + pub desktop_corner: bool, 52 + pub hide_labels: HideLabels, 43 53 } 44 54 45 - #[derive(Default, Deserialize, Debug, Clone, Copy)] 46 - pub enum Theme { 47 - #[default] 48 - Dark, 49 - Light, 50 - CatppuccinFrappe, 51 - CatppuccinLatte, 52 - CatppuccinMocha, 53 - CatppuccinMacchiato, 54 - Dracula, 55 - TokyoNight, 56 - TokyoNightStorm, 57 - TokyoNightLight, 58 - KanagawaWave, 59 - KanagawaDragon, 60 - KanagawaLotus, 61 - Moonfly, 62 - Nightfly, 63 - Oxocarbon, 64 - Ferra, 65 - Nord, 66 - SolarizedLight, 67 - SolarizedDark, 68 - GruvboxLight, 69 - GruvboxDark, 70 - Custom { 71 - background: i32, 72 - text_color: i32, 73 - primary: i32, 74 - success: i32, 75 - danger: i32, 76 - }, 77 - CustomAdvanced { 78 - dark: bool, 79 - text_color: i32, 80 - background: i32, 81 - background_weak: i32, 82 - background_strong: i32, 83 - primary: i32, 84 - primary_weak: i32, 85 - primary_strong: i32, 86 - secondary: i32, 87 - secondary_weak: i32, 88 - secondary_strong: i32, 89 - success: i32, 90 - success_weak: i32, 91 - success_strong: i32, 92 - danger: i32, 93 - danger_weak: i32, 94 - danger_strong: i32, 95 - }, 55 + #[derive(Deserialize, Debug)] 56 + pub struct Config { 57 + pub hidden_icon_menu: bool, 58 + pub taskbar_items: TaskbarItems, 59 + pub taskbar_behaviours: TaskbarBehaviours, 96 60 } 97 61 98 - impl Into<iced::Theme> for Theme { 99 - fn into(self) -> iced::Theme { 100 - match self { 101 - Theme::Dark => iced::Theme::Dark, 102 - Theme::Light => iced::Theme::Light, 103 - Theme::CatppuccinFrappe => iced::Theme::CatppuccinFrappe, 104 - Theme::CatppuccinLatte => iced::Theme::CatppuccinLatte, 105 - Theme::CatppuccinMocha => iced::Theme::CatppuccinMocha, 106 - Theme::CatppuccinMacchiato => iced::Theme::CatppuccinMacchiato, 107 - Theme::Dracula => iced::Theme::Dracula, 108 - Theme::Custom { 109 - background, 110 - text_color, 111 - primary, 112 - success, 113 - danger, 114 - } => iced::Theme::custom( 115 - String::from("custom-theme"), 116 - palette::Palette { 117 - background: color!(background), 118 - text: color!(text_color), 119 - primary: color!(primary), 120 - success: color!(success), 121 - danger: color!(danger), 122 - }, 123 - ), 124 - Theme::CustomAdvanced { 125 - dark, 126 - background, 127 - background_weak, 128 - background_strong, 129 - text_color, 130 - primary, 131 - primary_weak, 132 - primary_strong, 133 - secondary, 134 - secondary_weak, 135 - secondary_strong, 136 - success, 137 - success_weak, 138 - success_strong, 139 - danger, 140 - danger_weak, 141 - danger_strong, 142 - } => { 143 - let generate = |_| iced::theme::palette::Extended { 144 - background: palette::Background { 145 - base: palette::Pair { 146 - color: color!(background), 147 - text: color!(text_color), 148 - }, 149 - weak: palette::Pair { 150 - color: color!(background_weak), 151 - text: color!(text_color), 152 - }, 153 - strong: palette::Pair { 154 - color: color!(background_strong), 155 - text: color!(text_color), 156 - }, 157 - }, 158 - primary: palette::Primary { 159 - base: palette::Pair { 160 - color: color!(primary), 161 - text: color!(text_color), 162 - }, 163 - weak: palette::Pair { 164 - color: color!(primary_weak), 165 - text: color!(text_color), 166 - }, 167 - strong: palette::Pair { 168 - color: color!(primary_strong), 169 - text: color!(text_color), 170 - }, 171 - }, 172 - secondary: palette::Secondary { 173 - base: palette::Pair { 174 - color: color!(secondary), 175 - text: color!(text_color), 176 - }, 177 - weak: palette::Pair { 178 - color: color!(secondary_weak), 179 - text: color!(text_color), 180 - }, 181 - strong: palette::Pair { 182 - color: color!(secondary_strong), 183 - text: color!(text_color), 184 - }, 185 - }, 186 - success: palette::Success { 187 - base: palette::Pair { 188 - color: color!(success), 189 - text: color!(text_color), 190 - }, 191 - weak: palette::Pair { 192 - color: color!(success_weak), 193 - text: color!(text_color), 194 - }, 195 - strong: palette::Pair { 196 - color: color!(success_strong), 197 - text: color!(text_color), 198 - }, 199 - }, 200 - danger: palette::Danger { 201 - base: palette::Pair { 202 - color: color!(danger), 203 - text: color!(text_color), 204 - }, 205 - weak: palette::Pair { 206 - color: color!(danger_weak), 207 - text: color!(text_color), 208 - }, 209 - strong: palette::Pair { 210 - color: color!(danger_strong), 211 - text: color!(text_color), 212 - }, 213 - }, 214 - is_dark: dark, 215 - }; 216 - 217 - iced::Theme::custom_with_fn( 218 - String::from("custom-theme"), 219 - iced::theme::Palette { 220 - background: color!(background), 221 - text: color!(text_color), 222 - primary: color!(primary), 223 - success: color!(success), 224 - danger: color!(danger), 225 - }, 226 - generate, 227 - ) 228 - } 229 - Theme::TokyoNight => iced::Theme::TokyoNight, 230 - Theme::TokyoNightStorm => iced::Theme::TokyoNightStorm, 231 - Theme::TokyoNightLight => iced::Theme::TokyoNightLight, 232 - Theme::KanagawaWave => iced::Theme::KanagawaWave, 233 - Theme::KanagawaDragon => iced::Theme::KanagawaDragon, 234 - Theme::KanagawaLotus => iced::Theme::KanagawaLotus, 235 - Theme::Moonfly => iced::Theme::Moonfly, 236 - Theme::Nightfly => iced::Theme::Nightfly, 237 - Theme::Oxocarbon => iced::Theme::Oxocarbon, 238 - Theme::Ferra => iced::Theme::Ferra, 239 - Theme::Nord => iced::Theme::Nord, 240 - Theme::SolarizedLight => iced::Theme::SolarizedLight, 241 - Theme::SolarizedDark => iced::Theme::SolarizedDark, 242 - Theme::GruvboxLight => iced::Theme::GruvboxLight, 243 - Theme::GruvboxDark => iced::Theme::GruvboxDark, 62 + impl Default for Config { 63 + fn default() -> Self { 64 + Config { 65 + hidden_icon_menu: true, 66 + taskbar_items: TaskbarItems { 67 + search: SearchType::Hide, 68 + task_view: true, 69 + widgets: false, 70 + }, 71 + taskbar_behaviours: TaskbarBehaviours { 72 + position: Position::Bottom, 73 + alignment: Alignment::Left, 74 + auto_hide: false, 75 + show_badges: true, 76 + all_displays: true, 77 + desktop_corner: true, 78 + hide_labels: HideLabels::Always, 79 + }, 244 80 } 245 81 } 246 82 } 247 - 248 - #[derive(Deserialize, Debug)] 249 - pub enum SeperatorStyle { 250 - Solid, 251 - Dotted, 252 - Handle, 253 - }
+1 -9
src/main.rs
··· 4 4 use std::{fs, path::PathBuf}; 5 5 6 6 mod config; 7 - mod modules; 8 7 mod msg; 9 8 mod panel; 10 9 mod styles; 11 10 mod widgets; 12 - mod windows; 13 11 14 12 #[derive(Parser)] 15 13 #[command(version, about, long_about = None)] 16 14 struct NanelCli { 17 - /// Custom config file to read from 18 15 #[arg(short, long, value_name = "FILE")] 19 16 config: Option<PathBuf>, 20 - #[arg(value_enum, short, long, value_name = "FILE")] 21 - position: Option<config::Position>, 22 17 } 23 18 24 19 fn main() { ··· 28 23 29 24 if let Some(config_path) = cli.config { 30 25 let contents = fs::read_to_string(config_path).expect("Config file could not be read."); 31 - config = ron::from_str(&contents).expect("Invalid config"); 32 - } 33 26 34 - if let Some(position) = cli.position { 35 - config.position = position; 27 + config = ron::from_str(&contents).expect("Invalid config"); 36 28 } 37 29 38 30 panel_main(config).unwrap();
-247
src/modules.rs
··· 1 - use chrono::{DateTime, Datelike, Local, Timelike}; 2 - use iced::{ 3 - Alignment, Element, Length, 4 - widget::{column, row, text}, 5 - }; 6 - use iced_fonts::Bootstrap; 7 - use serde::Deserialize; 8 - 9 - use crate::{ 10 - config, 11 - msg::{Message, NanelWindowType}, 12 - panel::label, 13 - styles::{solid, transparent}, 14 - widgets::{ 15 - button_with_position::ButtonInfo, icon, small_icon, taskbar_button, taskbar_button_thin, 16 - taskbar_button_with_info, 17 - }, 18 - windows::{ 19 - calendar_menu, directory_menu, notification_menu, quick_settings_menu, start_menu, 20 - systray_menu, 21 - }, 22 - }; 23 - 24 - #[derive(Deserialize, Debug)] 25 - pub enum Module { 26 - StartMenu, 27 - Workspaces, 28 - DirectoryMenu, 29 - VerticalSeperator, 30 - Taskbar { 31 - merge_windows: bool, 32 - merge_pinned: bool, 33 - }, 34 - SystemTray { 35 - hidden: bool, 36 - }, 37 - QuickSettings { 38 - show_connection: bool, 39 - show_volume: bool, 40 - show_power: bool, 41 - }, 42 - DateTime { 43 - calendar: bool, 44 - upper_format: String, 45 - lower_format: String, 46 - }, 47 - NotificationTray, 48 - ViewDesktop { 49 - show_on_hover: bool, 50 - thin: bool, 51 - }, 52 - } 53 - 54 - pub fn get_connection<'a, Message>(show_connection: &bool) -> Option<Element<'a, Message>> { 55 - match show_connection { 56 - true => Some(small_icon(Bootstrap::Wifi).into()), 57 - false => None, 58 - } 59 - } 60 - 61 - pub fn get_volume<'a, Message>(show_volume: &bool) -> Option<Element<'a, Message>> { 62 - match show_volume { 63 - true => Some(small_icon(Bootstrap::VolumeUpFill).into()), 64 - false => None, 65 - } 66 - } 67 - 68 - pub fn get_power<'a, Message>(show_power: &bool) -> Option<Element<'a, Message>> { 69 - match show_power { 70 - true => Some(small_icon(Bootstrap::Battery).into()), 71 - false => None, 72 - } 73 - } 74 - pub fn start_menu<'a>(vertical: &bool) -> Element<'a, Message> { 75 - taskbar_button_with_info(icon(Bootstrap::Microsoft), true, vertical, transparent) 76 - .on_press_with(|info| Message::UserToggledWindow { 77 - x: info.position.x as i32, 78 - y: info.position.y as i32, 79 - viewport: (info.viewport.0 as i32, info.viewport.1 as i32), 80 - window_type: NanelWindowType::Start, 81 - container_id: start_menu::START_MENU.clone(), 82 - }) 83 - .into() 84 - } 85 - 86 - pub fn workspaces<'a>(vertical: &bool) -> Element<'a, Message> { 87 - taskbar_button(icon(Bootstrap::Stack), true, vertical, transparent) 88 - .on_press(Message::UserToggledWorkspaces) 89 - .into() 90 - } 91 - 92 - pub fn directory_menu<'a>(vertical: &bool) -> Element<'a, Message> { 93 - taskbar_button_with_info(icon(Bootstrap::FolderFill), true, vertical, transparent) 94 - .on_press_with(|info| Message::UserToggledWindow { 95 - x: info.position.x as i32, 96 - y: info.position.y as i32, 97 - viewport: (info.viewport.0 as i32, info.viewport.1 as i32), 98 - window_type: NanelWindowType::Directory, 99 - container_id: directory_menu::DIRECTORY_MENU.clone(), 100 - }) 101 - .into() 102 - } 103 - 104 - pub fn system_tray<'a>( 105 - hidden_menu: &bool, 106 - vertical: &bool, 107 - position: config::Position, 108 - ) -> Element<'a, Message> { 109 - let icon = match position { 110 - config::Position::Top => small_icon(Bootstrap::ChevronDown), 111 - config::Position::Bottom => small_icon(Bootstrap::ChevronUp), 112 - config::Position::Left => small_icon(Bootstrap::ChevronRight), 113 - config::Position::Right => small_icon(Bootstrap::ChevronLeft), 114 - }; 115 - 116 - match hidden_menu { 117 - false => text!("TODO: systray").into(), 118 - true => taskbar_button_with_info(icon, false, vertical, transparent) 119 - .on_press_with(|info| Message::UserToggledWindow { 120 - x: info.position.x as i32, 121 - y: info.position.y as i32, 122 - viewport: (info.viewport.0 as i32, info.viewport.1 as i32), 123 - window_type: NanelWindowType::SystemTray, 124 - container_id: systray_menu::SYSTRAY_MENU.clone(), 125 - }) 126 - .into(), 127 - } 128 - } 129 - 130 - pub fn notification_tray<'a>(vertical: &bool) -> Element<'a, Message> { 131 - taskbar_button_with_info(small_icon(Bootstrap::Bell), false, vertical, transparent) 132 - .on_press_with(|info| Message::UserToggledWindow { 133 - x: info.position.x as i32, 134 - y: info.position.y as i32, 135 - viewport: (info.viewport.0 as i32, info.viewport.1 as i32), 136 - window_type: NanelWindowType::Notification, 137 - container_id: notification_menu::NOTIFICATION_MENU.clone(), 138 - }) 139 - .into() 140 - } 141 - 142 - pub fn quick_settings<'a>( 143 - connection: Option<Element<'a, Message>>, 144 - volume: Option<Element<'a, Message>>, 145 - power: Option<Element<'a, Message>>, 146 - vertical: &bool, 147 - ) -> Element<'a, Message> { 148 - taskbar_button_with_info( 149 - match vertical { 150 - true => Into::<Element<Message>>::into( 151 - column![] 152 - .push_maybe(connection) 153 - .push_maybe(volume) 154 - .push_maybe(power) 155 - .spacing(6) 156 - .align_x(Alignment::Center) 157 - .width(Length::Fill), 158 - ), 159 - false => Into::<Element<Message>>::into( 160 - row![] 161 - .push_maybe(connection) 162 - .push_maybe(volume) 163 - .push_maybe(power) 164 - .spacing(6) 165 - .align_y(Alignment::Center) 166 - .height(Length::Fill), 167 - ), 168 - }, 169 - false, 170 - vertical, 171 - transparent, 172 - ) 173 - .on_press_with(|info| Message::UserToggledWindow { 174 - x: info.position.x as i32, 175 - y: info.position.y as i32, 176 - viewport: (info.viewport.0 as i32, info.viewport.1 as i32), 177 - window_type: NanelWindowType::QuickSettings, 178 - container_id: quick_settings_menu::QUICK_SETTINGS_MENU.clone(), 179 - }) 180 - .into() 181 - } 182 - 183 - pub fn date_time<'a>( 184 - datetime: DateTime<Local>, 185 - calendar: &bool, 186 - upper_format: &String, 187 - lower_format: &String, 188 - vertical: &bool, 189 - ) -> Element<'a, Message> { 190 - taskbar_button_with_info( 191 - match vertical { 192 - true => Into::<Element<Message>>::into( 193 - row![text("TODO")].clip(false).align_y(Alignment::Center), 194 - ), 195 - false => Into::<Element<Message>>::into( 196 - column![ 197 - label( 198 - (String::from(" ") 199 - + datetime.format(upper_format.as_str()).to_string().as_str() 200 - + " ") 201 - .as_str() 202 - ), 203 - label( 204 - (String::from(" ") 205 - + datetime.format(lower_format.as_str()).to_string().as_str() 206 - + " ") 207 - .as_str() 208 - ), 209 - ] 210 - .clip(false) 211 - .align_x(Alignment::Center), 212 - ), 213 - }, 214 - false, 215 - vertical, 216 - transparent, 217 - ) 218 - .on_press_with_maybe(match calendar { 219 - true => Some(|info: ButtonInfo| Message::UserToggledWindow { 220 - x: info.position.x as i32, 221 - y: info.position.y as i32, 222 - viewport: (info.viewport.0 as i32, info.viewport.1 as i32), 223 - window_type: NanelWindowType::Calendar, 224 - container_id: calendar_menu::CALENDAR_MENU.clone(), 225 - }), 226 - false => None, 227 - }) 228 - .padding(1) 229 - .into() 230 - } 231 - 232 - pub fn view_desktop<'a>(thin: &bool, vertical: &bool) -> Element<'a, Message> { 233 - match thin { 234 - true => taskbar_button_thin( 235 - text(if *vertical { "โ€”" } else { "|" }) 236 - .align_x(Alignment::Center) 237 - .align_y(Alignment::Center), 238 - vertical, 239 - transparent, 240 - ) 241 - .on_press(Message::UserToggledDesktop) 242 - .into(), 243 - false => taskbar_button(icon(Bootstrap::Display), true, vertical, solid) 244 - .on_press(Message::UserToggledDesktop) 245 - .into(), 246 - } 247 - }
+1 -21
src/msg.rs
··· 1 - use iced::{font, widget::container}; 1 + use iced::font; 2 2 use iced_layershell::to_layer_message; 3 3 4 4 #[to_layer_message(multi)] 5 5 #[derive(Clone, Debug)] 6 6 pub enum Message { 7 7 FontLoaded(Result<(), font::Error>), 8 - UserToggledWindow { 9 - x: i32, 10 - y: i32, 11 - viewport: (i32, i32), 12 - window_type: NanelWindowType, 13 - container_id: container::Id, 14 - }, 15 - UserToggledWorkspaces, 16 - UserToggledDesktop, 17 8 PanelTicked, 18 - UserClosedWindow(iced::window::Id), 19 - } 20 - 21 - #[derive(Debug, Clone, Copy, PartialEq, Eq)] 22 - pub enum NanelWindowType { 23 - Start, 24 - Directory, 25 - Notification, 26 - Calendar, 27 - SystemTray, 28 - QuickSettings, 29 9 }
+27 -279
src/panel.rs
··· 1 - use std::collections::{BTreeMap, HashMap}; 2 - 3 1 use chrono::prelude::*; 4 2 use iced::{ 5 - Alignment, Element, Font, Length, Subscription, Task, Theme, time, 6 - widget::{Text, column, container, row, text, vertical_rule}, 7 - window::Action as WindowAction, 3 + Element, Font, Length, Subscription, Task, time, 4 + widget::{column, container, row}, 8 5 }; 9 6 use iced_layershell::{ 10 - Appearance, 11 7 build_pattern::{MainSettings, daemon}, 12 - reexport::{Anchor, Layer, NewLayerShellSettings}, 8 + reexport::{Anchor, Layer}, 13 9 settings::{LayerShellSettings, StartMode}, 14 10 }; 15 - use iced_runtime::{Action, font, task}; 11 + use iced_runtime::font; 16 12 17 13 use crate::{ 18 - config::{BUTTON_SIZE, Config, GAP, Position}, 19 - modules::{ 20 - Module, date_time, directory_menu, get_connection, get_power, get_volume, 21 - notification_tray, quick_settings, start_menu, system_tray, view_desktop, workspaces, 22 - }, 23 - msg::{Message, NanelWindowType}, 24 - styles::{rounded_container, squared_container}, 25 - windows::{ 26 - calendar_menu, directory_menu, notification_menu, quick_settings_menu, start_menu, 27 - systray_menu, 28 - }, 14 + config::{Alignment, BUTTON_SIZE, Config, GAP, Position}, 15 + msg::Message, 16 + widgets::{main, right}, 29 17 }; 30 18 31 19 pub struct Nanel { 32 20 pub config: Config, 33 21 pub datetime: DateTime<Local>, 34 - pub window_ids: BTreeMap<iced::window::Id, NanelWindow>, 35 - } 36 - 37 - #[derive(Debug, Clone, Copy, PartialEq, Eq)] 38 - pub struct ParentPosition { 39 - pub panel: Position, 40 - pub x: i32, 41 - pub y: i32, 42 - } 43 - 44 - #[derive(Debug, Clone, PartialEq, Eq)] 45 - pub struct NanelWindow { 46 - pub parent_postion: ParentPosition, 47 - pub window_type: NanelWindowType, 48 - pub viewport: (i32, i32), 49 - pub container_id: container::Id, 50 - } 51 - 52 - pub fn label<'a>(string: &str) -> Text<'a> { 53 - text(String::from(string)) 54 - .font(Font::with_name("Selawik")) 55 - .align_x(Alignment::Center) 56 - .align_y(Alignment::Center) 57 22 } 58 23 59 24 impl Nanel { 60 - fn window_id(&self, info: &NanelWindow) -> Option<&iced::window::Id> { 61 - for (k, v) in self.window_ids.iter() { 62 - if info == v { 63 - return Some(k); 64 - } 65 - } 66 - None 67 - } 68 - 69 - fn construct_widget_list(&self, modules: &Vec<Module>, expand: bool) -> Element<Message> { 70 - let mut children = match expand { 71 - true => match self.is_vertical() { 72 - true => vec![column![].height(Length::Fill).into()], 73 - false => vec![row![].width(Length::Fill).into()], 74 - }, 75 - 76 - false => vec![], 77 - }; 78 - 79 - for module in modules.iter() { 80 - children.push(self.get_widget(module)); 81 - } 82 - 83 - if expand { 84 - match self.is_vertical() { 85 - true => children.push(column![].height(Length::Fill).into()), 86 - false => children.push(row![].width(Length::Fill).into()), 87 - } 88 - } 89 - 90 - match self.is_vertical() { 91 - true => Into::<Element<Message>>::into(column(children).spacing(GAP)), 92 - false => Into::<Element<Message>>::into(row(children).spacing(GAP)), 93 - } 94 - .into() 95 - } 96 - 97 25 pub fn is_vertical(&self) -> bool { 98 - match self.config.position { 26 + match self.config.taskbar_behaviours.position { 99 27 Position::Left | Position::Right => true, 100 28 Position::Top | Position::Bottom => false, 101 29 } 102 30 } 103 31 104 - fn left(&self) -> Element<Message> { 105 - self.construct_widget_list(&self.config.modules.left, false) 106 - } 107 - 108 - fn middle(&self) -> Element<Message> { 109 - self.construct_widget_list(&self.config.modules.middle, true) 110 - } 111 - 112 - fn right(&self) -> Element<Message> { 113 - self.construct_widget_list(&self.config.modules.right, false) 114 - } 115 - 116 32 fn tick_time(&self) -> Subscription<Message> { 117 33 time::every(time::Duration::from_millis(200)).map(|_x| Message::PanelTicked) 118 34 } 119 35 120 - pub fn get_widget(&self, module: &Module) -> Element<Message> { 121 - match module { 122 - Module::StartMenu => start_menu(&self.is_vertical()), 123 - Module::Workspaces => workspaces(&self.is_vertical()), 124 - Module::DirectoryMenu => directory_menu(&self.is_vertical()), 125 - Module::VerticalSeperator => vertical_rule(GAP).into(), 126 - Module::Taskbar { 127 - merge_windows: _, 128 - merge_pinned: _, 129 - } => text!("TODO: taskbar").into(), 130 - Module::SystemTray { hidden } => { 131 - system_tray(hidden, &self.is_vertical(), self.config.position) 132 - } 133 - Module::NotificationTray => notification_tray(&self.is_vertical()), 134 - Module::QuickSettings { 135 - show_connection, 136 - show_volume, 137 - show_power, 138 - } => quick_settings( 139 - get_connection(show_connection), 140 - get_volume(show_volume), 141 - get_power(show_power), 142 - &self.is_vertical(), 143 - ), 144 - Module::DateTime { 145 - calendar, 146 - upper_format, 147 - lower_format, 148 - } => date_time( 149 - self.datetime, 150 - calendar, 151 - upper_format, 152 - lower_format, 153 - &self.is_vertical(), 154 - ), 155 - Module::ViewDesktop { 156 - show_on_hover: _, 157 - thin, 158 - } => view_desktop(thin, &self.is_vertical()), 159 - } 160 - } 161 - 162 - fn id_info(&self, id: iced::window::Id) -> Option<NanelWindow> { 163 - self.window_ids.get(&id).cloned() 164 - } 165 - 166 - fn remove_id(&mut self, id: iced::window::Id) { 167 - self.window_ids.remove(&id); 36 + fn remove_id(&mut self, _id: iced::window::Id) { 37 + // self.window_ids.remove(&id); 168 38 } 169 39 170 40 fn new(flags: Config) -> (Self, Task<Message>) { ··· 172 42 Self { 173 43 config: flags, 174 44 datetime: Local::now(), 175 - window_ids: BTreeMap::new(), 176 45 }, 177 46 Task::batch(vec![ 178 47 font::load(iced_fonts::BOOTSTRAP_FONT_BYTES).map(Message::FontLoaded), ··· 184 53 Subscription::batch(vec![self.tick_time()]) 185 54 } 186 55 187 - fn open_popup(&mut self, window: NanelWindow) -> Task<Message> { 188 - let id = iced::window::Id::unique(); 189 - if let Some(_) = self.window_id(&window) { 190 - Task::none() 191 - } else { 192 - let size = (400, 400); 193 - let h_margin = if window.parent_postion.x - size.0 as i32 / 2 >= 0 { 194 - if window.parent_postion.x + size.0 as i32 / 2 > window.viewport.0 { 195 - window.viewport.0 - size.0 as i32 - 5 196 - } else { 197 - window.parent_postion.x - size.0 as i32 / 2 198 - } 199 - } else { 200 - 5 201 - }; 202 - let v_margin = if window.parent_postion.y - size.1 as i32 / 2 >= 0 { 203 - if window.parent_postion.y + size.1 as i32 / 2 > window.viewport.1 { 204 - window.viewport.1 - size.1 as i32 - 5 205 - } else { 206 - window.parent_postion.y - size.1 as i32 / 2 207 - } 208 - } else { 209 - 5 210 - }; 211 - 212 - let anchor = match window.parent_postion.panel { 213 - Position::Top => Anchor::Left | Anchor::Top, 214 - Position::Bottom => Anchor::Left | Anchor::Bottom, 215 - Position::Left => Anchor::Top | Anchor::Left, 216 - Position::Right => Anchor::Top | Anchor::Right, 217 - }; 218 - 219 - // (top, right, bottom, left) 220 - let margin = Some(match window.parent_postion.panel { 221 - Position::Top => (v_margin, 0, 0, h_margin), 222 - Position::Bottom => (0, 0, v_margin, h_margin), 223 - Position::Left => (v_margin, 0, 0, h_margin), 224 - Position::Right => (v_margin, h_margin, 0, 0), 225 - }); 226 - 227 - self.window_ids.insert(id, window); 228 - 229 - Task::done(Message::NewLayerShell { 230 - settings: NewLayerShellSettings { 231 - size: Some(size), 232 - layer: Layer::Top, 233 - anchor, 234 - exclusive_zone: None, 235 - margin, 236 - use_last_output: false, 237 - ..Default::default() 238 - }, 239 - id, 240 - }) 241 - } 242 - } 243 - 244 56 fn update(&mut self, message: Message) -> Task<Message> { 245 57 match message { 246 58 Message::FontLoaded(_) => Task::none(), 247 - Message::UserToggledWindow { 248 - x, 249 - y, 250 - viewport, 251 - window_type, 252 - container_id, 253 - } => { 254 - let window = NanelWindow { 255 - parent_postion: ParentPosition { 256 - panel: self.config.position, 257 - x, 258 - y, 259 - }, 260 - window_type, 261 - viewport, 262 - container_id, 263 - }; 264 - if let Some(id) = self.window_id(&window) { 265 - return Task::done(Message::UserClosedWindow(*id)); 266 - } 267 - self.open_popup(window) 268 - } 269 - Message::UserToggledWorkspaces => Task::none(), 270 - Message::UserToggledDesktop => Task::none(), 271 59 Message::PanelTicked => { 272 60 self.datetime = Local::now(); 273 61 Task::none() 274 62 } 275 - Message::UserClosedWindow(id) => { 276 - self.window_ids.remove(&id); 277 - task::effect(Action::Window(WindowAction::Close(id))) 278 - } 279 63 _ => unreachable!(), 280 64 } 281 65 } 282 66 283 - fn view(&self, id: iced::window::Id) -> Element<Message> { 284 - if let Some(window) = self.id_info(id) { 285 - return match window.window_type { 286 - NanelWindowType::Start => start_menu::view(id).style(rounded_container), 287 - NanelWindowType::Directory => directory_menu::view(id).style(rounded_container), 288 - NanelWindowType::Notification => { 289 - notification_menu::view(id).style(rounded_container) 290 - } 291 - NanelWindowType::Calendar => { 292 - calendar_menu::view(id, self.datetime).style(rounded_container) 293 - } 294 - NanelWindowType::SystemTray => systray_menu::view(id).style(rounded_container), 295 - NanelWindowType::QuickSettings => { 296 - quick_settings_menu::view(id).style(rounded_container) 297 - } 298 - } 299 - .into(); 300 - } 67 + fn view(&self, _id: iced::window::Id) -> Element<Message> { 68 + let children = vec![ 69 + main::view( 70 + self.is_vertical(), 71 + match self.config.taskbar_behaviours.alignment { 72 + Alignment::Left => false, 73 + Alignment::Center => true, 74 + }, 75 + self.config.taskbar_items.task_view, 76 + ), 77 + right::view(self.is_vertical()), 78 + ]; 301 79 302 - // Actual panel 303 - let children = vec![self.left(), self.middle(), self.right()]; 304 80 container(match self.is_vertical() { 305 81 true => Into::<Element<Message>>::into(column(children).spacing(GAP).padding(GAP)), 306 82 false => Into::<Element<Message>>::into(row(children).spacing(GAP).padding(GAP)), 307 83 }) 308 84 .width(Length::Fill) 309 85 .height(Length::Fill) 310 - .style(match &self.config.floating { 311 - true => rounded_container, 312 - false => squared_container, 313 - }) 314 86 .into() 315 87 } 316 88 317 89 fn namespace(&self) -> String { 318 90 String::from("nanel") 319 91 } 320 - 321 - fn theme(&self) -> Theme { 322 - self.config.theme.into() 323 - } 324 - 325 - fn style(&self, theme: &Theme) -> Appearance { 326 - Appearance { 327 - background_color: iced::Color { 328 - r: 0.0, 329 - g: 0.0, 330 - b: 0.0, 331 - a: 0.0, 332 - }, 333 - text_color: theme.palette().text, 334 - } 335 - } 336 92 } 337 93 338 94 pub fn panel_main(config: Config) -> Result<(), iced_layershell::Error> { 339 95 let panel_size = BUTTON_SIZE as u16 + (GAP * 2); 340 96 341 - let anchor = match &config.position { 97 + let anchor = match &config.taskbar_behaviours.position { 342 98 Position::Top => Anchor::Top | Anchor::Left | Anchor::Right, 343 99 Position::Bottom => Anchor::Bottom | Anchor::Left | Anchor::Right, 344 100 Position::Left => Anchor::Left | Anchor::Top | Anchor::Bottom, 345 101 Position::Right => Anchor::Right | Anchor::Top | Anchor::Bottom, 346 102 }; 347 103 348 - let size = match &config.position { 104 + let size = match &config.taskbar_behaviours.position { 349 105 Position::Top | Position::Bottom => (0, panel_size as u32), 350 106 Position::Left | Position::Right => (panel_size as u32, 0), 351 107 }; 352 108 353 - let start_mode = match &config.monitor { 354 - crate::config::Monitor::Single(target) => StartMode::TargetScreen(target.clone()), 355 - crate::config::Monitor::All => StartMode::AllScreens, 356 - }; 357 - 358 - let margin = match &config.floating { 359 - true => (GAP as i32, GAP as i32, GAP as i32, GAP as i32), 360 - false => (0, 0, 0, 0), 109 + let start_mode = match &config.taskbar_behaviours.all_displays { 110 + true => StartMode::AllScreens, 111 + false => StartMode::Active, 361 112 }; 362 113 363 114 daemon( ··· 374 125 exclusive_zone: panel_size as i32, 375 126 size: Some(size), 376 127 start_mode, 377 - margin, 378 128 ..Default::default() 379 129 }, 380 130 antialiasing: true, 381 131 default_font: Font::with_name("Selawik"), 382 132 ..Default::default() 383 133 }) 384 - .theme(Nanel::theme) 385 - .style(Nanel::style) 386 134 .run_with(|| Nanel::new(config)) 387 135 }
+16
src/widgets/icon.rs
··· 1 + use iced::{Alignment, widget::Text}; 2 + use iced_fonts::bootstrap::to_text; 3 + 4 + pub fn icon<'a>(icon: iced_fonts::Bootstrap) -> Text<'a> { 5 + to_text(icon) 6 + .size(24) 7 + .align_x(Alignment::Center) 8 + .align_y(Alignment::Center) 9 + } 10 + 11 + pub fn small_icon<'a>(icon: iced_fonts::Bootstrap) -> Text<'a> { 12 + to_text(icon) 13 + .size(18) 14 + .align_x(Alignment::Center) 15 + .align_y(Alignment::Center) 16 + }
+28
src/widgets/main.rs
··· 1 + use iced::{Renderer, Theme}; 2 + use iced_core::Element; 3 + use iced_fonts::Bootstrap; 4 + 5 + use crate::{msg::Message, styles::transparent}; 6 + 7 + use super::{MaybePush, icon::icon, taskbar_button, taskbar_section}; 8 + 9 + pub fn view<'a>( 10 + vertical: bool, 11 + centered: bool, 12 + task_view: bool, 13 + ) -> Element<'a, Message, Theme, Renderer> { 14 + taskbar_section( 15 + vec![ 16 + taskbar_button::button(icon(Bootstrap::Microsoft), true, &vertical, transparent).into(), 17 + ] 18 + .push_maybe(match task_view { 19 + true => Some( 20 + taskbar_button::button(icon(Bootstrap::Stack), true, &vertical, transparent).into(), 21 + ), 22 + false => None, 23 + }), 24 + centered, 25 + !centered, 26 + vertical, 27 + ) 28 + }
+45 -82
src/widgets/mod.rs
··· 1 1 pub mod button_with_position; 2 - use button_with_position::{ButtonWithPosition, button_with_position}; 2 + pub mod icon; 3 + pub mod main; 4 + pub mod right; 5 + pub mod taskbar_button; 3 6 use iced::{ 4 - Alignment, Element, Length, Renderer, Theme, 5 - widget::{Button, Text, button}, 7 + Element, Length, Renderer, Theme, 8 + widget::{column, row}, 6 9 }; 7 - use iced_fonts::bootstrap::to_text; 8 10 9 - use crate::{ 10 - config::{BUTTON_PADDING, BUTTON_SIZE}, 11 - msg::Message, 12 - }; 11 + use crate::msg::Message; 13 12 14 - pub fn taskbar_button_with_info<'a>( 15 - content: impl Into<Element<'a, Message, Theme, Renderer>>, 16 - equal_size: bool, 17 - vertical: &bool, 18 - style: impl Fn(&Theme, button::Status) -> button::Style + 'a, 19 - ) -> ButtonWithPosition<'a, Message> { 20 - match equal_size { 21 - true => button_with_position(content) 22 - .width(BUTTON_SIZE) 23 - .height(BUTTON_SIZE) 24 - .padding(BUTTON_PADDING) 25 - .style(style), 26 - false => match vertical { 27 - true => button_with_position(content) 28 - .width(BUTTON_SIZE) 29 - .padding(BUTTON_PADDING) 30 - .style(style), 31 - false => button_with_position(content) 32 - .height(BUTTON_SIZE) 33 - .padding(BUTTON_PADDING) 34 - .style(style), 35 - }, 36 - } 13 + pub trait MaybePush<T> { 14 + fn push_maybe(self, child: Option<T>) -> Self; 37 15 } 38 16 39 - pub fn taskbar_button<'a>( 40 - content: impl Into<Element<'a, Message, Theme, Renderer>>, 41 - equal_size: bool, 42 - vertical: &bool, 43 - style: impl Fn(&Theme, button::Status) -> button::Style + 'a, 44 - ) -> Button<'a, Message> { 45 - match equal_size { 46 - true => button(content) 47 - .width(BUTTON_SIZE) 48 - .height(BUTTON_SIZE) 49 - .padding(BUTTON_PADDING) 50 - .style(style), 51 - false => match vertical { 52 - true => button(content) 53 - .width(BUTTON_SIZE) 54 - .padding(BUTTON_PADDING) 55 - .style(style), 56 - false => button(content) 57 - .height(BUTTON_SIZE) 58 - .padding(BUTTON_PADDING) 59 - .style(style), 60 - }, 17 + impl<T> MaybePush<T> for Vec<T> { 18 + fn push_maybe(mut self, child: Option<T>) -> Self { 19 + if let Some(child) = child { 20 + self.push(child); 21 + self 22 + } else { 23 + self 24 + } 61 25 } 62 26 } 63 27 64 - pub fn taskbar_button_thin<'a>( 65 - content: impl Into<Element<'a, Message, Theme, Renderer>>, 66 - vertical: &bool, 67 - style: impl Fn(&Theme, button::Status) -> button::Style + 'a, 68 - ) -> Button<'a, Message> { 28 + fn taskbar_section<'a>( 29 + children: impl IntoIterator<Item = Element<'a, Message, Theme, Renderer>>, 30 + expand_left: bool, 31 + expand_right: bool, 32 + vertical: bool, 33 + ) -> Element<'a, Message> { 69 34 match vertical { 70 - true => button(content) 71 - .height(Length::Shrink) 72 - .width(BUTTON_SIZE) 73 - .padding(0) // Higher padding is too thick 74 - .style(style), 75 - false => button(content) 76 - .width(Length::Shrink) 77 - .height(BUTTON_SIZE) 78 - .padding(2) // Higher padding is too thick 79 - .style(style), 35 + true => column![] 36 + .push_maybe(match expand_left { 37 + true => Some(column![].height(Length::Fill)), 38 + false => None, 39 + }) 40 + .push(column(children)) 41 + .push_maybe(match expand_right { 42 + true => Some(column![].height(Length::Fill)), 43 + false => None, 44 + }) 45 + .into(), 46 + false => row![] 47 + .push_maybe(match expand_left { 48 + true => Some(row![].width(Length::Fill)), 49 + false => None, 50 + }) 51 + .push(row(children)) 52 + .push_maybe(match expand_right { 53 + true => Some(row![].width(Length::Fill)), 54 + false => None, 55 + }) 56 + .into(), 80 57 } 81 58 } 82 - 83 - pub fn icon<'a>(icon: iced_fonts::Bootstrap) -> Text<'a> { 84 - to_text(icon) 85 - .size(24) 86 - .align_x(Alignment::Center) 87 - .align_y(Alignment::Center) 88 - } 89 - 90 - pub fn small_icon<'a>(icon: iced_fonts::Bootstrap) -> Text<'a> { 91 - to_text(icon) 92 - .size(18) 93 - .align_x(Alignment::Center) 94 - .align_y(Alignment::Center) 95 - }
+10
src/widgets/right.rs
··· 1 + use iced::{Renderer, Theme, widget::text}; 2 + use iced_core::Element; 3 + 4 + use crate::msg::Message; 5 + 6 + use super::taskbar_section; 7 + 8 + pub fn view<'a>(vertical: bool) -> Element<'a, Message, Theme, Renderer> { 9 + taskbar_section(vec![text!("right").into()], true, false, vertical) 10 + }
+52
src/widgets/taskbar_button.rs
··· 1 + use iced::{Element, Length, Renderer, Theme}; 2 + 3 + use crate::{ 4 + config::{BUTTON_PADDING, BUTTON_SIZE}, 5 + msg::Message, 6 + }; 7 + 8 + use super::button_with_position::{ButtonWithPosition, button_with_position}; 9 + 10 + pub fn button<'a>( 11 + content: impl Into<Element<'a, Message, Theme, Renderer>>, 12 + equal_size: bool, 13 + vertical: &bool, 14 + style: impl Fn(&Theme, iced::widget::button::Status) -> iced::widget::button::Style + 'a, 15 + ) -> ButtonWithPosition<'a, Message> { 16 + match equal_size { 17 + true => button_with_position(content) 18 + .width(BUTTON_SIZE) 19 + .height(BUTTON_SIZE) 20 + .padding(BUTTON_PADDING) 21 + .style(style), 22 + false => match vertical { 23 + true => button_with_position(content) 24 + .width(BUTTON_SIZE) 25 + .padding(BUTTON_PADDING) 26 + .style(style), 27 + false => button_with_position(content) 28 + .height(BUTTON_SIZE) 29 + .padding(BUTTON_PADDING) 30 + .style(style), 31 + }, 32 + } 33 + } 34 + 35 + pub fn thin<'a>( 36 + content: impl Into<Element<'a, Message, Theme, Renderer>>, 37 + vertical: &bool, 38 + style: impl Fn(&Theme, iced::widget::button::Status) -> iced::widget::button::Style + 'a, 39 + ) -> iced::widget::Button<'a, Message> { 40 + match vertical { 41 + true => iced::widget::button(content) 42 + .height(Length::Shrink) 43 + .width(BUTTON_SIZE) 44 + .padding(0) // Higher padding is too thick 45 + .style(style), 46 + false => iced::widget::button(content) 47 + .width(Length::Shrink) 48 + .height(BUTTON_SIZE) 49 + .padding(2) // Higher padding is too thick 50 + .style(style), 51 + } 52 + }
-97
src/windows/calendar_menu.rs
··· 1 - use chrono::{DateTime, Datelike, Local}; 2 - use iced::{ 3 - Alignment::Center, 4 - Length, 5 - widget::{Container, button, column, container, row, text}, 6 - window, 7 - }; 8 - use iced_fonts::Bootstrap; 9 - use once_cell::sync::Lazy; 10 - 11 - use crate::{ 12 - config::{BUTTON_SIZE, GAP}, 13 - msg::Message, 14 - styles, 15 - widgets::small_icon, 16 - }; 17 - 18 - pub static CALENDAR_MENU: Lazy<container::Id> = Lazy::new(|| container::Id::new("cal_menu")); 19 - 20 - pub fn view<'a>(_window_id: window::Id, datetime: DateTime<Local>) -> Container<'a, Message> { 21 - let weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; 22 - 23 - let header = row(weekdays.iter().map(|day| { 24 - container(text(*day)) 25 - .width(Length::Fixed(BUTTON_SIZE)) 26 - .align_x(Center) 27 - .align_y(Center) 28 - .into() 29 - })); 30 - 31 - // first day of month and total days 32 - let first_day = datetime 33 - .with_day(1) 34 - .unwrap() 35 - .weekday() 36 - .num_days_from_sunday() as usize; 37 - 38 - let days_in_month = (datetime 39 - .with_day(1) 40 - .unwrap() 41 - .with_month(datetime.month() + 1) 42 - .unwrap_or(datetime.with_month(1).unwrap()) 43 - .signed_duration_since(datetime.with_day(1).unwrap()) 44 - .num_days() 45 - + 1) as usize; 46 - 47 - let grid = column((0..6).map(|r| { 48 - row((0..7).map(|col| { 49 - let day_num = r * 7 + col; 50 - let (content, style): ( 51 - String, 52 - for<'b> fn( 53 - &'b iced::Theme, 54 - iced::widget::button::Status, 55 - ) -> iced::widget::button::Style, 56 - ) = if day_num >= first_day && day_num < first_day + days_in_month { 57 - let day = day_num - first_day + 1; 58 - ( 59 - day.to_string(), 60 - match day == datetime.day() as usize { 61 - true => styles::solid, 62 - false => styles::transparent, 63 - }, 64 - ) 65 - } else { 66 - (String::new(), styles::transparent) 67 - }; 68 - 69 - button(text(content).align_x(Center).align_y(Center)) 70 - .width(Length::Fixed(BUTTON_SIZE)) 71 - .height(Length::Fixed(BUTTON_SIZE)) 72 - .style(style) 73 - .into() 74 - })) 75 - .spacing(1) 76 - .into() 77 - })) 78 - .spacing(1); 79 - 80 - container(column![ 81 - row![ 82 - text(datetime.format("%a %-e %B %Y").to_string()).size(24), 83 - button(small_icon(Bootstrap::ChevronLeft)) 84 - .style(styles::transparent) 85 - .width(Length::Shrink), 86 - button(small_icon(Bootstrap::ChevronRight)) 87 - .style(styles::transparent) 88 - .width(Length::Shrink), 89 - ], 90 - header, 91 - grid 92 - ]) 93 - .width(Length::Shrink) 94 - .width(Length::Shrink) 95 - .padding(GAP) 96 - .id(CALENDAR_MENU.clone()) 97 - }
-15
src/windows/directory_menu.rs
··· 1 - use iced::{ 2 - widget::{Container, button, container}, 3 - window, 4 - }; 5 - use once_cell::sync::Lazy; 6 - 7 - use crate::{config::GAP, msg::Message}; 8 - 9 - pub static DIRECTORY_MENU: Lazy<container::Id> = Lazy::new(|| container::Id::new("dir_menu")); 10 - 11 - pub fn view<'a>(window_id: window::Id) -> Container<'a, Message> { 12 - container(button("Close Directory").on_press(Message::UserClosedWindow(window_id))) 13 - .padding(GAP) 14 - .id(DIRECTORY_MENU.clone()) 15 - }
-6
src/windows/mod.rs
··· 1 - pub mod calendar_menu; 2 - pub mod directory_menu; 3 - pub mod notification_menu; 4 - pub mod quick_settings_menu; 5 - pub mod start_menu; 6 - pub mod systray_menu;
-15
src/windows/notification_menu.rs
··· 1 - use iced::{ 2 - widget::{Container, button, container}, 3 - window, 4 - }; 5 - use once_cell::sync::Lazy; 6 - 7 - use crate::{config::GAP, msg::Message}; 8 - 9 - pub static NOTIFICATION_MENU: Lazy<container::Id> = Lazy::new(|| container::Id::new("notif_menu")); 10 - 11 - pub fn view<'a>(window_id: window::Id) -> Container<'a, Message> { 12 - container(button("Close Notification").on_press(Message::UserClosedWindow(window_id))) 13 - .padding(GAP) 14 - .id(NOTIFICATION_MENU.clone()) 15 - }
-16
src/windows/quick_settings_menu.rs
··· 1 - use iced::{ 2 - widget::{Container, button, container}, 3 - window, 4 - }; 5 - use once_cell::sync::Lazy; 6 - 7 - use crate::{config::GAP, msg::Message}; 8 - 9 - pub static QUICK_SETTINGS_MENU: Lazy<container::Id> = 10 - Lazy::new(|| container::Id::new("quick_menu")); 11 - 12 - pub fn view<'a>(window_id: window::Id) -> Container<'a, Message> { 13 - container(button("Close QuickSettings").on_press(Message::UserClosedWindow(window_id))) 14 - .padding(GAP) 15 - .id(QUICK_SETTINGS_MENU.clone()) 16 - }
-15
src/windows/start_menu.rs
··· 1 - use iced::{ 2 - widget::{Container, button, container}, 3 - window, 4 - }; 5 - use once_cell::sync::Lazy; 6 - 7 - use crate::{config::GAP, msg::Message}; 8 - 9 - pub static START_MENU: Lazy<container::Id> = Lazy::new(|| container::Id::new("start_menu")); 10 - 11 - pub fn view<'a>(window_id: window::Id) -> Container<'a, Message> { 12 - container(button("Close Start").on_press(Message::UserClosedWindow(window_id))) 13 - .padding(GAP) 14 - .id(START_MENU.clone()) 15 - }
-15
src/windows/systray_menu.rs
··· 1 - use iced::{ 2 - widget::{Container, button, container}, 3 - window, 4 - }; 5 - use once_cell::sync::Lazy; 6 - 7 - use crate::{config::GAP, msg::Message}; 8 - 9 - pub static SYSTRAY_MENU: Lazy<container::Id> = Lazy::new(|| container::Id::new("sys_menu")); 10 - 11 - pub fn view<'a>(window_id: window::Id) -> Container<'a, Message> { 12 - container(button("Close Systray").on_press(Message::UserClosedWindow(window_id))) 13 - .padding(GAP) 14 - .id(SYSTRAY_MENU.clone()) 15 - }