Struct kas_core::theme::DrawMgr

source ·
pub struct DrawMgr<'a> { /* private fields */ }
Expand description

Draw interface

This interface is provided to widgets in crate::Layout::draw. Lower-level interfaces may be accessed through Self::draw_device.

DrawMgr is not a Copy or Clone type; instead it may be “reborrowed” via Self::re_id or Self::re_clone.

  • draw.check_box(&*self, self.state); — note &*self to convert from to &W from &mut W, since the latter would cause borrow conflicts

Implementations§

Reborrow with a new lifetime and new id

Rust allows references like &T or &mut T to be “reborrowed” through coercion: essentially, the pointer is copied under a new, shorter, lifetime. Until rfcs#1403 lands, reborrows on user types require a method call.

Examples found in repository?
src/theme/draw.rs (line 85)
84
85
86
    pub fn recurse(&mut self, child: &mut dyn Widget) {
        child.draw(self.re_id(child.id()));
    }

Reborrow with a new lifetime and same id

Rust allows references like &T or &mut T to be “reborrowed” through coercion: essentially, the pointer is copied under a new, shorter, lifetime. Until rfcs#1403 lands, reborrows on user types require a method call.

Examples found in repository?
src/layout/visitor.rs (line 366)
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
    fn draw(&mut self, mut draw: DrawMgr) {
        for child in &mut self.children {
            child.draw(draw.re_clone());
        }
    }
}

/// Float layout
struct Float<'a, I>
where
    I: DoubleEndedIterator<Item = Visitor<'a>>,
{
    children: I,
}

impl<'a, I> Layout for Float<'a, I>
where
    I: DoubleEndedIterator<Item = Visitor<'a>>,
{
    fn size_rules(&mut self, mgr: SizeMgr, axis: AxisInfo) -> SizeRules {
        let mut rules = SizeRules::EMPTY;
        for child in &mut self.children {
            rules = rules.max(child.size_rules(mgr.re(), axis));
        }
        rules
    }

    fn set_rect(&mut self, mgr: &mut ConfigMgr, rect: Rect) {
        for child in &mut self.children {
            child.set_rect(mgr, rect);
        }
    }

    fn find_id(&mut self, coord: Coord) -> Option<WidgetId> {
        self.children.find_map(|child| child.find_id(coord))
    }

    fn draw(&mut self, mut draw: DrawMgr) {
        let mut iter = (&mut self.children).rev();
        if let Some(first) = iter.next() {
            first.draw(draw.re_clone());
        }
        for child in iter {
            draw.with_pass(|draw| child.draw(draw));
        }
    }
}

/// A row/column over a slice
struct Slice<'a, W: Widget, D: Directional> {
    data: &'a mut DynRowStorage,
    direction: D,
    children: &'a mut [W],
}

impl<'a, W: Widget, D: Directional> Layout for Slice<'a, W, D> {
    fn size_rules(&mut self, mgr: SizeMgr, axis: AxisInfo) -> SizeRules {
        let dim = (self.direction, self.children.len());
        let mut solver = RowSolver::new(axis, dim, self.data);
        for (n, child) in self.children.iter_mut().enumerate() {
            solver.for_child(self.data, n, |axis| child.size_rules(mgr.re(), axis));
        }
        solver.finish(self.data)
    }

    fn set_rect(&mut self, mgr: &mut ConfigMgr, rect: Rect) {
        let dim = (self.direction, self.children.len());
        let mut setter = RowSetter::<D, Vec<i32>, _>::new(rect, dim, self.data);

        for (n, child) in self.children.iter_mut().enumerate() {
            child.set_rect(mgr, setter.child_rect(self.data, n));
        }
    }

    fn find_id(&mut self, coord: Coord) -> Option<WidgetId> {
        let solver = RowPositionSolver::new(self.direction);
        solver
            .find_child_mut(self.children, coord)
            .and_then(|child| child.find_id(coord))
    }

    fn draw(&mut self, mut draw: DrawMgr) {
        let solver = RowPositionSolver::new(self.direction);
        solver.for_children(self.children, draw.get_clip_rect(), |w| draw.recurse(w));
    }
}

/// Implement grid layout for children
struct Grid<'a, S, I> {
    data: &'a mut S,
    dim: GridDimensions,
    children: I,
}

