timer/
timer.rs

1// Copyright 2019 The Druid Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! An example of a timer.
16
17// On Windows platform, don't show a console when opening the app.
18#![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    /// Move the box towards the right, until it reaches the edge,
36    /// then reset it to the left but move it to another row.
37    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                // Start the timer when the application launches
55                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}