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
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Pushrod Widgets
// Group Box Widget
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use sdl2::render::{Canvas, Texture};
use sdl2::video::Window;

use crate::caches::TextureCache;
use crate::primitives::fill_box;
use crate::properties::{
    WidgetProperties, PROPERTY_BORDER_COLOR, PROPERTY_BORDER_WIDTH, PROPERTY_FONT_COLOR,
    PROPERTY_GROUP_BACKGROUND_COLOR, PROPERTY_MAIN_COLOR,
};
use crate::texture_store::TextureStore;
use crate::widget::Widget;
use sdl2::pixels::Color;
use sdl2::rect::Rect;

/// Base Widget.
#[derive(Default)]
pub struct GroupBoxWidget {
    texture_store: TextureStore,
    properties: WidgetProperties,
}

/// Implementation for drawing a `GroupBoxWidget`, with the `Widget` trait objects applied.
impl Widget for GroupBoxWidget {
    widget_default_impl!();

    /// This is a `BaseWidget` that is used as a standard blank `Widget`.
    ///
    /// - PROPERTY_MAIN_COLOR: the `Color` of the body of the `Widget`
    /// - PROPERTY_BORDER_WIDTH: the width of the border to draw
    /// - PROPERTY_BORDER_COLOR: the `Color` of the border.
    /// - PROPERTY_FONT_COLOR: the color of the font
    /// - PROPERTY_FONT_NAME: full or relative path to the font file to use to render the text
    /// - PROPERTY_FONT_SIZE: the size in points of the font
    /// - PROPERTY_FONT_STYLE: the `FontStyle` to apply to the font
    /// - PROPERTY_GROUP_BACKGROUND_COLOR: the background color of the group bounding box
    fn draw(&mut self, c: &mut Canvas<Window>, t: &mut TextureCache) -> Option<&Texture> {
        // ONLY update the texture if the `BaseWidget` shows that it's been invalidated.
        if self.invalidated() {
            let bounds = self.properties.get_bounds();

            self.texture_store
                .create_or_resize_texture(c, bounds.0, bounds.1);

            let mut cloned_properties = self.properties.clone();
            let mut current_origin = cloned_properties.get_origin();
            let current_bounds = cloned_properties.get_bounds();
            let border_width = cloned_properties.get_value(PROPERTY_BORDER_WIDTH) as u32;
            let text_color = cloned_properties.get_color(PROPERTY_FONT_COLOR, Color::BLACK);
            let (font_texture, width, height) =
                t.render_text(c, &mut self.properties, Some(text_color));
            let base_color = cloned_properties.get_color(PROPERTY_MAIN_COLOR, Color::WHITE);
            let border_color = cloned_properties.get_color(PROPERTY_BORDER_COLOR, Color::BLACK);

            current_origin.1 += (height / 4) as u32;

            cloned_properties.set_origin(current_origin.0, current_origin.1);

            c.with_texture_canvas(self.texture_store.get_mut_ref(), |texture| {
                // Fill the texture
                texture.set_draw_color(base_color);
                texture.clear();

                if border_width > 0 {
                    // Draw the border with the color of the border
                    texture.set_draw_color(border_color);

                    for border_width_count in 0..border_width {
                        texture
                            .draw_rect(Rect::new(
                                border_width_count as i32,
                                current_origin.1 as i32 + border_width_count as i32,
                                bounds.0 - (border_width_count * 2) as u32,
                                bounds.1 - current_origin.1 - (border_width_count * 2) as u32,
                            ))
                            .unwrap();
                    }
                }

                let box_color =
                    cloned_properties.get_color(PROPERTY_GROUP_BACKGROUND_COLOR, Color::GRAY);

                fill_box(
                    texture,
                    border_width,
                    current_origin.1 + border_width,
                    current_bounds.0 - (border_width * 2),
                    current_bounds.1 - current_origin.1 - (border_width * 2),
                    box_color,
                );

                fill_box(texture, 20, 0, width, height, Color::WHITE);

                texture.set_draw_color(border_color);
                texture.draw_rect(Rect::new(20, 0, width, height)).unwrap();

                texture
                    .copy(&font_texture, None, Rect::new(20, 0, width, height))
                    .unwrap();
            })
            .unwrap();
        }

        self.texture_store.get_optional_ref()
    }
}