impl<'a, S: GridStorage, I> Layout for Grid<'a, S, I>
where
    I: Iterator<Item = (GridChildInfo, Visitor<'a>)>,
{
    fn size_rules(&mut self, mgr: SizeMgr, axis: AxisInfo) -> SizeRules {
        let mut solver = GridSolver::<Vec<_>, Vec<_>, _>::new(axis, self.dim, self.data);
        for (info, child) in &mut self.children {
            solver.for_child(self.data, info, |axis| child.size_rules(mgr.re(), axis));
        }
        solver.finish(self.data)
    }

    fn set_rect(&mut self, mgr: &mut ConfigMgr, rect: Rect) {
        let mut setter = GridSetter::<Vec<_>, Vec<_>, _>::new(rect, self.dim, self.data);
        for (info, child) in &mut self.children {
            child.set_rect(mgr, setter.child_rect(self.data, info));
        }
    }

    fn find_id(&mut self, coord: Coord) -> Option<WidgetId> {
        // TODO(opt): more efficient search strategy?
        self.children.find_map(|(_, child)| child.find_id(coord))
    }

    fn draw(&mut self, mut draw: DrawMgr) {
        for (_, child) in &mut self.children {
            child.draw(draw.re_clone());
        }
    }

Recurse drawing to a child

Examples found in repository?
src/root.rs (line 60)
59
60
61
62
63
64
65
66
67
68
        fn draw(&mut self, mut draw: DrawMgr) {
            draw.recurse(&mut self.w);
            for (_, popup) in &self.popups {
                if let Some(widget) = self.w.find_widget_mut(&popup.id) {
                    draw.with_overlay(widget.rect(), |mut draw| {
                        draw.recurse(widget);
                    });
                }
            }
        }
More examples
Hide additional examples
src/layout/visitor.rs (line 310)
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
    fn draw_(&mut self, mut draw: DrawMgr) {
        match &mut self.layout {
            LayoutType::None => (),
            LayoutType::Component(component) => component.draw(draw),
            LayoutType::BoxComponent(layout) => layout.draw(draw),
            LayoutType::Single(child) | LayoutType::AlignSingle(child, _) => draw.recurse(*child),
            LayoutType::Align(layout, _) => layout.draw_(draw),
            LayoutType::Pack(layout, _, _) => layout.draw_(draw),
            LayoutType::Margins(layout, _, _) => layout.draw_(draw),
            LayoutType::Frame(child, storage, style) => {
                draw.frame(storage.rect, *style, Background::Default);
                child.draw_(draw);
            }
            LayoutType::Button(child, storage, color) => {
                let bg = match color {
                    Some(rgb) => Background::Rgb(*rgb),
                    None => Background::Default,
                };
                draw.frame(storage.rect, FrameStyle::Button, bg);
                child.draw_(draw);
            }
        }
    }
}

/// Implement row/column layout for children
struct List<'a, S, D, I> {
    data: &'a mut S,
    direction: D,
    children: I,
}

impl<'a, S: RowStorage, D: Directional, I> Layout for List<'a, S, D, I>
where
    I: ExactSizeIterator<Item = Visitor<'a>>,
{
    fn size_rules(&mut self, mgr: SizeMgr, axis: AxisInfo) -> SizeRules {
        let dim = (self.direction, self.children.len());
        let mut solver = RowSolver::new(axis, dim, self.data);
        for (n, child) in (&mut self.children).enumerate() {
            solver.for_child(self.data, n, |axis| child.size_rules(mgr.re(), axis));
        }
        solver.finish(self.data)
    }

    fn set_rect(&mut self, mgr: &mut ConfigMgr, rect: Rect) {
        let dim = (self.direction, self.children.len());
        let mut setter = RowSetter::<D, Vec<i32>, _>::new(rect, dim, self.data);

        for (n, child) in (&mut self.children).enumerate() {
            child.set_rect(mgr, setter.child_rect(self.data, n));
        }
    }

    fn find_id(&mut self, coord: Coord) -> Option<WidgetId> {
        // TODO(opt): more efficient search strategy?
        self.children.find_map(|child| child.find_id(coord))
    }

    fn draw(&mut self, mut draw: DrawMgr) {
        for child in &mut self.children {
            child.draw(draw.re_clone());
        }
    }
}

/// Float layout
struct Float<'a, I>
where
    I: DoubleEndedIterator<Item = Visitor<'a>>,
{
    children: I,
}

