mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 08:48:11 +00:00
LibGUI: Refine the per-item rects in GItemView
Previously we would consider anything in the large padded area around each item to also be part of the item for mouse event purposes. This didn't feel right when rubberbanding, so this patch factors out the per-item rect computation into a get_item_rects() helper which can then be used by the various functions that need it.
This commit is contained in:
parent
6e21d5c432
commit
5a02a0d140
2 changed files with 51 additions and 19 deletions
|
@ -71,14 +71,40 @@ Rect GItemView::item_rect(int item_index) const
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector<int> GItemView::items_intersecting_rect(const Rect& rect) const
|
||||||
|
{
|
||||||
|
ASSERT(model());
|
||||||
|
const auto& column_metadata = model()->column_metadata(model_column());
|
||||||
|
const auto& font = column_metadata.font ? *column_metadata.font : this->font();
|
||||||
|
Vector<int> item_indexes;
|
||||||
|
for (int item_index = 0; item_index < item_count(); ++item_index) {
|
||||||
|
Rect item_rect;
|
||||||
|
Rect icon_rect;
|
||||||
|
Rect text_rect;
|
||||||
|
auto item_text = model()->data(model()->index(item_index, model_column()));
|
||||||
|
get_item_rects(item_index, font, item_text, item_rect, icon_rect, text_rect);
|
||||||
|
if (icon_rect.intersects(rect) || text_rect.intersects(rect))
|
||||||
|
item_indexes.append(item_index);
|
||||||
|
}
|
||||||
|
return item_indexes;
|
||||||
|
}
|
||||||
|
|
||||||
int GItemView::item_at_event_position(const Point& position) const
|
int GItemView::item_at_event_position(const Point& position) const
|
||||||
{
|
{
|
||||||
|
ASSERT(model());
|
||||||
// FIXME: Since all items are the same size, just compute the clicked item index
|
// FIXME: Since all items are the same size, just compute the clicked item index
|
||||||
// instead of iterating over everything.
|
// instead of iterating over everything.
|
||||||
auto adjusted_position = position.translated(0, vertical_scrollbar().value());
|
auto adjusted_position = position.translated(0, vertical_scrollbar().value());
|
||||||
for (int i = 0; i < item_count(); ++i) {
|
const auto& column_metadata = model()->column_metadata(model_column());
|
||||||
if (item_rect(i).contains(adjusted_position))
|
const auto& font = column_metadata.font ? *column_metadata.font : this->font();
|
||||||
return i;
|
for (int item_index = 0; item_index < item_count(); ++item_index) {
|
||||||
|
Rect item_rect;
|
||||||
|
Rect icon_rect;
|
||||||
|
Rect text_rect;
|
||||||
|
auto item_text = model()->data(model()->index(item_index, model_column()));
|
||||||
|
get_item_rects(item_index, font, item_text, item_rect, icon_rect, text_rect);
|
||||||
|
if (icon_rect.contains(adjusted_position) || text_rect.contains(adjusted_position))
|
||||||
|
return item_index;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -126,10 +152,8 @@ void GItemView::mousemove_event(GMouseEvent& event)
|
||||||
m_rubber_band_current = event.position();
|
m_rubber_band_current = event.position();
|
||||||
auto rubber_band_rect = Rect::from_two_points(m_rubber_band_origin, m_rubber_band_current);
|
auto rubber_band_rect = Rect::from_two_points(m_rubber_band_origin, m_rubber_band_current);
|
||||||
selection().clear();
|
selection().clear();
|
||||||
for (int row_index = 0, row_count = model()->row_count(); row_index < row_count; ++row_index) {
|
for (auto item_index : items_intersecting_rect(rubber_band_rect)) {
|
||||||
auto item_rect = this->item_rect(row_index);
|
selection().add(model()->index(item_index, model_column()));
|
||||||
if (item_rect.intersects(rubber_band_rect))
|
|
||||||
selection().add(model()->index(row_index, model_column()));
|
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
return;
|
return;
|
||||||
|
@ -215,6 +239,18 @@ void GItemView::doubleclick_event(GMouseEvent& event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
icon_rect = { 0, 0, 32, 32 };
|
||||||
|
icon_rect.center_within(item_rect);
|
||||||
|
icon_rect.move_by(0, -font.glyph_height() - 6);
|
||||||
|
text_rect = { 0, icon_rect.bottom() + 6 + 1, font.width(item_text.to_string()), font.glyph_height() };
|
||||||
|
text_rect.center_horizontally_within(item_rect);
|
||||||
|
text_rect.inflate(6, 4);
|
||||||
|
text_rect.intersect(item_rect);
|
||||||
|
}
|
||||||
|
|
||||||
void GItemView::second_paint_event(GPaintEvent& event)
|
void GItemView::second_paint_event(GPaintEvent& event)
|
||||||
{
|
{
|
||||||
if (!m_rubber_banding)
|
if (!m_rubber_banding)
|
||||||
|
@ -243,7 +279,8 @@ void GItemView::paint_event(GPaintEvent& event)
|
||||||
const Font& font = column_metadata.font ? *column_metadata.font : this->font();
|
const Font& font = column_metadata.font ? *column_metadata.font : this->font();
|
||||||
|
|
||||||
for (int item_index = 0; item_index < model()->row_count(); ++item_index) {
|
for (int item_index = 0; item_index < model()->row_count(); ++item_index) {
|
||||||
bool is_selected_item = selection().contains(model()->index(item_index, m_model_column));
|
auto model_index = model()->index(item_index, m_model_column);
|
||||||
|
bool is_selected_item = selection().contains(model_index);
|
||||||
Color background_color;
|
Color background_color;
|
||||||
if (is_selected_item) {
|
if (is_selected_item) {
|
||||||
background_color = is_focused() ? palette().selection() : Color::from_rgb(0x606060);
|
background_color = is_focused() ? palette().selection() : Color::from_rgb(0x606060);
|
||||||
|
@ -251,26 +288,19 @@ void GItemView::paint_event(GPaintEvent& event)
|
||||||
background_color = widget_background_color;
|
background_color = widget_background_color;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect item_rect = this->item_rect(item_index);
|
|
||||||
auto model_index = model()->index(item_index, m_model_column);
|
|
||||||
|
|
||||||
auto icon = model()->data(model_index, GModel::Role::Icon);
|
auto icon = model()->data(model_index, GModel::Role::Icon);
|
||||||
auto item_text = model()->data(model_index, GModel::Role::Display);
|
auto item_text = model()->data(model_index, GModel::Role::Display);
|
||||||
|
|
||||||
Rect icon_rect = { 0, 0, 32, 32 };
|
Rect item_rect;
|
||||||
icon_rect.center_within(item_rect);
|
Rect icon_rect;
|
||||||
icon_rect.move_by(0, -font.glyph_height() - 6);
|
Rect text_rect;
|
||||||
|
get_item_rects(item_index, font, item_text, item_rect, icon_rect, text_rect);
|
||||||
|
|
||||||
if (icon.is_icon()) {
|
if (icon.is_icon()) {
|
||||||
if (auto bitmap = icon.as_icon().bitmap_for_size(icon_rect.width()))
|
if (auto bitmap = icon.as_icon().bitmap_for_size(icon_rect.width()))
|
||||||
painter.draw_scaled_bitmap(icon_rect, *bitmap, bitmap->rect());
|
painter.draw_scaled_bitmap(icon_rect, *bitmap, bitmap->rect());
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect text_rect { 0, icon_rect.bottom() + 6 + 1, font.width(item_text.to_string()), font.glyph_height() };
|
|
||||||
text_rect.center_horizontally_within(item_rect);
|
|
||||||
text_rect.inflate(6, 4);
|
|
||||||
text_rect.intersect(item_rect);
|
|
||||||
|
|
||||||
Color text_color;
|
Color text_color;
|
||||||
if (is_selected_item)
|
if (is_selected_item)
|
||||||
text_color = palette().selection_text();
|
text_color = palette().selection_text();
|
||||||
|
|
|
@ -39,7 +39,9 @@ private:
|
||||||
int item_count() const;
|
int item_count() const;
|
||||||
Rect item_rect(int item_index) const;
|
Rect item_rect(int item_index) const;
|
||||||
int item_at_event_position(const Point&) const;
|
int item_at_event_position(const Point&) const;
|
||||||
|
Vector<int> items_intersecting_rect(const Rect&) const;
|
||||||
void update_content_size();
|
void update_content_size();
|
||||||
|
void get_item_rects(int item_index, const Font&, const GVariant& item_text, Rect& item_rect, Rect& icon_rect, Rect& text_rect) const;
|
||||||
|
|
||||||
int m_horizontal_padding { 5 };
|
int m_horizontal_padding { 5 };
|
||||||
int m_model_column { 0 };
|
int m_model_column { 0 };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue