From a1a289c4c09c2ef8b8e19be0b65e60442f833e5e Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Mon, 21 Apr 2014 07:50:19 -0700 Subject: [PATCH] Push more of the painting logic into the grid column classes --- src/base_grid.cpp | 105 +++++++++++++++++++++----------------------- src/base_grid.h | 6 +-- src/grid_column.cpp | 42 ++++++++++++------ src/grid_column.h | 19 ++++++-- 4 files changed, 95 insertions(+), 77 deletions(-) diff --git a/src/base_grid.cpp b/src/base_grid.cpp index f3359df0e..fc577543a 100644 --- a/src/base_grid.cpp +++ b/src/base_grid.cpp @@ -69,6 +69,7 @@ BaseGrid::BaseGrid(wxWindow* parent, agi::Context *context) , scrollBar(new wxScrollBar(this, GRID_SCROLLBAR, wxDefaultPosition, wxDefaultSize, wxSB_VERTICAL)) , context(context) , columns(GetGridColumns()) +, columns_visible(OPT_GET("Subtitle/Grid/Column")->GetListBool()) , seek_listener(context->videoController->AddSeekListener([&] { Refresh(false); })) { scrollBar->SetScrollbar(0,10,100,10); @@ -81,6 +82,11 @@ BaseGrid::BaseGrid(wxWindow* parent, agi::Context *context) SetBackgroundStyle(wxBG_STYLE_PAINT); + for (size_t i : agi::util::range(std::min(columns_visible.size(), columns.size()))) { + if (!columns_visible[i]) + columns[i]->SetVisible(false); + } + UpdateStyle(); OnHighlightVisibleChange(*OPT_GET("Subtitle/Grid/Highlight Subtitles in Frame")); @@ -151,11 +157,14 @@ void BaseGrid::OnSubtitlesSave() { void BaseGrid::OnShowColMenu(wxCommandEvent &event) { int item = event.GetId() - MENU_SHOW_COL; - column_shown[item] = !column_shown[item]; + bool new_value = !columns_visible[item]; - OPT_SET("Subtitle/Grid/Column")->SetListBool(std::vector(std::begin(column_shown), std::end(column_shown))); + columns_visible[item] = new_value; + OPT_SET("Subtitle/Grid/Column")->SetListBool(columns_visible); + columns[item]->SetVisible(new_value); SetColumnWidths(); + Refresh(false); } @@ -188,15 +197,6 @@ void BaseGrid::UpdateStyle() { row_colors.SelectedComment.SetColour(to_wx(OPT_GET("Colour/Subtitle Grid/Background/Selected Comment")->GetColor())); row_colors.LeftCol.SetColour(to_wx(OPT_GET("Colour/Subtitle Grid/Left Column")->GetColor())); - // Set column widths - std::vector column_array(OPT_GET("Subtitle/Grid/Column")->GetListBool()); - column_shown.assign(column_array.begin(), column_array.end()); - column_shown.resize(columns.size(), true); - - column_header_widths.resize(columns.size()); - for (size_t i : agi::util::range(columns.size())) - column_header_widths[i] = dc.GetTextExtent(columns[i]->Header()).GetWidth(); - SetColumnWidths(); AdjustScrollbar(); @@ -255,20 +255,23 @@ void BaseGrid::SelectRow(int row, bool addToSelected, bool select) { void BaseGrid::OnPaint(wxPaintEvent &) { // Find which columns need to be repainted - std::vector paint_columns; + std::vector paint_columns; + paint_columns.resize(columns.size(), false); + bool any = false; for (wxRegionIterator region(GetUpdateRegion()); region; ++region) { wxRect updrect = region.GetRect(); int x = 0; for (size_t i : agi::util::range(columns.size())) { - if (updrect.x < x + column_widths[i] && updrect.x + updrect.width > x && column_widths[i]) - paint_columns.push_back(columns[i].get()); - else - paint_columns.push_back(nullptr); - x += column_widths[i]; + int width = columns[i]->Width(); + if (width && updrect.x < x + width && updrect.x + updrect.width > x) { + paint_columns[i] = true; + any = true; + } + x += width; } } - if (paint_columns.empty()) return; + if (!any) return; int w = 0; int h = 0; @@ -284,7 +287,7 @@ void BaseGrid::OnPaint(wxPaintEvent &) { // Draw labels dc.SetPen(*wxTRANSPARENT_PEN); dc.SetBrush(row_colors.LeftCol); - dc.DrawRectangle(0, lineHeight, column_widths[0], h-lineHeight); + dc.DrawRectangle(0, lineHeight, columns[0]->Width(), h-lineHeight); // Row colors wxColour text_standard(to_wx(OPT_GET("Colour/Subtitle Grid/Standard")->GetColor())); @@ -301,7 +304,7 @@ void BaseGrid::OnPaint(wxPaintEvent &) { int left = x + 4; if (columns[col]->Centered()) { wxSize ext = dc.GetTextExtent(str); - left += (column_widths[col] - 6 - ext.GetWidth()) / 2; + left += (columns[col]->Width() - 6 - ext.GetWidth()) / 2; } dc.DrawText(str, left, y + 2); @@ -317,7 +320,7 @@ void BaseGrid::OnPaint(wxPaintEvent &) { for (size_t i : agi::util::range(columns.size())) { if (paint_columns[i]) paint_text(columns[i]->Header(), x, 0, i); - x += column_widths[i]; + x += columns[i]->Width(); } dc.SetPen(grid_pen); @@ -325,10 +328,11 @@ void BaseGrid::OnPaint(wxPaintEvent &) { } // Paint the rows - int drawPerScreen = h/lineHeight + 1; - int nDraw = mid(0, drawPerScreen, GetRows() - yPos); + const int drawPerScreen = h/lineHeight + 1; + const int nDraw = mid(0, drawPerScreen, GetRows() - yPos); + const int grid_x = columns[0]->Width(); - auto active_line = context->selectionController->GetActiveLine(); + const auto active_line = context->selectionController->GetActiveLine(); auto const& selection = context->selectionController->GetSelectedSet(); for (int i : agi::util::range(nDraw)) { @@ -345,6 +349,13 @@ void BaseGrid::OnPaint(wxPaintEvent &) { else if (OPT_GET("Subtitle/Grid/Highlight Subtitles in Frame")->GetBool() && IsDisplayed(curDiag)) color = row_colors.Visible; + // Draw row background color + if (color != row_colors.Default) { + dc.SetPen(*wxTRANSPARENT_PEN); + dc.SetBrush(color); + dc.DrawRectangle(grid_x, (i + 1) * lineHeight + 1, w, lineHeight); + } + if (active_line != curDiag && curDiag->CollidesWith(active_line)) dc.SetTextForeground(text_collision); else if (inSel) @@ -352,22 +363,13 @@ void BaseGrid::OnPaint(wxPaintEvent &) { else dc.SetTextForeground(text_standard); - // Draw row background color - if (color != row_colors.Default) { - dc.SetPen(*wxTRANSPARENT_PEN); - dc.SetBrush(color); - dc.DrawRectangle(column_widths[0], (i + 1) * lineHeight + 1, w, lineHeight); - } - // Draw text int x = 0; int y = (i + 1) * lineHeight; for (size_t j : agi::util::range(columns.size())) { - if (column_widths[j] == 0) continue; - if (paint_columns[j]) - paint_text(columns[j]->Value(curDiag, context), x, y, j); - x += column_widths[j]; + columns[j]->Paint(dc, x + 4, y + 2, curDiag, context); + x += columns[j]->Width(); } // Draw grid @@ -381,14 +383,15 @@ void BaseGrid::OnPaint(wxPaintEvent &) { int maxH = (nDraw + 1) * lineHeight; int x = 0; dc.SetPen(grid_pen); - for (int width : column_widths) { - x += width; + for (auto const& column : columns) { + x += column->Width(); if (x < w) dc.DrawLine(x, 0, x, maxH); } dc.DrawLine(0, 0, 0, maxH); - dc.DrawLine(w - 1, 0, w - 1, maxH); + dc.DrawLine(w, 0, w, maxH); } + if (active_line && active_line->Row >= yPos && active_line->Row < yPos + nDraw) { dc.SetPen(wxPen(to_wx(OPT_GET("Colour/Subtitle Grid/Active Border")->GetColor()))); dc.SetBrush(*wxTRANSPARENT_BRUSH); @@ -531,7 +534,7 @@ void BaseGrid::OnContextMenu(wxContextMenuEvent &evt) { wxMenu menu; for (size_t i : agi::util::range(columns.size())) { if (columns[i]->CanHide()) - menu.Append(MENU_SHOW_COL + i, columns[i]->Description(), "", wxITEM_CHECK)->Check(!!column_shown[i]); + menu.Append(MENU_SHOW_COL + i, columns[i]->Description(), "", wxITEM_CHECK)->Check(columns[i]->Visible()); } PopupMenu(&menu); } @@ -579,25 +582,15 @@ void BaseGrid::SetColumnWidths() { wxClientDC dc(this); dc.SetFont(font); - WidthHelper helper{dc, std::unordered_map, int>{}}; - - column_widths.clear(); - for (auto i : agi::util::range(columns.size())) { - if (!column_shown[i]) - column_widths.push_back(0); - else { - int width = columns[i]->Width(context, helper); - if (width) // 10 is an arbitrary amount of padding - width = 10 + std::max(width, column_header_widths[i]); - column_widths.push_back(width); - } - } - text_refresh_rects.clear(); int x = 0; - for (auto i : agi::util::range(columns.size())) { - if (columns[i]->RefreshOnTextChange() && column_widths[i]) - text_refresh_rects.emplace_back(x, 0, column_widths[i], h); + + WidthHelper helper{dc, std::unordered_map, int>{}}; + for (auto const& column : columns) { + column->UpdateWidth(context, helper); + if (column->Width() && column->RefreshOnTextChange()) + text_refresh_rects.emplace_back(x, 0, column->Width(), h); + x += column->Width(); } } diff --git a/src/base_grid.h b/src/base_grid.h index f6b09c746..7c254fcbb 100644 --- a/src/base_grid.h +++ b/src/base_grid.h @@ -39,7 +39,7 @@ namespace agi { class OptionValue; } class AssDialogue; -struct GridColumn; +class GridColumn; class BaseGrid final : public wxWindow { std::vector connections; @@ -59,9 +59,7 @@ class BaseGrid final : public wxWindow { agi::Context *context; ///< Associated project context std::vector> columns; - std::vector column_widths; - std::vector column_header_widths; - std::vector column_shown; + std::vector columns_visible; std::vector text_refresh_rects; diff --git a/src/grid_column.cpp b/src/grid_column.cpp index 0b50f728d..f7e9f32c0 100644 --- a/src/grid_column.cpp +++ b/src/grid_column.cpp @@ -44,6 +44,24 @@ int WidthHelper::operator()(wxString const& str) { return dc.GetTextExtent(str).GetWidth(); } +void GridColumn::UpdateWidth(const agi::Context *c, WidthHelper &helper) { + if (!visible) { + width = 0; + return; + } + + width = Width(c, helper); + if (width) // 10 is an arbitrary amount of padding + width = 10 + std::max(width, helper(Header())); +} + +void GridColumn::Paint(wxDC &dc, int x, int y, const AssDialogue *d, const agi::Context *c) const { + wxString str = Value(d, c); + if (Centered()) + x += (width - 6 - dc.GetTextExtent(str).GetWidth()) / 2; + dc.DrawText(str, x, y); +} + namespace { #define COLUMN_HEADER(value) \ private: const wxString header = value; \ @@ -233,7 +251,6 @@ public: bool RefreshOnTextChange() const override { return true; } wxString Value(const AssDialogue *d, const agi::Context *) const override { - int duration = d->End - d->Start; auto const& text = d->Text.get(); @@ -255,18 +272,15 @@ public: }; class GridColumnText final : public GridColumn { - int override_mode; + const agi::OptionValue *override_mode; wxString replace_char; - agi::signal::Connection override_mode_connection; agi::signal::Connection replace_char_connection; public: GridColumnText() - : override_mode(OPT_GET("Subtitle/Grid/Hide Overrides")->GetInt()) + : override_mode(OPT_GET("Subtitle/Grid/Hide Overrides")) , replace_char(to_wx(OPT_GET("Subtitle/Grid/Hide Overrides Char")->GetString())) - , override_mode_connection(OPT_SUB("Subtitle/Grid/Hide Overrides", - [&](agi::OptionValue const& v) { override_mode = v.GetInt(); })) , replace_char_connection(OPT_SUB("Subtitle/Grid/Hide Overrides Char", [&](agi::OptionValue const& v) { replace_char = to_wx(v.GetString()); })) { @@ -280,23 +294,25 @@ public: wxString Value(const AssDialogue *d, const agi::Context *) const override { wxString str; + int mode = override_mode->GetInt(); // Show overrides - if (override_mode == 0) + if (mode == 0) str = to_wx(d->Text); // Hidden overrides else { - str.reserve(d->Text.get().size()); + auto const& text = d->Text.get(); + str.reserve(text.size()); size_t start = 0, pos; - while ((pos = d->Text.get().find('{', start)) != std::string::npos) { - str += to_wx(d->Text.get().substr(start, pos - start)); - if (override_mode == 1) + while ((pos = text.find('{', start)) != std::string::npos) { + str += to_wx(text.substr(start, pos - start)); + if (mode == 1) str += replace_char; - start = d->Text.get().find('}', pos); + start = text.find('}', pos); if (start != std::string::npos) ++start; } if (start != std::string::npos) - str += to_wx(d->Text.get().substr(start)); + str += to_wx(text.substr(start)); } // Cap length and set text diff --git a/src/grid_column.h b/src/grid_column.h index c2612a3a4..7cd47419b 100644 --- a/src/grid_column.h +++ b/src/grid_column.h @@ -43,20 +43,31 @@ struct WidthHelper { int operator()(wxString const& str); }; -struct GridColumn { +class GridColumn { +protected: + int width = 0; + bool visible = true; + + virtual int Width(const agi::Context *c, WidthHelper &helper) const = 0; + virtual wxString Value(const AssDialogue *d, const agi::Context *c) const = 0; + +public: virtual ~GridColumn() = default; - virtual bool Centered() const = 0; + virtual bool Centered() const { return false; } virtual bool CanHide() const { return true; } virtual bool RefreshOnTextChange() const { return false; } virtual wxString const& Header() const = 0; virtual wxString const& Description() const = 0; + virtual void Paint(wxDC &dc, int x, int y, const AssDialogue *d, const agi::Context *c) const; - virtual wxString Value(const AssDialogue *d, const agi::Context * = nullptr) const = 0; - virtual int Width(const agi::Context *c, WidthHelper &helper) const = 0; + int Width() const { return width; } + bool Visible() const { return visible; } + virtual void UpdateWidth(const agi::Context *c, WidthHelper &helper); virtual void SetByFrame(bool /* by_frame */) { } + void SetVisible(bool new_value) { visible = new_value; } }; std::vector> GetGridColumns(); \ No newline at end of file