impl<'a, I> Layout for Float<'a, I>
where
    I: DoubleEndedIterator<Item = Visitor<'a>>,
{
    fn size_rules(&mut self, mgr: SizeMgr, axis: AxisInfo) -> SizeRules {
        let mut rules = SizeRules::EMPTY;
        for child in &mut self.children {
            rules = rules.max(child.size_rules(mgr.re(), axis));
        }
        rules
    }

    fn set_rect(&mut self, mgr: &mut ConfigMgr, rect: Rect) {
        for child in &mut self.children {
            child.set_rect(mgr, rect);
        }
    }

    fn find_id(&mut self, coord: Coord) -> Option<WidgetId> {
        self.children.find_map(|child| child.find_id(coord))
    }

    fn draw(&mut self, mut draw: DrawMgr) {
        let mut iter = (&mut self.children).rev();
        if let Some(first) = iter.next() {
            first.draw(draw.re_clone());
        }
        for child in iter {
            draw.with_pass(|draw| child.draw(draw));
        }
    }
}

/// A row/column over a slice
struct Slice<'a, W: Widget, D: Directional> {
    data: &'a mut DynRowStorage,
    direction: D,
    children: &'a mut [W],
}

impl<'a, W: Widget, D: Directional> Layout for Slice<'a, W, D> {
    fn size_rules(&mut self, mgr: SizeMgr, axis: AxisInfo) -> SizeRules {
        let dim = (self.direction, self.children.len());
        let mut solver = RowSolver::new(axis, dim, self.data);
        for (n, child) in self.children.iter_mut().enumerate() {
            solver.for_child(self.data, n, |axis| child.size_rules(mgr.re(), axis));
        }
        solver.finish(self.data)
    }

    fn set_rect(&mut self, mgr: &mut ConfigMgr, rect: Rect) {
        let dim = (self.direction, self.children.len());
        let mut setter = RowSetter::<D, Vec<i32>, _>::new(rect, dim, self.data);

        for (n, child) in self.children.iter_mut().enumerate() {
            child.set_rect(mgr, setter.child_rect(self.data, n));
        }
    }

    fn find_id(&mut self, coord: Coord) -> Option<WidgetId> {
        let solver = RowPositionSolver::new(self.direction);
        solver
            .find_child_mut(self.children, coord)
            .and_then(|child| child.find_id(coord))
    }

