diff --git a/examples/cosmic/src/main.rs b/examples/cosmic/src/main.rs index 87b7ef2b..46ff5844 100644 --- a/examples/cosmic/src/main.rs +++ b/examples/cosmic/src/main.rs @@ -7,6 +7,6 @@ pub fn main() -> cosmic::iced::Result { let mut settings = settings(); settings.window.min_size = Some((600, 300)); // TODO: Window resize handles not functioning yet - // settings.window.decorations = false; + settings.window.decorations = false; Window::run(settings) } diff --git a/examples/cosmic/src/window.rs b/examples/cosmic/src/window.rs index 5b40ef40..26c758c5 100644 --- a/examples/cosmic/src/window.rs +++ b/examples/cosmic/src/window.rs @@ -1,4 +1,4 @@ -use cosmic::widget::{expander, expander_row, list_section_style, ListBox}; +use cosmic::widget::{expander, ListBox}; use cosmic::{ iced::widget::{ checkbox, column, container, horizontal_space, pick_list, progress_bar, radio, row, slider, @@ -7,11 +7,8 @@ use cosmic::{ iced::{self, theme, Alignment, Application, Color, Command, Element, Length, Theme}, iced_lazy::responsive, iced_winit::window::{drag, maximize, minimize}, - scrollable, - widget::{ - button, header_bar, list_item, list_row, list_section, list_view, nav_bar_style, - nav_button, toggler, - }, + list_item, list_row, list_section, list_view, nav_button, scrollable, + widget::{button, header_bar, list_row, list_view::*, nav_bar::nav_bar_style, toggler}, }; #[derive(Default)] @@ -77,6 +74,7 @@ impl Application for Window { .show_maximize(true) .show_minimize(true); window.slider_value = 50.0; + // window.theme = Theme::Light; window.pick_list_selected = Some("Option 1"); (window, Command::none()) } @@ -109,6 +107,7 @@ impl Application for Window { fn view(&self) -> Element { let mut header: Element = header_bar() .title(self.title()) + .nav_title(String::from("Settings")) .sidebar_active(self.sidebar_toggled) .show_minimize(self.show_minimize) .show_maximize(self.show_maximize) @@ -240,12 +239,12 @@ impl Application for Window { .icon(String::from("edit-paste")) .on_row_selected(Box::new(Message::RowSelected)) .rows(vec![ - expander_row() + list_row() .title("Label") .subtitle("Caption") .icon(String::from("help-about")), - expander_row().subtitle("Caption").title("Label"), - expander_row().title("Label") + list_row().subtitle("Caption").title("Label"), + list_row().title("Label") ]) ), list_section!( diff --git a/examples/text/src/buffer.rs b/examples/text/src/buffer.rs index 97d6c11c..9cdaa862 100644 --- a/examples/text/src/buffer.rs +++ b/examples/text/src/buffer.rs @@ -58,7 +58,7 @@ impl<'a> TextBuffer<'a> { let mut reshaped = 0; while self.shape_lines.len() < self.text_lines.len() - && (self.layout_lines.len() as i32) < lines + && (self.layout_lines.len() as i32) < lines { let line_i = FontLineIndex::new(self.shape_lines.len()); self.reshape_line(line_i); @@ -74,7 +74,9 @@ impl<'a> TextBuffer<'a> { pub fn reshape_line(&mut self, line_i: FontLineIndex) { let instant = Instant::now(); - let shape_line = self.font_matches.shape_line(line_i, &self.text_lines[line_i.get()]); + let shape_line = self + .font_matches + .shape_line(line_i, &self.text_lines[line_i.get()]); if line_i.get() < self.shape_lines.len() { self.shape_lines[line_i.get()] = shape_line; } else { @@ -131,7 +133,7 @@ impl<'a> TextBuffer<'a> { self.font_size, self.line_width, &mut self.layout_lines, - insert_i + insert_i, ); self.redraw = true; diff --git a/examples/text/src/font/layout.rs b/examples/text/src/font/layout.rs index 2ad4462a..3fc92a22 100644 --- a/examples/text/src/font/layout.rs +++ b/examples/text/src/font/layout.rs @@ -66,7 +66,8 @@ impl<'a> FontLayoutLine<'a> { // Compute the fractional offset-- you'll likely want to quantize this // in a real renderer - let offset = Vector::new(cache_key.x_bin.as_float(), cache_key.y_bin.as_float()); + let offset = + Vector::new(cache_key.x_bin.as_float(), cache_key.y_bin.as_float()); // Select our source order Render::new(&[ @@ -77,12 +78,12 @@ impl<'a> FontLayoutLine<'a> { // Standard scalable outline Source::Outline, ]) - // Select a subpixel format - .format(Format::Alpha) - // Apply the fractional offset - .offset(offset) - // Render the image - .render(&mut scaler, cache_key.glyph_id) + // Select a subpixel format + .format(Format::Alpha) + // Apply the fractional offset + .offset(offset) + // Render the image + .render(&mut scaler, cache_key.glyph_id) }); if let Some(ref image) = image_opt { @@ -96,28 +97,25 @@ impl<'a> FontLayoutLine<'a> { let mut i = 0; for off_y in 0..image.placement.height as i32 { for off_x in 0..image.placement.width as i32 { - let color = - (image.data[i] as u32) << 24 | - base & 0xFFFFFF; + let color = (image.data[i] as u32) << 24 | base & 0xFFFFFF; f(x + off_x, y + off_y, color); i += 1; } } - }, + } Content::Color => { let mut i = 0; for off_y in 0..image.placement.height as i32 { for off_x in 0..image.placement.width as i32 { - let color = - (image.data[i + 3] as u32) << 24 | - (image.data[i] as u32) << 16 | - (image.data[i + 1] as u32) << 8 | - (image.data[i + 2] as u32); + let color = (image.data[i + 3] as u32) << 24 + | (image.data[i] as u32) << 16 + | (image.data[i + 1] as u32) << 8 + | (image.data[i + 2] as u32); f(x + off_x, y + off_y, color); i += 4; } } - }, + } Content::SubpixelMask => { println!("TODO: SubpixelMask"); } diff --git a/examples/text/src/font/matches.rs b/examples/text/src/font/matches.rs index 028cacb0..1cb1664c 100644 --- a/examples/text/src/font/matches.rs +++ b/examples/text/src/font/matches.rs @@ -5,7 +5,15 @@ pub struct FontMatches<'a> { } impl<'a> FontMatches<'a> { - fn shape_fallback(&self, font_i: usize, line: &str, start_word: usize, end_word: usize, span_rtl: bool, blank: bool) -> (Vec, Vec) { + fn shape_fallback( + &self, + font_i: usize, + line: &str, + start_word: usize, + end_word: usize, + span_rtl: bool, + blank: bool, + ) -> (Vec, Vec) { let word = &line[start_word..end_word]; let font_scale = self.fonts[font_i].rustybuzz.units_per_em() as f32; @@ -101,15 +109,24 @@ impl<'a> FontMatches<'a> { (glyphs, missing) } - fn shape_word(&self, line: &str, start_word: usize, end_word: usize, span_rtl: bool, blank: bool) -> FontShapeWord { + fn shape_word( + &self, + line: &str, + start_word: usize, + end_word: usize, + span_rtl: bool, + blank: bool, + ) -> FontShapeWord { let mut font_i = 0; - let (mut glyphs, mut missing) = self.shape_fallback(font_i, line, start_word, end_word, span_rtl, blank); + let (mut glyphs, mut missing) = + self.shape_fallback(font_i, line, start_word, end_word, span_rtl, blank); //TODO: improve performance! font_i += 1; while !missing.is_empty() && font_i < self.fonts.len() { // println!("Evaluating fallback with font {}", font_i); - let (mut fb_glyphs, fb_missing) = self.shape_fallback(font_i, line, start_word, end_word, span_rtl, blank); + let (mut fb_glyphs, fb_missing) = + self.shape_fallback(font_i, line, start_word, end_word, span_rtl, blank); // Insert all matching glyphs let mut fb_i = 0; @@ -187,7 +204,11 @@ impl<'a> FontMatches<'a> { ) -> FontShapeSpan { let span = &line[start_span..end_span]; - log::debug!(" Span {}: '{}'", if span_rtl { "RTL" } else { "LTR" }, span); + log::debug!( + " Span {}: '{}'", + if span_rtl { "RTL" } else { "LTR" }, + span + ); let mut words = Vec::new(); @@ -202,10 +223,22 @@ impl<'a> FontMatches<'a> { } } if start_word < start_lb { - words.push(self.shape_word(line, start_span + start_word, start_span + start_lb, span_rtl, false)); + words.push(self.shape_word( + line, + start_span + start_word, + start_span + start_lb, + span_rtl, + false, + )); } if start_lb < end_lb { - words.push(self.shape_word(line, start_span + start_lb, start_span + end_lb, span_rtl, true)); + words.push(self.shape_word( + line, + start_span + start_lb, + start_span + end_lb, + span_rtl, + true, + )); } start_word = end_lb; } diff --git a/examples/text/src/font/mod.rs b/examples/text/src/font/mod.rs index c8dfaeae..a15f2f36 100644 --- a/examples/text/src/font/mod.rs +++ b/examples/text/src/font/mod.rs @@ -1,7 +1,4 @@ -use std::{ - collections::HashMap, - sync::Mutex, -}; +use std::{collections::HashMap, sync::Mutex}; pub use self::cache::*; mod cache; @@ -21,7 +18,6 @@ mod system; #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] pub struct FontCacheKey { glyph_id: u16, - } #[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd)] diff --git a/examples/text/src/font/shape.rs b/examples/text/src/font/shape.rs index f7448920..5ce8cd4d 100644 --- a/examples/text/src/font/shape.rs +++ b/examples/text/src/font/shape.rs @@ -26,27 +26,24 @@ impl<'a> FontShapeGlyph<'a> { let x_advance = font_size as f32 * self.x_advance; #[cfg(feature = "ab_glyph")] - let inner = self.font.ab_glyph.outline_glyph( - self.inner.with_scale_and_position( + let inner = self + .font + .ab_glyph + .outline_glyph(self.inner.with_scale_and_position( font_size as f32, - ab_glyph::point( - x + x_offset, - y - y_offset, - ) - ) - ); + ab_glyph::point(x + x_offset, y - y_offset), + )); #[cfg(feature = "rusttype")] - let inner = self.font.rusttype.glyph(self.inner) + let inner = self + .font + .rusttype + .glyph(self.inner) .scaled(rusttype::Scale::uniform(font_size as f32)) .positioned(rusttype::point(x + x_offset, y - y_offset)); #[cfg(feature = "swash")] - let inner = CacheKey::new( - self.inner, - font_size, - (x + x_offset, y - y_offset), - ); + let inner = CacheKey::new(self.inner, font_size, (x + x_offset, y - y_offset)); FontLayoutGlyph { start: self.start, diff --git a/examples/text/src/font/system.rs b/examples/text/src/font/system.rs index 98044e47..527c9db4 100644 --- a/examples/text/src/font/system.rs +++ b/examples/text/src/font/system.rs @@ -30,31 +30,28 @@ impl FontSystem { } } - Self { - db, - } + Self { db } } - pub fn matches<'a, F: Fn(&fontdb::FaceInfo) -> bool>(&'a self, f: F) -> Option> { + pub fn matches<'a, F: Fn(&fontdb::FaceInfo) -> bool>( + &'a self, + f: F, + ) -> Option> { let mut fonts = Vec::new(); for face in self.db.faces() { - if ! f(face) { + if !f(face) { continue; } let font_opt = Font::new( &face.post_script_name, match &face.source { - fontdb::Source::Binary(data) => { - data.deref().as_ref() - }, + fontdb::Source::Binary(data) => data.deref().as_ref(), fontdb::Source::File(path) => { println!("Unsupported fontdb Source::File('{}')", path.display()); continue; - }, - fontdb::Source::SharedFile(_path, data) => { - data.deref().as_ref() - }, + } + fontdb::Source::SharedFile(_path, data) => data.deref().as_ref(), }, face.index, ); @@ -67,10 +64,8 @@ impl FontSystem { } } - if ! fonts.is_empty() { - Some(FontMatches { - fonts - }) + if !fonts.is_empty() { + Some(FontMatches { fonts }) } else { None } diff --git a/examples/text/src/main.rs b/examples/text/src/main.rs index b73cb1e2..1bec4b77 100644 --- a/examples/text/src/main.rs +++ b/examples/text/src/main.rs @@ -1,17 +1,6 @@ use orbclient::{Color, EventOption, Renderer, Window, WindowFlag}; -use std::{ - cmp, - env, - fs, - time::Instant, -}; -use text::{ - FontLineIndex, - FontSystem, - TextAction, - TextCursor, - TextBuffer, -}; +use std::{cmp, env, fs, time::Instant}; +use text::{FontLineIndex, FontSystem, TextAction, TextBuffer, TextCursor}; fn main() { let display_scale = match orbclient::get_display_size() { @@ -112,10 +101,13 @@ fn main() { buffer.shape_until(scroll + window_lines); - scroll = cmp::max(0, cmp::min( - buffer.layout_lines().len() as i32 - (window_lines - 1), - scroll - )); + scroll = cmp::max( + 0, + cmp::min( + buffer.layout_lines().len() as i32 - (window_lines - 1), + scroll, + ), + ); if rehit { let instant = Instant::now(); @@ -173,7 +165,12 @@ fn main() { let mut line_y = line_height; let mut start_line_opt = None; let mut end_line = FontLineIndex::new(0); - for (line_i, line) in buffer.layout_lines().iter().skip(scroll as usize).enumerate() { + for (line_i, line) in buffer + .layout_lines() + .iter() + .skip(scroll as usize) + .enumerate() + { if line_y >= window.height() as i32 { break; } @@ -236,7 +233,7 @@ fn main() { start_y as i32, line_x as u32, (end_y - start_y) as u32, - Color::rgba(0xFF, 0xFF, 0xFF, 0x40) + Color::rgba(0xFF, 0xFF, 0xFF, 0x40), ); } } @@ -251,39 +248,39 @@ fn main() { for event in window.events() { match event.to_option() { - EventOption::Key(event) => { - match event.scancode { - orbclient::K_CTRL => ctrl_pressed = event.pressed, - orbclient::K_LEFT if event.pressed => buffer.action(TextAction::Left), - orbclient::K_RIGHT if event.pressed => buffer.action(TextAction::Right), - orbclient::K_UP if event.pressed => buffer.action(TextAction::Up), - orbclient::K_DOWN if event.pressed => buffer.action(TextAction::Down), - orbclient::K_BKSP if event.pressed => buffer.action(TextAction::Backspace), - orbclient::K_DEL if event.pressed => buffer.action(TextAction::Delete), - orbclient::K_PGUP if event.pressed => { - scroll -= window_lines; - buffer.redraw = true; - }, - orbclient::K_PGDN if event.pressed => { - scroll += window_lines; - buffer.redraw = true; - }, - orbclient::K_0 if event.pressed && ctrl_pressed => { - font_size_i = font_size_default; - buffer.set_font_size(font_sizes[font_size_i].0 * display_scale); - }, - orbclient::K_MINUS if event.pressed && ctrl_pressed => if font_size_i > 0 { + EventOption::Key(event) => match event.scancode { + orbclient::K_CTRL => ctrl_pressed = event.pressed, + orbclient::K_LEFT if event.pressed => buffer.action(TextAction::Left), + orbclient::K_RIGHT if event.pressed => buffer.action(TextAction::Right), + orbclient::K_UP if event.pressed => buffer.action(TextAction::Up), + orbclient::K_DOWN if event.pressed => buffer.action(TextAction::Down), + orbclient::K_BKSP if event.pressed => buffer.action(TextAction::Backspace), + orbclient::K_DEL if event.pressed => buffer.action(TextAction::Delete), + orbclient::K_PGUP if event.pressed => { + scroll -= window_lines; + buffer.redraw = true; + } + orbclient::K_PGDN if event.pressed => { + scroll += window_lines; + buffer.redraw = true; + } + orbclient::K_0 if event.pressed && ctrl_pressed => { + font_size_i = font_size_default; + buffer.set_font_size(font_sizes[font_size_i].0 * display_scale); + } + orbclient::K_MINUS if event.pressed && ctrl_pressed => { + if font_size_i > 0 { font_size_i -= 1; buffer.set_font_size(font_sizes[font_size_i].0 * display_scale); } - orbclient::K_EQUALS if event.pressed && ctrl_pressed => { - if font_size_i + 1 < font_sizes.len() { - font_size_i += 1; - buffer.set_font_size(font_sizes[font_size_i].0 * display_scale); - } - } - _ => (), } + orbclient::K_EQUALS if event.pressed && ctrl_pressed => { + if font_size_i + 1 < font_sizes.len() { + font_size_i += 1; + buffer.set_font_size(font_sizes[font_size_i].0 * display_scale); + } + } + _ => (), }, EventOption::TextInput(event) if !ctrl_pressed => { buffer.action(TextAction::Insert(event.character)); diff --git a/settings/Cargo.toml b/settings/Cargo.toml deleted file mode 100644 index 73889c24..00000000 --- a/settings/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "settings" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] diff --git a/settings/src/main.rs b/settings/src/main.rs deleted file mode 100644 index e7a11a96..00000000 --- a/settings/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/src/widget/expander.rs b/src/widget/expander.rs index 32193121..d200aad0 100644 --- a/src/widget/expander.rs +++ b/src/widget/expander.rs @@ -1,6 +1,6 @@ use std::vec; -use crate::list_box_row; +use crate::{list_box_row, widget::ListRow}; use apply::Apply; use derive_setters::Setters; use iced::{ @@ -20,7 +20,7 @@ pub struct Expander<'a, Message> { icon: Option, expansible: bool, #[setters(skip)] - rows: Option>>, + rows: Option>>, #[setters(strip_option)] on_row_selected: Option Message + 'a>>, } @@ -36,23 +36,6 @@ pub fn expander<'a, Message>() -> Expander<'a, Message> { } } -#[derive(Setters, Default, Debug, Clone)] -pub struct ExpanderRow<'a> { - pub(crate) title: &'a str, - #[setters(strip_option)] - pub subtitle: Option<&'a str>, - #[setters(strip_option)] - pub icon: Option, -} - -pub fn expander_row<'a>() -> ExpanderRow<'a> { - ExpanderRow { - title: "", - subtitle: None, - icon: None, - } -} - pub struct ExpanderState { pub expanded: bool, } @@ -70,13 +53,13 @@ pub enum ExpanderEvent { } impl<'a, Message> Expander<'a, Message> { - pub fn rows(mut self, rows: Vec>) -> Self { + pub fn rows(mut self, rows: Vec>) -> Self { self.rows = Some(rows); self.expansible = true; self } - pub fn push(&mut self, row: ExpanderRow<'a>) { + pub fn push(&mut self, row: ListRow<'a>) { if self.rows.is_none() { self.rows = Some(vec![]) } diff --git a/src/widget/list.rs b/src/widget/list.rs deleted file mode 100644 index 7977f6db..00000000 --- a/src/widget/list.rs +++ /dev/null @@ -1,84 +0,0 @@ -use iced::{widget, Background, Color, Theme}; - -#[macro_export] -macro_rules! list_item { - ($title:expr, $($x:expr),+ $(,)?) => ( - $crate::widget::list_row!( - $crate::iced::widget::Text::new($title), - $crate::iced::widget::horizontal_space( - $crate::iced::Length::Fill - ), - $($x),+ - ) - ); -} -pub use list_item; - -#[macro_export] -macro_rules! list_row { - ($($x:expr),+ $(,)?) => ( - $crate::iced::widget::Row::with_children(vec![ - $($crate::iced::Element::from($x)),+ - ]) - .align_items(Alignment::Center) - .padding([0, 8]) - .spacing(12) - ); -} -pub use list_row; - -#[macro_export] -macro_rules! list_section { - ($title:expr, $($x:expr),+ $(,)?) => ( - $crate::iced::widget::Column::with_children(vec![ - $crate::iced::widget::Text::new($title) - .font($crate::font::FONT_SEMIBOLD) - .into() - , - $crate::iced::widget::Container::new({ - let mut children = vec![$($crate::iced::Element::from($x)),+]; - - //TODO: more efficient method for adding separators - let mut i = 1; - while i < children.len() { - children.insert(i, $crate::iced::widget::horizontal_rule(12).into()); - i += 2; - } - - $crate::iced::widget::Column::with_children(children) - .spacing(12) - }) - .padding([12, 16]) - .style(theme::Container::Custom( - $crate::widget::list_section_style - )) - .into() - ]) - .spacing(8) - ); -} -pub use list_section; - -pub fn list_section_style(theme: &Theme) -> widget::container::Appearance { - let cosmic = &theme.cosmic().primary; - widget::container::Appearance { - text_color: Some(cosmic.on.into()), - background: Some(Background::Color(cosmic.base.into())), - border_radius: 8.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - } -} - -#[macro_export] -macro_rules! list_view { - ($($x:expr),+ $(,)?) => ( - $crate::iced::widget::Column::with_children( - vec![$($crate::iced::Element::from($x)),+] - ) - .spacing(24) - .padding(24) - .max_width(600) - ); -} -pub use list_view; diff --git a/src/widget/list_box.rs b/src/widget/list/list_box.rs similarity index 76% rename from src/widget/list_box.rs rename to src/widget/list/list_box.rs index cf20d25c..a0a52902 100644 --- a/src/widget/list_box.rs +++ b/src/widget/list/list_box.rs @@ -7,17 +7,19 @@ use iced_native::layout::{Limits, Node}; use iced_native::overlay::from_children; use iced_native::renderer::Style; use iced_native::widget::{column, horizontal_rule, Operation, Tree}; -use iced_native::{row, Clipboard, Element, Event, Layout, Shell, Widget, renderer, Background, Color}; +use iced_native::{ + renderer, row, Background, Clipboard, Color, Element, Event, Layout, Shell, Widget, +}; use iced_style::container::{Appearance, StyleSheet}; use iced_style::theme; use iced_style::theme::Container; #[derive(Setters)] pub struct ListBox<'a, Message, Renderer> - where - Renderer: iced_native::Renderer, - Renderer::Theme: StyleSheet + iced_style::rule::StyleSheet, - ::Theme: iced_style::rule::StyleSheet +where + Renderer: iced_native::Renderer, + Renderer::Theme: StyleSheet + iced_style::rule::StyleSheet, + ::Theme: iced_style::rule::StyleSheet, { spacing: u16, padding: Padding, @@ -32,11 +34,23 @@ pub struct ListBox<'a, Message, Renderer> on_item_selected: Option Message + 'a>>, } +pub fn list_box<'a, Message: 'a, Renderer>() -> ListBox<'a, Message, Renderer> +where + Renderer: iced_native::Renderer + 'a, + <::Theme as StyleSheet>::Style: From, + ::Theme: StyleSheet + iced_style::rule::StyleSheet, + <::Theme as iced_style::rule::StyleSheet>::Style: + From, +{ + ListBox::new() +} + impl<'a, Message: 'a, Renderer: iced_native::Renderer + 'a> ListBox<'a, Message, Renderer> where Renderer::Theme: StyleSheet + iced_style::rule::StyleSheet, <::Theme as StyleSheet>::Style: From, - <::Theme as iced_style::rule::StyleSheet>::Style: From + <::Theme as iced_style::rule::StyleSheet>::Style: + From, { /// The default padding of a [`ListBox`] drawn by this renderer. pub const DEFAULT_PADDING: u16 = 0; @@ -53,24 +67,20 @@ where children: Vec>, show_separators: bool, ) -> Self { - let end = children.len() - 1; + let children_size = children.len(); let children: Vec> = children .into_iter() .enumerate() .map(|(index, child)| { - let row_items = if show_separators && index != end { + let row_items = if show_separators && index != children_size - 1 { vec![ - row![child] - .align_items(Alignment::Center) + row![child].align_items(Alignment::Center).into(), + horizontal_rule(1) + .style(theme::Rule::Custom(separator_style)) .into(), - horizontal_rule(1).style(theme::Rule::Custom(separator_style)).into(), ] } else { - vec![ - row![child] - .align_items(Alignment::Center) - .into() - ] + vec![row![child].align_items(Alignment::Center).into()] }; column(row_items).into() }) @@ -101,7 +111,8 @@ impl<'a, Message: 'a, Renderer: iced_native::Renderer + 'a> std::default::Defaul where Renderer::Theme: StyleSheet + iced_style::rule::StyleSheet, <::Theme as StyleSheet>::Style: From, - <::Theme as iced_style::rule::StyleSheet>::Style: From + <::Theme as iced_style::rule::StyleSheet>::Style: + From, { fn default() -> Self { Self::new() @@ -111,7 +122,7 @@ where impl<'a, Message, Renderer> Widget for ListBox<'a, Message, Renderer> where Renderer: iced_native::Renderer, - ::Theme: StyleSheet + iced_style::rule::StyleSheet + ::Theme: StyleSheet + iced_style::rule::StyleSheet, { fn width(&self) -> Length { self.width @@ -354,7 +365,8 @@ pub fn draw_background( impl<'a, Message: 'a, Renderer: iced_native::Renderer + 'a> From> for Element<'a, Message, Renderer> - where ::Theme: StyleSheet + iced_style::rule::StyleSheet +where + ::Theme: StyleSheet + iced_style::rule::StyleSheet, { fn from(list_box: ListBox<'a, Message, Renderer>) -> Self { Self::new(list_box) @@ -375,7 +387,7 @@ pub use list_box_item; #[macro_export] macro_rules! list_box_heading { - ($title:expr) => ( + ($title:expr) => { $crate::iced::widget::container( $crate::iced::widget::row![ text($title).size(18), @@ -383,106 +395,54 @@ macro_rules! list_box_heading { $crate::iced::widget::horizontal_space(Length::Fill) ] .height(Length::Fill) - .align_items($crate::iced::alignment::Alignment::Center) + .align_items($crate::iced::alignment::Alignment::Center), ) - .style($crate::iced::theme::Container::Custom($crate::widget::expander_heading_style)) + .style($crate::iced::theme::Container::Custom( + $crate::widget::expander_heading_style, + )) .max_height(60) .padding(10) - ); - ($title:expr, $subtitle:expr) => ( + }; + ($title:expr, $subtitle:expr) => { $crate::iced::widget::container( $crate::iced::widget::row![ - column( - vec![ - text($title).size(18).into(), - text($subtitle).size(16).into(), - ] - ), + column(vec![ + text($title).size(18).into(), + text($subtitle).size(16).into(), + ]), $crate::iced::widget::vertical_space(Length::Fill), $crate::iced::widget::horizontal_space(Length::Fill) ] .height(Length::Fill) - .align_items($crate::iced::alignment::Alignment::Center) + .align_items($crate::iced::alignment::Alignment::Center), ) - .style($crate::iced::theme::Container::Custom($crate::widget::expander_heading_style)) + .style($crate::iced::theme::Container::Custom( + $crate::widget::expander_heading_style, + )) .max_height(60) .padding(10) - ); - ($title:expr, $subtitle:expr, $icon:expr) => ( + }; + ($title:expr, $subtitle:expr, $icon:expr) => { $crate::iced::widget::container( $crate::iced::widget::row![ container($crate::widget::icon($icon, 20)).padding(10), - column( - vec![ - text($title).size(18).into(), - text($subtitle).size(16).into(), - ] - ), + column(vec![ + text($title).size(18).into(), + text($subtitle).size(16).into(), + ]), $crate::iced::widget::vertical_space(Length::Fill), $crate::iced::widget::horizontal_space(Length::Fill) ] .height(Length::Fill) - .align_items($crate::iced::alignment::Alignment::Center) + .align_items($crate::iced::alignment::Alignment::Center), ) - .style($crate::iced::theme::Container::Custom($crate::widget::expander_heading_style)) + .style($crate::iced::theme::Container::Custom( + $crate::widget::expander_heading_style, + )) .max_height(60) .padding(10) - ); + }; } pub use list_box_heading; -#[macro_export] -macro_rules! list_box_row { - ($title:expr) => ( - $crate::iced::widget::container( - $crate::iced::widget::row![ - text($title).size(18), - $crate::iced::widget::vertical_space(Length::Fill), - $crate::iced::widget::horizontal_space(Length::Fill) - ] - .height(Length::Fill) - .align_items($crate::iced::alignment::Alignment::Center) - ) - .max_height(60) - .padding(10) - ); - ($title:expr, $subtitle:expr) => ( - $crate::iced::widget::container( - $crate::iced::widget::row![ - column( - vec![ - text($title).size(18).into(), - text($subtitle).size(16).into(), - ] - ), - $crate::iced::widget::vertical_space(Length::Fill), - $crate::iced::widget::horizontal_space(Length::Fill) - ] - .height(Length::Fill) - .align_items($crate::iced::alignment::Alignment::Center) - ) - .max_height(60) - .padding(10) - ); - ($title:expr, $subtitle:expr, $icon:expr) => ( - $crate::iced::widget::container( - $crate::iced::widget::row![ - container($crate::widget::icon($icon, 20)).padding(10), - column( - vec![ - text($title).size(18).into(), - text($subtitle).size(16).into(), - ] - ), - $crate::iced::widget::vertical_space(Length::Fill), - $crate::iced::widget::horizontal_space(Length::Fill) - ] - .height(Length::Fill) - .align_items($crate::iced::alignment::Alignment::Center) - ) - .max_height(60) - .padding(10) - ); -} -pub use list_box_row; use crate::widget::separator_style; diff --git a/src/widget/list/list_row.rs b/src/widget/list/list_row.rs new file mode 100644 index 00000000..9046ecbf --- /dev/null +++ b/src/widget/list/list_row.rs @@ -0,0 +1,18 @@ +use derive_setters::Setters; + +#[derive(Setters, Default, Debug, Clone)] +pub struct ListRow<'a> { + pub(crate) title: &'a str, + #[setters(strip_option)] + pub subtitle: Option<&'a str>, + #[setters(strip_option)] + pub icon: Option, +} + +pub fn list_row<'a>() -> ListRow<'a> { + ListRow { + title: "", + subtitle: None, + icon: None, + } +} diff --git a/src/widget/list/macros.rs b/src/widget/list/macros.rs new file mode 100644 index 00000000..52609320 --- /dev/null +++ b/src/widget/list/macros.rs @@ -0,0 +1,145 @@ +pub use iced::{widget, Background, Color, Theme}; + +pub mod list_view { + #[macro_export] + macro_rules! list_view { + ($($x:expr),+ $(,)?) => ( + $crate::iced::widget::Column::with_children( + vec![$($crate::iced::Element::from($x)),+] + ) + .spacing(24) + .padding(24) + .max_width(600) + ); + } + + #[macro_export] + macro_rules! list_row { + ($($x:expr),+ $(,)?) => ( + $crate::iced::widget::Row::with_children(vec![ + $($crate::iced::Element::from($x)),+ + ]) + .align_items(Alignment::Center) + .padding([0, 8]) + .spacing(12) + ); + } + + #[macro_export] + macro_rules! list_section { + ($title:expr, $($x:expr),+ $(,)?) => ( + $crate::iced::widget::Column::with_children(vec![ + $crate::iced::widget::Text::new($title) + .font($crate::font::FONT_SEMIBOLD) + .into() + , + $crate::iced::widget::Container::new({ + let mut children = vec![$($crate::iced::Element::from($x)),+]; + + //TODO: more efficient method for adding separators + let mut i = 1; + while i < children.len() { + children.insert(i, $crate::iced::widget::horizontal_rule(12).into()); + i += 2; + } + + $crate::iced::widget::Column::with_children(children) + .spacing(12) + }) + .padding([12, 16]) + .style(theme::Container::Custom( + list_section_style + )) + .into() + ]) + .spacing(8) + ); + } + + #[macro_export] + macro_rules! list_item { + ($title:expr, $($x:expr),+ $(,)?) => ( + $crate::list_row!( + $crate::iced::widget::Text::new($title), + $crate::iced::widget::horizontal_space( + $crate::iced::Length::Fill + ), + $($x),+ + ) + ); + } + + pub fn list_section_style(theme: &Theme) -> widget::container::Appearance { + let cosmic = &theme.cosmic().primary; + widget::container::Appearance { + text_color: Some(cosmic.on.into()), + background: Some(Background::Color(cosmic.base.into())), + border_radius: 8.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + } + } + + use crate::widget::{Background, Color}; + use iced::widget; + use iced_style::Theme; + + pub use list_item; + pub use list_row; + pub use list_section; + pub use list_view; +} + +pub mod list_box { + #[macro_export] + macro_rules! list_box_row { + ($title:expr) => { + $crate::iced::widget::container( + $crate::iced::widget::row![ + text($title).size(18), + $crate::iced::widget::vertical_space(Length::Fill), + $crate::iced::widget::horizontal_space(Length::Fill) + ] + .height(Length::Fill) + .align_items($crate::iced::alignment::Alignment::Center), + ) + .max_height(60) + .padding(10) + }; + ($title:expr, $subtitle:expr) => { + $crate::iced::widget::container( + $crate::iced::widget::row![ + column(vec![ + text($title).size(18).into(), + text($subtitle).size(16).into(), + ]), + $crate::iced::widget::vertical_space(Length::Fill), + $crate::iced::widget::horizontal_space(Length::Fill) + ] + .height(Length::Fill) + .align_items($crate::iced::alignment::Alignment::Center), + ) + .max_height(60) + .padding(10) + }; + ($title:expr, $subtitle:expr, $icon:expr) => { + $crate::iced::widget::container( + $crate::iced::widget::row![ + container($crate::widget::icon($icon, 20)).padding(10), + column(vec![ + text($title).size(18).into(), + text($subtitle).size(16).into(), + ]), + $crate::iced::widget::vertical_space(Length::Fill), + $crate::iced::widget::horizontal_space(Length::Fill) + ] + .height(Length::Fill) + .align_items($crate::iced::alignment::Alignment::Center), + ) + .max_height(60) + .padding(10) + }; + } + + pub use list_box_row; +} diff --git a/src/widget/list/mod.rs b/src/widget/list/mod.rs new file mode 100644 index 00000000..d437d307 --- /dev/null +++ b/src/widget/list/mod.rs @@ -0,0 +1,8 @@ +pub mod macros; +pub use macros::*; + +pub mod list_row; +pub use list_row::*; + +pub mod list_box; +pub use list_box::*; diff --git a/src/widget/mod.rs b/src/widget/mod.rs index 18418951..83e27946 100644 --- a/src/widget/mod.rs +++ b/src/widget/mod.rs @@ -7,14 +7,8 @@ pub use header_bar::*; mod icon; pub use self::icon::*; -mod list; -pub use list::*; - -mod nav; -pub use nav::*; - -mod navbar; -pub use navbar::*; +pub mod navigation; +pub use navigation::*; mod toggler; pub use toggler::*; @@ -25,5 +19,5 @@ pub use scrollable::*; mod expander; pub use expander::*; -pub mod list_box; -pub use list_box::*; \ No newline at end of file +pub mod list; +pub use list::*; diff --git a/src/widget/nav.rs b/src/widget/nav.rs deleted file mode 100644 index 1903cd69..00000000 --- a/src/widget/nav.rs +++ /dev/null @@ -1,52 +0,0 @@ -use iced::{widget, Background, Color, Theme}; - -#[macro_export] -macro_rules! nav_bar { - ($($x:expr),+ $(,)?) => ( - $crate::iced::widget::Container::new( - $crate::scrollable!( - $crate::iced::widget::row![ - $crate::iced::widget::Column::with_children( - vec![$($crate::iced::Element::from($x)),+] - ) - .spacing(12) - .padding(12), - ] - ) - ) - .max_width(300) - .padding(12) - .height(Length::Fill) - .style(theme::Container::Custom( - $crate::widget::nav_bar_style - )) - ); -} -pub use nav_bar; - -pub fn nav_bar_style(theme: &Theme) -> widget::container::Appearance { - let cosmic = &theme.cosmic().primary; - widget::container::Appearance { - text_color: Some(cosmic.on.into()), - background: Some(Background::Color(cosmic.base.into())), - border_radius: 8.0, - border_width: 0.0, - border_color: Color::TRANSPARENT, - } -} - -#[macro_export] -macro_rules! nav_button { - ($icon: expr, $title:expr, $condensed:expr) => {{ - if $condensed { - $crate::iced::widget::Button::new($crate::widget::icon($icon, 22)).padding(8) - } else { - $crate::widget::button!( - $crate::widget::icon($icon, 22), - $crate::iced::widget::Text::new($title), - $crate::iced::widget::horizontal_space($crate::iced::Length::Fill), - ) - } - }}; -} -pub use nav_button; diff --git a/src/widget/navigation/macros.rs b/src/widget/navigation/macros.rs new file mode 100644 index 00000000..674c0df0 --- /dev/null +++ b/src/widget/navigation/macros.rs @@ -0,0 +1,31 @@ +pub mod nav_bar { + use iced::{widget, Background, Color, Theme}; + + #[macro_export] + macro_rules! nav_button { + ($icon: expr, $title:expr, $condensed:expr) => {{ + if $condensed { + $crate::iced::widget::Button::new($crate::widget::icon($icon, 22)).padding(8) + } else { + $crate::widget::button!( + $crate::widget::icon($icon, 22), + $crate::iced::widget::Text::new($title), + $crate::iced::widget::horizontal_space($crate::iced::Length::Fill), + ) + } + }}; + } + + pub fn nav_bar_style(theme: &Theme) -> widget::container::Appearance { + let cosmic = &theme.cosmic().primary; + widget::container::Appearance { + text_color: Some(cosmic.on.into()), + background: Some(Background::Color(cosmic.base.into())), + border_radius: 8.0, + border_width: 0.0, + border_color: Color::TRANSPARENT, + } + } + + pub use nav_button; +} diff --git a/src/widget/navigation/mod.rs b/src/widget/navigation/mod.rs new file mode 100644 index 00000000..896b8382 --- /dev/null +++ b/src/widget/navigation/mod.rs @@ -0,0 +1,5 @@ +pub mod navbar; +pub use navbar::*; + +pub mod macros; +pub use macros::*; diff --git a/src/widget/navbar.rs b/src/widget/navigation/navbar.rs similarity index 100% rename from src/widget/navbar.rs rename to src/widget/navigation/navbar.rs