Serenity Operating System
at master 115 lines 3.1 kB view raw
1/* 2 * Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2022, the SerenityOS developers. 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#include <LibGUI/CheckBox.h> 9#include <LibGUI/Painter.h> 10#include <LibGfx/CharacterBitmap.h> 11#include <LibGfx/Font/Font.h> 12#include <LibGfx/Palette.h> 13#include <LibGfx/StylePainter.h> 14 15REGISTER_WIDGET(GUI, CheckBox) 16 17namespace GUI { 18 19CheckBox::CheckBox(String text) 20 : AbstractButton(move(text)) 21{ 22 REGISTER_BOOL_PROPERTY("autosize", is_autosize, set_autosize); 23 24 REGISTER_ENUM_PROPERTY( 25 "checkbox_position", checkbox_position, set_checkbox_position, CheckBoxPosition, 26 { CheckBoxPosition::Left, "Left" }, 27 { CheckBoxPosition::Right, "Right" }); 28 29 set_min_size(SpecialDimension::Shrink, SpecialDimension::Shrink); 30 set_preferred_size(SpecialDimension::OpportunisticGrow, SpecialDimension::Shrink); 31} 32 33int CheckBox::gap_between_box_and_rect() const 34{ 35 return 6; 36} 37 38int CheckBox::horizontal_padding() const 39{ 40 return 2; 41} 42 43Gfx::IntRect CheckBox::box_rect() const 44{ 45 int box_size = max(13, height() - 10); 46 47 Gfx::IntRect box_rect { 48 0, 49 height() / 2 - box_size / 2 - 1, 50 box_size, 51 box_size, 52 }; 53 if (m_checkbox_position == CheckBoxPosition::Right) 54 box_rect.set_right_without_resize(rect().right()); 55 56 return box_rect; 57} 58 59void CheckBox::paint_event(PaintEvent& event) 60{ 61 Painter painter(*this); 62 painter.add_clip_rect(event.rect()); 63 64 auto box_rect = this->box_rect(); 65 auto text_rect = rect(); 66 if (m_checkbox_position == CheckBoxPosition::Left) 67 text_rect.set_left(box_rect.right() + 1 + gap_between_box_and_rect()); 68 text_rect.set_width(static_cast<int>(ceilf(font().width(text())))); 69 text_rect.set_top(height() / 2 - font().pixel_size_rounded_up() / 2); 70 text_rect.set_height(font().pixel_size_rounded_up()); 71 72 if (fill_with_background_color()) 73 painter.fill_rect(rect(), palette().window()); 74 75 if (is_enabled() && is_hovered()) 76 painter.fill_rect(rect(), palette().hover_highlight()); 77 78 Gfx::StylePainter::paint_check_box(painter, box_rect, palette(), is_enabled(), is_checked(), is_being_pressed()); 79 80 paint_text(painter, text_rect, font(), Gfx::TextAlignment::TopLeft); 81 82 if (is_focused()) 83 painter.draw_focus_rect(text_rect.inflated(6, 6), palette().focus_outline()); 84} 85 86void CheckBox::click(unsigned) 87{ 88 if (!is_enabled()) 89 return; 90 set_checked(!is_checked()); 91} 92 93void CheckBox::set_autosize(bool autosize) 94{ 95 if (m_autosize == autosize) 96 return; 97 m_autosize = autosize; 98 if (m_autosize) 99 size_to_fit(); 100} 101 102void CheckBox::size_to_fit() 103{ 104 set_fixed_width(box_rect().width() + gap_between_box_and_rect() + static_cast<int>(ceilf(font().width(text()))) + horizontal_padding() * 2); 105} 106 107Optional<UISize> CheckBox::calculated_min_size() const 108{ 109 auto const& font = this->font(); 110 int width = box_rect().width(); 111 int height = max(22, max(static_cast<int>(ceilf(font.pixel_size())) + 8, box_rect().height())); 112 return UISize(width, height); 113} 114 115}