    fn draw(&mut self, mut draw: DrawMgr) {
        let solver = RowPositionSolver::new(self.direction);
        solver.for_children(self.children, draw.get_clip_rect(), |w| draw.recurse(w));
    }

Access event-management state

Access a SizeMgr

Access a ConfigMgr

Access a DrawShared

Access the low-level draw device

Note: this drawing API is modular, with limited functionality in the base trait Draw. To access further functionality, it is necessary to downcast with crate::draw::DrawIface::downcast_from.

Examples found in repository?
src/theme/draw.rs (line 130)
129
130
131
    pub fn draw_iface<DS: DrawSharedImpl>(&mut self) -> Option<DrawIface<DS>> {
        DrawIface::downcast_from(self.draw_device())
    }

Access the low-level draw device (implementation type)

The implementing type must be specified. See DrawIface::downcast_from.

Draw to a new pass

Adds a new draw pass for purposes of enforcing draw order. Content of the new pass will be drawn after content in the parent pass.

Examples found in repository?
src/layout/visitor.rs (line 407)
401
402
403
404
405
406
407
408
409
    fn draw(&mut self, mut draw: DrawMgr) {
        let mut iter = (&mut self.children).rev();
        if let Some(first) = iter.next() {
            first.draw(draw.re_clone());
        }
        for child in iter {
            draw.with_pass(|draw| child.draw(draw));
        }
    }

Draw to a new pass with clipping and offset (e.g. for scrolling)

Adds a new draw pass of type PassType::Clip, with draw operations clipped to rect and translated by `offset.

Draw to a new pass as an overlay (e.g. for pop-up menus)

Adds a new draw pass of type PassType::Overlay, with draw operations clipped to rect.

The theme is permitted to enlarge the rect for the purpose of drawing a frame or shadow around this overlay, thus the Self::get_clip_rect may be larger than expected.

Examples found in repository?
src/root.rs (lines 63-65)
59
60
61
62
63
64
65
66
67
68
        fn draw(&mut self, mut draw: DrawMgr) {
            draw.recurse(&mut self.w);
            for (_, popup) in &self.popups {
                if let Some(widget) = self.w.find_widget_mut(&popup.id) {
                    draw.with_overlay(widget.rect(), |mut draw| {
                        draw.recurse(widget);
                    });
                }
            }
        }

Target area for drawing

Drawing is restricted to this Rect, which may be the whole window, a clip region or an overlay. This may be used to cull hidden items from lists inside a scrollable view.

Examples found in repository?
src/layout/visitor.rs (line 447)
445
446
447
448
    fn draw(&mut self, mut draw: DrawMgr) {
        let solver = RowPositionSolver::new(self.direction);
        solver.for_children(self.children, draw.get_clip_rect(), |w| draw.recurse(w));
    }

Draw a frame inside the given rect

The frame dimensions are given by SizeMgr::frame.

Examples found in repository?
src/layout/visitor.rs (line 315)
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
    fn draw_(&mut self, mut draw: DrawMgr) {
        match &mut self.layout {
            LayoutType::None => (),
            LayoutType::Component(component) => component.draw(draw),
            LayoutType::BoxComponent(layout) => layout.draw(draw),
            LayoutType::Single(child) | LayoutType::AlignSingle(child, _) => draw.recurse(*child),
            LayoutType::Align(layout, _) => layout.draw_(draw),
            LayoutType::Pack(layout, _, _) => layout.draw_(draw),
            LayoutType::Margins(layout, _, _) => layout.draw_(draw),
            LayoutType::Frame(child, storage, style) => {
                draw.frame(storage.rect, *style, Background::Default);
                child.draw_(draw);
            }
            LayoutType::Button(child, storage, color) => {
                let bg = match color {
                    Some(rgb) => Background::Rgb(*rgb),
                    None => Background::Default,
                };
                draw.frame(storage.rect, FrameStyle::Button, bg);
                child.draw_(draw);
            }
        }
    }

Draw a separator in the given rect

Draw a selection box

This appears as a dashed box or similar around this rect. Note that the selection indicator is drawn outside of this rect, within a margin of size SizeMgr::inner_margins that is expected to be present around this box.

Draw text

Text is drawn from rect.pos and clipped to rect. If the text scrolls, rect should be the size of the whole text, not the window.

ConfigMgr::text_set_size should be called prior to this method to select a font, font size and wrap options (based on the TextClass).

Examples found in repository?
src/label.rs (line 60)
59
60
61
        fn draw(&mut self, mut draw: DrawMgr) {
            draw.text(self.rect(), &self.label, Self::CLASS);
        }

Draw text with effects

Text is drawn from rect.pos and clipped to rect. If the text scrolls, rect should be the size of the whole text, not the window.

Self::text already supports font effects: bold, emphasis, text size. In addition, this method supports underline and strikethrough effects.

ConfigMgr::text_set_size should be called prior to this method to select a font, font size and wrap options (based on the TextClass).

Draw some text using the standard font, with a subset selected

Other than visually highlighting the selection, this method behaves identically to Self::text. It is likely to be replaced in the future by a higher-level API.

Draw an edit marker at the given byte index on this text

The text cursor is draw from rect.pos and clipped to rect. If the text scrolls, rect should be the size of the whole text, not the window.

ConfigMgr::text_set_size should be called prior to this method to select a font, font size and wrap options (based on the TextClass).

Draw UI element: check box (without label)

The check box is a small visual element, typically a distinctive square box with or without a “check” selection mark.

The theme may animate transitions. To achieve this, last_change should be the time of the last state change caused by the user, or none when the last state change was programmatic.

Draw UI element: radio box (without label)

The radio box is a small visual element, typically a disinctive circular box with or without a “radio” selection mark.

The theme may animate transitions. To achieve this, last_change should be the time of the last state change caused by the user, or none when the last state change was programmatic.

Draw UI element: mark

Draw UI element: scroll bar

Draw UI element: slider

Draw UI element: progress bar

  • rect: area of whole widget
  • dir: direction of progress bar
  • state: highlighting information
  • value: progress value, between 0.0 and 1.0

Draw an image

Trait Implementations§

Performs the |= operation. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more
Cast from Self to T Read more
Try converting from Self to T Read more
Try approximate conversion from Self to T Read more
Cast approximately from Self to T Read more
Cast to integer, truncating Read more
Cast to the nearest integer Read more
Cast the floor to an integer Read more
Cast the ceiling to an integer Read more
Try converting to integer with truncation Read more
Try converting to the nearest integer Read more
Try converting the floor to an integer Read more
Try convert the ceiling to an integer Read more

Returns the argument unchanged.

Calls U::from(self).

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

The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.