mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:32:46 +00:00 
			
		
		
		
	LibGUI: Implement automatic scrolling in AbstractView
This adds automatic scrolling when dragging items in TreeViews and other widgets that inherit from AbstractView when the overloaded accepts_drag() returns true. This is implemented in FileSystemModel to allow directories and files to be dragged.
This commit is contained in:
		
							parent
							
								
									53cfc6ec9f
								
							
						
					
					
						commit
						d660e86d13
					
				
					 6 changed files with 45 additions and 7 deletions
				
			
		|  | @ -52,7 +52,7 @@ public: | |||
|     void scroll_to_bottom(); | ||||
| 
 | ||||
|     void set_automatic_scrolling_timer(bool active); | ||||
|     Gfx::IntPoint automatic_scroll_delta_from_position(const Gfx::IntPoint&) const; | ||||
|     virtual Gfx::IntPoint automatic_scroll_delta_from_position(const Gfx::IntPoint&) const; | ||||
| 
 | ||||
|     int width_occupied_by_vertical_scrollbar() const; | ||||
|     int height_occupied_by_horizontal_scrollbar() const; | ||||
|  | @ -75,6 +75,7 @@ protected: | |||
|     void set_content_size(const Gfx::IntSize&); | ||||
|     void set_size_occupied_by_fixed_elements(const Gfx::IntSize&); | ||||
|     virtual void on_automatic_scrolling_timer_fired() {}; | ||||
|     int autoscroll_threshold() const { return m_autoscroll_threshold; } | ||||
| 
 | ||||
| private: | ||||
|     class AbstractScrollableWidgetScrollbar final : public Scrollbar { | ||||
|  |  | |||
|  | @ -460,4 +460,14 @@ bool AbstractTableView::is_navigation(GUI::KeyEvent& event) | |||
|         return false; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| Gfx::IntPoint AbstractTableView::automatic_scroll_delta_from_position(const Gfx::IntPoint& pos) const | ||||
| { | ||||
|     if (pos.y() > column_header().height() + autoscroll_threshold()) | ||||
|         return AbstractScrollableWidget::automatic_scroll_delta_from_position(pos); | ||||
| 
 | ||||
|     Gfx::IntPoint position_excluding_header = { pos.x(), pos.y() - column_header().height() }; | ||||
|     return AbstractScrollableWidget::automatic_scroll_delta_from_position(position_excluding_header); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -100,6 +100,8 @@ protected: | |||
| 
 | ||||
|     void move_cursor_relative(int vertical_steps, int horizontal_steps, SelectionUpdate); | ||||
| 
 | ||||
|     virtual Gfx::IntPoint automatic_scroll_delta_from_position(const Gfx::IntPoint& pos) const override; | ||||
| 
 | ||||
| private: | ||||
|     void layout_headers(); | ||||
|     bool is_navigation(GUI::KeyEvent&); | ||||
|  |  | |||
|  | @ -335,6 +335,8 @@ void AbstractView::mouseup_event(MouseEvent& event) | |||
|     if (!model()) | ||||
|         return; | ||||
| 
 | ||||
|     set_automatic_scrolling_timer(false); | ||||
| 
 | ||||
|     if (m_might_drag) { | ||||
|         // We were unsure about unselecting items other than the current one
 | ||||
|         // in mousedown_event(), because we could be seeing a start of a drag.
 | ||||
|  | @ -759,13 +761,19 @@ void AbstractView::drag_move_event(DragEvent& event) | |||
| { | ||||
|     if (!model()) | ||||
|         return; | ||||
| 
 | ||||
|     auto index = index_at_event_position(event.position()); | ||||
|     ModelIndex new_drop_candidate_index; | ||||
|     if (index.is_valid()) { | ||||
|         bool acceptable = model()->accepts_drag(index, event.mime_types()); | ||||
|         if (acceptable) | ||||
|             new_drop_candidate_index = index; | ||||
|     bool acceptable = model()->accepts_drag(index, event.mime_types()); | ||||
| 
 | ||||
|     if (acceptable && index.is_valid()) | ||||
|         new_drop_candidate_index = index; | ||||
| 
 | ||||
|     if (acceptable) { | ||||
|         m_automatic_scroll_delta = automatic_scroll_delta_from_position(event.position()); | ||||
|         set_automatic_scrolling_timer(!m_automatic_scroll_delta.is_null()); | ||||
|     } | ||||
| 
 | ||||
|     if (m_drop_candidate_index != new_drop_candidate_index) { | ||||
|         m_drop_candidate_index = new_drop_candidate_index; | ||||
|         update(); | ||||
|  | @ -780,6 +788,17 @@ void AbstractView::drag_leave_event(Event&) | |||
|         m_drop_candidate_index = {}; | ||||
|         update(); | ||||
|     } | ||||
| 
 | ||||
|     set_automatic_scrolling_timer(false); | ||||
| } | ||||
| 
 | ||||
| void AbstractView::on_automatic_scrolling_timer_fired() | ||||
| { | ||||
|     if (m_automatic_scroll_delta.is_null()) | ||||
|         return; | ||||
| 
 | ||||
|     vertical_scrollbar().set_value(vertical_scrollbar().value() + m_automatic_scroll_delta.y()); | ||||
|     horizontal_scrollbar().set_value(horizontal_scrollbar().value() + m_automatic_scroll_delta.x()); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -142,6 +142,8 @@ protected: | |||
|     virtual void hide_event(HideEvent&) override; | ||||
|     virtual void focusin_event(FocusEvent&) override; | ||||
| 
 | ||||
|     virtual void on_automatic_scrolling_timer_fired() override; | ||||
| 
 | ||||
|     virtual void clear_selection(); | ||||
|     virtual void set_selection(ModelIndex const&); | ||||
|     virtual void set_selection_start_index(ModelIndex const&); | ||||
|  | @ -202,6 +204,8 @@ private: | |||
|     bool m_is_dragging { false }; | ||||
|     bool m_draw_item_text_with_shadow { false }; | ||||
|     bool m_suppress_update_on_selection_change { false }; | ||||
| 
 | ||||
|     Gfx::IntPoint m_automatic_scroll_delta {}; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -711,10 +711,12 @@ String FileSystemModel::column_name(int column) const | |||
| 
 | ||||
| bool FileSystemModel::accepts_drag(ModelIndex const& index, Vector<String> const& mime_types) const | ||||
| { | ||||
|     if (!index.is_valid()) | ||||
|         return false; | ||||
|     if (!mime_types.contains_slow("text/uri-list")) | ||||
|         return false; | ||||
| 
 | ||||
|     if (!index.is_valid()) | ||||
|         return true; | ||||
| 
 | ||||
|     auto& node = this->node(index); | ||||
|     return node.is_directory(); | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Marcus Nilsson
						Marcus Nilsson