Struct WindowConfig

Source
pub struct WindowConfig { /* private fields */ }
Expand description

Window configuration that can be applied to a WindowBuilder, or to an existing WindowHandle. It does not include anything related to app data.

Implementations§

Source§

impl WindowConfig

Source

pub fn window_size_policy(self, size_policy: WindowSizePolicy) -> Self

Set the window size policy.

Examples found in repository?
examples/sub_window.rs (line 152)
99    fn event(&mut self, child: &mut W, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) {
100        let wait_duration = Duration::from_millis(500);
101        let resched_dur = Duration::from_millis(50);
102        let cursor_size = Size::new(15., 15.);
103        let now = Instant::now();
104        let new_state = match &self.state {
105            TooltipState::Fresh => match event {
106                Event::MouseMove(me) if ctx.is_hot() => Some(TooltipState::Waiting {
107                    last_move: now,
108                    timer_expire: now + wait_duration,
109                    token: ctx.request_timer(wait_duration),
110                    position_in_window_coordinates: me.window_pos,
111                }),
112                _ => None,
113            },
114            TooltipState::Waiting {
115                last_move,
116                timer_expire,
117                token,
118                position_in_window_coordinates,
119            } => match event {
120                Event::MouseMove(me) if ctx.is_hot() => {
121                    let (cur_token, cur_expire) = if *timer_expire - now < resched_dur {
122                        (ctx.request_timer(wait_duration), now + wait_duration)
123                    } else {
124                        (*token, *timer_expire)
125                    };
126                    Some(TooltipState::Waiting {
127                        last_move: now,
128                        timer_expire: cur_expire,
129                        token: cur_token,
130                        position_in_window_coordinates: me.window_pos,
131                    })
132                }
133                Event::Timer(tok) if tok == token => {
134                    let deadline = *last_move + wait_duration;
135                    ctx.set_handled();
136                    if deadline > now {
137                        let wait_for = deadline - now;
138                        tracing::info!("Waiting another {:?}", wait_for);
139                        Some(TooltipState::Waiting {
140                            last_move: *last_move,
141                            timer_expire: deadline,
142                            token: ctx.request_timer(wait_for),
143                            position_in_window_coordinates: *position_in_window_coordinates,
144                        })
145                    } else {
146                        let tooltip_position_in_window_coordinates =
147                            (position_in_window_coordinates.to_vec2() + cursor_size.to_vec2())
148                                .to_point();
149                        let win_id = ctx.new_sub_window(
150                            WindowConfig::default()
151                                .show_titlebar(false)
152                                .window_size_policy(WindowSizePolicy::Content)
153                                .set_level(WindowLevel::Tooltip(ctx.window().clone()))
154                                .set_position(tooltip_position_in_window_coordinates),
155                            Label::<()>::new(self.tip.clone()),
156                            (),
157                            env.clone(),
158                        );
159                        Some(TooltipState::Showing(win_id))
160                    }
161                }
162                _ => None,
163            },
164            TooltipState::Showing(win_id) => {
165                match event {
166                    Event::MouseMove(me) if !ctx.is_hot() => {
167                        // TODO another timer on leaving
168                        tracing::info!("Sending close window for {:?}", win_id);
169                        ctx.submit_command(CLOSE_WINDOW.to(*win_id));
170                        Some(TooltipState::Waiting {
171                            last_move: now,
172                            timer_expire: now + wait_duration,
173                            token: ctx.request_timer(wait_duration),
174                            position_in_window_coordinates: me.window_pos,
175                        })
176                    }
177                    _ => None,
178                }
179            }
180        };
181
182        if let Some(state) = new_state {
183            self.state = state;
184        }
185
186        if !ctx.is_handled() {
187            child.event(ctx, event, data, env);
188        }
189    }
Source

pub fn window_size(self, size: impl Into<Size>) -> Self

Set the window’s initial drawing area size in display points.

You can pass in a tuple (width, height) or a Size, e.g. to create a window with a drawing area 1000dp wide and 500dp high:

