Skip to content

Commit

Permalink
Merge pull request #841 from xStrom/true-hot
Browse files Browse the repository at this point in the history
Keep hot state consistent with mouse position.
  • Loading branch information
xStrom authored Apr 15, 2020
2 parents 185941d + 2e1c601 commit ee55405
Show file tree
Hide file tree
Showing 17 changed files with 353 additions and 228 deletions.
94 changes: 74 additions & 20 deletions druid/examples/timer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,63 +16,117 @@
use std::time::{Duration, Instant};

use druid::kurbo::Line;
use druid::widget::prelude::*;
use druid::{AppLauncher, Color, LocalizedString, TimerToken, WindowDesc};
use druid::widget::BackgroundBrush;
use druid::{AppLauncher, Color, LocalizedString, Point, Rect, TimerToken, WidgetPod, WindowDesc};

static TIMER_INTERVAL: u64 = 10;

struct TimerWidget {
timer_id: TimerToken,
on: bool,
simple_box: WidgetPod<u32, SimpleBox>,
pos: Point,
}

impl TimerWidget {
/// Move the box towards the right, until it reaches the edge,
/// then reset it to the left but move it to another row.
fn adjust_box_pos(&mut self, container_size: Size) {
let box_size = self.simple_box.layout_rect().size();
self.pos.x += 2.;
if self.pos.x + box_size.width > container_size.width {
self.pos.x = 0.;
self.pos.y += box_size.height;
if self.pos.y + box_size.height > container_size.height {
self.pos.y = 0.;
}
}
}
}

impl Widget<u32> for TimerWidget {
fn event(&mut self, ctx: &mut EventCtx, event: &Event, _data: &mut u32, _env: &Env) {
fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut u32, env: &Env) {
match event {
Event::MouseDown(_) => {
self.on = !self.on;
ctx.request_paint();
let deadline = Instant::now() + Duration::from_millis(500);
Event::WindowConnected => {
// Start the timer when the application launches
let deadline = Instant::now() + Duration::from_millis(TIMER_INTERVAL);
self.timer_id = ctx.request_timer(deadline);
}
Event::Timer(id) => {
if *id == self.timer_id {
self.on = !self.on;
ctx.request_paint();
let deadline = Instant::now() + Duration::from_millis(500);
self.adjust_box_pos(ctx.size());
ctx.request_layout();
let deadline = Instant::now() + Duration::from_millis(TIMER_INTERVAL);
self.timer_id = ctx.request_timer(deadline);
}
}
_ => (),
}
self.simple_box.event(ctx, event, data, env);
}

fn lifecycle(&mut self, _ctx: &mut LifeCycleCtx, _event: &LifeCycle, _data: &u32, _env: &Env) {}
fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle, data: &u32, env: &Env) {
self.simple_box.lifecycle(ctx, event, data, env);
}

fn update(&mut self, ctx: &mut UpdateCtx, _old_data: &u32, data: &u32, env: &Env) {
self.simple_box.update(ctx, data, env);
}

fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints, data: &u32, env: &Env) -> Size {
let size = self.simple_box.layout(ctx, &bc.loosen(), data, env);
let rect = Rect::from_origin_size(self.pos, size);
self.simple_box.set_layout_rect(ctx, data, env, rect);
bc.constrain((500.0, 500.0))
}

fn paint(&mut self, ctx: &mut PaintCtx, data: &u32, env: &Env) {
self.simple_box.paint_with_offset(ctx, data, env);
}
}

struct SimpleBox;

impl Widget<u32> for SimpleBox {
fn event(&mut self, _ctx: &mut EventCtx, _event: &Event, _data: &mut u32, _env: &Env) {}

fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, _event: &LifeCycle, _data: &u32, _env: &Env) {
match _event {
LifeCycle::HotChanged(_) => ctx.request_paint(),
_ => (),
}
}

fn update(&mut self, _ctx: &mut UpdateCtx, _old_data: &u32, _data: &u32, _env: &Env) {}

