1#![windows_subsystem = "windows"]
19
20use std::time::Duration;
21
22use druid::widget::prelude::*;
23use druid::widget::BackgroundBrush;
24use druid::{AppLauncher, Color, LocalizedString, Point, TimerToken, WidgetPod, WindowDesc};
25
26static TIMER_INTERVAL: Duration = Duration::from_millis(10);
27
28struct TimerWidget {
29 timer_id: TimerToken,
30 simple_box: WidgetPod<u32, SimpleBox>,
31 pos: Point,
32}
33
34impl TimerWidget {
35 fn adjust_box_pos(&mut self, container_size: Size) {
38 let box_size = self.simple_box.layout_rect().size();
39 self.pos.x += 2.;
40 if self.pos.x + box_size.width > container_size.width {
41 self.pos.x = 0.;
42 self.pos.y += box_size.height;
43 if self.pos.y + box_size.height > container_size.height {
44 self.pos.y = 0.;
45 }
46 }
47 }
48}
49
50impl Widget<u32> for TimerWidget {
51 fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut u32, env: &Env) {
52 match event {
53 Event::WindowConnected => {
54 self.timer_id = ctx.request_timer(TIMER_INTERVAL);
56 }
57 Event::Timer(id) => {
58 if *id == self.timer_id {
59 self.adjust_box_pos(ctx.size());
60 ctx.request_layout();
61 self.timer_id = ctx.request_timer(TIMER_INTERVAL);
62 }
63 }
64 _ => (),
65 }
66 self.simple_box.event(ctx, event, data, env);
67 }
68
69 fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle, data: &u32, env: &Env) {
70 self.simple_box.lifecycle(ctx, event, data, env);
71 }
72
73 fn update(&mut self, ctx: &mut UpdateCtx, _old_data: &u32, data: &u32, env: &Env) {
74 self.simple_box.update(ctx, data, env);
75 }
76
77 fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints, data: &u32, env: &Env) -> Size {
78 self.simple_box.layout(ctx, &bc.loosen(), data, env);
79 self.simple_box.set_origin(ctx, self.pos);
80 bc.constrain((500.0, 500.0))
81 }
82
83 fn paint(&mut self, ctx: &mut PaintCtx, data: &u32, env: &Env) {
84 self.simple_box.paint(ctx, data, env);
85 }
86}
87
88struct SimpleBox;
89
90impl Widget<u32> for SimpleBox {
91 fn event(&mut self, _ctx: &mut EventCtx, _event: &Event, _data: &mut u32, _env: &Env) {}
92
93 fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle, _data: &u32, _env: &Env) {
94 if let LifeCycle::HotChanged(_) = event {
95 ctx.request_paint();
96 }
97 }
98
99 fn update(&mut self, _ctx: &mut UpdateCtx, _old_data: &u32, _data: &u32, _env: &Env) {}
100
101 fn layout(
102 &mut self,
103 _ctx: &mut LayoutCtx,
104 bc: &BoxConstraints,
105 _data: &u32,
106 _env: &Env,
107 ) -> Size {
108 bc.constrain((50.0, 50.0))
109 }
110
111 fn paint(&mut self, ctx: &mut PaintCtx, data: &u32, env: &Env) {
112 let mut background = if ctx.is_hot() {
113 BackgroundBrush::Color(Color::rgb8(200, 55, 55))
114 } else {
115 BackgroundBrush::Color(Color::rgb8(30, 210, 170))
116 };
117 background.paint(ctx, data, env);
118 }
119}
120
121pub fn main() {
122 let window = WindowDesc::new(TimerWidget {
123 timer_id: TimerToken::INVALID,
124 simple_box: WidgetPod::new(SimpleBox),
125 pos: Point::ZERO,
126 })
127 .with_min_size((200., 200.))
128 .title(LocalizedString::new("timer-demo-window-title").with_placeholder("Look at it go!"));
129
130 AppLauncher::with_window(window)
131 .log_to_console()
132 .launch(0u32)
133 .expect("launch failed");
134}