window.window_size((1000.0, 500.0));

The actual window size in pixels will depend on the platform DPI settings.

This should be considered a request to the platform to set the size of the window. The platform might increase the size a tiny bit due to DPI.

Examples found in repository?
examples/sub_window.rs (line 357)
332fn build_root_widget() -> impl Widget<HelloState> {
333    let label = EnvScope::new(
334        |env, _t| env.set(theme::TEXT_COLOR, env.get(theme::PRIMARY_LIGHT)),
335        ControllerHost::new(
336            Label::new(|data: &HelloState, _env: &Env| {
337                format!("Hello {}! {} ", data.name, data.sub.my_stuff)
338            }),
339            TooltipController::new("Tips! Are good"),
340        ),
341    );
342    // a textbox that modifies `name`.
343    let textbox = TextBox::new()
344        .with_placeholder("Who are we greeting?")
345        .fix_width(TEXT_BOX_WIDTH)
346        .lens(HelloState::sub.then(SubState::my_stuff));
347
348    let button = Button::new("Make sub window")
349        .on_click(|ctx, data: &mut SubState, env| {
350            let tb = TextBox::new().lens(SubState::my_stuff);
351            let drag_thing = Label::new("Drag me").controller(DragWindowController::new());
352            let col = Flex::column().with_child(drag_thing).with_child(tb);
353
354            ctx.new_sub_window(
355                WindowConfig::default()
356                    .show_titlebar(false)
357                    .window_size(Size::new(100., 100.))
358                    .set_level(WindowLevel::AppWindow),
359                col,
360                data.clone(),
361                env.clone(),
362            );
363        })
364        .center()
365        .lens(HelloState::sub);
366
367    let check_box =
368        ControllerHost::new(Checkbox::new("Closeable?"), CancelClose).lens(HelloState::closeable);
369    // arrange the two widgets vertically, with some padding
370    let layout = Flex::column()
371        .with_child(label)
372        .with_flex_child(ScreenThing.lens(Unit::default()).padding(5.), 1.)
373        .with_spacer(VERTICAL_WIDGET_SPACING)
374        .with_child(textbox)
375        .with_child(button)
376        .with_child(check_box);
377
378    // center the two widgets in the available space
379    Align::centered(layout)
380}
Source

pub fn with_min_size(self, size: impl Into<Size>) -> Self

Set the window’s minimum drawing area size in display points.

The actual minimum window size in pixels will depend on the platform DPI settings.

This should be considered a request to the platform to set the minimum size of the window. The platform might increase the size a tiny bit due to DPI.

To set the window’s initial drawing area size use window_size.

Source

pub fn resizable(self, resizable: bool) -> Self

Set whether the window should be resizable.

Source

pub fn show_titlebar(self, show_titlebar: bool) -> Self

Set whether the window should have a titlebar and decorations.