fn layout(
&mut self,
_layout_ctx: &mut LayoutCtx,
_ctx: &mut LayoutCtx,
bc: &BoxConstraints,
_data: &u32,
_env: &Env,
) -> Size {
bc.constrain((100.0, 100.0))
bc.constrain((50.0, 50.0))
}

fn paint(&mut self, ctx: &mut PaintCtx, _data: &u32, _env: &Env) {
if self.on {
ctx.stroke(Line::new((10.0, 10.0), (10.0, 50.0)), &Color::WHITE, 1.0);
}
fn paint(&mut self, ctx: &mut PaintCtx, data: &u32, env: &Env) {
let mut background = if ctx.is_hot() {
BackgroundBrush::Color(Color::rgb8(200, 55, 55))
} else {
BackgroundBrush::Color(Color::rgb8(30, 210, 170))
};
background.paint(ctx, data, env);
}
}

fn main() {
let window = WindowDesc::new(|| TimerWidget {
timer_id: TimerToken::INVALID,
on: false,
simple_box: WidgetPod::new(SimpleBox),
pos: Point::ZERO,
})
.title(LocalizedString::new("timer-demo-window-title").with_placeholder("Tick Tock"));
.with_min_size((200., 200.))
.title(LocalizedString::new("timer-demo-window-title").with_placeholder("Look at it go!"));

AppLauncher::with_window(window)
.use_simple_logger()
Expand Down
19 changes: 6 additions & 13 deletions druid/src/contexts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ use crate::core::{BaseState, CommandQueue, FocusChange};
use crate::piet::Piet;
use crate::piet::RenderContext;
use crate::{
Affine, Command, Cursor, Insets, Rect, Size, Target, Text, TimerToken, WidgetId, WindowHandle,
WindowId,
Affine, Command, Cursor, Insets, Point, Rect, Size, Target, Text, TimerToken, WidgetId,
WindowHandle, WindowId,
};

/// A mutable context provided to event handling methods of widgets.
Expand All @@ -43,7 +43,6 @@ pub struct EventCtx<'a> {
pub(crate) window: &'a WindowHandle,
pub(crate) base_state: &'a mut BaseState,
pub(crate) focus_widget: Option<WidgetId>,
pub(crate) had_active: bool,
pub(crate) is_handled: bool,
pub(crate) is_root: bool,
}
Expand Down Expand Up @@ -85,9 +84,11 @@ pub struct UpdateCtx<'a> {
/// creating text layout objects, which are likely to be useful
/// during widget layout.
pub struct LayoutCtx<'a, 'b: 'a> {
pub(crate) command_queue: &'a mut CommandQueue,
pub(crate) base_state: &'a mut BaseState,
pub(crate) text_factory: &'a mut Text<'b>,
pub(crate) paint_insets: Insets,
pub(crate) window_id: WindowId,
pub(crate) mouse_pos: Option<Point>,
}

/// Z-order paint operations with transformations.
Expand Down Expand Up @@ -388,14 +389,6 @@ impl<'a> EventCtx<'a> {
pub fn widget_id(&self) -> WidgetId {
self.base_state.id
}

pub(crate) fn make_lifecycle_ctx(&mut self) -> LifeCycleCtx {
LifeCycleCtx {
command_queue: self.command_queue,
base_state: self.base_state,
window_id: self.window_id,
}
}
}

impl<'a> LifeCycleCtx<'a> {
Expand Down Expand Up @@ -557,7 +550,7 @@ impl<'a, 'b> LayoutCtx<'a, 'b> {
/// [`Insets`]: struct.Insets.html
/// [`WidgetPod::paint_insets`]: struct.WidgetPod.html#method.paint_insets
pub fn set_paint_insets(&mut self, insets: impl Into<Insets>) {
self.paint_insets = insets.into().nonnegative();
self.base_state.paint_insets = insets.into().nonnegative();
}
}

Expand Down
Loading

0 comments on commit ee55405

Please sign in to comment.