diff options
author | Andreas Kling <kling@serenityos.org> | 2020-08-26 15:54:03 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-08-26 17:00:40 +0200 |
commit | 447b65bf7ba035d7c321d1046c6a42b97dd71fbb (patch) | |
tree | 04bfe21d0301d6dcdc8951399bbe6dbded11e0f6 /Libraries | |
parent | 49a5038a1aca68b766805788f8e28e22372d91fb (diff) | |
download | serenity-447b65bf7ba035d7c321d1046c6a42b97dd71fbb.zip |
LibGUI: Add (optional) row headers to GUI::TableView
You can now get row headers in your TableView by simply calling:
table_view.row_header().set_visible(true)
Note that rows are not yet resizable.
Diffstat (limited to 'Libraries')
-rw-r--r-- | Libraries/LibGUI/AbstractTableView.cpp | 46 | ||||
-rw-r--r-- | Libraries/LibGUI/AbstractTableView.h | 13 | ||||
-rw-r--r-- | Libraries/LibGUI/HeaderView.cpp | 39 | ||||
-rw-r--r-- | Libraries/LibGUI/HeaderView.h | 3 | ||||
-rw-r--r-- | Libraries/LibGUI/TableView.cpp | 9 |
5 files changed, 92 insertions, 18 deletions
diff --git a/Libraries/LibGUI/AbstractTableView.cpp b/Libraries/LibGUI/AbstractTableView.cpp index f778c17df8..4994cca09d 100644 --- a/Libraries/LibGUI/AbstractTableView.cpp +++ b/Libraries/LibGUI/AbstractTableView.cpp @@ -42,6 +42,9 @@ AbstractTableView::AbstractTableView() { m_column_header = add<HeaderView>(*this, Gfx::Orientation::Horizontal); m_column_header->move_to_back(); + m_row_header = add<HeaderView>(*this, Gfx::Orientation::Vertical); + m_row_header->move_to_back(); + m_row_header->set_visible(false); set_should_hide_unnecessary_scrollbars(true); } @@ -90,6 +93,21 @@ void AbstractTableView::update_column_sizes() } } +void AbstractTableView::update_row_sizes() +{ + if (!model()) + return; + + auto& model = *this->model(); + int row_count = model.row_count(); + + for (int row = 0; row < row_count; ++row) { + if (!column_header().is_section_visible(row)) + continue; + row_header().set_section_size(row, item_height()); + } +} + void AbstractTableView::update_content_size() { if (!model()) @@ -105,8 +123,8 @@ void AbstractTableView::update_content_size() int content_height = item_count() * item_height(); set_content_size({ content_width, content_height }); - column_header().set_width(content_width); - set_size_occupied_by_fixed_elements({ 0, m_column_header->height() }); + set_size_occupied_by_fixed_elements({ row_header().width(), column_header().height() }); + layout_headers(); } TableCellPaintingDelegate* AbstractTableView::column_painting_delegate(int column) const @@ -278,7 +296,7 @@ Gfx::IntRect AbstractTableView::content_rect(const ModelIndex& index) const Gfx::IntRect AbstractTableView::row_rect(int item_index) const { - return { 0, m_column_header->height() + (item_index * item_height()), max(content_size().width(), width()), item_height() }; + return { row_header().is_visible() ? row_header().width() : 0 , column_header().height() + (item_index * item_height()), max(content_size().width(), width()), item_height() }; } Gfx::IntPoint AbstractTableView::adjusted_position(const Gfx::IntPoint& position) const @@ -289,6 +307,7 @@ Gfx::IntPoint AbstractTableView::adjusted_position(const Gfx::IntPoint& position void AbstractTableView::did_update_model(unsigned flags) { AbstractView::did_update_model(flags); + update_row_sizes(); update_column_sizes(); update_content_size(); update(); @@ -297,9 +316,7 @@ void AbstractTableView::did_update_model(unsigned flags) void AbstractTableView::resize_event(ResizeEvent& event) { AbstractView::resize_event(event); - - if (column_header().is_visible()) - column_header().set_relative_rect(frame_thickness(), frame_thickness(), content_width(), column_header().preferred_size().height()); + layout_headers(); } void AbstractTableView::header_did_change_section_size(Badge<HeaderView>, Gfx::Orientation, int, int) @@ -327,7 +344,22 @@ void AbstractTableView::set_column_headers_visible(bool visible) void AbstractTableView::did_scroll() { AbstractView::did_scroll(); - column_header().set_x(frame_thickness() + -horizontal_scrollbar().value()); + layout_headers(); +} + +void AbstractTableView::layout_headers() +{ + if (column_header().is_visible()) { + int x = frame_thickness() + (row_header().is_visible() ? row_header().width() : 0) + -horizontal_scrollbar().value(); + int y = frame_thickness(); + column_header().set_relative_rect(x, y, content_width(), column_header().preferred_size().height()); + } + + if (row_header().is_visible()) { + int x = frame_thickness(); + int y = (frame_thickness() + (column_header().is_visible() ? column_header().height() : 0)) + -vertical_scrollbar().value(); + row_header().set_relative_rect(x, y, row_header().preferred_size().width(), content_height()); + } } } diff --git a/Libraries/LibGUI/AbstractTableView.h b/Libraries/LibGUI/AbstractTableView.h index 318d56e1f3..34ca3b4950 100644 --- a/Libraries/LibGUI/AbstractTableView.h +++ b/Libraries/LibGUI/AbstractTableView.h @@ -82,6 +82,12 @@ public: virtual void did_scroll() override; + HeaderView& column_header() { return *m_column_header; } + const HeaderView& column_header() const { return *m_column_header; } + + HeaderView& row_header() { return *m_row_header; } + const HeaderView& row_header() const { return *m_row_header; } + protected: virtual ~AbstractTableView() override; AbstractTableView(); @@ -96,15 +102,16 @@ protected: void update_content_size(); virtual void update_column_sizes(); + virtual void update_row_sizes(); virtual int item_count() const; TableCellPaintingDelegate* column_painting_delegate(int column) const; - HeaderView& column_header() { return *m_column_header; } - const HeaderView& column_header() const { return *m_column_header; } - private: + void layout_headers(); + RefPtr<HeaderView> m_column_header; + RefPtr<HeaderView> m_row_header; HashMap<int, OwnPtr<TableCellPaintingDelegate>> m_column_painting_delegate; diff --git a/Libraries/LibGUI/HeaderView.cpp b/Libraries/LibGUI/HeaderView.cpp index 8ffb74fb84..99bd38fdec 100644 --- a/Libraries/LibGUI/HeaderView.cpp +++ b/Libraries/LibGUI/HeaderView.cpp @@ -221,11 +221,8 @@ void HeaderView::mouseup_event(MouseEvent& event) } } -void HeaderView::paint_event(PaintEvent& event) +void HeaderView::paint_horizontal(Painter& painter) { - Painter painter(*this); - painter.add_clip_rect(event.rect()); - painter.fill_rect(rect(), palette().button()); painter.draw_line({ 0, 0 }, { rect().right(), 0 }, palette().threed_highlight()); painter.draw_line({ 0, rect().bottom() }, { rect().right(), rect().bottom() }, palette().threed_shadow1()); int x_offset = 0; @@ -259,6 +256,40 @@ void HeaderView::paint_event(PaintEvent& event) } } +void HeaderView::paint_vertical(Painter& painter) +{ + painter.draw_line(rect().top_left(), rect().bottom_left(), palette().threed_highlight()); + painter.draw_line(rect().top_right(), rect().bottom_right(), palette().threed_shadow1()); + int y_offset = 0; + int section_count = this->section_count(); + for (int section = 0; section < section_count; ++section) { + if (!is_section_visible(section)) + continue; + int section_size = this->section_size(section); + Gfx::IntRect cell_rect(0, y_offset, width(), section_size); + bool pressed = section == m_pressed_section && m_pressed_section_is_pressed; + bool hovered = false; + Gfx::StylePainter::paint_button(painter, cell_rect, palette(), Gfx::ButtonStyle::Normal, pressed, hovered); + String text = String::format("%d", section); + auto text_rect = cell_rect.shrunken(horizontal_padding() * 2, 0); + if (pressed) + text_rect.move_by(1, 1); + painter.draw_text(text_rect, text, font(), section_alignment(section), palette().button_text()); + y_offset += section_size; + } +} + +void HeaderView::paint_event(PaintEvent& event) +{ + Painter painter(*this); + painter.add_clip_rect(event.rect()); + painter.fill_rect(rect(), palette().button()); + if (orientation() == Gfx::Orientation::Horizontal) + paint_horizontal(painter); + else + paint_vertical(painter); +} + void HeaderView::set_section_visible(int section, bool visible) { auto& data = section_data(section); diff --git a/Libraries/LibGUI/HeaderView.h b/Libraries/LibGUI/HeaderView.h index a4cb1d4a7c..eb68fc7403 100644 --- a/Libraries/LibGUI/HeaderView.h +++ b/Libraries/LibGUI/HeaderView.h @@ -68,6 +68,9 @@ private: Gfx::IntRect section_resize_grabbable_rect(int) const; + void paint_horizontal(Painter&); + void paint_vertical(Painter&); + Menu& ensure_context_menu(); RefPtr<Menu> m_context_menu; diff --git a/Libraries/LibGUI/TableView.cpp b/Libraries/LibGUI/TableView.cpp index cd7aec09cb..ea4b25aac5 100644 --- a/Libraries/LibGUI/TableView.cpp +++ b/Libraries/LibGUI/TableView.cpp @@ -66,7 +66,8 @@ void TableView::paint_event(PaintEvent& event) return; int exposed_width = max(content_size().width(), width()); - int y_offset = column_header().height(); + int x_offset = row_header().is_visible() ? row_header().width() : 0; + int y_offset = column_header().is_visible() ? column_header().height() : 0; bool dummy; int first_visible_row = index_at_event_position(frame_inner_rect().top_left(), dummy).row(); @@ -99,13 +100,13 @@ void TableView::paint_event(PaintEvent& event) } painter.fill_rect(row_rect(painted_item_index), background_color); - int x_offset = 0; + int x = x_offset; for (int column_index = 0; column_index < model()->column_count(); ++column_index) { if (!column_header().is_section_visible(column_index)) continue; int column_width = this->column_width(column_index); bool is_key_column = m_key_column == column_index; - Gfx::IntRect cell_rect(horizontal_padding() + x_offset, y, column_width, item_height()); + Gfx::IntRect cell_rect(horizontal_padding() + x, y, column_width, item_height()); auto cell_rect_for_fill = cell_rect.inflated(horizontal_padding() * 2, 0); if (is_key_column) painter.fill_rect(cell_rect_for_fill, key_column_background_color); @@ -139,7 +140,7 @@ void TableView::paint_event(PaintEvent& event) painter.draw_text(cell_rect, data.to_string(), font_for_index(cell_index), text_alignment, text_color, Gfx::TextElision::Right); } } - x_offset += column_width + horizontal_padding() * 2; + x += column_width + horizontal_padding() * 2; } ++painted_item_index; }; |