Examples found in repository?
examples/sub_window.rs (line 151)
99    fn event(&mut self, child: &mut W, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) {
100        let wait_duration = Duration::from_millis(500);
101        let resched_dur = Duration::from_millis(50);
102        let cursor_size = Size::new(15., 15.);
103        let now = Instant::now();
104        let new_state = match &self.state {
105            TooltipState::Fresh => match event {
106                Event::MouseMove(me) if ctx.is_hot() => Some(TooltipState::Waiting {
107                    last_move: now,
108                    timer_expire: now + wait_duration,
109                    token: ctx.request_timer(wait_duration),
110                    position_in_window_coordinates: me.window_pos,
111                }),
112                _ => None,
113            },
114            TooltipState::Waiting {
115                last_move,
116                timer_expire,
117                token,
118                position_in_window_coordinates,
119            } => match event {
120                Event::MouseMove(me) if ctx.is_hot() => {
121                    let (cur_token, cur_expire) = if *timer_expire - now < resched_dur {
122                        (ctx.request_timer(wait_duration), now + wait_duration)
123                    } else {
124                        (*token, *timer_expire)
125                    };
126                    Some(TooltipState::Waiting {
127                        last_move: now,
128                        timer_expire: cur_expire,
129                        token: cur_token,
130                        position_in_window_coordinates: me.window_pos,
131                    })
132                }
133                Event::Timer(tok) if tok == token => {
134                    let deadline = *last_move + wait_duration;
135                    ctx.set_handled();
136                    if deadline > now {
137                        let wait_for = deadline - now;
138                        tracing::info!("Waiting another {:?}", wait_for);
139                        Some(TooltipState::Waiting {
140                            last_move: *last_move,
141                            timer_expire: deadline,
142                            token: ctx.request_timer(wait_for),
143                            position_in_window_coordinates: *position_in_window_coordinates,
144                        })
145                    } else {
146                        let tooltip_position_in_window_coordinates =
147                            (position_in_window_coordinates.to_vec2() + cursor_size.to_vec2())
148                                .to_point();
149                        let win_id = ctx.new_sub_window(
150                            WindowConfig::default()
151                                .show_titlebar(false)
152                                .window_size_policy(WindowSizePolicy::Content)
153                                .set_level(WindowLevel::Tooltip(ctx.window().clone()))
154                                .set_position(tooltip_position_in_window_coordinates),
155                            Label::<()>::new(self.tip.clone()),
156                            (),
157                            env.clone(),
158                        );
159                        Some(TooltipState::Showing(win_id))
160                    }
161                }
162                _ => None,
163            },
164            TooltipState::Showing(win_id) => {
165                match event {
166                    Event::MouseMove(me) if !ctx.is_hot() => {
167                        // TODO another timer on leaving
168                        tracing::info!("Sending close window for {:?}", win_id);
169                        ctx.submit_command(CLOSE_WINDOW.to(*win_id));
170                        Some(TooltipState::Waiting {
171                            last_move: now,
172                            timer_expire: now + wait_duration,
173                            token: ctx.request_timer(wait_duration),
174                            position_in_window_coordinates: me.window_pos,
175                        })
176                    }
177                    _ => None,
178                }
179            }
180        };
181
182        if let Some(state) = new_state {
183            self.state = state;
184        }
185
186        if !ctx.is_handled() {
187            child.event(ctx, event, data, env);
188        }
189    }
190
191    fn lifecycle(
192        &mut self,
193        child: &mut W,
194        ctx: &mut LifeCycleCtx,
195        event: &LifeCycle,
196        data: &T,
197        env: &Env,
198    ) {
199        if let LifeCycle::HotChanged(false) = event {
200            if let TooltipState::Showing(win_id) = self.state {
201                ctx.submit_command(CLOSE_WINDOW.to(win_id));
202            }
203            self.state = TooltipState::Fresh;
204        }
205        child.lifecycle(ctx, event, data, env)
206    }
207}
208
209struct DragWindowController {
210    init_pos: Option<Point>,
211    //dragging: bool
212}
213
214impl DragWindowController {
215    pub fn new() -> Self {
216        DragWindowController { init_pos: None }
217    }
218}
219
220impl<T, W: Widget<T>> Controller<T, W> for DragWindowController {
221    fn event(&mut self, child: &mut W, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) {
222        match event {
223            Event::MouseDown(me) if me.buttons.has_left() => {
224                ctx.set_active(true);
225                self.init_pos = Some(me.window_pos)
226            }
227            Event::MouseMove(me) if ctx.is_active() && me.buttons.has_left() => {
228                if let Some(init_pos) = self.init_pos {
229                    let within_window_change = me.window_pos.to_vec2() - init_pos.to_vec2();
230                    let old_pos = ctx.window().get_position();
231                    let new_pos = old_pos + within_window_change;
232                    tracing::info!(
233                        "Drag {:?} ",
234                        (
235                            init_pos,
236                            me.window_pos,
237                            within_window_change,
238                            old_pos,
239                            new_pos
240                        )
241                    );
242                    ctx.window().set_position(new_pos)
243                }
244            }
245            Event::MouseUp(_me) if ctx.is_active() => {
246                self.init_pos = None;
247                ctx.set_active(false)
248            }
249            _ => (),
250        }
251        child.event(ctx, event, data, env)
252    }
253}
254
255struct ScreenThing;
256
257impl Widget<()> for ScreenThing {
258    fn event(&mut self, _ctx: &mut EventCtx, _event: &Event, _data: &mut (), _env: &Env) {}
259
260    fn lifecycle(&mut self, _ctx: &mut LifeCycleCtx, _event: &LifeCycle, _data: &(), _env: &Env) {}
261
262    fn update(&mut self, _ctx: &mut UpdateCtx, _old_data: &(), _data: &(), _env: &Env) {}
263
264    fn layout(
265        &mut self,
266        _ctx: &mut LayoutCtx,
267        bc: &BoxConstraints,
268        _data: &(),
269        _env: &Env,
270    ) -> Size {
271        bc.constrain(Size::new(800.0, 600.0))
272    }
273
274    fn paint(&mut self, ctx: &mut PaintCtx, _data: &(), env: &Env) {
275        let sz = ctx.size();
276
277        let monitors = Screen::get_monitors();
278        let all = monitors
279            .iter()
280            .map(|x| x.virtual_rect())
281            .fold(Rect::ZERO, |s, r| r.union(s));
282        if all.width() > 0. && all.height() > 0. {
283            let trans = Affine::scale(f64::min(sz.width / all.width(), sz.height / all.height()))
284                * Affine::translate(all.origin().to_vec2()).inverse();
285            let font = env.get(theme::UI_FONT).family;
286
287            for (i, mon) in monitors.iter().enumerate() {
288                let vr = mon.virtual_rect();
289                let tr = trans.transform_rect_bbox(vr);
290                ctx.stroke(tr, &Color::WHITE, 1.0);
291
292                if let Ok(tl) = ctx
293                    .text()
294                    .new_text_layout(format!(
295                        "{}:{}x{}@{},{}",
296                        i,
297                        vr.width(),
298                        vr.height(),
299                        vr.x0,
300                        vr.y0
301                    ))
302                    .max_width(tr.width() - 5.)
303                    .font(font.clone(), env.get(theme::TEXT_SIZE_NORMAL))
304                    .text_color(Color::WHITE)
305                    .build()
306                {
307                    ctx.draw_text(&tl, tr.center() - tl.size().to_vec2() * 0.5);
308                }
309            }
310        }
311    }
312}
313
314struct CancelClose;
315
316impl<W: Widget<bool>> Controller<bool, W> for CancelClose {
317    fn event(
318        &mut self,
319        w: &mut W,
320        ctx: &mut EventCtx<'_, '_>,
321        event: &Event,
322        data: &mut bool,
323        env: &Env,
324    ) {
325        match (&data, event) {
326            (false, Event::WindowCloseRequested) => ctx.set_handled(),
327            _ => w.event(ctx, event, data, env),
328        }
329    }
330}
331
332fn build_root_widget() -> impl Widget<HelloState> {
333    let label = EnvScope::new(
334        |env, _t| env.set(theme::TEXT_COLOR, env.get(theme::PRIMARY_LIGHT)),
335        ControllerHost::new(
336            Label::new(|data: &HelloState, _env: &Env| {
337                format!("Hello {}! {} ", data.name, data.sub.my_stuff)
338            }),
339            TooltipController::new("Tips! Are good"),
340        ),
341    );
342    // a textbox that modifies `name`.
343    let textbox = TextBox::new()
344        .with_placeholder("Who are we greeting?")
345        .fix_width(TEXT_BOX_WIDTH)
346        .lens(HelloState::sub.then(SubState::my_stuff));
347
348    let button = Button::new("Make sub window")
349        .on_click(|ctx, data: &mut SubState, env| {
350            let tb = TextBox::new().lens(SubState::my_stuff);
351            let drag_thing = Label::new("Drag me").controller(DragWindowController::new());
352            let col = Flex::column().with_child(drag_thing).with_child(tb);
353
354            ctx.new_sub_window(
355                WindowConfig::default()
356                    .show_titlebar(false)
357                    .window_size(Size::new(100., 100.))
358                    .set_level(WindowLevel::AppWindow),
359                col,
360                data.clone(),
361                env.clone(),
362            );
363        })
364        .center()
365        .lens(HelloState::sub);
366
367    let check_box =
368        ControllerHost::new(Checkbox::new("Closeable?"), CancelClose).lens(HelloState::closeable);
369    // arrange the two widgets vertically, with some padding
370    let layout = Flex::column()
371        .with_child(label)
372        .with_flex_child(ScreenThing.lens(Unit::default()).padding(5.), 1.)
373        .with_spacer(VERTICAL_WIDGET_SPACING)
374        .with_child(textbox)
375        .with_child(button)
376        .with_child(check_box);
377
378    // center the two widgets in the available space
379    Align::centered(layout)
380}
Source

