mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:17:34 +00:00
LibGUI: Implement basic rubber band selections in ColumnsView
This patch adds the ability to select multiple entries in a column using a rubber band selection. Currently the implementation is lacking support for expanding a selection using the ctrl modifier.
This commit is contained in:
parent
f0a20fc902
commit
9b6fab264f
2 changed files with 80 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020, Sergey Bugaev <bugaevc@serenityos.org>
|
* Copyright (c) 2020, Sergey Bugaev <bugaevc@serenityos.org>
|
||||||
* Copyright (c) 2022, the SerenityOS developers.
|
* Copyright (c) 2022, the SerenityOS developers.
|
||||||
|
* Copyright (c) 2022, Jakob-Niklas See <git@nwex.de>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -57,6 +58,29 @@ void ColumnsView::select_all()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ColumnsView::second_paint_event(PaintEvent& event)
|
||||||
|
{
|
||||||
|
if (!m_rubber_banding)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Painter painter(*this);
|
||||||
|
painter.add_clip_rect(event.rect());
|
||||||
|
painter.add_clip_rect(widget_inner_rect());
|
||||||
|
painter.translate(frame_thickness(), frame_thickness());
|
||||||
|
painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value());
|
||||||
|
|
||||||
|
int column_x = 0;
|
||||||
|
for (auto const& column : m_columns) {
|
||||||
|
if (m_rubber_band_origin_column.parent_index == column.parent_index)
|
||||||
|
break;
|
||||||
|
column_x += column.width + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rubber_band_rect = Gfx::IntRect::from_two_points({ column_x, m_rubber_band_origin }, { column_x + m_rubber_band_origin_column.width, m_rubber_band_current });
|
||||||
|
painter.fill_rect(rubber_band_rect, palette().rubber_band_fill());
|
||||||
|
painter.draw_rect(rubber_band_rect, palette().rubber_band_border());
|
||||||
|
}
|
||||||
|
|
||||||
void ColumnsView::paint_event(PaintEvent& event)
|
void ColumnsView::paint_event(PaintEvent& event)
|
||||||
{
|
{
|
||||||
AbstractView::paint_event(event);
|
AbstractView::paint_event(event);
|
||||||
|
@ -280,6 +304,54 @@ void ColumnsView::mousedown_event(MouseEvent& event)
|
||||||
if (index.is_valid() && !(event.modifiers() & Mod_Ctrl)) {
|
if (index.is_valid() && !(event.modifiers() & Mod_Ctrl)) {
|
||||||
if (model()->row_count(index))
|
if (model()->row_count(index))
|
||||||
push_column(index);
|
push_column(index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selection_mode() == SelectionMode::MultiSelection) {
|
||||||
|
m_rubber_banding = true;
|
||||||
|
m_rubber_band_origin_column = *column;
|
||||||
|
m_rubber_band_origin = event.position().y();
|
||||||
|
m_rubber_band_current = event.position().y();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColumnsView::mousemove_event(MouseEvent& event)
|
||||||
|
{
|
||||||
|
if (m_rubber_banding) {
|
||||||
|
m_rubber_band_current = AK::clamp(event.position().y(), 0, widget_inner_rect().height());
|
||||||
|
|
||||||
|
auto parent = m_rubber_band_origin_column.parent_index;
|
||||||
|
int row_count = model()->row_count(parent);
|
||||||
|
|
||||||
|
clear_selection();
|
||||||
|
|
||||||
|
set_suppress_update_on_selection_change(true);
|
||||||
|
|
||||||
|
for (int row = 0; row < row_count; row++) {
|
||||||
|
auto index = model()->index(row, m_model_column, parent);
|
||||||
|
VERIFY(index.is_valid());
|
||||||
|
|
||||||
|
int row_top = row * item_height();
|
||||||
|
int row_bottom = row * item_height() + item_height();
|
||||||
|
|
||||||
|
if ((m_rubber_band_origin > row_top && m_rubber_band_current < row_top) || (m_rubber_band_origin > row_bottom && m_rubber_band_current < row_bottom)) {
|
||||||
|
add_selection(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
set_suppress_update_on_selection_change(false);
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractView::mousemove_event(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColumnsView::mouseup_event(MouseEvent& event)
|
||||||
|
{
|
||||||
|
if (m_rubber_banding && event.button() == MouseButton::Primary) {
|
||||||
|
m_rubber_banding = false;
|
||||||
|
update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,11 @@ private:
|
||||||
int text_padding() const { return 2; }
|
int text_padding() const { return 2; }
|
||||||
|
|
||||||
virtual void model_did_update(unsigned flags) override;
|
virtual void model_did_update(unsigned flags) override;
|
||||||
|
virtual void second_paint_event(PaintEvent&) override;
|
||||||
virtual void paint_event(PaintEvent&) override;
|
virtual void paint_event(PaintEvent&) override;
|
||||||
virtual void mousedown_event(MouseEvent& event) override;
|
virtual void mousedown_event(MouseEvent& event) override;
|
||||||
|
virtual void mousemove_event(MouseEvent&) override;
|
||||||
|
virtual void mouseup_event(MouseEvent&) override;
|
||||||
|
|
||||||
virtual void select_range(ModelIndex const&) override;
|
virtual void select_range(ModelIndex const&) override;
|
||||||
|
|
||||||
|
@ -51,6 +54,11 @@ private:
|
||||||
Optional<Column> column_at_event_position(Gfx::IntPoint const&) const;
|
Optional<Column> column_at_event_position(Gfx::IntPoint const&) const;
|
||||||
ModelIndex index_at_event_position_in_column(Gfx::IntPoint const&, Column const&) const;
|
ModelIndex index_at_event_position_in_column(Gfx::IntPoint const&, Column const&) const;
|
||||||
|
|
||||||
|
bool m_rubber_banding { false };
|
||||||
|
int m_rubber_band_origin { 0 };
|
||||||
|
Column m_rubber_band_origin_column;
|
||||||
|
int m_rubber_band_current { 0 };
|
||||||
|
|
||||||
Vector<Column> m_columns;
|
Vector<Column> m_columns;
|
||||||
int m_model_column { 0 };
|
int m_model_column { 0 };
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue