mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 13:32:45 +00:00 
			
		
		
		
	LibGUI: Make NumericInput work well in GML
- Register the widget - Register property getters and setters - Rename getters and setters to match the property names, as required by the GML compiler. The names min/max/value are chosen to match SpinBox. - Prevent a crash when the minimum is less than the maximum (which can happen while editing the GML).
This commit is contained in:
		
							parent
							
								
									da349607a3
								
							
						
					
					
						commit
						5f0230a57e
					
				
					 3 changed files with 46 additions and 35 deletions
				
			
		|  | @ -187,7 +187,7 @@ PDFViewerWidget::PDFViewerWidget() | |||
| 
 | ||||
|     m_viewer = v_splitter.add<PDFViewer>(); | ||||
|     m_viewer->on_page_change = [&](auto new_page) { | ||||
|         m_page_text_box->set_current_number(new_page + 1, GUI::AllowCallback::No); | ||||
|         m_page_text_box->set_value(new_page + 1, GUI::AllowCallback::No); | ||||
|         m_go_to_prev_page_action->set_enabled(new_page > 0); | ||||
|         m_go_to_next_page_action->set_enabled(new_page < m_viewer->document()->get_page_count() - 1); | ||||
|     }; | ||||
|  | @ -263,13 +263,13 @@ void PDFViewerWidget::initialize_toolbar(GUI::Toolbar& toolbar) | |||
| 
 | ||||
|     m_go_to_prev_page_action = GUI::Action::create("Go to &Previous Page", Gfx::Bitmap::load_from_file("/res/icons/16x16/go-up.png"sv).release_value_but_fixme_should_propagate_errors(), [&](auto&) { | ||||
|         VERIFY(m_viewer->current_page() > 0); | ||||
|         m_page_text_box->set_current_number(m_viewer->current_page()); | ||||
|         m_page_text_box->set_value(m_viewer->current_page()); | ||||
|     }); | ||||
|     m_go_to_prev_page_action->set_enabled(false); | ||||
| 
 | ||||
|     m_go_to_next_page_action = GUI::Action::create("Go to &Next Page", Gfx::Bitmap::load_from_file("/res/icons/16x16/go-down.png"sv).release_value_but_fixme_should_propagate_errors(), [&](auto&) { | ||||
|         VERIFY(m_viewer->current_page() < m_viewer->document()->get_page_count() - 1); | ||||
|         m_page_text_box->set_current_number(m_viewer->current_page() + 2); | ||||
|         m_page_text_box->set_value(m_viewer->current_page() + 2); | ||||
|     }); | ||||
|     m_go_to_next_page_action->set_enabled(false); | ||||
| 
 | ||||
|  | @ -279,7 +279,7 @@ void PDFViewerWidget::initialize_toolbar(GUI::Toolbar& toolbar) | |||
|     m_page_text_box = toolbar.add<GUI::NumericInput>(); | ||||
|     m_page_text_box->set_enabled(false); | ||||
|     m_page_text_box->set_fixed_width(30); | ||||
|     m_page_text_box->set_min_number(1); | ||||
|     m_page_text_box->set_min(1); | ||||
| 
 | ||||
