summaryrefslogtreecommitdiff
path: root/wx+
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:29:28 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:29:28 +0200
commit75c07011b7c4d06acd7b45dabdcd60ab9d80f385 (patch)
tree8853c3978dd152ef377e652239448b1352320206 /wx+
parent5.22 (diff)
downloadFreeFileSync-75c07011b7c4d06acd7b45dabdcd60ab9d80f385.tar.gz
FreeFileSync-75c07011b7c4d06acd7b45dabdcd60ab9d80f385.tar.bz2
FreeFileSync-75c07011b7c4d06acd7b45dabdcd60ab9d80f385.zip
5.23
Diffstat (limited to 'wx+')
-rw-r--r--wx+/font_size.h2
-rw-r--r--wx+/graph.cpp10
-rw-r--r--wx+/grid.cpp767
-rw-r--r--wx+/grid.h137
-rw-r--r--wx+/popup_dlg.cpp8
-rw-r--r--wx+/popup_dlg_generated.cpp146
-rw-r--r--wx+/popup_dlg_generated.h56
7 files changed, 482 insertions, 644 deletions
diff --git a/wx+/font_size.h b/wx+/font_size.h
index 7bfc62fc..4639d194 100644
--- a/wx+/font_size.h
+++ b/wx+/font_size.h
@@ -48,7 +48,7 @@ void setMainInstructionFont(wxWindow& control)
{
wxFont font = control.GetFont();
#ifdef ZEN_WIN //http://msdn.microsoft.com/de-DE/library/windows/desktop/aa974176#fonts
- font.SetPointSize(numeric::round(wxNORMAL_FONT->GetPointSize() * 4.0 / 3));
+ font.SetPointSize(wxNORMAL_FONT->GetPointSize() * 4 / 3); //integer round down
//get main instruction color: don't hard-code, respect accessibility!
typedef HTHEME (WINAPI* OpenThemeDataFun )(HWND hwnd, LPCWSTR pszClassList);
diff --git a/wx+/graph.cpp b/wx+/graph.cpp
index 2f5b3775..9298b10b 100644
--- a/wx+/graph.cpp
+++ b/wx+/graph.cpp
@@ -721,13 +721,13 @@ void Graph2D::render(wxDC& dc) const
*low = *high = (*low + *high) / 2;
};
- for (auto it = allSelections.begin(); it != allSelections.end(); ++it)
+ for (const SelectionBlock& sel : allSelections)
{
//harmonize with active mouse selection above
- double screenFromX = cvrtX.realToScreen(it->from.x);
- double screenFromY = cvrtY.realToScreen(it->from.y);
- double screenToX = cvrtX.realToScreen(it->to.x);
- double screenToY = cvrtY.realToScreen(it->to.y);
+ double screenFromX = cvrtX.realToScreen(sel.from.x);
+ double screenFromY = cvrtY.realToScreen(sel.from.y);
+ double screenToX = cvrtX.realToScreen(sel.to.x);
+ double screenToY = cvrtY.realToScreen(sel.to.y);
shrink(&screenFromX, &screenToX);
shrink(&screenFromY, &screenToY);
diff --git a/wx+/grid.cpp b/wx+/grid.cpp
index 184302bf..87f81dda 100644
--- a/wx+/grid.cpp
+++ b/wx+/grid.cpp
@@ -297,6 +297,7 @@ protected:
SetToolTip(new wxToolTip(L"a b\n\
a b")); //ugly, but is working (on Windows)
tt = GetToolTip(); //should be bound by now
+ assert(tt);
if (tt)
tt->SetTip(text);
}
@@ -542,8 +543,8 @@ namespace
class ColumnResizing
{
public:
- ColumnResizing(wxWindow& wnd, size_t col, size_t compPos, int startWidth, int clientPosX) :
- wnd_(wnd), col_(col), compPos_(compPos), startWidth_(startWidth), clientPosX_(clientPosX)
+ ColumnResizing(wxWindow& wnd, size_t col, int startWidth, int clientPosX) :
+ wnd_(wnd), col_(col), startWidth_(startWidth), clientPosX_(clientPosX)
{
wnd_.CaptureMouse();
}
@@ -554,14 +555,12 @@ public:
}
size_t getColumn () const { return col_; }
- size_t getComponentPos() const { return compPos_; }
int getStartWidth () const { return startWidth_; }
int getStartPosX () const { return clientPosX_; }
private:
wxWindow& wnd_;
const size_t col_;
- const size_t compPos_;
const int startWidth_;
const int clientPosX_;
};
@@ -570,10 +569,9 @@ private:
class ColumnMove
{
public:
- ColumnMove(wxWindow& wnd, size_t colFrom, size_t compPos, int clientPosX) :
+ ColumnMove(wxWindow& wnd, size_t colFrom, int clientPosX) :
wnd_(wnd),
colFrom_(colFrom),
- compPos_(compPos),
colTo_(colFrom),
clientPosX_(clientPosX),
singleClick_(true) { wnd_.CaptureMouse(); }
@@ -581,7 +579,6 @@ public:
size_t getColumnFrom() const { return colFrom_; }
size_t& refColumnTo() { return colTo_; }
- size_t getComponentPos() const { return compPos_; }
int getStartPosX () const { return clientPosX_; }
bool isRealMove() const { return !singleClick_; }
@@ -590,7 +587,6 @@ public:
private:
wxWindow& wnd_;
const size_t colFrom_;
- const size_t compPos_;
size_t colTo_;
const int clientPosX_;
bool singleClick_;
@@ -625,36 +621,35 @@ private:
wxPoint labelAreaTL(refParent().CalcScrolledPosition(wxPoint(0, 0)).x, 0); //client coordinates
- std::vector<std::vector<ColumnWidth>> compAbsWidths = refParent().getColWidths(); //resolve stretched widths
- for (auto iterComp = compAbsWidths.begin(); iterComp != compAbsWidths.end(); ++iterComp)
- for (auto iterCol = iterComp->begin(); iterCol != iterComp->end(); ++iterCol)
- {
- const size_t col = iterCol - iterComp->begin();
- const int width = iterCol->width_; //don't use unsigned for calculations!
-
- if (labelAreaTL.x > rect.GetRight())
- return; //done
- if (labelAreaTL.x + width > rect.x)
- drawColumnLabel(dc, wxRect(labelAreaTL, wxSize(width, colLabelHeight)), col, iterCol->type_, iterComp - compAbsWidths.begin());
- labelAreaTL.x += width;
- }
+ std::vector<ColumnWidth> absWidths = refParent().getColWidths(); //resolve stretched widths
+ for (auto it = absWidths.begin(); it != absWidths.end(); ++it)
+ {
+ const size_t col = it - absWidths.begin();
+ const int width = it->width_; //don't use unsigned for calculations!
+
+ if (labelAreaTL.x > rect.GetRight())
+ return; //done
+ if (labelAreaTL.x + width > rect.x)
+ drawColumnLabel(dc, wxRect(labelAreaTL, wxSize(width, colLabelHeight)), col, it->type_);
+ labelAreaTL.x += width;
+ }
}
- void drawColumnLabel(wxDC& dc, const wxRect& rect, size_t col, ColumnType colType, size_t compPos)
+ void drawColumnLabel(wxDC& dc, const wxRect& rect, size_t col, ColumnType colType)
{
- if (auto dataView = refParent().getDataProvider(compPos))
+ if (auto dataView = refParent().getDataProvider())
{
- const bool isHighlighted = activeResizing ? col == activeResizing->getColumn () && compPos == activeResizing->getComponentPos() : //highlight column on mouse-over
- activeMove ? col == activeMove ->getColumnFrom() && compPos == activeMove ->getComponentPos() :
- highlight ? col == highlight->first && compPos == highlight->second :
+ const bool isHighlighted = activeResizing ? col == activeResizing->getColumn () : //highlight column on mouse-over
+ activeMove ? col == activeMove ->getColumnFrom() :
+ highlightCol ? col == *highlightCol :
false;
RecursiveDcClipper clip(dc, rect);
dataView->renderColumnLabel(refParent(), dc, rect, colType, isHighlighted);
//draw move target location
- if (refParent().columnMoveAllowed(compPos))
- if (activeMove && activeMove->isRealMove() && activeMove->getComponentPos() == compPos)
+ if (refParent().allowColumnMove)
+ if (activeMove && activeMove->isRealMove())
{
if (col + 1 == activeMove->refColumnTo()) //handle pos 1, 2, .. up to "at end" position
dc.GradientFillLinear(wxRect(rect.GetTopRight(), rect.GetBottomRight() + wxPoint(-2, 0)), COLOR_LABEL_GRADIENT_FROM, *wxBLUE, wxSOUTH);
@@ -677,11 +672,11 @@ private:
if (action->wantResize)
{
if (!event.LeftDClick()) //double-clicks never seem to arrive here; why is this checked at all???
- if (Opt<int> colWidth = refParent().getColWidth(action->col, action->compPos))
- activeResizing.reset(new ColumnResizing(*this, action->col, action->compPos, *colWidth, event.GetPosition().x));
+ if (Opt<int> colWidth = refParent().getColWidth(action->col))
+ activeResizing.reset(new ColumnResizing(*this, action->col, *colWidth, event.GetPosition().x));
}
else //a move or single click
- activeMove.reset(new ColumnMove(*this, action->col, action->compPos, event.GetPosition().x));
+ activeMove.reset(new ColumnMove(*this, action->col, event.GetPosition().x));
}
event.Skip();
}
@@ -692,10 +687,9 @@ private:
if (activeMove)
{
- const size_t compPos = activeMove->getComponentPos();
if (activeMove->isRealMove())
{
- if (refParent().columnMoveAllowed(compPos))
+ if (refParent().allowColumnMove)
{
const auto colFrom = activeMove->getColumnFrom();
auto colTo = activeMove->refColumnTo();
@@ -703,13 +697,13 @@ private:
if (colTo > colFrom) //simulate "colFrom" deletion
--colTo;
- refParent().moveColumn(colFrom, colTo, compPos);
+ refParent().moveColumn(colFrom, colTo);
}
}
else //notify single label click
{
- if (const Opt<ColumnType> colType = refParent().colToType(activeMove->getColumnFrom(), compPos))
- sendEventNow(GridClickEvent(EVENT_GRID_COL_LABEL_MOUSE_LEFT, event, -1, *colType, compPos));
+ if (const Opt<ColumnType> colType = refParent().colToType(activeMove->getColumnFrom()))
+ sendEventNow(GridClickEvent(EVENT_GRID_COL_LABEL_MOUSE_LEFT, event, -1, *colType));
}
activeMove.reset();
}
@@ -733,10 +727,10 @@ private:
if (action->wantResize)
{
//auto-size visible range on double-click
- const int bestWidth = refParent().getBestColumnSize(action->col, action->compPos); //return -1 on error
+ const int bestWidth = refParent().getBestColumnSize(action->col); //return -1 on error
if (bestWidth >= 0)
{
- refParent().setColWidthAndNotify(bestWidth, action->col, action->compPos);
+ refParent().setColumnWidth(bestWidth, action->col, ALLOW_GRID_EVENT);
refParent().Refresh(); //refresh main grid as well!
}
}
@@ -748,16 +742,15 @@ private:
if (activeResizing)
{
const auto col = activeResizing->getColumn();
- const auto compPos = activeResizing->getComponentPos();
const int newWidth = activeResizing->getStartWidth() + event.GetPosition().x - activeResizing->getStartPosX();
//set width tentatively
- refParent().setColWidthAndNotify(newWidth, col, compPos);
+ refParent().setColumnWidth(newWidth, col, ALLOW_GRID_EVENT);
//check if there's a small gap after last column, if yes, fill it
int gapWidth = GetClientSize().GetWidth() - refParent().getColWidthsSum(GetClientSize().GetWidth());
if (std::abs(gapWidth) < COLUMN_FILL_GAP_TOLERANCE)
- refParent().setColWidthAndNotify(newWidth + gapWidth, col, compPos);
+ refParent().setColumnWidth(newWidth + gapWidth, col, ALLOW_GRID_EVENT);
refParent().Refresh(); //refresh columns on main grid as well!
}
@@ -768,7 +761,7 @@ private:
{
activeMove->setRealMove();
- const auto col = refParent().clientPosToMoveTargetColumn(event.GetPosition(), activeMove->getComponentPos());
+ const ptrdiff_t col = refParent().clientPosToMoveTargetColumn(event.GetPosition());
if (col >= 0)
activeMove->refColumnTo() = col;
}
@@ -777,7 +770,7 @@ private:
{
if (const Opt<ColAction> action = refParent().clientPosToColumnAction(event.GetPosition()))
{
- highlight.reset(new std::pair<size_t, size_t>(action->col, action->compPos));
+ highlightCol.reset(new size_t(action->col));
if (action->wantResize)
SetCursor(wxCURSOR_SIZEWE); //set window-local only! :)
@@ -786,7 +779,7 @@ private:
}
else
{
- highlight.reset();
+ highlightCol.reset();
SetCursor(*wxSTANDARD_CURSOR);
}
}
@@ -795,11 +788,9 @@ private:
const wxString toolTip = [&]() -> wxString
{
const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition());
- if (const auto colInfo = refParent().getColumnAtPos(absPos.x)) //returns (column type, compPos)
- {
- if (auto prov = refParent().getDataProvider(colInfo->second))
- return prov->getToolTip(colInfo->first);
- }
+ if (const Opt<ColumnType> ct = refParent().getColumnAtPos(absPos.x))
+ if (auto prov = refParent().getDataProvider())
+ return prov->getToolTip(*ct);
return wxString();
}();
setToolTip(toolTip);
@@ -810,7 +801,7 @@ private:
virtual void onLeaveWindow(wxMouseEvent& event)
{
- highlight.reset(); //wxEVT_LEAVE_WINDOW does not respect mouse capture! -> however highlight is drawn unconditionally during move/resize!
+ highlightCol.reset(); //wxEVT_LEAVE_WINDOW does not respect mouse capture! -> however highlight is drawn unconditionally during move/resize!
Refresh();
event.Skip();
}
@@ -819,15 +810,15 @@ private:
{
if (const Opt<ColAction> action = refParent().clientPosToColumnAction(event.GetPosition()))
{
- if (const Opt<ColumnType> colType = refParent().colToType(action->col, action->compPos))
- sendEventNow(GridClickEvent(EVENT_GRID_COL_LABEL_MOUSE_RIGHT, event, -1, *colType, action->compPos)); //notify right click
+ if (const Opt<ColumnType> colType = refParent().colToType(action->col))
+ sendEventNow(GridClickEvent(EVENT_GRID_COL_LABEL_MOUSE_RIGHT, event, -1, *colType)); //notify right click
}
event.Skip();
}
std::unique_ptr<ColumnResizing> activeResizing;
std::unique_ptr<ColumnMove> activeMove;
- std::unique_ptr<std::pair<size_t, size_t>> highlight; //(column, component) mouse-over
+ std::unique_ptr<size_t> highlightCol; //column during mouse-over
};
//----------------------------------------------------------------------------------------------------------------
@@ -893,13 +884,13 @@ public:
}
}
- void setCursor(size_t row, size_t compPos)
+ void setCursor(size_t row)
{
- cursor = std::make_pair(row, compPos);
+ cursorRow = row;
activeSelection.reset(); //e.g. user might search with F3 while holding down left mouse button
selectionAnchor = row;
}
- std::pair<size_t, size_t> getCursor() const { return cursor; } // (row, component position)
+ size_t getCursor() const { return cursorRow; }
private:
virtual void render(wxDC& dc, const wxRect& rect)
@@ -924,27 +915,25 @@ private:
wxPoint cellAreaTL(refParent().CalcScrolledPosition(wxPoint(0, 0))); //client coordinates
- std::vector<std::vector<ColumnWidth>> compAbsWidths = refParent().getColWidths(); //resolve stretched widths
- for (auto iterComp = compAbsWidths.begin(); iterComp != compAbsWidths.end(); ++iterComp)
+ std::vector<ColumnWidth> absWidths = refParent().getColWidths(); //resolve stretched widths
{
- int compWidth = 0;
- for (const ColumnWidth& cw : *iterComp)
- compWidth += cw.width_;
+ int totalWidth = 0;
+ for (const ColumnWidth& cw : absWidths)
+ totalWidth += cw.width_;
- const size_t compPos = iterComp - compAbsWidths.begin();
- if (auto prov = refParent().getDataProvider(compPos))
+ if (auto prov = refParent().getDataProvider())
{
//draw background lines
for (int row = rowFirst; row < rowLast; ++row)
{
- const wxRect rowRect(cellAreaTL + wxPoint(0, row * rowHeight), wxSize(compWidth, rowHeight));
+ const wxRect rowRect(cellAreaTL + wxPoint(0, row * rowHeight), wxSize(totalWidth, rowHeight));
RecursiveDcClipper dummy2(dc, rowRect); //solve issues with drawBackground() painting in area outside of rect
//(which is not also refreshed by renderCell()) -> keep small scope!
- prov->renderRowBackgound(dc, rowRect, row, refParent().IsThisEnabled(), drawAsSelected(row, compPos));
+ prov->renderRowBackgound(dc, rowRect, row, refParent().IsThisEnabled(), drawAsSelected(row));
}
//draw single cells, column by column
- for (const ColumnWidth& cw : *iterComp)
+ for (const ColumnWidth& cw : absWidths)
{
if (cellAreaTL.x > rect.GetRight())
return; //done
@@ -955,27 +944,25 @@ private:
const wxRect cellRect(cellAreaTL.x, cellAreaTL.y + row * rowHeight, cw.width_, rowHeight);
RecursiveDcClipper clip(dc, cellRect);
- prov->renderCell(dc, cellRect, row, cw.type_, drawAsSelected(row, compPos));
+ prov->renderCell(dc, cellRect, row, cw.type_, drawAsSelected(row));
}
cellAreaTL.x += cw.width_;
}
}
- else
- cellAreaTL.x += compWidth;
}
}
- bool drawAsSelected(size_t row, size_t compPos) const
+ bool drawAsSelected(size_t row) const
{
if (activeSelection) //check if user is currently selecting with mouse
{
const size_t rowFrom = std::min(activeSelection->getStartRow(), activeSelection->getCurrentRow());
const size_t rowTo = std::max(activeSelection->getStartRow(), activeSelection->getCurrentRow());
- if (compPos == activeSelection->getComponentPos() && rowFrom <= row && row <= rowTo)
+ if (rowFrom <= row && row <= rowTo)
return activeSelection->isPositiveSelect(); //overwrite default
}
- return refParent().isSelected(row, compPos);
+ return refParent().isSelected(row);
}
virtual void onMouseLeftDown (wxMouseEvent& event) { onMouseDown(event); }
@@ -989,12 +976,10 @@ private:
const auto row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
if (row >= 0)
{
- const auto colInfo = refParent().getColumnAtPos(absPos.x); //returns (column type, compPos)
-
- const ColumnType colType = colInfo ? colInfo->first : DUMMY_COLUMN_TYPE;
- const ptrdiff_t compPos = colInfo ? colInfo->second : -1;
+ const Opt<ColumnType> ct = refParent().getColumnAtPos(absPos.x);
+ const ColumnType colType = ct ? *ct : DUMMY_COLUMN_TYPE;
//client is interested in all double-clicks, even those outside of the grid!
- sendEventNow(GridClickEvent(EVENT_GRID_MOUSE_LEFT_DOUBLE, event, row, colType, compPos));
+ sendEventNow(GridClickEvent(EVENT_GRID_MOUSE_LEFT_DOUBLE, event, row, colType));
}
event.Skip();
}
@@ -1008,34 +993,28 @@ private:
const ptrdiff_t row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
if (row >= 0)
{
- const auto colInfo = refParent().getColumnAtPos(absPos.x); //returns (column type, compPos)
- const ColumnType colType = colInfo ? colInfo->first : DUMMY_COLUMN_TYPE;
- const ptrdiff_t compPos = colInfo ? colInfo->second : -1;
+ const Opt<ColumnType> ct = refParent().getColumnAtPos(absPos.x);
+ const ColumnType colType = ct ? *ct : DUMMY_COLUMN_TYPE;
- if (!event.RightDown() || !refParent().isSelected(row, compPos)) //do NOT start a new selection if user right-clicks on a selected area!
+ if (!event.RightDown() || !refParent().isSelected(row)) //do NOT start a new selection if user right-clicks on a selected area!
{
if (event.ControlDown())
- {
- if (compPos >= 0)
- activeSelection.reset(new MouseSelection(*this, row, compPos, !refParent().isSelected(row, compPos)));
- }
+ activeSelection.reset(new MouseSelection(*this, row, !refParent().isSelected(row)));
else if (event.ShiftDown())
{
- if (compPos >= 0)
- activeSelection.reset(new MouseSelection(*this, selectionAnchor, compPos, true));
- refParent().clearSelectionAllAndNotify();
+ activeSelection.reset(new MouseSelection(*this, selectionAnchor, true));
+ refParent().clearSelection(ALLOW_GRID_EVENT);
}
else
{
- if (compPos >= 0)
- activeSelection.reset(new MouseSelection(*this, row, compPos, true));
- refParent().clearSelectionAllAndNotify();
+ activeSelection.reset(new MouseSelection(*this, row, true));
+ refParent().clearSelection(ALLOW_GRID_EVENT);
}
}
- //notify event *after* potential "clearSelectionAllAndNotify()" above: a client should first receive a GridRangeSelectEvent for clearing the grid, if necessary,
+ //notify event *after* potential "clearSelection(true)" above: a client should first receive a GridRangeSelectEvent for clearing the grid, if necessary,
//then GridClickEvent and the associated GridRangeSelectEvent one after the other
- GridClickEvent mouseEvent(event.RightDown() ? EVENT_GRID_MOUSE_RIGHT_DOWN : EVENT_GRID_MOUSE_LEFT_DOWN, event, row, colType, compPos);
+ GridClickEvent mouseEvent(event.RightDown() ? EVENT_GRID_MOUSE_RIGHT_DOWN : EVENT_GRID_MOUSE_LEFT_DOWN, event, row, colType);
sendEventNow(mouseEvent);
Refresh();
@@ -1052,22 +1031,21 @@ private:
{
if (activeSelection->getCurrentRow() < rowCount)
{
- cursor.first = activeSelection->getCurrentRow();
+ cursorRow = activeSelection->getCurrentRow();
selectionAnchor = activeSelection->getStartRow(); //allowed to be "out of range"
}
else if (activeSelection->getStartRow() < rowCount) //don't change cursor if "to" and "from" are out of range
{
- cursor.first = rowCount - 1;
+ cursorRow = rowCount - 1;
selectionAnchor = activeSelection->getStartRow(); //allowed to be "out of range"
}
else //total selection "out of range"
- selectionAnchor = cursor.first;
+ selectionAnchor = cursorRow;
}
//slight deviation from Explorer: change cursor while dragging mouse! -> unify behavior with shift + direction keys
refParent().selectRangeAndNotify(activeSelection->getStartRow (), //from
activeSelection->getCurrentRow(), //to
- activeSelection->getComponentPos(),
activeSelection->isPositiveSelect());
activeSelection.reset();
}
@@ -1075,14 +1053,12 @@ private:
//this one may point to row which is not in visible area!
const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition());
- const auto row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
- const auto colInfo = refParent().getColumnAtPos(absPos.x); //returns optional pair (column type, compPos)
-
- const ColumnType colType = colInfo ? colInfo->first : DUMMY_COLUMN_TYPE; //we probably should notify even if colInfo is invalid!
- const ptrdiff_t compPos = colInfo ? colInfo->second : -1;
+ const ptrdiff_t row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
+ const Opt<ColumnType> ct = refParent().getColumnAtPos(absPos.x);
+ const ColumnType colType = ct ? *ct : DUMMY_COLUMN_TYPE; //we probably should notify even if colInfo is invalid!
//notify click event after the range selection! e.g. this makes sure the selection is applied before showing a context menu
- sendEventNow(GridClickEvent(event.RightUp() ? EVENT_GRID_MOUSE_RIGHT_UP : EVENT_GRID_MOUSE_LEFT_UP, event, row, colType, compPos));
+ sendEventNow(GridClickEvent(event.RightUp() ? EVENT_GRID_MOUSE_RIGHT_UP : EVENT_GRID_MOUSE_LEFT_UP, event, row, colType));
Refresh();
event.Skip(); //allow changing focus
@@ -1106,13 +1082,11 @@ private:
const ptrdiff_t rowCount = refParent().getRowCount();
const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition());
- const auto row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
- const auto colInfo = refParent().getColumnAtPos(absPos.x); //returns (column type, compPos)
- if (colInfo && 0 <= row && row < rowCount)
- {
- if (auto prov = refParent().getDataProvider(colInfo->second))
- return prov->getToolTip(row, colInfo->first);
- }
+ const ptrdiff_t row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
+ const Opt<ColumnType> ct = refParent().getColumnAtPos(absPos.x);
+ if (ct && 0 <= row && row < rowCount)
+ if (auto prov = refParent().getDataProvider())
+ return prov->getToolTip(row, *ct);
return wxString();
}();
@@ -1137,17 +1111,16 @@ private:
}
const ptrdiff_t rowCount = refParent().getRowCount();
- if (rowCount <= 0 || refParent().comp.empty())
+ if (rowCount <= 0)
{
event.Skip();
return;
}
- auto setSingleSelection = [&](ptrdiff_t row, ptrdiff_t compPos)
+ auto setSingleSelection = [&](ptrdiff_t row)
{
- numeric::confine<ptrdiff_t>(row, 0, rowCount - 1);
- numeric::confine<ptrdiff_t>(compPos, 0, refParent().comp.size() - 1);
- refParent().setGridCursor(row, compPos); //behave like an "external" set cursor!
+ numeric::confine<ptrdiff_t>(row, 0, rowCount - 1);
+ refParent().setGridCursor(row); //behave like an "external" set cursor!
};
auto setSelectionRange = [&](ptrdiff_t row)
@@ -1156,11 +1129,10 @@ private:
numeric::confine<ptrdiff_t>(row, 0, rowCount - 1);
- for (Grid::Component& c : refParent().comp)
- c.selection.clear(); //clear selection, do NOT fire event
- refParent().selectRangeAndNotify(selectionAnchor, row, cursor.second); //set new selection + fire event
+ refParent().selection.clear(); //clear selection, do NOT fire event
+ refParent().selectRangeAndNotify(selectionAnchor, row); //set new selection + fire event
- cursor.first = row; //don't call setCursor() since it writes to "selectionAnchor"!
+ cursorRow = row; //don't call setCursor() since it writes to "selectionAnchor"!
this->makeRowVisible(row);
refParent().Refresh();
};
@@ -1170,21 +1142,21 @@ private:
case WXK_UP:
case WXK_NUMPAD_UP:
if (event.ShiftDown())
- setSelectionRange(cursor.first - 1);
+ setSelectionRange(cursorRow - 1);
else if (event.ControlDown())
refParent().scrollDelta(0, -1);
else
- setSingleSelection(cursor.first - 1, cursor.second);
+ setSingleSelection(cursorRow - 1);
return; //swallow event: wxScrolledWindow, wxWidgets 2.9.3 on Kubuntu x64 processes arrow keys: prevent this!
case WXK_DOWN:
case WXK_NUMPAD_DOWN:
if (event.ShiftDown())
- setSelectionRange(cursor.first + 1);
+ setSelectionRange(cursorRow + 1);
else if (event.ControlDown())
refParent().scrollDelta(0, 1);
else
- setSingleSelection(cursor.first + 1, cursor.second);
+ setSingleSelection(cursorRow + 1);
return; //swallow event
case WXK_LEFT:
@@ -1194,7 +1166,7 @@ private:
else if (event.ShiftDown())
;
else
- setSingleSelection(cursor.first, cursor.second - 1);
+ setSingleSelection(cursorRow);
return;
case WXK_RIGHT:
@@ -1204,7 +1176,7 @@ private:
else if (event.ShiftDown())
;
else
- setSingleSelection(cursor.first, cursor.second + 1);
+ setSingleSelection(cursorRow);
return;
case WXK_HOME:
@@ -1212,9 +1184,9 @@ private:
if (event.ShiftDown())
setSelectionRange(0);
else if (event.ControlDown())
- setSingleSelection(0, 0);
+ setSingleSelection(0);
else
- setSingleSelection(0, cursor.second);
+ setSingleSelection(0);
return;
case WXK_END:
@@ -1222,39 +1194,39 @@ private:
if (event.ShiftDown())
setSelectionRange(rowCount - 1);
else if (event.ControlDown())
- setSingleSelection(rowCount - 1, refParent().comp.size() - 1);
+ setSingleSelection(rowCount - 1);
else
- setSingleSelection(rowCount - 1, cursor.second);
+ setSingleSelection(rowCount - 1);
return;
case WXK_PAGEUP:
case WXK_NUMPAD_PAGEUP:
if (event.ShiftDown())
- setSelectionRange(cursor.first - GetClientSize().GetHeight() / rowLabelWin_.getRowHeight());
+ setSelectionRange(cursorRow - GetClientSize().GetHeight() / rowLabelWin_.getRowHeight());
else if (event.ControlDown())
;
else
- setSingleSelection(cursor.first - GetClientSize().GetHeight() / rowLabelWin_.getRowHeight(), cursor.second);
+ setSingleSelection(cursorRow - GetClientSize().GetHeight() / rowLabelWin_.getRowHeight());
return;
case WXK_PAGEDOWN:
case WXK_NUMPAD_PAGEDOWN:
if (event.ShiftDown())
- setSelectionRange(cursor.first + GetClientSize().GetHeight() / rowLabelWin_.getRowHeight());
+ setSelectionRange(cursorRow + GetClientSize().GetHeight() / rowLabelWin_.getRowHeight());
else if (event.ControlDown())
;
else
- setSingleSelection(cursor.first + GetClientSize().GetHeight() / rowLabelWin_.getRowHeight(), cursor.second);
+ setSingleSelection(cursorRow + GetClientSize().GetHeight() / rowLabelWin_.getRowHeight());
return;
case 'A': //Ctrl + A - select all
if (event.ControlDown())
- refParent().selectRangeAndNotify(0, rowCount, cursor.second);
+ refParent().selectRangeAndNotify(0, rowCount);
break;
case WXK_NUMPAD_ADD: //CTRL + '+' - auto-size all
if (event.ControlDown())
- refParent().autoSizeColumns(cursor.second);
+ refParent().autoSizeColumns(ALLOW_GRID_EVENT);
return;
}
@@ -1266,8 +1238,8 @@ private:
class MouseSelection : private wxEvtHandler
{
public:
- MouseSelection(MainWin& wnd, size_t rowStart, size_t compPos, bool positiveSelect) :
- wnd_(wnd), rowStart_(rowStart), compPos_(compPos), rowCurrent_(rowStart), positiveSelect_(positiveSelect), toScrollX(0), toScrollY(0),
+ MouseSelection(MainWin& wnd, size_t rowStart, bool positiveSelect) :
+ wnd_(wnd), rowStart_(rowStart), rowCurrent_(rowStart), positiveSelect_(positiveSelect), toScrollX(0), toScrollY(0),
tickCountLast(getTicks()),
ticksPerSec_(ticksPerSec())
{
@@ -1279,7 +1251,6 @@ private:
~MouseSelection() { if (wnd_.HasCapture()) wnd_.ReleaseMouse(); }
size_t getStartRow () const { return rowStart_; }
- size_t getComponentPos () const { return compPos_; }
size_t getCurrentRow () const { return rowCurrent_; }
bool isPositiveSelect() const { return positiveSelect_; } //are we selecting or unselecting?
@@ -1352,7 +1323,6 @@ private:
MainWin& wnd_;
const size_t rowStart_;
- const size_t compPos_;
ptrdiff_t rowCurrent_;
const bool positiveSelect_;
wxTimer timer;
@@ -1397,7 +1367,7 @@ private:
std::unique_ptr<MouseSelection> activeSelection; //bound while user is selecting with mouse
- std::pair<ptrdiff_t, ptrdiff_t> cursor; //(row, component position), always valid! still unsigned type to facilitate "onKeyDown()"
+ ptrdiff_t cursorRow;
size_t selectionAnchor;
bool gridUpdatePending;
};
@@ -1415,7 +1385,8 @@ Grid::Grid(wxWindow* parent,
showScrollbarY(SB_SHOW_AUTOMATIC),
colLabelHeight(0), //dummy init
drawRowLabel(true),
- comp(1),
+ allowColumnMove(true),
+ allowColumnResize(true),
rowCountOld(0)
{
cornerWin_ = new CornerWin (*this); //
@@ -1617,23 +1588,31 @@ void Grid::showRowLabel(bool show)
}
-std::vector<size_t> Grid::getSelectedRows(size_t compPos) const
+void Grid::selectAllRows(GridEventPolicy rangeEventPolicy)
{
- if (compPos < comp.size())
- return comp[compPos].selection.get();
- assert(false);
- return std::vector<size_t>();
+ selection.selectAll();
+ mainWin_->Refresh();
+
+ if (rangeEventPolicy == ALLOW_GRID_EVENT) //notify event, even if we're not triggered by user interaction
+ {
+ GridRangeSelectEvent selEvent(0, getRowCount(), true);
+ if (wxEvtHandler* evtHandler = GetEventHandler())
+ evtHandler->ProcessEvent(selEvent);
+ }
}
-void Grid::setSelectedRows(const std::vector<size_t>& sel, size_t compPos)
+void Grid::clearSelection(GridEventPolicy rangeEventPolicy)
{
- if (compPos < comp.size())
+ selection.clear();
+ mainWin_->Refresh();
+
+ if (rangeEventPolicy == ALLOW_GRID_EVENT) //notify event, even if we're not triggered by user interaction
{
- comp[compPos].selection.set(sel);
- Refresh();
+ GridRangeSelectEvent unselectionEvent(0, getRowCount(), false);
+ if (wxEvtHandler* evtHandler = GetEventHandler())
+ evtHandler->ProcessEvent(unselectionEvent);
}
- else assert(false);
}
@@ -1667,7 +1646,7 @@ void Grid::redirectRowLabelEvent(wxMouseEvent& event)
size_t Grid::getRowCount() const
{
- return comp.empty() ? 0 : comp.front().dataView_ ? comp.front().dataView_->getRowCount() : 0;
+ return dataView_ ? dataView_->getRowCount() : 0;
}
@@ -1680,9 +1659,8 @@ void Grid::Refresh(bool eraseBackground, const wxRect* rect)
updateWindowSizes();
}
- for (Component& c : comp)
- if (c.selection.size() != rowCountNew) //clear selection only when needed (consider setSelectedRows())
- c.selection.init(rowCountNew);
+ if (selection.size() != rowCountNew) //clear selection only when needed (consider setSelectedRows())
+ selection.init(rowCountNew);
wxScrolledWindow::Refresh(eraseBackground, rect);
}
@@ -1696,56 +1674,49 @@ void Grid::setRowHeight(int height)
}
-void Grid::setColumnConfig(const std::vector<Grid::ColumnAttribute>& attr, size_t compPos)
+void Grid::setColumnConfig(const std::vector<Grid::ColumnAttribute>& attr)
{
- if (compPos < comp.size())
- {
- //hold ownership of non-visible columns
- comp[compPos].oldColAttributes = attr;
+ //hold ownership of non-visible columns
+ oldColAttributes = attr;
- std::vector<VisibleColumn> visibleCols;
- for (const ColumnAttribute& ca : attr)
- if (ca.visible_)
- visibleCols.push_back(VisibleColumn(ca.type_, ca.offset_, ca.stretch_));
+ std::vector<VisibleColumn> visCols;
+ for (const ColumnAttribute& ca : attr)
+ if (ca.visible_)
+ visCols.push_back(VisibleColumn(ca.type_, ca.offset_, ca.stretch_));
- //"ownership" of visible columns is now within Grid
- comp[compPos].visibleCols = visibleCols;
+ //"ownership" of visible columns is now within Grid
+ visibleCols = visCols;
- updateWindowSizes();
- Refresh();
- }
+ updateWindowSizes();
+ Refresh();
}
-std::vector<Grid::ColumnAttribute> Grid::getColumnConfig(size_t compPos) const
+std::vector<Grid::ColumnAttribute> Grid::getColumnConfig() const
{
- if (compPos < comp.size())
- {
- //get non-visible columns (+ outdated visible ones)
- std::vector<ColumnAttribute> output = comp[compPos].oldColAttributes;
+ //get non-visible columns (+ outdated visible ones)
+ std::vector<ColumnAttribute> output = oldColAttributes;
- auto iterVcols = comp[compPos].visibleCols.begin();
- auto iterVcolsend = comp[compPos].visibleCols.end();
+ auto iterVcols = visibleCols.begin();
+ auto iterVcolsend = visibleCols.end();
- //update visible columns but keep order of non-visible ones!
- for (ColumnAttribute& ca : output)
- if (ca.visible_)
+ //update visible columns but keep order of non-visible ones!
+ for (ColumnAttribute& ca : output)
+ if (ca.visible_)
+ {
+ if (iterVcols != iterVcolsend)
{
- if (iterVcols != iterVcolsend)
- {
- ca.type_ = iterVcols->type_;
- ca.stretch_ = iterVcols->stretch_;
- ca.offset_ = iterVcols->offset_;
- ++iterVcols;
- }
- else
- assert(false);
+ ca.type_ = iterVcols->type_;
+ ca.stretch_ = iterVcols->stretch_;
+ ca.offset_ = iterVcols->offset_;
+ ++iterVcols;
}
- assert(iterVcols == iterVcolsend);
+ else
+ assert(false);
+ }
+ assert(iterVcols == iterVcolsend);
- return output;
- }
- return std::vector<ColumnAttribute>();
+ return output;
}
@@ -1841,34 +1812,6 @@ void Grid::SetScrollbar(int orientation, int position, int thumbSize, int range,
}
#endif
-//get rid of scrollbars, but preserve scrolling behavior!
-#ifdef ZEN_WIN
-WXLRESULT Grid::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
-{
- //we land here if wxWindowMSW::MSWWindowProc() couldn't handle the message
- //http://msdn.microsoft.com/en-us/library/windows/desktop/ms645614(v=vs.85).aspx
- if (nMsg == WM_MOUSEHWHEEL) //horizontal wheel
- {
- const int distance = GET_WHEEL_DELTA_WPARAM(wParam);
- const int delta = WHEEL_DELTA;
- int rotations = distance / delta;
-
- if (GetLayoutDirection() == wxLayout_RightToLeft)
- rotations = -rotations;
-
- static int linesPerRotation = -1;
- if (linesPerRotation < 0)
- if (!::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerRotation, 0))
- linesPerRotation = 3;
-
- scrollDelta(rotations * linesPerRotation, 0); //in scroll units
- return 0; //"If an application processes this message, it should return zero."
- }
-
- return wxScrolledWindow::MSWDefWindowProc(nMsg, wParam, lParam);
-}
-#endif
-
wxWindow& Grid::getCornerWin () { return *cornerWin_; }
wxWindow& Grid::getRowLabelWin() { return *rowLabelWin_; }
@@ -1877,27 +1820,20 @@ wxWindow& Grid::getMainWin () { return *mainWin_; }
const wxWindow& Grid::getMainWin() const { return *mainWin_; }
-wxRect Grid::getColumnLabelArea(ColumnType colType, size_t compPos) const
+wxRect Grid::getColumnLabelArea(ColumnType colType) const
{
- std::vector<std::vector<ColumnWidth>> compAbsWidths = getColWidths(); //resolve negative/stretched widths
- if (compPos < compAbsWidths.size())
- {
- auto iterComp = compAbsWidths.begin() + compPos;
-
- auto iterCol = std::find_if(iterComp->begin(), iterComp->end(), [&](const ColumnWidth& cw) { return cw.type_ == colType; });
- if (iterCol != iterComp->end())
- {
- ptrdiff_t posX = 0;
- for (auto it = compAbsWidths.begin(); it != iterComp; ++it)
- for (const ColumnWidth& cw : *it)
- posX += cw.width_;
+ std::vector<ColumnWidth> absWidths = getColWidths(); //resolve negative/stretched widths
- for (auto it = iterComp->begin(); it != iterCol; ++it)
- posX += it->width_;
+ auto iterCol = std::find_if(absWidths.begin(), absWidths.end(), [&](const ColumnWidth& cw) { return cw.type_ == colType; });
+ if (iterCol != absWidths.end())
+ {
+ ptrdiff_t posX = 0;
+ for (auto it = absWidths.begin(); it != iterCol; ++it)
+ posX += it->width_;
- return wxRect(wxPoint(posX, 0), wxSize(iterCol->width_, colLabelHeight));
- }
+ return wxRect(wxPoint(posX, 0), wxSize(iterCol->width_, colLabelHeight));
}
+
return wxRect();
}
@@ -1907,32 +1843,26 @@ Opt<Grid::ColAction> Grid::clientPosToColumnAction(const wxPoint& pos) const
const int absPosX = CalcUnscrolledPosition(pos).x;
if (absPosX >= 0)
{
- int accuWidth = 0;
+ const int resizeTolerance = allowColumnResize ? COLUMN_RESIZE_TOLERANCE : 0;
+ std::vector<ColumnWidth> absWidths = getColWidths(); //resolve stretched widths
- std::vector<std::vector<ColumnWidth>> compAbsWidths = getColWidths(); //resolve stretched widths
- for (size_t compPos = 0; compPos < compAbsWidths.size(); ++compPos)
+ int accuWidth = 0;
+ for (size_t col = 0; col < absWidths.size(); ++col)
{
- const int resizeTolerance = columnResizeAllowed(compPos) ? COLUMN_RESIZE_TOLERANCE : 0;
-
- for (size_t col = 0; col < compAbsWidths[compPos].size(); ++col)
+ accuWidth += absWidths[col].width_;
+ if (std::abs(absPosX - accuWidth) < resizeTolerance)
{
- accuWidth += compAbsWidths[compPos][col].width_;
- if (std::abs(absPosX - accuWidth) < resizeTolerance)
- {
- ColAction out = {};
- out.wantResize = true;
- out.col = col;
- out.compPos = compPos;
- return out;
- }
- else if (absPosX < accuWidth)
- {
- ColAction out = {};
- out.wantResize = false;
- out.col = col;
- out.compPos = compPos;
- return out;
- }
+ ColAction out = {};
+ out.wantResize = true;
+ out.col = col;
+ return out;
+ }
+ else if (absPosX < accuWidth)
+ {
+ ColAction out = {};
+ out.wantResize = false;
+ out.col = col;
+ return out;
}
}
}
@@ -1940,54 +1870,42 @@ Opt<Grid::ColAction> Grid::clientPosToColumnAction(const wxPoint& pos) const
}
-void Grid::moveColumn(size_t colFrom, size_t colTo, size_t compPos)
+void Grid::moveColumn(size_t colFrom, size_t colTo)
{
- if (compPos < comp.size())
+ if (colFrom < visibleCols.size() &&
+ colTo < visibleCols.size() &&
+ colTo != colFrom)
{
- auto& visibleCols = comp[compPos].visibleCols;
- if (colFrom < visibleCols.size() &&
- colTo < visibleCols.size() &&
- colTo != colFrom)
- {
- const auto colAtt = visibleCols[colFrom];
- visibleCols.erase (visibleCols.begin() + colFrom);
- visibleCols.insert(visibleCols.begin() + colTo, colAtt);
- }
+ const auto colAtt = visibleCols[colFrom];
+ visibleCols.erase (visibleCols.begin() + colFrom);
+ visibleCols.insert(visibleCols.begin() + colTo, colAtt);
}
}
-ptrdiff_t Grid::clientPosToMoveTargetColumn(const wxPoint& pos, size_t compPos) const
+ptrdiff_t Grid::clientPosToMoveTargetColumn(const wxPoint& pos) const
{
- std::vector<std::vector<ColumnWidth>> compAbsWidths = getColWidths(); //resolve negative/stretched widths
- if (compPos < compAbsWidths.size())
- {
- auto iterComp = compAbsWidths.begin() + compPos;
- const int absPosX = CalcUnscrolledPosition(pos).x;
+ std::vector<ColumnWidth> absWidths = getColWidths(); //resolve negative/stretched widths
- int accuWidth = 0;
- for (auto it = compAbsWidths.begin(); it != iterComp; ++it)
- for (const ColumnWidth& cw : *it)
- accuWidth += cw.width_;
+ const int absPosX = CalcUnscrolledPosition(pos).x;
- for (auto iterCol = iterComp->begin(); iterCol != iterComp->end(); ++iterCol)
- {
- const int width = iterCol->width_; //beware dreaded unsigned conversions!
- accuWidth += width;
+ int accuWidth = 0;
+ for (auto iterCol = absWidths.begin(); iterCol != absWidths.end(); ++iterCol)
+ {
+ const int width = iterCol->width_; //beware dreaded unsigned conversions!
+ accuWidth += width;
- if (absPosX < accuWidth - width / 2)
- return iterCol - iterComp->begin();
- }
- return iterComp->size();
+ if (absPosX < accuWidth - width / 2)
+ return iterCol - absWidths.begin();
}
- return -1;
+ return absWidths.size();
}
-Opt<ColumnType> Grid::colToType(size_t col, size_t compPos) const
+Opt<ColumnType> Grid::colToType(size_t col) const
{
- if (compPos < comp.size() && col < comp[compPos].visibleCols.size())
- return comp[compPos].visibleCols[col].type_;
+ if (col < visibleCols.size())
+ return visibleCols[col].type_;
return NoValue();
}
@@ -1995,96 +1913,61 @@ Opt<ColumnType> Grid::colToType(size_t col, size_t compPos) const
ptrdiff_t Grid::getRowAtPos(int posY) const { return rowLabelWin_->getRowAtPos(posY); }
-Opt<std::pair<ColumnType, size_t>> Grid::getColumnAtPos(int posX) const
+Opt<ColumnType> Grid::getColumnAtPos(int posX) const
{
if (posX >= 0)
{
- std::vector<std::vector<ColumnWidth>> compAbsWidths = getColWidths(); //resolve negative/stretched widths
-
int accWidth = 0;
- for (size_t compPos = 0; compPos < compAbsWidths.size(); ++compPos)
- for (const ColumnWidth& cw : compAbsWidths[compPos])
- {
- accWidth += cw.width_;
- if (posX < accWidth)
- return std::make_pair(cw.type_, compPos);
- }
+ for (const ColumnWidth& cw : getColWidths())
+ {
+ accWidth += cw.width_;
+ if (posX < accWidth)
+ return cw.type_;
+ }
}
return NoValue();
}
-wxRect Grid::getCellArea(size_t row, ColumnType colType, size_t compPos) const
+wxRect Grid::getCellArea(size_t row, ColumnType colType) const
{
- const wxRect& colArea = getColumnLabelArea(colType, compPos);
+ const wxRect& colArea = getColumnLabelArea(colType);
const wxRect& rowArea = rowLabelWin_->getRowLabelArea(row);
return wxRect(wxPoint(colArea.x, rowArea.y), wxSize(colArea.width, rowArea.height));
}
-void Grid::setGridCursor(size_t row, size_t compPos)
+void Grid::setGridCursor(size_t row)
{
- if (compPos < comp.size())
- {
- mainWin_->setCursor(row, compPos);
- mainWin_->makeRowVisible(row);
+ mainWin_->setCursor(row);
+ mainWin_->makeRowVisible(row);
- for (Grid::Component& c : comp)
- c.selection.clear(); //clear selection, do NOT fire event
- selectRangeAndNotify(row, row, compPos); //set new selection + fire event
+ selection.clear(); //clear selection, do NOT fire event
+ selectRangeAndNotify(row, row); //set new selection + fire event
- mainWin_->Refresh();
- rowLabelWin_->Refresh(); //row labels! (Kubuntu)
- }
+ mainWin_->Refresh();
+ rowLabelWin_->Refresh(); //row labels! (Kubuntu)
}
-void Grid::selectRangeAndNotify(ptrdiff_t rowFrom, ptrdiff_t rowTo, size_t compPos, bool positive)
+void Grid::selectRangeAndNotify(ptrdiff_t rowFrom, ptrdiff_t rowTo, bool positive)
{
- if (compPos < comp.size())
- {
- //sort + convert to half-open range
- auto rowFirst = std::min(rowFrom, rowTo);
- auto rowLast = std::max(rowFrom, rowTo) + 1;
-
- const size_t rowCount = getRowCount();
- numeric::confine<ptrdiff_t>(rowFirst, 0, rowCount);
- numeric::confine<ptrdiff_t>(rowLast, 0, rowCount);
-
- comp[compPos].selection.selectRange(rowFirst, rowLast, positive);
-
- //notify event
- GridRangeSelectEvent selectionEvent(rowFirst, rowLast, compPos, positive);
- if (wxEvtHandler* evtHandler = GetEventHandler())
- evtHandler->ProcessEvent(selectionEvent);
-
- mainWin_->Refresh();
- }
-}
+ //sort + convert to half-open range
+ auto rowFirst = std::min(rowFrom, rowTo);
+ auto rowLast = std::max(rowFrom, rowTo) + 1;
+ const size_t rowCount = getRowCount();
+ numeric::confine<ptrdiff_t>(rowFirst, 0, rowCount);
+ numeric::confine<ptrdiff_t>(rowLast, 0, rowCount);
-void Grid::clearSelection(bool emitSelectRangeEvent, size_t compPos)
-{
- if (compPos < comp.size())
- {
- comp[compPos].selection.clear();
- mainWin_->Refresh();
-
- if (emitSelectRangeEvent)
- {
- //notify event, even if we're not triggered by user interaction
- GridRangeSelectEvent unselectionEvent(0, 0, compPos, false);
- if (wxEvtHandler* evtHandler = GetEventHandler())
- evtHandler->ProcessEvent(unselectionEvent);
- }
- }
-}
+ selection.selectRange(rowFirst, rowLast, positive);
+ //notify event
+ GridRangeSelectEvent selectionEvent(rowFirst, rowLast, positive);
+ if (wxEvtHandler* evtHandler = GetEventHandler())
+ evtHandler->ProcessEvent(selectionEvent);
-void Grid::clearSelectionAllAndNotify()
-{
- for (size_t compPos = 0; compPos < comp.size(); ++compPos)
- clearSelection(true, compPos);
+ mainWin_->Refresh();
}
@@ -2113,46 +1996,41 @@ void Grid::scrollTo(size_t row)
}
-std::pair<size_t, size_t> Grid::getGridCursor() const
+size_t Grid::getGridCursor() const
{
return mainWin_->getCursor();
}
-int Grid::getBestColumnSize(size_t col, size_t compPos) const
+int Grid::getBestColumnSize(size_t col) const
{
- if (compPos < comp.size())
+ if (dataView_ && col < visibleCols.size())
{
- const auto& visibleCols = comp[compPos].visibleCols;
- auto dataView = comp[compPos].dataView_;
- if (dataView && col < visibleCols.size())
- {
- const ColumnType type = visibleCols[col].type_;
+ const ColumnType type = visibleCols[col].type_;
- wxClientDC dc(mainWin_);
- dc.SetFont(mainWin_->GetFont()); //harmonize with MainWin::render()
+ wxClientDC dc(mainWin_);
+ dc.SetFont(mainWin_->GetFont()); //harmonize with MainWin::render()
- int maxSize = 0;
+ int maxSize = 0;
- auto rowRange = rowLabelWin_->getRowsOnClient(mainWin_->GetClientRect()); //returns range [begin, end)
- for (auto row = rowRange.first; row < rowRange.second; ++row)
- maxSize = std::max(maxSize, dataView->getBestSize(dc, row, type));
+ auto rowRange = rowLabelWin_->getRowsOnClient(mainWin_->GetClientRect()); //returns range [begin, end)
+ for (auto row = rowRange.first; row < rowRange.second; ++row)
+ maxSize = std::max(maxSize, dataView_->getBestSize(dc, row, type));
- return maxSize;
- }
+ return maxSize;
}
return -1;
}
-void Grid::setColWidthAndNotify(int width, size_t col, size_t compPos, bool notifyAsync)
+void Grid::setColumnWidth(int width, size_t col, GridEventPolicy columnResizeEventPolicy, bool notifyAsync)
{
- if (compPos < comp.size() && col < comp[compPos].visibleCols.size())
+ if (col < visibleCols.size())
{
- VisibleColumn& vcRs = comp[compPos].visibleCols[col];
+ VisibleColumn& vcRs = visibleCols[col];
- const std::vector<std::vector<int>> stretchedWidths = getColStretchedWidths(mainWin_->GetClientSize().GetWidth());
- if (stretchedWidths.size() != comp.size() || stretchedWidths[compPos].size() != comp[compPos].visibleCols.size())
+ const std::vector<int> stretchedWidths = getColStretchedWidths(mainWin_->GetClientSize().GetWidth());
+ if (stretchedWidths.size() != visibleCols.size())
{
assert(false);
return;
@@ -2163,7 +2041,7 @@ void Grid::setColWidthAndNotify(int width, size_t col, size_t compPos, bool noti
//unusual delay when enlarging the column again later
width = std::max(width, COLUMN_MIN_WIDTH);
- vcRs.offset_ = width - stretchedWidths[compPos][col]; //width := stretchedWidth + offset
+ vcRs.offset_ = width - stretchedWidths[col]; //width := stretchedWidth + offset
//III. resizing any column should normalize *all* other stretched columns' offsets considering current mainWinWidth!
// test case:
@@ -2171,21 +2049,20 @@ void Grid::setColWidthAndNotify(int width, size_t col, size_t compPos, bool noti
//2. shrink main window width so that horizontal scrollbars are shown despite the streched column
//3. shrink a fixed-size column so that the scrollbars vanish and columns cover full width again
//4. now verify that the stretched column is resizing immediately if main window is enlarged again
- for (size_t compPos2 = 0; compPos2 < comp.size(); ++compPos2)
- {
- auto& visibleCols = comp[compPos2].visibleCols;
- for (size_t col2 = 0; col2 < visibleCols.size(); ++col2)
- if (visibleCols[col2].stretch_ > 0) //normalize stretched columns only
- visibleCols[col2].offset_ = std::max(visibleCols[col2].offset_, COLUMN_MIN_WIDTH - stretchedWidths[compPos2][col2]);
- }
+ for (size_t col2 = 0; col2 < visibleCols.size(); ++col2)
+ if (visibleCols[col2].stretch_ > 0) //normalize stretched columns only
+ visibleCols[col2].offset_ = std::max(visibleCols[col2].offset_, COLUMN_MIN_WIDTH - stretchedWidths[col2]);
- GridColumnResizeEvent sizeEvent(vcRs.offset_, vcRs.type_, compPos);
- if (wxEvtHandler* evtHandler = GetEventHandler())
+ if (columnResizeEventPolicy == ALLOW_GRID_EVENT)
{
- if (notifyAsync)
- evtHandler->AddPendingEvent(sizeEvent);
- else
- evtHandler->ProcessEvent(sizeEvent);
+ GridColumnResizeEvent sizeEvent(vcRs.offset_, vcRs.type_);
+ if (wxEvtHandler* evtHandler = GetEventHandler())
+ {
+ if (notifyAsync)
+ evtHandler->AddPendingEvent(sizeEvent);
+ else
+ evtHandler->ProcessEvent(sizeEvent);
+ }
}
}
else
@@ -2193,16 +2070,15 @@ void Grid::setColWidthAndNotify(int width, size_t col, size_t compPos, bool noti
}
-void Grid::autoSizeColumns(size_t compPos)
+void Grid::autoSizeColumns(GridEventPolicy columnResizeEventPolicy)
{
- if (compPos < comp.size() && comp[compPos].allowColumnResize)
+ if (allowColumnResize)
{
- auto& visibleCols = comp[compPos].visibleCols;
for (size_t col = 0; col < visibleCols.size(); ++col)
{
- const int bestWidth = getBestColumnSize(col, compPos); //return -1 on error
+ const int bestWidth = getBestColumnSize(col); //return -1 on error
if (bestWidth >= 0)
- setColWidthAndNotify(bestWidth, col, compPos, true);
+ setColumnWidth(bestWidth, col, columnResizeEventPolicy, true);
}
updateWindowSizes();
Refresh();
@@ -2210,91 +2086,71 @@ void Grid::autoSizeColumns(size_t compPos)
}
-std::vector<std::vector<int>> Grid::getColStretchedWidths(int clientWidth) const //final width = (normalized) (stretchedWidth + offset)
+std::vector<int> Grid::getColStretchedWidths(int clientWidth) const //final width = (normalized) (stretchedWidth + offset)
{
assert(clientWidth >= 0);
clientWidth = std::max(clientWidth, 0);
int stretchTotal = 0;
- for (const Component& c : comp)
- for (const VisibleColumn& vc : c.visibleCols)
- {
- assert(vc.stretch_ >= 0);
- stretchTotal += vc.stretch_;
- }
+ for (const VisibleColumn& vc : visibleCols)
+ {
+ assert(vc.stretch_ >= 0);
+ stretchTotal += vc.stretch_;
+ }
int remainingWidth = clientWidth;
- std::vector<std::vector<int>> output;
- for (const Component& c : comp)
- {
- output.push_back(std::vector<int>());
- auto& compWidths = output.back();
+ std::vector<int> output;
- if (stretchTotal <= 0)
- compWidths.resize(c.visibleCols.size()); //fill with zeros
- else
- for (const VisibleColumn& vc : c.visibleCols)
- {
- const int width = clientWidth * vc.stretch_ / stretchTotal; //rounds down!
- compWidths.push_back(width);
- remainingWidth -= width;
- }
- }
+ if (stretchTotal <= 0)
+ output.resize(visibleCols.size()); //fill with zeros
+ else
+ for (const VisibleColumn& vc : visibleCols)
+ {
+ const int width = clientWidth * vc.stretch_ / stretchTotal; //rounds down!
+ output.push_back(width);
+ remainingWidth -= width;
+ }
//distribute *all* of clientWidth: should suffice to enlarge the first few stretched columns; no need to minimize total absolute error of distribution
if (stretchTotal > 0)
if (remainingWidth > 0)
{
- for (size_t compPos2 = 0; compPos2 < comp.size(); ++compPos2)
- {
- auto& visibleCols = comp[compPos2].visibleCols;
- for (size_t col2 = 0; col2 < visibleCols.size(); ++col2)
- if (visibleCols[col2].stretch_ > 0)
- {
- ++output[compPos2][col2];
- if (--remainingWidth == 0)
- return output;
- }
- }
+ for (size_t col2 = 0; col2 < visibleCols.size(); ++col2)
+ if (visibleCols[col2].stretch_ > 0)
+ {
+ ++output[col2];
+ if (--remainingWidth == 0)
+ return output;
+ }
assert(false);
}
return output;
}
-std::vector<std::vector<Grid::ColumnWidth>> Grid::getColWidths() const
+std::vector<Grid::ColumnWidth> Grid::getColWidths() const
{
return getColWidths(mainWin_->GetClientSize().GetWidth());
}
-std::vector<std::vector<Grid::ColumnWidth>> Grid::getColWidths(int mainWinWidth) const //evaluate stretched columns; structure matches "comp"
+std::vector<Grid::ColumnWidth> Grid::getColWidths(int mainWinWidth) const //evaluate stretched columns
{
- const std::vector<std::vector<int>> stretchedWidths = getColStretchedWidths(mainWinWidth);
- assert(stretchedWidths.size() == comp.size());
+ const std::vector<int> stretchedWidths = getColStretchedWidths(mainWinWidth);
+ assert(stretchedWidths.size() == visibleCols.size());
- std::vector<std::vector<ColumnWidth>> output;
-
- for (size_t compPos2 = 0; compPos2 < comp.size(); ++compPos2)
+ std::vector<ColumnWidth> output;
+ for (size_t col2 = 0; col2 < visibleCols.size(); ++col2)
{
- assert(stretchedWidths[compPos2].size() == comp[compPos2].visibleCols.size());
-
- output.push_back(std::vector<ColumnWidth>());
- auto& compWidths = output.back();
-
- auto& visibleCols = comp[compPos2].visibleCols;
- for (size_t col2 = 0; col2 < visibleCols.size(); ++col2)
- {
- const auto& vc = visibleCols[col2];
- int width = stretchedWidths[compPos2][col2] + vc.offset_;
+ const auto& vc = visibleCols[col2];
+ int width = stretchedWidths[col2] + vc.offset_;
- if (vc.stretch_ > 0)
- width = std::max(width, COLUMN_MIN_WIDTH); //normalization really needed here: e.g. smaller main window would result in negative width
- else
- width = std::max(width, 0); //support smaller width than COLUMN_MIN_WIDTH if set via configuration
+ if (vc.stretch_ > 0)
+ width = std::max(width, COLUMN_MIN_WIDTH); //normalization really needed here: e.g. smaller main window would result in negative width
+ else
+ width = std::max(width, 0); //support smaller width than COLUMN_MIN_WIDTH if set via configuration
- compWidths.push_back(ColumnWidth(vc.type_, width));
- }
+ output.push_back(ColumnWidth(vc.type_, width));
}
return output;
}
@@ -2303,8 +2159,7 @@ std::vector<std::vector<Grid::ColumnWidth>> Grid::getColWidths(int mainWinWidth)
int Grid::getColWidthsSum(int mainWinWidth) const
{
int sum = 0;
- for (const std::vector<ColumnWidth>& cols : getColWidths(mainWinWidth))
- for (const ColumnWidth& cw : cols)
- sum += cw.width_;
+ for (const ColumnWidth& cw : getColWidths(mainWinWidth))
+ sum += cw.width_;
return sum;
};
diff --git a/wx+/grid.h b/wx+/grid.h
index e8f62a12..9bbb6c99 100644
--- a/wx+/grid.h
+++ b/wx+/grid.h
@@ -38,32 +38,30 @@ extern const wxEventType EVENT_GRID_SELECT_RANGE; //generates: GridRangeSelectEv
struct GridClickEvent : public wxMouseEvent
{
- GridClickEvent(wxEventType et, const wxMouseEvent& me, ptrdiff_t row, ColumnType colType, size_t compPos) : wxMouseEvent(me), row_(row), colType_(colType), compPos_(compPos) { SetEventType(et); }
+ GridClickEvent(wxEventType et, const wxMouseEvent& me, ptrdiff_t row, ColumnType colType) : wxMouseEvent(me), row_(row), colType_(colType) { SetEventType(et); }
virtual wxEvent* Clone() const { return new GridClickEvent(*this); }
+
const ptrdiff_t row_; //-1 for invalid position, >= rowCount if out of range
const ColumnType colType_;
- const size_t compPos_;
};
struct GridColumnResizeEvent : public wxCommandEvent
{
- GridColumnResizeEvent(int offset, ColumnType colType, size_t compPos) : wxCommandEvent(EVENT_GRID_COL_RESIZE), colType_(colType), offset_(offset), compPos_(compPos) {}
+ GridColumnResizeEvent(int offset, ColumnType colType) : wxCommandEvent(EVENT_GRID_COL_RESIZE), colType_(colType), offset_(offset) {}
virtual wxEvent* Clone() const { return new GridColumnResizeEvent(*this); }
const ColumnType colType_;
const int offset_;
- const size_t compPos_;
};
struct GridRangeSelectEvent : public wxCommandEvent
{
- GridRangeSelectEvent(size_t rowFirst, size_t rowLast, size_t compPos, bool positive) : wxCommandEvent(EVENT_GRID_SELECT_RANGE), rowFirst_(rowFirst), rowLast_(rowLast), compPos_(compPos), positive_(positive) { assert(rowFirst <= rowLast); }
+ GridRangeSelectEvent(size_t rowFirst, size_t rowLast, bool positive) : wxCommandEvent(EVENT_GRID_SELECT_RANGE), positive_(positive), rowFirst_(rowFirst), rowLast_(rowLast) { assert(rowFirst <= rowLast); }
virtual wxEvent* Clone() const { return new GridRangeSelectEvent(*this); }
+ const bool positive_; //"false" when clearing selection!
const size_t rowFirst_; //selected range: [rowFirst_, rowLast_)
- const size_t rowLast_; //range is empty when clearing selection
- const size_t compPos_;
- const bool positive_;
+ const size_t rowLast_;
};
typedef void (wxEvtHandler::*GridClickEventFunction )(GridClickEvent&);
@@ -90,7 +88,7 @@ class GridData
public:
virtual ~GridData() {}
- virtual size_t getRowCount() const = 0; //if there are multiple grid components, only the first one will be polled for row count!
+ virtual size_t getRowCount() const = 0;
//grid area
virtual wxString getValue(size_t row, ColumnType colType) const = 0;
@@ -116,6 +114,12 @@ protected: //optional helper routines
static void drawColumnLabelText (wxDC& dc, const wxRect& rect, const wxString& text);
};
+enum GridEventPolicy
+{
+ ALLOW_GRID_EVENT,
+ DENY_GRID_EVENT
+};
+
class Grid : public wxScrolledWindow
{
@@ -131,10 +135,6 @@ public:
void setRowHeight(int height);
- //grid component := a grid is divided into multiple components each of which is essentially a set of connected columns
- void setComponentCount(size_t count) { comp.resize(count); updateWindowSizes(); }
- size_t getComponentCount() const { return comp.size(); }
-
struct ColumnAttribute
{
ColumnAttribute(ColumnType type, int offset, int stretch, bool visible = true) : type_(type), visible_(visible), stretch_(std::max(stretch, 0)), offset_(offset) { assert(stretch >=0 ); }
@@ -146,12 +146,12 @@ public:
int offset_;
};
- void setColumnConfig(const std::vector<ColumnAttribute>& attr, size_t compPos = 0); //set column count + widths
- std::vector<ColumnAttribute> getColumnConfig(size_t compPos = 0) const;
+ void setColumnConfig(const std::vector<ColumnAttribute>& attr); //set column count + widths
+ std::vector<ColumnAttribute> getColumnConfig() const;
- void setDataProvider(const std::shared_ptr<GridData>& dataView, size_t compPos = 0) { if (compPos < comp.size()) comp[compPos].dataView_ = dataView; }
- /**/ GridData* getDataProvider(size_t compPos = 0) { return compPos < comp.size() ? comp[compPos].dataView_.get() : nullptr; }
- const GridData* getDataProvider(size_t compPos = 0) const { return compPos < comp.size() ? comp[compPos].dataView_.get() : nullptr; }
+ void setDataProvider(const std::shared_ptr<GridData>& dataView) { dataView_ = dataView; }
+ /**/ GridData* getDataProvider() { return dataView_.get(); }
+ const GridData* getDataProvider() const { return dataView_.get(); }
//-----------------------------------------------------------------------------
void setColumnLabelHeight(int height);
@@ -166,9 +166,9 @@ public:
//alternative until wxScrollHelper::ShowScrollbars() becomes available in wxWidgets 2.9
void showScrollBars(ScrollBarStatus horizontal, ScrollBarStatus vertical);
- std::vector<size_t> getSelectedRows(size_t compPos = 0) const;
- void setSelectedRows(const std::vector<size_t>& sel, size_t compPos = 0);
- void clearSelection(bool emitSelectRangeEvent = true, size_t compPos = 0); //turn off range selection event when calling this function in an event handler to avoid recursion!
+ std::vector<size_t> getSelectedRows() const { return selection.get(); }
+ void selectAllRows (GridEventPolicy rangeEventPolicy);
+ void clearSelection(GridEventPolicy rangeEventPolicy); //turn off range selection event when calling this function in an event handler to avoid recursion!
void scrollDelta(int deltaX, int deltaY); //in scroll units
@@ -179,21 +179,20 @@ public:
const wxWindow& getMainWin() const;
ptrdiff_t getRowAtPos(int posY) const; //return -1 for invalid position, >= rowCount if out of range; absolute coordinates!
- Opt<std::pair<ColumnType, size_t>> getColumnAtPos(int posX) const; //returns (column type, component pos)
+ Opt<ColumnType> getColumnAtPos(int posX) const;
- wxRect getCellArea(size_t row, ColumnType colType, size_t compPos = 0) const; //returns empty rect if column not found; absolute coordinates!
+ wxRect getCellArea(size_t row, ColumnType colType) const; //returns empty rect if column not found; absolute coordinates!
- void enableColumnMove (bool value, size_t compPos = 0) { if (compPos < comp.size()) comp[compPos].allowColumnMove = value; }
- void enableColumnResize(bool value, size_t compPos = 0) { if (compPos < comp.size()) comp[compPos].allowColumnResize = value; }
+ void enableColumnMove (bool value) { allowColumnMove = value; }
+ void enableColumnResize(bool value) { allowColumnResize = value; }
- void setGridCursor(size_t row, size_t compPos = 0); //set + show + select cursor (+ emit range selection event)
- std::pair<size_t, size_t> getGridCursor() const; //(row, component pos)
+ void setGridCursor(size_t row); //set + show + select cursor (+ emit range selection event)
+ size_t getGridCursor() const; //returns row
void scrollTo(size_t row);
virtual void Refresh(bool eraseBackground = true, const wxRect* rect = nullptr);
virtual bool Enable( bool enable = true) { Refresh(); return wxScrolledWindow::Enable(enable); }
- void autoSizeColumns(size_t compPos = 0);
//############################################################################################################
private:
@@ -211,11 +210,9 @@ private:
virtual void SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh); //get rid of scrollbars, but preserve scrolling behavior!
#endif
-#ifdef ZEN_WIN
- virtual WXLRESULT MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam); //support horizontal mouse wheel
-#endif
+ int getBestColumnSize(size_t col) const; //return -1 on error
- int getBestColumnSize(size_t col, size_t compPos) const; //return -1 on error
+ void autoSizeColumns(GridEventPolicy columnResizeEventPolicy);
friend class GridData;
class SubWindow;
@@ -240,15 +237,8 @@ private:
return selection;
}
- void set(const std::vector<size_t>& newSel)
- {
- clear();
- for (size_t row : newSel)
- if (row < rowSelectionValue.size())
- rowSelectionValue[row] = true;
- }
-
- void clear() { selectRange(0, rowSelectionValue.size(), false); }
+ void selectAll() { selectRange(0, rowSelectionValue.size(), true); }
+ void clear () { selectRange(0, rowSelectionValue.size(), false); }
bool isSelected(size_t row) const { return row < rowSelectionValue.size() ? rowSelectionValue[row] != 0 : false; }
@@ -276,70 +266,52 @@ private:
int offset_;
};
- struct Component
- {
- Component() : allowColumnMove(true), allowColumnResize(true) {}
-
- std::shared_ptr<GridData> dataView_;
- Selection selection;
- bool allowColumnMove;
- bool allowColumnResize;
-
- std::vector<VisibleColumn> visibleCols; //individual widths, type and total column count
- std::vector<ColumnAttribute> oldColAttributes; //visible + nonvisible columns; use for conversion in setColumnConfig()/getColumnConfig() *only*!
- };
-
struct ColumnWidth
{
ColumnWidth(ColumnType type, int width) : type_(type), width_(width) {}
ColumnType type_;
int width_;
};
- std::vector<std::vector<ColumnWidth>> getColWidths() const; //
- std::vector<std::vector<ColumnWidth>> getColWidths(int mainWinWidth) const; //evaluate stretched columns; structure matches "comp"
+ std::vector<ColumnWidth> getColWidths() const; //
+ std::vector<ColumnWidth> getColWidths(int mainWinWidth) const; //evaluate stretched columns
int getColWidthsSum(int mainWinWidth) const;
- std::vector<std::vector<int>> getColStretchedWidths(int clientWidth) const; //final width = (normalized) (stretchedWidth + offset)
+ std::vector<int> getColStretchedWidths(int clientWidth) const; //final width = (normalized) (stretchedWidth + offset)
- Opt<int> getColWidth(size_t col, size_t compPos) const
+ Opt<int> getColWidth(size_t col) const
{
const auto& widths = getColWidths();
- if (compPos < widths.size() && col < widths[compPos].size())
- return widths[compPos][col].width_;
+ if (col < widths.size())
+ return widths[col].width_;
return NoValue();
}
- void setColWidthAndNotify(int width, size_t col, size_t compPos, bool notifyAsync = false);
+ void setColumnWidth(int width, size_t col, GridEventPolicy columnResizeEventPolicy, bool notifyAsync = false);
- wxRect getColumnLabelArea(ColumnType colType, size_t compPos) const; //returns empty rect if column not found
+ wxRect getColumnLabelArea(ColumnType colType) const; //returns empty rect if column not found
- void selectRangeAndNotify(ptrdiff_t rowFrom, ptrdiff_t rowTo, size_t compPos, bool positive = true); //select inclusive range [rowFrom, rowTo] + notify event!
+ void selectRangeAndNotify(ptrdiff_t rowFrom, ptrdiff_t rowTo, bool positive = true); //select inclusive range [rowFrom, rowTo] + notify event!
- void clearSelectionAllAndNotify(); //clear selection + notify event
-
- bool isSelected(size_t row, size_t compPos) const { return compPos < comp.size() ? comp[compPos].selection.isSelected(row) : false; }
-
- bool columnMoveAllowed (size_t compPos) const { return compPos < comp.size() ? comp[compPos].allowColumnMove : false; }
- bool columnResizeAllowed(size_t compPos) const { return compPos < comp.size() ? comp[compPos].allowColumnResize : false; }
+ bool isSelected(size_t row) const { return selection.isSelected(row); }
struct ColAction
{
bool wantResize; //"!wantResize" means "move" or "single click"
size_t col;
- size_t compPos;
};
Opt<ColAction> clientPosToColumnAction(const wxPoint& pos) const;
- void moveColumn(size_t colFrom, size_t colTo, size_t compPos);
- ptrdiff_t clientPosToMoveTargetColumn(const wxPoint& pos, size_t compPos) const; //return < 0 on error
+ void moveColumn(size_t colFrom, size_t colTo);
+ ptrdiff_t clientPosToMoveTargetColumn(const wxPoint& pos) const; //return < 0 on error
- Opt<ColumnType> colToType(size_t col, size_t compPos) const;
+ Opt<ColumnType> colToType(size_t col) const;
/*
Visual layout:
- ------------------------------------------------
- |CornerWin | ColLabelWin: |
- |-------------------------- Comp1 | Comp2 ... | row label and main window are vertically tiled into one or more "components"
- |RowLabelWin | MainWin: |
- ------------------------------------------------
+ --------------------------------
+ |CornerWin | ColLabelWin |
+ |------------------------------|
+ |RowLabelWin | MainWin |
+ | | |
+ --------------------------------
*/
CornerWin* cornerWin_;
RowLabelWin* rowLabelWin_;
@@ -352,7 +324,14 @@ private:
int colLabelHeight;
bool drawRowLabel;
- std::vector<Component> comp;
+ std::shared_ptr<GridData> dataView_;
+ Selection selection;
+ bool allowColumnMove;
+ bool allowColumnResize;
+
+ std::vector<VisibleColumn> visibleCols; //individual widths, type and total column count
+ std::vector<ColumnAttribute> oldColAttributes; //visible + nonvisible columns; use for conversion in setColumnConfig()/getColumnConfig() *only*!
+
size_t rowCountOld; //at the time of last Grid::Refresh()
};
}
diff --git a/wx+/popup_dlg.cpp b/wx+/popup_dlg.cpp
index 27526922..2c7887fa 100644
--- a/wx+/popup_dlg.cpp
+++ b/wx+/popup_dlg.cpp
@@ -14,7 +14,6 @@
using namespace zen;
-
namespace
{
void setAsStandard(wxButton& btn)
@@ -62,7 +61,12 @@ void setBestInitialSize(wxTextCtrl& ctrl, const wxString& text, wxSize maxSize)
it = itEnd + 1;
}
- const wxSize bestSize(bestWidth + scrollbarWidth, std::min(rowCount * rowHeight, maxSize.y));
+#if defined ZEN_WIN || defined ZEN_LINUX
+ const int rowGap = 0;
+#elif defined ZEN_MAC
+ const int rowGap = 1;
+#endif
+ const wxSize bestSize(bestWidth + scrollbarWidth, std::min(rowCount * (rowHeight + rowGap), maxSize.y));
ctrl.SetMinSize(bestSize); //alas, SetMinClientSize() is just not working!
}
}
diff --git a/wx+/popup_dlg_generated.cpp b/wx+/popup_dlg_generated.cpp
index b7618545..70c5cb20 100644
--- a/wx+/popup_dlg_generated.cpp
+++ b/wx+/popup_dlg_generated.cpp
@@ -11,79 +11,79 @@
PopupDialogGenerated::PopupDialogGenerated( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxDialog( parent, id, title, pos, size, style )
{
- this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
- this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
-
- wxBoxSizer* bSizer24;
- bSizer24 = new wxBoxSizer( wxVERTICAL );
-
- m_panel33 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
- m_panel33->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
-
- wxBoxSizer* bSizer165;
- bSizer165 = new wxBoxSizer( wxHORIZONTAL );
-
- m_bitmapMsgType = new wxStaticBitmap( m_panel33, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 );
- bSizer165->Add( m_bitmapMsgType, 0, wxALL, 10 );
-
- wxBoxSizer* bSizer16;
- bSizer16 = new wxBoxSizer( wxVERTICAL );
-
- m_staticTextMain = new wxStaticText( m_panel33, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextMain->Wrap( -1 );
- bSizer16->Add( m_staticTextMain, 0, wxTOP|wxBOTTOM|wxRIGHT, 15 );
-
- m_textCtrlTextDetail = new wxTextCtrl( m_panel33, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER );
- bSizer16->Add( m_textCtrlTextDetail, 1, wxEXPAND, 5 );
-
-
- bSizer165->Add( bSizer16, 1, wxEXPAND, 5 );
-
-
- m_panel33->SetSizer( bSizer165 );
- m_panel33->Layout();
- bSizer165->Fit( m_panel33 );
- bSizer24->Add( m_panel33, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
-
- m_staticline6 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
- bSizer24->Add( m_staticline6, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 );
-
- wxBoxSizer* bSizer25;
- bSizer25 = new wxBoxSizer( wxVERTICAL );
-
- m_checkBoxCustom = new wxCheckBox( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- bSizer25->Add( m_checkBoxCustom, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxRIGHT|wxLEFT, 5 );
-
- bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
-
- m_buttonAffirmative = new wxButton( this, wxID_YES, _("dummy"), wxDefaultPosition, wxSize( -1,30 ), 0 );
- bSizerStdButtons->Add( m_buttonAffirmative, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
-
- m_buttonNegative = new wxButton( this, wxID_NO, _("dummy"), wxDefaultPosition, wxSize( -1,30 ), 0 );
- bSizerStdButtons->Add( m_buttonNegative, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
-
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
- bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
-
-
- bSizer25->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 );
-
-
- bSizer24->Add( bSizer25, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
-
-
- this->SetSizer( bSizer24 );
- this->Layout();
- bSizer24->Fit( this );
-
- this->Centre( wxBOTH );
-
- // Connect Events
- this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( PopupDialogGenerated::OnClose ) );
- m_checkBoxCustom->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnCheckBoxClick ), NULL, this );
- m_buttonAffirmative->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnButtonAffirmative ), NULL, this );
- m_buttonNegative->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnButtonNegative ), NULL, this );
- m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnCancel ), NULL, this );
+ this->SetSizeHints( wxSize( -1,-1 ), wxDefaultSize );
+ this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
+
+ wxBoxSizer* bSizer24;
+ bSizer24 = new wxBoxSizer( wxVERTICAL );
+
+ m_panel33 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
+ m_panel33->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
+
+ wxBoxSizer* bSizer165;
+ bSizer165 = new wxBoxSizer( wxHORIZONTAL );
+
+ m_bitmapMsgType = new wxStaticBitmap( m_panel33, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ bSizer165->Add( m_bitmapMsgType, 0, wxALL, 10 );
+
+ wxBoxSizer* bSizer16;
+ bSizer16 = new wxBoxSizer( wxVERTICAL );
+
+ m_staticTextMain = new wxStaticText( m_panel33, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextMain->Wrap( -1 );
+ bSizer16->Add( m_staticTextMain, 0, wxTOP|wxBOTTOM|wxRIGHT, 15 );
+
+ m_textCtrlTextDetail = new wxTextCtrl( m_panel33, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxNO_BORDER );
+ bSizer16->Add( m_textCtrlTextDetail, 1, wxEXPAND, 5 );
+
+
+ bSizer165->Add( bSizer16, 1, wxEXPAND, 5 );
+
+
+ m_panel33->SetSizer( bSizer165 );
+ m_panel33->Layout();
+ bSizer165->Fit( m_panel33 );
+ bSizer24->Add( m_panel33, 1, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+
+ m_staticline6 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
+ bSizer24->Add( m_staticline6, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+ wxBoxSizer* bSizer25;
+ bSizer25 = new wxBoxSizer( wxVERTICAL );
+
+ m_checkBoxCustom = new wxCheckBox( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ bSizer25->Add( m_checkBoxCustom, 0, wxALIGN_CENTER_HORIZONTAL|wxTOP|wxRIGHT|wxLEFT, 5 );
+
+ bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
+
+ m_buttonAffirmative = new wxButton( this, wxID_YES, _("dummy"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ bSizerStdButtons->Add( m_buttonAffirmative, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 );
+
+ m_buttonNegative = new wxButton( this, wxID_NO, _("dummy"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ bSizerStdButtons->Add( m_buttonNegative, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
+
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,30 ), 0 );
+ bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM|wxRIGHT, 5 );
+
+
+ bSizer25->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 );
+
+
+ bSizer24->Add( bSizer25, 0, wxALIGN_CENTER_HORIZONTAL|wxEXPAND, 5 );
+
+
+ this->SetSizer( bSizer24 );
+ this->Layout();
+ bSizer24->Fit( this );
+
+ this->Centre( wxBOTH );
+
+ // Connect Events
+ this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( PopupDialogGenerated::OnClose ) );
+ m_checkBoxCustom->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnCheckBoxClick ), NULL, this );
+ m_buttonAffirmative->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnButtonAffirmative ), NULL, this );
+ m_buttonNegative->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnButtonNegative ), NULL, this );
+ m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnCancel ), NULL, this );
}
PopupDialogGenerated::~PopupDialogGenerated()
diff --git a/wx+/popup_dlg_generated.h b/wx+/popup_dlg_generated.h
index 5aab9f68..3aab2257 100644
--- a/wx+/popup_dlg_generated.h
+++ b/wx+/popup_dlg_generated.h
@@ -37,35 +37,35 @@
///////////////////////////////////////////////////////////////////////////////
/// Class PopupDialogGenerated
///////////////////////////////////////////////////////////////////////////////
-class PopupDialogGenerated : public wxDialog
+class PopupDialogGenerated : public wxDialog
{
- private:
-
- protected:
- wxPanel* m_panel33;
- wxStaticBitmap* m_bitmapMsgType;
- wxStaticText* m_staticTextMain;
- wxTextCtrl* m_textCtrlTextDetail;
- wxStaticLine* m_staticline6;
- wxCheckBox* m_checkBoxCustom;
- wxBoxSizer* bSizerStdButtons;
- wxButton* m_buttonAffirmative;
- wxButton* m_buttonNegative;
- wxButton* m_buttonCancel;
-
- // Virtual event handlers, overide them in your derived class
- virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
- virtual void OnCheckBoxClick( wxCommandEvent& event ) { event.Skip(); }
- virtual void OnButtonAffirmative( wxCommandEvent& event ) { event.Skip(); }
- virtual void OnButtonNegative( wxCommandEvent& event ) { event.Skip(); }
- virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); }
-
-
- public:
-
- PopupDialogGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
- ~PopupDialogGenerated();
-
+private:
+
+protected:
+ wxPanel* m_panel33;
+ wxStaticBitmap* m_bitmapMsgType;
+ wxStaticText* m_staticTextMain;
+ wxTextCtrl* m_textCtrlTextDetail;
+ wxStaticLine* m_staticline6;
+ wxCheckBox* m_checkBoxCustom;
+ wxBoxSizer* bSizerStdButtons;
+ wxButton* m_buttonAffirmative;
+ wxButton* m_buttonNegative;
+ wxButton* m_buttonCancel;
+
+ // Virtual event handlers, overide them in your derived class
+ virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
+ virtual void OnCheckBoxClick( wxCommandEvent& event ) { event.Skip(); }
+ virtual void OnButtonAffirmative( wxCommandEvent& event ) { event.Skip(); }
+ virtual void OnButtonNegative( wxCommandEvent& event ) { event.Skip(); }
+ virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); }
+
+
+public:
+
+ PopupDialogGenerated( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("dummy"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
+ ~PopupDialogGenerated();
+
};
#endif //__POPUP_DLG_GENERATED_H__
bgstack15