Serenity Operating System
at master 124 lines 4.2 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2022, the SerenityOS developers. 4 * Copyright (c) 2022, Timothy Slater <tslater2006@gmail.com> 5 * 6 * SPDX-License-Identifier: BSD-2-Clause 7 */ 8 9#include <LibGUI/Button.h> 10#include <LibGUI/SpinBox.h> 11#include <LibGUI/TextBox.h> 12 13REGISTER_WIDGET(GUI, SpinBox) 14 15namespace GUI { 16 17SpinBox::SpinBox() 18{ 19 set_min_size({ 40, 22 }); 20 set_preferred_size({ SpecialDimension::OpportunisticGrow, 22 }); 21 m_editor = add<TextBox>(); 22 m_editor->set_text("0"sv); 23 m_editor->on_change = [this, weak_this = make_weak_ptr()] { 24 if (!weak_this) 25 return; 26 27 auto value = m_editor->text().to_uint(); 28 if (!value.has_value() && m_editor->text().length() > 0) 29 m_editor->do_delete(); 30 }; 31 m_editor->on_focusout = [this] { 32 auto value = m_editor->text().to_int(); 33 if (value.has_value()) 34 set_value(value.value()); 35 else 36 set_value(min()); 37 }; 38 m_editor->on_up_pressed = [this] { 39 set_value(m_value + 1); 40 }; 41 m_editor->on_down_pressed = [this] { 42 set_value(m_value - 1); 43 }; 44 m_editor->on_return_pressed = [this] { 45 if (on_return_pressed) 46 on_return_pressed(); 47 }; 48 49 m_increment_button = add<Button>(); 50 m_increment_button->set_button_style(Gfx::ButtonStyle::ThickCap); 51 m_increment_button->set_icon(Gfx::Bitmap::load_from_file("/res/icons/16x16/upward-triangle.png"sv).release_value_but_fixme_should_propagate_errors()); 52 m_increment_button->set_focus_policy(GUI::FocusPolicy::NoFocus); 53 m_increment_button->on_click = [this](auto) { set_value(m_value + 1); }; 54 m_increment_button->set_auto_repeat_interval(150); 55 m_decrement_button = add<Button>(); 56 m_decrement_button->set_button_style(Gfx::ButtonStyle::ThickCap); 57 m_decrement_button->set_icon(Gfx::Bitmap::load_from_file("/res/icons/16x16/downward-triangle.png"sv).release_value_but_fixme_should_propagate_errors()); 58 m_decrement_button->set_focus_policy(GUI::FocusPolicy::NoFocus); 59 m_decrement_button->on_click = [this](auto) { set_value(m_value - 1); }; 60 m_decrement_button->set_auto_repeat_interval(150); 61 62 REGISTER_INT_PROPERTY("min", min, set_min); 63 REGISTER_INT_PROPERTY("max", max, set_max); 64} 65 66void SpinBox::set_value(int value, AllowCallback allow_callback) 67{ 68 value = clamp(value, m_min, m_max); 69 if (m_value == value) 70 return; 71 m_value = value; 72 73 m_increment_button->set_enabled(m_value < m_max); 74 m_decrement_button->set_enabled(m_value > m_min); 75 76 m_editor->set_text(DeprecatedString::number(value)); 77 update(); 78 if (on_change && allow_callback == AllowCallback::Yes) 79 on_change(value); 80} 81 82void SpinBox::set_range(int min, int max, AllowCallback allow_callback) 83{ 84 VERIFY(min <= max); 85 if (m_min == min && m_max == max) 86 return; 87 88 m_min = min; 89 m_max = max; 90 91 int old_value = m_value; 92 m_value = clamp(m_value, m_min, m_max); 93 if (m_value != old_value) { 94 m_editor->set_text(DeprecatedString::number(m_value)); 95 if (on_change && allow_callback == AllowCallback::Yes) 96 on_change(m_value); 97 } 98 99 m_increment_button->set_enabled(m_value < m_max); 100 m_decrement_button->set_enabled(m_value > m_min); 101 102 update(); 103} 104 105void SpinBox::mousewheel_event(MouseEvent& event) 106{ 107 auto wheel_delta = event.wheel_delta_y() / abs(event.wheel_delta_y()); 108 if (event.modifiers() == KeyModifier::Mod_Ctrl) 109 wheel_delta *= 6; 110 set_value(m_value - wheel_delta); 111 event.accept(); 112} 113 114void SpinBox::resize_event(ResizeEvent& event) 115{ 116 int frame_thickness = m_editor->frame_thickness(); 117 int button_height = (event.size().height() / 2) - frame_thickness; 118 int button_width = 15; 119 m_increment_button->set_relative_rect(width() - button_width - frame_thickness, frame_thickness, button_width, button_height); 120 m_decrement_button->set_relative_rect(width() - button_width - frame_thickness, frame_thickness + button_height, button_width, button_height); 121 m_editor->set_relative_rect(0, 0, width(), height()); 122} 123 124}