From 3a281546817c24f7bd411689252cf7aa25cc4cbe Mon Sep 17 00:00:00 2001 From: Joe Neeman Date: Sun, 19 Apr 2020 13:25:25 -0500 Subject: [PATCH] Fix widgets to not stroke outside the paint_rects. Fixes #628. --- druid/src/widget/button.rs | 8 +++----- druid/src/widget/checkbox.rs | 11 +++++++---- druid/src/widget/painter.rs | 4 +++- druid/src/widget/progress_bar.rs | 19 +++++++++++-------- druid/src/widget/scroll.rs | 8 ++++++-- druid/src/widget/slider.rs | 15 +++++++++------ druid/src/widget/stepper.rs | 11 ++++++++--- druid/src/widget/switch.rs | 14 +++++++------- 8 files changed, 54 insertions(+), 36 deletions(-) diff --git a/druid/src/widget/button.rs b/druid/src/widget/button.rs index ba5d6f9222..950aaf164d 100644 --- a/druid/src/widget/button.rs +++ b/druid/src/widget/button.rs @@ -114,8 +114,10 @@ impl Widget for Button { let is_active = ctx.is_active(); let is_hot = ctx.is_hot(); let size = ctx.size(); + let stroke_width = env.get(theme::BUTTON_BORDER_WIDTH); let rounded_rect = Rect::from_origin_size(Point::ORIGIN, size) + .inset(-stroke_width / 2.0) .to_rounded_rect(env.get(theme::BUTTON_BORDER_RADIUS)); let bg_gradient = if is_active { @@ -138,11 +140,7 @@ impl Widget for Button { env.get(theme::BORDER_DARK) }; - ctx.stroke( - rounded_rect, - &border_color, - env.get(theme::BUTTON_BORDER_WIDTH), - ); + ctx.stroke(rounded_rect, &border_color, stroke_width); ctx.fill(rounded_rect, &bg_gradient); diff --git a/druid/src/widget/checkbox.rs b/druid/src/widget/checkbox.rs index 5f58925f09..b978459397 100644 --- a/druid/src/widget/checkbox.rs +++ b/druid/src/widget/checkbox.rs @@ -14,7 +14,7 @@ //! A checkbox widget. -use crate::kurbo::{BezPath, Point, Rect, RoundedRect, Size}; +use crate::kurbo::{BezPath, Point, Rect, Size}; use crate::piet::{LineCap, LineJoin, LinearGradient, RenderContext, StrokeStyle, UnitPoint}; use crate::theme; use crate::widget::{Label, LabelText}; @@ -94,9 +94,12 @@ impl Widget for Checkbox { fn paint(&mut self, ctx: &mut PaintCtx, data: &bool, env: &Env) { let size = env.get(theme::BASIC_WIDGET_HEIGHT); + let border_width = 1.; - let rect = - RoundedRect::from_origin_size(Point::ORIGIN, Size::new(size, size).to_vec2(), 2.); + let rect = Size::new(size, size) + .to_rect() + .inset(-border_width / 2.) + .to_rounded_rect(2.); //Paint the background let background_gradient = LinearGradient::new( @@ -116,7 +119,7 @@ impl Widget for Checkbox { env.get(theme::BORDER_DARK) }; - ctx.stroke(rect, &border_color, 1.); + ctx.stroke(rect, &border_color, border_width); if *data { // Paint the checkmark diff --git a/druid/src/widget/painter.rs b/druid/src/widget/painter.rs index 1969fb2263..6f76ff5fab 100644 --- a/druid/src/widget/painter.rs +++ b/druid/src/widget/painter.rs @@ -64,7 +64,9 @@ use crate::{ /// const STROKE_WIDTH: f64 = 2.0; /// /// let colorwell: Painter = Painter::new(|ctx, data: &Color, env| { -/// let bounds = ctx.size().to_rect(); +/// // Shrink the bounds a little, to ensure that our stroke remains within +/// // the paint bounds. +/// let bounds = ctx.size().to_rect().inset(-STROKE_WIDTH / 2.0); /// let rounded = bounds.to_rounded_rect(CORNER_RADIUS); /// ctx.fill(rounded, data); /// ctx.stroke(rounded, &env.get(druid::theme::PRIMARY_DARK), STROKE_WIDTH); diff --git a/druid/src/widget/progress_bar.rs b/druid/src/widget/progress_bar.rs index 286d820874..2f24bc4d64 100644 --- a/druid/src/widget/progress_bar.rs +++ b/druid/src/widget/progress_bar.rs @@ -14,7 +14,7 @@ //! A progress bar widget. -use crate::kurbo::{Point, RoundedRect, Size}; +use crate::kurbo::{Point, Rect, Size}; use crate::theme; use crate::{ BoxConstraints, Env, Event, EventCtx, LayoutCtx, LifeCycle, LifeCycleCtx, LinearGradient, @@ -59,19 +59,21 @@ impl Widget for ProgressBar { fn paint(&mut self, ctx: &mut PaintCtx, data: &f64, env: &Env) { let clamped = data.max(0.0).min(1.0); + let stroke_width = 2.0; - let rounded_rect = RoundedRect::from_origin_size( + let rounded_rect = Rect::from_origin_size( Point::ORIGIN, (Size { width: ctx.size().width, height: env.get(theme::BASIC_WIDGET_HEIGHT), }) .to_vec2(), - 4., - ); + ) + .inset(-stroke_width / 2.0) + .to_rounded_rect(4.0); //Paint the border - ctx.stroke(rounded_rect, &env.get(theme::BORDER_DARK), 2.0); + ctx.stroke(rounded_rect, &env.get(theme::BORDER_DARK), stroke_width); //Paint the background let background_gradient = LinearGradient::new( @@ -86,15 +88,16 @@ impl Widget for ProgressBar { //Paint the bar let calculated_bar_width = clamped * rounded_rect.width(); - let rounded_rect = RoundedRect::from_origin_size( + let rounded_rect = Rect::from_origin_size( Point::ORIGIN, (Size { width: calculated_bar_width, height: env.get(theme::BASIC_WIDGET_HEIGHT), }) .to_vec2(), - env.get(theme::PROGRESS_BAR_RADIUS), - ); + ) + .inset(-stroke_width / 2.0) + .to_rounded_rect(env.get(theme::PROGRESS_BAR_RADIUS)); let bar_gradient = LinearGradient::new( UnitPoint::TOP, UnitPoint::BOTTOM, diff --git a/druid/src/widget/scroll.rs b/druid/src/widget/scroll.rs index 1fb3d1ee93..44c5e6755e 100644 --- a/druid/src/widget/scroll.rs +++ b/druid/src/widget/scroll.rs @@ -253,7 +253,9 @@ impl> Scroll { // Vertical bar if viewport.height() < self.child_size.height { - let bounds = self.calc_vertical_bar_bounds(viewport, env); + let bounds = self + .calc_vertical_bar_bounds(viewport, env) + .inset(-edge_width / 2.0); let rect = RoundedRect::from_rect(bounds, radius); ctx.render_ctx.fill(rect, &brush); ctx.render_ctx.stroke(rect, &border_brush, edge_width); @@ -261,7 +263,9 @@ impl> Scroll { // Horizontal bar if viewport.width() < self.child_size.width { - let bounds = self.calc_horizontal_bar_bounds(viewport, env); + let bounds = self + .calc_horizontal_bar_bounds(viewport, env) + .inset(-edge_width / 2.0); let rect = RoundedRect::from_rect(bounds, radius); ctx.render_ctx.fill(rect, &brush); ctx.render_ctx.stroke(rect, &border_brush, edge_width); diff --git a/druid/src/widget/slider.rs b/druid/src/widget/slider.rs index 9fb1711615..e5849b903f 100644 --- a/druid/src/widget/slider.rs +++ b/druid/src/widget/slider.rs @@ -14,7 +14,7 @@ //! A slider widget. -use crate::kurbo::{Circle, Point, Rect, RoundedRect, Shape, Size}; +use crate::kurbo::{Circle, Point, Rect, Shape, Size}; use crate::theme; use crate::{ BoxConstraints, Env, Event, EventCtx, LayoutCtx, LifeCycle, LifeCycleCtx, LinearGradient, @@ -138,13 +138,16 @@ impl Widget for Slider { let rect = Rect::from_origin_size(Point::ORIGIN, ctx.size()); let knob_size = env.get(theme::BASIC_WIDGET_HEIGHT); let track_thickness = 4.; + let border_width = 2.; + let knob_stroke_width = 2.; //Paint the background let background_width = rect.width() - knob_size; let background_origin = Point::new(knob_size / 2., (knob_size - track_thickness) / 2.); let background_size = Size::new(background_width, track_thickness); - let background_rect = - RoundedRect::from_origin_size(background_origin, background_size.to_vec2(), 2.); + let background_rect = Rect::from_origin_size(background_origin, background_size) + .inset(-border_width / 2.) + .to_rounded_rect(2.); let background_gradient = LinearGradient::new( UnitPoint::TOP, @@ -155,7 +158,7 @@ impl Widget for Slider { ), ); - ctx.stroke(background_rect, &env.get(theme::BORDER_DARK), 2.0); + ctx.stroke(background_rect, &env.get(theme::BORDER_DARK), border_width); ctx.fill(background_rect, &background_gradient); @@ -165,7 +168,7 @@ impl Widget for Slider { let knob_position = (rect.width() - knob_size) * clamped + knob_size / 2.; self.knob_pos = Point::new(knob_position, knob_size / 2.); - let knob_circle = Circle::new(self.knob_pos, knob_size / 2.); + let knob_circle = Circle::new(self.knob_pos, (knob_size - knob_stroke_width) / 2.); let normal_knob_gradient = LinearGradient::new( UnitPoint::TOP, @@ -197,7 +200,7 @@ impl Widget for Slider { env.get(theme::FOREGROUND_DARK) }; - ctx.stroke(knob_circle, &border_color, 2.); + ctx.stroke(knob_circle, &border_color, knob_stroke_width); //Actually paint the knob ctx.fill(knob_circle, &knob_gradient); diff --git a/druid/src/widget/stepper.rs b/druid/src/widget/stepper.rs index fe39551b07..6033b163a5 100644 --- a/druid/src/widget/stepper.rs +++ b/druid/src/widget/stepper.rs @@ -17,7 +17,7 @@ use std::f64::EPSILON; use std::time::Duration; -use crate::kurbo::{BezPath, Rect, RoundedRect}; +use crate::kurbo::{BezPath, Rect}; use crate::piet::{LinearGradient, RenderContext, UnitPoint}; use crate::{ BoxConstraints, Env, Event, EventCtx, LayoutCtx, LifeCycle, LifeCycleCtx, PaintCtx, Size, @@ -120,13 +120,18 @@ impl Default for Stepper { impl Widget for Stepper { fn paint(&mut self, ctx: &mut PaintCtx, _data: &f64, env: &Env) { - let rounded_rect = RoundedRect::from_origin_size(Point::ORIGIN, ctx.size().to_vec2(), 4.); + let stroke_width = 2.0; + let rounded_rect = ctx + .size() + .to_rect() + .inset(-stroke_width / 2.0) + .to_rounded_rect(4.0); let height = ctx.size().height; let width = env.get(theme::BASIC_WIDGET_HEIGHT); let button_size = Size::new(width, height / 2.); - ctx.stroke(rounded_rect, &env.get(theme::BORDER_DARK), 2.0); + ctx.stroke(rounded_rect, &env.get(theme::BORDER_DARK), stroke_width); ctx.clip(rounded_rect); // draw buttons for increase/decrease diff --git a/druid/src/widget/switch.rs b/druid/src/widget/switch.rs index 6ddf7e668c..cfa1debde4 100644 --- a/druid/src/widget/switch.rs +++ b/druid/src/widget/switch.rs @@ -14,7 +14,7 @@ //! A toggle switch widget. -use crate::kurbo::{Circle, Point, Rect, RoundedRect, Shape, Size}; +use crate::kurbo::{Circle, Point, Rect, Shape, Size}; use crate::piet::{ FontBuilder, LinearGradient, RenderContext, Text, TextLayout, TextLayoutBuilder, UnitPoint, }; @@ -201,12 +201,12 @@ impl Widget for Switch { let knob_size = switch_height - 2. * SWITCH_PADDING; let on_pos = switch_width - knob_size / 2. - SWITCH_PADDING; let off_pos = knob_size / 2. + SWITCH_PADDING; + let stroke_width = 2.0; - let background_rect = RoundedRect::from_origin_size( - Point::ORIGIN, - Size::new(switch_width, switch_height).to_vec2(), - switch_height / 2., - ); + let background_rect = Size::new(switch_width, switch_height) + .to_rect() + .inset(-stroke_width / 2.0) + .to_rounded_rect(switch_height / 2.); // position knob if !self.animation_in_progress && !self.knob_dragged { @@ -242,7 +242,7 @@ impl Widget for Switch { ), ); - ctx.stroke(background_rect, &env.get(theme::BORDER_DARK), 2.0); + ctx.stroke(background_rect, &env.get(theme::BORDER_DARK), stroke_width); ctx.fill(background_rect, &background_gradient_on_state); ctx.fill(background_rect, &background_gradient_off_state); ctx.clip(background_rect);