mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:12:45 +00:00 
			
		
		
		
	LibGUI: Move most of mouse event handling to GAbstractView
This deduplicates existing code, and also gives all the model-backed widgets selection manipulation and drag support for free :^)
This commit is contained in:
		
							parent
							
								
									fd11c96e8e
								
							
						
					
					
						commit
						d3ce7ae0e3
					
				
					 9 changed files with 197 additions and 185 deletions
				
			
		|  | @ -251,7 +251,7 @@ int GAbstractColumnView::column_width(int column_index) const | ||||||
| void GAbstractColumnView::mousemove_event(GMouseEvent& event) | void GAbstractColumnView::mousemove_event(GMouseEvent& event) | ||||||
| { | { | ||||||
|     if (!model()) |     if (!model()) | ||||||
|         return; |         return GAbstractView::mousemove_event(event); | ||||||
| 
 | 
 | ||||||
|     if (m_in_column_resize) { |     if (m_in_column_resize) { | ||||||
|         auto delta = event.position() - m_column_resize_origin; |         auto delta = event.position() - m_column_resize_origin; | ||||||
|  | @ -301,6 +301,8 @@ void GAbstractColumnView::mousemove_event(GMouseEvent& event) | ||||||
|             set_hovered_header_index(-1); |             set_hovered_header_index(-1); | ||||||
|     } |     } | ||||||
|     window()->set_override_cursor(GStandardCursor::None); |     window()->set_override_cursor(GStandardCursor::None); | ||||||
|  | 
 | ||||||
|  |     GAbstractView::mousemove_event(event); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GAbstractColumnView::mouseup_event(GMouseEvent& event) | void GAbstractColumnView::mouseup_event(GMouseEvent& event) | ||||||
|  | @ -311,6 +313,7 @@ void GAbstractColumnView::mouseup_event(GMouseEvent& event) | ||||||
|             if (!column_resize_grabbable_rect(m_resizing_column).contains(adjusted_position)) |             if (!column_resize_grabbable_rect(m_resizing_column).contains(adjusted_position)) | ||||||
|                 window()->set_override_cursor(GStandardCursor::None); |                 window()->set_override_cursor(GStandardCursor::None); | ||||||
|             m_in_column_resize = false; |             m_in_column_resize = false; | ||||||
|  |             return; | ||||||
|         } |         } | ||||||
|         if (m_pressed_column_header_index != -1) { |         if (m_pressed_column_header_index != -1) { | ||||||
|             auto header_rect = this->header_rect(m_pressed_column_header_index); |             auto header_rect = this->header_rect(m_pressed_column_header_index); | ||||||
|  | @ -325,17 +328,20 @@ void GAbstractColumnView::mouseup_event(GMouseEvent& event) | ||||||
|             m_pressed_column_header_index = -1; |             m_pressed_column_header_index = -1; | ||||||
|             m_pressed_column_header_is_pressed = false; |             m_pressed_column_header_is_pressed = false; | ||||||
|             update_headers(); |             update_headers(); | ||||||
|  |             return; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     GAbstractView::mouseup_event(event); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GAbstractColumnView::mousedown_event(GMouseEvent& event) | void GAbstractColumnView::mousedown_event(GMouseEvent& event) | ||||||
| { | { | ||||||
|     if (!model()) |     if (!model()) | ||||||
|         return; |         return GAbstractView::mousedown_event(event); | ||||||
| 
 | 
 | ||||||
|     if (event.button() != GMouseButton::Left) |     if (event.button() != GMouseButton::Left) | ||||||
|         return; |         return GAbstractView::mousedown_event(event); | ||||||
| 
 | 
 | ||||||
|     if (event.y() < header_height()) { |     if (event.y() < header_height()) { | ||||||
|         int column_count = model()->column_count(); |         int column_count = model()->column_count(); | ||||||
|  | @ -361,19 +367,13 @@ void GAbstractColumnView::mousedown_event(GMouseEvent& event) | ||||||
| 
 | 
 | ||||||
|     bool is_toggle; |     bool is_toggle; | ||||||
|     auto index = index_at_event_position(event.position(), is_toggle); |     auto index = index_at_event_position(event.position(), is_toggle); | ||||||
|     if (!index.is_valid()) { | 
 | ||||||
|         selection().clear(); |     if (index.is_valid() && is_toggle && model()->row_count(index)) { | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|     if (is_toggle && model()->row_count(index)) { |  | ||||||
|         toggle_index(index); |         toggle_index(index); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (event.modifiers() & Mod_Ctrl) |     GAbstractView::mousedown_event(event); | ||||||
|         selection().toggle(index); |  | ||||||
|     else |  | ||||||
|         selection().set(index); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| GModelIndex GAbstractColumnView::index_at_event_position(const Point& position, bool& is_toggle) const | GModelIndex GAbstractColumnView::index_at_event_position(const Point& position, bool& is_toggle) const | ||||||
|  |  | ||||||
|  | @ -24,8 +24,10 @@ | ||||||
|  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | #include <AK/StringBuilder.h> | ||||||
| #include <Kernel/KeyCode.h> | #include <Kernel/KeyCode.h> | ||||||
| #include <LibGUI/GAbstractView.h> | #include <LibGUI/GAbstractView.h> | ||||||
|  | #include <LibGUI/GDragOperation.h> | ||||||
| #include <LibGUI/GModel.h> | #include <LibGUI/GModel.h> | ||||||
| #include <LibGUI/GModelEditingDelegate.h> | #include <LibGUI/GModelEditingDelegate.h> | ||||||
| #include <LibGUI/GPainter.h> | #include <LibGUI/GPainter.h> | ||||||
|  | @ -171,3 +173,151 @@ NonnullRefPtr<Font> GAbstractView::font_for_index(const GModelIndex& index) cons | ||||||
|         return *column_metadata.font; |         return *column_metadata.font; | ||||||
|     return font(); |     return font(); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void GAbstractView::mousedown_event(GMouseEvent& event) | ||||||
|  | { | ||||||
|  |     GScrollableWidget::mousedown_event(event); | ||||||
|  | 
 | ||||||
|  |     if (!model()) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     if (event.button() == GMouseButton::Left) | ||||||
|  |         m_left_mousedown_position = event.position(); | ||||||
|  | 
 | ||||||
|  |     auto index = index_at_event_position(event.position()); | ||||||
|  |     m_might_drag = false; | ||||||
|  | 
 | ||||||
|  |     if (!index.is_valid()) { | ||||||
|  |         m_selection.clear(); | ||||||
|  |     } else if (event.modifiers() & Mod_Ctrl) { | ||||||
|  |         m_selection.toggle(index); | ||||||
|  |     } else if (event.button() == GMouseButton::Left) { | ||||||
|  |         // We might be starting a drag, so don't throw away other selected items yet.
 | ||||||
|  |         m_might_drag = true; | ||||||
|  |         m_selection.add(index); | ||||||
|  |     } else { | ||||||
|  |         m_selection.set(index); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     update(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GAbstractView::mousemove_event(GMouseEvent& event) | ||||||
|  | { | ||||||
|  |     if (!model() || !m_might_drag) | ||||||
|  |         return GScrollableWidget::mousemove_event(event); | ||||||
|  | 
 | ||||||
|  |     if (!(event.buttons() & GMouseButton::Left) || m_selection.is_empty()) { | ||||||
|  |         m_might_drag = false; | ||||||
|  |         return GScrollableWidget::mousemove_event(event); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     auto diff = event.position() - m_left_mousedown_position; | ||||||
|  |     auto distance_travelled_squared = diff.x() * diff.x() + diff.y() * diff.y(); | ||||||
|  |     constexpr int drag_distance_threshold = 5; | ||||||
|  | 
 | ||||||
|  |     if (distance_travelled_squared <= drag_distance_threshold) | ||||||
|  |         return GScrollableWidget::mousemove_event(event); | ||||||
|  | 
 | ||||||
|  |     dbg() << "Initiate drag!"; | ||||||
|  |     auto drag_operation = GDragOperation::construct(); | ||||||
|  | 
 | ||||||
|  |     RefPtr<GraphicsBitmap> bitmap; | ||||||
|  | 
 | ||||||
|  |     StringBuilder text_builder; | ||||||
|  |     StringBuilder data_builder; | ||||||
|  |     bool first = true; | ||||||
|  |     m_selection.for_each_index([&](auto& index) { | ||||||
|  |         auto text_data = m_model->data(index); | ||||||
|  |         if (!first) | ||||||
|  |             text_builder.append(", "); | ||||||
|  |         text_builder.append(text_data.to_string()); | ||||||
|  | 
 | ||||||
|  |         auto drag_data = m_model->data(index, GModel::Role::DragData); | ||||||
|  |         data_builder.append(drag_data.to_string()); | ||||||
|  |         data_builder.append('\n'); | ||||||
|  | 
 | ||||||
|  |         first = false; | ||||||
|  | 
 | ||||||
|  |         if (!bitmap) { | ||||||
|  |             GVariant icon_data = model()->data(index, GModel::Role::Icon); | ||||||
|  |             if (icon_data.is_icon()) | ||||||
|  |                 bitmap = icon_data.as_icon().bitmap_for_size(32); | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     drag_operation->set_text(text_builder.to_string()); | ||||||
|  |     drag_operation->set_bitmap(bitmap); | ||||||
|  |     drag_operation->set_data("url-list", data_builder.to_string()); | ||||||
|  | 
 | ||||||
|  |     auto outcome = drag_operation->exec(); | ||||||
|  | 
 | ||||||
|  |     switch (outcome) { | ||||||
|  |     case GDragOperation::Outcome::Accepted: | ||||||
|  |         dbg() << "Drag was accepted!"; | ||||||
|  |         break; | ||||||
|  |     case GDragOperation::Outcome::Cancelled: | ||||||
|  |         dbg() << "Drag was cancelled!"; | ||||||
|  |         break; | ||||||
|  |     default: | ||||||
|  |         ASSERT_NOT_REACHED(); | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GAbstractView::mouseup_event(GMouseEvent& event) | ||||||
|  | { | ||||||
|  |     GScrollableWidget::mouseup_event(event); | ||||||
|  | 
 | ||||||
|  |     if (!model()) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     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.
 | ||||||
|  |         // Since we're here, it was not that; so fix up the selection now.
 | ||||||
|  |         auto index = index_at_event_position(event.position()); | ||||||
|  |         if (index.is_valid()) | ||||||
|  |             m_selection.set(index); | ||||||
|  |         else | ||||||
|  |             m_selection.clear(); | ||||||
|  |         m_might_drag = false; | ||||||
|  |         update(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GAbstractView::doubleclick_event(GMouseEvent& event) | ||||||
|  | { | ||||||
|  |     if (!model()) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     if (event.button() != GMouseButton::Left) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     m_might_drag = false; | ||||||
|  | 
 | ||||||
|  |     auto index = index_at_event_position(event.position()); | ||||||
|  | 
 | ||||||
|  |     if (!index.is_valid()) | ||||||
|  |         m_selection.clear(); | ||||||
|  |     else if (!m_selection.contains(index)) | ||||||
|  |         m_selection.set(index); | ||||||
|  | 
 | ||||||
|  |     activate_selected(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GAbstractView::context_menu_event(GContextMenuEvent& event) | ||||||
|  | { | ||||||
|  |     if (!model()) | ||||||
|  |         return; | ||||||
|  | 
 | ||||||
|  |     auto index = index_at_event_position(event.position()); | ||||||
|  | 
 | ||||||
|  |     if (index.is_valid()) | ||||||
|  |         m_selection.add(index); | ||||||
|  |     else | ||||||
|  |         selection().clear(); | ||||||
|  | 
 | ||||||
|  |     if (on_context_menu_request) | ||||||
|  |         on_context_menu_request(index, event); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -76,6 +76,12 @@ protected: | ||||||
|     explicit GAbstractView(GWidget* parent); |     explicit GAbstractView(GWidget* parent); | ||||||
|     virtual ~GAbstractView() override; |     virtual ~GAbstractView() override; | ||||||
| 
 | 
 | ||||||
|  |     virtual void mousedown_event(GMouseEvent&) override; | ||||||
|  |     virtual void mousemove_event(GMouseEvent&) override; | ||||||
|  |     virtual void mouseup_event(GMouseEvent&) override; | ||||||
|  |     virtual void doubleclick_event(GMouseEvent&) override; | ||||||
|  |     virtual void context_menu_event(GContextMenuEvent&) override; | ||||||
|  | 
 | ||||||
|     virtual void did_scroll() override; |     virtual void did_scroll() override; | ||||||
|     void activate(const GModelIndex&); |     void activate(const GModelIndex&); | ||||||
|     void activate_selected(); |     void activate_selected(); | ||||||
|  | @ -86,6 +92,9 @@ protected: | ||||||
|     RefPtr<GWidget> m_edit_widget; |     RefPtr<GWidget> m_edit_widget; | ||||||
|     Rect m_edit_widget_content_rect; |     Rect m_edit_widget_content_rect; | ||||||
| 
 | 
 | ||||||
|  |     Point m_left_mousedown_position; | ||||||
|  |     bool m_might_drag { false }; | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     RefPtr<GModel> m_model; |     RefPtr<GModel> m_model; | ||||||
|     OwnPtr<GModelEditingDelegate> m_editing_delegate; |     OwnPtr<GModelEditingDelegate> m_editing_delegate; | ||||||
|  |  | ||||||
|  | @ -216,6 +216,8 @@ GModelIndex GColumnsView::index_at_event_position(const Point& a_position) const | ||||||
| 
 | 
 | ||||||
| void GColumnsView::mousedown_event(GMouseEvent& event) | void GColumnsView::mousedown_event(GMouseEvent& event) | ||||||
| { | { | ||||||
|  |     GAbstractView::mousedown_event(event); | ||||||
|  | 
 | ||||||
|     if (!model()) |     if (!model()) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  | @ -223,15 +225,7 @@ void GColumnsView::mousedown_event(GMouseEvent& event) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     auto index = index_at_event_position(event.position()); |     auto index = index_at_event_position(event.position()); | ||||||
|     if (!index.is_valid()) { |     if (index.is_valid() && !(event.modifiers() & Mod_Ctrl)) { | ||||||
|         selection().clear(); |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (event.modifiers() & Mod_Ctrl) { |  | ||||||
|         selection().toggle(index); |  | ||||||
|     } else { |  | ||||||
|         selection().set(index); |  | ||||||
|         if (model()->row_count(index)) |         if (model()->row_count(index)) | ||||||
|             push_column(index); |             push_column(index); | ||||||
|     } |     } | ||||||
|  | @ -250,34 +244,6 @@ void GColumnsView::did_update_model() | ||||||
|     update(); |     update(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GColumnsView::doubleclick_event(GMouseEvent& event) |  | ||||||
| { |  | ||||||
|     if (!model()) |  | ||||||
|         return; |  | ||||||
| 
 |  | ||||||
|     if (event.button() != GMouseButton::Left) |  | ||||||
|         return; |  | ||||||
| 
 |  | ||||||
|     mousedown_event(event); |  | ||||||
|     activate_selected(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GColumnsView::context_menu_event(GContextMenuEvent& event) |  | ||||||
| { |  | ||||||
|     if (!model()) |  | ||||||
|         return; |  | ||||||
| 
 |  | ||||||
|     auto index = index_at_event_position(event.position()); |  | ||||||
|     if (index.is_valid()) { |  | ||||||
|         if (!selection().contains(index)) |  | ||||||
|             selection().set(index); |  | ||||||
|     } else { |  | ||||||
|         selection().clear(); |  | ||||||
|     } |  | ||||||
|     if (on_context_menu_request) |  | ||||||
|         on_context_menu_request(index, event); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GColumnsView::keydown_event(GKeyEvent& event) | void GColumnsView::keydown_event(GKeyEvent& event) | ||||||
| { | { | ||||||
|     if (!model()) |     if (!model()) | ||||||
|  |  | ||||||
|  | @ -51,8 +51,6 @@ private: | ||||||
|     virtual void did_update_model() override; |     virtual void did_update_model() override; | ||||||
|     virtual void paint_event(GPaintEvent&) override; |     virtual void paint_event(GPaintEvent&) override; | ||||||
|     virtual void mousedown_event(GMouseEvent& event) override; |     virtual void mousedown_event(GMouseEvent& event) override; | ||||||
|     virtual void doubleclick_event(GMouseEvent& event) override; |  | ||||||
|     virtual void context_menu_event(GContextMenuEvent& event) override; |  | ||||||
|     virtual void keydown_event(GKeyEvent& event) override; |     virtual void keydown_event(GKeyEvent& event) override; | ||||||
| 
 | 
 | ||||||
|     struct Column { |     struct Column { | ||||||
|  |  | ||||||
|  | @ -138,32 +138,32 @@ GModelIndex GItemView::index_at_event_position(const Point& position) const | ||||||
| 
 | 
 | ||||||
| void GItemView::mousedown_event(GMouseEvent& event) | void GItemView::mousedown_event(GMouseEvent& event) | ||||||
| { | { | ||||||
|     auto index = index_at_event_position(event.position()); |     if (!model()) | ||||||
|  |         return GAbstractView::mousedown_event(event); | ||||||
| 
 | 
 | ||||||
|     if (event.button() == GMouseButton::Left) { |     if (event.button() != GMouseButton::Left) | ||||||
|         m_left_mousedown_position = event.position(); |         return GAbstractView::mousedown_event(event); | ||||||
|         if (!index.is_valid()) { | 
 | ||||||
|             if (event.modifiers() & Mod_Ctrl) { |     auto index = index_at_event_position(event.position()); | ||||||
|                 selection().for_each_index([&](auto& index) { |     if (index.is_valid()) { | ||||||
|                     m_rubber_band_remembered_selection.append(index); |         // We might start dragging this item, but not rubber-banding.
 | ||||||
|                 }); |         return GAbstractView::mousedown_event(event); | ||||||
|             } else { |  | ||||||
|                 selection().clear(); |  | ||||||
|             } |  | ||||||
|             m_rubber_banding = true; |  | ||||||
|             m_rubber_band_origin = event.position(); |  | ||||||
|             m_rubber_band_current = event.position(); |  | ||||||
|         } else { |  | ||||||
|             if (event.modifiers() & Mod_Ctrl) |  | ||||||
|                 selection().toggle(index); |  | ||||||
|             else if (selection().size() > 1) |  | ||||||
|                 m_might_drag = true; |  | ||||||
|             else |  | ||||||
|                 selection().set(index); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     GAbstractView::mousedown_event(event); |     ASSERT(m_rubber_band_remembered_selection.is_empty()); | ||||||
|  | 
 | ||||||
|  |     if (event.modifiers() & Mod_Ctrl) { | ||||||
|  |         selection().for_each_index([&](auto& index) { | ||||||
|  |             m_rubber_band_remembered_selection.append(index); | ||||||
|  |         }); | ||||||
|  |     } else { | ||||||
|  |         selection().clear(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     m_might_drag = false; | ||||||
|  |     m_rubber_banding = true; | ||||||
|  |     m_rubber_band_origin = event.position(); | ||||||
|  |     m_rubber_band_current = event.position(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GItemView::mouseup_event(GMouseEvent& event) | void GItemView::mouseup_event(GMouseEvent& event) | ||||||
|  | @ -172,14 +172,6 @@ void GItemView::mouseup_event(GMouseEvent& event) | ||||||
|         m_rubber_banding = false; |         m_rubber_banding = false; | ||||||
|         m_rubber_band_remembered_selection.clear(); |         m_rubber_band_remembered_selection.clear(); | ||||||
|         update(); |         update(); | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|     auto index = index_at_event_position(event.position()); |  | ||||||
|     if (index.is_valid()) { |  | ||||||
|         if ((selection().size() > 1) & m_might_drag) { |  | ||||||
|             selection().set(index); |  | ||||||
|             m_might_drag = false; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|     GAbstractView::mouseup_event(event); |     GAbstractView::mouseup_event(event); | ||||||
| } | } | ||||||
|  | @ -207,86 +199,9 @@ void GItemView::mousemove_event(GMouseEvent& event) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (event.buttons() & GMouseButton::Left && !selection().is_empty()) { |  | ||||||
|         auto diff = event.position() - m_left_mousedown_position; |  | ||||||
|         auto distance_travelled_squared = diff.x() * diff.x() + diff.y() * diff.y(); |  | ||||||
|         constexpr int drag_distance_threshold = 5; |  | ||||||
|         if (distance_travelled_squared > (drag_distance_threshold)) { |  | ||||||
|             dbg() << "Initiate drag!"; |  | ||||||
|             auto drag_operation = GDragOperation::construct(); |  | ||||||
| 
 |  | ||||||
|             RefPtr<GraphicsBitmap> bitmap; |  | ||||||
| 
 |  | ||||||
|             StringBuilder text_builder; |  | ||||||
|             StringBuilder data_builder; |  | ||||||
|             int index_iterations = 0; |  | ||||||
|             selection().for_each_index([&](auto& index) { |  | ||||||
|                 index_iterations++; |  | ||||||
|                 auto text_data = model()->data(index); |  | ||||||
|                 if (index_iterations == 0) |  | ||||||
|                     text_builder.append(" "); |  | ||||||
|                 text_builder.append(text_data.to_string()); |  | ||||||
|                 if (!(index_iterations == selection().size())) |  | ||||||
|                     text_builder.append(", "); |  | ||||||
| 
 |  | ||||||
|                 auto drag_data = model()->data(index, GModel::Role::DragData); |  | ||||||
|                 data_builder.append(drag_data.to_string()); |  | ||||||
|                 data_builder.append('\n'); |  | ||||||
| 
 |  | ||||||
|                 if (!bitmap) { |  | ||||||
|                     GVariant icon_data = model()->data(index, GModel::Role::Icon); |  | ||||||
|                     if (icon_data.is_icon()) |  | ||||||
|                         bitmap = icon_data.as_icon().bitmap_for_size(32); |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
| 
 |  | ||||||
|             drag_operation->set_text(text_builder.to_string()); |  | ||||||
|             drag_operation->set_bitmap(bitmap); |  | ||||||
|             drag_operation->set_data("url-list", data_builder.to_string()); |  | ||||||
|             auto outcome = drag_operation->exec(); |  | ||||||
|             switch (outcome) { |  | ||||||
|             case GDragOperation::Outcome::Accepted: |  | ||||||
|                 dbg() << "Drag was accepted!"; |  | ||||||
|                 break; |  | ||||||
|             case GDragOperation::Outcome::Cancelled: |  | ||||||
|                 dbg() << "Drag was cancelled!"; |  | ||||||
|                 break; |  | ||||||
|             default: |  | ||||||
|                 ASSERT_NOT_REACHED(); |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     GAbstractView::mousemove_event(event); |     GAbstractView::mousemove_event(event); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GItemView::context_menu_event(GContextMenuEvent& event) |  | ||||||
| { |  | ||||||
|     if (!model()) |  | ||||||
|         return; |  | ||||||
|     auto index = index_at_event_position(event.position()); |  | ||||||
|     if (index.is_valid()) { |  | ||||||
|         if (!selection().contains(index)) |  | ||||||
|             selection().set(index); |  | ||||||
|     } else { |  | ||||||
|         selection().clear(); |  | ||||||
|     } |  | ||||||
|     if (on_context_menu_request) |  | ||||||
|         on_context_menu_request(index, event); |  | ||||||
|     GAbstractView::context_menu_event(event); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GItemView::doubleclick_event(GMouseEvent& event) |  | ||||||
| { |  | ||||||
|     if (!model()) |  | ||||||
|         return; |  | ||||||
|     if (event.button() == GMouseButton::Left) { |  | ||||||
|         mousedown_event(event); |  | ||||||
|         activate_selected(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GItemView::get_item_rects(int item_index, const Font& font, const GVariant& item_text, Rect& item_rect, Rect& icon_rect, Rect& text_rect) const | void GItemView::get_item_rects(int item_index, const Font& font, const GVariant& item_text, Rect& item_rect, Rect& icon_rect, Rect& text_rect) const | ||||||
| { | { | ||||||
|     item_rect = this->item_rect(item_index); |     item_rect = this->item_rect(item_index); | ||||||
|  |  | ||||||
|  | @ -61,8 +61,6 @@ private: | ||||||
|     virtual void mousemove_event(GMouseEvent&) override; |     virtual void mousemove_event(GMouseEvent&) override; | ||||||
|     virtual void mouseup_event(GMouseEvent&) override; |     virtual void mouseup_event(GMouseEvent&) override; | ||||||
|     virtual void keydown_event(GKeyEvent&) override; |     virtual void keydown_event(GKeyEvent&) override; | ||||||
|     virtual void doubleclick_event(GMouseEvent&) override; |  | ||||||
|     virtual void context_menu_event(GContextMenuEvent&) override; |  | ||||||
| 
 | 
 | ||||||
|     int item_count() const; |     int item_count() const; | ||||||
|     Rect item_rect(int item_index) const; |     Rect item_rect(int item_index) const; | ||||||
|  | @ -75,10 +73,6 @@ private: | ||||||
|     int m_visual_column_count { 0 }; |     int m_visual_column_count { 0 }; | ||||||
|     int m_visual_row_count { 0 }; |     int m_visual_row_count { 0 }; | ||||||
| 
 | 
 | ||||||
|     bool m_might_drag { false }; |  | ||||||
| 
 |  | ||||||
|     Point m_left_mousedown_position; |  | ||||||
| 
 |  | ||||||
|     Size m_effective_item_size { 80, 80 }; |     Size m_effective_item_size { 80, 80 }; | ||||||
| 
 | 
 | ||||||
|     bool m_rubber_banding { false }; |     bool m_rubber_banding { false }; | ||||||
|  |  | ||||||
|  | @ -102,25 +102,6 @@ Point GListView::adjusted_position(const Point& position) const | ||||||
|     return position.translated(horizontal_scrollbar().value() - frame_thickness(), vertical_scrollbar().value() - frame_thickness()); |     return position.translated(horizontal_scrollbar().value() - frame_thickness(), vertical_scrollbar().value() - frame_thickness()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GListView::mousedown_event(GMouseEvent& event) |  | ||||||
| { |  | ||||||
|     if (!model()) |  | ||||||
|         return; |  | ||||||
| 
 |  | ||||||
|     if (event.button() != GMouseButton::Left) |  | ||||||
|         return; |  | ||||||
| 
 |  | ||||||
|     auto index = index_at_event_position(event.position()); |  | ||||||
|     if (index.is_valid()) { |  | ||||||
|         if (event.modifiers() & Mod_Ctrl) |  | ||||||
|             selection().toggle(index); |  | ||||||
|         else |  | ||||||
|             selection().set(index); |  | ||||||
|     } else { |  | ||||||
|         selection().clear(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GListView::paint_event(GPaintEvent& event) | void GListView::paint_event(GPaintEvent& event) | ||||||
| { | { | ||||||
|     GFrame::paint_event(event); |     GFrame::paint_event(event); | ||||||
|  |  | ||||||
|  | @ -60,7 +60,6 @@ public: | ||||||
| private: | private: | ||||||
|     virtual void did_update_model() override; |     virtual void did_update_model() override; | ||||||
|     virtual void paint_event(GPaintEvent&) override; |     virtual void paint_event(GPaintEvent&) override; | ||||||
|     virtual void mousedown_event(GMouseEvent&) override; |  | ||||||
|     virtual void doubleclick_event(GMouseEvent&) override; |     virtual void doubleclick_event(GMouseEvent&) override; | ||||||
|     virtual void keydown_event(GKeyEvent&) override; |     virtual void keydown_event(GKeyEvent&) override; | ||||||
|     virtual void resize_event(GResizeEvent&) override; |     virtual void resize_event(GResizeEvent&) override; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Sergey Bugaev
						Sergey Bugaev