pub fn set_position(self, position: Point) -> Self

Sets the window position in virtual screen coordinates. position Position in pixels.

Examples found in repository?
examples/sub_window.rs (line 154)
99    fn event(&mut self, child: &mut W, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) {
100        let wait_duration = Duration::from_millis(500);
101        let resched_dur = Duration::from_millis(50);
102        let cursor_size = Size::new(15., 15.);
103        let now = Instant::now();
104        let new_state = match &self.state {
105            TooltipState::Fresh => match event {
106                Event::MouseMove(me) if ctx.is_hot() => Some(TooltipState::Waiting {
107                    last_move: now,
108                    timer_expire: now + wait_duration,
109                    token: ctx.request_timer(wait_duration),
110                    position_in_window_coordinates: me.window_pos,
111                }),
112                _ => None,
113            },
114            TooltipState::Waiting {
115                last_move,
116                timer_expire,
117                token,
118                position_in_window_coordinates,
119            } => match event {
120                Event::MouseMove(me) if ctx.is_hot() => {
121                    let (cur_token, cur_expire) = if *timer_expire - now < resched_dur {
122                        (ctx.request_timer(wait_duration), now + wait_duration)
123                    } else {
124                        (*token, *timer_expire)
125                    };
126                    Some(TooltipState::Waiting {
127                        last_move: now,
128                        timer_expire: cur_expire,
129                        token: cur_token,
130                        position_in_window_coordinates: me.window_pos,
131                    })
132                }
133                Event::Timer(tok) if tok == token => {
134                    let deadline = *last_move + wait_duration;
135                    ctx.set_handled();
136                    if deadline > now {
137                        let wait_for = deadline - now;
138                        tracing::info!("Waiting another {:?}", wait_for);
139                        Some(TooltipState::Waiting {
140                            last_move: *last_move,
141                            timer_expire: deadline,
142                            token: ctx.request_timer(wait_for),
143                            position_in_window_coordinates: *position_in_window_coordinates,
144                        })
145                    } else {
146                        let tooltip_position_in_window_coordinates =
147                            (position_in_window_coordinates.to_vec2() + cursor_size.to_vec2())
148                                .to_point();
149                        let win_id = ctx.new_sub_window(
150                            WindowConfig::default()
151                                .show_titlebar(false)
152                                .window_size_policy(WindowSizePolicy::Content)
153                                .set_level(WindowLevel::Tooltip(ctx.window().clone()))
154                                .set_position(tooltip_position_in_window_coordinates),
155                            Label::<()>::new(self.tip.clone()),
156                            (),
157                            env.clone(),
158                        );
159                        Some(TooltipState::Showing(win_id))
160                    }
161                }
162                _ => None,
163            },
164            TooltipState::Showing(win_id) => {
165                match event {
166                    Event::MouseMove(me) if !ctx.is_hot() => {
167                        // TODO another timer on leaving
168                        tracing::info!("Sending close window for {:?}", win_id);
169                        ctx.submit_command(CLOSE_WINDOW.to(*win_id));
170                        Some(TooltipState::Waiting {
171                            last_move: now,
172                            timer_expire: now + wait_duration,
173                            token: ctx.request_timer(wait_duration),
174                            position_in_window_coordinates: me.window_pos,
175                        })
176                    }
177                    _ => None,
178                }
179            }
180        };
181
182        if let Some(state) = new_state {
183            self.state = state;
184        }
185
186        if !ctx.is_handled() {
187            child.event(ctx, event, data, env);
188        }
189    }
Source

