suzy/platform/opengl/widgets/
mod.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use super::{
6    OpenGlRenderPlatform, SelectableSlicedImage, Text, TextAlignment,
7    TextLayoutSettings, Texture,
8};
9use crate::dims::{Rect, SimplePadding2d};
10use crate::graphics::Color;
11use crate::selectable::{Selectable, SelectionState, SelectionStateV0};
12use crate::widget::{
13    WidgetChildReceiver, WidgetContent, WidgetGraphicReceiver, WidgetInit,
14};
15use crate::widgets::TextContent;
16
17const BUTTON_DATA: &[u8] = include_bytes!("button-all.data");
18const BUTTON_STATES: &[SelectionState] = &[
19    SelectionState::normal(),
20    SelectionState::hover(),
21    SelectionState::focus(),
22    SelectionState::active(),
23];
24
25type Plat = OpenGlRenderPlatform;
26
27pub struct DefaultOpenGlButton {
28    image: SelectableSlicedImage,
29    text_graphic: Text,
30    text: crate::watch::Watched<String>,
31}
32
33impl Default for DefaultOpenGlButton {
34    fn default() -> Self {
35        DefaultOpenGlButton {
36            image: SelectableSlicedImage::default(),
37            text_graphic: Text::default(),
38            text: crate::watch::Watched::new("Button".to_string()),
39        }
40    }
41}
42
43impl TextContent for DefaultOpenGlButton {
44    fn set_text(&mut self, text: &str) {
45        *self.text = text.to_string();
46    }
47}
48
49impl WidgetContent<Plat> for DefaultOpenGlButton {
50    fn init(mut init: impl WidgetInit<Self, Plat>) {
51        init.watch(|this, rect| {
52            this.image.set_fill(&rect, &SimplePadding2d::zero());
53
54            let text_settings = this.text_graphic.render_settings();
55            text_settings.x = rect.left();
56            text_settings.y = rect.center_y();
57        });
58        init.watch(|this, rect| {
59            let text_layout = TextLayoutSettings::default()
60                .wrap_width(rect.width())
61                .alignment(TextAlignment::Center)
62                .y_offset(-12.0);
63            this.text_graphic.set_text(&this.text, text_layout);
64        });
65        init.watch(|this, _rect| {
66            this.image.set_image(
67                Texture::from_rgba_cached(112, 37, 1, BUTTON_DATA),
68                &SimplePadding2d::uniform(6.0),
69                BUTTON_STATES,
70            );
71        });
72    }
73
74    fn children(&mut self, _receiver: impl WidgetChildReceiver<Plat>) {
75        // no children
76    }
77
78    fn graphics(&mut self, mut receiver: impl WidgetGraphicReceiver<Plat>) {
79        receiver.graphic(&mut self.image);
80        receiver.graphic(&mut self.text_graphic);
81    }
82}
83
84impl Selectable for DefaultOpenGlButton {
85    fn selection_changed(&mut self, state: SelectionState) {
86        self.image.selection_changed(state);
87        let text_settings = self.text_graphic.render_settings();
88        text_settings.text_color = match state.v0() {
89            SelectionStateV0::Active => Color::BLACK,
90            _ => Color::WHITE,
91        };
92        let (r, g, b, _) = text_settings.text_color.rgba();
93        text_settings.outline_color = Color::create_rgba(r, g, b, 0.0);
94    }
95}