summaryrefslogtreecommitdiff
path: root/wx+/grid.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'wx+/grid.cpp')
-rw-r--r--wx+/grid.cpp179
1 files changed, 104 insertions, 75 deletions
diff --git a/wx+/grid.cpp b/wx+/grid.cpp
index 80c9aaf1..6eb25ac9 100644
--- a/wx+/grid.cpp
+++ b/wx+/grid.cpp
@@ -99,14 +99,13 @@ wxDEFINE_EVENT(EVENT_GRID_CONTEXT_MENU, GridContextMenuEvent);
}
//----------------------------------------------------------------------------------------------------------------
-void GridData::renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected)
+void GridData::renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected, HoverArea rowHover)
{
if (enabled)
{
if (selected)
dc.GradientFillLinear(rect, getColorSelectionGradientFrom(), getColorSelectionGradientTo(), wxEAST);
- else
- clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
+ //else: clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); -> already the default
}
else
clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
@@ -384,6 +383,9 @@ private:
else
parent_.HandleOnMouseWheel(event);
+ onMouseMovement(event);
+ event.Skip(false);
+
//if (!sendEventToParent(event))
// event.Skip();
}
@@ -462,7 +464,7 @@ public:
int bestWidth = 0;
for (ptrdiff_t i = rowFrom; i <= rowTo; ++i)
- bestWidth = std::max(bestWidth, dc.GetTextExtent(formatRow(i)).GetWidth() + fastFromDIP(2 * ROW_LABEL_BORDER_DIP));
+ bestWidth = std::max(bestWidth, dc.GetTextExtent(formatRowNum(i)).GetWidth() + fastFromDIP(2 * ROW_LABEL_BORDER_DIP));
return bestWidth;
}
@@ -500,7 +502,7 @@ public:
}
private:
- static std::wstring formatRow(size_t row) { return formatNumber(row + 1); } //convert number to std::wstring including thousands separator
+ static std::wstring formatRowNum(size_t row) { return formatNumber(row + 1); } //convert number to std::wstring including thousands separator
bool AcceptsFocus() const override { return false; }
@@ -533,7 +535,7 @@ private:
wxRect textRect = rect;
textRect.Deflate(fastFromDIP(1));
- GridData::drawCellText(dc, textRect, formatRow(row), wxALIGN_CENTRE);
+ GridData::drawCellText(dc, textRect, formatRowNum(row), wxALIGN_CENTRE);
//border lines
{
@@ -733,8 +735,9 @@ private:
}
else //notify single label click
{
+ const wxPoint mousePos = GetPosition() + event.GetPosition();
if (const std::optional<ColumnType> colType = refParent().colToType(activeClickOrMove_->getColumnFrom()))
- sendEventToParent(GridLabelClickEvent(EVENT_GRID_COL_LABEL_MOUSE_LEFT, *colType));
+ sendEventToParent(GridLabelClickEvent(EVENT_GRID_COL_LABEL_MOUSE_LEFT, *colType, mousePos));
}
activeClickOrMove_.reset();
}
@@ -840,16 +843,18 @@ private:
void onMouseRightDown(wxMouseEvent& event) override
{
+ const wxPoint mousePos = GetPosition() + event.GetPosition();
+
if (const std::optional<ColAction> action = refParent().clientPosToColumnAction(event.GetPosition()))
{
if (const std::optional<ColumnType> colType = refParent().colToType(action->col))
- sendEventToParent(GridLabelClickEvent(EVENT_GRID_COL_LABEL_MOUSE_RIGHT, *colType)); //notify right click
+ sendEventToParent(GridLabelClickEvent(EVENT_GRID_COL_LABEL_MOUSE_RIGHT, *colType, mousePos)); //notify right click
else assert(false);
}
else
//notify right click (on free space after last column)
if (fillGapAfterColumns)
- sendEventToParent(GridLabelClickEvent(EVENT_GRID_COL_LABEL_MOUSE_RIGHT, ColumnType::none));
+ sendEventToParent(GridLabelClickEvent(EVENT_GRID_COL_LABEL_MOUSE_RIGHT, ColumnType::none, mousePos));
event.Skip();
}
@@ -894,14 +899,16 @@ private:
void render(wxDC& dc, const wxRect& rect) override
{
const bool enabled = renderAsEnabled(*this);
- clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
+ clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)); //CONTRACT! expected by GridData::renderRowBackgound()!
- dc.SetFont(GetFont()); //harmonize with Grid::getBestColumnSize()
+ if (auto prov = refParent().getDataProvider())
+ {
+ dc.SetFont(GetFont()); //harmonize with Grid::getBestColumnSize()
- wxDCTextColourChanger textColor(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); //use user setting for labels
+ wxDCTextColourChanger textColor(dc, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); //use user setting for labels
+
+ std::vector<ColumnWidth> absWidths = refParent().getColWidths(); //resolve stretched widths
- std::vector<ColumnWidth> absWidths = refParent().getColWidths(); //resolve stretched widths
- {
int totalRowWidth = 0;
for (const ColumnWidth& cw : absWidths)
totalRowWidth += cw.width;
@@ -910,36 +917,37 @@ private:
if (fillGapAfterColumns)
totalRowWidth = std::max(totalRowWidth, GetClientSize().GetWidth());
- if (auto prov = refParent().getDataProvider())
- {
- RecursiveDcClipper dummy2(dc, rect); //do NOT draw background on cells outside of invalidated rect invalidating foreground text!
+ RecursiveDcClipper dummy(dc, rect); //do NOT draw background on cells outside of invalidated rect invalidating foreground text!
- wxPoint cellAreaTL(refParent().CalcScrolledPosition(wxPoint(0, 0))); //client coordinates
- const int rowHeight = rowLabelWin_.getRowHeight();
- const auto rowRange = rowLabelWin_.getRowsOnClient(rect); //returns range [begin, end)
+ const wxPoint gridAreaTL(refParent().CalcScrolledPosition(wxPoint(0, 0))); //client coordinates
+ const int rowHeight = rowLabelWin_.getRowHeight();
+ const auto rowRange = rowLabelWin_.getRowsOnClient(rect); //returns range [begin, end)
+ for (auto row = rowRange.first; row < rowRange.second; ++row)
+ {
//draw background lines
- for (auto row = rowRange.first; row < rowRange.second; ++row)
- {
- const wxRect rowRect(cellAreaTL + wxPoint(0, row * rowHeight), wxSize(totalRowWidth, rowHeight));
- RecursiveDcClipper dummy3(dc, rowRect);
- prov->renderRowBackgound(dc, rowRect, row, enabled, drawAsSelected(row));
- }
+ const wxRect rowRect(gridAreaTL + wxPoint(0, row * rowHeight), wxSize(totalRowWidth, rowHeight));
+ const bool drawSelected = drawAsSelected(row);
+ const HoverArea rowHover = getRowHoverToDraw(row);
- //draw single cells, column by column
+ RecursiveDcClipper dummy2(dc, rowRect);
+ prov->renderRowBackgound(dc, rowRect, row, enabled, drawSelected, rowHover);
+
+ //draw cells column by column
+ wxRect cellRect = rowRect;
for (const ColumnWidth& cw : absWidths)
{
- if (cellAreaTL.x > rect.GetRight())
- return; //done
-
- if (cellAreaTL.x + cw.width > rect.x)
- for (auto row = rowRange.first; row < rowRange.second; ++row)
- {
- const wxRect cellRect(cellAreaTL.x, cellAreaTL.y + row * rowHeight, cw.width, rowHeight);
- RecursiveDcClipper dummy3(dc, cellRect);
- prov->renderCell(dc, cellRect, row, cw.type, enabled, drawAsSelected(row), getRowHoverToDraw(row));
- }
- cellAreaTL.x += cw.width;
+ cellRect.width = cw.width;
+
+ if (cellRect.x > rect.GetRight())
+ break; //done
+
+ if (cellRect.x + cw.width > rect.x)
+ {
+ RecursiveDcClipper dummy3(dc, cellRect);
+ prov->renderCell(dc, cellRect, row, cw.type, enabled, drawSelected, rowHover);
+ }
+ cellRect.x += cw.width;
}
}
}
@@ -979,15 +987,21 @@ private:
{
if (auto prov = refParent().getDataProvider())
{
- wxClientDC dc(this);
- dc.SetFont(GetFont());
-
+ const wxPoint mousePos = GetPosition() + event.GetPosition();
const ptrdiff_t rowCount = refParent().getRowCount();
const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition());
const ptrdiff_t row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
const ColumnPosInfo cpi = refParent().getColumnAtPos(absPos.x); //returns ColumnType::none if no column at x position!
- const HoverArea rowHover = 0 <= row && row < rowCount ? prov->getRowMouseHover(dc, row, cpi.colType, cpi.cellRelativePosX, cpi.colWidth) : HoverArea::none;
- const wxPoint mousePos = GetPosition() + event.GetPosition();
+ const HoverArea rowHover = [&]
+ {
+ if (0 <= row && row < rowCount && cpi.colType != ColumnType::none)
+ {
+ wxClientDC dc(this);
+ dc.SetFont(GetFont());
+ return prov->getMouseHover(dc, row, cpi.colType, cpi.cellRelativePosX, cpi.colWidth);
+ }
+ return HoverArea::none;
+ }();
//client is interested in all double-clicks, even those outside of the grid!
sendEventToParent(GridClickEvent(EVENT_GRID_MOUSE_LEFT_DOUBLE, row, rowHover, mousePos));
@@ -999,17 +1013,23 @@ private:
{
if (auto prov = refParent().getDataProvider())
{
- onMouseMovement(event); //update highlight in obscure cases (e.g. right-click while context menu is open)
-
- wxClientDC dc(this);
- dc.SetFont(GetFont());
+ onMouseMovement(event); //update highlight in obscure cases (e.g. right-click while context menu is open)
- const ptrdiff_t rowCount = refParent().getRowCount();
- const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition());
- const ptrdiff_t row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
- const ColumnPosInfo cpi = refParent().getColumnAtPos(absPos.x); //returns ColumnType::none if no column at x position!
- const HoverArea rowHover = 0 <= row && row < rowCount ? prov->getRowMouseHover(dc, row, cpi.colType, cpi.cellRelativePosX, cpi.colWidth) : HoverArea::none;
const wxPoint mousePos = GetPosition() + event.GetPosition();
+ const ptrdiff_t rowCount = refParent().getRowCount();
+ const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition());
+ const ptrdiff_t row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
+ const ColumnPosInfo cpi = refParent().getColumnAtPos(absPos.x); //returns ColumnType::none if no column at x position!
+ const HoverArea rowHover = [&]
+ {
+ if (0 <= row && row < rowCount && cpi.colType != ColumnType::none)
+ {
+ wxClientDC dc(this);
+ dc.SetFont(GetFont());
+ return prov->getMouseHover(dc, row, cpi.colType, cpi.cellRelativePosX, cpi.colWidth);
+ }
+ return HoverArea::none;
+ }();
assert(row >= 0);
//row < 0 was possible in older wxWidgets: https://github.com/wxWidgets/wxWidgets/commit/2c69d27c0d225d3a331c773da466686153185320#diff-9f11c8f2cb1f734f7c0c1071aba491a5
@@ -1050,7 +1070,7 @@ private:
//update mouse highlight (in case it was frozen above)
event.SetPosition(ScreenToClient(wxGetMousePosition())); //mouse position may have changed within above callbacks (e.g. context menu was shown)!
- onMouseMovement(event);
+ onMouseMovement(event);
}
event.Skip(); //allow changing focus
}
@@ -1077,9 +1097,9 @@ private:
}
//slight deviation from Explorer: change cursor while dragging mouse! -> unify behavior with shift + direction keys
- const ptrdiff_t rowFrom = activeSelection_->getStartRow();
- const ptrdiff_t rowTo = activeSelection_->getCurrentRow();
- const bool positive = activeSelection_->isPositiveSelect();
+ const ptrdiff_t rowFrom = activeSelection_->getStartRow();
+ const ptrdiff_t rowTo = activeSelection_->getCurrentRow();
+ const bool positive = activeSelection_->isPositiveSelect();
const GridClickEvent mouseClick = activeSelection_->getFirstClick();
assert((mouseClick.GetEventType() == EVENT_GRID_MOUSE_RIGHT_DOWN) == event.RightUp());
@@ -1090,29 +1110,34 @@ private:
if (mouseClick.GetEventType() == EVENT_GRID_MOUSE_RIGHT_DOWN)
sendEventToParent(GridContextMenuEvent(mouseClick.mousePos_));
}
-
#if 0
if (!event.RightUp())
if (auto prov = refParent().getDataProvider())
{
- wxClientDC dc(this);
- dc.SetFont(GetFont());
-
//this one may point to row which is not in visible area!
- const ptrdiff_t rowCount = refParent().getRowCount();
- const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition());
- const ptrdiff_t row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
- const ColumnPosInfo cpi = refParent().getColumnAtPos(absPos.x); //returns ColumnType::none if no column at x position!
- const HoverArea rowHover = 0 <= row && row < rowCount ? prov->getRowMouseHover(dc, row, cpi.colType, cpi.cellRelativePosX, cpi.colWidth) : HoverArea::none;
const wxPoint mousePos = GetPosition() + event.GetPosition();
+ const ptrdiff_t rowCount = refParent().getRowCount();
+ const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition());
+ const ptrdiff_t row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
+ const ColumnPosInfo cpi = refParent().getColumnAtPos(absPos.x); //returns ColumnType::none if no column at x position!
+ const HoverArea rowHover = [&]
+ {
+ if (0 <= row && row < rowCount && cpi.colType != ColumnType::none)
+ {
+ wxClientDC dc(this);
+ dc.SetFont(GetFont());
+ return prov->getMouseHover(dc, row, cpi.colType, cpi.cellRelativePosX, cpi.colWidth);
+ }
+ return HoverArea::none;
+ }();
//notify click event after the range selection! e.g. this makes sure the selection is applied before showing a context menu
sendEventToParent(GridClickEvent(EVENT_GRID_MOUSE_LEFT_UP, row, rowHover, mousePos));
}
#endif
-
+
//update mouse highlight and tooltip: macOS no mouse movement event is generated after a mouse button click (unlike on Windows)
event.SetPosition(ScreenToClient(wxGetMousePosition())); //mouse position may have changed within above callbacks (e.g. context menu was shown)!
- onMouseMovement(event);
+ onMouseMovement(event);
event.Skip(); //allow changing focus
}
@@ -1135,18 +1160,25 @@ private:
{
if (auto prov = refParent().getDataProvider())
{
- wxClientDC dc(this);
- dc.SetFont(GetFont());
-
const ptrdiff_t rowCount = refParent().getRowCount();
const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition());
const ptrdiff_t row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
const ColumnPosInfo cpi = refParent().getColumnAtPos(absPos.x); //returns ColumnType::none if no column at x position!
+ const HoverArea rowHover = [&]
+ {
+ if (0 <= row && row < rowCount && cpi.colType != ColumnType::none)
+ {
+ wxClientDC dc(this);
+ dc.SetFont(GetFont());
+ return prov->getMouseHover(dc, row, cpi.colType, cpi.cellRelativePosX, cpi.colWidth);
+ }
+ return HoverArea::none;
+ }();
const std::wstring toolTip = [&]
{
- if (cpi.colType != ColumnType::none && 0 <= row && row < rowCount)
- return prov->getToolTip(row, cpi.colType);
+ if (0 <= row && row < rowCount && cpi.colType != ColumnType::none)
+ return prov->getToolTip(row, cpi.colType, rowHover);
return std::wstring();
}();
setToolTip(toolTip); //show even during mouse selection!
@@ -1154,10 +1186,7 @@ private:
if (activeSelection_)
activeSelection_->evalMousePos(); //call on both mouse movement + timer event!
else
- {
- const HoverArea rowHover = 0 <= row && row < rowCount ? prov->getRowMouseHover(dc, row, cpi.colType, cpi.cellRelativePosX, cpi.colWidth) : HoverArea::none;
updateMouseHover({row, rowHover});
- }
}
event.Skip();
}
bgstack15