From 286a4dd14f5155c8b23db470b2ee466e1c26ba66 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 9 Aug 2021 10:46:34 +0100 Subject: [PATCH 01/25] Gallery: default to flat theme --- examples/gallery.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gallery.rs b/examples/gallery.rs index 08b343334..e50afc82c 100644 --- a/examples/gallery.rs +++ b/examples/gallery.rs @@ -103,8 +103,8 @@ fn main() -> Result<(), kas::shell::Error> { #[cfg(feature = "stack_dst")] let theme = kas::theme::MultiTheme::builder() - .add("shaded", kas::theme::ShadedTheme::new()) .add("flat", kas::theme::FlatTheme::new()) + .add("shaded", kas::theme::ShadedTheme::new()) .build(); #[cfg(not(feature = "stack_dst"))] let theme = kas::theme::ShadedTheme::new(); From 7ad29af7061af3233db3a34e1cfecd8c3ef3d1c6 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 9 Aug 2021 11:45:30 +0100 Subject: [PATCH 02/25] Flat theme: adjust button frame --- crates/kas-theme/src/colors.rs | 2 +- crates/kas-theme/src/flat_theme.rs | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/kas-theme/src/colors.rs b/crates/kas-theme/src/colors.rs index 9e7603032..7a7282dda 100644 --- a/crates/kas-theme/src/colors.rs +++ b/crates/kas-theme/src/colors.rs @@ -125,7 +125,7 @@ impl ColorsLinear { pub fn light() -> Self { Colors { background: Rgba::grey(0.9), - frame: Rgba::rgb(0.8, 0.8, 0.9), + frame: Rgba::grey(0.5), edit_bg: Rgba::grey(1.0), edit_bg_error: Rgba::rgb(1.0, 0.5, 0.5), text: Rgba::grey(0.0), diff --git a/crates/kas-theme/src/flat_theme.rs b/crates/kas-theme/src/flat_theme.rs index 40e0d6f05..6ddf7d03d 100644 --- a/crates/kas-theme/src/flat_theme.rs +++ b/crates/kas-theme/src/flat_theme.rs @@ -77,7 +77,7 @@ const DIMS: dim::Parameters = dim::Parameters { inner_margin: 1.2, text_margin: 2.0, frame_size: 4.0, - button_frame: 6.0, + button_frame: 2.4, scrollbar_size: Vec2::splat(8.0), slider_size: Vec2(12.0, 25.0), progress_bar: Vec2::splat(12.0), @@ -421,12 +421,15 @@ where fn button(&mut self, rect: Rect, col: Option, state: InputState) { let outer = Quad::from(rect); - let col = col.map(|c| c.into()).unwrap_or(self.cols.button); + + let inner = outer.shrink(self.window.dims.button_frame as f32 * BG_SHRINK_FACTOR); + let col = col.map(|c| c.into()).unwrap_or(self.cols.background); let col = ColorsLinear::adjust_for_state(col, state); + self.draw.rect(inner, col); let inner = outer.shrink(self.window.dims.button_frame as f32); - self.draw.rounded_frame(outer, inner, 0.0, col); - self.draw.rect(inner, col); + self.draw + .rounded_frame(outer, inner, BG_SHRINK_FACTOR, self.cols.frame); if let Some(col) = self.cols.nav_region(state) { let outer = outer.shrink(self.window.dims.inner_margin as f32); From b5abd326f94918577f917f6458a447ba00df7e4e Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 9 Aug 2021 12:09:33 +0100 Subject: [PATCH 03/25] Adjust text colours --- crates/kas-core/src/draw/color.rs | 14 ++++++-- crates/kas-theme/src/colors.rs | 58 ++++++++++++++---------------- crates/kas-theme/src/flat_theme.rs | 23 ++++++------ 3 files changed, 50 insertions(+), 45 deletions(-) diff --git a/crates/kas-core/src/draw/color.rs b/crates/kas-core/src/draw/color.rs index 00fc0b5a8..e24d46abe 100644 --- a/crates/kas-core/src/draw/color.rs +++ b/crates/kas-core/src/draw/color.rs @@ -57,9 +57,14 @@ impl Rgba { Self::rgba(s, s, s, a) } + /// Get the sum of the three colour components + pub fn sum(self) -> f32 { + self.r + self.g + self.b + } + /// Average three colour components (desaturate) pub fn average(self) -> Self { - Self::ga((self.r + self.g + self.b) * (1.0 / 3.0), self.a) + Self::ga(self.sum() * (1.0 / 3.0), self.a) } /// Multiply and clamp three colour components @@ -131,9 +136,14 @@ impl Rgb { Self::rgb(s, s, s) } + /// Get the sum of the three colour components + pub fn sum(self) -> f32 { + self.r + self.g + self.b + } + /// Average three colour components (desaturate) pub fn average(self) -> Self { - Self::grey((self.r + self.g + self.b) * (1.0 / 3.0)) + Self::grey(self.sum() * (1.0 / 3.0)) } /// Multiply and clamp three colour components diff --git a/crates/kas-theme/src/colors.rs b/crates/kas-theme/src/colors.rs index 7a7282dda..174c62181 100644 --- a/crates/kas-theme/src/colors.rs +++ b/crates/kas-theme/src/colors.rs @@ -6,7 +6,7 @@ //! Colour schemes use kas::draw::color::{Rgba, Rgba8Srgb}; -use kas::draw::{InputState, TextClass}; +use kas::draw::InputState; const MULT_DEPRESS: f32 = 0.75; const MULT_HIGHLIGHT: f32 = 1.25; @@ -24,16 +24,14 @@ pub struct Colors { pub edit_bg: C, /// Background colour of `EditBox` (error state) pub edit_bg_error: C, - /// Text colour in an `EditBox` + /// Normal text colour (over background) pub text: C, - /// Selected tect colour - pub text_sel: C, + /// Opposing text colour (e.g. white if `text` is black) + pub text_invert: C, + /// Disabled text colour + pub text_disabled: C, /// Selected text background colour pub text_sel_bg: C, - /// Text colour in a `Label` - pub label_text: C, - /// Text colour on a `TextButton` - pub button_text: C, /// Highlight colour for keyboard navigation pub nav_focus: C, /// Colour of a `TextButton` @@ -56,10 +54,9 @@ impl From for ColorsLinear { edit_bg: col.edit_bg.into(), edit_bg_error: col.edit_bg_error.into(), text: col.text.into(), - text_sel: col.text_sel.into(), + text_invert: col.text_invert.into(), + text_disabled: col.text_disabled.into(), text_sel_bg: col.text_sel_bg.into(), - label_text: col.label_text.into(), - button_text: col.button_text.into(), nav_focus: col.nav_focus.into(), button: col.button.into(), checkbox: col.checkbox.into(), @@ -75,10 +72,9 @@ impl From for ColorsSrgb { edit_bg: col.edit_bg.into(), edit_bg_error: col.edit_bg_error.into(), text: col.text.into(), - text_sel: col.text_sel.into(), + text_invert: col.text_invert.into(), + text_disabled: col.text_disabled.into(), text_sel_bg: col.text_sel_bg.into(), - label_text: col.label_text.into(), - button_text: col.button_text.into(), nav_focus: col.nav_focus.into(), button: col.button.into(), checkbox: col.checkbox.into(), @@ -110,11 +106,10 @@ impl ColorsLinear { frame: Rgba::grey(0.7), edit_bg: Rgba::grey(1.0), edit_bg_error: Rgba::rgb(1.0, 0.5, 0.5), - text: Rgba::grey(0.0), - text_sel: Rgba::grey(1.0), + text: Rgba::BLACK, + text_invert: Rgba::WHITE, + text_disabled: Rgba::grey(0.4), text_sel_bg: Rgba::rgb(0.15, 0.525, 0.75), - label_text: Rgba::grey(0.0), - button_text: Rgba::grey(1.0), nav_focus: Rgba::rgb(0.9, 0.65, 0.4), button: Rgba::rgb(0.2, 0.7, 1.0), checkbox: Rgba::rgb(0.2, 0.7, 1.0), @@ -128,11 +123,10 @@ impl ColorsLinear { frame: Rgba::grey(0.5), edit_bg: Rgba::grey(1.0), edit_bg_error: Rgba::rgb(1.0, 0.5, 0.5), - text: Rgba::grey(0.0), - text_sel: Rgba::grey(0.0), + text: Rgba::BLACK, + text_invert: Rgba::WHITE, + text_disabled: Rgba::grey(0.4), text_sel_bg: Rgba::rgb(0.8, 0.72, 0.24), - label_text: Rgba::grey(0.0), - button_text: Rgba::grey(0.0), nav_focus: Rgba::rgb(0.9, 0.65, 0.4), button: Rgba::rgb(1.0, 0.9, 0.3), checkbox: Rgba::grey(0.4), @@ -146,11 +140,10 @@ impl ColorsLinear { frame: Rgba::grey(0.4), edit_bg: Rgba::grey(0.1), edit_bg_error: Rgba::rgb(1.0, 0.5, 0.5), - text: Rgba::grey(1.0), - text_sel: Rgba::grey(1.0), + text: Rgba::WHITE, + text_invert: Rgba::BLACK, + text_disabled: Rgba::grey(0.6), text_sel_bg: Rgba::rgb(0.6, 0.3, 0.1), - label_text: Rgba::grey(1.0), - button_text: Rgba::grey(1.0), nav_focus: Rgba::rgb(1.0, 0.7, 0.5), button: Rgba::rgb(0.5, 0.1, 0.1), checkbox: Rgba::rgb(0.5, 0.1, 0.1), @@ -222,12 +215,13 @@ impl ColorsLinear { self.button_state(state) } - /// Get text colour from class - pub fn text_class(&self, class: TextClass) -> Rgba { - match class { - TextClass::Label | TextClass::MenuLabel | TextClass::LabelScroll => self.label_text, - TextClass::Button => self.button_text, - TextClass::Edit | TextClass::EditMulti => self.text, + /// Get appropriate text colour over the given background + pub fn text_over(&self, bg: Rgba) -> Rgba { + let bg_sum = bg.sum(); + if (bg_sum - self.text_invert.sum()).abs() > (bg_sum - self.text.sum()).abs() { + self.text_invert + } else { + self.text } } } diff --git a/crates/kas-theme/src/flat_theme.rs b/crates/kas-theme/src/flat_theme.rs index 6ddf7d03d..006d2c437 100644 --- a/crates/kas-theme/src/flat_theme.rs +++ b/crates/kas-theme/src/flat_theme.rs @@ -319,24 +319,24 @@ where self.draw.frame(outer, inner, col); } - fn text(&mut self, pos: Coord, text: &TextDisplay, class: TextClass) { + fn text(&mut self, pos: Coord, text: &TextDisplay, _: TextClass) { let pos = pos; - let col = self.cols.text_class(class); + let col = self.cols.text; self.draw.text(pos.into(), text, col); } - fn text_effects(&mut self, pos: Coord, text: &dyn TextApi, class: TextClass) { + fn text_effects(&mut self, pos: Coord, text: &dyn TextApi, _: TextClass) { self.draw.text_col_effects( (pos).into(), text.display(), - self.cols.text_class(class), + self.cols.text, text.effect_tokens(), ); } - fn text_accel(&mut self, pos: Coord, text: &Text, state: bool, class: TextClass) { + fn text_accel(&mut self, pos: Coord, text: &Text, state: bool, _: TextClass) { let pos = Vec2::from(pos); - let col = self.cols.text_class(class); + let col = self.cols.text; if state { let effects = text.text().effect_tokens(); self.draw.text_col_effects(pos, text.as_ref(), col, effects); @@ -350,10 +350,11 @@ where pos: Coord, text: &TextDisplay, range: Range, - class: TextClass, + _: TextClass, ) { let pos = Vec2::from(pos); - let col = self.cols.text_class(class); + let col = self.cols.text; + let sel_col = self.cols.text_over(self.cols.text_sel_bg); // Draw background: for (p1, p2) in &text.highlight_lines(range.clone()) { @@ -372,7 +373,7 @@ where Effect { start: range.start.cast(), flags: Default::default(), - aux: self.cols.text_sel, + aux: sel_col, }, Effect { start: range.end.cast(), @@ -383,11 +384,11 @@ where self.draw.text_effects(pos, text, &effects); } - fn edit_marker(&mut self, pos: Coord, text: &TextDisplay, class: TextClass, byte: usize) { + fn edit_marker(&mut self, pos: Coord, text: &TextDisplay, _: TextClass, byte: usize) { let width = self.window.dims.font_marker_width; let pos = Vec2::from(pos); - let mut col = self.cols.text_class(class); + let mut col = self.cols.text; for cursor in text.text_glyph_pos(byte).rev() { let mut p1 = pos + Vec2::from(cursor.pos); let mut p2 = p1; From 5fb0b3e67dad115a4a49825b804e33729f8c1004 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 9 Aug 2021 12:24:21 +0100 Subject: [PATCH 04/25] TextButton: align self --- crates/kas-widgets/src/button.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/crates/kas-widgets/src/button.rs b/crates/kas-widgets/src/button.rs index ad7725cdc..6aa293ec8 100644 --- a/crates/kas-widgets/src/button.rs +++ b/crates/kas-widgets/src/button.rs @@ -23,6 +23,7 @@ pub struct Button, M: 'static> { keys1: VirtualKeyCodes, frame_size: Size, frame_offset: Offset, + ideal_size: Size, color: Option, #[widget_derive] #[widget] @@ -37,6 +38,7 @@ impl, M: 'static> Debug for Button { .field("keys1", &self.keys1) .field("frame_size", &self.frame_size) .field("frame_offset", &self.frame_offset) + .field("ideal_size", &self.ideal_size) .field("color", &self.color) .field("label", &self.label) .finish_non_exhaustive() @@ -64,10 +66,14 @@ impl, M: 'static> Layout for Button { let (rules, offset, size) = frame_rules.surround_as_margin(content_rules); self.frame_size.set_component(axis, size); self.frame_offset.set_component(axis, offset); + self.ideal_size.set_component(axis, rules.ideal_size()); rules } - fn set_rect(&mut self, mgr: &mut Manager, mut rect: Rect, align: AlignHints) { + fn set_rect(&mut self, mgr: &mut Manager, rect: Rect, align: AlignHints) { + let mut rect = align + .complete(Align::Centre, Align::Centre) + .aligned_rect(self.ideal_size, rect); self.core.rect = rect; rect.pos += self.frame_offset; rect.size -= self.frame_size; @@ -89,6 +95,7 @@ impl> Button { keys1: Default::default(), frame_size: Default::default(), frame_offset: Default::default(), + ideal_size: Default::default(), color: None, label, on_push: None, @@ -110,6 +117,7 @@ impl> Button { keys1: self.keys1, frame_size: self.frame_size, frame_offset: self.frame_offset, + ideal_size: self.ideal_size, color: self.color, label: self.label, on_push: Some(Rc::new(f)), @@ -205,6 +213,7 @@ pub struct TextButton { keys1: VirtualKeyCodes, frame_size: Size, frame_offset: Offset, + ideal_size: Size, color: Option, label: Text, on_push: Option Option>>, @@ -217,6 +226,7 @@ impl Debug for TextButton { .field("keys1", &self.keys1) .field("frame_size", &self.frame_size) .field("frame_offset", &self.frame_offset) + .field("ideal_size", &self.ideal_size) .field("color", &self.color) .field("label", &self.label) .finish_non_exhaustive() @@ -245,10 +255,14 @@ impl Layout for TextButton { let (rules, offset, size) = frame_rules.surround_as_margin(content_rules); self.frame_size.set_component(axis, size); self.frame_offset.set_component(axis, offset); + self.ideal_size.set_component(axis, rules.ideal_size()); rules } fn set_rect(&mut self, _: &mut Manager, rect: Rect, align: AlignHints) { + let rect = align + .complete(Align::Centre, Align::Centre) + .aligned_rect(self.ideal_size, rect); self.core.rect = rect; let size = rect.size - self.frame_size; self.label.update_env(|env| { @@ -276,6 +290,7 @@ impl TextButton { keys1: Default::default(), frame_size: Default::default(), frame_offset: Default::default(), + ideal_size: Default::default(), color: None, label: text, on_push: None, @@ -297,6 +312,7 @@ impl TextButton { keys1: self.keys1, frame_size: self.frame_size, frame_offset: self.frame_offset, + ideal_size: self.ideal_size, color: self.color, label: self.label, on_push: Some(Rc::new(f)), From ab16d92eb03bfbbb3fd6a5801b872d9f40491a68 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 9 Aug 2021 14:38:52 +0100 Subject: [PATCH 05/25] FlatTheme::button: use border colour for nav highlight --- crates/kas-theme/src/flat_theme.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/crates/kas-theme/src/flat_theme.rs b/crates/kas-theme/src/flat_theme.rs index 006d2c437..e53acad30 100644 --- a/crates/kas-theme/src/flat_theme.rs +++ b/crates/kas-theme/src/flat_theme.rs @@ -423,19 +423,16 @@ where fn button(&mut self, rect: Rect, col: Option, state: InputState) { let outer = Quad::from(rect); - let inner = outer.shrink(self.window.dims.button_frame as f32 * BG_SHRINK_FACTOR); let col = col.map(|c| c.into()).unwrap_or(self.cols.background); let col = ColorsLinear::adjust_for_state(col, state); - self.draw.rect(inner, col); + if col != self.cols.background { + let inner = outer.shrink(self.window.dims.button_frame as f32 * BG_SHRINK_FACTOR); + self.draw.rect(inner, col); + } + let col = self.cols.nav_region(state).unwrap_or(self.cols.frame); let inner = outer.shrink(self.window.dims.button_frame as f32); - self.draw - .rounded_frame(outer, inner, BG_SHRINK_FACTOR, self.cols.frame); - - if let Some(col) = self.cols.nav_region(state) { - let outer = outer.shrink(self.window.dims.inner_margin as f32); - self.draw.rounded_frame(outer, inner, 0.6, col); - } + self.draw.rounded_frame(outer, inner, BG_SHRINK_FACTOR, col); } fn edit_box(&mut self, rect: Rect, state: InputState) { From 21b4a882dce6316887e2d26902388cb37612d79c Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 9 Aug 2021 15:12:30 +0100 Subject: [PATCH 06/25] FlatTheme: nicer checkbox and radiobox --- crates/kas-theme/src/flat_theme.rs | 36 ++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/crates/kas-theme/src/flat_theme.rs b/crates/kas-theme/src/flat_theme.rs index e53acad30..579cd183f 100644 --- a/crates/kas-theme/src/flat_theme.rs +++ b/crates/kas-theme/src/flat_theme.rs @@ -441,28 +441,40 @@ where } fn checkbox(&mut self, rect: Rect, checked: bool, state: InputState) { - let bg_col = self.cols.bg_col(state); - let nav_col = self.cols.nav_region(state).or(Some(bg_col)); + let outer = Quad::from(rect); - let inner = self.draw_edit_box(rect, bg_col, nav_col); + let col = ColorsLinear::adjust_for_state(self.cols.background, state); + if col != self.cols.background { + let inner = outer.shrink(self.window.dims.button_frame as f32 * BG_SHRINK_FACTOR); + self.draw.rect(inner, col); + } + + let col = self.cols.nav_region(state).unwrap_or(self.cols.frame); + let inner = outer.shrink(self.window.dims.button_frame as f32); + self.draw.rounded_frame(outer, inner, BG_SHRINK_FACTOR, col); if let Some(col) = self.cols.check_mark_state(state, checked) { - let radius = inner.size().sum() * (1.0 / 16.0); - let inner = inner.shrink(self.window.dims.inner_margin as f32 + radius); - self.draw.rounded_line(inner.a, inner.b, radius, col); - self.draw.rounded_line(inner.ab(), inner.ba(), radius, col); + let inner = inner.shrink((2 * self.window.dims.inner_margin) as f32); + self.draw.rect(inner, col); } } fn radiobox(&mut self, rect: Rect, checked: bool, state: InputState) { - let bg_col = self.cols.bg_col(state); - let nav_col = self.cols.nav_region(state).or(Some(bg_col)); + let outer = Quad::from(rect); - let inner = self.draw_edit_box(rect, bg_col, nav_col); + let col = ColorsLinear::adjust_for_state(self.cols.background, state); + if col != self.cols.background { + self.draw.circle(outer, 0.0, col); + } + + let col = self.cols.nav_region(state).unwrap_or(self.cols.frame); + let r = 1.0 - 2.0 * self.window.dims.button_frame as f32 / rect.size.0 as f32; + self.draw.circle(outer, r, col); if let Some(col) = self.cols.check_mark_state(state, checked) { - let inner = inner.shrink(self.window.dims.inner_margin as f32); - self.draw.circle(inner, 0.5, col); + let r = self.window.dims.button_frame + 2 * self.window.dims.inner_margin as i32; + let inner = outer.shrink(r as f32); + self.draw.circle(inner, 0.0, col); } } From 352d59783f9d3bcab1813d946782b8a38245c08b Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 9 Aug 2021 15:56:21 +0100 Subject: [PATCH 07/25] Adjust colour categories --- crates/kas-theme/src/colors.rs | 87 +++++++++++++--------------- crates/kas-theme/src/config.rs | 1 - crates/kas-theme/src/flat_theme.rs | 4 +- crates/kas-theme/src/shaded_theme.rs | 6 +- 4 files changed, 45 insertions(+), 53 deletions(-) diff --git a/crates/kas-theme/src/colors.rs b/crates/kas-theme/src/colors.rs index 174c62181..756d80f55 100644 --- a/crates/kas-theme/src/colors.rs +++ b/crates/kas-theme/src/colors.rs @@ -25,19 +25,29 @@ pub struct Colors { /// Background colour of `EditBox` (error state) pub edit_bg_error: C, /// Normal text colour (over background) + /// Theme accent + /// + /// This should be a bold colour, used for small details. + pub accent: C, + /// Soft version of accent + /// + /// A softer version of the accent colour, used for block elements in some themes. + pub accent_soft: C, + /// Highlight colour for keyboard navigation + /// + /// This may be the same as `accent`. It should contrast well with + /// `accent_soft`. Themes should use `nav_focus` over `accent` where a + /// strong contrast is required. + pub nav_focus: C, pub text: C, /// Opposing text colour (e.g. white if `text` is black) pub text_invert: C, /// Disabled text colour pub text_disabled: C, /// Selected text background colour + /// + /// This may be the same as `accent_soft`. pub text_sel_bg: C, - /// Highlight colour for keyboard navigation - pub nav_focus: C, - /// Colour of a `TextButton` - pub button: C, - /// Colour of mark within a `CheckBox` or `RadioBox` - pub checkbox: C, } /// [`Colors`] parameterised for reading and writing using sRGB @@ -51,15 +61,15 @@ impl From for ColorsLinear { Colors { background: col.background.into(), frame: col.frame.into(), + accent: col.accent.into(), + accent_soft: col.accent_soft.into(), + nav_focus: col.nav_focus.into(), edit_bg: col.edit_bg.into(), edit_bg_error: col.edit_bg_error.into(), text: col.text.into(), text_invert: col.text_invert.into(), text_disabled: col.text_disabled.into(), text_sel_bg: col.text_sel_bg.into(), - nav_focus: col.nav_focus.into(), - button: col.button.into(), - checkbox: col.checkbox.into(), } } } @@ -69,15 +79,15 @@ impl From for ColorsSrgb { Colors { background: col.background.into(), frame: col.frame.into(), + accent: col.accent.into(), + accent_soft: col.accent_soft.into(), + nav_focus: col.nav_focus.into(), edit_bg: col.edit_bg.into(), edit_bg_error: col.edit_bg_error.into(), text: col.text.into(), text_invert: col.text_invert.into(), text_disabled: col.text_disabled.into(), text_sel_bg: col.text_sel_bg.into(), - nav_focus: col.nav_focus.into(), - button: col.button.into(), - checkbox: col.checkbox.into(), } } } @@ -104,32 +114,15 @@ impl ColorsLinear { Colors { background: Rgba::grey(1.0), frame: Rgba::grey(0.7), - edit_bg: Rgba::grey(1.0), - edit_bg_error: Rgba::rgb(1.0, 0.5, 0.5), - text: Rgba::BLACK, - text_invert: Rgba::WHITE, - text_disabled: Rgba::grey(0.4), - text_sel_bg: Rgba::rgb(0.15, 0.525, 0.75), + accent: Rgba::rgb(0.2, 0.7, 1.0), + accent_soft: Rgba::rgb(0.2, 0.7, 1.0), nav_focus: Rgba::rgb(0.9, 0.65, 0.4), - button: Rgba::rgb(0.2, 0.7, 1.0), - checkbox: Rgba::rgb(0.2, 0.7, 1.0), - } - } - - /// Light scheme - pub fn light() -> Self { - Colors { - background: Rgba::grey(0.9), - frame: Rgba::grey(0.5), edit_bg: Rgba::grey(1.0), edit_bg_error: Rgba::rgb(1.0, 0.5, 0.5), text: Rgba::BLACK, text_invert: Rgba::WHITE, text_disabled: Rgba::grey(0.4), - text_sel_bg: Rgba::rgb(0.8, 0.72, 0.24), - nav_focus: Rgba::rgb(0.9, 0.65, 0.4), - button: Rgba::rgb(1.0, 0.9, 0.3), - checkbox: Rgba::grey(0.4), + text_sel_bg: Rgba::rgb(0.15, 0.525, 0.75), } } @@ -138,15 +131,15 @@ impl ColorsLinear { Colors { background: Rgba::grey(0.2), frame: Rgba::grey(0.4), + accent: Rgba::rgb(0.5, 0.1, 0.1), + accent_soft: Rgba::rgb(0.5, 0.1, 0.1), + nav_focus: Rgba::rgb(1.0, 0.7, 0.5), edit_bg: Rgba::grey(0.1), edit_bg_error: Rgba::rgb(1.0, 0.5, 0.5), text: Rgba::WHITE, text_invert: Rgba::BLACK, text_disabled: Rgba::grey(0.6), text_sel_bg: Rgba::rgb(0.6, 0.3, 0.1), - nav_focus: Rgba::rgb(1.0, 0.7, 0.5), - button: Rgba::rgb(0.5, 0.1, 0.1), - checkbox: Rgba::rgb(0.5, 0.1, 0.1), } } @@ -183,18 +176,24 @@ impl ColorsLinear { } } - /// Get colour for a button, depending on state + /// Get accent colour, adjusted for state + #[inline] + pub fn accent_state(&self, state: InputState) -> Rgba { + Self::adjust_for_state(self.accent, state) + } + + /// Get soft accent colour, adjusted for state #[inline] - pub fn button_state(&self, state: InputState) -> Rgba { - Self::adjust_for_state(self.button, state) + pub fn accent_soft_state(&self, state: InputState) -> Rgba { + Self::adjust_for_state(self.accent_soft, state) } /// Get colour for a checkbox mark, depending on state pub fn check_mark_state(&self, state: InputState, checked: bool) -> Option { if checked { - Some(Self::adjust_for_state(self.checkbox, state)) + Some(Self::adjust_for_state(self.accent, state)) } else if state.depress { - Some(self.checkbox.multiply(MULT_DEPRESS)) + Some(self.accent.multiply(MULT_DEPRESS)) } else { None } @@ -203,18 +202,12 @@ impl ColorsLinear { /// Get background highlight colour of a menu entry, if any pub fn menu_entry(&self, state: InputState) -> Option { if state.depress || state.nav_focus { - Some(self.button.multiply(MULT_DEPRESS)) + Some(self.accent_soft.multiply(MULT_DEPRESS)) } else { None } } - /// Get colour of a scrollbar, depending on state - #[inline] - pub fn scrollbar_state(&self, state: InputState) -> Rgba { - self.button_state(state) - } - /// Get appropriate text colour over the given background pub fn text_over(&self, bg: Rgba) -> Rgba { let bg_sum = bg.sum(); diff --git a/crates/kas-theme/src/config.rs b/crates/kas-theme/src/config.rs index 838e8ae22..dc21e6ed6 100644 --- a/crates/kas-theme/src/config.rs +++ b/crates/kas-theme/src/config.rs @@ -237,7 +237,6 @@ mod defaults { pub fn color_schemes() -> BTreeMap { let mut schemes = BTreeMap::new(); schemes.insert("".to_string(), ColorsLinear::white_blue().into()); - schemes.insert("light".to_string(), ColorsLinear::light().into()); schemes.insert("dark".to_string(), ColorsLinear::dark().into()); schemes } diff --git a/crates/kas-theme/src/flat_theme.rs b/crates/kas-theme/src/flat_theme.rs index 579cd183f..7942405e3 100644 --- a/crates/kas-theme/src/flat_theme.rs +++ b/crates/kas-theme/src/flat_theme.rs @@ -234,7 +234,7 @@ where let outer = Quad::from(rect); let thickness = outer.size().min_comp() / 2.0; let inner = outer.shrink(thickness); - let col = self.cols.scrollbar_state(state); + let col = self.cols.accent_soft_state(state); self.draw.rounded_frame(outer, inner, 0.0, col); if let Some(col) = self.cols.nav_region(state) { @@ -515,7 +515,7 @@ where } else { inner.b.1 = inner.a.1 + value * (inner.b.1 - inner.a.1); } - let col = self.cols.button; + let col = self.cols.accent_soft; self.draw.rect(inner, col); } diff --git a/crates/kas-theme/src/shaded_theme.rs b/crates/kas-theme/src/shaded_theme.rs index fab3807e1..ff9200bd7 100644 --- a/crates/kas-theme/src/shaded_theme.rs +++ b/crates/kas-theme/src/shaded_theme.rs @@ -205,7 +205,7 @@ where let outer = Quad::from(rect); let thickness = outer.size().min_comp() / 2.0; let inner = outer.shrink(thickness); - let col = self.cols.scrollbar_state(state); + let col = self.cols.accent_soft_state(state); self.draw.shaded_round_frame(outer, inner, (0.0, 0.6), col); if let Some(col) = self.cols.nav_region(state) { @@ -317,7 +317,7 @@ where fn button(&mut self, rect: Rect, col: Option, state: InputState) { let outer = Quad::from(rect); let inner = outer.shrink(self.window.dims.button_frame as f32); - let col = col.map(|c| c.into()).unwrap_or(self.cols.button); + let col = col.map(|c| c.into()).unwrap_or(self.cols.accent_soft); let col = ColorsLinear::adjust_for_state(col, state); self.draw.shaded_round_frame(outer, inner, (0.0, 0.6), col); @@ -398,7 +398,7 @@ where } let thickness = outer.size().min_comp() / 2.0; let inner = outer.shrink(thickness); - let col = self.cols.button; + let col = self.cols.accent_soft; self.draw.shaded_round_frame(outer, inner, (0.0, 0.6), col); } From f84741827c53f330a9209da40c7ef4bed0256241 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 9 Aug 2021 16:12:53 +0100 Subject: [PATCH 08/25] Update light theme definition --- crates/kas-theme/src/colors.rs | 39 ++++++++++++++++++---------------- crates/kas-theme/src/config.rs | 2 +- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/crates/kas-theme/src/colors.rs b/crates/kas-theme/src/colors.rs index 756d80f55..4764fe559 100644 --- a/crates/kas-theme/src/colors.rs +++ b/crates/kas-theme/src/colors.rs @@ -7,6 +7,7 @@ use kas::draw::color::{Rgba, Rgba8Srgb}; use kas::draw::InputState; +use std::str::FromStr; const MULT_DEPRESS: f32 = 0.75; const MULT_HIGHLIGHT: f32 = 1.25; @@ -95,37 +96,39 @@ impl From for ColorsSrgb { impl Default for ColorsLinear { #[inline] fn default() -> Self { - Colors::white_blue() + ColorsSrgb::default().into() } } impl Default for ColorsSrgb { #[inline] fn default() -> Self { - ColorsLinear::default().into() + ColorsSrgb::light() } } -// NOTE: these colour schemes are defined using linear (Rgba) colours instead of -// sRGB (Rgba8Srgb) colours for historical reasons. Either should be fine. -impl ColorsLinear { - /// White background with blue activable items - pub fn white_blue() -> Self { +impl ColorsSrgb { + /// Default "light" scheme + pub fn light() -> Self { Colors { - background: Rgba::grey(1.0), - frame: Rgba::grey(0.7), - accent: Rgba::rgb(0.2, 0.7, 1.0), - accent_soft: Rgba::rgb(0.2, 0.7, 1.0), - nav_focus: Rgba::rgb(0.9, 0.65, 0.4), - edit_bg: Rgba::grey(1.0), - edit_bg_error: Rgba::rgb(1.0, 0.5, 0.5), - text: Rgba::BLACK, - text_invert: Rgba::WHITE, - text_disabled: Rgba::grey(0.4), - text_sel_bg: Rgba::rgb(0.15, 0.525, 0.75), + background: Rgba8Srgb::from_str("#FAFAFA").unwrap(), + frame: Rgba8Srgb::from_str("#BCBCBC").unwrap(), + accent: Rgba8Srgb::from_str("#7E3FF2").unwrap(), + accent_soft: Rgba8Srgb::from_str("#B38DF9").unwrap(), + nav_focus: Rgba8Srgb::from_str("#7E3FF2").unwrap(), + edit_bg: Rgba8Srgb::from_str("#FAFAFA").unwrap(), + edit_bg_error: Rgba8Srgb::from_str("#FFBCBC").unwrap(), + text: Rgba8Srgb::from_str("#000000").unwrap(), + text_invert: Rgba8Srgb::from_str("#FFFFFF").unwrap(), + text_disabled: Rgba8Srgb::from_str("#AAAAAA").unwrap(), + text_sel_bg: Rgba8Srgb::from_str("#A172FA").unwrap(), } } +} +// NOTE: these colour schemes are defined using linear (Rgba) colours instead of +// sRGB (Rgba8Srgb) colours for historical reasons. Either should be fine. +impl ColorsLinear { /// Dark scheme pub fn dark() -> Self { Colors { diff --git a/crates/kas-theme/src/config.rs b/crates/kas-theme/src/config.rs index dc21e6ed6..1d61d8c64 100644 --- a/crates/kas-theme/src/config.rs +++ b/crates/kas-theme/src/config.rs @@ -236,7 +236,7 @@ mod defaults { pub fn color_schemes() -> BTreeMap { let mut schemes = BTreeMap::new(); - schemes.insert("".to_string(), ColorsLinear::white_blue().into()); + schemes.insert("".to_string(), ColorsSrgb::light()); schemes.insert("dark".to_string(), ColorsLinear::dark().into()); schemes } From 7d7732a318efe6d21c42f04bfde444591311b867 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Mon, 9 Aug 2021 16:29:56 +0100 Subject: [PATCH 09/25] Update dark and blue theme definitions --- crates/kas-theme/src/colors.rs | 47 ++++++++++++++++++++++------------ crates/kas-theme/src/config.rs | 7 ++--- examples/gallery.rs | 2 +- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/crates/kas-theme/src/colors.rs b/crates/kas-theme/src/colors.rs index 4764fe559..3b067a644 100644 --- a/crates/kas-theme/src/colors.rs +++ b/crates/kas-theme/src/colors.rs @@ -25,7 +25,6 @@ pub struct Colors { pub edit_bg: C, /// Background colour of `EditBox` (error state) pub edit_bg_error: C, - /// Normal text colour (over background) /// Theme accent /// /// This should be a bold colour, used for small details. @@ -40,6 +39,7 @@ pub struct Colors { /// `accent_soft`. Themes should use `nav_focus` over `accent` where a /// strong contrast is required. pub nav_focus: C, + /// Normal text colour (over background) pub text: C, /// Opposing text colour (e.g. white if `text` is black) pub text_invert: C, @@ -124,28 +124,43 @@ impl ColorsSrgb { text_sel_bg: Rgba8Srgb::from_str("#A172FA").unwrap(), } } -} -// NOTE: these colour schemes are defined using linear (Rgba) colours instead of -// sRGB (Rgba8Srgb) colours for historical reasons. Either should be fine. -impl ColorsLinear { /// Dark scheme pub fn dark() -> Self { Colors { - background: Rgba::grey(0.2), - frame: Rgba::grey(0.4), - accent: Rgba::rgb(0.5, 0.1, 0.1), - accent_soft: Rgba::rgb(0.5, 0.1, 0.1), - nav_focus: Rgba::rgb(1.0, 0.7, 0.5), - edit_bg: Rgba::grey(0.1), - edit_bg_error: Rgba::rgb(1.0, 0.5, 0.5), - text: Rgba::WHITE, - text_invert: Rgba::BLACK, - text_disabled: Rgba::grey(0.6), - text_sel_bg: Rgba::rgb(0.6, 0.3, 0.1), + background: Rgba8Srgb::from_str("#404040").unwrap(), + frame: Rgba8Srgb::from_str("#AAAAAA").unwrap(), + accent: Rgba8Srgb::from_str("#F74C00").unwrap(), + accent_soft: Rgba8Srgb::from_str("#E77346").unwrap(), + nav_focus: Rgba8Srgb::from_str("#A33100").unwrap(), + edit_bg: Rgba8Srgb::from_str("#595959").unwrap(), + edit_bg_error: Rgba8Srgb::from_str("#FFBCBC").unwrap(), + text: Rgba8Srgb::from_str("#FFFFFF").unwrap(), + text_invert: Rgba8Srgb::from_str("#000000").unwrap(), + text_disabled: Rgba8Srgb::from_str("#CBCBCB").unwrap(), + text_sel_bg: Rgba8Srgb::from_str("#E77346").unwrap(), } } + /// Blue scheme + pub fn blue() -> Self { + Colors { + background: Rgba8Srgb::from_str("#FFFFFF").unwrap(), + frame: Rgba8Srgb::from_str("#DADADA").unwrap(), + accent: Rgba8Srgb::from_str("#7CDAFF").unwrap(), + accent_soft: Rgba8Srgb::from_str("#7CDAFF").unwrap(), + nav_focus: Rgba8Srgb::from_str("#3B697A").unwrap(), + edit_bg: Rgba8Srgb::from_str("#FFFFFF").unwrap(), + edit_bg_error: Rgba8Srgb::from_str("#FFBCBC").unwrap(), + text: Rgba8Srgb::from_str("#000000").unwrap(), + text_invert: Rgba8Srgb::from_str("#FFFFFF").unwrap(), + text_disabled: Rgba8Srgb::from_str("#AAAAAA").unwrap(), + text_sel_bg: Rgba8Srgb::from_str("#6CC0E1").unwrap(), + } + } +} + +impl ColorsLinear { /// Adjust a colour depending on state pub fn adjust_for_state(col: Rgba, state: InputState) -> Rgba { if state.disabled { diff --git a/crates/kas-theme/src/config.rs b/crates/kas-theme/src/config.rs index 1d61d8c64..c6dc36411 100644 --- a/crates/kas-theme/src/config.rs +++ b/crates/kas-theme/src/config.rs @@ -5,7 +5,7 @@ //! Theme configuration -use crate::{ColorsLinear, ColorsSrgb, ThemeConfig}; +use crate::{ColorsSrgb, ThemeConfig}; use kas::draw::TextClass; use kas::text::fonts::{fonts, AddMode, FontSelector}; use kas::TkAction; @@ -236,8 +236,9 @@ mod defaults { pub fn color_schemes() -> BTreeMap { let mut schemes = BTreeMap::new(); - schemes.insert("".to_string(), ColorsSrgb::light()); - schemes.insert("dark".to_string(), ColorsLinear::dark().into()); + schemes.insert("light".to_string(), ColorsSrgb::light()); + schemes.insert("dark".to_string(), ColorsSrgb::dark()); + schemes.insert("blue".to_string(), ColorsSrgb::blue()); schemes } diff --git a/examples/gallery.rs b/examples/gallery.rs index e50afc82c..254ab475e 100644 --- a/examples/gallery.rs +++ b/examples/gallery.rs @@ -324,7 +324,7 @@ fn main() -> Result<(), kas::shell::Error> { fn activations(&mut self, mgr: &mut Manager, item: Item) -> VoidResponse { match item { Item::Button => println!("Clicked!"), - Item::LightTheme => mgr.adjust_theme(|theme| theme.set_scheme("")), + Item::LightTheme => mgr.adjust_theme(|theme| theme.set_scheme("light")), Item::DarkTheme => mgr.adjust_theme(|theme| theme.set_scheme("dark")), Item::Check(b) => println!("CheckBox: {}", b), Item::Combo(c) => println!("ComboBox: {}", c), From e9be94709ecab3a35d82794f2ae776ae532f02ea Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 10 Aug 2021 09:20:55 +0100 Subject: [PATCH 10/25] FlatTheme::button: colour whole button on nav focus --- crates/kas-theme/src/flat_theme.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/kas-theme/src/flat_theme.rs b/crates/kas-theme/src/flat_theme.rs index 7942405e3..aef47efc6 100644 --- a/crates/kas-theme/src/flat_theme.rs +++ b/crates/kas-theme/src/flat_theme.rs @@ -423,7 +423,11 @@ where fn button(&mut self, rect: Rect, col: Option, state: InputState) { let outer = Quad::from(rect); - let col = col.map(|c| c.into()).unwrap_or(self.cols.background); + let col = if state.nav_focus && !state.disabled { + self.cols.accent_soft + } else { + col.map(|c| c.into()).unwrap_or(self.cols.background) + }; let col = ColorsLinear::adjust_for_state(col, state); if col != self.cols.background { let inner = outer.shrink(self.window.dims.button_frame as f32 * BG_SHRINK_FACTOR); From 886afa2ac87f638aaf55bfcd1ef64e44c7e91607 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 10 Aug 2021 09:34:25 +0100 Subject: [PATCH 11/25] kas_theme::dim: make checkbox inner size configurable --- crates/kas-theme/src/dim.rs | 5 ++++- crates/kas-theme/src/flat_theme.rs | 1 + crates/kas-theme/src/shaded_theme.rs | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/kas-theme/src/dim.rs b/crates/kas-theme/src/dim.rs index 4d9fcaf1a..0185cdfcd 100644 --- a/crates/kas-theme/src/dim.rs +++ b/crates/kas-theme/src/dim.rs @@ -32,6 +32,8 @@ pub struct Parameters { pub frame_size: f32, /// Button frame size (non-flat outer region) pub button_frame: f32, + /// Checkbox inner size in Points + pub checkbox_inner: f32, /// Scrollbar minimum handle size pub scrollbar_size: Vec2, /// Slider minimum handle size @@ -87,7 +89,8 @@ impl Dimensions { text_margin, frame, button_frame: (params.button_frame * scale_factor).cast_nearest(), - checkbox: i32::conv_nearest(9.0 * dpp) + 2 * (i32::from(inner_margin) + frame), + checkbox: i32::conv_nearest(params.checkbox_inner * dpp) + + 2 * (i32::from(inner_margin) + frame), scrollbar: Size::from(params.scrollbar_size * scale_factor), slider: Size::from(params.slider_size * scale_factor), progress_bar: Size::from(params.progress_bar * scale_factor), diff --git a/crates/kas-theme/src/flat_theme.rs b/crates/kas-theme/src/flat_theme.rs index aef47efc6..adfe49d68 100644 --- a/crates/kas-theme/src/flat_theme.rs +++ b/crates/kas-theme/src/flat_theme.rs @@ -78,6 +78,7 @@ const DIMS: dim::Parameters = dim::Parameters { text_margin: 2.0, frame_size: 4.0, button_frame: 2.4, + checkbox_inner: 5.0, scrollbar_size: Vec2::splat(8.0), slider_size: Vec2(12.0, 25.0), progress_bar: Vec2::splat(12.0), diff --git a/crates/kas-theme/src/shaded_theme.rs b/crates/kas-theme/src/shaded_theme.rs index ff9200bd7..f3f0813e7 100644 --- a/crates/kas-theme/src/shaded_theme.rs +++ b/crates/kas-theme/src/shaded_theme.rs @@ -61,6 +61,7 @@ const DIMS: dim::Parameters = dim::Parameters { text_margin: 2.0, frame_size: 5.0, button_frame: 5.0, + checkbox_inner: 9.0, scrollbar_size: Vec2::splat(8.0), slider_size: Vec2(12.0, 25.0), progress_bar: Vec2::splat(12.0), From fff62f7e4ad12e0296e5b6f84df7bb5deb02bead Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 10 Aug 2021 11:28:05 +0100 Subject: [PATCH 12/25] Rename vertex shaders: give specific names --- crates/kas-wgpu/src/draw/flat_round.rs | 2 +- crates/kas-wgpu/src/draw/shaded_round.rs | 2 +- crates/kas-wgpu/src/draw/shaded_square.rs | 2 +- crates/kas-wgpu/src/draw/shaders.rs | 18 +++++++++--------- .../{scaled_122.vert => flat_round.vert} | 0 ...caled_122.vert.spv => flat_round.vert.spv} | Bin .../{scaled_222.vert => shaded_round.vert} | 0 ...led_222.vert.spv => shaded_round.vert.spv} | Bin .../{scaled_2.vert => shaded_square.vert} | 0 ...aled_2.vert.spv => shaded_square.vert.spv} | Bin 10 files changed, 12 insertions(+), 12 deletions(-) rename crates/kas-wgpu/src/draw/shaders/{scaled_122.vert => flat_round.vert} (100%) rename crates/kas-wgpu/src/draw/shaders/{scaled_122.vert.spv => flat_round.vert.spv} (100%) rename crates/kas-wgpu/src/draw/shaders/{scaled_222.vert => shaded_round.vert} (100%) rename crates/kas-wgpu/src/draw/shaders/{scaled_222.vert.spv => shaded_round.vert.spv} (100%) rename crates/kas-wgpu/src/draw/shaders/{scaled_2.vert => shaded_square.vert} (100%) rename crates/kas-wgpu/src/draw/shaders/{scaled_2.vert.spv => shaded_square.vert.spv} (100%) diff --git a/crates/kas-wgpu/src/draw/flat_round.rs b/crates/kas-wgpu/src/draw/flat_round.rs index 5f62ddc4b..a38c4d3ba 100644 --- a/crates/kas-wgpu/src/draw/flat_round.rs +++ b/crates/kas-wgpu/src/draw/flat_round.rs @@ -56,7 +56,7 @@ impl Pipeline { label: Some("FR render_pipeline"), layout: Some(&pipeline_layout), vertex: wgpu::VertexState { - module: &shaders.vert_122, + module: &shaders.vert_flat_round, entry_point: "main", buffers: &[wgpu::VertexBufferLayout { array_stride: size_of::() as wgpu::BufferAddress, diff --git a/crates/kas-wgpu/src/draw/shaded_round.rs b/crates/kas-wgpu/src/draw/shaded_round.rs index 0a258612a..527e0cbdb 100644 --- a/crates/kas-wgpu/src/draw/shaded_round.rs +++ b/crates/kas-wgpu/src/draw/shaded_round.rs @@ -52,7 +52,7 @@ impl Pipeline { label: Some("SR render_pipeline"), layout: Some(&pipeline_layout), vertex: wgpu::VertexState { - module: &shaders.vert_222, + module: &shaders.vert_shaded_round, entry_point: "main", buffers: &[wgpu::VertexBufferLayout { array_stride: size_of::() as wgpu::BufferAddress, diff --git a/crates/kas-wgpu/src/draw/shaded_square.rs b/crates/kas-wgpu/src/draw/shaded_square.rs index 8214c09f7..d6513db1a 100644 --- a/crates/kas-wgpu/src/draw/shaded_square.rs +++ b/crates/kas-wgpu/src/draw/shaded_square.rs @@ -41,7 +41,7 @@ impl Pipeline { label: Some("SS render_pipeline"), layout: Some(&pipeline_layout), vertex: wgpu::VertexState { - module: &shaders.vert_2, + module: &shaders.vert_shaded_square, entry_point: "main", buffers: &[wgpu::VertexBufferLayout { array_stride: size_of::() as wgpu::BufferAddress, diff --git a/crates/kas-wgpu/src/draw/shaders.rs b/crates/kas-wgpu/src/draw/shaders.rs index e2339c715..5257aa8a5 100644 --- a/crates/kas-wgpu/src/draw/shaders.rs +++ b/crates/kas-wgpu/src/draw/shaders.rs @@ -9,9 +9,9 @@ use wgpu::{include_spirv, ShaderModule}; /// Shader manager pub struct ShaderManager { - pub vert_122: ShaderModule, - pub vert_2: ShaderModule, - pub vert_222: ShaderModule, + pub vert_flat_round: ShaderModule, + pub vert_shaded_square: ShaderModule, + pub vert_shaded_round: ShaderModule, pub vert_image: ShaderModule, pub vert_glyph: ShaderModule, pub frag_flat_round: ShaderModule, @@ -29,9 +29,9 @@ macro_rules! create { impl ShaderManager { pub fn new(device: &wgpu::Device) -> Self { - let vert_122 = create!(device, "shaders/scaled_122.vert.spv"); - let vert_2 = create!(device, "shaders/scaled_2.vert.spv"); - let vert_222 = create!(device, "shaders/scaled_222.vert.spv"); + let vert_flat_round = create!(device, "shaders/flat_round.vert.spv"); + let vert_shaded_square = create!(device, "shaders/shaded_square.vert.spv"); + let vert_shaded_round = create!(device, "shaders/shaded_round.vert.spv"); let vert_image = create!(device, "shaders/image.vert.spv"); let vert_glyph = create!(device, "shaders/glyph.vert.spv"); @@ -44,9 +44,9 @@ impl ShaderManager { ShaderManager { vert_image, vert_glyph, - vert_122, - vert_2, - vert_222, + vert_flat_round, + vert_shaded_square, + vert_shaded_round, frag_flat_round, frag_shaded_square, frag_shaded_round, diff --git a/crates/kas-wgpu/src/draw/shaders/scaled_122.vert b/crates/kas-wgpu/src/draw/shaders/flat_round.vert similarity index 100% rename from crates/kas-wgpu/src/draw/shaders/scaled_122.vert rename to crates/kas-wgpu/src/draw/shaders/flat_round.vert diff --git a/crates/kas-wgpu/src/draw/shaders/scaled_122.vert.spv b/crates/kas-wgpu/src/draw/shaders/flat_round.vert.spv similarity index 100% rename from crates/kas-wgpu/src/draw/shaders/scaled_122.vert.spv rename to crates/kas-wgpu/src/draw/shaders/flat_round.vert.spv diff --git a/crates/kas-wgpu/src/draw/shaders/scaled_222.vert b/crates/kas-wgpu/src/draw/shaders/shaded_round.vert similarity index 100% rename from crates/kas-wgpu/src/draw/shaders/scaled_222.vert rename to crates/kas-wgpu/src/draw/shaders/shaded_round.vert diff --git a/crates/kas-wgpu/src/draw/shaders/scaled_222.vert.spv b/crates/kas-wgpu/src/draw/shaders/shaded_round.vert.spv similarity index 100% rename from crates/kas-wgpu/src/draw/shaders/scaled_222.vert.spv rename to crates/kas-wgpu/src/draw/shaders/shaded_round.vert.spv diff --git a/crates/kas-wgpu/src/draw/shaders/scaled_2.vert b/crates/kas-wgpu/src/draw/shaders/shaded_square.vert similarity index 100% rename from crates/kas-wgpu/src/draw/shaders/scaled_2.vert rename to crates/kas-wgpu/src/draw/shaders/shaded_square.vert diff --git a/crates/kas-wgpu/src/draw/shaders/scaled_2.vert.spv b/crates/kas-wgpu/src/draw/shaders/shaded_square.vert.spv similarity index 100% rename from crates/kas-wgpu/src/draw/shaders/scaled_2.vert.spv rename to crates/kas-wgpu/src/draw/shaders/shaded_square.vert.spv From 2a3d8982cad9812a8f9945b0857f312912a49ab0 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 10 Aug 2021 11:53:06 +0100 Subject: [PATCH 13/25] DrawPipe: do not pass (dummy) size on window construction --- crates/kas-wgpu/src/draw/custom.rs | 6 ++++-- crates/kas-wgpu/src/draw/draw_pipe.rs | 15 +++++---------- crates/kas-wgpu/src/window.rs | 4 +--- examples/mandlebrot/mandlebrot.rs | 2 +- 4 files changed, 11 insertions(+), 16 deletions(-) diff --git a/crates/kas-wgpu/src/draw/custom.rs b/crates/kas-wgpu/src/draw/custom.rs index e607e8c04..8649594de 100644 --- a/crates/kas-wgpu/src/draw/custom.rs +++ b/crates/kas-wgpu/src/draw/custom.rs @@ -61,7 +61,9 @@ pub trait CustomPipe: 'static { type Window: CustomWindow; /// Construct a window associated with this pipeline - fn new_window(&self, device: &wgpu::Device, size: Size) -> Self::Window; + /// + /// Note: [`Self::resize`] will be called before usage. + fn new_window(&self, device: &wgpu::Device) -> Self::Window; /// Called whenever the window is resized fn resize( @@ -164,7 +166,7 @@ pub enum Void {} /// A dummy implementation (does nothing) impl CustomPipe for () { type Window = (); - fn new_window(&self, _: &wgpu::Device, _: Size) -> Self::Window {} + fn new_window(&self, _: &wgpu::Device) -> Self::Window {} fn resize(&self, _: &mut Self::Window, _: &wgpu::Device, _: &wgpu::Queue, _: Size) {} } diff --git a/crates/kas-wgpu/src/draw/draw_pipe.rs b/crates/kas-wgpu/src/draw/draw_pipe.rs index b251e32a6..4ea6242d5 100644 --- a/crates/kas-wgpu/src/draw/draw_pipe.rs +++ b/crates/kas-wgpu/src/draw/draw_pipe.rs @@ -12,7 +12,7 @@ use super::*; use kas::cast::Cast; use kas::draw::color::Rgba; use kas::draw::*; -use kas::geom::{Coord, Quad, Rect, Size, Vec2}; +use kas::geom::{Quad, Rect, Size, Vec2}; use kas::text::{Effect, TextDisplay}; use kas_theme::DrawShadedImpl; @@ -96,17 +96,12 @@ impl DrawPipe { } /// Construct per-window state - pub fn new_window(&self, size: Size) -> DrawWindow { - let vsize = Vec2::from(size); - let scale: Scale = [-0.5 * vsize.0, 0.5 * vsize.1, 2.0 / vsize.0, -2.0 / vsize.1]; - - let rect = Rect::new(Coord::ZERO, size); - - let custom = self.custom.new_window(&self.device, size); + pub fn new_window(&self) -> DrawWindow { + let custom = self.custom.new_window(&self.device); DrawWindow { - scale, - clip_regions: vec![(rect, Offset::ZERO)], + scale: Default::default(), + clip_regions: vec![Default::default()], images: Default::default(), shaded_square: Default::default(), shaded_round: Default::default(), diff --git a/crates/kas-wgpu/src/window.rs b/crates/kas-wgpu/src/window.rs index f89a196ce..23dfcfe55 100644 --- a/crates/kas-wgpu/src/window.rs +++ b/crates/kas-wgpu/src/window.rs @@ -53,9 +53,7 @@ impl>> Window { ) -> Result { let time = Instant::now(); - // Create draw immediately (with Size::ZERO) to find ideal window size let scale_factor = shared.scale_factor as f32; - let mut draw = shared.draw.draw.new_window(Size::ZERO); let mut theme_window = shared.theme.new_window(scale_factor); let mut mgr = ManagerState::new(shared.config.clone()); @@ -87,7 +85,7 @@ impl>> Window { let size: Size = window.inner_size().into(); info!("Constucted new window with size {:?}", size); - // draw was initially created with Size::ZERO; we must resize + let mut draw = shared.draw.draw.new_window(); shared.draw.draw.resize(&mut draw, size); let surface = unsafe { shared.instance.create_surface(&window) }; diff --git a/examples/mandlebrot/mandlebrot.rs b/examples/mandlebrot/mandlebrot.rs index 06dc36962..0cdbd07c2 100644 --- a/examples/mandlebrot/mandlebrot.rs +++ b/examples/mandlebrot/mandlebrot.rs @@ -147,7 +147,7 @@ struct PipeWindow { impl CustomPipe for Pipe { type Window = PipeWindow; - fn new_window(&self, _: &wgpu::Device, _: Size) -> Self::Window { + fn new_window(&self, _: &wgpu::Device) -> Self::Window { let push_constants = PushConstants { p: DVec2::splat(0.0), q: DVec2::splat(1.0), From 2de01d76ce5e36eccc125024d0af6def2ac89c78 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 10 Aug 2021 14:10:28 +0100 Subject: [PATCH 14/25] Change flat/shaded round antialias pattern Using a grid-aligned pattern is better for small circles. --- crates/kas-core/src/geom/vector.rs | 11 +++++++++++ crates/kas-wgpu/src/draw/draw_pipe.rs | 9 +++------ crates/kas-wgpu/src/draw/flat_round.rs | 18 +++++++++--------- crates/kas-wgpu/src/draw/shaded_round.rs | 4 ++-- .../kas-wgpu/src/draw/shaders/flat_round.frag | 4 ++-- .../src/draw/shaders/flat_round.frag.spv | Bin 3136 -> 2960 bytes .../src/draw/shaders/shaded_round.frag | 4 ++-- .../src/draw/shaders/shaded_round.frag.spv | Bin 5200 -> 5020 bytes 8 files changed, 29 insertions(+), 21 deletions(-) diff --git a/crates/kas-core/src/geom/vector.rs b/crates/kas-core/src/geom/vector.rs index 7bdeefe7c..82cd05ffb 100644 --- a/crates/kas-core/src/geom/vector.rs +++ b/crates/kas-core/src/geom/vector.rs @@ -146,6 +146,9 @@ macro_rules! impl_vec2 { /// Zero pub const ZERO: $T = $T::splat(0.0); + /// One + pub const ONE: $T = $T::splat(1.0); + /// Positive infinity pub const INFINITY: $T = $T::splat(<$f>::INFINITY); @@ -335,6 +338,14 @@ macro_rules! impl_vec2 { } } + impl Div<$T> for $f { + type Output = $T; + #[inline] + fn div(self, rhs: $T) -> Self::Output { + $T(self / rhs.0, self / rhs.1) + } + } + impl From<($f, $f)> for $T { #[inline] fn from(arg: ($f, $f)) -> Self { diff --git a/crates/kas-wgpu/src/draw/draw_pipe.rs b/crates/kas-wgpu/src/draw/draw_pipe.rs index 4ea6242d5..50127b0ac 100644 --- a/crates/kas-wgpu/src/draw/draw_pipe.rs +++ b/crates/kas-wgpu/src/draw/draw_pipe.rs @@ -125,12 +125,9 @@ impl DrawPipe { window.clip_regions[0].0.size = size; let vsize = Vec2::from(size); - window.scale = [ - -0.5 * vsize.0, - -0.5 * vsize.1, - 2.0 / vsize.0, - -2.0 / vsize.1, - ]; + let off = vsize * -0.5; + let scale = 2.0 / vsize; + window.scale = [off.0, off.1, scale.0, -scale.1]; self.custom .resize(&mut window.custom, &self.device, &self.queue, size); diff --git a/crates/kas-wgpu/src/draw/flat_round.rs b/crates/kas-wgpu/src/draw/flat_round.rs index a38c4d3ba..377a0b830 100644 --- a/crates/kas-wgpu/src/draw/flat_round.rs +++ b/crates/kas-wgpu/src/draw/flat_round.rs @@ -12,8 +12,8 @@ use kas::geom::{Quad, Vec2}; use std::mem::size_of; /// Offset relative to the size of a pixel used by the fragment shader to -/// implement multi-sampling. -const OFFSET: f32 = 0.125; +/// implement 4x multi-sampling. The pattern is defined by the fragment shader. +const AA_OFFSET: f32 = 0.5 * std::f32::consts::FRAC_1_SQRT_2; // NOTE(opt): in theory we could reduce data transmission to the GPU by 1/3 by // sending quads (two triangles) as instances in triangle-strip mode. The @@ -130,7 +130,7 @@ impl Window { let na = -nb; // Since we take the mid-point, all offsets are uniform - let p = Vec2::splat(OFFSET / radius); + let p = Vec2::splat(AA_OFFSET / radius); let p1my = p1 - vy; let p1py = p1 + vy; @@ -180,13 +180,13 @@ impl Window { let mid = (aa + bb) * 0.5; let n0 = Vec2::splat(0.0); - let nb = (bb - aa).sign(); + let nb = Vec2::ONE; // = (bb - aa).sign(); let na = -nb; let nab = Vec2(na.0, nb.1); let nba = Vec2(nb.0, na.1); // Since we take the mid-point, all offsets are uniform - let p = nb / (bb - mid) * OFFSET; + let p = nb / (bb - mid) * AA_OFFSET; let aa = Vertex::new2(aa, col, inner, na, p); let ab = Vertex::new2(ab, col, inner, nab, p); @@ -249,10 +249,10 @@ impl Window { let n0a = Vec2(0.0, na.1); let n0b = Vec2(0.0, nb.1); - let paa = na / (aa - cc) * OFFSET; - let pab = nab / (ab - cd) * OFFSET; - let pba = nba / (ba - dc) * OFFSET; - let pbb = nb / (bb - dd) * OFFSET; + let paa = na / (aa - cc) * AA_OFFSET; + let pab = nab / (ab - cd) * AA_OFFSET; + let pba = nba / (ba - dc) * AA_OFFSET; + let pbb = nb / (bb - dd) * AA_OFFSET; // We must add corners separately to ensure correct interpolation of dir // values, hence need 16 points: diff --git a/crates/kas-wgpu/src/draw/shaded_round.rs b/crates/kas-wgpu/src/draw/shaded_round.rs index 527e0cbdb..efeafb0fa 100644 --- a/crates/kas-wgpu/src/draw/shaded_round.rs +++ b/crates/kas-wgpu/src/draw/shaded_round.rs @@ -13,8 +13,8 @@ use std::f32::consts::FRAC_PI_2; use std::mem::size_of; /// Offset relative to the size of a pixel used by the fragment shader to -/// implement multi-sampling. -const OFFSET: f32 = 0.125; +/// implement 4x multi-sampling. The pattern is defined by the fragment shader. +const OFFSET: f32 = 0.5 * std::f32::consts::FRAC_1_SQRT_2; #[repr(C)] #[derive(Clone, Copy, Debug)] diff --git a/crates/kas-wgpu/src/draw/shaders/flat_round.frag b/crates/kas-wgpu/src/draw/shaders/flat_round.frag index e540dbea2..efae18976 100644 --- a/crates/kas-wgpu/src/draw/shaders/flat_round.frag +++ b/crates/kas-wgpu/src/draw/shaders/flat_round.frag @@ -23,8 +23,8 @@ float sample_a(vec2 pos) { void main() { // Multi-sample alpha to avoid ugly aliasing. - vec2 off1 = vec2(off.x, 3.0 * off.y); - vec2 off2 = vec2(3.0 * off.x, off.y); + vec2 off1 = vec2(off.x, 0.0); + vec2 off2 = vec2(0.0, off.y); float alpha = sample_a(pos + off1) + sample_a(pos - off1) + sample_a(pos + off2) diff --git a/crates/kas-wgpu/src/draw/shaders/flat_round.frag.spv b/crates/kas-wgpu/src/draw/shaders/flat_round.frag.spv index be16d4cbcfdea3ba6984541876f716d6aa37b798..5e9b85c74bd9c8c62ce2b8272a328436ebbd0b23 100644 GIT binary patch literal 2960 zcmZ9NTW^y`5QaC2%^{Q=$f;056V56nEtF#+Ax;2uFeDIYpaHC}iBnuTwq+Zn-nFXw zTPprTullQcQ`Gm_ZwC#mG~RdKnVs2hc6U6`e{6RMePJ-{53fQ#Mnk`t5cY*#aV}TZ zDs$c5*4%}Q-{LV82BITA!&+I;jO=9fCWgb3uO$~HE0RZ&5v{>T$%F=!A%uSvpb++k za-~{&yj1Ph+F2*-)vDds*;cJnZT<91ZL`K%F2-`4Qk@%W;<<#%TB-DK7UPmQTrRz+-`M+3#v@S z=QTy!0nJ_Q3me~BZ#HY4Xe)%TG`F_5&uNOj)IoamrFg7o;BL9v*b&?Eaz3Q z%CQq|g|P66e)ALk-bZ>d*1h$nx7=#9*qZVe<2h`1vY(AC>pS^=2AFSVfca(ycqoSv z4?8^KFg0P|Kbgab4?29vVd};xry3p+=03508iNKHo&lcCVZ_v#0Z)w?!~(O18;WgC zGXwlh4kL~iIq~s868_Hla6SyyayATdfXTrf#&$_F1AIA$5npkb^JL)jeGVh$zA@mh z=P=@VhZh{a;qaovC5M+BUUrx}!ywnK97cTG;j+Vb9KP!?ca1@u`#Frb;xO-?LA}8K z9O(xPY+!F&icr^ort>KnK#;7Orfnr9?a+8ezJ z9ovlbJ(}T=S?PNXMg^##*UMm>*vMwl4vjkxH%6FAek)98Hn1I^^1SF*2%nyC>y{^*=3 z9QIYstTj72=W6jD3lk52tHaZzUs7M9zT{%y^RJkqW^z$m-n#7_owsW`HRqk0j-9vW zb>5HHc?VwSKBJeEl`}Xip+20|y!OD}=_Bx~^1+v00!N(}v}^VVXEDwR6NB@$81xx< zi$SkpJv=e^E;#(jL0{oqOsBVy=l8S+`U^hrtmnJouFB4y=`-|qc#A>5@iFN+#QY=0 zr0?JZPfThDXEEtN#Dr%bo z1e@h43;R5Gq?57hdxFwY^>pa!I6_YPLJY#ujqDix1S^q zp25BEmy}c=?$Zwv{GUpQLCw}B@TSw#$n$5aDSZte_(zGOzmbb!+=eh5IgO*=!Lf%` z-6Zx*-(x-g*on`#@s6?mrwCUhyhrv&O&IjJ%ktx04N7>MpJ}$YxnG#Oiax6OK+^4e zhNQF3^x>rQova&?-~-QohzCdQh&LgD8<$wECKGQypC_Lw=W|dP-p=%pFzevS!#?3G z=Ctr(r}LkL&)?byeRoEJ54^3J74|;Iq{AJR{FT-n7oL$|d#B1$+fx#FdiF`ld({+< G`u`7R;JqvW literal 3136 zcmZ9NYjcxT5XTQ~g3wAYP>LXz7UVLbRj^PHDM>2?G0;Ns3YtDmQi+o$nItgdI~~W* z;`kkW<)`wEjQ`(x&N^#$W^?{~IlFuIoM$sWcJ7T3_JxUXC^SP(vtdk{5GKR^xK^rL z)uq9(v9x^cLp-L!cyz>PT009`;k~TY!EjRip7;~-m*TI*GunfXk_n9~LkNE+by6tPcnHOyE=5*r-(R*6O`pZ7}?)-K@1+oo21k z>dUM3O2rq#0q581)Y~r`-k~TDUuRM0n^YZxY_F$q*`-&zS8qu!s=f)Wz3xD`pw2{m zRZFxT);dsK*f?ve(`ojjtq|VT+TGo~q9yv$2g%WQImanZA&@I;_g-Ylmws8!5?Jln zi?%|zJ0gERB0v70T#SA1z8tQ1+g(ai{$jj`-G26iDJwcB=ZC2pibjzKxbV_A`gScev*8w!?gP5OwY3Fygwyjf9Wr_PD=A`SP~F^FsTz zE{Kn*Hf9?#wgt%tw4#F-B_Gs^9X|beRui25gXN&iZF!AswKYe_k@Xwo;v7jMNBSimgl~(&%;dQd{+AdVSLb&hc|%E@>GS%gWmEmC&`7) z@-Q!b9%d$a>^#g(e9)7Jw}sB~Fh9wI-tue-lM5Src+cp_`BW=2lJ99lUjyILv!t`x z$#*s;E~`Jh-|xiuKNk~&o-t3+o6JllkG-jFVSLa(PJPaV$px8iM;IMBO;=AkYS`3E zqUMH}{rF?w7IQY{2DX0`;f9#+pZe$t#Ee~$AK&?em|5_qR+|Nfgn6sTvsw=)+3sgb zGW$%PPBQ0Y-;5X^^wdK?L{&A^WqEQ*Xk)c G`u{JvGs*1$ diff --git a/crates/kas-wgpu/src/draw/shaders/shaded_round.frag b/crates/kas-wgpu/src/draw/shaders/shaded_round.frag index 2cf41e3ce..41e4674b4 100644 --- a/crates/kas-wgpu/src/draw/shaders/shaded_round.frag +++ b/crates/kas-wgpu/src/draw/shaders/shaded_round.frag @@ -27,8 +27,8 @@ float sample_a(vec2 dir) { void main() { // Multi-sample alpha to avoid ugly aliasing. A single colour sample is adequate. - vec2 off1 = vec2(off.x, 3.0 * off.y); - vec2 off2 = vec2(3.0 * off.x, off.y); + vec2 off1 = vec2(off.x, 0.0); + vec2 off2 = vec2(0.0, off.y); float alpha = sample_a(dir + off1) + sample_a(dir - off1) + sample_a(dir + off2) diff --git a/crates/kas-wgpu/src/draw/shaders/shaded_round.frag.spv b/crates/kas-wgpu/src/draw/shaders/shaded_round.frag.spv index 7fbe5cc1cb54f006346eb0bbbeb6088566a565b1..4c3418e3cd12ff03f0ad4aa26bc4587a8dda9621 100644 GIT binary patch literal 5020 zcmZ9O=XaD<5XN8F4JDyhDZ)k&5D=vI5?Z205$FJEl#E%X)ooAbrCLQ`{JzUO>Lb7Oyzm~vvO>*}g&59S+td-KKqE1k{x&i3x+ zd{cX$qS^Q%bJiourkJ7kw>eC5(gEu7WL z1iW4<_-05KH730QRHrY1H z-ZRQRILiJ)wsMumctmzO#!PZT_^O1OUrV<|oR{toI2-n=(9|(d6v4bY#CP}fb)~V{ z&>vfL$TK9}7;stG;9h3p1#Q4l|B@>uC5-PigEgbqjk2ow)G!QlQE|IDXqL^ z;jHuw^joT=T7LG324-JqVD^Ouo|3|Vr#d{%VfKwi{G1d9JkR0z4li(+eWuZuJ*HJ_ zoxqDEnP6v9Bc zKN@|{rZC`h4s$PQ#54p1PVXq^fVUIh`I0Y_G&!uNFf?LX9By@(drc#zJ%s^t?`iOz zDGa#R;foG)-)Y3_Nem6lyFvpGq%hz?hc7wI`$QxDS_%Wc?(hwVzj64c!$S^_lyEk@ zQLG(}8n;py@NI|hL|miww)YCEMsJhZOI$o$x*yr_j(t$_rFNxkySI-@zD)Ai;U^A1 zE#Yi<3;md%m3*1xg~Kl$e&z6Mhu=8-*5P*%&(tiKN2S&#BMqJ-G)_7vnXB~}FO7{a zCwqc498xKJqBMSZ{L`ha&urN<1FwH-tD-$CHB0tf*{m0SaxD!0p*^!y^?k=LPWjyy zmkV}U_d{WFP?&S44pusLUNwhzyvy;<|6FXN^W^QV|HY5KCaOC`+JY<}C!X3zN@Gn;sRi@eS6 zi?{im@b zfPLk69=<-FkClI}y*Y!D^}p8l*m+&1|cGv5If5_rqO_khp2MK(D{V$Q9?#K4o2y@Ruy+l9#q&p4>V zcLKHWS)HB2z7F3E%+JQYTbLMl>To9Dtj=Cx>cCr_Dq(8vl~|p9!oJRa+0?Q591tc3 zo;sX0IID9=m^$!Qr&^d=_~^s=hNC9)t&za}qWSYieHyu(^dE}a~?hF2$WRg7i&PebrmJmmc6VmWj ztj{@N>w}Lz+GJ6~1l>9A^nk zp7GMX5<5$b>!O6Zww`^$%we(wpVco4Q~zF^Prop+@Q=iidq6^dd^QI-%P}bIYh98} zttk?G^kF^W|I)Z^{Ae5hHDT7qa$Xmv&yhH;8^XlUjQd6yj#~BFjmy$ECB)(*2eq$C z!;^bh`j%uwQm0=!`rM8jJdJ!~CB);uBOwQ8>Y?=alKYYe5{r2h`R8%Gk7d&jo^>S8 z6A88OF|HwLILq-&7|zb_kHU=exr7+@^@Rl9?3co8C3YTP2@?Zv>-1Wf+%)6f2*WW~ zFj rF#X`E!#LqAet|IDZ;I#sE|S14l>Dp}VNEI}@QWom$$wf4IM(fd$+cz@ literal 5200 zcmZ9O*LPJ_5XMi)O@Pq5^hA&%NRui82`!XB02LI0%O$xfkmQEk&_M`Ynn)Fp?u+j} zxqR}UvMhD^{r1_znstXY%s1c6o|(PRJ}0-l-?aWoQkGODLz178R7NEI#3ad}q%zq0 zhR+)26?>cKEnc#KjG;++NF-;NR%T?;&RlyJff>?e(pKpW=@aR2tszIvgv!++Nq$#> zOfoR3Z^+i|TAMBAyK_Cc-h8&$mTS)UWDAE5=bL(qesjYA#~ag$pe$3oXXp<%ih(6vuU$WU2gIM|WFJmL8mu^`I}??+md_ zQd{D0Eb$vk{Lkg9*1H+Ml%LL6o*WQ9Ev09ZY+J-Fvb_Ok!n4XXA3jzT!M=`)?<(|k zrn#AL}A!kVn1LjU4 z@Z2YanZV4%J4$T1ECODU!hk<u{aJYaL$a@OpJRf1_7UN_@u+99Ok=(kbfqH0iSjFoWtKZ%r^;P?Zp%Z ze97U<4qtKjs>6KC5bE$PLpVDyXNM5GnZkf?Iea_fO;!)ZK z`>4^J<+9+hLY1=B(s7!nzbrnnYWV|X;m{iS17(TB6CWXKYsSbQ6?pw8nG^ldsr$|! zC%-JlsWmCYFRU4@u9F=itFHGjVIxdZ%N^Kt$*dB3*A-&o@F{rCBN-_55!-*4|9DDj(0{1)dk|54{( z5bi7SuSLI3yPhdLOFBc!-Cd+!4R(FALY43&N;H@sdHK+@3>pm7PooBH)cLM$N6#=2c?sw@PjoeTuxdh<^4P;t(Fc}gxDb|v8ht>=)v~` z-g-0()5F%}g>4Nn)-=h&v$vVDZPHe$-+z1LE$48|@%uj_4&Hiq2vghqPGRP=y>$sQ z%Xlfd#O*s!5T+hEcAnkB%t4H~TV&zDM`e4Y)~hH??_aei?p3c8u3E~yIxdTFuZSI! z!f}_t)Zwn2kS>cpXMR#jUpvoJ!t7y)l$iBDElmIG@!6gcCKvvWIBK7jQlFUZ0nTci z6ZXBnkx#FoQev#(JmLS++%`Yf=D#S+*;vg>!mQaD=ejIR4r1IDVK{p2&`mopdsRv< zF>27ePZplq*JW=?Z%7;Umz6cQA_tF9ub-5B;w2yL From cd6dec733f1e1aeb56a357700c2209ece365bd49 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 10 Aug 2021 16:07:25 +0100 Subject: [PATCH 15/25] Fix circle inner radius and FlatTheme::radiobox --- crates/kas-theme/src/flat_theme.rs | 3 ++- crates/kas-wgpu/src/draw/flat_round.rs | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/kas-theme/src/flat_theme.rs b/crates/kas-theme/src/flat_theme.rs index adfe49d68..da4d3615a 100644 --- a/crates/kas-theme/src/flat_theme.rs +++ b/crates/kas-theme/src/flat_theme.rs @@ -473,7 +473,8 @@ where } let col = self.cols.nav_region(state).unwrap_or(self.cols.frame); - let r = 1.0 - 2.0 * self.window.dims.button_frame as f32 / rect.size.0 as f32; + const F: f32 = 2.0 * (1.0 - BG_SHRINK_FACTOR); // match checkbox frame + let r = 1.0 - F * self.window.dims.button_frame as f32 / rect.size.0 as f32; self.draw.circle(outer, r, col); if let Some(col) = self.cols.check_mark_state(state, checked) { diff --git a/crates/kas-wgpu/src/draw/flat_round.rs b/crates/kas-wgpu/src/draw/flat_round.rs index 377a0b830..5154f8414 100644 --- a/crates/kas-wgpu/src/draw/flat_round.rs +++ b/crates/kas-wgpu/src/draw/flat_round.rs @@ -163,7 +163,7 @@ impl Window { ]); } - /// Bounds on input: `0 ≤ inner_radius ≤ 1`. + /// Bounds on input: `0 ≤ inner_radius ≤ 1`. pub fn circle(&mut self, pass: PassId, rect: Quad, inner_radius: f32, col: Rgba) { let aa = rect.a; let bb = rect.b; @@ -173,7 +173,8 @@ impl Window { return; } - let inner = inner_radius.max(0.0).min(1.0); + let inner = inner_radius.clamp(0.0, 1.0); + let inner = inner * inner; // shader compares to square let ab = Vec2(aa.0, bb.1); let ba = Vec2(bb.0, aa.1); From 88e52d8480882a1f8b6e3b3ac23ea0eb2334328c Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 10 Aug 2021 16:44:28 +0100 Subject: [PATCH 16/25] FlatTheme::slider: draw circular handle --- crates/kas-theme/src/flat_theme.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/crates/kas-theme/src/flat_theme.rs b/crates/kas-theme/src/flat_theme.rs index da4d3615a..ce8e25d67 100644 --- a/crates/kas-theme/src/flat_theme.rs +++ b/crates/kas-theme/src/flat_theme.rs @@ -77,10 +77,11 @@ const DIMS: dim::Parameters = dim::Parameters { inner_margin: 1.2, text_margin: 2.0, frame_size: 4.0, + // NOTE: visual thickness is (button_frame * scale_factor).round() * (1 - BG_SHRINK_FACTOR) button_frame: 2.4, checkbox_inner: 5.0, scrollbar_size: Vec2::splat(8.0), - slider_size: Vec2(12.0, 25.0), + slider_size: Vec2(16.0, 16.0), progress_bar: Vec2::splat(12.0), }; @@ -506,8 +507,20 @@ where let col = self.cols.frame; self.draw.rounded_frame(outer, inner, 0.0, col); - // handle - self.draw_handle(h_rect, state); + // handle; force it to be square + let size = Size::splat(h_rect.size.0.min(h_rect.size.1)); + let offset = Offset::from((h_rect.size - size) / 2); + let outer = Quad::from(Rect::new(h_rect.pos + offset, size)); + + let col = if state.nav_focus && !state.disabled { + self.cols.accent_soft + } else { + self.cols.background + }; + let col = ColorsLinear::adjust_for_state(col, state); + self.draw.circle(outer, 0.0, col); + let col = self.cols.nav_region(state).unwrap_or(self.cols.frame); + self.draw.circle(outer, 14.0 / 16.0, col); } fn progress_bar(&mut self, rect: Rect, dir: Direction, _: InputState, value: f32) { From 0e359fa61c9a56aaee8dc76bc6b716594d16ee57 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Tue, 10 Aug 2021 17:03:44 +0100 Subject: [PATCH 17/25] FlatTheme::slider: colour first part of track --- crates/kas-theme/src/flat_theme.rs | 27 +++++++++++++++++++++------ examples/gallery.rs | 2 +- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/crates/kas-theme/src/flat_theme.rs b/crates/kas-theme/src/flat_theme.rs index ce8e25d67..b5706b556 100644 --- a/crates/kas-theme/src/flat_theme.rs +++ b/crates/kas-theme/src/flat_theme.rs @@ -499,13 +499,28 @@ where fn slider(&mut self, rect: Rect, h_rect: Rect, dir: Direction, state: InputState) { // track let mut outer = Quad::from(rect); - outer = match dir.is_horizontal() { - true => outer.shrink_vec(Vec2(0.0, outer.size().1 * (3.0 / 8.0))), - false => outer.shrink_vec(Vec2(outer.size().0 * (3.0 / 8.0), 0.0)), + let mid = Vec2::from(h_rect.pos + h_rect.size / 2); + let (mut first, mut second); + if dir.is_horizontal() { + outer = outer.shrink_vec(Vec2(0.0, outer.size().1 * (1.0 / 3.0))); + first = outer; + second = outer; + first.b.0 = mid.0; + second.a.0 = mid.0; + } else { + outer = outer.shrink_vec(Vec2(outer.size().0 * (1.0 / 3.0), 0.0)); + first = outer; + second = outer; + first.b.1 = mid.1; + second.a.1 = mid.1; }; - let inner = outer.shrink(outer.size().min_comp() / 2.0); - let col = self.cols.frame; - self.draw.rounded_frame(outer, inner, 0.0, col); + + let dist = outer.size().min_comp() / 2.0; + let inner = first.shrink(dist); + self.draw.rounded_frame(first, inner, 0.0, self.cols.accent); + let inner = second.shrink(dist); + self.draw + .rounded_frame(second, inner, 1.0 / 3.0, self.cols.frame); // handle; force it to be square let size = Size::splat(h_rect.size.0.min(h_rect.size.1)); diff --git a/examples/gallery.rs b/examples/gallery.rs index 254ab475e..412cd37af 100644 --- a/examples/gallery.rs +++ b/examples/gallery.rs @@ -253,7 +253,7 @@ fn main() -> Result<(), kas::shell::Error> { .on_select(|_, index| Some(Item::Combo((index + 1).cast()))), #[widget(row=8, col=0)] _ = Label::new("Slider"), #[widget(row=8, col=1, handler = handle_slider)] s = - Slider::::new(-2, 2, 1).with_value(0), + Slider::::new(0, 10, 1).with_value(0), #[widget(row=9, col=0)] _ = Label::new("ScrollBar"), #[widget(row=9, col=1, handler = handle_scroll)] sc: ScrollBar = ScrollBar::new().with_limits(100, 20), From 6771be0d89e25bee3d4cc2781f817a52fedcd2ab Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Wed, 11 Aug 2021 12:42:12 +0100 Subject: [PATCH 18/25] FlatTheme::editbox: new graphics --- crates/kas-theme/src/colors.rs | 2 +- crates/kas-theme/src/flat_theme.rs | 59 +++++++++++++++--------------- crates/kas-widgets/src/editbox.rs | 4 +- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/crates/kas-theme/src/colors.rs b/crates/kas-theme/src/colors.rs index 3b067a644..b73fbecb0 100644 --- a/crates/kas-theme/src/colors.rs +++ b/crates/kas-theme/src/colors.rs @@ -167,7 +167,7 @@ impl ColorsLinear { col.average() } else if state.depress { col.multiply(MULT_DEPRESS) - } else if state.hover { + } else if state.hover || state.char_focus { col.multiply(MULT_HIGHLIGHT).max(MIN_HIGHLIGHT) } else { col diff --git a/crates/kas-theme/src/flat_theme.rs b/crates/kas-theme/src/flat_theme.rs index b5706b556..b11ec6867 100644 --- a/crates/kas-theme/src/flat_theme.rs +++ b/crates/kas-theme/src/flat_theme.rs @@ -206,31 +206,6 @@ impl<'a, DS: DrawSharedImpl> DrawHandle<'a, DS> where DS::Draw: DrawRoundedImpl, { - /// Draw an edit box with optional navigation highlight. - /// Return the inner rect. - /// - /// - `outer`: define position via outer rect - /// - `bg_col`: colour of background - /// - `nav_col`: colour of navigation highlight, if visible - fn draw_edit_box(&mut self, outer: Rect, bg_col: Rgba, nav_col: Option) -> Quad { - let outer = Quad::from(outer); - let inner1 = outer.shrink(self.window.dims.frame as f32 * BG_SHRINK_FACTOR); - let inner2 = outer.shrink(self.window.dims.frame as f32); - - self.draw.rect(inner1, bg_col); - - // We draw over the inner rect, taking advantage of the fact that - // rounded frames get drawn after flat rects. - self.draw - .rounded_frame(outer, inner2, BG_SHRINK_FACTOR, self.cols.frame); - - if let Some(col) = nav_col { - self.draw.rounded_frame(inner1, inner2, 0.6, col); - } - - inner2 - } - /// Draw a handle (for slider, scrollbar) fn draw_handle(&mut self, rect: Rect, state: InputState) { let outer = Quad::from(rect); @@ -390,7 +365,7 @@ where let width = self.window.dims.font_marker_width; let pos = Vec2::from(pos); - let mut col = self.cols.text; + let mut col = self.cols.nav_focus; for cursor in text.text_glyph_pos(byte).rev() { let mut p1 = pos + Vec2::from(cursor.pos); let mut p2 = p1; @@ -441,9 +416,35 @@ where self.draw.rounded_frame(outer, inner, BG_SHRINK_FACTOR, col); } - fn edit_box(&mut self, rect: Rect, state: InputState) { - let bg_col = self.cols.bg_col(state); - self.draw_edit_box(rect, bg_col, self.cols.nav_region(state)); + fn edit_box(&mut self, rect: Rect, mut state: InputState) { + let outer = Quad::from(rect); + + state.depress = false; + let col = match state.error { + true => self.cols.edit_bg_error, + false => self.cols.edit_bg, + }; + let col = ColorsLinear::adjust_for_state(col, state); + if col != self.cols.background { + let inner = outer.shrink(self.window.dims.button_frame as f32 * BG_SHRINK_FACTOR); + self.draw.rect(inner, col); + } + + let inner = outer.shrink(self.window.dims.button_frame as f32); + self.draw + .rounded_frame(outer, inner, BG_SHRINK_FACTOR, self.cols.frame); + + let col = if state.nav_focus { + self.cols.nav_focus + } else { + // TODO: should this be a dedicated colour? + ColorsLinear::adjust_for_state(self.cols.accent.average(), state) + }; + let r = 0.5 * self.window.dims.button_frame as f32; + let y = outer.b.1 - r; + let a = Vec2(outer.a.0 + r, y); + let b = Vec2(outer.b.0 - r, y); + self.draw.rounded_line(a, b, r, col); } fn checkbox(&mut self, rect: Rect, checked: bool, state: InputState) { diff --git a/crates/kas-widgets/src/editbox.rs b/crates/kas-widgets/src/editbox.rs index 948179c2e..c7e2494a9 100644 --- a/crates/kas-widgets/src/editbox.rs +++ b/crates/kas-widgets/src/editbox.rs @@ -353,7 +353,7 @@ impl Layout for EditBox { if !self.rect().contains(coord) { return None; } - self.inner.find_id(coord).or(Some(self.id())) + Some(self.inner.id()) } fn draw(&self, draw_handle: &mut dyn DrawHandle, mgr: &event::ManagerState, disabled: bool) { @@ -407,7 +407,7 @@ impl std::ops::DerefMut for EditBox { /// line-wrapping and a larger vertical height). This mode is only recommended /// for short texts for performance reasons. #[derive(Clone, Default, Debug, Widget)] -#[widget(config(key_nav = true, cursor_icon = event::CursorIcon::Text))] +#[widget(config(key_nav = true, hover_highlight = true, cursor_icon = event::CursorIcon::Text))] #[handler(handle=noauto, generics = <> where G: EditGuard)] pub struct EditField { #[widget_core] From 63449a8653dbbc3fd7d869a462ab63fc4e7351c9 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Wed, 11 Aug 2021 14:46:28 +0100 Subject: [PATCH 19/25] FlatTheme::scrollbar: update appearance --- crates/kas-theme/src/flat_theme.rs | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/crates/kas-theme/src/flat_theme.rs b/crates/kas-theme/src/flat_theme.rs index b11ec6867..0ad0cfc9e 100644 --- a/crates/kas-theme/src/flat_theme.rs +++ b/crates/kas-theme/src/flat_theme.rs @@ -202,25 +202,6 @@ impl ThemeApi for FlatTheme { } } -impl<'a, DS: DrawSharedImpl> DrawHandle<'a, DS> -where - DS::Draw: DrawRoundedImpl, -{ - /// Draw a handle (for slider, scrollbar) - fn draw_handle(&mut self, rect: Rect, state: InputState) { - let outer = Quad::from(rect); - let thickness = outer.size().min_comp() / 2.0; - let inner = outer.shrink(thickness); - let col = self.cols.accent_soft_state(state); - self.draw.rounded_frame(outer, inner, 0.0, col); - - if let Some(col) = self.cols.nav_region(state) { - let outer = outer.shrink(thickness / 4.0); - self.draw.rounded_frame(outer, inner, 0.6, col); - } - } -} - impl<'a, DS: DrawSharedImpl> draw::DrawHandle for DrawHandle<'a, DS> where DS::Draw: DrawRoundedImpl, @@ -490,11 +471,17 @@ where // track let outer = Quad::from(rect); let inner = outer.shrink(outer.size().min_comp() / 2.0); - let col = self.cols.frame; + let mut col = self.cols.frame; + col.a = 0.5; // HACK self.draw.rounded_frame(outer, inner, 0.0, col); // handle - self.draw_handle(h_rect, state); + let outer = Quad::from(h_rect); + let r = outer.size().min_comp() * 0.125; + let outer = outer.shrink(r); + let inner = outer.shrink(3.0 * r); + let col = ColorsLinear::adjust_for_state(self.cols.frame, state); + self.draw.rounded_frame(outer, inner, 0.0, col); } fn slider(&mut self, rect: Rect, h_rect: Rect, dir: Direction, state: InputState) { From 65ba2132d5f011f678ecac9444b95c488407fba8 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Wed, 11 Aug 2021 14:52:16 +0100 Subject: [PATCH 20/25] ScrollBar: limit thickness --- crates/kas-widgets/src/scrollbar.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/kas-widgets/src/scrollbar.rs b/crates/kas-widgets/src/scrollbar.rs index 1c52fd58a..c09756c14 100644 --- a/crates/kas-widgets/src/scrollbar.rs +++ b/crates/kas-widgets/src/scrollbar.rs @@ -21,6 +21,7 @@ pub struct ScrollBar { core: CoreData, direction: D, // Terminology assumes vertical orientation: + width: i32, min_handle_len: i32, handle_len: i32, handle_value: i32, // contract: > 0 @@ -48,6 +49,7 @@ impl ScrollBar { ScrollBar { core: Default::default(), direction, + width: 0, min_handle_len: 0, handle_len: 0, handle_value: 1, @@ -207,11 +209,17 @@ impl Layout for ScrollBar { if self.direction.is_vertical() == axis.is_vertical() { SizeRules::new(min_len, min_len, margins, Stretch::High) } else { + self.width = size.1; SizeRules::fixed(size.1, margins) } } fn set_rect(&mut self, mgr: &mut Manager, rect: Rect, align: AlignHints) { + let mut ideal_size = Size::splat(self.width); + ideal_size.set_component(self.direction, i32::MAX); + let rect = align + .complete(Align::Centre, Align::Centre) + .aligned_rect(ideal_size, rect); self.core.rect = rect; self.handle.set_rect(mgr, rect, align); let _ = self.update_handle(); From dd6c5269bf1cbe5245925ef8515c00ce798eb641 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Wed, 11 Aug 2021 15:18:05 +0100 Subject: [PATCH 21/25] ScrollBars>: draw contents under scrollbars This requires the min_spec feature! --- crates/kas-widgets/src/scrollbar.rs | 50 ++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/crates/kas-widgets/src/scrollbar.rs b/crates/kas-widgets/src/scrollbar.rs index c09756c14..70460c4f2 100644 --- a/crates/kas-widgets/src/scrollbar.rs +++ b/crates/kas-widgets/src/scrollbar.rs @@ -499,6 +499,17 @@ impl ScrollBars { pub fn inner_mut(&mut self) -> &mut W { &mut self.inner } + + fn draw_(&self, draw_handle: &mut dyn DrawHandle, mgr: &event::ManagerState, disabled: bool) { + let disabled = disabled || self.is_disabled(); + if self.show_bars.0 { + self.horiz_bar.draw(draw_handle, mgr, disabled); + } + if self.show_bars.1 { + self.vert_bar.draw(draw_handle, mgr, disabled); + } + self.inner.draw(draw_handle, mgr, disabled); + } } impl Scrollable for ScrollBars { @@ -586,15 +597,38 @@ impl Layout for ScrollBars { .or(Some(self.id())) } + #[cfg(feature = "min_spec")] + default fn draw( + &self, + draw_handle: &mut dyn DrawHandle, + mgr: &event::ManagerState, + disabled: bool, + ) { + self.draw_(draw_handle, mgr, disabled); + } + #[cfg(not(feature = "min_spec"))] fn draw(&self, draw_handle: &mut dyn DrawHandle, mgr: &event::ManagerState, disabled: bool) { - let disabled = disabled || self.is_disabled(); - if self.show_bars.0 { - self.horiz_bar.draw(draw_handle, mgr, disabled); - } - if self.show_bars.1 { - self.vert_bar.draw(draw_handle, mgr, disabled); - } - self.inner.draw(draw_handle, mgr, disabled); + self.draw_(draw_handle, mgr, disabled); + } +} + +#[cfg(feature = "min_spec")] +impl Layout for ScrollBars> { + fn draw(&self, draw_handle: &mut dyn DrawHandle, mgr: &event::ManagerState, disabled: bool) { + let disabled = disabled || self.is_disabled() || self.inner.is_disabled(); + // Enlarge clip region to *our* rect: + draw_handle.with_clip_region(self.core.rect, self.inner.scroll_offset(), &mut |handle| { + self.inner.inner().draw(handle, mgr, disabled) + }); + // Use a second clip region to force draw order: + draw_handle.with_clip_region(self.core.rect, Offset::ZERO, &mut |draw_handle| { + if self.show_bars.0 { + self.horiz_bar.draw(draw_handle, mgr, disabled); + } + if self.show_bars.1 { + self.vert_bar.draw(draw_handle, mgr, disabled); + } + }); } } From 45205b70300bc93f3bb2d1482a055f58d22871d3 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Wed, 11 Aug 2021 15:29:43 +0100 Subject: [PATCH 22/25] Update README regarding Rust version --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 92451af7f..10e9c94bf 100644 --- a/README.md +++ b/README.md @@ -56,14 +56,13 @@ Installation and dependencies #### Rust -KAS requires [Rust] version 1.52 or greater (currently in **beta**: *usually* -we maintain compatibility with the latest stable release). -Using the **nightly** channel does have a couple of advantages: +KAS requires a recent [Rust] compiler. Currently, version 1.52 or greater is +required. Using the **nightly** channel does have a few advantages: - Proceedural macros emit better diagnostics. In some cases, diagnostics are missed without nightly rustc, hence **nightly is recommended for development**. -- Documentation generated via `cargo doc` requires nightly for links -- A few minor option things: see [Feature flags](#feature-flags) below. +- The `nightly` (`min_spec`) feature allows some visual improvements (see below). +- The `doc_cfg` feature may be used for API docs. ### Quick-start @@ -137,8 +136,9 @@ The `kas` crate has the following feature flags: Additionally, the following flags require a nightly compiler: - `nightly`: enables "more stable" unstable features -- `min_spec` (enabled by `nightly`): use `min_specialization` to draw - underlines in `AccelLabel` +- `min_spec` (enabled by `nightly`): use `min_specialization` for some visual + improvements: scrolled regions are drawn under scrollbars, + underlines on checkbox accelerator keys show with the Alt key. - `spec`: use `specialization` to enable `TryFormat` - `gat`: compatibility with `kas-text/gat` From 38a6ba12a217bac16ac3c17f8f315f3116af42d9 Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Wed, 11 Aug 2021 15:44:43 +0100 Subject: [PATCH 23/25] Update progress bar appearance --- crates/kas-theme/src/flat_theme.rs | 17 ++++++++--------- crates/kas-widgets/src/progress.rs | 12 ++++++++++++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/crates/kas-theme/src/flat_theme.rs b/crates/kas-theme/src/flat_theme.rs index 0ad0cfc9e..5dfbf866b 100644 --- a/crates/kas-theme/src/flat_theme.rs +++ b/crates/kas-theme/src/flat_theme.rs @@ -82,7 +82,7 @@ const DIMS: dim::Parameters = dim::Parameters { checkbox_inner: 5.0, scrollbar_size: Vec2::splat(8.0), slider_size: Vec2(16.0, 16.0), - progress_bar: Vec2::splat(12.0), + progress_bar: Vec2::splat(8.0), }; pub struct DrawHandle<'a, DS: DrawSharedImpl> { @@ -527,18 +527,17 @@ where } fn progress_bar(&mut self, rect: Rect, dir: Direction, _: InputState, value: f32) { - let outer = Quad::from(rect); - let mut inner = outer.shrink(self.window.dims.frame as f32); - let col = self.cols.frame; - self.draw.rounded_frame(outer, inner, BG_SHRINK_FACTOR, col); + let mut outer = Quad::from(rect); + let inner = outer.shrink(outer.size().min_comp() / 2.0); + self.draw.rounded_frame(outer, inner, 0.75, self.cols.frame); if dir.is_horizontal() { - inner.b.0 = inner.a.0 + value * (inner.b.0 - inner.a.0); + outer.b.0 = outer.a.0 + value * (outer.b.0 - outer.a.0); } else { - inner.b.1 = inner.a.1 + value * (inner.b.1 - inner.a.1); + outer.b.1 = outer.a.1 + value * (outer.b.1 - outer.a.1); } - let col = self.cols.accent_soft; - self.draw.rect(inner, col); + let inner = outer.shrink(outer.size().min_comp() / 2.0); + self.draw.rounded_frame(outer, inner, 0.0, self.cols.accent); } fn image(&mut self, id: ImageId, rect: Rect) { diff --git a/crates/kas-widgets/src/progress.rs b/crates/kas-widgets/src/progress.rs index 2a6b87c8e..03ab01636 100644 --- a/crates/kas-widgets/src/progress.rs +++ b/crates/kas-widgets/src/progress.rs @@ -17,6 +17,7 @@ pub struct ProgressBar { #[widget_core] core: CoreData, direction: D, + width: i32, value: f32, } @@ -39,6 +40,7 @@ impl ProgressBar { ProgressBar { core: Default::default(), direction, + width: 0, value: 0.0, } } @@ -81,10 +83,20 @@ impl Layout for ProgressBar { if self.direction.is_vertical() == axis.is_vertical() { SizeRules::new(size.0, size.0, margins, Stretch::High) } else { + self.width = size.1; SizeRules::fixed(size.1, margins) } } + fn set_rect(&mut self, _: &mut Manager, rect: Rect, align: AlignHints) { + let mut ideal_size = Size::splat(self.width); + ideal_size.set_component(self.direction, i32::MAX); + let rect = align + .complete(Align::Centre, Align::Centre) + .aligned_rect(ideal_size, rect); + self.core.rect = rect; + } + fn draw(&self, draw_handle: &mut dyn DrawHandle, mgr: &ManagerState, disabled: bool) { let dir = self.direction.as_direction(); let state = self.input_state(mgr, disabled); From be5df43707930e7cfe1544efe202e8d3332fb39b Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Wed, 11 Aug 2021 15:49:30 +0100 Subject: [PATCH 24/25] FlatTheme::editbox: do not draw underline when not focussed --- crates/kas-theme/src/flat_theme.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/crates/kas-theme/src/flat_theme.rs b/crates/kas-theme/src/flat_theme.rs index 5dfbf866b..68803d58f 100644 --- a/crates/kas-theme/src/flat_theme.rs +++ b/crates/kas-theme/src/flat_theme.rs @@ -415,17 +415,13 @@ where self.draw .rounded_frame(outer, inner, BG_SHRINK_FACTOR, self.cols.frame); - let col = if state.nav_focus { - self.cols.nav_focus - } else { - // TODO: should this be a dedicated colour? - ColorsLinear::adjust_for_state(self.cols.accent.average(), state) - }; - let r = 0.5 * self.window.dims.button_frame as f32; - let y = outer.b.1 - r; - let a = Vec2(outer.a.0 + r, y); - let b = Vec2(outer.b.0 - r, y); - self.draw.rounded_line(a, b, r, col); + if state.nav_focus { + let r = 0.5 * self.window.dims.button_frame as f32; + let y = outer.b.1 - r; + let a = Vec2(outer.a.0 + r, y); + let b = Vec2(outer.b.0 - r, y); + self.draw.rounded_line(a, b, r, self.cols.nav_focus); + } } fn checkbox(&mut self, rect: Rect, checked: bool, state: InputState) { From 778acb56ae19692aea8b72496d9afa9622cd4dad Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Wed, 11 Aug 2021 16:08:22 +0100 Subject: [PATCH 25/25] Add margins to frames and separators --- crates/kas-core/src/draw/handle.rs | 8 ++++++++ crates/kas-theme/src/dim.rs | 11 ++++++++++- crates/kas-theme/src/flat_theme.rs | 3 ++- crates/kas-theme/src/shaded_theme.rs | 1 + crates/kas-widgets/src/separator.rs | 3 ++- examples/gallery.rs | 2 +- 6 files changed, 24 insertions(+), 4 deletions(-) diff --git a/crates/kas-core/src/draw/handle.rs b/crates/kas-core/src/draw/handle.rs index f6951240a..afd787d5d 100644 --- a/crates/kas-core/src/draw/handle.rs +++ b/crates/kas-core/src/draw/handle.rs @@ -138,6 +138,8 @@ pub trait SizeHandle { fn pixels_from_em(&self, em: f32) -> f32; /// Size of a frame around child widget(s) + /// + /// This already includes the margins specified by [`Self::frame_margins`]. fn frame(&self, vert: bool) -> FrameRules; /// Frame/margin around a menu entry @@ -160,6 +162,9 @@ pub trait SizeHandle { /// Widgets must not draw in outer margins. fn outer_margins(&self) -> Margins; + /// The margin around frames and separators + fn frame_margins(&self) -> Margins; + /// The margin around text elements /// /// Similar to [`Self::outer_margins`], but intended for things like text @@ -467,6 +472,9 @@ impl> SizeHandle for R { fn outer_margins(&self) -> Margins { self.deref().outer_margins() } + fn frame_margins(&self) -> Margins { + self.deref().frame_margins() + } fn text_margins(&self) -> Margins { self.deref().text_margins() } diff --git a/crates/kas-theme/src/dim.rs b/crates/kas-theme/src/dim.rs index 0185cdfcd..bc817e46c 100644 --- a/crates/kas-theme/src/dim.rs +++ b/crates/kas-theme/src/dim.rs @@ -26,6 +26,8 @@ pub struct Parameters { pub outer_margin: f32, /// Margin inside a frame before contents pub inner_margin: f32, + /// Margin around frames and seperators + pub frame_margin: f32, /// Margin between text elements pub text_margin: f32, /// Frame size @@ -53,6 +55,7 @@ pub struct Dimensions { pub min_line_length: i32, pub outer_margin: u16, pub inner_margin: u16, + pub frame_margin: u16, pub text_margin: u16, pub frame: i32, pub button_frame: i32, @@ -75,6 +78,7 @@ impl Dimensions { let outer_margin = (params.outer_margin * scale_factor).cast_nearest(); let inner_margin = (params.inner_margin * scale_factor).cast_nearest(); + let frame_margin = (params.frame_margin * scale_factor).cast_nearest(); let text_margin = (params.text_margin * scale_factor).cast_nearest(); let frame = (params.frame_size * scale_factor).cast_nearest(); Dimensions { @@ -86,6 +90,7 @@ impl Dimensions { min_line_length: (8.0 * dpem).cast_nearest(), outer_margin, inner_margin, + frame_margin, text_margin, frame, button_frame: (params.button_frame * scale_factor).cast_nearest(), @@ -146,7 +151,7 @@ impl SizeHandle for Window { } fn frame(&self, _vert: bool) -> FrameRules { - FrameRules::new_sym(self.dims.frame, 0, 0) + FrameRules::new_sym(self.dims.frame, 0, self.dims.frame_margin) } fn menu_frame(&self, vert: bool) -> FrameRules { let mut size = self.dims.frame; @@ -171,6 +176,10 @@ impl SizeHandle for Window { Margins::splat(self.dims.outer_margin) } + fn frame_margins(&self) -> Margins { + Margins::splat(self.dims.frame_margin) + } + fn text_margins(&self) -> Margins { Margins::splat(self.dims.text_margin) } diff --git a/crates/kas-theme/src/flat_theme.rs b/crates/kas-theme/src/flat_theme.rs index 68803d58f..be7f72b96 100644 --- a/crates/kas-theme/src/flat_theme.rs +++ b/crates/kas-theme/src/flat_theme.rs @@ -75,8 +75,9 @@ impl FlatTheme { const DIMS: dim::Parameters = dim::Parameters { outer_margin: 8.0, inner_margin: 1.2, + frame_margin: 2.4, text_margin: 2.0, - frame_size: 4.0, + frame_size: 2.4, // NOTE: visual thickness is (button_frame * scale_factor).round() * (1 - BG_SHRINK_FACTOR) button_frame: 2.4, checkbox_inner: 5.0, diff --git a/crates/kas-theme/src/shaded_theme.rs b/crates/kas-theme/src/shaded_theme.rs index f3f0813e7..0c0ea367e 100644 --- a/crates/kas-theme/src/shaded_theme.rs +++ b/crates/kas-theme/src/shaded_theme.rs @@ -58,6 +58,7 @@ impl ShadedTheme { const DIMS: dim::Parameters = dim::Parameters { outer_margin: 6.0, inner_margin: 1.2, + frame_margin: 1.2, text_margin: 2.0, frame_size: 5.0, button_frame: 5.0, diff --git a/crates/kas-widgets/src/separator.rs b/crates/kas-widgets/src/separator.rs index fcbc0a0a7..855a85890 100644 --- a/crates/kas-widgets/src/separator.rs +++ b/crates/kas-widgets/src/separator.rs @@ -49,7 +49,8 @@ impl Separator { impl Layout for Separator { fn size_rules(&mut self, size_handle: &mut dyn SizeHandle, axis: AxisInfo) -> SizeRules { - SizeRules::extract_fixed(axis, size_handle.separator(), Default::default()) + let margins = size_handle.frame_margins(); + SizeRules::extract_fixed(axis, size_handle.separator(), margins) } fn draw(&self, draw_handle: &mut dyn DrawHandle, _: &event::ManagerState, _: bool) { diff --git a/examples/gallery.rs b/examples/gallery.rs index 412cd37af..af9bcebb4 100644 --- a/examples/gallery.rs +++ b/examples/gallery.rs @@ -119,8 +119,8 @@ fn main() -> Result<(), kas::shell::Error> { } let themes = vec![ - MenuEntry::new("&Shaded", Menu::Theme("shaded")).boxed_menu(), MenuEntry::new("&Flat", Menu::Theme("flat")).boxed_menu(), + MenuEntry::new("&Shaded", Menu::Theme("shaded")).boxed_menu(), ]; // Enumerate colour schemes. Access through the toolkit since this handles // config loading.