1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use std::cmp::max;
use std::ops::{Deref, DerefMut};

use fltk::enums::FrameType;
use fltk::menu::MenuButton;
use fltk::prelude::*;

use super::{LayoutElement, LayoutWidgetWrapper, Size};

pub struct ButtonElement<B: ButtonExt + Clone> {
    widget: B,
}

impl<B: ButtonExt + Clone> LayoutWidgetWrapper<B> for ButtonElement<B> {
    fn wrap(widget: B) -> Self {
        Self { widget }
    }
}

impl<B: ButtonExt + Clone> LayoutElement for ButtonElement<B> {
    fn min_size(&self) -> Size {
        button_min_size(&self.widget, self.widget.down_frame())
    }

    fn layout(&self, x: i32, y: i32, width: i32, height: i32) {
        self.widget.clone().resize(x, y, width, height)
    }
}

impl<B: ButtonExt + Clone> Deref for ButtonElement<B> {
    type Target = B;
    fn deref(&self) -> &Self::Target {
        &self.widget
    }
}

impl<B: ButtonExt + Clone> DerefMut for ButtonElement<B> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.widget
    }
}

pub struct MenuButtonElement {
    widget: MenuButton,
}

impl LayoutWidgetWrapper<MenuButton> for MenuButtonElement {
    fn wrap(widget: MenuButton) -> Self {
        Self { widget }
    }
}

impl LayoutElement for MenuButtonElement {
    fn min_size(&self) -> Size {
        button_min_size(&self.widget, self.widget.down_frame())
    }

    fn layout(&self, x: i32, y: i32, width: i32, height: i32) {
        self.widget.clone().resize(x, y, width, height)
    }
}

fn button_min_size<B: WidgetExt>(button: &B, down_frame: FrameType) -> Size {
    let (label_width, label_height) = button.measure_label();
    let up_frame = button.frame();
    let frame_dx = max(up_frame.dx(), down_frame.dx());
    let frame_dy = max(up_frame.dy(), down_frame.dy());
    let frame_dw = max(up_frame.dw(), down_frame.dw());
    let frame_dh = max(up_frame.dh(), down_frame.dh());
    let frame_width = frame_dx + frame_dw;
    let frame_height = frame_dy + frame_dh;

    Size {
        width: label_width + frame_width + label_height,
        height: label_height + 2 * frame_height,
    }
}