diff options
Diffstat (limited to 'wx+')
-rw-r--r-- | wx+/button.cpp | 10 | ||||
-rw-r--r-- | wx+/button.h | 8 | ||||
-rw-r--r-- | wx+/context_menu.h | 8 | ||||
-rw-r--r-- | wx+/file_drop.h | 4 | ||||
-rw-r--r-- | wx+/format_unit.cpp | 12 | ||||
-rw-r--r-- | wx+/format_unit.h | 2 | ||||
-rw-r--r-- | wx+/graph.cpp | 26 | ||||
-rw-r--r-- | wx+/graph.h | 22 | ||||
-rw-r--r-- | wx+/grid.cpp | 466 | ||||
-rw-r--r-- | wx+/grid.h | 64 | ||||
-rw-r--r-- | wx+/mouse_move_dlg.cpp | 2 | ||||
-rw-r--r-- | wx+/no_flicker.h | 4 | ||||
-rw-r--r-- | wx+/pch.h | 2 | ||||
-rw-r--r-- | wx+/serialize.h | 95 | ||||
-rw-r--r-- | wx+/shell_execute.h | 6 | ||||
-rw-r--r-- | wx+/timespan.h | 10 | ||||
-rw-r--r-- | wx+/tooltip.cpp | 9 | ||||
-rw-r--r-- | wx+/tooltip.h | 2 |
18 files changed, 366 insertions, 386 deletions
diff --git a/wx+/button.cpp b/wx+/button.cpp index 9efdf071..1e9cb7f0 100644 --- a/wx+/button.cpp +++ b/wx+/button.cpp @@ -38,12 +38,12 @@ BitmapButton::BitmapButton(wxWindow* parent, } -void BitmapButton::setBitmapFront(const wxBitmap& bitmap, unsigned spaceAfter) +void BitmapButton::setBitmapFront(const wxBitmap& bitmap, size_t spaceAfter) { if (!isEqual(bitmap, bitmapFront) || spaceAfter != m_spaceAfter) //avoid flicker { bitmapFront = bitmap; - m_spaceAfter = spaceAfter; + m_spaceAfter = static_cast<unsigned int>(spaceAfter); refreshButtonLabel(); } } @@ -60,12 +60,12 @@ void BitmapButton::setTextLabel(const wxString& text) } -void BitmapButton::setBitmapBack(const wxBitmap& bitmap, unsigned spaceBefore) +void BitmapButton::setBitmapBack(const wxBitmap& bitmap, size_t spaceBefore) { if (!isEqual(bitmap, bitmapBack) || spaceBefore != m_spaceBefore) //avoid flicker { bitmapBack = bitmap; - m_spaceBefore = spaceBefore; + m_spaceBefore = static_cast<unsigned int>(spaceBefore); refreshButtonLabel(); } } @@ -106,7 +106,7 @@ wxSize getSizeNeeded(const wxString& text, wxFont& font) wxString textFormatted = text; textFormatted.Replace(wxT("&"), wxT(""), false); //remove accelerator - dc.GetMultiLineTextExtent(textFormatted, &width, &height , NULL, &font); + dc.GetMultiLineTextExtent(textFormatted, &width, &height, nullptr, &font); return wxSize(width, height); } diff --git a/wx+/button.h b/wx+/button.h index 471a5b5a..bf741945 100644 --- a/wx+/button.h +++ b/wx+/button.h @@ -24,18 +24,18 @@ public: const wxValidator& validator = wxDefaultValidator, const wxString& name = wxButtonNameStr); - void setBitmapFront(const wxBitmap& bitmap, unsigned spaceAfter = 0); + void setBitmapFront(const wxBitmap& bitmap, size_t spaceAfter = 0); void setTextLabel( const wxString& text); - void setBitmapBack( const wxBitmap& bitmap, unsigned spaceBefore = 0); + void setBitmapBack( const wxBitmap& bitmap, size_t spaceBefore = 0); private: wxBitmap createBitmapFromText(const wxString& text); void refreshButtonLabel(); wxBitmap bitmapFront; - unsigned m_spaceAfter; + unsigned int m_spaceAfter; wxString textLabel; - unsigned m_spaceBefore; + unsigned int m_spaceBefore; wxBitmap bitmapBack; }; diff --git a/wx+/context_menu.h b/wx+/context_menu.h index 894da832..8f80fac2 100644 --- a/wx+/context_menu.h +++ b/wx+/context_menu.h @@ -27,12 +27,12 @@ namespace zen class ContextMenu : private wxEvtHandler { public: - void addItem(const wxString& label, const std::function<void()>& command, const wxBitmap* bmp = NULL, bool enabled = true) + void addItem(const wxString& label, const std::function<void()>& command, const wxBitmap* bmp = nullptr, bool enabled = true) { wxMenuItem* newItem = new wxMenuItem(&menu, wxID_ANY, label); - if (bmp) newItem->SetBitmap(*bmp); - if (!enabled) newItem->Enable(false); - menu.Append(newItem); //do NOT append item before setting bitmap! wxWidgets screws up for yet another crappy reason + if (bmp) newItem->SetBitmap(*bmp); //do not set AFTER appending item! wxWidgets screws up for yet another crappy reason + menu.Append(newItem); + if (!enabled) newItem->Enable(false); //do not enable BEFORE appending item! wxWidgets screws up for yet another crappy reason menu.Connect(newItem->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(ContextMenu::onSelection), new GenericCommand(command), /*pass ownership*/ this); } diff --git a/wx+/file_drop.h b/wx+/file_drop.h index c2a14423..0e9ba538 100644 --- a/wx+/file_drop.h +++ b/wx+/file_drop.h @@ -18,8 +18,8 @@ namespace zen void setupFileDrop(wxWindow& wnd); //2. register events: -//wnd.Connect (EVENT_DROP_FILE, FileDropEventHandler(MyDlg::OnFilesDropped), NULL, this); -//wnd.Disconnect(EVENT_DROP_FILE, FileDropEventHandler(MyDlg::OnFilesDropped), NULL, this); +//wnd.Connect (EVENT_DROP_FILE, FileDropEventHandler(MyDlg::OnFilesDropped), nullptr, this); +//wnd.Disconnect(EVENT_DROP_FILE, FileDropEventHandler(MyDlg::OnFilesDropped), nullptr, this); //3. do something: //void MyDlg::OnFilesDropped(FileDropEvent& event); diff --git a/wx+/format_unit.cpp b/wx+/format_unit.cpp index 0a054534..f6d2e5c2 100644 --- a/wx+/format_unit.cpp +++ b/wx+/format_unit.cpp @@ -35,7 +35,7 @@ std::wstring zen::filesizeToShortString(Int64 size) if (numeric::abs(size) <= 999) return replaceCpy(_P("1 Byte", "%x Bytes", to<int>(size)), L"%x", - toString<std::wstring>(size)); + numberTo<std::wstring>(size)); else { double filesize = to<double>(size); @@ -131,7 +131,7 @@ std::wstring zen::remainingTimeToShortString(double timeInSec) output = _P("1 day", "%x days", formattedTime); break; } - return replaceCpy(output, L"%x", zen::toString<std::wstring>(formattedTime)); + return replaceCpy(output, L"%x", zen::numberTo<std::wstring>(formattedTime)); } @@ -151,7 +151,7 @@ std::wstring zen::ffs_Impl::includeNumberSeparator(const std::wstring& number) if (i <= 3) break; i -= 3; - if (!cStringIsDigit(output[i - 1])) + if (!isDigit(output[i - 1])) break; output.insert(i, zen::getThousandsSeparator()); } @@ -164,10 +164,10 @@ std::wstring zen::ffs_Impl::includeNumberSeparator(const std::wstring& number) void zen::scrollToBottom(wxScrolledWindow* scrWindow) { int height = 0; - scrWindow->GetClientSize(NULL, &height); + scrWindow->GetClientSize(nullptr, &height); int pixelPerLine = 0; - scrWindow->GetScrollPixelsPerUnit(NULL, &pixelPerLine); + scrWindow->GetScrollPixelsPerUnit(nullptr, &pixelPerLine); if (height > 0 && pixelPerLine > 0) { @@ -203,7 +203,7 @@ std::wstring zen::utcToLocalTimeString(Int64 utcTime) &systemTimeUtc)) //__out LPSYSTEMTIME lpSystemTime return _("Error"); - if (!::SystemTimeToTzSpecificLocalTime(NULL, //__in_opt LPTIME_ZONE_INFORMATION lpTimeZone, + if (!::SystemTimeToTzSpecificLocalTime(nullptr, //__in_opt LPTIME_ZONE_INFORMATION lpTimeZone, &systemTimeUtc, //__in LPSYSTEMTIME lpUniversalTime, &systemTimeLocal)) //__out LPSYSTEMTIME lpLocalTime return _("Error"); diff --git a/wx+/format_unit.h b/wx+/format_unit.h index 361818cc..71501db7 100644 --- a/wx+/format_unit.h +++ b/wx+/format_unit.h @@ -57,7 +57,7 @@ std::wstring includeNumberSeparator(const std::wstring& number); template <class NumberType> inline std::wstring toStringSep(NumberType number) { - return ffs_Impl::includeNumberSeparator(zen::toString<std::wstring>(number)); + return ffs_Impl::includeNumberSeparator(zen::numberTo<std::wstring>(number)); } } diff --git a/wx+/graph.cpp b/wx+/graph.cpp index 7bbfa805..185121f1 100644 --- a/wx+/graph.cpp +++ b/wx+/graph.cpp @@ -20,6 +20,8 @@ using namespace numeric; const wxEventType zen::wxEVT_GRAPH_SELECTION = wxNewEventType(); +const std::shared_ptr<LabelFormatter> Graph2D::GraphAttributes::defaultFormat = std::make_shared<DecimalNumberFormatter>(); //for some buggy reason MSVC isn't able to use a temporary as a default argument instead + namespace { inline @@ -239,10 +241,10 @@ Graph2D::Graph2D(wxWindow* parent, const wxString& name) : wxPanel(parent, winid, pos, size, style, name) { - Connect(wxEVT_PAINT, wxPaintEventHandler(Graph2D::onPaintEvent), NULL, this); - Connect(wxEVT_SIZE, wxEventHandler(Graph2D::onRefreshRequired), NULL, this); + Connect(wxEVT_PAINT, wxPaintEventHandler(Graph2D::onPaintEvent), nullptr, this); + Connect(wxEVT_SIZE, wxEventHandler(Graph2D::onRefreshRequired), nullptr, this); //http://wiki.wxwidgets.org/Flicker-Free_Drawing - Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(Graph2D::onEraseBackGround), NULL, this); + Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(Graph2D::onEraseBackGround), nullptr, this); //SetDoubleBuffered(true); slow as hell! @@ -252,10 +254,10 @@ Graph2D::Graph2D(wxWindow* parent, SetBackgroundStyle(wxBG_STYLE_CUSTOM); #endif - Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(Graph2D::OnMouseLeftDown), NULL, this); - Connect(wxEVT_MOTION, wxMouseEventHandler(Graph2D::OnMouseMovement), NULL, this); - Connect(wxEVT_LEFT_UP, wxMouseEventHandler(Graph2D::OnMouseLeftUp), NULL, this); - Connect(wxEVT_MOUSE_CAPTURE_LOST, wxMouseCaptureLostEventHandler(Graph2D::OnMouseCaptureLost), NULL, this); + Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(Graph2D::OnMouseLeftDown), nullptr, this); + Connect(wxEVT_MOTION, wxMouseEventHandler(Graph2D::OnMouseMovement), nullptr, this); + Connect(wxEVT_LEFT_UP, wxMouseEventHandler(Graph2D::OnMouseLeftUp), nullptr, this); + Connect(wxEVT_MOUSE_CAPTURE_LOST, wxMouseCaptureLostEventHandler(Graph2D::OnMouseCaptureLost), nullptr, this); } @@ -483,11 +485,11 @@ void Graph2D::render(wxDC& dc) const wxPoint currentPos = activeSel->refCurrentPos() - dataOrigin; //normalize positions - restrict(startPos .x, 0, dataArea.width); //allow for one past the end(!) to enable "full range selections" - restrict(currentPos.x, 0, dataArea.width); // + confine(startPos .x, 0, dataArea.width); //allow for one past the end(!) to enable "full range selections" + confine(currentPos.x, 0, dataArea.width); // - restrict(startPos .y, 0, dataArea.height); // - restrict(currentPos.y, 0, dataArea.height); // + confine(startPos .y, 0, dataArea.height); // + confine(currentPos.y, 0, dataArea.height); // //save current selection as double coordinates activeSel->refSelection().from = SelectionBlock::Point(cvrtX.screenToReal(startPos.x + 0.5), //+0.5 start selection in the middle of a pixel @@ -547,7 +549,7 @@ void Graph2D::render(wxDC& dc) const if (!curve.empty()) { dc.SetPen(wxPen(j->second.color, j->second.lineWidth)); - dc.DrawLines(curve.size(), &curve[0]); + dc.DrawLines(static_cast<int>(curve.size()), &curve[0]); } } } diff --git a/wx+/graph.h b/wx+/graph.h index 19de4869..db52753b 100644 --- a/wx+/graph.h +++ b/wx+/graph.h @@ -93,12 +93,12 @@ double nextNiceNumber(double blockSize); //round to next number which is conveni struct DecimalNumberFormatter : public LabelFormatter { virtual double getOptimalBlockSize(double sizeProposed) const { return nextNiceNumber(sizeProposed); } - virtual wxString formatText(double value, double optimalBlockSize) const { return zen::toString<wxString>(value); } + virtual wxString formatText(double value, double optimalBlockSize) const { return zen::numberTo<wxString>(value); } }; //------------------------------------------------------------------------------------------------------------ //emit data selection event -//Usage: wnd.Connect(wxEVT_GRAPH_SELECTION, GraphSelectEventHandler(MyDlg::OnGraphSelection), NULL, this); +//Usage: wnd.Connect(wxEVT_GRAPH_SELECTION, GraphSelectEventHandler(MyDlg::OnGraphSelection), nullptr, this); // void MyDlg::OnGraphSelection(GraphSelectEvent& event); @@ -154,14 +154,14 @@ public: LineAttributes() : autoColor(true), lineWidth(2) {} LineAttributes& setColor(const wxColour& col) { color = col; autoColor = false; return *this; } - LineAttributes& setLineWidth(size_t width) { lineWidth = width; return *this; } + LineAttributes& setLineWidth(size_t width) { lineWidth = static_cast<int>(width); return *this; } private: friend class Graph2D; bool autoColor; wxColour color; - size_t lineWidth; + int lineWidth; }; void setData(const std::shared_ptr<GraphData>& data, const LineAttributes& attr = LineAttributes()); @@ -218,17 +218,19 @@ public: GraphAttributes& setAutoSize() { minXauto = true; maxXauto = true; minYauto = true; maxYauto = true; return *this; } - GraphAttributes& setLabelX(PosLabelX posX, size_t height = 25, const std::shared_ptr<LabelFormatter>& newLabelFmt = std::shared_ptr<LabelFormatter>(new DecimalNumberFormatter())) + static const std::shared_ptr<LabelFormatter> defaultFormat; + + GraphAttributes& setLabelX(PosLabelX posX, size_t height = 25, const std::shared_ptr<LabelFormatter>& newLabelFmt = defaultFormat) { labelposX = posX; - labelHeightX = height; + labelHeightX = static_cast<int>(height); labelFmtX = newLabelFmt; return *this; } - GraphAttributes& setLabelY(PosLabelY posY, size_t width = 60, const std::shared_ptr<LabelFormatter>& newLabelFmt = std::shared_ptr<LabelFormatter>(new DecimalNumberFormatter())) + GraphAttributes& setLabelY(PosLabelY posY, size_t width = 60, const std::shared_ptr<LabelFormatter>& newLabelFmt = defaultFormat) { labelposY = posY; - labelWidthY = width; + labelWidthY = static_cast<int>(width); labelFmtY = newLabelFmt; return *this; } @@ -249,11 +251,11 @@ public: double maxY; PosLabelX labelposX; - size_t labelHeightX; + int labelHeightX; std::shared_ptr<LabelFormatter> labelFmtX; PosLabelY labelposY; - size_t labelWidthY; + int labelWidthY; std::shared_ptr<LabelFormatter> labelFmtY; SelMode mouseSelMode; diff --git a/wx+/grid.cpp b/wx+/grid.cpp index bfb08eb1..10e427ef 100644 --- a/wx+/grid.cpp +++ b/wx+/grid.cpp @@ -105,7 +105,7 @@ private: //another fix for yet another poor wxWidgets implementation (wxDCClipper does *not* stack) -hash_map<wxDC*, wxRect> clippingAreas; +hash_map<wxDC*, wxRect> clippingAreas; //associate "active" clipping area with each DC class DcClipper { @@ -132,7 +132,7 @@ public: ~DcClipper() { dc_.DestroyClippingRegion(); - if (oldRect.get() != NULL) + if (oldRect.get() != nullptr) { dc_.SetClippingRegion(*oldRect); clippingAreas[&dc_] = *oldRect; @@ -159,13 +159,13 @@ const wxEventType zen::EVENT_GRID_MOUSE_RIGHT_UP = wxNewEventType(); const wxEventType zen::EVENT_GRID_SELECT_RANGE = wxNewEventType(); //---------------------------------------------------------------------------------------------------------------- -void GridData::renderRowBackgound(wxDC& dc, const wxRect& rect, int row, bool enabled, bool selected, bool hasFocus) +void GridData::renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected, bool hasFocus) { drawCellBackground(dc, rect, enabled, selected, hasFocus, getColorMainWinBackground()); } -void GridData::renderCell(Grid& grid, wxDC& dc, const wxRect& rect, int row, ColumnType colType) +void GridData::renderCell(Grid& grid, wxDC& dc, const wxRect& rect, size_t row, ColumnType colType) { wxRect rectTmp = drawCellBorder(dc, rect); @@ -175,7 +175,7 @@ void GridData::renderCell(Grid& grid, wxDC& dc, const wxRect& rect, int row, Col } -size_t GridData::getBestSize(wxDC& dc, int row, ColumnType colType) +size_t GridData::getBestSize(wxDC& dc, size_t row, ColumnType colType) { return dc.GetTextExtent(getValue(row, colType)).GetWidth() + 2 * COLUMN_BORDER_LEFT; //some border on left and right side } @@ -283,10 +283,10 @@ public: wxWindow(&parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS | wxBORDER_NONE, wxPanelNameStr), parent_(parent) { - Connect(wxEVT_PAINT, wxPaintEventHandler(SubWindow::onPaintEvent), NULL, this); - Connect(wxEVT_SIZE, wxEventHandler(SubWindow::onSizeEvent), NULL, this); + Connect(wxEVT_PAINT, wxPaintEventHandler(SubWindow::onPaintEvent), nullptr, this); + Connect(wxEVT_SIZE, wxEventHandler(SubWindow::onSizeEvent), nullptr, this); //http://wiki.wxwidgets.org/Flicker-Free_Drawing - Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(SubWindow::onEraseBackGround), NULL, this); + Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(SubWindow::onEraseBackGround), nullptr, this); //SetDoubleBuffered(true); slow as hell! @@ -296,28 +296,29 @@ public: SetBackgroundStyle(wxBG_STYLE_CUSTOM); #endif - Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(SubWindow::onFocus), NULL, this); - Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(SubWindow::onFocus), NULL, this); - - Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(SubWindow::onMouseLeftDown ), NULL, this); - Connect(wxEVT_LEFT_UP, wxMouseEventHandler(SubWindow::onMouseLeftUp ), NULL, this); - Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(SubWindow::onMouseLeftDouble), NULL, this); - Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(SubWindow::onMouseRightDown ), NULL, this); - Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(SubWindow::onMouseRightUp ), NULL, this); - Connect(wxEVT_MOTION, wxMouseEventHandler(SubWindow::onMouseMovement ), NULL, this); - Connect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(SubWindow::onLeaveWindow ), NULL, this); - Connect(wxEVT_MOUSE_CAPTURE_LOST, wxMouseCaptureLostEventHandler(SubWindow::onMouseCaptureLost), NULL, this); - - Connect(wxEVT_CHAR, wxKeyEventHandler(SubWindow::onChar ), NULL, this); - Connect(wxEVT_KEY_UP, wxKeyEventHandler(SubWindow::onKeyUp ), NULL, this); - Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(SubWindow::onKeyDown), NULL, this); + Connect(wxEVT_SET_FOCUS, wxFocusEventHandler(SubWindow::onFocus), nullptr, this); + Connect(wxEVT_KILL_FOCUS, wxFocusEventHandler(SubWindow::onFocus), nullptr, this); + Connect(wxEVT_CHILD_FOCUS, wxEventHandler(SubWindow::onChildFocus), nullptr, this); + + Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(SubWindow::onMouseLeftDown ), nullptr, this); + Connect(wxEVT_LEFT_UP, wxMouseEventHandler(SubWindow::onMouseLeftUp ), nullptr, this); + Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(SubWindow::onMouseLeftDouble), nullptr, this); + Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(SubWindow::onMouseRightDown ), nullptr, this); + Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(SubWindow::onMouseRightUp ), nullptr, this); + Connect(wxEVT_MOTION, wxMouseEventHandler(SubWindow::onMouseMovement ), nullptr, this); + Connect(wxEVT_LEAVE_WINDOW, wxMouseEventHandler(SubWindow::onLeaveWindow ), nullptr, this); + Connect(wxEVT_MOUSE_CAPTURE_LOST, wxMouseCaptureLostEventHandler(SubWindow::onMouseCaptureLost), nullptr, this); + + Connect(wxEVT_CHAR, wxKeyEventHandler(SubWindow::onChar ), nullptr, this); + Connect(wxEVT_KEY_UP, wxKeyEventHandler(SubWindow::onKeyUp ), nullptr, this); + Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(SubWindow::onKeyDown), nullptr, this); } Grid& refParent() { return parent_; } const Grid& refParent() const { return parent_; } template <class T> - bool sendEventNow(T& event) //return "true" if a suitable event handler function was found and executed, and the function did not call wxEvent::Skip. + bool sendEventNow(T&& event) //take both "rvalue + lvalues", return "true" if a suitable event handler function was found and executed, and the function did not call wxEvent::Skip. { if (wxEvtHandler* evtHandler = parent_.GetEventHandler()) return evtHandler->ProcessEvent(event); @@ -333,7 +334,7 @@ protected: if (text != oldText) { if (text.IsEmpty()) - SetToolTip(NULL); //wxGTK doesn't allow wxToolTip with empty text! + SetToolTip(nullptr); //wxGTK doesn't allow wxToolTip with empty text! else { //wxWidgets bug: tooltip multiline property is defined by first tooltip text containing newlines or not (same is true for maximum width) @@ -351,6 +352,7 @@ private: virtual void render(wxDC& dc, const wxRect& rect) = 0; virtual void onFocus(wxFocusEvent& event) { event.Skip(); } + virtual void onChildFocus(wxEvent& event) {} //wxGTK::wxScrolledWindow automatically scrolls to child window when child gets focus -> prevent! virtual void onMouseLeftDown (wxMouseEvent& event) { event.Skip(); } virtual void onMouseLeftUp (wxMouseEvent& event) { event.Skip(); } @@ -437,51 +439,49 @@ public: SubWindow(parent), rowHeight(DEFAULT_ROW_HEIGHT) {} - int getBestWidth(int rowFrom, int rowTo) + int getBestWidth(ptrdiff_t rowFrom, ptrdiff_t rowTo) { wxClientDC dc(this); int bestWidth = 0; - for (int i = rowFrom; i <= rowTo; ++i) + for (ptrdiff_t i = rowFrom; i <= rowTo; ++i) bestWidth = std::max(bestWidth, dc.GetTextExtent(formatRow(i)).GetWidth() + 2 * ROW_LABEL_BORDER); return bestWidth; } - int getLogicalHeight() const { return refParent().getRowCount() * rowHeight; } + size_t getLogicalHeight() const { return refParent().getRowCount() * rowHeight; } - int getRowAtPos(int posY) const //returns < 0 if row not found + ptrdiff_t getRowAtPos(ptrdiff_t posY) const //returns < 0 if row not found { if (posY >= 0 && rowHeight > 0) { - const int row = posY / rowHeight; - if (row < static_cast<int>(refParent().getRowCount())) + const size_t row = posY / rowHeight; + if (row < refParent().getRowCount()) return row; } return -1; } - int getRowHeight() const { return rowHeight; } - void setRowHeight(int height) { rowHeight = height; } + ptrdiff_t getRowHeight() const { return std::max<ptrdiff_t>(1, rowHeight); } //guarantees to return size >= 1 ! + void setRowHeight(size_t height) { rowHeight = height; } - wxRect getRowLabelArea(int row) const //returns empty rect if row not found + wxRect getRowLabelArea(ptrdiff_t row) const { return wxRect(wxPoint(0, rowHeight * row), wxSize(GetClientSize().GetWidth(), rowHeight)); } - std::pair<int, int> getRowsOnClient(const wxRect& clientRect) const //returns range [begin, end) + std::pair<ptrdiff_t, ptrdiff_t> getRowsOnClient(const wxRect& clientRect) const //returns range [begin, end) { const int yFrom = refParent().CalcUnscrolledPosition(clientRect.GetTopLeft ()).y; const int yTo = refParent().CalcUnscrolledPosition(clientRect.GetBottomRight()).y; - const int rowBegin = std::max(yFrom / rowHeight, 0); - const int rowEnd = std::min((yTo / rowHeight) + 1, static_cast<int>(refParent().getRowCount())); - - return std::make_pair(rowBegin, rowEnd); + return std::make_pair(std::max<ptrdiff_t>(yFrom / rowHeight, 0), + std::min<ptrdiff_t>((yTo / rowHeight) + 1, refParent().getRowCount())); } private: - static wxString formatRow(int row) { return toStringSep(row + 1); } //convert number to std::wstring including thousands separator + static wxString formatRow(size_t row) { return toStringSep(row + 1); } //convert number to std::wstring including thousands separator virtual bool AcceptsFocus() const { return false; } @@ -497,9 +497,8 @@ private: dc.SetFont(labelFont); dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)); - const std::pair<int, int> rowRange = getRowsOnClient(rect); //returns range [begin, end) - - for (int row = rowRange.first; row < rowRange.second; ++row) + auto rowRange = getRowsOnClient(rect); //returns range [begin, end) + for (auto row = rowRange.first; row < rowRange.second; ++row) { wxRect singleLabelArea = getRowLabelArea(row); if (singleLabelArea.GetHeight() > 0) @@ -510,7 +509,7 @@ private: } } - void drawRowLabel(wxDC& dc, const wxRect& rect, int row) + void drawRowLabel(wxDC& dc, const wxRect& rect, size_t row) { //clearArea(dc, rect, getColorRowLabel()); dc.GradientFillLinear(rect, COLOR_LABEL_GRADIENT_FROM, COLOR_LABEL_GRADIENT_TO, wxWEST); //clear overlapping cells @@ -540,7 +539,7 @@ private: virtual void onMouseMovement(wxMouseEvent& event) { refParent().redirectRowLabelEvent(event); } virtual void onMouseLeftUp (wxMouseEvent& event) { refParent().redirectRowLabelEvent(event); } - int rowHeight; + ptrdiff_t rowHeight; }; @@ -549,7 +548,7 @@ namespace class ColumnResizing { public: - ColumnResizing(wxWindow& wnd, int col, size_t compPos, int startWidth, int clientPosX) : + ColumnResizing(wxWindow& wnd, size_t col, size_t compPos, ptrdiff_t startWidth, int clientPosX) : wnd_(wnd), col_(col), compPos_(compPos), @@ -557,24 +556,24 @@ public: clientPosX_(clientPosX) { wnd_.CaptureMouse(); } ~ColumnResizing() { if (wnd_.HasCapture()) wnd_.ReleaseMouse(); } - int getColumn () const { return col_; } - size_t getComponentPos() const { return compPos_; } - int getStartWidth () const { return startWidth_; } - int getStartPosX () const { return clientPosX_; } + size_t getColumn () const { return col_; } + size_t getComponentPos() const { return compPos_; } + ptrdiff_t getStartWidth () const { return startWidth_; } + int getStartPosX () const { return clientPosX_; } private: wxWindow& wnd_; - const int col_; - const size_t compPos_; - const int startWidth_; - const int clientPosX_; + const size_t col_; + const size_t compPos_; + const ptrdiff_t startWidth_; + const int clientPosX_; }; class ColumnMove { public: - ColumnMove(wxWindow& wnd, int colFrom, size_t compPos, int clientPosX) : + ColumnMove(wxWindow& wnd, size_t colFrom, size_t compPos, int clientPosX) : wnd_(wnd), colFrom_(colFrom), compPos_(compPos), @@ -583,19 +582,19 @@ public: singleClick_(true) { wnd_.CaptureMouse(); } ~ColumnMove() { if (wnd_.HasCapture()) wnd_.ReleaseMouse(); } - int getColumnFrom() const { return colFrom_; } - int& refColumnTo() { return colTo_; } - size_t getComponentPos() const { return compPos_; } - int getStartPosX () const { return clientPosX_; } + 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_; } - bool setRealMove() { return singleClick_ = false; } + void setRealMove() { singleClick_ = false; } private: wxWindow& wnd_; - const int colFrom_; + const size_t colFrom_; const size_t compPos_; - int colTo_; + size_t colTo_; const int clientPosX_; bool singleClick_; }; @@ -607,7 +606,7 @@ private: class Grid::ColLabelWin : public SubWindow { public: - ColLabelWin(Grid& parent) : SubWindow(parent), highlight(-1, 0) {} + ColLabelWin(Grid& parent) : SubWindow(parent) {} private: virtual bool AcceptsFocus() const { return false; } @@ -643,13 +642,14 @@ private: } } - void drawColumnLabel(wxDC& dc, const wxRect& rect, int col, ColumnType colType, size_t compPos) + void drawColumnLabel(wxDC& dc, const wxRect& rect, size_t col, ColumnType colType, size_t compPos) { if (auto dataView = refParent().getDataProvider(compPos)) { const bool isHighlighted = activeResizing ? col == activeResizing->getColumn () && compPos == activeResizing->getComponentPos() : //highlight column on mouse-over activeMove ? col == activeMove ->getColumnFrom() && compPos == activeMove ->getComponentPos() : - /**/ col == highlight.first && compPos == highlight.second; + highlight ? col == highlight->first && compPos == highlight->second : + false; DcClipper clip(dc, rect); dataView->renderColumnLabel(refParent(), dc, rect, colType, isHighlighted); @@ -680,9 +680,9 @@ private: { if (event.LeftDClick()) //auto-size visible range on double-click { - const int bestWidth = refParent().getBestColumnSize(action->col, action->compPos); //return -1 on error + const auto bestWidth = refParent().getBestColumnSize(action->col, action->compPos); //return -1 on error if (bestWidth >= 0) - refParent().setColWidth(action->col, action->compPos, std::max(COLUMN_MIN_WIDTH, bestWidth)); + refParent().setColWidth(action->col, action->compPos, std::max<ptrdiff_t>(COLUMN_MIN_WIDTH, bestWidth)); } else { @@ -707,8 +707,8 @@ private: { if (refParent().columnMoveAllowed(compPos)) { - const int colFrom = activeMove->getColumnFrom(); - int colTo = activeMove->refColumnTo(); + const auto colFrom = activeMove->getColumnFrom(); + auto colTo = activeMove->refColumnTo(); if (colTo > colFrom) //simulate "colFrom" deletion --colTo; @@ -718,12 +718,8 @@ private: } else //notify single label click { - const Opt<ColumnType> colType = refParent().colToType(activeMove->getColumnFrom(), compPos); - if (colType) - { - GridClickEvent clickEvent(EVENT_GRID_COL_LABEL_MOUSE_LEFT, event, -1, *colType, compPos); - sendEventNow(clickEvent); - } + if (const Opt<ColumnType> colType = refParent().colToType(activeMove->getColumnFrom(), compPos)) + sendEventNow(GridClickEvent(EVENT_GRID_COL_LABEL_MOUSE_LEFT, event, -1, *colType, compPos)); } activeMove.reset(); } @@ -747,19 +743,14 @@ private: if (action && action->wantResize) { //auto-size visible range on double-click - const int bestWidth = refParent().getBestColumnSize(action->col, action->compPos); //return -1 on error + const auto bestWidth = refParent().getBestColumnSize(action->col, action->compPos); //return -1 on error if (bestWidth >= 0) { - const size_t newWidth = std::max(COLUMN_MIN_WIDTH, bestWidth); + const auto newWidth = std::max<ptrdiff_t>(COLUMN_MIN_WIDTH, bestWidth); refParent().setColWidth(action->col, action->compPos, newWidth); - const Opt<ColumnType> colType = refParent().colToType(action->col, action->compPos); - if (colType) - { - //notify column resize - GridColumnResizeEvent sizeEvent(newWidth, *colType, action->compPos); - sendEventNow(sizeEvent); - } + if (const Opt<ColumnType> colType = refParent().colToType(action->col, action->compPos)) + sendEventNow(GridColumnResizeEvent(newWidth, *colType, action->compPos)); //notify column resize } } event.Skip(); @@ -769,23 +760,18 @@ private: { if (activeResizing) { - const int col = activeResizing->getColumn(); - const size_t compPos = activeResizing->getComponentPos(); + const auto col = activeResizing->getColumn(); + const auto compPos = activeResizing->getComponentPos(); if (Opt<size_t> colWidth = refParent().getAbsoluteWidth(col, compPos)) { - const int newWidth = std::max(COLUMN_MIN_WIDTH, activeResizing->getStartWidth() + event.GetPosition().x - activeResizing->getStartPosX()); - if (newWidth != static_cast<int>(*colWidth)) + const size_t newWidth = std::max<ptrdiff_t>(COLUMN_MIN_WIDTH, activeResizing->getStartWidth() + event.GetPosition().x - activeResizing->getStartPosX()); + if (newWidth != *colWidth) { refParent().setColWidth(col, compPos, newWidth); - const Opt<ColumnType> colType = refParent().colToType(col, compPos); - if (colType) - { - //notify column resize - GridColumnResizeEvent sizeEvent(newWidth, *colType, compPos); - sendEventNow(sizeEvent); - } + if (const Opt<ColumnType> colType = refParent().colToType(col, compPos)) + sendEventNow(GridColumnResizeEvent(static_cast<int>(newWidth), *colType, compPos)); //notify column resize refParent().Refresh(); } @@ -798,18 +784,16 @@ private: { activeMove->setRealMove(); - const int col = refParent().clientPosToMoveTargetColumn(event.GetPosition(), activeMove->getComponentPos()); + const auto col = refParent().clientPosToMoveTargetColumn(event.GetPosition(), activeMove->getComponentPos()); if (col >= 0) activeMove->refColumnTo() = col; } } else { - const Opt<ColAction> action = refParent().clientPosToColumnAction(event.GetPosition()); - if (action) + if (const Opt<ColAction> action = refParent().clientPosToColumnAction(event.GetPosition())) { - highlight.first = action->col; - highlight.second = action->compPos; + highlight.reset(new std::pair<size_t, size_t>(action->col, action->compPos)); if (action->wantResize) SetCursor(wxCURSOR_SIZEWE); //set window-local only! :) @@ -818,21 +802,18 @@ private: } else { - highlight.first = -1; + highlight.reset(); SetCursor(*wxSTANDARD_CURSOR); } } - //change tooltip + //update tooltip const wxString toolTip = [&]() -> wxString { const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition()); - - const auto colInfo = refParent().getColumnAtPos(absPos.x); //returns (column type, compPos), column < 0 if not found - if (colInfo) + if (const auto colInfo = refParent().getColumnAtPos(absPos.x)) //returns (column type, compPos) { - auto prov = refParent().getDataProvider(colInfo->second); - if (prov) + if (auto prov = refParent().getDataProvider(colInfo->second)) return prov->getToolTip(colInfo->first); } return wxString(); @@ -845,30 +826,24 @@ private: virtual void onLeaveWindow(wxMouseEvent& event) { - highlight.first = -1; //onLeaveWindow() does not respect mouse capture! -> however highlight is drawn unconditionally during move/resize! + highlight.reset(); //onLeaveWindow() does not respect mouse capture! -> however highlight is drawn unconditionally during move/resize! Refresh(); event.Skip(); } virtual void onMouseRightDown(wxMouseEvent& event) { - const Opt<ColAction> action = refParent().clientPosToColumnAction(event.GetPosition()); - if (action) + if (const Opt<ColAction> action = refParent().clientPosToColumnAction(event.GetPosition())) { - const Opt<ColumnType> colType = refParent().colToType(action->col, action->compPos); - if (colType) - { - //notify right click - GridClickEvent clickEvent(EVENT_GRID_COL_LABEL_MOUSE_RIGHT, event, -1, *colType, action->compPos); - sendEventNow(clickEvent); - } + 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 } event.Skip(); } std::unique_ptr<ColumnResizing> activeResizing; std::unique_ptr<ColumnMove> activeMove; - std::pair<int, size_t> highlight; //(column, component) mouse-over, row < 0 if none + std::unique_ptr<std::pair<size_t, size_t>> highlight; //(column, component) mouse-over }; //---------------------------------------------------------------------------------------------------------------- @@ -882,19 +857,18 @@ public: ColLabelWin& colLabelWin) : SubWindow(parent), rowLabelWin_(rowLabelWin), colLabelWin_(colLabelWin), - cursor(-1, -1), - selectionAnchor(-1) {} + selectionAnchor(0) {} - void makeRowVisible(int row) + void makeRowVisible(size_t row) { const wxRect labelRect = rowLabelWin_.getRowLabelArea(row); //returns empty rect if column not found if (labelRect.height > 0) { int scrollPosX = 0; - refParent().GetViewStart(&scrollPosX, NULL); + refParent().GetViewStart(&scrollPosX, nullptr); int pixelsPerUnitY = 0; - refParent().GetScrollPixelsPerUnit(NULL, &pixelsPerUnitY); + refParent().GetScrollPixelsPerUnit(nullptr, &pixelsPerUnitY); if (pixelsPerUnitY <= 0) return; const int clientPosY = refParent().CalcScrolledPosition(labelRect.GetTopLeft()).y; @@ -925,12 +899,12 @@ public: } } - void setCursor(int row, size_t compPos) + void setCursor(size_t row, size_t compPos) { cursor = std::make_pair(row, compPos); selectionAnchor = row; } - std::pair<int, size_t> getCursor() const { return cursor; } // (row, component position) + std::pair<size_t, size_t> getCursor() const { return cursor; } // (row, component position) private: virtual void render(wxDC& dc, const wxRect& rect) @@ -956,8 +930,8 @@ private: std::vector<std::vector<VisibleColumn>> compAbsWidths = refParent().getAbsoluteWidths(); //resolve negative/stretched widths for (auto iterComp = compAbsWidths.begin(); iterComp != compAbsWidths.end(); ++iterComp) { - const int compWidth = std::accumulate(iterComp->begin(), iterComp->end(), 0, - [](int val, const VisibleColumn& vc) { return val + vc.width_; }); + const ptrdiff_t compWidth = std::accumulate(iterComp->begin(), iterComp->end(), static_cast<ptrdiff_t>(0), + [](ptrdiff_t sum, const VisibleColumn& vc) { return sum + vc.width_; }); const size_t compPos = iterComp - compAbsWidths.begin(); if (auto prov = refParent().getDataProvider(compPos)) @@ -1017,14 +991,9 @@ private: virtual void onMouseLeftDouble(wxMouseEvent& event) { const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition()); - const int row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 if no row at this position - const auto colInfo = refParent().getColumnAtPos(absPos.x); //returns (column type, compPos), column < 0 if not found - if (colInfo) - { - //notify event - GridClickEvent mouseEvent(EVENT_GRID_MOUSE_LEFT_DOUBLE, event, row, colInfo->first, colInfo->second); - sendEventNow(mouseEvent); - } + const auto row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 if no row at this position + if (const auto colInfo = refParent().getColumnAtPos(absPos.x)) //returns (column type, compPos) + sendEventNow(GridClickEvent(EVENT_GRID_MOUSE_LEFT_DOUBLE, event, row, colInfo->first, colInfo->second)); event.Skip(); } @@ -1035,10 +1004,10 @@ private: const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition()); - const int row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 if no row at this position - const auto colInfo = refParent().getColumnAtPos(absPos.x); //returns (column type, compPos), column < 0 if not found + const ptrdiff_t row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 if no row at this position + const auto colInfo = refParent().getColumnAtPos(absPos.x); //returns (column type, compPos) const ColumnType colType = colInfo ? colInfo->first : DUMMY_COLUMN_TYPE; - const int compPos = colInfo ? colInfo->second : -1; + const ptrdiff_t compPos = colInfo ? colInfo->second : -1; //notify event GridClickEvent mouseEvent(event.RightDown() ? EVENT_GRID_MOUSE_RIGHT_DOWN : EVENT_GRID_MOUSE_LEFT_DOWN, event, row, colType, compPos); @@ -1053,26 +1022,28 @@ private: { if (row >= 0 && compPos >= 0) activeSelection.reset(new MouseSelection(*this, row, compPos, !refParent().isSelected(row, compPos))); - selectionAnchor = row; + selectionAnchor = cursor.first; //[!] anchor is coupled with cursor, *not* row } else if (event.ShiftDown()) { if (row >= 0 && compPos >= 0) activeSelection.reset(new MouseSelection(*this, selectionAnchor, compPos, true)); + else + selectionAnchor = cursor.first; refParent().clearSelectionAll(); } else { if (row >= 0 && compPos >= 0) activeSelection.reset(new MouseSelection(*this, row, compPos, true)); - selectionAnchor = row; + selectionAnchor = cursor.first; refParent().clearSelectionAll(); } } Refresh(); } - event.Skip(); //allow changin focus + event.Skip(); //allow changing focus } void onMouseUp(wxMouseEvent& event) @@ -1081,10 +1052,10 @@ private: if (activeSelection) { - const int rowFrom = activeSelection->getStartRow(); - const int rowTo = activeSelection->getCurrentRow(); - const size_t compPos = activeSelection->getComponentPos(); - const bool positive = activeSelection->isPositiveSelect(); + const auto rowFrom = activeSelection->getStartRow(); + const auto rowTo = activeSelection->getCurrentRow(); + const auto compPos = activeSelection->getComponentPos(); + const bool positive = activeSelection->isPositiveSelect(); refParent().selectRange(rowFrom, rowTo, compPos, positive); cursor.first = activeSelection->getCurrentRow(); //slight deviation from Explorer: change cursor while dragging mouse! -> unify behavior with shift + direction keys @@ -1095,15 +1066,14 @@ private: //this one may point to row which is not in visible area! const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition()); - const int row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 if no row at this position - const auto colInfo = refParent().getColumnAtPos(absPos.x); //returns (column type, compPos), column < 0 if not found + const auto row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 if no row at this position + 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 int compPos = colInfo ? colInfo->second : 0; + const size_t compPos = colInfo ? colInfo->second : 0; //notify event - GridClickEvent mouseEvent(event.RightUp() ? EVENT_GRID_MOUSE_RIGHT_UP : EVENT_GRID_MOUSE_LEFT_UP, event, row, colType, compPos); - sendEventNow(mouseEvent); + sendEventNow(GridClickEvent(event.RightUp() ? EVENT_GRID_MOUSE_RIGHT_UP : EVENT_GRID_MOUSE_LEFT_UP, event, row, colType, compPos)); Refresh(); event.Skip(); //allow changing focus @@ -1126,12 +1096,11 @@ private: { const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition()); - const int row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 if no row at this position - const auto colInfo = refParent().getColumnAtPos(absPos.x); //returns (column type, compPos), column < 0 if not found + const auto row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 if no row at this position + const auto colInfo = refParent().getColumnAtPos(absPos.x); //returns (column type, compPos) if (colInfo && row >= 0) { - auto prov = refParent().getDataProvider(colInfo->second); - if (prov) + if (auto prov = refParent().getDataProvider(colInfo->second)) return prov->getToolTip(row, colInfo->first); } return wxString(); @@ -1157,27 +1126,33 @@ private: keyCode = WXK_NUMPAD_LEFT; } - const int rowCount = refParent().getRowCount(); + const ptrdiff_t rowCount = refParent().getRowCount(); + if (rowCount <= 0 || refParent().comp.empty()) + { + event.Skip(); + return; + } - auto setSingleSelection = [&](int row, int compPos) + auto setSingleSelection = [&](ptrdiff_t row, ptrdiff_t compPos) { - numeric::restrict(row, 0, rowCount - 1); - numeric::restrict(compPos, 0, static_cast<int>(refParent().comp.size()) - 1); - refParent().setGridCursor(row, compPos); + 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! }; - auto setSelectionRange = [&](int row) + auto setSelectionRange = [&](ptrdiff_t row) { - numeric::restrict(row, 0, rowCount - 1); + //unlike "setSingleSelection" this function doesn't seem to belong into Grid: management of selectionAnchor should be local - cursor.first = row; - if (selectionAnchor < 0) - selectionAnchor = row; - this->makeRowVisible(row); + numeric::confine<ptrdiff_t>(row, 0, rowCount - 1); auto& comp = refParent().comp; std::for_each(comp.begin(), comp.end(), [](Grid::Component& c) { c.selection.clear(); }); //clear selection, do NOT fire event refParent().selectRange(selectionAnchor, row, cursor.second); //set new selection + fire event + + cursor.first = row; //don't call setCursor() since it writes to "selectionAnchor"! + this->makeRowVisible(row); + refParent().Refresh(); }; switch (keyCode) @@ -1190,7 +1165,7 @@ private: refParent().scrollDelta(0, -1); else setSingleSelection(cursor.first - 1, cursor.second); - break; + return; //swallow event: wxScrolledWindow, wxWidgets 2.9.3 on Kubuntu x64 processes arrow keys: prevent this! case WXK_DOWN: case WXK_NUMPAD_DOWN: @@ -1200,7 +1175,7 @@ private: refParent().scrollDelta(0, 1); else setSingleSelection(cursor.first + 1, cursor.second); - break; + return; //swallow event case WXK_LEFT: case WXK_NUMPAD_LEFT: @@ -1210,7 +1185,7 @@ private: ; else setSingleSelection(cursor.first, cursor.second - 1); - break; + return; case WXK_RIGHT: case WXK_NUMPAD_RIGHT: @@ -1220,7 +1195,7 @@ private: ; else setSingleSelection(cursor.first, cursor.second + 1); - break; + return; case WXK_HOME: case WXK_NUMPAD_HOME: @@ -1230,7 +1205,7 @@ private: setSingleSelection(0, 0); else setSingleSelection(0, cursor.second); - break; + return; case WXK_END: case WXK_NUMPAD_END: @@ -1240,7 +1215,7 @@ private: setSingleSelection(rowCount - 1, refParent().comp.size() - 1); else setSingleSelection(rowCount - 1, cursor.second); - break; + return; case WXK_PAGEUP: case WXK_NUMPAD_PAGEUP: @@ -1250,7 +1225,7 @@ private: ; else setSingleSelection(cursor.first - GetClientSize().GetHeight() / rowLabelWin_.getRowHeight(), cursor.second); - break; + return; case WXK_PAGEDOWN: case WXK_NUMPAD_PAGEDOWN: @@ -1260,7 +1235,7 @@ private: ; else setSingleSelection(cursor.first + GetClientSize().GetHeight() / rowLabelWin_.getRowHeight(), cursor.second); - break; + return; case 'A': //Ctrl + A - select all if (event.ControlDown()) @@ -1270,10 +1245,9 @@ private: case WXK_NUMPAD_ADD: //CTRL + '+' - auto-size all if (event.ControlDown()) refParent().autoSizeColumns(cursor.second); - break; + return; } - Refresh(); event.Skip(); } @@ -1282,26 +1256,24 @@ private: class MouseSelection : private wxEvtHandler { public: - MouseSelection(MainWin& wnd, - int rowStart, - size_t compPos, - bool positiveSelect) : wnd_(wnd), rowStart_(rowStart), compPos_(compPos), rowCurrent_(rowStart), positiveSelect_(positiveSelect), toScrollX(0), toScrollY(0), tickCountLast(clock()) + MouseSelection(MainWin& wnd, ptrdiff_t rowStart, size_t compPos, bool positiveSelect) : + wnd_(wnd), rowStart_(rowStart), compPos_(compPos), rowCurrent_(rowStart), positiveSelect_(positiveSelect), toScrollX(0), toScrollY(0), tickCountLast(clock()) { wnd_.CaptureMouse(); - timer.Connect(wxEVT_TIMER, wxEventHandler(MouseSelection::onTimer), NULL, this); + timer.Connect(wxEVT_TIMER, wxEventHandler(MouseSelection::onTimer), nullptr, this); timer.Start(100); //timer interval in ms evalMousePos(); } ~MouseSelection() { if (wnd_.HasCapture()) wnd_.ReleaseMouse(); } - int getStartRow () const { return rowStart_; } - size_t getComponentPos () const { return compPos_; } - int getCurrentRow () const { return rowCurrent_; } - bool isPositiveSelect() const { return positiveSelect_; } //are we selecting or unselecting? + ptrdiff_t getStartRow () const { return rowStart_; } + size_t getComponentPos () const { return compPos_; } + ptrdiff_t getCurrentRow () const { return rowCurrent_; } + bool isPositiveSelect() const { return positiveSelect_; } //are we selecting or unselecting? void evalMousePos() { - const clock_t now = clock(); + const clock_t now = std::clock(); const double deltaTime = static_cast<double>(now - tickCountLast) / CLOCKS_PER_SEC; //unit: [sec] tickCountLast = now; @@ -1316,7 +1288,7 @@ private: clientPos.x >= clientSize.GetWidth() ? clientPos.x - (clientSize.GetWidth() - 1) : 0; int pixelsPerUnitY = 0; - wnd_.refParent().GetScrollPixelsPerUnit(NULL, &pixelsPerUnitY); + wnd_.refParent().GetScrollPixelsPerUnit(nullptr, &pixelsPerUnitY); if (pixelsPerUnitY <= 0) return; const double mouseDragSpeedIncScrollU = pixelsPerUnitY > 0 ? MOUSE_DRAG_ACCELERATION * wnd_.rowLabelWin_.getRowHeight() / pixelsPerUnitY : 0; //unit: [scroll units / (pixel * sec)] @@ -1345,14 +1317,14 @@ private: { //select current row *after* scrolling wxPoint clientPosTrimmed = clientPos; - numeric::restrict(clientPosTrimmed.y, 0, clientSize.GetHeight() - 1); //do not select row outside client window! + numeric::confine(clientPosTrimmed.y, 0, clientSize.GetHeight() - 1); //do not select row outside client window! wxPoint absPos = wnd_.refParent().CalcUnscrolledPosition(clientPosTrimmed); - int currentRow = wnd_.rowLabelWin_.getRowAtPos(absPos.y); //return -1 if no row at this position //make sure "current row" is always at a valid position while moving! + ptrdiff_t currentRow = wnd_.rowLabelWin_.getRowAtPos(absPos.y); //return -1 if no row at this position if (currentRow < 0) - currentRow = static_cast<int>(wnd_.refParent().getRowCount()) - 1; //seems, we hit the empty space at the end + currentRow = wnd_.refParent().getRowCount() - 1; //seems, we hit the empty space at the end: empty size covered! if (currentRow >= 0 && rowCurrent_ != currentRow) { @@ -1366,9 +1338,9 @@ private: void onTimer(wxEvent& event) { evalMousePos(); } MainWin& wnd_; - const int rowStart_; + const ptrdiff_t rowStart_; const size_t compPos_; - int rowCurrent_; + ptrdiff_t rowCurrent_; const bool positiveSelect_; wxTimer timer; double toScrollX; //count outstanding scroll units to scroll while dragging mouse @@ -1391,8 +1363,8 @@ private: std::unique_ptr<MouseSelection> activeSelection; //bound while user is selecting with mouse - std::pair<int, int> cursor; //(row, component position) -1 if none - int selectionAnchor; //-1 if none + std::pair<ptrdiff_t, ptrdiff_t> cursor; //(row, component position), always valid! still unsigned type to facilitate "onKeyDown()" + size_t selectionAnchor; }; //---------------------------------------------------------------------------------------------------------------- @@ -1411,9 +1383,9 @@ Grid::Grid(wxWindow* parent, comp(1), colSizeOld(0) { - Connect(wxEVT_PAINT, wxPaintEventHandler(Grid::onPaintEvent ), NULL, this); - Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(Grid::onEraseBackGround), NULL, this); - Connect(wxEVT_SIZE, wxEventHandler (Grid::onSizeEvent ), NULL, this); + Connect(wxEVT_PAINT, wxPaintEventHandler(Grid::onPaintEvent ), nullptr, this); + Connect(wxEVT_ERASE_BACKGROUND, wxEraseEventHandler(Grid::onEraseBackGround), nullptr, this); + Connect(wxEVT_SIZE, wxEventHandler (Grid::onSizeEvent ), nullptr, this); cornerWin_ = new CornerWin (*this); // rowLabelWin_ = new RowLabelWin(*this); //owership handled by "this" @@ -1440,7 +1412,6 @@ void Grid::updateWindowSizes(bool updateScrollbar) GetClientRect(); -> possibly trimmed by scrollbars /|\ mainWin_->GetClientSize() -> also trimmed, since it's a sub-window ! - */ //update scrollbars: showing/hiding scrollbars changes client size! @@ -1454,7 +1425,7 @@ void Grid::updateWindowSizes(bool updateScrollbar) int scrollPosY = 0; GetViewStart(&scrollPosX, &scrollPosY); //preserve current scroll position - const int pixPerScrollUnitY = std::max(1, rowLabelWin_->getRowHeight()); + const int pixPerScrollUnitY = rowLabelWin_->getRowHeight(); const int pixPerScrollUnitX = pixPerScrollUnitY; const int scrollUnitsX = std::ceil(static_cast<double>( getMinAbsoluteWidthTotal()) / pixPerScrollUnitX); @@ -1462,7 +1433,7 @@ void Grid::updateWindowSizes(bool updateScrollbar) SetScrollbars(pixPerScrollUnitX, pixPerScrollUnitY, //another abysmal wxWidgets design decision: why is precision needlessly reduced to "pixelsPerUnit"???? scrollUnitsX, scrollUnitsY, - scrollPosX, scrollPosY); + scrollPosX, scrollPosY); } const wxRect clientRect = GetClientRect(); @@ -1472,16 +1443,16 @@ void Grid::updateWindowSizes(bool updateScrollbar) int rowLabelWidth = 0; //calculate optimal row label width if (drawRowLabel) { - const int heightTotal = rowLabelWin_->getLogicalHeight(); + const auto heightTotal = rowLabelWin_->getLogicalHeight(); if (heightTotal > 0) { - int yFrom = CalcUnscrolledPosition(wxPoint(0, 0)).y; - int yTo = CalcUnscrolledPosition(wxPoint(0, mainWinHeight - 1)).y ; - numeric::restrict(yFrom, 0, heightTotal - 1); - numeric::restrict(yTo, 0, heightTotal - 1); + ptrdiff_t yFrom = CalcUnscrolledPosition(wxPoint(0, 0)).y; + ptrdiff_t yTo = CalcUnscrolledPosition(wxPoint(0, mainWinHeight - 1)).y ; + numeric::confine<ptrdiff_t>(yFrom, 0, heightTotal - 1); + numeric::confine<ptrdiff_t>(yTo, 0, heightTotal - 1); - const int rowFrom = rowLabelWin_->getRowAtPos(yFrom); - const int rowTo = rowLabelWin_->getRowAtPos(yTo); + const ptrdiff_t rowFrom = rowLabelWin_->getRowAtPos(yFrom); + const ptrdiff_t rowTo = rowLabelWin_->getRowAtPos(yTo); if (rowFrom >= 0 && rowTo >= 0) rowLabelWidth = rowLabelWin_->getBestWidth(rowFrom, rowTo); } @@ -1513,9 +1484,9 @@ void Grid::showRowLabel(bool show) } -std::vector<int> Grid::getSelectedRows(size_t compPos) const +std::vector<size_t> Grid::getSelectedRows(size_t compPos) const { - return compPos < comp.size() ? comp[compPos].selection.get() : std::vector<int>(); + return compPos < comp.size() ? comp[compPos].selection.get() : std::vector<size_t>(); } @@ -1532,8 +1503,8 @@ void Grid::scrollDelta(int deltaX, int deltaY) //const int unitsTotalY = GetScrollLines(wxVERTICAL); //if (unitsTotalX <= 0 || unitsTotalY <= 0) return; -> premature - //numeric::restrict(scrollPosX, 0, unitsTotalX - 1); //make sure scroll target is in valid range - //numeric::restrict(scrollPosY, 0, unitsTotalY - 1); // + //numeric::confine(scrollPosX, 0, unitsTotalX - 1); //make sure scroll target is in valid range + //numeric::confine(scrollPosY, 0, unitsTotalY - 1); // Scroll(scrollPosX, scrollPosY); updateWindowSizes(); //may show horizontal scroll bar @@ -1543,7 +1514,8 @@ void Grid::scrollDelta(int deltaX, int deltaY) void Grid::redirectRowLabelEvent(wxMouseEvent& event) { event.m_x = 0; - mainWin_->ProcessEvent(event); + if (wxEvtHandler* evtHandler = mainWin_->GetEventHandler()) + evtHandler->ProcessEvent(event); if (event.ButtonDown() && wxWindow::FindFocus() != mainWin_) mainWin_->SetFocus(); @@ -1569,7 +1541,7 @@ void Grid::Refresh(bool eraseBackground, const wxRect* rect) } -void Grid::setRowHeight(int height) +void Grid::setRowHeight(size_t height) { rowLabelWin_->setRowHeight(height); updateWindowSizes(); @@ -1707,13 +1679,15 @@ wxRect Grid::getColumnLabelArea(ColumnType colType, size_t compPos) const auto iterCol = std::find_if(iterComp->begin(), iterComp->end(), [&](const VisibleColumn& vc) { return vc.type_ == colType; }); if (iterCol != iterComp->end()) { - int posX = std::accumulate(compAbsWidths.begin(), iterComp, 0, - [](int val, const std::vector<VisibleColumn>& cols) + ptrdiff_t posX = std::accumulate(compAbsWidths.begin(), iterComp, static_cast<ptrdiff_t>(0), + [](ptrdiff_t sum, const std::vector<VisibleColumn>& cols) { - return val + std::accumulate(cols.begin(), cols.end(), 0, [](int val2, const VisibleColumn& vc) { return val2 + vc.width_; }); + return sum + std::accumulate(cols.begin(), cols.end(), static_cast<ptrdiff_t>(0), + [](ptrdiff_t val2, const VisibleColumn& vc) { return val2 + vc.width_; }); }); - posX += std::accumulate(iterComp->begin(), iterCol, 0, [](int val, const VisibleColumn& vc) { return val + vc.width_; }); + posX += std::accumulate(iterComp->begin(), iterCol, static_cast<ptrdiff_t>(0), + [](ptrdiff_t sum, const VisibleColumn& vc) { return sum + vc.width_; }); return wxRect(wxPoint(posX, 0), wxSize(iterCol->width_, colLabelHeight)); } @@ -1727,7 +1701,7 @@ Opt<Grid::ColAction> Grid::clientPosToColumnAction(const wxPoint& pos) const const int absPosX = CalcUnscrolledPosition(pos).x; if (absPosX >= 0) { - int accuWidth = 0; + ptrdiff_t accuWidth = 0; std::vector<std::vector<VisibleColumn>> compAbsWidths = getAbsoluteWidths(); //resolve negative/stretched widths for (auto iterComp = compAbsWidths.begin(); iterComp != compAbsWidths.end(); ++iterComp) @@ -1780,7 +1754,7 @@ void Grid::moveColumn(size_t colFrom, size_t colTo, size_t compPos) } -int Grid::clientPosToMoveTargetColumn(const wxPoint& pos, size_t compPos) const +ptrdiff_t Grid::clientPosToMoveTargetColumn(const wxPoint& pos, size_t compPos) const { std::vector<std::vector<VisibleColumn>> compAbsWidths = getAbsoluteWidths(); //resolve negative/stretched widths if (compPos < compAbsWidths.size()) @@ -1788,16 +1762,16 @@ int Grid::clientPosToMoveTargetColumn(const wxPoint& pos, size_t compPos) const auto iterComp = compAbsWidths.begin() + compPos; const int absPosX = CalcUnscrolledPosition(pos).x; - int accuWidth = std::accumulate(compAbsWidths.begin(), iterComp, 0, - [](int val, const std::vector<VisibleColumn>& cols) + ptrdiff_t accuWidth = std::accumulate(compAbsWidths.begin(), iterComp, static_cast<ptrdiff_t>(0), + [](ptrdiff_t sum, const std::vector<VisibleColumn>& cols) { - return val + std::accumulate(cols.begin(), cols.end(), 0, - [](int val2, const VisibleColumn& vc) { return val2 + vc.width_; }); + return sum + std::accumulate(cols.begin(), cols.end(), static_cast<ptrdiff_t>(0), + [](ptrdiff_t sum2, const VisibleColumn& vc) { return sum2 + vc.width_; }); }); for (auto iterCol = iterComp->begin(); iterCol != iterComp->end(); ++iterCol) { - const int width = iterCol->width_; //beware dreaded unsigned conversions! + const ptrdiff_t width = iterCol->width_; //beware dreaded unsigned conversions! accuWidth += width; if (absPosX < accuWidth - width / 2) @@ -1821,7 +1795,7 @@ Opt<ColumnType> Grid::colToType(size_t col, size_t compPos) const } -int Grid::getRowAtPos(int posY) const { return rowLabelWin_->getRowAtPos(posY); } +ptrdiff_t Grid::getRowAtPos(int posY) const { return rowLabelWin_->getRowAtPos(posY); } Opt<std::pair<ColumnType, size_t>> Grid::getColumnAtPos(int posX) const @@ -1830,7 +1804,7 @@ Opt<std::pair<ColumnType, size_t>> Grid::getColumnAtPos(int posX) const { std::vector<std::vector<VisibleColumn>> compAbsWidths = getAbsoluteWidths(); //resolve negative/stretched widths - int accWidth = 0; + ptrdiff_t accWidth = 0; for (auto iterComp = compAbsWidths.begin(); iterComp != compAbsWidths.end(); ++iterComp) for (auto iterCol = iterComp->begin(); iterCol != iterComp->end(); ++iterCol) { @@ -1846,7 +1820,7 @@ Opt<std::pair<ColumnType, size_t>> Grid::getColumnAtPos(int posX) const } -wxRect Grid::getCellArea(int row, ColumnType colType, size_t compPos) const +wxRect Grid::getCellArea(size_t row, ColumnType colType, size_t compPos) const { const wxRect& colArea = getColumnLabelArea(colType, compPos); const wxRect& rowArea = rowLabelWin_->getRowLabelArea(row); @@ -1854,7 +1828,7 @@ wxRect Grid::getCellArea(int row, ColumnType colType, size_t compPos) const } -void Grid::setGridCursor(int row, size_t compPos) +void Grid::setGridCursor(size_t row, size_t compPos) { if (compPos < comp.size()) { @@ -1864,11 +1838,12 @@ void Grid::setGridCursor(int row, size_t compPos) mainWin_->setCursor(row, compPos); mainWin_->makeRowVisible(row); mainWin_->Refresh(); + rowLabelWin_->Refresh(); //row labels! (Kubuntu) } } -void Grid::selectRange(int rowFrom, int rowTo, size_t compPos, bool positive) +void Grid::selectRange(ptrdiff_t rowFrom, ptrdiff_t rowTo, size_t compPos, bool positive) { if (compPos < comp.size()) { @@ -1893,17 +1868,17 @@ void Grid::clearSelectionAll() } -void Grid::scrollTo(int row) +void Grid::scrollTo(size_t row) { const wxRect labelRect = rowLabelWin_->getRowLabelArea(row); //returns empty rect if column not found if (labelRect.height > 0) { int pixelsPerUnitY = 0; - GetScrollPixelsPerUnit(NULL, &pixelsPerUnitY); - if (pixelsPerUnitY >= 0) + GetScrollPixelsPerUnit(nullptr, &pixelsPerUnitY); + if (pixelsPerUnitY > 0) { int scrollPosX = 0; - GetViewStart(&scrollPosX, NULL); + GetViewStart(&scrollPosX, nullptr); int scrollPosY = labelRect.GetTopLeft().y / pixelsPerUnitY; Scroll(scrollPosX, scrollPosY); @@ -1914,13 +1889,13 @@ void Grid::scrollTo(int row) } -std::pair<int, size_t> Grid::getGridCursor() const +std::pair<size_t, size_t> Grid::getGridCursor() const { return mainWin_->getCursor(); } -int Grid::getBestColumnSize(size_t col, size_t compPos) const +ptrdiff_t Grid::getBestColumnSize(size_t col, size_t compPos) const { if (compPos < comp.size()) { @@ -1934,9 +1909,9 @@ int Grid::getBestColumnSize(size_t col, size_t compPos) const dc.SetFont(mainWin_->GetFont()); size_t maxSize = 0; - const std::pair<int, int> rowRange = rowLabelWin_->getRowsOnClient(mainWin_->GetClientRect()); //returns range [begin, end) - for (int row = rowRange.first; row < rowRange.second; ++row) + 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; @@ -1957,13 +1932,12 @@ void Grid::autoSizeColumns(size_t compPos) const int bestWidth = getBestColumnSize(col, compPos); //return -1 on error if (bestWidth >= 0) { - const size_t newWidth = std::max(COLUMN_MIN_WIDTH, bestWidth); + const auto newWidth = std::max(COLUMN_MIN_WIDTH, bestWidth); iter->width_ = newWidth; //notify column resize (asynchronously!) GridColumnResizeEvent sizeEvent(newWidth, iter->type_, compPos); - wxEvtHandler* evtHandler = GetEventHandler(); - if (evtHandler) + if (wxEvtHandler* evtHandler = GetEventHandler()) evtHandler->AddPendingEvent(sizeEvent); } } @@ -1973,9 +1947,9 @@ void Grid::autoSizeColumns(size_t compPos) } -int Grid::getMinAbsoluteWidthTotal() const +ptrdiff_t Grid::getMinAbsoluteWidthTotal() const { - int minWidthTotal = 0; + ptrdiff_t minWidthTotal = 0; //bool haveStretchedCols = false; std::for_each(comp.begin(), comp.end(), [&](const Component& c) @@ -2000,9 +1974,9 @@ std::vector<std::vector<Grid::VisibleColumn>> Grid::getAbsoluteWidths() const // { std::vector<std::vector<VisibleColumn>> output; - std::vector<std::pair<int, VisibleColumn*>> stretchedCols; //(factor, column to stretch) - int factorTotal = 0; - int minWidthTotal = 0; + std::vector<std::pair<ptrdiff_t, VisibleColumn*>> stretchedCols; //(factor, column to stretch) + ptrdiff_t factorTotal = 0; + ptrdiff_t minWidthTotal = 0; output.reserve(comp.size()); std::for_each(comp.begin(), comp.end(), @@ -2033,13 +2007,13 @@ std::vector<std::vector<Grid::VisibleColumn>> Grid::getAbsoluteWidths() const // if (!stretchedCols.empty()) { - const int widthToFill = mainWin_->GetClientSize().GetWidth() - minWidthTotal; + const ptrdiff_t widthToFill = mainWin_->GetClientSize().GetWidth() - minWidthTotal; if (widthToFill > 0) { int widthRemaining = widthToFill; for (auto iter = stretchedCols.begin(); iter != stretchedCols.end(); ++iter) { - const int addWidth = (widthToFill * iter->first) / factorTotal; //round down + const ptrdiff_t addWidth = (widthToFill * iter->first) / factorTotal; //round down iter->second->width_ += addWidth; widthRemaining -= addWidth; } @@ -35,7 +35,7 @@ extern const wxEventType EVENT_GRID_SELECT_RANGE; //generates: GridRangeSelectEv //NOTE: neither first nor second row need to match EVENT_GRID_MOUSE_LEFT_DOWN/EVENT_GRID_MOUSE_LEFT_UP: user holding SHIFT; moving out of window... //=> range always specifies *valid* rows -//example: wnd.Connect(EVENT_GRID_COL_LABEL_LEFT_CLICK, GridClickEventHandler(MyDlg::OnLeftClick), NULL, this); +//example: wnd.Connect(EVENT_GRID_COL_LABEL_LEFT_CLICK, GridClickEventHandler(MyDlg::OnLeftClick), nullptr, this); struct GridClickEvent : public wxMouseEvent @@ -96,11 +96,11 @@ public: virtual size_t getRowCount() const = 0; //if there are multiple grid components, only the first one will be polled for row count! //grid area - virtual wxString getValue(int row, ColumnType colType) const = 0; - virtual void renderRowBackgound(wxDC& dc, const wxRect& rect, int row, bool enabled, bool selected, bool hasFocus); //default implementation - virtual void renderCell(Grid& grid, wxDC& dc, const wxRect& rect, int row, ColumnType colType); // - virtual size_t getBestSize(wxDC& dc, int row, ColumnType colType); //must correspond to renderCell()! - virtual wxString getToolTip(int row, ColumnType colType) const { return wxString(); } + virtual wxString getValue(size_t row, ColumnType colType) const = 0; + virtual void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected, bool hasFocus); //default implementation + virtual void renderCell(Grid& grid, wxDC& dc, const wxRect& rect, size_t row, ColumnType colType); // + virtual size_t getBestSize(wxDC& dc, size_t row, ColumnType colType); //must correspond to renderCell()! + virtual wxString getToolTip(size_t row, ColumnType colType) const { return wxString(); } //label area virtual wxString getColumnLabel(ColumnType colType) const = 0; @@ -130,7 +130,7 @@ public: size_t getRowCount() const; - void setRowHeight(int height); + void setRowHeight(size_t 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(); } @@ -148,8 +148,8 @@ public: std::vector<ColumnAttribute> getColumnConfig(size_t compPos = 0) 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() : NULL; } - const GridData* getDataProvider(size_t compPos = 0) const { return compPos < comp.size() ? comp[compPos].dataView_.get() : NULL; } + /**/ 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 setColumnLabelHeight(int height); @@ -157,7 +157,7 @@ public: void showScrollBars(bool horizontal, bool vertical); - std::vector<int> getSelectedRows(size_t compPos = 0) const; + std::vector<size_t> getSelectedRows(size_t compPos = 0) const; void clearSelection(size_t compPos = 0) { if (compPos < comp.size()) comp[compPos].selection.clear(); } void scrollDelta(int deltaX, int deltaY); //in scroll units @@ -167,20 +167,20 @@ public: wxWindow& getColLabelWin(); wxWindow& getMainWin (); - int getRowAtPos(int posY) const; //returns < 0 if column not found; absolute coordinates! + ptrdiff_t getRowAtPos(int posY) const; //returns < 0 if column not found; absolute coordinates! Opt<std::pair<ColumnType, size_t>> getColumnAtPos(int posX) const; //returns (column type, component pos) - wxRect getCellArea(int row, ColumnType colType, size_t compPos = 0) const; //returns empty rect if column not found; absolute coordinates! + wxRect getCellArea(size_t row, ColumnType colType, size_t compPos = 0) 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 setGridCursor(int row, size_t compPos = 0); //set + show + select cursor - std::pair<int, size_t> getGridCursor() const; //(row, component pos) row == -1 if none + void setGridCursor(size_t row, size_t compPos = 0); //set + show + select cursor + std::pair<size_t, size_t> getGridCursor() const; //(row, component pos) - void scrollTo(int row); + void scrollTo(size_t row); - virtual void Refresh(bool eraseBackground = true, const wxRect* rect = NULL); + 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); @@ -198,7 +198,7 @@ private: void SetScrollbar(int orientation, int position, int thumbSize, int range, bool refresh); //get rid of scrollbars, but preserve scrolling behavior! #endif - int getBestColumnSize(size_t col, size_t compPos) const; //return -1 on error + ptrdiff_t getBestColumnSize(size_t col, size_t compPos) const; //return -1 on error friend class GridData; class SubWindow; @@ -212,9 +212,9 @@ private: public: void init(size_t rowCount) { rowSelectionValue.resize(rowCount); clear(); } - std::vector<int> get() const + std::vector<size_t> get() const { - std::vector<int> selection; + std::vector<size_t> selection; for (auto iter = rowSelectionValue.begin(); iter != rowSelectionValue.end(); ++iter) if (*iter != 0) selection.push_back(iter - rowSelectionValue.begin()); @@ -225,13 +225,13 @@ private: bool isSelected(size_t row) const { return row < rowSelectionValue.size() ? rowSelectionValue[row] != 0 : false; } - void selectRange(int rowFrom, int rowTo, bool positive = true) //select [rowFrom, rowTo], very tolerant: trims and swaps if required! + void selectRange(ptrdiff_t rowFrom, ptrdiff_t rowTo, bool positive = true) //select [rowFrom, rowTo], very tolerant: trims and swaps if required! { - int rowFirst = std::min(rowFrom, rowTo); - int rowLast = std::max(rowFrom, rowTo) + 1; + auto rowFirst = std::min(rowFrom, rowTo); + auto rowLast = std::max(rowFrom, rowTo) + 1; - numeric::restrict(rowFirst, 0, static_cast<int>(rowSelectionValue.size())); - numeric::restrict(rowLast, 0, static_cast<int>(rowSelectionValue.size())); + numeric::confine<ptrdiff_t>(rowFirst, 0, rowSelectionValue.size()); + numeric::confine<ptrdiff_t>(rowLast, 0, rowSelectionValue.size()); std::fill(rowSelectionValue.begin() + rowFirst, rowSelectionValue.begin() + rowLast, positive); } @@ -242,9 +242,9 @@ private: struct VisibleColumn { - VisibleColumn(ColumnType type, int width) : type_(type), width_(width) {} + VisibleColumn(ColumnType type, ptrdiff_t width) : type_(type), width_(width) {} ColumnType type_; - int width_; //may be NEGATIVE => treat as proportional stretch! use getAbsoluteWidths() to evaluate!!! + ptrdiff_t width_; //may be NEGATIVE => treat as proportional stretch! use getAbsoluteWidths() to evaluate!!! }; struct Component @@ -260,7 +260,7 @@ private: std::vector<ColumnAttribute> oldColAttributes; //visible + nonvisible columns; use for conversion in setColumnConfig()/getColumnConfig() *only*! }; - int getMinAbsoluteWidthTotal() const; //assigns minimum width to stretched columns + ptrdiff_t getMinAbsoluteWidthTotal() const; //assigns minimum width to stretched columns std::vector<std::vector<VisibleColumn>> getAbsoluteWidths() const; //evaluate negative widths as stretched absolute values! structure matches "comp" Opt<size_t> getAbsoluteWidth(size_t col, size_t compPos) const //resolve stretched columns @@ -271,7 +271,7 @@ private: return NoValue(); } - void setColWidth(size_t col, size_t compPos, int width) //width may be >= 0: absolute, or < 0: stretched + void setColWidth(size_t col, size_t compPos, ptrdiff_t width) //width may be >= 0: absolute, or < 0: stretched { if (compPos < comp.size() && col < comp[compPos].visibleCols.size()) comp[compPos].visibleCols[col].width_ = width; @@ -279,10 +279,11 @@ private: wxRect getColumnLabelArea(ColumnType colType, size_t compPos) const; //returns empty rect if column not found - void selectRange(int rowFrom, int rowTo, size_t compPos, bool positive = true); //select range + notify event! + void selectRange(ptrdiff_t rowFrom, ptrdiff_t rowTo, size_t compPos, bool positive = true); //select range + notify event! + void clearSelectionAll(); //clear selection + notify event - bool isSelected(int row, size_t compPos) const { return compPos < comp.size() ? comp[compPos].selection.isSelected(row) : false; } + 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; } @@ -295,11 +296,10 @@ private: }; Opt<ColAction> clientPosToColumnAction(const wxPoint& pos) const; void moveColumn(size_t colFrom, size_t colTo, size_t compPos); - int clientPosToMoveTargetColumn(const wxPoint& pos, size_t compPos) const; + ptrdiff_t clientPosToMoveTargetColumn(const wxPoint& pos, size_t compPos) const; //return < 0 on error Opt<ColumnType> colToType(size_t col, size_t compPos) const; - /* Visual layout: ------------------------------------------------ diff --git a/wx+/mouse_move_dlg.cpp b/wx+/mouse_move_dlg.cpp index 20e6d420..697a5d47 100644 --- a/wx+/mouse_move_dlg.cpp +++ b/wx+/mouse_move_dlg.cpp @@ -49,7 +49,7 @@ MouseMoveWindow::MouseMoveWindow(wxWindow& parent, bool includeParent) : wxWindo dynamic_cast<wxPanel*> (&wnd) || dynamic_cast<wxFrame*> (&wnd) || dynamic_cast<wxDialog*> (&wnd)) - wnd.Connect(wxEVT_LEFT_DOWN, memFunMouseDown, NULL, this); + wnd.Connect(wxEVT_LEFT_DOWN, memFunMouseDown, nullptr, this); }; if (includeParent) diff --git a/wx+/no_flicker.h b/wx+/no_flicker.h index f745a12a..22952977 100644 --- a/wx+/no_flicker.h +++ b/wx+/no_flicker.h @@ -12,7 +12,7 @@ namespace zen { inline -void setText(wxTextCtrl& control, const wxString& newText, bool* additionalLayoutChange = NULL) +void setText(wxTextCtrl& control, const wxString& newText, bool* additionalLayoutChange = nullptr) { if (additionalLayoutChange && !*additionalLayoutChange) //never revert from true to false! *additionalLayoutChange = control.GetValue().length() != newText.length(); //avoid screen flicker: update layout only when necessary @@ -22,7 +22,7 @@ void setText(wxTextCtrl& control, const wxString& newText, bool* additionalLayou } inline -void setText(wxStaticText& control, const wxString& newText, bool* additionalLayoutChange = NULL) +void setText(wxStaticText& control, const wxString& newText, bool* additionalLayoutChange = nullptr) { if (additionalLayoutChange && !*additionalLayoutChange) *additionalLayoutChange = control.GetLabel().length() != newText.length(); //avoid screen flicker: update layout only when necessary @@ -101,6 +101,6 @@ #include <stdexcept> //Boost -#include <boost/scoped_array.hpp> + #endif //FFS_PRECOMPILED_HEADER diff --git a/wx+/serialize.h b/wx+/serialize.h index 4a06c001..b6a478cd 100644 --- a/wx+/serialize.h +++ b/wx+/serialize.h @@ -51,43 +51,54 @@ private: }; -//wxInputStream proxy throwing FileError on error -class CheckedReader +class CheckedIo +{ +protected: + CheckedIo(wxStreamBase& stream) : stream_(stream) {} + + void check() const + { + if (stream_.GetLastError() != wxSTREAM_NO_ERROR) + throwException(); + } + virtual void throwException() const = 0; + +private: + wxStreamBase& stream_; +}; + + +//wxInputStream proxy throwing exception on error +class CheckedReader : private CheckedIo { public: - CheckedReader(wxInputStream& stream, const Zstring& errorObjName) : stream_(stream), errorObjName_(errorObjName) {} + CheckedReader(wxInputStream& stream) : CheckedIo(stream), stream_(stream) {} template <class T> - T readNumberC() const; //throw FileError, checked read operation + T readPOD() const; //throw! template <class S> - S readStringC() const; //throw FileError, checked read operation + S readString() const; //throw! private: - void check() const; - wxInputStream& stream_; - const Zstring& errorObjName_; //used for error text only }; //wxOutputStream proxy throwing FileError on error -class CheckedWriter +class CheckedWriter : private CheckedIo { public: - CheckedWriter(wxOutputStream& stream, const Zstring& errorObjName) : stream_(stream), errorObjName_(errorObjName) {} + CheckedWriter(wxOutputStream& stream) : CheckedIo(stream), stream_(stream) {} template <class T> - void writeNumberC(T number) const; //throw FileError, checked write operation + void writePOD(T number) const; //throw! template <class S> - void writeStringC(const S& str) const; //throw FileError, checked write operation + void writeString(const S& str) const; //throw! private: - void check() const; - wxOutputStream& stream_; - const Zstring& errorObjName_; //used for error text only! }; @@ -139,8 +150,11 @@ S readString(wxInputStream& stream) const auto strLength = readPOD<std::uint32_t>(stream); S output; - output.resize(strLength); //throw std::bad_alloc - stream.Read(&*output.begin(), sizeof(CharType) * strLength); + if (strLength > 0) + { + output.resize(strLength); //throw std::bad_alloc + stream.Read(&*output.begin(), sizeof(CharType) * strLength); + } return output; } @@ -153,68 +167,49 @@ void writeString(wxOutputStream& stream, const S& str) } -inline -void CheckedReader::check() const -{ - if (stream_.GetLastError() != wxSTREAM_NO_ERROR) - throw zen::FileError(_("Error reading from synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\""); -} - - template <class T> inline -T CheckedReader::readNumberC() const //checked read operation +T CheckedReader::readPOD() const //checked read operation { - T output = readPOD<T>(stream_); + T output = zen::readPOD<T>(stream_); check(); return output; } template <class S> inline -S CheckedReader::readStringC() const //checked read operation +S CheckedReader::readString() const //checked read operation { S output; try { - output = readString<S>(stream_); //throw std::bad_alloc - check(); - if (stream_.LastRead() != output.length() * sizeof(typename S::value_type)) //some additional check - throw FileError(_("Error reading from synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\""); - } - catch (std::exception&) - { - throw FileError(_("Error reading from synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\""); + output = zen::readString<S>(stream_); //throw std::bad_alloc } + catch (std::exception&) { throwException(); } + + check(); + if (stream_.LastRead() != output.length() * sizeof(typename S::value_type)) //some additional check + throwException(); return output; } template <class T> inline -void CheckedWriter::writeNumberC(T number) const //checked write operation +void CheckedWriter::writePOD(T number) const //checked write operation { - writePOD<T>(stream_, number); + zen::writePOD<T>(stream_, number); check(); } template <class S> inline -void CheckedWriter::writeStringC(const S& str) const //checked write operation +void CheckedWriter::writeString(const S& str) const //checked write operation { - writeString(stream_, str); + zen::writeString(stream_, str); check(); if (stream_.LastWrite() != str.length() * sizeof(typename S::value_type)) //some additional check - throw FileError(_("Error writing to synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\""); + throwException(); } - - -inline -void CheckedWriter::check() const -{ - if (stream_.GetLastError() != wxSTREAM_NO_ERROR) - throw FileError(_("Error writing to synchronization database:") + L" \n" + L"\"" + errorObjName_ + L"\""); -} - } #endif //SERIALIZE_H_INCLUDED diff --git a/wx+/shell_execute.h b/wx+/shell_execute.h index 310fe88c..3468a1c8 100644 --- a/wx+/shell_execute.h +++ b/wx+/shell_execute.h @@ -51,9 +51,9 @@ void shellExecute(const wxString& command, ExecutionType type = EXEC_TYPE_ASYNC) if (!argv.empty()) { filename = argv[0]; - for (std::vector<std::wstring>::const_iterator i = argv.begin() + 1; i != argv.end(); ++i) - arguments += (i != argv.begin() ? L" " : L"") + - (i->empty() || std::find_if(i->begin(), i->end(), &cStringIsWhiteSpace<wchar_t>) != i->end() ? L"\"" + *i + L"\"" : *i); + for (auto iter = argv.begin() + 1; iter != argv.end(); ++iter) + arguments += (iter != argv.begin() ? L" " : L"") + + (iter->empty() || std::any_of(iter->begin(), iter->end(), &isWhiteSpace<wchar_t>) ? L"\"" + *iter + L"\"" : *iter); } SHELLEXECUTEINFO execInfo = {}; diff --git a/wx+/timespan.h b/wx+/timespan.h index 241a029e..58d5df4e 100644 --- a/wx+/timespan.h +++ b/wx+/timespan.h @@ -52,10 +52,10 @@ public: Layout(); //connect events - m_spinBtn ->Connect(wxEVT_SCROLL_LINEUP, wxEventHandler (TimeSpanCtrl::OnSpinUp), NULL, this); - m_spinBtn ->Connect(wxEVT_SCROLL_LINEDOWN, wxEventHandler (TimeSpanCtrl::OnSpinDown), NULL, this); - m_textCtrl->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler (TimeSpanCtrl::OnKeyPress), NULL, this); - m_textCtrl->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(TimeSpanCtrl::OnMouseAction), NULL, this); + m_spinBtn ->Connect(wxEVT_SCROLL_LINEUP, wxEventHandler (TimeSpanCtrl::OnSpinUp), nullptr, this); + m_spinBtn ->Connect(wxEVT_SCROLL_LINEDOWN, wxEventHandler (TimeSpanCtrl::OnSpinDown), nullptr, this); + m_textCtrl->Connect(wxEVT_KEY_DOWN, wxKeyEventHandler (TimeSpanCtrl::OnKeyPress), nullptr, this); + m_textCtrl->Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler(TimeSpanCtrl::OnMouseAction), nullptr, this); setValue(0); } @@ -94,7 +94,7 @@ public: textVal.Trim(false); wxDateTime tmp(time_t(0)); - if (tmp.ParseFormat(textVal, FORMAT_TIMESPAN, wxDateTime(tmp)) == NULL) + if (tmp.ParseFormat(textVal, FORMAT_TIMESPAN, wxDateTime(tmp)) == nullptr) return 0; return (isNegative ? -1 : 1) * diff --git a/wx+/tooltip.cpp b/wx+/tooltip.cpp index 7b4c51e0..6d81cdae 100644 --- a/wx+/tooltip.cpp +++ b/wx+/tooltip.cpp @@ -48,7 +48,7 @@ public: }; -Tooltip::Tooltip() : tipWindow(new PopupFrameGenerated(NULL)) +Tooltip::Tooltip() : tipWindow(new PopupFrameGenerated(nullptr)) { #ifdef FFS_WIN //neither looks good nor works at all on Linux tipWindow->Disable(); //prevent window stealing focus! @@ -94,5 +94,12 @@ void Tooltip::show(const wxString& text, wxPoint mousePos, const wxBitmap* bmp) void Tooltip::hide() { +#ifdef FFS_LINUX + //on wxGTK the tip window occassionally goes blank and stays that way. This is somehow triggered by wxWindow::Hide() and doesn't seem to be a wxWidgets bug (=> GTK?) + //apply brute force: + tipWindow->Destroy(); + tipWindow = new PopupFrameGenerated(nullptr); +#endif + tipWindow->Hide(); } diff --git a/wx+/tooltip.h b/wx+/tooltip.h index 7babe3c3..195ceaf7 100644 --- a/wx+/tooltip.h +++ b/wx+/tooltip.h @@ -17,7 +17,7 @@ public: Tooltip(); ~Tooltip(); - void show(const wxString& text, wxPoint mousePos, const wxBitmap* bmp = NULL); //absolute screen coordinates + void show(const wxString& text, wxPoint mousePos, const wxBitmap* bmp = nullptr); //absolute screen coordinates void hide(); private: |