pub fn set_level(self, level: WindowLevel) -> Self

Sets the WindowLevel of the window

Examples found in repository?
examples/sub_window.rs (line 153)
99    fn event(&mut self, child: &mut W, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) {
100        let wait_duration = Duration::from_millis(500);
101        let resched_dur = Duration::from_millis(50);
102        let cursor_size = Size::new(15., 15.);
103        let now = Instant::now();
104        let new_state = match &self.state {
105            TooltipState::Fresh => match event {
106                Event::MouseMove(me) if ctx.is_hot() => Some(TooltipState::Waiting {
107                    last_move: now,
108                    timer_expire: now + wait_duration,
109                    token: ctx.request_timer(wait_duration),
110                    position_in_window_coordinates: me.window_pos,
111                }),
112                _ => None,
113            },
114            TooltipState::Waiting {
115                last_move,
116                timer_expire,
117                token,
118                position_in_window_coordinates,
119            } => match event {
120                Event::MouseMove(me) if ctx.is_hot() => {
121                    let (cur_token, cur_expire) = if *timer_expire - now < resched_dur {
122                        (ctx.request_timer(wait_duration), now + wait_duration)
123                    } else {
124                        (*token, *timer_expire)
125                    };
126                    Some(TooltipState::Waiting {
127                        last_move: now,
128                        timer_expire: cur_expire,
129                        token: cur_token,
130                        position_in_window_coordinates: me.window_pos,
131                    })
132                }
133                Event::Timer(tok) if tok == token => {
134                    let deadline = *last_move + wait_duration;
135                    ctx.set_handled();
136                    if deadline > now {
137                        let wait_for = deadline - now;
138                        tracing::info!("Waiting another {:?}", wait_for);
139                        Some(TooltipState::Waiting {
140                            last_move: *last_move,
141                            timer_expire: deadline,
142                            token: ctx.request_timer(wait_for),
143                            position_in_window_coordinates: *position_in_window_coordinates,
144                        })
145                    } else {
146                        let tooltip_position_in_window_coordinates =
147                            (position_in_window_coordinates.to_vec2() + cursor_size.to_vec2())
148                                .to_point();
149                        let win_id = ctx.new_sub_window(
150                            WindowConfig::default()
151                                .show_titlebar(false)
152                                .window_size_policy(WindowSizePolicy::Content)
153                                .set_level(WindowLevel::Tooltip(ctx.window().clone()))
154                                .set_position(tooltip_position_in_window_coordinates),
155                            Label::<()>::new(self.tip.clone()),
156                            (),
157                            env.clone(),
158                        );
159                        Some(TooltipState::Showing(win_id))
160                    }
161                }
162                _ => None,
163            },
164            TooltipState::Showing(win_id) => {
165                match event {
166                    Event::MouseMove(me) if !ctx.is_hot() => {
167                        // TODO another timer on leaving
168                        tracing::info!("Sending close window for {:?}", win_id);
169                        ctx.submit_command(CLOSE_WINDOW.to(*win_id));
170                        Some(TooltipState::Waiting {
171                            last_move: now,
172                            timer_expire: now + wait_duration,
173                            token: ctx.request_timer(wait_duration),
174                            position_in_window_coordinates: me.window_pos,
175                        })
176                    }
177                    _ => None,
178                }
179            }
180        };
181
182        if let Some(state) = new_state {
183            self.state = state;
184        }
185
186        if !ctx.is_handled() {
187            child.event(ctx, event, data, env);
188        }
189    }
190
191    fn lifecycle(
192        &mut self,
193        child: &mut W,
194        ctx: &mut LifeCycleCtx,
195        event: &LifeCycle,
196        data: &T,
197        env: &Env,
198    ) {
199        if let LifeCycle::HotChanged(false) = event {
200            if let TooltipState::Showing(win_id) = self.state {
201                ctx.submit_command(CLOSE_WINDOW.to(win_id));
202            }
203            self.state = TooltipState::Fresh;
204        }
205        child.lifecycle(ctx, event, data, env)
206    }
207}
208
209struct DragWindowController {
210    init_pos: Option<Point>,
211    //dragging: bool
212}
213
214impl DragWindowController {
215    pub fn new() -> Self {
216        DragWindowController { init_pos: None }
217    }
218}
219
220impl<T, W: Widget<T>> Controller<T, W> for DragWindowController {
221    fn event(&mut self, child: &mut W, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) {
222        match event {
223            Event::MouseDown(me) if me.buttons.has_left() => {
224                ctx.set_active(true);
225                self.init_pos = Some(me.window_pos)
226            }
227            Event::MouseMove(me) if ctx.is_active() && me.buttons.has_left() => {
228                if let Some(init_pos) = self.init_pos {
229                    let within_window_change = me.window_pos.to_vec2() - init_pos.to_vec2();
230                    let old_pos = ctx.window().get_position();
231                    let new_pos = old_pos + within_window_change;
232                    tracing::info!(
233                        "Drag {:?} ",
234                        (
235                            init_pos,
236                            me.window_pos,
237                            within_window_change,
238                            old_pos,
239                            new_pos
240                        )
241                    );
242                    ctx.window().set_position(new_pos)
243                }
244            }
245            Event::MouseUp(_me) if ctx.is_active() => {
246                self.init_pos = None;
247                ctx.set_active(false)
248            }
249            _ => (),
250        }
251        child.event(ctx, event, data, env)
252    }
253}
254
255struct ScreenThing;
256
257impl Widget<()> for ScreenThing {
258    fn event(&mut self, _ctx: &mut EventCtx, _event: &Event, _data: &mut (), _env: &Env) {}
259
260    fn lifecycle(&mut self, _ctx: &mut LifeCycleCtx, _event: &LifeCycle, _data: &(), _env: &Env) {}
261
262    fn update(&mut self, _ctx: &mut UpdateCtx, _old_data: &(), _data: &(), _env: &Env) {}
263
264    fn layout(
265        &mut self,
266        _ctx: &mut LayoutCtx,
267        bc: &BoxConstraints,
268        _data: &(),
269        _env: &Env,
270    ) -> Size {
271        bc.constrain(Size::new(800.0, 600.0))
272    }
273
274    fn paint(&mut self, ctx: &mut PaintCtx, _data: &(), env: &Env) {
275        let sz = ctx.size();
276
277        let monitors = Screen::get_monitors();
278        let all = monitors
279            .iter()
280            .map(|x| x.virtual_rect())
281            .fold(Rect::ZERO, |s, r| r.union(s));
282        if all.width() > 0. && all.height() > 0. {
283            let trans = Affine::scale(f64::min(sz.width / all.width(), sz.height / all.height()))
284                * Affine::translate(all.origin().to_vec2()).inverse();
285            let font = env.get(theme::UI_FONT).family;
286
287            for (i, mon) in monitors.iter().enumerate() {
288                let vr = mon.virtual_rect();
289                let tr = trans.transform_rect_bbox(vr);
290                ctx.stroke(tr, &Color::WHITE, 1.0);
291
292                if let Ok(tl) = ctx
293                    .text()
294                    .new_text_layout(format!(
295                        "{}:{}x{}@{},{}",
296                        i,
297                        vr.width(),
298                        vr.height(),
299                        vr.x0,
300                        vr.y0
301                    ))
302                    .max_width(tr.width() - 5.)
303                    .font(font.clone(), env.get(theme::TEXT_SIZE_NORMAL))
304                    .text_color(Color::WHITE)
305                    .build()
306                {
307                    ctx.draw_text(&tl, tr.center() - tl.size().to_vec2() * 0.5);
308                }
309            }
310        }
311    }
312}
313
314struct CancelClose;
315
316impl<W: Widget<bool>> Controller<bool, W> for CancelClose {
317    fn event(
318        &mut self,
319        w: &mut W,
320        ctx: &mut EventCtx<'_, '_>,
321        event: &Event,
322        data: &mut bool,
323        env: &Env,
324    ) {
325        match (&data, event) {
326            (false, Event::WindowCloseRequested) => ctx.set_handled(),
327            _ => w.event(ctx, event, data, env),
328        }
329    }
330}
331
332fn build_root_widget() -> impl Widget<HelloState> {
333    let label = EnvScope::new(
334        |env, _t| env.set(theme::TEXT_COLOR, env.get(theme::PRIMARY_LIGHT)),
335        ControllerHost::new(
336            Label::new(|data: &HelloState, _env: &Env| {
337                format!("Hello {}! {} ", data.name, data.sub.my_stuff)
338            }),
339            TooltipController::new("Tips! Are good"),
340        ),
341    );
342    // a textbox that modifies `name`.
343    let textbox = TextBox::new()
344        .with_placeholder("Who are we greeting?")
345        .fix_width(TEXT_BOX_WIDTH)
346        .lens(HelloState::sub.then(SubState::my_stuff));
347
348    let button = Button::new("Make sub window")
349        .on_click(|ctx, data: &mut SubState, env| {
350            let tb = TextBox::new().lens(SubState::my_stuff);
351            let drag_thing = Label::new("Drag me").controller(DragWindowController::new());
352            let col = Flex::column().with_child(drag_thing).with_child(tb);
353
354            ctx.new_sub_window(
355                WindowConfig::default()
356                    .show_titlebar(false)
357                    .window_size(Size::new(100., 100.))
358                    .set_level(WindowLevel::AppWindow),
359                col,
360                data.clone(),
361                env.clone(),
362            );
363        })
364        .center()
365        .lens(HelloState::sub);
366
367    let check_box =
368        ControllerHost::new(Checkbox::new("Closeable?"), CancelClose).lens(HelloState::closeable);
369    // arrange the two widgets vertically, with some padding
370    let layout = Flex::column()
371        .with_child(label)
372        .with_flex_child(ScreenThing.lens(Unit::default()).padding(5.), 1.)
373        .with_spacer(VERTICAL_WIDGET_SPACING)
374        .with_child(textbox)
375        .with_child(button)
376        .with_child(check_box);
377
378    // center the two widgets in the available space
379    Align::centered(layout)
380}
Source

