mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 12:12:45 +00:00 
			
		
		
		
	LibGUI: Add Banner concept to AbstractScrollableWidget
Banners are abstract widgets which can house additional controls and information on a temporary basis, popping in from the top of their parent when needed.
This commit is contained in:
		
							parent
							
								
									c2cc01c920
								
							
						
					
					
						commit
						3c4a563415
					
				
					 2 changed files with 42 additions and 6 deletions
				
			
		|  | @ -40,6 +40,19 @@ AbstractScrollableWidget::AbstractScrollableWidget() | |||
|     }; | ||||
| } | ||||
| 
 | ||||
| void AbstractScrollableWidget::set_banner_widget(Widget* widget) | ||||
| { | ||||
|     if (m_banner_widget == widget) | ||||
|         return; | ||||
|     if (m_banner_widget) | ||||
|         remove_child(*m_banner_widget); | ||||
|     if (!widget) | ||||
|         return; | ||||
| 
 | ||||
|     m_banner_widget = widget; | ||||
|     add_child(*m_banner_widget); | ||||
| } | ||||
| 
 | ||||
| void AbstractScrollableWidget::handle_wheel_event(MouseEvent& event, Widget& event_source) | ||||
| { | ||||
|     if (!m_scrollbars_enabled) { | ||||
|  | @ -77,16 +90,25 @@ void AbstractScrollableWidget::mousewheel_event(MouseEvent& event) | |||
| void AbstractScrollableWidget::custom_layout() | ||||
| { | ||||
|     auto inner_rect = frame_inner_rect_for_size(size()); | ||||
|     int height_wanted_by_banner_widget = m_banner_widget && m_banner_widget->is_visible() ? m_banner_widget->effective_min_size().height().as_int() : 0; | ||||
|     int height_wanted_by_horizontal_scrollbar = m_horizontal_scrollbar->is_visible() ? m_horizontal_scrollbar->effective_min_size().height().as_int() : 0; | ||||
|     int width_wanted_by_vertical_scrollbar = m_vertical_scrollbar->is_visible() ? m_vertical_scrollbar->effective_min_size().width().as_int() : 0; | ||||
| 
 | ||||
|     if (m_banner_widget && m_banner_widget->is_visible()) { | ||||
|         m_banner_widget->set_relative_rect( | ||||
|             inner_rect.left(), | ||||
|             inner_rect.top(), | ||||
|             inner_rect.width(), | ||||
|             height_wanted_by_banner_widget); | ||||
|     } | ||||
| 
 | ||||
|     { | ||||
|         int vertical_scrollbar_width = m_vertical_scrollbar->effective_min_size().width().as_int(); | ||||
|         m_vertical_scrollbar->set_relative_rect( | ||||
|             inner_rect.right() + 1 - vertical_scrollbar_width, | ||||
|             inner_rect.top(), | ||||
|             inner_rect.top() + height_wanted_by_banner_widget, | ||||
|             vertical_scrollbar_width, | ||||
|             inner_rect.height() - height_wanted_by_horizontal_scrollbar); | ||||
|             inner_rect.height() - height_wanted_by_horizontal_scrollbar - height_wanted_by_banner_widget); | ||||
|     } | ||||
| 
 | ||||
|     { | ||||
|  | @ -160,7 +182,7 @@ void AbstractScrollableWidget::update_scrollbar_visibility() | |||
|         if (m_min_content_size == Gfx::IntSize {}) | ||||
|             effective_min_content_size = m_content_size; | ||||
|         int horizontal_buffer = rect().width() - 2 * frame_thickness() - effective_min_content_size.width(); | ||||
|         int vertical_buffer = rect().height() - 2 * frame_thickness() - effective_min_content_size.height(); | ||||
|         int vertical_buffer = rect().height() - 2 * frame_thickness() - effective_min_content_size.height() - height_occupied_by_banner_widget(); | ||||
|         bool horizontal_scrollbar_should_be_visible = false, vertical_scrollbar_should_be_visible = false; | ||||
|         vertical_scrollbar_should_be_visible = vertical_buffer < 0; | ||||
|         if (vertical_scrollbar_should_be_visible) | ||||
|  | @ -198,6 +220,11 @@ void AbstractScrollableWidget::set_size_occupied_by_fixed_elements(Gfx::IntSize | |||
|     update_scrollbar_ranges(); | ||||
| } | ||||
| 
 | ||||
| int AbstractScrollableWidget::height_occupied_by_banner_widget() const | ||||
| { | ||||
|     return m_banner_widget && m_banner_widget->is_visible() ? m_banner_widget->height() : 0; | ||||
| } | ||||
| 
 | ||||
| int AbstractScrollableWidget::height_occupied_by_horizontal_scrollbar() const | ||||
| { | ||||
|     return m_horizontal_scrollbar->is_visible() ? m_horizontal_scrollbar->height() : 0; | ||||
|  | @ -210,7 +237,7 @@ int AbstractScrollableWidget::width_occupied_by_vertical_scrollbar() const | |||
| 
 | ||||
| Margins AbstractScrollableWidget::content_margins() const | ||||
| { | ||||
|     return Frame::content_margins() + Margins { 0, width_occupied_by_vertical_scrollbar(), height_occupied_by_horizontal_scrollbar(), 0 }; | ||||
|     return Frame::content_margins() + Margins { height_occupied_by_banner_widget(), width_occupied_by_vertical_scrollbar(), height_occupied_by_horizontal_scrollbar(), 0 }; | ||||
| } | ||||
| 
 | ||||
| Gfx::IntRect AbstractScrollableWidget::visible_content_rect() const | ||||
|  | @ -312,7 +339,8 @@ Gfx::IntRect AbstractScrollableWidget::widget_inner_rect() const | |||
| { | ||||
|     auto rect = frame_inner_rect(); | ||||
|     rect.set_width(rect.width() - width_occupied_by_vertical_scrollbar()); | ||||
|     rect.set_height(rect.height() - height_occupied_by_horizontal_scrollbar()); | ||||
|     rect.set_height(rect.height() - height_occupied_by_horizontal_scrollbar() - height_occupied_by_banner_widget()); | ||||
|     rect.set_top(rect.top() + height_occupied_by_banner_widget()); | ||||
|     return rect; | ||||
| } | ||||
| 
 | ||||
|  | @ -336,7 +364,9 @@ Optional<UISize> AbstractScrollableWidget::calculated_min_size() const | |||
| { | ||||
|     auto vertical_scrollbar = m_vertical_scrollbar->effective_min_size().height().as_int(); | ||||
|     auto horizontal_scrollbar = m_horizontal_scrollbar->effective_min_size().width().as_int(); | ||||
|     return { { horizontal_scrollbar + corner_widget().width() + frame_thickness() * 2, vertical_scrollbar + corner_widget().height() + frame_thickness() * 2 } }; | ||||
|     auto banner = m_banner_widget && m_banner_widget->is_visible() ? m_banner_widget->effective_min_size().width().as_int() : 0; | ||||
|     auto max_width = max(banner, horizontal_scrollbar + corner_widget().width() + frame_thickness() * 2); | ||||
|     return { { max_width, vertical_scrollbar + corner_widget().height() + frame_thickness() * 2 + height_occupied_by_banner_widget() } }; | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -50,6 +50,10 @@ public: | |||
|     Widget& corner_widget() { return *m_corner_widget; } | ||||
|     Widget const& corner_widget() const { return *m_corner_widget; } | ||||
| 
 | ||||
|     void set_banner_widget(Widget*); | ||||
|     Widget* banner_widget() { return m_banner_widget; } | ||||
|     Widget const* banner_widget() const { return m_banner_widget; } | ||||
| 
 | ||||
|     void scroll_to_top(); | ||||
|     void scroll_to_bottom(); | ||||
| 
 | ||||
|  | @ -58,6 +62,7 @@ public: | |||
| 
 | ||||
|     int width_occupied_by_vertical_scrollbar() const; | ||||
|     int height_occupied_by_horizontal_scrollbar() const; | ||||
|     int height_occupied_by_banner_widget() const; | ||||
| 
 | ||||
|     virtual Margins content_margins() const override; | ||||
| 
 | ||||
|  | @ -111,6 +116,7 @@ private: | |||
|     RefPtr<AbstractScrollableWidgetScrollbar> m_vertical_scrollbar; | ||||
|     RefPtr<AbstractScrollableWidgetScrollbar> m_horizontal_scrollbar; | ||||
|     RefPtr<Widget> m_corner_widget; | ||||
|     WeakPtr<Widget> m_banner_widget; | ||||
|     Gfx::IntSize m_content_size; | ||||
|     Gfx::IntSize m_min_content_size; | ||||
|     Gfx::IntSize m_size_occupied_by_fixed_elements; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 thankyouverycool
						thankyouverycool