Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep hot state consistent with mouse position. #841

Merged
merged 5 commits into from
Apr 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -386,14 +387,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 @@ -551,7 +544,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