pub fn set_always_on_top(self, always_on_top: bool) -> Self

Sets whether the window is always on top.

An always on top window stays on top, even after clicking off of it.

Source

pub fn set_window_state(self, state: WindowState) -> Self

Sets the WindowState of the window.

Source

pub fn transparent(self, transparent: bool) -> Self

Set whether the window background should be transparent

Source

pub fn apply_to_builder(&self, builder: &mut WindowBuilder)

Apply this window configuration to the passed in WindowBuilder

Source

pub fn apply_to_handle(&self, win_handle: &mut WindowHandle)

Apply this window configuration to the passed in WindowHandle

Trait Implementations§

Source§

impl Default for WindowConfig

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl PartialEq for WindowConfig

Source§

fn eq(&self, other: &WindowConfig) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl StructuralPartialEq for WindowConfig

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> AnyEq for T
where T: Any + PartialEq,

Source§

fn equals(&self, other: &(dyn Any + 'static)) -> bool

Source§

fn as_any(&self) -> &(dyn Any + 'static)

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> RoundFrom<T> for T

Source§

fn round_from(x: T) -> T

Performs the conversion.
Source§

impl<T, U> RoundInto<U> for T
where U: RoundFrom<T>,

Source§

fn round_into(self) -> U

Performs the conversion.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more