From 24ec63a178567d1378f165a2601acdf324897a8f Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Sun, 14 Jun 2020 15:34:19 +0200 Subject: [PATCH] widgets: Allow widgets to fill remaining space This is implemented by propagating the expected remaining space to all widget draw calls. It is not currently as smart as it could be, but it works well enough to let the last widget in a row/column fill things. BarWidget-type widgets and the Launcher widget now fill remaining space if their length is set to 0. --- src/app.rs | 1 + src/config.rs | 8 +++--- src/widget.rs | 58 +++++++++++++++++++++++++++++---------- src/widgets/bar_widget.rs | 12 +++++--- src/widgets/calendar.rs | 1 + src/widgets/clock.rs | 1 + src/widgets/date.rs | 1 + src/widgets/launcher.rs | 17 +++++++++--- 8 files changed, 73 insertions(+), 26 deletions(-) diff --git a/src/app.rs b/src/app.rs index da4b0aa..fd84dbc 100644 --- a/src/app.rs +++ b/src/app.rs @@ -272,6 +272,7 @@ impl<'a> App<'a> { force, }, (0, 0), + size, )?; mmap.flush().unwrap(); diff --git a/src/config.rs b/src/config.rs index 07fbcf7..58fa875 100644 --- a/src/config.rs +++ b/src/config.rs @@ -282,7 +282,7 @@ impl Default for Config { widget: Box::new(Widget::Battery { font: None, font_size: 24.0, - length: 600, + length: 0, }), }, Widget::Margin { @@ -291,7 +291,7 @@ impl Default for Config { device: "intel_backlight".to_string(), font: None, font_size: 24.0, - length: 600, + length: 0, }), }, #[cfg(feature = "pulseaudio-widget")] @@ -300,7 +300,7 @@ impl Default for Config { widget: Box::new(Widget::PulseAudio { font: None, font_size: 24.0, - length: 600, + length: 0, }), }, ]), @@ -314,7 +314,7 @@ impl Default for Config { Widget::Launcher { font: None, font_size: 32.0, - length: 1200, + length: 0, app_opener: "".to_string(), term_opener: "".to_string(), url_opener: "".to_string(), diff --git a/src/widget.rs b/src/widget.rs index cc9aaf0..6f16938 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -56,6 +56,7 @@ pub trait Widget { &mut self, ctx: &mut DrawContext, pos: (u32, u32), + expansion: (u32, u32), ) -> Result; fn keyboard_input( @@ -115,16 +116,20 @@ impl<'a> Widget for VerticalLayout<'a> { &mut self, ctx: &mut DrawContext, pos: (u32, u32), + expansion: (u32, u32), ) -> Result { - let mut offset = pos.1; + let mut offset = 0; let mut width = 0; let mut damage = Vec::new(); let mut full_damage = false; - for child in &mut self.children { - let mut report = child.draw(ctx, (pos.0, offset))?; + let mut report = child.draw( + ctx, + (pos.0, offset + pos.1), + (expansion.0, expansion.1 - offset), + )?; if report.width > width { - width = report.width; + width = report.width } offset += report.height; full_damage |= report.full_damage; @@ -133,7 +138,7 @@ impl<'a> Widget for VerticalLayout<'a> { Ok(DrawReport { width, - height: offset - pos.1, + height: offset, damage, full_damage, }) @@ -189,6 +194,19 @@ impl<'a> HorizontalLayout<'a> { pub fn new(children: Vec>) -> Box { Box::new(HorizontalLayout { children }) } + + fn height(&self) -> u32 { + let mut height = 0; + + for child in &self.children { + let size = child.size(); + if size.1 > height { + height = size.1; + } + } + + height + } } impl<'a> Widget for HorizontalLayout<'a> { @@ -226,16 +244,20 @@ impl<'a> Widget for HorizontalLayout<'a> { &mut self, ctx: &mut DrawContext, pos: (u32, u32), + expansion: (u32, u32), ) -> Result { - let mut offset = pos.0; + let mut offset = 0; let mut height = 0; let mut damage = Vec::new(); let mut full_damage = false; - for child in &mut self.children { - let mut report = child.draw(ctx, (offset, pos.1))?; + let mut report = child.draw( + ctx, + (offset + pos.0, pos.1), + (expansion.0 - offset, expansion.1), + )?; if report.height > height { - height = report.height; + height = report.height } offset += report.width; full_damage |= report.full_damage; @@ -243,7 +265,7 @@ impl<'a> Widget for HorizontalLayout<'a> { } Ok(DrawReport { - width: offset - pos.0, + width: offset, height, damage, full_damage, @@ -327,10 +349,17 @@ impl<'a> Widget for Margin<'a> { &mut self, ctx: &mut DrawContext, pos: (u32, u32), + expansion: (u32, u32), ) -> Result { - let report = self - .child - .draw(ctx, (pos.0 + self.margins.0, pos.1 + self.margins.2))?; + let expansion = ( + expansion.0 - self.margins.0 - self.margins.1, + expansion.1 - self.margins.2 - self.margins.3, + ); + let report = self.child.draw( + ctx, + (pos.0 + self.margins.0, pos.1 + self.margins.2), + expansion, + )?; Ok(DrawReport { width: report.width + self.margins.0 + self.margins.1, height: report.height + self.margins.2 + self.margins.3, @@ -397,8 +426,9 @@ impl<'a> Widget for Fixed<'a> { &mut self, ctx: &mut DrawContext, pos: (u32, u32), + expansion: (u32, u32), ) -> Result { - let report = self.child.draw(ctx, pos)?; + let report = self.child.draw(ctx, pos, expansion)?; Ok(DrawReport { width: self.size.0, height: self.size.1, diff --git a/src/widgets/bar_widget.rs b/src/widgets/bar_widget.rs index 98931fb..3ca0fa3 100644 --- a/src/widgets/bar_widget.rs +++ b/src/widgets/bar_widget.rs @@ -83,8 +83,12 @@ impl<'a> Widget for BarWidget<'a> { &mut self, ctx: &mut DrawContext, pos: (u32, u32), + expansion: (u32, u32), ) -> Result { - let (width, height) = self.size(); + if self.length == 0 { + self.length = expansion.0; + } + let (width, height) = (self.length, self.font_size); { let mut d = self.dirty.lock().unwrap(); if !*d && !ctx.force { @@ -105,7 +109,7 @@ impl<'a> Widget for BarWidget<'a> { draw_bar( &mut buf.offset((bar_off, 0))?, &c, - self.length - bar_off, + width - bar_off, self.font_size, val, )?; @@ -117,7 +121,7 @@ impl<'a> Widget for BarWidget<'a> { draw_bar( &mut buf.offset((bar_off, 0))?, &c, - self.length - bar_off, + width - bar_off, self.font_size, val, )?; @@ -125,7 +129,7 @@ impl<'a> Widget for BarWidget<'a> { draw_box( &mut buf.offset((bar_off, 0))?, &c, - (self.length - bar_off, self.font_size), + (width - bar_off, self.font_size), )?; Ok(DrawReport { width, diff --git a/src/widgets/calendar.rs b/src/widgets/calendar.rs index 35fae80..728a7df 100644 --- a/src/widgets/calendar.rs +++ b/src/widgets/calendar.rs @@ -203,6 +203,7 @@ impl<'a> Widget for Calendar<'a> { &mut self, ctx: &mut DrawContext, pos: (u32, u32), + _expansion: (u32, u32), ) -> Result { let (width, height) = self.size(); if ctx.time.date() == self.cur_date && !ctx.force && !self.dirty { diff --git a/src/widgets/clock.rs b/src/widgets/clock.rs index 60ac4c7..99bff56 100644 --- a/src/widgets/clock.rs +++ b/src/widgets/clock.rs @@ -52,6 +52,7 @@ impl<'a> Widget for Clock<'a> { &mut self, ctx: &mut DrawContext, pos: (u32, u32), + _expansion: (u32, u32), ) -> Result { let (width, height) = self.size(); if !(ctx.time.date() != self.cur_time.date() diff --git a/src/widgets/date.rs b/src/widgets/date.rs index ca5ed2f..658982e 100644 --- a/src/widgets/date.rs +++ b/src/widgets/date.rs @@ -39,6 +39,7 @@ impl<'a> Widget for Date<'a> { &mut self, ctx: &mut DrawContext, pos: (u32, u32), + _expansion: (u32, u32), ) -> Result { let (width, height) = self.size(); diff --git a/src/widgets/launcher.rs b/src/widgets/launcher.rs index 21baa36..6c34147 100644 --- a/src/widgets/launcher.rs +++ b/src/widgets/launcher.rs @@ -60,7 +60,12 @@ impl<'a> Launcher<'a> { }) } - fn draw_launcher(&self, buf: &mut Buffer, bg: &Color) -> Result<(), ::std::io::Error> { + fn draw_launcher( + &self, + buf: &mut Buffer, + bg: &Color, + width: u32, + ) -> Result<(), ::std::io::Error> { let mut x_off = if !self.input.is_empty() { let c = if self.matches.is_empty() { Color::new(1.0, 0.5, 0.5, 1.0) @@ -77,7 +82,7 @@ impl<'a> Launcher<'a> { 0 }; - let mut width_remaining: i32 = (self.length - x_off) as i32; + let mut width_remaining: i32 = (width - x_off) as i32; for (idx, m) in self.matches.iter().enumerate() { let mut b = match buf.offset((x_off, 0)) { Ok(b) => b, @@ -266,8 +271,12 @@ impl<'a> Widget for Launcher<'a> { &mut self, ctx: &mut DrawContext, pos: (u32, u32), + expansion: (u32, u32), ) -> Result { - let (width, height) = self.size(); + if self.length == 0 { + self.length = expansion.0; + } + let (width, height) = (self.length, self.font_size); if !self.dirty && !ctx.force { return Ok(DrawReport::empty(width, height)); } @@ -313,7 +322,7 @@ impl<'a> Widget for Launcher<'a> { match self.input.chars().next() { Some('=') => self.draw_calc(buf, ctx.bg), Some('!') => self.draw_shell(buf, ctx.bg), - _ => self.draw_launcher(buf, ctx.bg), + _ => self.draw_launcher(buf, ctx.bg, width), }?; Ok(DrawReport {