|     m_page_text_box->on_number_changed = [&](i64 number) { | ||||
|         auto page_count = m_viewer->document()->get_page_count(); | ||||
|  | @ -396,8 +396,8 @@ PDF::PDFErrorOr<void> PDFViewerWidget::try_open_file(StringView path, NonnullOwn | |||
|     m_total_page_label->set_text(TRY(String::formatted("of {}", document->get_page_count()))); | ||||
| 
 | ||||
|     m_page_text_box->set_enabled(true); | ||||
|     m_page_text_box->set_current_number(1, GUI::AllowCallback::No); | ||||
|     m_page_text_box->set_max_number(document->get_page_count()); | ||||
|     m_page_text_box->set_value(1, GUI::AllowCallback::No); | ||||
|     m_page_text_box->set_max(document->get_page_count()); | ||||
|     m_go_to_prev_page_action->set_enabled(false); | ||||
|     m_go_to_next_page_action->set_enabled(document->get_page_count() > 1); | ||||
|     m_toggle_sidebar_action->set_enabled(true); | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2021, Matthew Olsson <mattco@serenityos.org> | ||||
|  * Copyright (c) 2024, Sam Atkins <atkinssj@serenityos.org> | ||||
|  * | ||||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
|  | @ -7,6 +8,8 @@ | |||
| #include "NumericInput.h" | ||||
| #include <ctype.h> | ||||
| 
 | ||||
| REGISTER_WIDGET(GUI, NumericInput); | ||||
| 
 | ||||
| namespace GUI { | ||||
| 
 | ||||
| NumericInput::NumericInput() | ||||
|  | @ -16,14 +19,14 @@ NumericInput::NumericInput() | |||
|     on_change = [&] { | ||||
|         auto number_opt = text().to_number<int>(); | ||||
|         if (number_opt.has_value()) { | ||||
|             set_current_number(number_opt.value(), GUI::AllowCallback::No); | ||||
|             set_value(number_opt.value(), GUI::AllowCallback::No); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         StringBuilder builder; | ||||
|         bool first = true; | ||||
|         for (auto& ch : text()) { | ||||
|             if (isdigit(ch) || (first && ((ch == '-' && m_min_number < 0) || ch == '+'))) | ||||
|             if (isdigit(ch) || (first && ((ch == '-' && m_min < 0) || ch == '+'))) | ||||
|                 builder.append(ch); | ||||
|             first = false; | ||||
|         } | ||||
|  | @ -37,57 +40,61 @@ NumericInput::NumericInput() | |||
|         } | ||||
| 
 | ||||
|         set_text(builder.to_byte_string()); | ||||
|         set_current_number(new_number_opt.value(), GUI::AllowCallback::No); | ||||
|         set_value(new_number_opt.value(), GUI::AllowCallback::No); | ||||
|     }; | ||||
| 
 | ||||
|     on_up_pressed = [&] { | ||||
|         if (m_current_number < m_max_number) | ||||
|             set_current_number(m_current_number + 1); | ||||
|         if (m_value < m_max) | ||||
|             set_value(m_value + 1); | ||||
|     }; | ||||
| 
 | ||||
|     on_down_pressed = [&] { | ||||
|         if (m_current_number > m_min_number) | ||||
|             set_current_number(m_current_number - 1); | ||||
|         if (m_value > m_min) | ||||
|             set_value(m_value - 1); | ||||
|     }; | ||||
| 
 | ||||
|     on_focusout = [&] { on_focus_lost(); }; | ||||
|     on_return_pressed = [&] { on_focus_lost(); }; | ||||
|     on_escape_pressed = [&] { on_focus_lost(); }; | ||||
| 
 | ||||
|     REGISTER_INT_PROPERTY("min", min, set_min); | ||||
|     REGISTER_INT_PROPERTY("max", max, set_max); | ||||
|     REGISTER_INT_PROPERTY("value", value, set_value); | ||||
| } | ||||
| 
 | ||||
| void NumericInput::set_min_number(i64 number) | ||||
| void NumericInput::set_min(i64 number) | ||||
| { | ||||
|     m_min_number = number; | ||||
|     if (m_current_number < number) | ||||
|         set_current_number(number); | ||||
|     m_min = number; | ||||
|     if (m_value < number) | ||||
|         set_value(number); | ||||
| } | ||||
| 
 | ||||
| void NumericInput::set_max_number(i64 number) | ||||
| void NumericInput::set_max(i64 number) | ||||
| { | ||||
|     m_max_number = number; | ||||
|     if (m_current_number > number) | ||||
|         set_current_number(number); | ||||
|     m_max = number; | ||||
|     if (m_value > number) | ||||
|         set_value(number); | ||||
| } | ||||
| 
 | ||||
| void NumericInput::on_focus_lost() | ||||
| { | ||||
|     if (m_needs_text_reset) { | ||||
|         set_text(ByteString::number(m_current_number)); | ||||
|         set_text(ByteString::number(m_value)); | ||||
|         m_needs_text_reset = false; | ||||
|     } | ||||
|     if (on_number_changed) | ||||
|         on_number_changed(m_current_number); | ||||
|         on_number_changed(m_value); | ||||
| } | ||||
| 
 | ||||
| void NumericInput::set_current_number(i64 number, GUI::AllowCallback allow_callback) | ||||
| void NumericInput::set_value(i64 number, GUI::AllowCallback allow_callback) | ||||
| { | ||||
|     if (number == m_current_number) | ||||
|     if (number == m_value) | ||||
|         return; | ||||
| 
 | ||||
|     m_current_number = clamp(number, m_min_number, m_max_number); | ||||
|     set_text(ByteString::number(m_current_number)); | ||||
|     m_value = clamp(number, ::min(m_min, m_max), ::max(m_min, m_max)); | ||||
|     set_text(ByteString::number(m_value)); | ||||
|     if (on_number_changed && allow_callback == GUI::AllowCallback::Yes) | ||||
|         on_number_changed(m_current_number); | ||||
|         on_number_changed(m_value); | ||||
| } | ||||
| 
 | ||||
| void NumericInput::mousewheel_event(GUI::MouseEvent& event) | ||||
|  | @ -95,7 +102,7 @@ void NumericInput::mousewheel_event(GUI::MouseEvent& event) | |||
|     auto wheel_delta = event.wheel_delta_y() / abs(event.wheel_delta_y()); | ||||
|     if (event.modifiers() == KeyModifier::Mod_Ctrl) | ||||
|         wheel_delta *= 6; | ||||
|     set_current_number(m_current_number - wheel_delta); | ||||
|     set_value(m_value - wheel_delta); | ||||
|     event.accept(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2021, Matthew Olsson <mattco@serenityos.org> | ||||
|  * Copyright (c) 2024, Sam Atkins <atkinssj@serenityos.org> | ||||
|  * | ||||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
|  | @ -18,9 +19,12 @@ public: | |||
| 
 | ||||
|     Function<void(i64)> on_number_changed; | ||||
| 
 | ||||
|     void set_min_number(i64 number); | ||||
|     void set_max_number(i64 number); | ||||
|     void set_current_number(i64 number, GUI::AllowCallback allow_callback = GUI::AllowCallback::Yes); | ||||
|     i64 min() const { return m_min; } | ||||
|     void set_min(i64 number); | ||||
|     i64 max() const { return m_max; } | ||||
|     void set_max(i64 number); | ||||
|     i64 value() const { return m_value; } | ||||
|     void set_value(i64 number, GUI::AllowCallback allow_callback = GUI::AllowCallback::Yes); | ||||
| 
 | ||||
|     virtual void mousewheel_event(GUI::MouseEvent&) override; | ||||
| 
 | ||||
|  | @ -29,9 +33,9 @@ private: | |||
|     void on_focus_lost(); | ||||
| 
 | ||||
|     bool m_needs_text_reset { false }; | ||||
|     i64 m_current_number { 0 }; | ||||
|     i64 m_min_number { NumericLimits<i64>::min() }; | ||||
|     i64 m_max_number { NumericLimits<i64>::max() }; | ||||
|     i64 m_value { 0 }; | ||||
|     i64 m_min { NumericLimits<i64>::min() }; | ||||
|     i64 m_max { NumericLimits<i64>::max() }; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Sam Atkins
						Sam Atkins