summaryrefslogtreecommitdiff
path: root/wx+
diff options
context:
space:
mode:
Diffstat (limited to 'wx+')
-rw-r--r--wx+/app_main.h14
-rw-r--r--wx+/async_task.h2
-rw-r--r--wx+/bitmap_button.h17
-rw-r--r--wx+/choice_enum.h4
-rw-r--r--wx+/context_menu.h51
-rw-r--r--wx+/dc.h53
-rw-r--r--wx+/file_drop.cpp7
-rw-r--r--wx+/file_drop.h46
-rw-r--r--wx+/graph.cpp130
-rw-r--r--wx+/graph.h53
-rw-r--r--wx+/grid.cpp459
-rw-r--r--wx+/grid.h86
-rw-r--r--wx+/image_resources.cpp16
-rw-r--r--wx+/image_tools.cpp4
-rw-r--r--wx+/popup_dlg.cpp18
-rw-r--r--wx+/popup_dlg_generated.cpp106
-rw-r--r--wx+/popup_dlg_generated.h46
-rw-r--r--wx+/rtl.h2
-rw-r--r--wx+/toggle_button.h4
19 files changed, 537 insertions, 581 deletions
diff --git a/wx+/app_main.h b/wx+/app_main.h
index 570a2a9c..17a59d7b 100644
--- a/wx+/app_main.h
+++ b/wx+/app_main.h
@@ -21,16 +21,10 @@ bool globalWindowWasSet();
-
//######################## implementation ########################
namespace impl
{
-inline
-bool& refGlobalWindowStatus()
-{
- static bool status = false; //external linkage!
- return status;
-}
+inline bool haveGlobalWindow = false;
}
@@ -40,10 +34,12 @@ void setGlobalWindow(wxWindow* window)
wxTheApp->SetTopWindow(window);
wxTheApp->SetExitOnFrameDelete(true);
- impl::refGlobalWindowStatus() = true;
+ impl::haveGlobalWindow = true;
}
-inline bool globalWindowWasSet() { return impl::refGlobalWindowStatus(); }
+
+inline
+bool globalWindowWasSet() { return impl::haveGlobalWindow; }
}
#endif //APP_MAIN_H_08215601837818347575856
diff --git a/wx+/async_task.h b/wx+/async_task.h
index 47660a6a..1571c917 100644
--- a/wx+/async_task.h
+++ b/wx+/async_task.h
@@ -114,7 +114,7 @@ private:
class AsyncGuiQueue : private wxEvtHandler
{
public:
- AsyncGuiQueue(int pollingMs = 50) : pollingMs_(pollingMs) { timer_.Connect(wxEVT_TIMER, wxEventHandler(AsyncGuiQueue::onTimerEvent), nullptr, this); }
+ AsyncGuiQueue(int pollingMs = 50) : pollingMs_(pollingMs) { timer_.Bind(wxEVT_TIMER, [this](wxTimerEvent& event) { onTimerEvent(event); }); }
template <class Fun, class Fun2>
void processAsync(Fun&& evalAsync, Fun2&& evalOnGui)
diff --git a/wx+/bitmap_button.h b/wx+/bitmap_button.h
index 508a72fc..8fe8e146 100644
--- a/wx+/bitmap_button.h
+++ b/wx+/bitmap_button.h
@@ -26,7 +26,7 @@ public:
const wxSize& size = wxDefaultSize,
long style = 0,
const wxValidator& validator = wxDefaultValidator,
- const wxString& name = wxButtonNameStr) :
+ const wxString& name = wxASCII_STR(wxButtonNameStr)) :
wxBitmapButton(parent, id, wxNullBitmap, pos, size, style, validator, name)
{
SetLabel(label);
@@ -98,9 +98,10 @@ wxBitmap renderSelectedButton(const wxSize& sz)
wxBitmap bmp(sz); //seems we don't need to pass 24-bit depth here even for high-contrast color schemes
{
wxMemoryDC dc(bmp);
- dc.SetBrush(wxColor(0xcc, 0xe4, 0xf8)); //light blue
- dc.SetPen (wxColor(0x79, 0xbc, 0xed)); //medium blue
- dc.DrawRectangle(wxRect(bmp.GetSize()));
+
+ const wxColor borderCol(0x79, 0xbc, 0xed); //medium blue
+ const wxColor innerCol (0xcc, 0xe4, 0xf8); //light blue
+ drawFilledRectangle(dc, wxRect(bmp.GetSize()), fastFromDIP(1), borderCol, innerCol);
}
return bmp;
}
@@ -116,7 +117,8 @@ wxBitmap renderPressedButton(const wxSize& sz)
const wxColor colTo(0x11, 0x79, 0xfe); //light blue
wxMemoryDC dc(bmp);
- dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
+ dc.SetPen(*wxTRANSPARENT_PEN); //wxTRANSPARENT_PEN is about 2x faster than redundantly drawing with col!
+
wxRect rect(bmp.GetSize());
const int borderSize = fastFromDIP(3);
@@ -125,10 +127,13 @@ wxBitmap renderPressedButton(const wxSize& sz)
const wxColor colGradient((colFrom.Red () * (borderSize - i) + colTo.Red () * i) / borderSize,
(colFrom.Green() * (borderSize - i) + colTo.Green() * i) / borderSize,
(colFrom.Blue () * (borderSize - i) + colTo.Blue () * i) / borderSize);
- dc.SetPen(colGradient);
+ dc.SetBrush(colGradient);
dc.DrawRectangle(rect);
rect.Deflate(1);
}
+
+ dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
+ dc.DrawRectangle(rect);
}
return bmp;
}
diff --git a/wx+/choice_enum.h b/wx+/choice_enum.h
index e11b9991..626aa39a 100644
--- a/wx+/choice_enum.h
+++ b/wx+/choice_enum.h
@@ -104,7 +104,7 @@ Enum getEnumVal(const EnumDescrList<Enum>& mapping, const wxChoice& ctrl)
{
const int selectedPos = ctrl.GetSelection();
- if (0 <= selectedPos && selectedPos < static_cast<int>(mapping.descrList.size()))
+ if (0 <= selectedPos && selectedPos < std::ssize(mapping.descrList))
return mapping.descrList[selectedPos].first;
else
{
@@ -117,7 +117,7 @@ template <class Enum> void updateTooltipEnumVal(const EnumDescrList<Enum>& mappi
{
const int selectedPos = ctrl.GetSelection();
- if (0 <= selectedPos && selectedPos < static_cast<int>(mapping.descrList.size()))
+ if (0 <= selectedPos && selectedPos < std::ssize(mapping.descrList))
{
if (const auto& [text, tooltip] = mapping.descrList[selectedPos].second;
!tooltip.empty())
diff --git a/wx+/context_menu.h b/wx+/context_menu.h
index 7096da33..c53cec39 100644
--- a/wx+/context_menu.h
+++ b/wx+/context_menu.h
@@ -13,15 +13,14 @@
#include <wx/menu.h>
#include <wx/app.h>
-/*
-A context menu supporting lambda callbacks!
-
-Usage:
- ContextMenu menu;
- menu.addItem(L"Some Label", [&]{ ...do something... }); -> capture by reference is fine, as long as captured variables have at least scope of ContextMenu::popup()!
- ...
- menu.popup(wnd);
-*/
+/* A context menu supporting lambda callbacks!
+
+ Usage:
+ ContextMenu menu;
+ menu.addItem(L"Some Label", [&]{ ...do something... }); -> capture by reference is fine, as long as captured variables have at least scope of ContextMenu::popup()!
+ ...
+ menu.popup(wnd); */
+
namespace zen
{
class ContextMenu : private wxEvtHandler
@@ -32,9 +31,11 @@ public:
void addItem(const wxString& label, const std::function<void()>& command, const wxImage& img = wxNullImage, bool enabled = true)
{
wxMenuItem* newItem = new wxMenuItem(menu_.get(), wxID_ANY, label); //menu owns item!
- if (img.IsOk()) newItem->SetBitmap(img); //do not set AFTER appending item! wxWidgets screws up for yet another crappy reason
+ if (img.IsOk())
+ newItem->SetBitmap(img); //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
+ if (!enabled)
+ newItem->Enable(false); //do not enable BEFORE appending item! wxWidgets screws up for yet another crappy reason
commandList_[newItem->GetId()] = command; //defer event connection, this may be a submenu only!
}
@@ -42,7 +43,8 @@ public:
{
wxMenuItem* newItem = menu_->AppendCheckItem(wxID_ANY, label);
newItem->Check(checked);
- if (!enabled) newItem->Enable(false);
+ if (!enabled)
+ newItem->Enable(false);
commandList_[newItem->GetId()] = command;
}
@@ -50,7 +52,8 @@ public:
{
wxMenuItem* newItem = menu_->AppendRadioItem(wxID_ANY, label);
newItem->Check(selected);
- if (!enabled) newItem->Enable(false);
+ if (!enabled)
+ newItem->Enable(false);
commandList_[newItem->GetId()] = command;
}
@@ -65,16 +68,18 @@ public:
submenu.menu_->SetNextHandler(menu_.get()); //on wxGTK submenu events are not propagated to their parent menu by default!
wxMenuItem* newItem = new wxMenuItem(menu_.get(), wxID_ANY, label, L"", wxITEM_NORMAL, submenu.menu_.release()); //menu owns item, item owns submenu!
- if (img.IsOk()) newItem->SetBitmap(img); //do not set AFTER appending item! wxWidgets screws up for yet another crappy reason
+ if (img.IsOk())
+ newItem->SetBitmap(img); //do not set AFTER appending item! wxWidgets screws up for yet another crappy reason
menu_->Append(newItem);
- if (!enabled) newItem->Enable(false);
+ if (!enabled)
+ newItem->Enable(false);
}
void popup(wxWindow& wnd, const wxPoint& pos = wxDefaultPosition) //show popup menu + process lambdas
{
//eventually all events from submenu items will be received by this menu
for (const auto& [itemId, command] : commandList_)
- menu_->Connect(itemId, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(ContextMenu::onSelection), new GenericCommand(command) /*pass ownership*/, this);
+ menu_->Bind(wxEVT_COMMAND_MENU_SELECTED, [command /*clang bug*/= command](wxCommandEvent& event) { command(); }, itemId);
wnd.PopupMenu(menu_.get(), pos);
wxTheApp->ProcessPendingEvents(); //make sure lambdas are evaluated before going out of scope;
@@ -85,20 +90,8 @@ private:
ContextMenu (const ContextMenu&) = delete;
ContextMenu& operator=(const ContextMenu&) = delete;
- void onSelection(wxCommandEvent& event)
- {
- if (auto cmd = dynamic_cast<GenericCommand*>(event.m_callbackUserData))
- (cmd->fun_)();
- }
-
- struct GenericCommand : public wxObject
- {
- GenericCommand(const std::function<void()>& fun) : fun_(fun) {}
- std::function<void()> fun_;
- };
-
std::unique_ptr<wxMenu> menu_ = std::make_unique<wxMenu>();
- std::map<int, std::function<void()>> commandList_; //(item id, command)
+ std::map<int /*item id*/, std::function<void()> /*command*/> commandList_;
};
}
diff --git a/wx+/dc.h b/wx+/dc.h
index f1b92ad2..d4b68109 100644
--- a/wx+/dc.h
+++ b/wx+/dc.h
@@ -31,20 +31,36 @@ namespace zen
BufferedPaintDC(wxWindow& wnd, std::unique_ptr<wxBitmap>& buffer)
}; */
-
inline
void clearArea(wxDC& dc, const wxRect& rect, const wxColor& col)
{
if (rect.width > 0 && //clearArea() is surprisingly expensive
rect.height > 0)
- {
- wxDCPenChanger dummy (dc, col);
- wxDCBrushChanger dummy2(dc, col);
- dc.DrawRectangle(rect);
+ {
+ //wxDC::DrawRectangle() just widens inner area if wxTRANSPARENT_PEN is used!
+ //bonus: wxTRANSPARENT_PEN is about 2x faster than redundantly drawing with col!
+ wxDCPenChanger dummy (dc, *wxTRANSPARENT_PEN);
+ wxDCBrushChanger dummy2(dc, col);
+ dc.DrawRectangle(rect);
}
}
+//properly draw rectangle respecting high DPI (and avoiding wxPen position fuzzyness)
+inline
+void drawFilledRectangle(wxDC& dc, wxRect rect, int borderWidth, const wxColor& borderCol, const wxColor& innerCol)
+{
+ assert(borderCol.IsSolid() && innerCol.IsSolid());
+ wxDCPenChanger graphPen (dc, *wxTRANSPARENT_PEN);
+ wxDCBrushChanger graphBrush(dc, borderCol);
+ dc.DrawRectangle(rect);
+ rect.Deflate(borderWidth); //attention, more wxWidgets design mistakes: behavior of wxRect::Deflate depends on object being const/non-const!!!
+
+ dc.SetBrush(innerCol);
+ dc.DrawRectangle(rect);
+}
+
+
/* Standard DPI:
Windows/Ubuntu: 96 x 96
macOS: wxWidgets uses DIP (note: wxScreenDC().GetPPI() returns 72 x 72 which is a lie; looks like 96 x 96) */
@@ -52,17 +68,14 @@ void clearArea(wxDC& dc, const wxRect& rect, const wxColor& col)
inline
int fastFromDIP(int d) //like wxWindow::FromDIP (but tied to primary monitor and buffered)
{
-#ifdef wxHAVE_DPI_INDEPENDENT_PIXELS //pulled from wx/window.h: https://github.com/wxWidgets/wxWidgets/blob/master/include/wx/window.h#L2029
- return d; //e.g. macOS, GTK3
-#else //https://github.com/wxWidgets/wxWidgets/blob/master/src/common/wincmn.cpp#L2865
- static_assert(GTK_MAJOR_VERSION == 2);
+#ifndef wxHAVE_DPI_INDEPENDENT_PIXELS
+#error why is wxHAVE_DPI_INDEPENDENT_PIXELS not defined?
+#endif
//GTK2 doesn't properly support high DPI: https://freefilesync.org/forum/viewtopic.php?t=6114
//=> requires general fix at wxWidgets-level
- assert(wxTheApp); //only call after wxWidgets was initalized!
- static const int dpiY = wxScreenDC().GetPPI().y; //perf: buffering for calls to ::GetDeviceCaps() needed!?
- const int defaultDpi = 96;
- return 1.0 * d * dpiY / defaultDpi + 0.49 /*round values like 1.5 down, e.g. 1 pixel on 150% scale*/;
-#endif
+
+ //https://github.com/wxWidgets/wxWidgets/blob/d9d05c2bb201078f5e762c42458ca2f74af5b322/include/wx/window.h#L2060
+ return d; //e.g. macOS, GTK3
}
@@ -74,8 +87,8 @@ class RecursiveDcClipper
public:
RecursiveDcClipper(wxDC& dc, const wxRect& r) : dc_(dc)
{
- if (auto it = clippingAreas.find(&dc);
- it != clippingAreas.end())
+ if (auto it = clippingAreas_.find(&dc);
+ it != clippingAreas_.end())
{
oldRect_ = it->second;
@@ -87,7 +100,7 @@ public:
else
{
dc_.SetClippingRegion(r);
- clippingAreas.emplace(&dc_, r);
+ clippingAreas_.emplace(&dc_, r);
}
}
@@ -97,10 +110,10 @@ public:
if (oldRect_)
{
dc_.SetClippingRegion(*oldRect_);
- clippingAreas[&dc_] = *oldRect_;
+ clippingAreas_[&dc_] = *oldRect_;
}
else
- clippingAreas.erase(&dc_);
+ clippingAreas_.erase(&dc_);
}
private:
@@ -108,7 +121,7 @@ private:
RecursiveDcClipper& operator=(const RecursiveDcClipper&) = delete;
//associate "active" clipping area with each DC
- inline static std::unordered_map<wxDC*, wxRect> clippingAreas;
+ inline static std::unordered_map<wxDC*, wxRect> clippingAreas_;
std::optional<wxRect> oldRect_;
wxDC& dc_;
diff --git a/wx+/file_drop.cpp b/wx+/file_drop.cpp
index 938f9dbd..42cfbd3d 100644
--- a/wx+/file_drop.cpp
+++ b/wx+/file_drop.cpp
@@ -13,7 +13,10 @@
using namespace zen;
-const wxEventType zen::EVENT_DROP_FILE = wxNewEventType();
+namespace zen
+{
+wxDEFINE_EVENT(EVENT_DROP_FILE, FileDropEvent);
+}
@@ -23,7 +26,7 @@ namespace
class WindowDropTarget : public wxFileDropTarget
{
public:
- WindowDropTarget(const wxWindow& dropWindow) : dropWindow_(dropWindow) {}
+ explicit WindowDropTarget(const wxWindow& dropWindow) : dropWindow_(dropWindow) {}
private:
wxDragResult OnDragOver(wxCoord x, wxCoord y, wxDragResult def) override
diff --git a/wx+/file_drop.h b/wx+/file_drop.h
index 0a1089fc..e5de8f95 100644
--- a/wx+/file_drop.h
+++ b/wx+/file_drop.h
@@ -16,47 +16,29 @@
namespace zen
{
-//register simple file drop event (without issue of freezing dialogs and without wxFileDropTarget overdesign)
-//CAVEAT: a drop target window must not be directly or indirectly contained within a wxStaticBoxSizer until the following wxGTK bug
-//is fixed. According to wxWidgets release cycles this is expected to be: never http://trac.wxwidgets.org/ticket/2763
+/* register simple file drop event (without issue of freezing dialogs and without wxFileDropTarget overdesign)
+ CAVEAT: a drop target window must not be directly or indirectly contained within a wxStaticBoxSizer until the following wxGTK bug
+ is fixed. According to wxWidgets release cycles this is expected to be: never http://trac.wxwidgets.org/ticket/2763
-/*
-1. setup a window to emit EVENT_DROP_FILE:
- - simple file system paths: setupFileDrop
- - any shell paths with validation: setupShellItemDrop
+ 1. setup a window to emit EVENT_DROP_FILE:
+ - simple file system paths: setupFileDrop
+ - any shell paths with validation: setupShellItemDrop
-2. register events:
-wnd.Connect (EVENT_DROP_FILE, FileDropEventHandler(MyDlg::OnFilesDropped), nullptr, this);
-wnd.Disconnect(EVENT_DROP_FILE, FileDropEventHandler(MyDlg::OnFilesDropped), nullptr, this);
+ 2. register events:
+ wnd.Bind(EVENT_DROP_FILE, [this](FileDropEvent& event) { onFilesDropped(event); }); */
+struct FileDropEvent;
+wxDECLARE_EVENT(EVENT_DROP_FILE, FileDropEvent);
-3. do something:
-void MyDlg::OnFilesDropped(FileDropEvent& event);
-*/
-extern const wxEventType EVENT_DROP_FILE;
-
-
-class FileDropEvent : public wxCommandEvent
+struct FileDropEvent : public wxEvent
{
-public:
- FileDropEvent(const std::vector<Zstring>& droppedPaths) : wxCommandEvent(EVENT_DROP_FILE), droppedPaths_(droppedPaths) { StopPropagation(); }
-
- const std::vector<Zstring>& getPaths() const { return droppedPaths_; }
-
-private:
- wxEvent* Clone() const override { return new FileDropEvent(*this); }
+ explicit FileDropEvent(const std::vector<Zstring>& droppedPaths) : wxEvent(0 /*winid*/, EVENT_DROP_FILE), itemPaths_(droppedPaths) {}
+ FileDropEvent* Clone() const override { return new FileDropEvent(*this); }
- const std::vector<Zstring> droppedPaths_;
+ const std::vector<Zstring> itemPaths_;
};
-using FileDropEventFunction = void (wxEvtHandler::*)(FileDropEvent&);
-
-#define FileDropEventHandler(func) \
- (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(FileDropEventFunction, &func)
-
-
-
void setupFileDrop(wxWindow& dropWindow);
}
diff --git a/wx+/graph.cpp b/wx+/graph.cpp
index f3805fca..7bd67504 100644
--- a/wx+/graph.cpp
+++ b/wx+/graph.cpp
@@ -10,6 +10,7 @@
#include <numeric>
#include <zen/basic_math.h>
#include <zen/scope_guard.h>
+#include <zen/perf.h>
#include "dc.h"
using namespace zen;
@@ -17,7 +18,10 @@ using namespace zen;
//todo: support zoom via mouse wheel?
-const wxEventType zen::wxEVT_GRAPH_SELECTION = wxNewEventType();
+namespace zen
+{
+wxDEFINE_EVENT(EVENT_GRAPH_SELECTION, GraphSelectEvent);
+}
double zen::nextNiceNumber(double blockSize) //round to next number which is a convenient to read block size
@@ -44,26 +48,18 @@ wxColor getDefaultColor(size_t pos)
{
switch (pos % 10)
{
- case 0:
- return { 0, 69, 134 }; //blue
- case 1:
- return { 255, 66, 14 }; //red
- case 2:
- return { 255, 211, 32 }; //yellow
- case 3:
- return { 87, 157, 28 }; //green
- case 4:
- return { 126, 0, 33 }; //royal
- case 5:
- return { 131, 202, 255 }; //light blue
- case 6:
- return { 49, 64, 4 }; //dark green
- case 7:
- return { 174, 207, 0 }; //light green
- case 8:
- return { 75, 31, 111 }; //purple
- case 9:
- return { 255, 149, 14 }; //orange
+ //*INDENT-OFF*
+ case 0: return { 0, 69, 134 }; //blue
+ case 1: return { 255, 66, 14 }; //red
+ case 2: return { 255, 211, 32 }; //yellow
+ case 3: return { 87, 157, 28 }; //green
+ case 4: return { 126, 0, 33 }; //royal
+ case 5: return { 131, 202, 255 }; //light blue
+ case 6: return { 49, 64, 4 }; //dark green
+ case 7: return { 174, 207, 0 }; //light green
+ case 8: return { 75, 31, 111 }; //purple
+ case 9: return { 255, 149, 14 }; //orange
+ //*INDENT-ON*
}
assert(false);
return *wxBLACK;
@@ -228,7 +224,7 @@ void drawCornerText(wxDC& dc, const wxRect& graphArea, const wxString& txt, Grap
//add text shadow to improve readability:
wxDCTextColourChanger textColor(dc, colorBack);
- dc.DrawText(txt, drawPos + border + wxSize(fastFromDIP(1), fastFromDIP(1)));
+ dc.DrawText(txt, drawPos + border + wxSize(1, 1) /*better without fastFromDIP()?*/);
textColor.Set(colorText);
dc.DrawText(txt, drawPos + border);
@@ -292,7 +288,7 @@ struct GetIntersectionX
{
const double deltaX = to.x - from.x;
const double deltaY = to.y - from.y;
- return numeric::isNull(deltaX) ? to : CurvePoint(x_, from.y + (x_ - from.x) / deltaX * deltaY);
+ return numeric::isNull(deltaX) ? to : CurvePoint{x_, from.y + (x_ - from.x) / deltaX * deltaY};
}
private:
@@ -306,7 +302,7 @@ struct GetIntersectionY
{
const double deltaX = to.x - from.x;
const double deltaY = to.y - from.y;
- return numeric::isNull(deltaY) ? to : CurvePoint(from.x + (y_ - from.y) / deltaY * deltaX, y_);
+ return numeric::isNull(deltaY) ? to : CurvePoint{from.x + (y_ - from.y) / deltaY * deltaX, y_};
}
private:
@@ -350,7 +346,7 @@ std::vector<CurvePoint> ContinuousCurveData::getPoints(double minX, double maxX,
for (int i = posFrom; i <= posTo; ++i)
{
const double x = cvrtX.screenToReal(i);
- points.emplace_back(x, getValue(x));
+ points.emplace_back(CurvePoint{x, getValue(x)});
}
}
return points;
@@ -375,7 +371,7 @@ std::vector<CurvePoint> SparseCurveData::getPoints(double minX, double maxX, con
if (addSteps_)
if (pt.y != points.back().y)
- points.emplace_back(CurvePoint(pt.x, points.back().y)); //[!] aliasing parameter not yet supported via emplace_back: VS bug! => make copy
+ points.emplace_back(CurvePoint{pt.x, points.back().y}); //[!] aliasing parameter not yet supported via emplace_back: VS bug! => make copy
}
points.push_back(pt);
};
@@ -393,9 +389,9 @@ std::vector<CurvePoint> SparseCurveData::getPoints(double minX, double maxX, con
const int posGe = ptGe ? cvrtX.realToScreenRound(ptGe->x) : i - 1;
assert(!ptLe || posLe <= i); //check for invalid return values
assert(!ptGe || posGe >= i); //
- /*
- Breakdown of all combinations of posLe, posGe and expected action (n >= 1)
- Note: For every empty x-range of at least one pixel, both next and previous points must be saved to keep the interpolating line stable!!!
+
+ /* Breakdown of all combinations of posLe, posGe and expected action (n >= 1)
+ Note: For every empty x-range of at least one pixel, both next and previous points must be saved to keep the interpolating line stable!!!
posLe | posGe | action
+-------+-------+--------
@@ -410,8 +406,7 @@ std::vector<CurvePoint> SparseCurveData::getPoints(double minX, double maxX, con
| none | i + n | save ptGe; jump to position posGe + 1
| i | i + n | save ptLe; if n == 1: continue; else: save ptGe; jump to position posGe + 1
| i - n | i + n | save ptLe, ptGe; jump to position posGe + 1
- +-------+-------+--------
- */
+ +-------+-------+-------- */
if (posGe < i)
{
if (posLe == i)
@@ -448,18 +443,18 @@ Graph2D::Graph2D(wxWindow* parent,
long style,
const wxString& name) : wxPanel(parent, winid, pos, size, style, name)
{
- Connect(wxEVT_PAINT, wxPaintEventHandler(Graph2D::onPaintEvent), nullptr, this);
- Connect(wxEVT_SIZE, wxSizeEventHandler (Graph2D::onSizeEvent ), nullptr, this);
+ Bind(wxEVT_PAINT, [this](wxPaintEvent& event) { onPaintEvent(event); });
+ Bind(wxEVT_SIZE, [this](wxSizeEvent& event) { Refresh(); event.Skip(); });
Bind(wxEVT_ERASE_BACKGROUND, [](wxEraseEvent& event) {}); //https://wiki.wxwidgets.org/Flicker-Free_Drawing
//SetDoubleBuffered(true); slow as hell!
SetBackgroundStyle(wxBG_STYLE_PAINT);
- 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);
+ Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& event) { onMouseLeftDown(event); });
+ Bind(wxEVT_MOTION, [this](wxMouseEvent& event) { onMouseMovement(event); });
+ Bind(wxEVT_LEFT_UP, [this](wxMouseEvent& event) { onMouseLeftUp (event); });
+ Bind(wxEVT_MOUSE_CAPTURE_LOST, [this](wxMouseCaptureLostEvent& event) { onMouseCaptureLost(event); });
}
@@ -471,7 +466,7 @@ void Graph2D::onPaintEvent(wxPaintEvent& event)
}
-void Graph2D::OnMouseLeftDown(wxMouseEvent& event)
+void Graph2D::onMouseLeftDown(wxMouseEvent& event)
{
activeSel_ = std::make_unique<MouseSelection>(*this, event.GetPosition());
@@ -481,7 +476,7 @@ void Graph2D::OnMouseLeftDown(wxMouseEvent& event)
}
-void Graph2D::OnMouseMovement(wxMouseEvent& event)
+void Graph2D::onMouseMovement(wxMouseEvent& event)
{
if (activeSel_.get())
{
@@ -491,7 +486,7 @@ void Graph2D::OnMouseMovement(wxMouseEvent& event)
}
-void Graph2D::OnMouseLeftUp(wxMouseEvent& event)
+void Graph2D::onMouseLeftUp(wxMouseEvent& event)
{
if (activeSel_.get())
{
@@ -510,7 +505,7 @@ void Graph2D::OnMouseLeftUp(wxMouseEvent& event)
}
-void Graph2D::OnMouseCaptureLost(wxMouseCaptureLostEvent& event)
+void Graph2D::onMouseCaptureLost(wxMouseCaptureLostEvent& event)
{
activeSel_.reset();
Refresh();
@@ -546,15 +541,14 @@ void Graph2D::render(wxDC& dc) const
//wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
const int xLabelHeight = attr_.xLabelHeight ? *attr_.xLabelHeight : GetCharHeight() + fastFromDIP(2) /*margin*/;
- const int yLabelWidth = attr_.yLabelWidth ? *attr_.yLabelWidth : dc.GetTextExtent(L"1,23457e+07").x;
-
- /*
- -----------------------
- | | x-label |
- -----------------------
- |y-label | graph area |
- |----------------------
- */
+ const int yLabelWidth = attr_.yLabelWidth ? *attr_.yLabelWidth : dc.GetTextExtent(L"1.23457e+07").x;
+
+ /* -----------------------
+ | | x-label |
+ -----------------------
+ |y-label | graph area |
+ |---------------------- */
+
wxRect graphArea = clientRect;
int xLabelPosY = clientRect.y;
int yLabelPosX = clientRect.x;
@@ -589,15 +583,9 @@ void Graph2D::render(wxDC& dc) const
assert(attr_.labelposX == LABEL_X_NONE || attr_.labelFmtX);
assert(attr_.labelposY == LABEL_Y_NONE || attr_.labelFmtY);
- {
- //paint graph background (excluding label area)
- wxDCPenChanger dummy (dc, wxPen(getBorderColor(), fastFromDIP(1)));
- wxDCBrushChanger dummy2(dc, attr_.colorBack);
- //accessibility: consider system text and background colors; small drawback: color of graphs is NOT connected to the background! => responsibility of client to use correct colors
-
- dc.DrawRectangle(graphArea);
- graphArea.Deflate(1, 1); //attention more wxWidgets design mistakes: behavior of wxRect::Deflate depends on object being const/non-const!!!
- }
+ //paint graph background (excluding label area)
+ drawFilledRectangle(dc, graphArea, fastFromDIP(1), getBorderColor(), attr_.colorBack);
+ graphArea.Deflate(fastFromDIP(1));
//set label areas respecting graph area border!
const wxRect xLabelArea(graphArea.x, xLabelPosY, graphArea.width, xLabelHeight);
@@ -691,8 +679,8 @@ void Graph2D::render(wxDC& dc) const
if (curves_[index].second.fillMode == CurveAttributes::FILL_CURVE)
if (!cp.empty())
{
- cp.emplace_back(CurvePoint(cp.back ().x, minY)); //add lower right and left corners
- cp.emplace_back(CurvePoint(cp.front().x, minY)); //[!] aliasing parameter not yet supported via emplace_back: VS bug! => make copy
+ cp.emplace_back(CurvePoint{cp.back ().x, minY}); //add lower right and left corners
+ cp.emplace_back(CurvePoint{cp.front().x, minY}); //[!] aliasing parameter not yet supported via emplace_back: VS bug! => make copy
oobMarker[index].back() = true;
oobMarker[index].push_back(true);
oobMarker[index].push_back(true);
@@ -733,26 +721,26 @@ void Graph2D::render(wxDC& dc) const
widen(&screenFromY, &screenToY);
//save current selection as "double" coordinates
- activeSel_->refSelection().from = CurvePoint(cvrtX.screenToReal(screenFromX),
- cvrtY.screenToReal(screenFromY));
+ activeSel_->refSelection().from = CurvePoint{cvrtX.screenToReal(screenFromX),
+ cvrtY.screenToReal(screenFromY)};
- activeSel_->refSelection().to = CurvePoint(cvrtX.screenToReal(screenToX),
- cvrtY.screenToReal(screenToY));
+ activeSel_->refSelection().to = CurvePoint{cvrtX.screenToReal(screenToX),
+ cvrtY.screenToReal(screenToY)};
}
//#################### begin drawing ####################
//1. draw colored area under curves
for (auto it = curves_.begin(); it != curves_.end(); ++it)
if (it->second.fillMode != CurveAttributes::FILL_NONE)
- {
- const std::vector<wxPoint>& points = drawPoints[it - curves_.begin()];
- if (points.size() >= 3)
+ if (const std::vector<wxPoint>& points = drawPoints[it - curves_.begin()];
+ points.size() >= 3)
{
- wxDCBrushChanger dummy(dc, it->second.fillColor);
- wxDCPenChanger dummy2(dc, wxPen(it->second.fillColor, fastFromDIP(1)));
+ //wxDC::DrawPolygon() draws *transparent* border if wxTRANSPARENT_PEN is used!
+ //unlike wxDC::DrawRectangle() which just widens inner area!
+ wxDCPenChanger dummy (dc, wxPen(it->second.fillColor, 1 /*[!] width*/));
+ wxDCBrushChanger dummy2(dc, it->second.fillColor);
dc.DrawPolygon(static_cast<int>(points.size()), &points[0]);
}
- }
//2. draw all currently set mouse selections (including active selection)
std::vector<SelectionBlock> allSelections = oldSel_;
diff --git a/wx+/graph.h b/wx+/graph.h
index f1f0c76c..a6e99200 100644
--- a/wx+/graph.h
+++ b/wx+/graph.h
@@ -19,26 +19,19 @@
//elegant 2D graph as wxPanel specialization
namespace zen
{
-/*
-Example:
- //init graph (optional)
+/* //init graph (optional)
m_panelGraph->setAttributes(Graph2D::MainAttributes().
setLabelX(Graph2D::LABEL_X_BOTTOM, 20, std::make_shared<LabelFormatterTimeElapsed>()).
setLabelY(Graph2D::LABEL_Y_RIGHT, 60, std::make_shared<LabelFormatterBytes>()));
//set graph data
std::shared_ptr<CurveData> curveDataBytes_ = ...
- m_panelGraph->setCurve(curveDataBytes_, Graph2D::CurveAttributes().setLineWidth(2).setColor(wxColor(0, 192, 0)));
-*/
+ m_panelGraph->setCurve(curveDataBytes_, Graph2D::CurveAttributes().setLineWidth(2).setColor(wxColor(0, 192, 0))); */
struct CurvePoint
{
- CurvePoint() {}
- CurvePoint(double xVal, double yVal) : x(xVal), y(yVal) {}
double x = 0;
double y = 0;
};
-inline bool operator==(const CurvePoint& lhs, const CurvePoint& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y; }
-inline bool operator!=(const CurvePoint& lhs, const CurvePoint& rhs) { return !(lhs == rhs); }
struct CurveData
@@ -84,7 +77,7 @@ private:
const size_t sz = getSize();
const size_t pos = std::min<ptrdiff_t>(std::floor(x), sz - 1); //[!] expect unsigned underflow if empty!
if (pos < sz)
- return CurvePoint(pos, getValue(pos));
+ return CurvePoint{1.0 * pos, getValue(pos)};
return {};
}
@@ -92,7 +85,7 @@ private:
{
const size_t pos = std::max<ptrdiff_t>(std::ceil(x), 0); //[!] use std::max with signed type!
if (pos < getSize())
- return CurvePoint(pos, getValue(pos));
+ return CurvePoint{1.0 * pos, getValue(pos)};
return {};
}
};
@@ -131,12 +124,11 @@ struct DecimalNumberFormatter : public LabelFormatter
};
//------------------------------------------------------------------------------------------------------------
+//example: wnd.Bind(EVENT_GRAPH_SELECTION, [this](GraphSelectEvent& event) { onGraphSelect(event); });
-//emit data selection event
-//Usage: wnd.Connect(wxEVT_GRAPH_SELECTION, GraphSelectEventHandler(MyDlg::OnGraphSelection), nullptr, this);
-// void MyDlg::OnGraphSelection(GraphSelectEvent& event);
+struct GraphSelectEvent;
+wxDECLARE_EVENT(EVENT_GRAPH_SELECTION, GraphSelectEvent);
-extern const wxEventType wxEVT_GRAPH_SELECTION;
struct SelectionBlock
{
@@ -144,23 +136,13 @@ struct SelectionBlock
CurvePoint to;
};
-class GraphSelectEvent : public wxCommandEvent
+struct GraphSelectEvent : public wxEvent
{
-public:
- GraphSelectEvent(const SelectionBlock& selBlock) : wxCommandEvent(wxEVT_GRAPH_SELECTION), selBlock_(selBlock) {}
- wxEvent* Clone() const override { return new GraphSelectEvent(selBlock_); }
-
- SelectionBlock getSelection() { return selBlock_; }
+ explicit GraphSelectEvent(const SelectionBlock& selBlock) : wxEvent(0 /*winid*/, EVENT_GRAPH_SELECTION), selectBlock_(selBlock) {}
+ GraphSelectEvent* Clone() const override { return new GraphSelectEvent(*this); }
-private:
- SelectionBlock selBlock_;
+ SelectionBlock selectBlock_;
};
-
-using GraphSelectEventFunction = void (wxEvtHandler::*)(GraphSelectEvent&);
-
-#define GraphSelectEventHandler(func) \
- (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(GraphSelectEventFunction, &func)
-
//------------------------------------------------------------------------------------------------------------
class Graph2D : public wxPanel
@@ -171,7 +153,7 @@ public:
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL | wxNO_BORDER,
- const wxString& name = wxPanelNameStr);
+ const wxString& name = wxASCII_STR(wxPanelNameStr));
class CurveAttributes
{
@@ -288,6 +270,8 @@ public:
std::map<PosCorner, wxString> cornerTexts;
+ //accessibility: consider system text and background colors;
+ //small drawback: color of graphs is NOT connected to the background! => responsibility of client to use correct colors
wxColor colorText = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
wxColor colorBack = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
@@ -308,13 +292,12 @@ public:
void clearSelection() { oldSel_.clear(); Refresh(); }
private:
- void OnMouseLeftDown(wxMouseEvent& event);
- void OnMouseMovement(wxMouseEvent& event);
- void OnMouseLeftUp (wxMouseEvent& event);
- void OnMouseCaptureLost(wxMouseCaptureLostEvent& event);
+ void onMouseLeftDown(wxMouseEvent& event);
+ void onMouseMovement(wxMouseEvent& event);
+ void onMouseLeftUp (wxMouseEvent& event);
+ void onMouseCaptureLost(wxMouseCaptureLostEvent& event);
void onPaintEvent(wxPaintEvent& event);
- void onSizeEvent(wxSizeEvent& event) { Refresh(); event.Skip(); }
void render(wxDC& dc) const;
diff --git a/wx+/grid.cpp b/wx+/grid.cpp
index 3f1599f3..80c9aaf1 100644
--- a/wx+/grid.cpp
+++ b/wx+/grid.cpp
@@ -55,8 +55,7 @@ const int COLUMN_MOVE_MARKER_WIDTH_DIP = 3;
const bool fillGapAfterColumns = true; //draw rows/column label to fill full window width; may become an instance variable some time?
-/*
-IsEnabled() vs IsThisEnabled() since wxWidgets 2.9.5:
+/* IsEnabled() vs IsThisEnabled() since wxWidgets 2.9.5:
void wxWindowBase::NotifyWindowOnEnableChange(), called from bool wxWindowBase::Enable(), fails to refresh
child elements when disabling a IsTopLevel() dialog, e.g. when showing a modal dialog.
@@ -73,8 +72,7 @@ The perfect solution would be a bool renderAsEnabled() { return "IsEnabled() but
However "IsThisEnabled()" is good enough (same like the old IsEnabled() on wxWidgets 2.8.12) and it avoids this pathetic behavior on XP.
(Similar problem on Win 7: e.g. directly click sync button without comparing first)
-=> 2018-07-30: roll our own:
-*/
+=> 2018-07-30: roll our own: */
bool renderAsEnabled(wxWindow& win)
{
if (win.IsTopLevel())
@@ -88,25 +86,39 @@ bool renderAsEnabled(wxWindow& win)
}
//----------------------------------------------------------------------------------------------------------------
-const wxEventType zen::EVENT_GRID_MOUSE_LEFT_DOUBLE = wxNewEventType();
-const wxEventType zen::EVENT_GRID_MOUSE_LEFT_DOWN = wxNewEventType();
-const wxEventType zen::EVENT_GRID_MOUSE_LEFT_UP = wxNewEventType();
-const wxEventType zen::EVENT_GRID_MOUSE_RIGHT_DOWN = wxNewEventType();
-const wxEventType zen::EVENT_GRID_MOUSE_RIGHT_UP = wxNewEventType();
-const wxEventType zen::EVENT_GRID_SELECT_RANGE = wxNewEventType();
-const wxEventType zen::EVENT_GRID_COL_LABEL_MOUSE_LEFT = wxNewEventType();
-const wxEventType zen::EVENT_GRID_COL_LABEL_MOUSE_RIGHT = wxNewEventType();
-const wxEventType zen::EVENT_GRID_COL_RESIZE = wxNewEventType();
+namespace zen
+{
+wxDEFINE_EVENT(EVENT_GRID_MOUSE_LEFT_DOUBLE, GridClickEvent);
+wxDEFINE_EVENT(EVENT_GRID_MOUSE_LEFT_DOWN, GridClickEvent);
+wxDEFINE_EVENT(EVENT_GRID_MOUSE_RIGHT_DOWN, GridClickEvent);
+wxDEFINE_EVENT(EVENT_GRID_SELECT_RANGE, GridSelectEvent);
+wxDEFINE_EVENT(EVENT_GRID_COL_LABEL_MOUSE_LEFT, GridLabelClickEvent);
+wxDEFINE_EVENT(EVENT_GRID_COL_LABEL_MOUSE_RIGHT, GridLabelClickEvent);
+wxDEFINE_EVENT(EVENT_GRID_COL_RESIZE, GridColumnResizeEvent);
+wxDEFINE_EVENT(EVENT_GRID_CONTEXT_MENU, GridContextMenuEvent);
+}
//----------------------------------------------------------------------------------------------------------------
void GridData::renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected)
{
- drawCellBackground(dc, rect, enabled, selected, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
+ if (enabled)
+ {
+ if (selected)
+ dc.GradientFillLinear(rect, getColorSelectionGradientFrom(), getColorSelectionGradientTo(), wxEAST);
+ else
+ clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
+ }
+ else
+ clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
}
void GridData::renderCell(wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool enabled, bool selected, HoverArea rowHover)
{
+ wxDCTextColourChanger textColor(dc);
+ if (enabled && selected) //accessibility: always set *both* foreground AND background colors!
+ textColor.Set(*wxBLACK);
+
wxRect rectTmp = drawCellBorder(dc, rect);
rectTmp.x += getColumnGapLeft();
@@ -131,20 +143,6 @@ wxRect GridData::drawCellBorder(wxDC& dc, const wxRect& rect) //returns remainin
}
-void GridData::drawCellBackground(wxDC& dc, const wxRect& rect, bool enabled, bool selected, const wxColor& backgroundColor)
-{
- if (enabled)
- {
- if (selected)
- dc.GradientFillLinear(rect, getColorSelectionGradientFrom(), getColorSelectionGradientTo(), wxEAST);
- else
- clearArea(dc, rect, backgroundColor);
- }
- else
- clearArea(dc, rect, wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
-}
-
-
void GridData::drawCellText(wxDC& dc, const wxRect& rect, const std::wstring& text, int alignment, const wxSize* textExtentHint)
{
/* Performance Notes (Windows):
@@ -270,37 +268,37 @@ class Grid::SubWindow : public wxWindow
{
public:
SubWindow(Grid& parent) :
- wxWindow(&parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS | wxBORDER_NONE, wxPanelNameStr),
+ wxWindow(&parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS | wxBORDER_NONE, wxASCII_STR(wxPanelNameStr)),
parent_(parent)
{
- Connect(wxEVT_PAINT, wxPaintEventHandler(SubWindow::onPaintEvent), nullptr, this);
- Connect(wxEVT_SIZE, wxSizeEventHandler (SubWindow::onSizeEvent), nullptr, this);
+ Bind(wxEVT_PAINT, [this](wxPaintEvent& event) { onPaintEvent(event); });
+ Bind(wxEVT_SIZE, [this](wxSizeEvent& event) { Refresh(); event.Skip(); });
Bind(wxEVT_ERASE_BACKGROUND, [](wxEraseEvent& event) {}); //https://wiki.wxwidgets.org/Flicker-Free_Drawing
//SetDoubleBuffered(true); slow as hell!
SetBackgroundStyle(wxBG_STYLE_PAINT);
- 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);
+ Bind(wxEVT_SET_FOCUS, [this](wxFocusEvent& event) { onFocus(event); });
+ Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& event) { onFocus(event); });
+ Bind(wxEVT_CHILD_FOCUS, [](wxChildFocusEvent& event) {}); //wxGTK::wxScrolledWindow automatically scrolls to child window when child gets focus -> prevent!
- 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_MOUSEWHEEL, wxMouseEventHandler(SubWindow::onMouseWheel ), nullptr, this);
- Connect(wxEVT_MOUSE_CAPTURE_LOST, wxMouseCaptureLostEventHandler(SubWindow::onMouseCaptureLost), nullptr, this);
+ Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& event) { onMouseLeftDown (event); });
+ Bind(wxEVT_LEFT_UP, [this](wxMouseEvent& event) { onMouseLeftUp (event); });
+ Bind(wxEVT_LEFT_DCLICK, [this](wxMouseEvent& event) { onMouseLeftDouble(event); });
+ Bind(wxEVT_RIGHT_DOWN, [this](wxMouseEvent& event) { onMouseRightDown (event); });
+ Bind(wxEVT_RIGHT_UP, [this](wxMouseEvent& event) { onMouseRightUp (event); });
+ Bind(wxEVT_MOTION, [this](wxMouseEvent& event) { onMouseMovement (event); });
+ Bind(wxEVT_LEAVE_WINDOW, [this](wxMouseEvent& event) { onLeaveWindow (event); });
+ Bind(wxEVT_MOUSEWHEEL, [this](wxMouseEvent& event) { onMouseWheel (event); });
+ Bind(wxEVT_MOUSE_CAPTURE_LOST, [this](wxMouseCaptureLostEvent& event) { onMouseCaptureLost(event); });
- Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(SubWindow::onKeyDown), nullptr, this);
- Connect(wxEVT_KEY_UP, wxKeyEventHandler(SubWindow::onKeyUp ), nullptr, this);
+ Bind(wxEVT_KEY_DOWN, [this](wxKeyEvent& event) { onKeyDown(event); });
+ Bind(wxEVT_KEY_UP, [this](wxKeyEvent& event) { onKeyUp (event); });
assert(GetClientAreaOrigin() == wxPoint()); //generally assumed when dealing with coordinates below
}
- Grid& refParent() { return parent_; }
+ Grid& refParent() { return parent_; }
const Grid& refParent() const { return parent_; }
template <class T>
@@ -337,7 +335,6 @@ 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(); }
@@ -362,19 +359,30 @@ private:
void onMouseWheel(wxMouseEvent& event)
{
- /*
- MSDN, WM_MOUSEWHEEL: "Sent to the focus window when the mouse wheel is rotated.
- The DefWindowProc function propagates the message to the window's parent.
- There should be no internal forwarding of the message, since DefWindowProc propagates
- it up the parent chain until it finds a window that processes it."
+ /* MSDN, WM_MOUSEWHEEL: "Sent to the focus window when the mouse wheel is rotated.
+ The DefWindowProc function propagates the message to the window's parent.
+ There should be no internal forwarding of the message, since DefWindowProc propagates
+ it up the parent chain until it finds a window that processes it."
- On OS X there is no such propagation! => we need a redirection (the same wxGrid implements)
- */
+ On OS X there is no such propagation! => we need a redirection (the same wxGrid implements)
- //new wxWidgets 3.0 screw-up for GTK2: wxScrollHelperEvtHandler::ProcessEvent() ignores wxEVT_MOUSEWHEEL events
- //thereby breaking the scenario of redirection to parent we need here (but also breaking their very own wxGrid sample)
- //=> call wxScrolledWindow mouse wheel handler directly
- parent_.HandleOnMouseWheel(event);
+ new wxWidgets 3.0 screw-up for GTK2: wxScrollHelperEvtHandler::ProcessEvent() ignores wxEVT_MOUSEWHEEL events
+ thereby breaking the scenario of redirection to parent we need here (but also breaking their very own wxGrid sample)
+ => call wxScrolledWindow mouse wheel handler directly */
+
+ //wxWidgets never ceases to amaze: multi-line scrolling is implemented maximally inefficient by repeating wxEVT_SCROLLWIN_LINEUP!! => WTF!
+ if (event.GetWheelAxis() == wxMOUSE_WHEEL_VERTICAL && //=> reimplement wxScrollHelperBase::HandleOnMouseWheel() in a non-retarded way
+ !event.IsPageScroll())
+ {
+ mouseRotateRemainder_ += -event.GetWheelRotation();
+ const int rotations = mouseRotateRemainder_ / event.GetWheelDelta();
+ mouseRotateRemainder_ -= rotations * event.GetWheelDelta();
+
+ const int rowsDelta = rotations * event.GetLinesPerAction();
+ parent_.scrollDelta(0, rowsDelta);
+ }
+ else
+ parent_.HandleOnMouseWheel(event);
//if (!sendEventToParent(event))
// event.Skip();
@@ -392,14 +400,9 @@ private:
render(dc, it.GetRect());
}
- void onSizeEvent(wxSizeEvent& event)
- {
- Refresh();
- event.Skip();
- }
-
Grid& parent_;
std::optional<wxBitmap> doubleBuffer_;
+ int mouseRotateRemainder_ = 0;
};
//----------------------------------------------------------------------------------------------------------------
@@ -432,7 +435,7 @@ private:
dc.DrawLine(clientRect.GetBottomLeft(), clientRect.GetBottomRight());
wxRect rectShrinked = clientRect;
- rectShrinked.Deflate(1);
+ rectShrinked.Deflate(fastFromDIP(1));
dc.SetPen(wxPen(*wxWHITE, fastFromDIP(1)));
//dc.DrawLine(clientRect.GetTopLeft(), clientRect.GetTopRight() + wxPoint(1, 0));
@@ -528,7 +531,7 @@ private:
//label text
wxRect textRect = rect;
- textRect.Deflate(1);
+ textRect.Deflate(fastFromDIP(1));
GridData::drawCellText(dc, textRect, formatRow(row), wxALIGN_CENTRE);
@@ -657,7 +660,7 @@ private:
const int clientWidth = GetClientSize().GetWidth(); //need reliable, stable width in contrast to rect.width
if (totalWidth < clientWidth)
- drawColumnLabel(dc, wxRect(labelAreaTL, wxSize(clientWidth - totalWidth, colLabelHeight)), absWidths.size(), ColumnType::NONE, enabled);
+ drawColumnLabel(dc, wxRect(labelAreaTL, wxSize(clientWidth - totalWidth, colLabelHeight)), absWidths.size(), ColumnType::none, enabled);
}
}
@@ -758,7 +761,7 @@ private:
const int bestWidth = refParent().getBestColumnSize(action->col); //return -1 on error
if (bestWidth >= 0)
{
- refParent().setColumnWidth(bestWidth, action->col, GridEventPolicy::ALLOW);
+ refParent().setColumnWidth(bestWidth, action->col, GridEventPolicy::allow);
refParent().Refresh(); //refresh main grid as well!
}
}
@@ -773,12 +776,12 @@ private:
const int newWidth = activeResizing_->getStartWidth() + event.GetPosition().x - activeResizing_->getStartPosX();
//set width tentatively
- refParent().setColumnWidth(newWidth, col, GridEventPolicy::ALLOW);
+ refParent().setColumnWidth(newWidth, col, GridEventPolicy::allow);
//check if there's a small gap after last column, if yes, fill it
const int gapWidth = GetClientSize().GetWidth() - refParent().getColWidthsSum(GetClientSize().GetWidth());
if (std::abs(gapWidth) < fastFromDIP(COLUMN_FILL_GAP_TOLERANCE_DIP))
- refParent().setColumnWidth(newWidth + gapWidth, col, GridEventPolicy::ALLOW);
+ refParent().setColumnWidth(newWidth + gapWidth, col, GridEventPolicy::allow);
refParent().Refresh(); //refresh columns on main grid as well!
}
@@ -815,8 +818,8 @@ private:
const std::wstring toolTip = [&]
{
const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition());
- const ColumnType colType = refParent().getColumnAtPos(absPos.x).colType; //returns ColumnType::NONE if no column at x position!
- if (colType != ColumnType::NONE)
+ const ColumnType colType = refParent().getColumnAtPos(absPos.x).colType; //returns ColumnType::none if no column at x position!
+ if (colType != ColumnType::none)
if (auto prov = refParent().getDataProvider())
return prov->getToolTip(colType);
return std::wstring();
@@ -846,7 +849,7 @@ private:
else
//notify right click (on free space after last column)
if (fillGapAfterColumns)
- sendEventToParent(GridLabelClickEvent(EVENT_GRID_COL_LABEL_MOUSE_RIGHT, ColumnType::NONE));
+ sendEventToParent(GridLabelClickEvent(EVENT_GRID_COL_LABEL_MOUSE_RIGHT, ColumnType::none));
event.Skip();
}
@@ -859,7 +862,7 @@ private:
//----------------------------------------------------------------------------------------------------------------
namespace
{
-const wxEventType EVENT_GRID_HAS_SCROLLED = wxNewEventType(); //internal to Grid::MainWin::ScrollWindow()
+wxDEFINE_EVENT(EVENT_GRID_HAS_SCROLLED, wxCommandEvent);
}
//----------------------------------------------------------------------------------------------------------------
@@ -872,7 +875,7 @@ public:
rowLabelWin_(rowLabelWin),
colLabelWin_(colLabelWin)
{
- Connect(EVENT_GRID_HAS_SCROLLED, wxEventHandler(MainWin::onRequestWindowUpdate), nullptr, this);
+ Bind(EVENT_GRID_HAS_SCROLLED, [this](wxCommandEvent& event) { onRequestWindowUpdate(event); });
}
~MainWin() { assert(!gridUpdatePending_); }
@@ -951,7 +954,7 @@ private:
}
else if (highlight_.row == row)
return highlight_.rowHover;
- return HoverArea::NONE;
+ return HoverArea::none;
}
bool drawAsSelected(size_t row) const
@@ -976,10 +979,14 @@ private:
{
if (auto prov = refParent().getDataProvider())
{
+ wxClientDC dc(this);
+ dc.SetFont(GetFont());
+
+ const ptrdiff_t rowCount = refParent().getRowCount();
const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition());
const ptrdiff_t row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
- const ColumnPosInfo cpi = refParent().getColumnAtPos(absPos.x); //returns ColumnType::NONE if no column at x position!
- const HoverArea rowHover = prov->getRowMouseHover(row, cpi.colType, cpi.cellRelativePosX, cpi.colWidth);
+ const ColumnPosInfo cpi = refParent().getColumnAtPos(absPos.x); //returns ColumnType::none if no column at x position!
+ const HoverArea rowHover = 0 <= row && row < rowCount ? prov->getRowMouseHover(dc, row, cpi.colType, cpi.cellRelativePosX, cpi.colWidth) : HoverArea::none;
const wxPoint mousePos = GetPosition() + event.GetPosition();
//client is interested in all double-clicks, even those outside of the grid!
@@ -992,40 +999,58 @@ private:
{
if (auto prov = refParent().getDataProvider())
{
+ onMouseMovement(event); //update highlight in obscure cases (e.g. right-click while context menu is open)
+
+ wxClientDC dc(this);
+ dc.SetFont(GetFont());
+
+ const ptrdiff_t rowCount = refParent().getRowCount();
const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition());
const ptrdiff_t row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
- const ColumnPosInfo cpi = refParent().getColumnAtPos(absPos.x); //returns ColumnType::NONE if no column at x position!
- const HoverArea rowHover = prov->getRowMouseHover(row, cpi.colType, cpi.cellRelativePosX, cpi.colWidth);
+ const ColumnPosInfo cpi = refParent().getColumnAtPos(absPos.x); //returns ColumnType::none if no column at x position!
+ const HoverArea rowHover = 0 <= row && row < rowCount ? prov->getRowMouseHover(dc, row, cpi.colType, cpi.cellRelativePosX, cpi.colWidth) : HoverArea::none;
const wxPoint mousePos = GetPosition() + event.GetPosition();
- //row < 0 possible!!! Pressing "Menu Key" simulates mouse-right-button down + up at position 0xffff/0xffff!
+
+ assert(row >= 0);
+ //row < 0 was possible in older wxWidgets: https://github.com/wxWidgets/wxWidgets/commit/2c69d27c0d225d3a331c773da466686153185320#diff-9f11c8f2cb1f734f7c0c1071aba491a5
+ //=> pressing "Menu Key" simulated mouse-right-button down + up at position 0xffff/0xffff!
GridClickEvent mouseEvent(event.RightDown() ? EVENT_GRID_MOUSE_RIGHT_DOWN : EVENT_GRID_MOUSE_LEFT_DOWN, row, rowHover, mousePos);
- if (!sendEventToParent(mouseEvent)) //allow client to swallow event!
+
+ freezeMouseHighlight_ = true; //e.g. while showing context menu
+ const bool processed = sendEventToParent(mouseEvent); //allow client to swallow event!
+ freezeMouseHighlight_ = false;
+
+ if (!processed)
{
if (wxWindow::FindFocus() != this) //doesn't seem to happen automatically for right mouse button
SetFocus();
- if (row >= 0)
- if (!event.RightDown() || !refParent().isSelected(row)) //do NOT start a new selection if user right-clicks on a selected area!
+ if (event.RightDown() && (row < 0 || refParent().isSelected(row))) //=> open context menu *immediately* and do *not* start a new selection
+ sendEventToParent(GridContextMenuEvent(mousePos));
+ else if (row >= 0)
+ {
+ if (event.ControlDown())
+ activeSelection_ = std::make_unique<MouseSelection>(*this, row, !refParent().isSelected(row) /*positive*/, false /*gridWasCleared*/, mouseEvent);
+ else if (event.ShiftDown())
{
- if (event.ControlDown())
- activeSelection_ = std::make_unique<MouseSelection>(*this, row, !refParent().isSelected(row) /*positive*/, false /*gridWasCleared*/, mouseEvent);
- else if (event.ShiftDown())
- {
- refParent().clearSelection(GridEventPolicy::DENY);
- activeSelection_ = std::make_unique<MouseSelection>(*this, selectionAnchor_, true /*positive*/, true /*gridWasCleared*/, mouseEvent);
- }
- else
- {
- refParent().clearSelection(GridEventPolicy::DENY);
- activeSelection_ = std::make_unique<MouseSelection>(*this, row, true /*positive*/, true /*gridWasCleared*/, mouseEvent);
- //DO NOT emit range event for clearing selection! would be inconsistent with keyboard handling (moving cursor neither emits range event)
- //and is also harmful when range event is considered a final action
- //e.g. cfg grid would prematurely show a modal dialog after changed config
- }
+ refParent().clearSelection(GridEventPolicy::deny);
+ activeSelection_ = std::make_unique<MouseSelection>(*this, selectionAnchor_, true /*positive*/, true /*gridWasCleared*/, mouseEvent);
}
- Refresh();
+ else
+ {
+ refParent().clearSelection(GridEventPolicy::deny);
+ activeSelection_ = std::make_unique<MouseSelection>(*this, row, true /*positive*/, true /*gridWasCleared*/, mouseEvent);
+ //DO NOT emit range event for clearing selection! would be inconsistent with keyboard handling (moving cursor neither emits range event)
+ //and is also harmful when range event is considered a final action
+ //e.g. cfg grid would prematurely show a modal dialog after changed config
+ }
+ }
}
+
+ //update mouse highlight (in case it was frozen above)
+ event.SetPosition(ScreenToClient(wxGetMousePosition())); //mouse position may have changed within above callbacks (e.g. context menu was shown)!
+ onMouseMovement(event);
}
event.Skip(); //allow changing focus
}
@@ -1056,29 +1081,39 @@ private:
const ptrdiff_t rowTo = activeSelection_->getCurrentRow();
const bool positive = activeSelection_->isPositiveSelect();
const GridClickEvent mouseClick = activeSelection_->getFirstClick();
+ assert((mouseClick.GetEventType() == EVENT_GRID_MOUSE_RIGHT_DOWN) == event.RightUp());
activeSelection_.reset(); //release mouse capture *before* sending the event (which might show a modal popup dialog requiring the mouse!!!)
- refParent().selectRange(rowFrom, rowTo, positive, &mouseClick, GridEventPolicy::ALLOW);
- }
+ refParent().selectRange(rowFrom, rowTo, positive, &mouseClick, GridEventPolicy::allow);
- if (auto prov = refParent().getDataProvider())
- {
- //this one may point to row which is not in visible area!
- const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition());
- const ptrdiff_t row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
- const ColumnPosInfo cpi = refParent().getColumnAtPos(absPos.x); //returns ColumnType::NONE if no column at x position!
- const HoverArea rowHover = prov->getRowMouseHover(row, cpi.colType, cpi.cellRelativePosX, cpi.colWidth);
- const wxPoint mousePos = GetPosition() + event.GetPosition();
- //notify click event after the range selection! e.g. this makes sure the selection is applied before showing a context menu
- sendEventToParent(GridClickEvent(event.RightUp() ? EVENT_GRID_MOUSE_RIGHT_UP : EVENT_GRID_MOUSE_LEFT_UP, row, rowHover, mousePos));
+ if (mouseClick.GetEventType() == EVENT_GRID_MOUSE_RIGHT_DOWN)
+ sendEventToParent(GridContextMenuEvent(mouseClick.mousePos_));
}
- //update highlight_ and tooltip: on OS X no mouse movement event is generated after a mouse button click (unlike on Windows)
+#if 0
+ if (!event.RightUp())
+ if (auto prov = refParent().getDataProvider())
+ {
+ wxClientDC dc(this);
+ dc.SetFont(GetFont());
+
+ //this one may point to row which is not in visible area!
+ const ptrdiff_t rowCount = refParent().getRowCount();
+ const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition());
+ const ptrdiff_t row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
+ const ColumnPosInfo cpi = refParent().getColumnAtPos(absPos.x); //returns ColumnType::none if no column at x position!
+ const HoverArea rowHover = 0 <= row && row < rowCount ? prov->getRowMouseHover(dc, row, cpi.colType, cpi.cellRelativePosX, cpi.colWidth) : HoverArea::none;
+ const wxPoint mousePos = GetPosition() + event.GetPosition();
+ //notify click event after the range selection! e.g. this makes sure the selection is applied before showing a context menu
+ sendEventToParent(GridClickEvent(EVENT_GRID_MOUSE_LEFT_UP, row, rowHover, mousePos));
+ }
+#endif
+
+ //update mouse highlight and tooltip: macOS no mouse movement event is generated after a mouse button click (unlike on Windows)
event.SetPosition(ScreenToClient(wxGetMousePosition())); //mouse position may have changed within above callbacks (e.g. context menu was shown)!
onMouseMovement(event);
- Refresh();
event.Skip(); //allow changing focus
}
@@ -1087,12 +1122,12 @@ private:
if (activeSelection_)
{
if (activeSelection_->gridWasCleared())
- refParent().clearSelection(GridEventPolicy::ALLOW); //see onMouseDown(); selection is "completed" => emit GridSelectEvent
+ refParent().clearSelection(GridEventPolicy::allow); //see onMouseDown(); selection is "completed" => emit GridSelectEvent
activeSelection_.reset();
+ Refresh();
}
- highlight_.row = -1;
- Refresh();
+ updateMouseHover({-1, HoverArea::none});
//event.Skip(); -> we DID handle it!
}
@@ -1100,15 +1135,17 @@ private:
{
if (auto prov = refParent().getDataProvider())
{
+ wxClientDC dc(this);
+ dc.SetFont(GetFont());
+
const ptrdiff_t rowCount = refParent().getRowCount();
const wxPoint absPos = refParent().CalcUnscrolledPosition(event.GetPosition());
const ptrdiff_t row = rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
- const ColumnPosInfo cpi = refParent().getColumnAtPos(absPos.x); //returns ColumnType::NONE if no column at x position!
- const HoverArea rowHover = prov->getRowMouseHover(row, cpi.colType, cpi.cellRelativePosX, cpi.colWidth);
+ const ColumnPosInfo cpi = refParent().getColumnAtPos(absPos.x); //returns ColumnType::none if no column at x position!
const std::wstring toolTip = [&]
{
- if (cpi.colType != ColumnType::NONE && 0 <= row && row < rowCount)
+ if (cpi.colType != ColumnType::none && 0 <= row && row < rowCount)
return prov->getToolTip(row, cpi.colType);
return std::wstring();
}();
@@ -1118,22 +1155,17 @@ private:
activeSelection_->evalMousePos(); //call on both mouse movement + timer event!
else
{
- refreshHighlight(highlight_);
- highlight_.row = row;
- highlight_.rowHover = rowHover;
- refreshHighlight(highlight_); //multiple Refresh() calls are condensed into single one!
+ const HoverArea rowHover = 0 <= row && row < rowCount ? prov->getRowMouseHover(dc, row, cpi.colType, cpi.cellRelativePosX, cpi.colWidth) : HoverArea::none;
+ updateMouseHover({row, rowHover});
}
}
event.Skip();
}
- void onLeaveWindow(wxMouseEvent& event) override //wxEVT_LEAVE_WINDOW does not respect mouse capture!
+ void onLeaveWindow(wxMouseEvent& event) override
{
- if (!activeSelection_)
- {
- refreshHighlight(highlight_);
- highlight_.row = -1;
- }
+ if (!activeSelection_) //wxEVT_LEAVE_WINDOW does not respect mouse capture!
+ updateMouseHover({-1, HoverArea::none});
event.Skip();
}
@@ -1148,9 +1180,10 @@ private:
wnd_(wnd), rowStart_(rowStart), rowCurrent_(rowStart), positiveSelect_(positive), gridWasCleared_(gridWasCleared), firstClick_(firstClick)
{
wnd_.CaptureMouse();
- timer_.Connect(wxEVT_TIMER, wxEventHandler(MouseSelection::onTimer), nullptr, this);
+ timer_.Bind(wxEVT_TIMER, [this](wxTimerEvent& event) { evalMousePos(); });
timer_.Start(100); //timer interval in ms
evalMousePos();
+ wnd_.Refresh();
}
~MouseSelection() { if (wnd_.HasCapture()) wnd_.ReleaseMouse(); }
@@ -1179,6 +1212,7 @@ private:
int pixelsPerUnitY = 0;
wnd_.refParent().GetScrollPixelsPerUnit(nullptr, &pixelsPerUnitY);
+ assert(pixelsPerUnitY > 0);
if (pixelsPerUnitY <= 0)
return;
@@ -1211,6 +1245,7 @@ private:
const wxPoint absPos = wnd_.refParent().CalcUnscrolledPosition(clientPosTrimmed);
const ptrdiff_t newRow = wnd_.rowLabelWin_.getRowAtPos(absPos.y); //return -1 for invalid position; >= rowCount if out of range
+ assert(newRow >= 0);
if (newRow >= 0)
if (rowCurrent_ != newRow)
{
@@ -1220,8 +1255,6 @@ private:
}
private:
- void onTimer(wxEvent& event) { evalMousePos(); }
-
MainWin& wnd_;
const size_t rowStart_;
ptrdiff_t rowCurrent_;
@@ -1237,7 +1270,9 @@ private:
struct MouseHighlight
{
ptrdiff_t row = -1;
- HoverArea rowHover = HoverArea::NONE;
+ HoverArea rowHover = HoverArea::none;
+
+ bool operator==(const MouseHighlight&) const = default;
};
void ScrollWindow(int dx, int dy, const wxRect* rect) override
@@ -1266,7 +1301,7 @@ private:
assert(gridUpdatePending_);
ZEN_ON_SCOPE_EXIT(gridUpdatePending_ = false);
- refParent().updateWindowSizes(false); //row label width has changed -> do *not* update scrollbars: recursion on wxGTK! -> still a problem, now that we're called async??
+ refParent().updateWindowSizes(false); //row label width has changed -> do *not* update scrollbars: recursion on wxGTK! -> still a problem, now that this function is called async??
rowLabelWin_.Update(); //update while dragging scroll thumb
}
@@ -1278,18 +1313,27 @@ private:
RefreshRect(cellArea, false);
}
- void refreshHighlight(const MouseHighlight& hl)
+ void updateMouseHover(const MouseHighlight& hl)
{
- const ptrdiff_t rowCount = refParent().getRowCount();
- if (0 <= hl.row && hl.row < rowCount && hl.rowHover != HoverArea::NONE) //no highlight_? => NOP!
- refreshRow(hl.row);
+ if (highlight_ != hl && !freezeMouseHighlight_)
+ {
+ const ptrdiff_t rowCount = refParent().getRowCount();
+ if (0 <= highlight_.row && highlight_.row < rowCount && highlight_.rowHover != HoverArea::none) //no highlight_? => NOP!
+ refreshRow(highlight_.row);
+
+ highlight_ = hl;
+
+ if (0 <= highlight_.row && highlight_.row < rowCount && highlight_.rowHover != HoverArea::none) //no highlight_? => NOP!
+ refreshRow(highlight_.row);
+ }
}
RowLabelWin& rowLabelWin_;
ColLabelWin& colLabelWin_;
std::unique_ptr<MouseSelection> activeSelection_; //bound while user is selecting with mouse
- MouseHighlight highlight_; //current mouse highlight_ (superseded by activeSelection_ if available)
+ MouseHighlight highlight_; //current mouse highlight
+ bool freezeMouseHighlight_ = false;
ptrdiff_t cursorRow_ = 0;
size_t selectionAnchor_ = 0;
@@ -1326,12 +1370,11 @@ Grid::Grid(wxWindow* parent,
assert(GetClientSize() == GetSize() && GetWindowBorderSize() == wxSize()); //borders are NOT allowed for Grid
//reason: updateWindowSizes() wants to use "GetSize()" as a "GetClientSize()" including scrollbars
- Connect(wxEVT_PAINT, wxPaintEventHandler(Grid::onPaintEvent), nullptr, this);
- Connect(wxEVT_SIZE, wxSizeEventHandler (Grid::onSizeEvent ), nullptr, this);
+ Bind(wxEVT_PAINT, [this](wxPaintEvent& event) { wxPaintDC dc(this); });
+ Bind(wxEVT_SIZE, [this](wxSizeEvent& event) { updateWindowSizes(); event.Skip(); });
Bind(wxEVT_ERASE_BACKGROUND, [](wxEraseEvent& event) {}); //https://wiki.wxwidgets.org/Flicker-Free_Drawing
- Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(Grid::onKeyDown), nullptr, this);
- Connect(wxEVT_KEY_UP, wxKeyEventHandler(Grid::onKeyUp ), nullptr, this);
+ Bind(wxEVT_KEY_DOWN, [this](wxKeyEvent& event) { onKeyDown(event); });
}
@@ -1522,12 +1565,12 @@ wxSize Grid::GetSizeAvailableForScrollTarget(const wxSize& size)
//lame hard-coded numbers (from Ubuntu 19.10) and openSuse
//=> let's have a *close* eye on scrollbar fluctuation!
- assert(scrollBarSizeTmp.x == 0 ||
- scrollBarSizeTmp.x == 6 || scrollBarSizeTmp.x == 13 || //Ubuntu 19.10
- scrollBarSizeTmp.x == 16); //openSuse
- assert(scrollBarSizeTmp.y == 0 ||
- scrollBarSizeTmp.y == 6 || scrollBarSizeTmp.y == 13 || //Ubuntu 19.10
- scrollBarSizeTmp.y == 16); //openSuse
+ assert(scrollBarSizeTmp.x == 0 ||
+ scrollBarSizeTmp.x == 6 || scrollBarSizeTmp.x == 13 || //Ubuntu 19.10
+ scrollBarSizeTmp.x == 16); //openSuse
+ assert(scrollBarSizeTmp.y == 0 ||
+ scrollBarSizeTmp.y == 6 || scrollBarSizeTmp.y == 13 || //Ubuntu 19.10
+ scrollBarSizeTmp.y == 16); //openSuse
#else
#error unknown GTK version!
#endif
@@ -1550,35 +1593,6 @@ wxSize Grid::GetSizeAvailableForScrollTarget(const wxSize& size)
}
-void Grid::onPaintEvent(wxPaintEvent& event) { wxPaintDC dc(this); }
-
-
-void Grid::onKeyUp(wxKeyEvent& event)
-{
- int keyCode = event.GetKeyCode();
- if (event.ShiftDown() && keyCode == WXK_F10) //== alias for menu key
- keyCode = WXK_WINDOWS_MENU;
-
- switch (keyCode)
- {
- case WXK_MENU: //
- case WXK_WINDOWS_MENU: //simulate right mouse click at cursor(+1) position
- {
- const int cursorNextPosY = rowLabelWin_->getRowHeight() * std::min(getRowCount(), mainWin_->getCursor() + 1);
- const int clientPosMainWinY = std::clamp(CalcScrolledPosition(wxPoint(0, cursorNextPosY)).y, //absolute -> client coordinates
- 0, mainWin_->GetClientSize().GetHeight() - 1);
- const wxPoint mousePos = mainWin_->GetPosition() + wxPoint(0, clientPosMainWinY); //mainWin_-relative to Grid-relative
-
- GridClickEvent clickEvent(EVENT_GRID_MOUSE_RIGHT_UP, -1, HoverArea::NONE, mousePos);
- if (wxEvtHandler* evtHandler = GetEventHandler())
- evtHandler->ProcessEvent(clickEvent);
- }
- return;
- }
- event.Skip();
-}
-
-
void Grid::onKeyDown(wxKeyEvent& event)
{
int keyCode = event.GetKeyCode();
@@ -1600,7 +1614,7 @@ void Grid::onKeyDown(wxKeyEvent& event)
if (rowCount > 0)
{
row = std::clamp<ptrdiff_t>(row, 0, rowCount - 1);
- setGridCursor(row, GridEventPolicy::ALLOW);
+ setGridCursor(row, GridEventPolicy::allow);
}
};
@@ -1616,16 +1630,16 @@ void Grid::onKeyDown(wxKeyEvent& event)
switch (keyCode)
{
case WXK_MENU: //
- case WXK_WINDOWS_MENU: //simulate right mouse click at cursor(+1) position
+ case WXK_WINDOWS_MENU: //simulate right mouse click at cursor row (+1) position
{
const int cursorNextPosY = rowLabelWin_->getRowHeight() * std::min(getRowCount(), mainWin_->getCursor() + 1);
const int clientPosMainWinY = std::clamp(CalcScrolledPosition(wxPoint(0, cursorNextPosY)).y, //absolute -> client coordinates
0, mainWin_->GetClientSize().GetHeight() - 1);
const wxPoint mousePos = mainWin_->GetPosition() + wxPoint(0, clientPosMainWinY); //mainWin_-relative to Grid-relative
- GridClickEvent clickEvent(EVENT_GRID_MOUSE_RIGHT_DOWN, -1, HoverArea::NONE, mousePos);
+ GridContextMenuEvent contextEvent(mousePos);
if (wxEvtHandler* evtHandler = GetEventHandler())
- evtHandler->ProcessEvent(clickEvent);
+ evtHandler->ProcessEvent(contextEvent);
}
return;
@@ -1716,12 +1730,12 @@ void Grid::onKeyDown(wxKeyEvent& event)
case 'A': //Ctrl + A - select all
if (event.ControlDown())
- selectRange(0, rowCount, true /*positive*/, nullptr /*mouseInitiated*/, GridEventPolicy::ALLOW);
+ selectRange(0, rowCount, true /*positive*/, nullptr /*mouseClick*/, GridEventPolicy::allow);
break;
case WXK_NUMPAD_ADD: //CTRL + '+' - auto-size all
if (event.ControlDown())
- autoSizeColumns(GridEventPolicy::ALLOW);
+ autoSizeColumns(GridEventPolicy::allow);
return;
}
@@ -1743,60 +1757,41 @@ void Grid::showRowLabel(bool show)
}
-void Grid::selectRow(size_t row, GridEventPolicy rangeEventPolicy)
-{
- selection_.selectRow(row);
- mainWin_->Refresh();
-
- if (rangeEventPolicy == GridEventPolicy::ALLOW)
- {
- GridSelectEvent selEvent(row, row + 1, true, nullptr /*mouseClick*/);
- if (wxEvtHandler* evtHandler = GetEventHandler())
- evtHandler->ProcessEvent(selEvent);
- }
-}
-
-
-void Grid::selectAllRows(GridEventPolicy rangeEventPolicy)
+void Grid::selectRange(size_t rowFirst, size_t rowLast, bool positive, GridEventPolicy rangeEventPolicy)
{
- selection_.selectAll();
+ selection_.selectRange(rowFirst, rowLast, positive);
mainWin_->Refresh();
- if (rangeEventPolicy == GridEventPolicy::ALLOW)
+ if (rangeEventPolicy == GridEventPolicy::allow)
{
- GridSelectEvent selEvent(0, getRowCount(), true /*positive*/, nullptr /*mouseClick*/);
+ GridSelectEvent selEvent(rowFirst, rowLast, positive, nullptr /*mouseClick*/);
if (wxEvtHandler* evtHandler = GetEventHandler())
- evtHandler->ProcessEvent(selEvent);
+ /*bool processed = */evtHandler->ProcessEvent(selEvent);
}
}
-void Grid::clearSelection(GridEventPolicy rangeEventPolicy)
-{
- selection_.clear();
- mainWin_->Refresh();
-
- if (rangeEventPolicy == GridEventPolicy::ALLOW)
- {
- GridSelectEvent unselectionEvent(0, getRowCount(), false /*positive*/, nullptr /*mouseClick*/);
- if (wxEvtHandler* evtHandler = GetEventHandler())
- evtHandler->ProcessEvent(unselectionEvent);
- }
-}
+void Grid::selectRow(size_t row, GridEventPolicy rangeEventPolicy) { selectRange(row, row + 1, true /*positive*/, rangeEventPolicy); }
+void Grid::selectAllRows (GridEventPolicy rangeEventPolicy) { selectRange(0, selection_.gridSize(), true /*positive*/, rangeEventPolicy); }
+void Grid::clearSelection (GridEventPolicy rangeEventPolicy) { selectRange(0, selection_.gridSize(), false /*positive*/, rangeEventPolicy); }
void Grid::scrollDelta(int deltaX, int deltaY)
{
- wxPoint scrollPos = GetViewStart();
+ const wxPoint scrollPosOld = GetViewStart();
- scrollPos.x += deltaX;
- scrollPos.y += deltaY;
+ wxPoint scrollPosNew = scrollPosOld;
+ scrollPosNew.x += deltaX;
+ scrollPosNew.y += deltaY;
- scrollPos.x = std::max(0, scrollPos.x); //wxScrollHelper::Scroll() will exit prematurely if input happens to be "-1"!
- scrollPos.y = std::max(0, scrollPos.y); //
+ scrollPosNew.x = std::max(0, scrollPosNew.x); //wxScrollHelper::Scroll() will exit prematurely if input happens to be "-1"!
+ scrollPosNew.y = std::max(0, scrollPosNew.y); //
- Scroll(scrollPos); //internally calls wxWindows::Update()!
- updateWindowSizes(); //may show horizontal scroll bar if row column gets wider
+ if (scrollPosNew != scrollPosOld)
+ {
+ Scroll(scrollPosNew); //internally calls wxWindows::Update()!
+ updateWindowSizes(); //may show horizontal scroll bar if row column gets wider
+ }
}
@@ -1826,7 +1821,7 @@ void Grid::Refresh(bool eraseBackground, const wxRect* rect)
updateWindowSizes();
}
- if (selection_.maxSize() != rowCountNew) //clear selection only when needed (consider setSelectedRows())
+ if (selection_.gridSize() != rowCountNew) //clear selection only when needed (consider setSelectedRows())
selection_.init(rowCountNew);
wxScrolledWindow::Refresh(eraseBackground, rect);
@@ -1850,7 +1845,7 @@ void Grid::setColumnConfig(const std::vector<Grid::ColAttributes>& attr)
for (const ColAttributes& ca : attr)
{
assert(ca.stretch >= 0);
- assert(ca.type != ColumnType::NONE);
+ assert(ca.type != ColumnType::none);
if (ca.visible)
visCols.push_back({ ca.type, ca.offset, std::max(ca.stretch, 0) });
@@ -2003,7 +1998,7 @@ ColumnType Grid::colToType(size_t col) const
{
if (col < visibleCols_.size())
return visibleCols_[col].type;
- return ColumnType::NONE;
+ return ColumnType::none;
}
@@ -2022,7 +2017,7 @@ Grid::ColumnPosInfo Grid::getColumnAtPos(int posX) const
return { cw.type, posX + cw.width - accWidth, cw.width };
}
}
- return { ColumnType::NONE, 0, 0 };
+ return { ColumnType::none, 0, 0 };
}
@@ -2066,7 +2061,7 @@ void Grid::setGridCursor(size_t row, GridEventPolicy rangeEventPolicy)
makeRowVisible(row);
selection_.clear(); //clear selection, do NOT fire event
- selectRange(row, row, true /*positive*/, nullptr /*mouseInitiated*/, rangeEventPolicy); //set new selection + fire event
+ selectRange(row, row, true /*positive*/, nullptr /*mouseClick*/, rangeEventPolicy); //set new selection + fire event
}
@@ -2078,7 +2073,7 @@ void Grid::selectWithCursor(ptrdiff_t row) //emits GridSelectEvent
makeRowVisible(row);
selection_.clear(); //clear selection, do NOT fire event
- selectRange(anchorRow, row, true /*positive*/, nullptr /*mouseInitiated*/, GridEventPolicy::ALLOW); //set new selection + fire event
+ selectRange(anchorRow, row, true /*positive*/, nullptr /*mouseClick*/, GridEventPolicy::allow); //set new selection + fire event
}
@@ -2138,11 +2133,11 @@ void Grid::selectRange(ptrdiff_t rowFrom, ptrdiff_t rowTo, bool positive, const
selection_.selectRange(rowFirst, rowLast, positive);
mainWin_->Refresh();
- if (rangeEventPolicy == GridEventPolicy::ALLOW)
+ if (rangeEventPolicy == GridEventPolicy::allow)
{
GridSelectEvent selectionEvent(rowFirst, rowLast, positive, mouseClick);
if (wxEvtHandler* evtHandler = GetEventHandler())
- evtHandler->ProcessEvent(selectionEvent);
+ /*bool processed = */evtHandler->ProcessEvent(selectionEvent);
}
}
@@ -2243,7 +2238,7 @@ void Grid::setColumnWidth(int width, size_t col, GridEventPolicy columnResizeEve
if (visibleCols_[col2].stretch > 0) //normalize stretched columns only
visibleCols_[col2].offset = std::max(visibleCols_[col2].offset, fastFromDIP(COLUMN_MIN_WIDTH_DIP) - stretchedWidths[col2]);
- if (columnResizeEventPolicy == GridEventPolicy::ALLOW)
+ if (columnResizeEventPolicy == GridEventPolicy::allow)
{
GridColumnResizeEvent sizeEvent(vcRs.offset, vcRs.type);
if (wxEvtHandler* evtHandler = GetEventHandler())
diff --git a/wx+/grid.h b/wx+/grid.h
index 05710e3f..43a1d2a0 100644
--- a/wx+/grid.h
+++ b/wx+/grid.h
@@ -19,28 +19,33 @@
//a user-friendly, extensible and high-performance grid control
namespace zen
{
-enum class ColumnType { NONE = -1 }; //user-defiend column type
-enum class HoverArea { NONE = -1 }; //user-defined area for mouse selections for a given row (may span multiple columns or split a single column into multiple areas)
-
-//wxContextMenuEvent? => automatically generated by wxWidgets when right mouse down/up is not handled; even OS-dependent in which case event is generated
-//=> inappropriate! client decides when to show context! => simulate right mouse click when WXK_WINDOWS_MENU button is pressed
-//=> same behavior as earlier wxWidgets: https://github.com/wxWidgets/wxWidgets/commit/2c69d27c0d225d3a331c773da466686153185320#diff-9f11c8f2cb1f734f7c0c1071aba491a5
+enum class ColumnType { none = -1 }; //user-defiend column type
+enum class HoverArea { none = -1 }; //user-defined area for mouse selections for a given row (may span multiple columns or split a single column into multiple areas)
//------------------------ events ------------------------------------------------
-extern const wxEventType EVENT_GRID_MOUSE_LEFT_DOUBLE; //
-extern const wxEventType EVENT_GRID_MOUSE_LEFT_DOWN; //
-extern const wxEventType EVENT_GRID_MOUSE_LEFT_UP; //generates: GridClickEvent
-extern const wxEventType EVENT_GRID_MOUSE_RIGHT_DOWN; //
-extern const wxEventType EVENT_GRID_MOUSE_RIGHT_UP; //
+//example: wnd.Bind(EVENT_GRID_COL_LABEL_LEFT_CLICK, [this](GridClickEvent& event) { onGridLeftClick(event); });
+
+struct GridClickEvent;
+struct GridSelectEvent;
+struct GridLabelClickEvent;
+struct GridColumnResizeEvent;
+struct GridContextMenuEvent;
+
+wxDECLARE_EVENT(EVENT_GRID_MOUSE_LEFT_DOUBLE, GridClickEvent);
+wxDECLARE_EVENT(EVENT_GRID_MOUSE_LEFT_DOWN, GridClickEvent);
+wxDECLARE_EVENT(EVENT_GRID_MOUSE_RIGHT_DOWN, GridClickEvent);
-extern const wxEventType EVENT_GRID_SELECT_RANGE; //generates: GridSelectEvent
+wxDECLARE_EVENT(EVENT_GRID_SELECT_RANGE, GridSelectEvent);
//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...
-extern const wxEventType EVENT_GRID_COL_LABEL_MOUSE_LEFT; //generates: GridLabelClickEvent
-extern const wxEventType EVENT_GRID_COL_LABEL_MOUSE_RIGHT; //
-extern const wxEventType EVENT_GRID_COL_RESIZE; //generates: GridColumnResizeEvent
+wxDECLARE_EVENT(EVENT_GRID_COL_LABEL_MOUSE_LEFT, GridLabelClickEvent);
+wxDECLARE_EVENT(EVENT_GRID_COL_LABEL_MOUSE_RIGHT, GridLabelClickEvent);
+wxDECLARE_EVENT(EVENT_GRID_COL_RESIZE, GridColumnResizeEvent);
+
+//wxContextMenuEvent? => generated by wxWidgets when right mouse down/up is not handled; even OS-dependent in which case event is generated
+//=> inappropriate! we know better when to show context!
+wxDECLARE_EVENT(EVENT_GRID_CONTEXT_MENU, GridContextMenuEvent);
-//example: wnd.Connect(EVENT_GRID_COL_LABEL_LEFT_CLICK, GridClickEventHandler(MyDlg::OnLeftClick), nullptr, this);
struct GridClickEvent : public wxEvent
{
@@ -49,7 +54,7 @@ struct GridClickEvent : public wxEvent
GridClickEvent* Clone() const override { return new GridClickEvent(*this); }
const ptrdiff_t row_; //-1 for invalid position, >= rowCount if out of range
- const HoverArea hoverArea_; //may be HoverArea::NONE
+ const HoverArea hoverArea_; //may be HoverArea::none
const wxPoint mousePos_; //client coordinates
};
@@ -71,7 +76,7 @@ struct GridLabelClickEvent : public wxEvent
GridLabelClickEvent(wxEventType et, ColumnType colType) : wxEvent(0 /*winid*/, et), colType_(colType) {}
GridLabelClickEvent* Clone() const override { return new GridLabelClickEvent(*this); }
- const ColumnType colType_; //may be ColumnType::NONE
+ const ColumnType colType_; //may be ColumnType::none
};
struct GridColumnResizeEvent : public wxEvent
@@ -83,16 +88,13 @@ struct GridColumnResizeEvent : public wxEvent
const int offset_;
};
-using GridClickEventFunction = void (wxEvtHandler::*)(GridClickEvent&);
-using GridSelectEventFunction = void (wxEvtHandler::*)(GridSelectEvent&);
-using GridLabelClickEventFunction = void (wxEvtHandler::*)(GridLabelClickEvent&);
-using GridColumnResizeEventFunction = void (wxEvtHandler::*)(GridColumnResizeEvent&);
-
-#define GridClickEventHandler(func) (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(GridClickEventFunction, &func)
-#define GridSelectEventHandler(func) (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(GridSelectEventFunction, &func)
-#define GridLabelClickEventHandler(func) (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(GridLabelClickEventFunction, &func)
-#define GridColumnResizeEventHandler(func)(wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(GridColumnResizeEventFunction, &func)
+struct GridContextMenuEvent : public wxEvent
+{
+ explicit GridContextMenuEvent(const wxPoint& mousePos) : wxEvent(0 /*winid*/, EVENT_GRID_CONTEXT_MENU), mousePos_(mousePos) {}
+ GridContextMenuEvent* Clone() const override { return new GridContextMenuEvent(*this); }
+ const wxPoint mousePos_; //client coordinates
+};
//------------------------------------------------------------------------------------------------------------
class Grid;
@@ -110,8 +112,8 @@ public:
virtual void renderRowBackgound(wxDC& dc, const wxRect& rect, size_t row, bool enabled, bool selected); //default implementation
virtual void renderCell (wxDC& dc, const wxRect& rect, size_t row, ColumnType colType, bool enabled, bool selected, HoverArea rowHover);
virtual int getBestSize (wxDC& dc, size_t row, ColumnType colType); //must correspond to renderCell()!
+ virtual HoverArea getRowMouseHover (wxDC& dc, size_t row, ColumnType colType, int cellRelativePosX, int cellWidth) { return HoverArea::none; }
virtual std::wstring getToolTip (size_t row, ColumnType colType) const { return std::wstring(); }
- virtual HoverArea getRowMouseHover (size_t row, ColumnType colType, int cellRelativePosX, int cellWidth) { return HoverArea::NONE; }
//label area:
virtual std::wstring getColumnLabel(ColumnType colType) const = 0;
@@ -126,7 +128,6 @@ public:
static void drawCellText(wxDC& dc, const wxRect& rect, const std::wstring& text,
int alignment = wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL, const wxSize* textExtentHint = nullptr); //returns text extent
static wxRect drawCellBorder (wxDC& dc, const wxRect& rect); //returns inner rectangle
- static void drawCellBackground(wxDC& dc, const wxRect& rect, bool enabled, bool selected, const wxColor& backgroundColor);
static wxRect drawColumnLabelBackground(wxDC& dc, const wxRect& rect, bool highlighted); //returns inner rectangle
static void drawColumnLabelText (wxDC& dc, const wxRect& rect, const std::wstring& text, bool enabled);
@@ -135,8 +136,8 @@ public:
enum class GridEventPolicy
{
- ALLOW,
- DENY
+ allow,
+ deny
};
@@ -148,7 +149,7 @@ public:
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxTAB_TRAVERSAL | wxNO_BORDER,
- const wxString& name = wxPanelNameStr);
+ const wxString& name = wxASCII_STR(wxPanelNameStr));
size_t getRowCount() const;
@@ -156,7 +157,7 @@ public:
struct ColAttributes
{
- ColumnType type = ColumnType::NONE;
+ ColumnType type = ColumnType::none;
//first, client width is partitioned according to all available stretch factors, then "offset_" is added
//universal model: a non-stretched column has stretch factor 0 with the "offset" becoming identical to final width!
int offset = 0;
@@ -185,9 +186,11 @@ public:
void showScrollBars(ScrollBarStatus horizontal, ScrollBarStatus vertical);
std::vector<size_t> getSelectedRows() const { return selection_.get(); }
+
void selectRow(size_t row, GridEventPolicy rangeEventPolicy);
void selectAllRows (GridEventPolicy rangeEventPolicy); //turn off range selection event when calling this function in an event handler to avoid recursion!
void clearSelection(GridEventPolicy rangeEventPolicy); //
+ void selectRange(size_t rowFirst, size_t rowLast, bool positive, GridEventPolicy rangeEventPolicy); //select [rowFirst, rowLast)
void scrollDelta(int deltaX, int deltaY); //in scroll units
@@ -201,7 +204,7 @@ public:
struct ColumnPosInfo
{
- ColumnType colType = ColumnType::NONE; //ColumnType::NONE no column at x position!
+ ColumnType colType = ColumnType::none; //ColumnType::none no column at x position!
int cellRelativePosX = 0;
int colWidth = 0;
};
@@ -226,10 +229,7 @@ public:
//############################################################################################################
private:
- void onPaintEvent(wxPaintEvent& event);
- void onSizeEvent(wxSizeEvent& event) { updateWindowSizes(); event.Skip(); }
void onKeyDown(wxKeyEvent& event);
- void onKeyUp (wxKeyEvent& event);
void updateWindowSizes(bool updateScrollbar = true);
@@ -256,7 +256,7 @@ private:
public:
void init(size_t rowCount) { selected_.resize(rowCount); clear(); }
- size_t maxSize() const { return selected_.size(); }
+ size_t gridSize() const { return selected_.size(); }
std::vector<size_t> get() const
{
@@ -267,9 +267,7 @@ private:
return result;
}
- void selectRow(size_t row) { selectRange(row, row + 1, true); }
- void selectAll () { selectRange(0, selected_.size(), true); }
- void clear () { selectRange(0, selected_.size(), false); }
+ void clear() { selectRange(0, selected_.size(), false); }
bool isSelected(size_t row) const { return row < selected_.size() ? selected_[row] != 0 : false; }
@@ -291,14 +289,14 @@ private:
struct VisibleColumn
{
- ColumnType type = ColumnType::NONE;
+ ColumnType type = ColumnType::none;
int offset = 0;
int stretch = 0; //>= 0
};
struct ColumnWidth
{
- ColumnType type = ColumnType::NONE;
+ ColumnType type = ColumnType::none;
int width = 0;
};
std::vector<ColumnWidth> getColWidths() const; //
@@ -332,7 +330,7 @@ private:
void moveColumn(size_t colFrom, size_t colTo);
ptrdiff_t clientPosToMoveTargetColumn(const wxPoint& pos) const; //return < 0 on error
- ColumnType colToType(size_t col) const; //returns ColumnType::NONE on error
+ ColumnType colToType(size_t col) const; //returns ColumnType::none on error
/* Grid window layout:
_______________________________
diff --git a/wx+/image_resources.cpp b/wx+/image_resources.cpp
index d09e5dfa..b89abe6d 100644
--- a/wx+/image_resources.cpp
+++ b/wx+/image_resources.cpp
@@ -128,7 +128,7 @@ private:
Protected<std::vector<std::pair<std::string, ImageHolder>>> result_;
using TaskType = FunctionReturnTypeT<decltype(&getScalerTask)>;
- std::optional<ThreadGroup<TaskType>> threadGroup_{ ThreadGroup<TaskType>(std::max<int>(std::thread::hardware_concurrency(), 1), "xBRZ Scaler") };
+ std::optional<ThreadGroup<TaskType>> threadGroup_{ ThreadGroup<TaskType>(std::max<int>(std::thread::hardware_concurrency(), 1), Zstr("xBRZ Scaler")) };
//hardware_concurrency() == 0 if "not computable or well defined"
};
@@ -182,7 +182,7 @@ ImageBuffer::ImageBuffer(const Zstring& zipPath) //throw FileError
try //to load from ZIP first:
{
//wxFFileInputStream/wxZipInputStream loads in junks of 512 bytes => WTF!!! => implement sane file loading:
- const std::string rawStream = loadBinContainer<std::string>(zipPath, nullptr /*notifyUnbufferedIO*/); //throw FileError
+ const std::string rawStream = getFileContent(zipPath, nullptr /*notifyUnbufferedIO*/); //throw FileError
wxMemoryInputStream memStream(rawStream.c_str(), rawStream.size()); //does not take ownership
wxZipInputStream zipStream(memStream, wxConvUTF8);
//do NOT rely on wxConvLocal! On failure shows unhelpful popup "Cannot convert from the charset 'Unknown encoding (-1)'!"
@@ -195,11 +195,11 @@ ImageBuffer::ImageBuffer(const Zstring& zipPath) //throw FileError
}
catch (FileError&) //fall back to folder
{
- traverseFolder(beforeLast(zipPath, Zstr(".zip"), IF_MISSING_RETURN_NONE), [&](const FileInfo& fi)
+ traverseFolder(beforeLast(zipPath, Zstr(".zip"), IfNotFoundReturn::none), [&](const FileInfo& fi)
{
if (endsWith(fi.fullPath, Zstr(".png")))
{
- std::string stream = loadBinContainer<std::string>(fi.fullPath, nullptr /*notifyUnbufferedIO*/); //throw FileError
+ std::string stream = getFileContent(fi.fullPath, nullptr /*notifyUnbufferedIO*/); //throw FileError
streams.emplace_back(fi.itemName, std::move(stream));
}
}, nullptr, nullptr, [](const std::wstring& errorMsg) { throw FileError(errorMsg); });
@@ -227,7 +227,7 @@ ImageBuffer::ImageBuffer(const Zstring& zipPath) //throw FileError
//=> there's only one type of wxImage: with alpha channel, no mask!!!
convertToVanillaImage(img);
- const std::string imageName = utfTo<std::string>(beforeLast(fileName, Zstr("."), IF_MISSING_RETURN_NONE));
+ const std::string imageName = utfTo<std::string>(beforeLast(fileName, Zstr("."), IfNotFoundReturn::none));
imagesRaw_.emplace(imageName, img);
if (hqScaler_)
@@ -311,7 +311,7 @@ std::unique_ptr<ImageBuffer> globalImageBuffer;
void zen::imageResourcesInit(const Zstring& zipPath) //throw FileError
{
- assert(runningMainThread()); //wxWidgets is not thread-safe!
+ assert(runningOnMainThread()); //wxWidgets is not thread-safe!
assert(!globalImageBuffer);
globalImageBuffer = std::make_unique<ImageBuffer>(zipPath); //throw FileError
}
@@ -319,7 +319,7 @@ void zen::imageResourcesInit(const Zstring& zipPath) //throw FileError
void zen::ImageResourcesCleanup()
{
- assert(runningMainThread()); //wxWidgets is not thread-safe!
+ assert(runningOnMainThread()); //wxWidgets is not thread-safe!
assert(globalImageBuffer);
globalImageBuffer.reset();
}
@@ -327,7 +327,7 @@ void zen::ImageResourcesCleanup()
const wxImage& zen::loadImage(const std::string& name, int maxWidth /*optional*/, int maxHeight /*optional*/)
{
- assert(runningMainThread()); //wxWidgets is not thread-safe!
+ assert(runningOnMainThread()); //wxWidgets is not thread-safe!
assert(globalImageBuffer);
if (globalImageBuffer)
return globalImageBuffer->getImage(name, maxWidth, maxHeight);
diff --git a/wx+/image_tools.cpp b/wx+/image_tools.cpp
index 19ba6ba6..4569a2a7 100644
--- a/wx+/image_tools.cpp
+++ b/wx+/image_tools.cpp
@@ -70,7 +70,7 @@ void copySubImage(const wxImage& src, wxPoint srcPos,
void copyImageLayover(const wxImage& src,
- /**/ wxImage& trg, wxPoint trgPos)
+ /**/ wxImage& trg, wxPoint trgPos)
{
const int srcWidth = src.GetWidth ();
const int srcHeight = src.GetHeight();
@@ -119,7 +119,7 @@ std::vector<std::pair<wxString, wxSize>> getTextExtentInfo(const wxString& text,
dc.SetFont(font); //the font parameter of GetMultiLineTextExtent() is not evaluated on OS X, wxWidgets 2.9.5, so apply it to the DC directly!
std::vector<std::pair<wxString, wxSize>> lineInfo; //text + extent
- for (const wxString& line : split(text, L'\n', SplitType::ALLOW_EMPTY))
+ for (const wxString& line : split(text, L'\n', SplitOnEmpty::allow))
lineInfo.emplace_back(line, line.empty() ? wxSize() : dc.GetTextExtent(line));
return lineInfo;
diff --git a/wx+/popup_dlg.cpp b/wx+/popup_dlg.cpp
index bdb904f2..ffde9824 100644
--- a/wx+/popup_dlg.cpp
+++ b/wx+/popup_dlg.cpp
@@ -173,7 +173,7 @@ public:
else
m_checkBoxCustom->Hide();
- Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(StandardPopupDialog::OnKeyPressed), nullptr, this); //dialog-specific local key events
+ Bind(wxEVT_CHAR_HOOK, [this](wxKeyEvent& event) { onLocalKeyEvent(event); }); //dialog-specific local key events
//------------------------------------------------------------------------------
StdButtons stdBtns;
@@ -225,31 +225,31 @@ public:
}
private:
- void OnClose (wxCloseEvent& event) override { EndModal(static_cast<int>(ConfirmationButton3::cancel)); }
- void OnCancel(wxCommandEvent& event) override { EndModal(static_cast<int>(ConfirmationButton3::cancel)); }
+ void onClose (wxCloseEvent& event) override { EndModal(static_cast<int>(ConfirmationButton3::cancel)); }
+ void onCancel(wxCommandEvent& event) override { EndModal(static_cast<int>(ConfirmationButton3::cancel)); }
- void OnButtonAccept(wxCommandEvent& event) override
+ void onButtonAccept(wxCommandEvent& event) override
{
if (checkBoxValue_)
*checkBoxValue_ = m_checkBoxCustom->GetValue();
EndModal(static_cast<int>(ConfirmationButton3::accept));
}
- void OnButtonAcceptAll(wxCommandEvent& event) override
+ void onButtonAcceptAll(wxCommandEvent& event) override
{
if (checkBoxValue_)
*checkBoxValue_ = m_checkBoxCustom->GetValue();
EndModal(static_cast<int>(ConfirmationButton3::acceptAll));
}
- void OnButtonDecline(wxCommandEvent& event) override
+ void onButtonDecline(wxCommandEvent& event) override
{
if (checkBoxValue_)
*checkBoxValue_ = m_checkBoxCustom->GetValue();
EndModal(static_cast<int>(ConfirmationButton3::decline));
}
- void OnKeyPressed(wxKeyEvent& event)
+ void onLocalKeyEvent(wxKeyEvent& event)
{
switch (event.GetKeyCode())
{
@@ -257,7 +257,7 @@ private:
case WXK_NUMPAD_ENTER:
{
wxCommandEvent dummy(wxEVT_COMMAND_BUTTON_CLICKED);
- OnButtonAccept(dummy);
+ onButtonAccept(dummy);
return;
}
@@ -268,7 +268,7 @@ private:
event.Skip();
}
- void OnCheckBoxClick(wxCommandEvent& event) override { updateGui(); event.Skip(); }
+ void onCheckBoxClick(wxCommandEvent& event) override { updateGui(); event.Skip(); }
void updateGui()
{
diff --git a/wx+/popup_dlg_generated.cpp b/wx+/popup_dlg_generated.cpp
index 7fc05d53..b9da4c38 100644
--- a/wx+/popup_dlg_generated.cpp
+++ b/wx+/popup_dlg_generated.cpp
@@ -11,91 +11,91 @@
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 ) );
+ this->SetSizeHints( wxSize( -1, -1 ), wxDefaultSize );
+ this->SetBackgroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE ) );
- wxBoxSizer* bSizer24;
- bSizer24 = new wxBoxSizer( wxVERTICAL );
+ 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 ) );
+ 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 );
+ 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 );
+ 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 );
+ wxBoxSizer* bSizer16;
+ bSizer16 = new wxBoxSizer( wxVERTICAL );
- bSizer16->Add( 0, 10, 0, 0, 5 );
+ bSizer16->Add( 0, 10, 0, 0, 5 );
- m_staticTextMain = new wxStaticText( m_panel33, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
- m_staticTextMain->Wrap( -1 );
- bSizer16->Add( m_staticTextMain, 0, wxRIGHT, 10 );
+ m_staticTextMain = new wxStaticText( m_panel33, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ m_staticTextMain->Wrap( -1 );
+ bSizer16->Add( m_staticTextMain, 0, wxRIGHT, 10 );
- bSizer16->Add( 0, 5, 0, 0, 5 );
+ bSizer16->Add( 0, 5, 0, 0, 5 );
- m_textCtrlTextDetail = new wxTextCtrl( m_panel33, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxBORDER_NONE );
- bSizer16->Add( m_textCtrlTextDetail, 1, wxEXPAND, 5 );
+ m_textCtrlTextDetail = new wxTextCtrl( m_panel33, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxBORDER_NONE );
+ bSizer16->Add( m_textCtrlTextDetail, 1, wxEXPAND, 5 );
- bSizer165->Add( bSizer16, 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, wxEXPAND, 5 );
+ m_panel33->SetSizer( bSizer165 );
+ m_panel33->Layout();
+ bSizer165->Fit( m_panel33 );
+ bSizer24->Add( m_panel33, 1, wxEXPAND, 5 );
- m_staticline6 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
- bSizer24->Add( m_staticline6, 0, wxEXPAND, 5 );
+ m_staticline6 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
+ bSizer24->Add( m_staticline6, 0, wxEXPAND, 5 );
- wxBoxSizer* bSizer25;
- bSizer25 = new wxBoxSizer( wxVERTICAL );
+ 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|wxALL, 5 );
+ m_checkBoxCustom = new wxCheckBox( this, wxID_ANY, _("dummy"), wxDefaultPosition, wxDefaultSize, 0 );
+ bSizer25->Add( m_checkBoxCustom, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5 );
- bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
+ bSizerStdButtons = new wxBoxSizer( wxHORIZONTAL );
- m_buttonAccept = new wxButton( this, wxID_YES, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
+ m_buttonAccept = new wxButton( this, wxID_YES, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
- m_buttonAccept->SetDefault();
- bSizerStdButtons->Add( m_buttonAccept, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
+ m_buttonAccept->SetDefault();
+ bSizerStdButtons->Add( m_buttonAccept, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT|wxLEFT, 5 );
- m_buttonAcceptAll = new wxButton( this, wxID_YESTOALL, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
- bSizerStdButtons->Add( m_buttonAcceptAll, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
+ m_buttonAcceptAll = new wxButton( this, wxID_YESTOALL, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+ bSizerStdButtons->Add( m_buttonAcceptAll, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
- m_buttonDecline = new wxButton( this, wxID_NO, _("dummy"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
- bSizerStdButtons->Add( m_buttonDecline, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
+ m_buttonDecline = new wxButton( this, wxID_NO, _("dummy"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+ bSizerStdButtons->Add( m_buttonDecline, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
- m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1,-1 ), 0 );
- bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
+ m_buttonCancel = new wxButton( this, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxSize( -1, -1 ), 0 );
+ bSizerStdButtons->Add( m_buttonCancel, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
- bSizer25->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 );
+ bSizer25->Add( bSizerStdButtons, 0, wxALIGN_RIGHT, 5 );
- bSizer24->Add( bSizer25, 0, wxEXPAND, 5 );
+ bSizer24->Add( bSizer25, 0, wxEXPAND, 5 );
- this->SetSizer( bSizer24 );
- this->Layout();
- bSizer24->Fit( this );
+ this->SetSizer( bSizer24 );
+ this->Layout();
+ bSizer24->Fit( this );
- this->Centre( wxBOTH );
+ 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_buttonAccept->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnButtonAccept ), NULL, this );
- m_buttonAcceptAll->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnButtonAcceptAll ), NULL, this );
- m_buttonDecline->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnButtonDecline ), NULL, this );
- m_buttonCancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::OnCancel ), NULL, this );
+ // Connect Events
+ this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( PopupDialogGenerated::onClose ) );
+ m_checkBoxCustom->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( PopupDialogGenerated::onCheckBoxClick ), NULL, this );
+ m_buttonAccept->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::onButtonAccept ), NULL, this );
+ m_buttonAcceptAll->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::onButtonAcceptAll ), NULL, this );
+ m_buttonDecline->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( PopupDialogGenerated::onButtonDecline ), 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 8191ca0f..52bd593c 100644
--- a/wx+/popup_dlg_generated.h
+++ b/wx+/popup_dlg_generated.h
@@ -38,34 +38,34 @@
///////////////////////////////////////////////////////////////////////////////
class PopupDialogGenerated : public wxDialog
{
- private:
+private:
- protected:
- wxPanel* m_panel33;
- wxStaticBitmap* m_bitmapMsgType;
- wxStaticText* m_staticTextMain;
- wxTextCtrl* m_textCtrlTextDetail;
- wxStaticLine* m_staticline6;
- wxCheckBox* m_checkBoxCustom;
- wxBoxSizer* bSizerStdButtons;
- wxButton* m_buttonAccept;
- wxButton* m_buttonAcceptAll;
- wxButton* m_buttonDecline;
- wxButton* m_buttonCancel;
+protected:
+ wxPanel* m_panel33;
+ wxStaticBitmap* m_bitmapMsgType;
+ wxStaticText* m_staticTextMain;
+ wxTextCtrl* m_textCtrlTextDetail;
+ wxStaticLine* m_staticline6;
+ wxCheckBox* m_checkBoxCustom;
+ wxBoxSizer* bSizerStdButtons;
+ wxButton* m_buttonAccept;
+ wxButton* m_buttonAcceptAll;
+ wxButton* m_buttonDecline;
+ 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 OnButtonAccept( wxCommandEvent& event ) { event.Skip(); }
- virtual void OnButtonAcceptAll( wxCommandEvent& event ) { event.Skip(); }
- virtual void OnButtonDecline( wxCommandEvent& event ) { event.Skip(); }
- virtual void OnCancel( wxCommandEvent& event ) { event.Skip(); }
+ // 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 onButtonAccept( wxCommandEvent& event ) { event.Skip(); }
+ virtual void onButtonAcceptAll( wxCommandEvent& event ) { event.Skip(); }
+ virtual void onButtonDecline( wxCommandEvent& event ) { event.Skip(); }
+ virtual void onCancel( wxCommandEvent& event ) { event.Skip(); }
- public:
+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();
+ 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();
};
diff --git a/wx+/rtl.h b/wx+/rtl.h
index 8e386b49..7b1c7926 100644
--- a/wx+/rtl.h
+++ b/wx+/rtl.h
@@ -33,7 +33,7 @@ wxImage mirrorIfRtl(const wxImage& img);
//---------------------- implementation ------------------------
namespace impl
{
-//don't use wxDC::DrawLabel:
+//don't use wxDC::DrawLabel:
// - expensive GetTextExtent() call even when passing an empty string!!!
// - 1-off alignment bugs!
inline
diff --git a/wx+/toggle_button.h b/wx+/toggle_button.h
index 0a359c5c..560ad77e 100644
--- a/wx+/toggle_button.h
+++ b/wx+/toggle_button.h
@@ -24,7 +24,7 @@ public:
const wxSize& size = wxDefaultSize,
long style = 0,
const wxValidator& validator = wxDefaultValidator,
- const wxString& name = wxButtonNameStr) :
+ const wxString& name = wxASCII_STR(wxButtonNameStr)) :
wxBitmapButton(parent, id, bitmap, pos, size, style, validator, name) {}
//wxButton constructor
@@ -35,7 +35,7 @@ public:
const wxSize& size = wxDefaultSize,
long style = 0,
const wxValidator& validator = wxDefaultValidator,
- const wxString& name = wxButtonNameStr) :
+ const wxString& name = wxASCII_STR(wxButtonNameStr)) :
wxBitmapButton(parent, id, wxNullBitmap, pos, size, style, validator, name)
{
SetLabel(label);
bgstack15