summaryrefslogtreecommitdiff
path: root/wx+/grid.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'wx+/grid.cpp')
-rw-r--r--wx+/grid.cpp124
1 files changed, 64 insertions, 60 deletions
diff --git a/wx+/grid.cpp b/wx+/grid.cpp
index f80c9c73..9d896dc2 100644
--- a/wx+/grid.cpp
+++ b/wx+/grid.cpp
@@ -88,7 +88,7 @@ void GridData::renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType c
rectTmp.x += COLUMN_GAP_LEFT;
rectTmp.width -= COLUMN_GAP_LEFT;
- drawCellText(dc, rectTmp, getValue(row, colType), true);
+ drawCellText(dc, rectTmp, getValue(row, colType));
}
@@ -122,65 +122,71 @@ void GridData::drawCellBackground(wxDC& dc, const wxRect& rect, bool enabled, bo
}
-namespace
-{
-const wchar_t ELLIPSIS = L'\u2026'; //...
-
-template <class Function> inline
-std::wstring getTruncatedText(const std::wstring& text, Function textFits)
+void GridData::drawCellText(wxDC& dc, const wxRect& rect, const std::wstring& text, int alignment)
{
- if (textFits(text))
- return text;
-
- //unlike Windows 7 Explorer, we truncate UTF-16 correctly: e.g. CJK-Ideogramm encodes to TWO wchar_t: utfCvrtTo<std::wstring>("\xf0\xa4\xbd\x9c");
- size_t low = 0; //number of unicode chars!
- size_t high = unicodeLength(text); //
-
- for (;;)
- {
- const size_t middle = (low + high) / 2;
+ /*
+ performance notes (Windows):
+ - wxDC::GetTextExtent() is by far the most expensive call (20x more expensive than wxDC::DrawText())
+ - wxDC::DrawLabel() is inefficiently implemented; internally calls: wxDC::GetMultiLineTextExtent(), wxDC::GetTextExtent(), wxDC::DrawText()
+ - wxDC::GetMultiLineTextExtent() calls wxDC::GetTextExtent()
+ - wxDC::DrawText also calls wxDC::GetTextExtent()!!
+ => wxDC::DrawLabel() boils down to 3(!) calls to wxDC::GetTextExtent()!!!
+ - wxDC::DrawLabel results in GetTextExtent() call even for empty strings!!!
+ => skip the wxDC::DrawLabel() cruft and directly call wxDC::DrawText!
+ */
- std::wstring candidate(strBegin(text), findUnicodePos(text, middle));
- candidate += ELLIPSIS;
+ //truncate large texts and add ellipsis
+ assert(!contains(text, L"\n"));
+ const wchar_t ELLIPSIS = L'\u2026'; //"..."
+
+ std::wstring textTrunc = text;
+ wxSize extentTrunc = dc.GetTextExtent(textTrunc);
+ if (extentTrunc.GetWidth() > rect.width)
+ {
+ //unlike Windows 7 Explorer, we truncate UTF-16 correctly: e.g. CJK-Ideogramm encodes to TWO wchar_t: utfCvrtTo<std::wstring>("\xf0\xa4\xbd\x9c");
+ size_t low = 0; //number of unicode chars!
+ size_t high = unicodeLength(text); //
+ if (high > 1)
+ for (;;)
+ {
+ const size_t middle = (low + high) / 2; //=> never 0 when "high - low > 1"
+ if (high - low <= 1)
+ {
+ if (low == 0)
+ {
+ textTrunc = ELLIPSIS;
+ extentTrunc = dc.GetTextExtent(ELLIPSIS);
+ }
+ break;
+ }
- if (high - low <= 1)
- return candidate;
+ const std::wstring& candidate = std::wstring(strBegin(text), findUnicodePos(text, middle)) + ELLIPSIS;
+ const wxSize extentCand = dc.GetTextExtent(candidate); //perf: most expensive call of this routine!
- if (textFits(candidate))
- low = middle;
- else
- high = middle;
+ if (extentCand.GetWidth() <= rect.width)
+ {
+ low = middle;
+ textTrunc = candidate;
+ extentTrunc = extentCand;
+ }
+ else
+ high = middle;
+ }
}
-}
-
-
-void drawTextLabelFitting(wxDC& dc, const std::wstring& text, const wxRect& rect, int alignment)
-{
- RecursiveDcClipper clip(dc, rect); //wxDC::DrawLabel doesn't care about width, WTF?
-
- /*
- performance notes:
- wxDC::DrawLabel() is implemented in terms of both wxDC::GetMultiLineTextExtent() and wxDC::DrawText()
- wxDC::GetMultiLineTextExtent() is implemented in terms of wxDC::GetTextExtent()
-
- average total times:
- Windows Linux
- single wxDC::DrawText() 7µs 50µs
- wxDC::DrawLabel() + 10µs 90µs
- repeated GetTextExtent()
- */
- //truncate large texts and add ellipsis
- auto textFits = [&](const std::wstring& phrase) { return dc.GetTextExtent(phrase).GetWidth() <= rect.GetWidth(); };
- dc.DrawLabel(getTruncatedText(text, textFits), rect, alignment);
-}
-}
+ wxPoint pt = rect.GetTopLeft();
+ if (alignment & wxALIGN_RIGHT) //note: wxALIGN_LEFT == 0!
+ pt.x += rect.width - extentTrunc.GetWidth();
+ else if (alignment & wxALIGN_CENTER_HORIZONTAL)
+ pt.x += (rect.width - extentTrunc.GetWidth()) / 2;
+ if (alignment & wxALIGN_BOTTOM) //note: wxALIGN_TOP == 0!
+ pt.y += rect.height - extentTrunc.GetHeight();
+ else if (alignment & wxALIGN_CENTER_VERTICAL)
+ pt.y += (rect.height - extentTrunc.GetHeight()) / 2;
-void GridData::drawCellText(wxDC& dc, const wxRect& rect, const std::wstring& text, bool enabled, int alignment)
-{
- wxDCTextColourChanger dummy(dc, enabled ? dc.GetTextForeground() : wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT));
- drawTextLabelFitting(dc, text, rect, alignment);
+ RecursiveDcClipper clip(dc, rect);
+ dc.DrawText(textTrunc, pt);
}
@@ -226,7 +232,7 @@ void GridData::drawColumnLabelBackground(wxDC& dc, const wxRect& rect, bool high
void GridData::drawColumnLabelText(wxDC& dc, const wxRect& rect, const std::wstring& text)
{
wxDCTextColourChanger dummy(dc, getColorLabelText()); //accessibility: always set both foreground AND background colors!
- drawTextLabelFitting(dc, text, rect, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
+ drawCellText(dc, rect, text, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL);
}
//----------------------------------------------------------------------------------------------------------------
@@ -524,10 +530,8 @@ private:
//label text
wxRect textRect = rect;
textRect.Deflate(1);
- {
- RecursiveDcClipper clip(dc, textRect); //wxDC::DrawLabel doesn't care about with, WTF?
- dc.DrawLabel(formatRow(row), textRect, wxALIGN_CENTRE);
- }
+
+ GridData::drawCellText(dc, textRect, formatRow(row), wxALIGN_CENTRE);
//border lines
{
@@ -1668,7 +1672,7 @@ void Grid::scrollDelta(int deltaX, int deltaY)
scrollPosX = std::max(0, scrollPosX); //wxScrollHelper::Scroll() will exit prematurely if input happens to be "-1"!
scrollPosY = std::max(0, scrollPosY); //
- Scroll(scrollPosX, scrollPosY);
+ Scroll(scrollPosX, scrollPosY); //internally calls wxWindows::Update()!
updateWindowSizes(); //may show horizontal scroll bar
}
@@ -2014,7 +2018,7 @@ void Grid::makeRowVisible(size_t row)
if (clientPosY < 0)
{
const int scrollPosY = labelRect.y / pixelsPerUnitY;
- Scroll(scrollPosX, scrollPosY);
+ Scroll(scrollPosX, scrollPosY); //internally calls wxWindows::Update()!
updateWindowSizes(); //may show horizontal scroll bar
}
else if (clientPosY + labelRect.height > rowLabelWin_->GetClientSize().GetHeight())
@@ -2076,7 +2080,7 @@ void Grid::scrollTo(size_t row)
if (scrollPosYOld != scrollPosYNew) //support polling
{
- Scroll(scrollPosXOld, scrollPosYNew);
+ Scroll(scrollPosXOld, scrollPosYNew); //internally calls wxWindows::Update()!
updateWindowSizes(); //may show horizontal scroll bar
Refresh();
}
bgstack15