summaryrefslogtreecommitdiff
path: root/wx+
diff options
context:
space:
mode:
Diffstat (limited to 'wx+')
-rw-r--r--wx+/async_task.h147
-rw-r--r--wx+/choice_enum.h4
-rw-r--r--wx+/context_menu.h10
-rw-r--r--wx+/dc.h4
-rw-r--r--wx+/file_drop.h4
-rw-r--r--wx+/graph.cpp2
-rw-r--r--wx+/graph.h74
-rw-r--r--wx+/grid.cpp122
-rw-r--r--wx+/grid.h14
-rw-r--r--wx+/image_resources.cpp2
-rw-r--r--wx+/image_tools.h4
-rw-r--r--wx+/popup_dlg.cpp18
-rw-r--r--wx+/rtl.h2
13 files changed, 267 insertions, 140 deletions
diff --git a/wx+/async_task.h b/wx+/async_task.h
new file mode 100644
index 00000000..b23f6948
--- /dev/null
+++ b/wx+/async_task.h
@@ -0,0 +1,147 @@
+// **************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 *
+// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
+// **************************************************************************
+
+#ifndef ASYNC_JOB_839147839170432143214321
+#define ASYNC_JOB_839147839170432143214321
+
+#include <functional>
+#include <zen/thread.h>
+#include <zen/scope_guard.h>
+#include <zen/stl_tools.h>
+#include <wx/timer.h>
+
+
+namespace zen
+{
+/*
+Run a task in an async thread, but process result in GUI event loop
+-------------------------------------------------------------------
+1. put AsyncGuiQueue instance inside a dialog:
+ AsyncGuiQueue guiQueue;
+
+2. schedule async task and synchronous continuation:
+ guiQueue.processAsync(evalAsync, evalOnGui);
+*/
+
+namespace impl
+{
+struct Task
+{
+ virtual ~Task() {}
+ virtual bool resultReady () const = 0;
+ virtual void evaluateResult() = 0;
+};
+
+
+template <class ResultType, class Fun>
+class ConcreteTask : public Task
+{
+public:
+ template <class Fun2>
+ ConcreteTask(std::future<ResultType>&& asyncResult, Fun2&& evalOnGui) : asyncResult_(std::move(asyncResult)), evalOnGui_(std::forward<Fun2>(evalOnGui)) {}
+
+ bool resultReady () const override { return isReady(asyncResult_); }
+ void evaluateResult() override
+ {
+#ifndef NDEBUG
+ assert(resultReady() && !resultEvaluated_);
+ resultEvaluated_ = true;
+#endif
+ evalResult(IsSameType<ResultType, void>());
+ }
+
+private:
+ void evalResult(FalseType /*void result type*/) { evalOnGui_(asyncResult_.get()); }
+ void evalResult(TrueType /*void result type*/) { asyncResult_.get(); evalOnGui_(); }
+
+ std::future<ResultType> asyncResult_;
+ Fun evalOnGui_; //keep "evalOnGui" strictly separated from async thread: in particular do not copy in thread!
+#ifndef NDEBUG
+ bool resultEvaluated_ = false;
+#endif
+};
+
+
+class AsyncTasks
+{
+public:
+ AsyncTasks() {}
+
+ template <class Fun, class Fun2>
+ void add(Fun&& evalAsync, Fun2&& evalOnGui)
+ {
+ using ResultType = decltype(evalAsync());
+ tasks.push_back(std::make_unique<ConcreteTask<ResultType, Fun2>>(zen::runAsync(std::forward<Fun>(evalAsync)), std::forward<Fun2>(evalOnGui)));
+ }
+ //equivalent to "evalOnGui(evalAsync())"
+ // -> evalAsync: the usual thread-safety requirements apply!
+ // -> evalOnGui: no thread-safety concerns, but must only reference variables with greater-equal lifetime than the AsyncTask instance!
+
+ void evalResults() //call from gui thread repreatedly
+ {
+ if (!inRecursion) //prevent implicit recursion, e.g. if we're called from an idle event and spawn another one via the callback below
+ {
+ inRecursion = true;
+ ZEN_ON_SCOPE_EXIT(inRecursion = false);
+
+ std::vector<std::unique_ptr<Task>> readyTasks; //Reentrancy; access to AsyncTasks::add is not protected! => evaluate outside erase_if
+
+ erase_if(tasks, [&](std::unique_ptr<Task>& task)
+ {
+ if (task->resultReady())
+ {
+ readyTasks.push_back(std::move(task));
+ return true;
+ }
+ return false;
+ });
+
+ for (auto& task : readyTasks)
+ task->evaluateResult();
+ }
+ }
+
+ bool empty() const { return tasks.empty(); }
+
+private:
+ AsyncTasks (const AsyncTasks&) = delete;
+ AsyncTasks& operator=(const AsyncTasks&) = delete;
+
+ bool inRecursion = false;
+ std::vector<std::unique_ptr<Task>> tasks;
+};
+}
+
+
+class AsyncGuiQueue : private wxEvtHandler
+{
+public:
+ AsyncGuiQueue() { timer.Connect(wxEVT_TIMER, wxEventHandler(AsyncGuiQueue::onTimerEvent), nullptr, this); }
+
+ template <class Fun, class Fun2>
+ void processAsync(Fun&& evalAsync, Fun2&& evalOnGui)
+ {
+ asyncTasks.add(std::forward<Fun >(evalAsync),
+ std::forward<Fun2>(evalOnGui));
+ if (!timer.IsRunning())
+ timer.Start(50 /*unit: [ms]*/);
+ }
+
+private:
+ void onTimerEvent(wxEvent& event) //schedule and run long-running tasks asynchronously
+ {
+ asyncTasks.evalResults(); //process results on GUI queue
+ if (asyncTasks.empty())
+ timer.Stop();
+ }
+
+ impl::AsyncTasks asyncTasks;
+ wxTimer timer; //don't use wxWidgets' idle handling => repeated idle requests/consumption hogs 100% cpu!
+};
+
+}
+
+#endif //ASYNC_JOB_839147839170432143214321
diff --git a/wx+/choice_enum.h b/wx+/choice_enum.h
index 6a795d4a..9b1575ee 100644
--- a/wx+/choice_enum.h
+++ b/wx+/choice_enum.h
@@ -27,10 +27,10 @@ Set enum value:
setEnumVal(enumDescrMap, *m_choiceHandleError, value);
Get enum value:
- value = getEnumVal(enumDescrMap, *m_choiceHandleError)
+ value = getEnumVal(enumDescrMap, *m_choiceHandleError)
Update enum tooltips (after user changed selection):
- updateTooltipEnumVal(enumDescrMap, *m_choiceHandleError);
+ updateTooltipEnumVal(enumDescrMap, *m_choiceHandleError);
*/
diff --git a/wx+/context_menu.h b/wx+/context_menu.h
index 2ae85162..ec62852d 100644
--- a/wx+/context_menu.h
+++ b/wx+/context_menu.h
@@ -17,10 +17,10 @@
A context menu supporting C++11 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);
+ 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
@@ -28,7 +28,7 @@ namespace zen
class ContextMenu : private wxEvtHandler
{
public:
- ContextMenu() : menu(zen::make_unique<wxMenu>()) {}
+ ContextMenu() : menu(std::make_unique<wxMenu>()) {}
void addItem(const wxString& label, const std::function<void()>& command, const wxBitmap* bmp = nullptr, bool enabled = true)
{
diff --git a/wx+/dc.h b/wx+/dc.h
index 0d3c1cb8..3fba4aaf 100644
--- a/wx+/dc.h
+++ b/wx+/dc.h
@@ -48,7 +48,7 @@ public:
auto it = refDcToAreaMap().find(&dc);
if (it != refDcToAreaMap().end())
{
- oldRect = zen::make_unique<wxRect>(it->second);
+ oldRect = std::make_unique<wxRect>(it->second);
wxRect tmp = r;
tmp.Intersect(*oldRect); //better safe than sorry
@@ -98,7 +98,7 @@ public:
{
const wxSize clientSize = wnd.GetClientSize();
if (!buffer_ || clientSize != wxSize(buffer->GetWidth(), buffer->GetHeight()))
- buffer = zen::make_unique<wxBitmap>(clientSize.GetWidth(), clientSize.GetHeight());
+ buffer = std::make_unique<wxBitmap>(clientSize.GetWidth(), clientSize.GetHeight());
SelectObject(*buffer);
diff --git a/wx+/file_drop.h b/wx+/file_drop.h
index c9f2469c..f8943788 100644
--- a/wx+/file_drop.h
+++ b/wx+/file_drop.h
@@ -28,8 +28,8 @@ namespace zen
/*
1. setup a window to emit EVENT_DROP_FILE:
- - simple file system paths: setupFileDrop
- - any shell paths with validation: setupShellItemDrop
+ - simple file system paths: setupFileDrop
+ - any shell paths with validation: setupShellItemDrop
2. register events:
wnd.Connect (EVENT_DROP_FILE, FileDropEventHandler(MyDlg::OnFilesDropped), nullptr, this);
diff --git a/wx+/graph.cpp b/wx+/graph.cpp
index d76e4d41..601c4913 100644
--- a/wx+/graph.cpp
+++ b/wx+/graph.cpp
@@ -453,7 +453,7 @@ void Graph2D::onPaintEvent(wxPaintEvent& event)
void Graph2D::OnMouseLeftDown(wxMouseEvent& event)
{
- activeSel = zen::make_unique<MouseSelection>(*this, event.GetPosition());
+ activeSel = std::make_unique<MouseSelection>(*this, event.GetPosition());
if (!event.ControlDown())
oldSel.clear();
diff --git a/wx+/graph.h b/wx+/graph.h
index 34c7ab3c..ea05709d 100644
--- a/wx+/graph.h
+++ b/wx+/graph.h
@@ -27,19 +27,20 @@ Example:
setLabelY(Graph2D::Y_LABEL_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() : x(0), y(0) {}
+ CurvePoint() {}
CurvePoint(double xVal, double yVal) : x(xVal), y(yVal) {}
- double x;
- double y;
+ 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
{
virtual ~CurveData() {}
@@ -67,9 +68,10 @@ struct SparseCurveData : public CurveData
private:
void getPoints(double minX, double maxX, int pixelWidth, std::vector<CurvePoint>& points) const override;
- bool addSteps_;
+ const bool addSteps_;
};
+
struct ArrayCurveData : public SparseCurveData
{
virtual double getValue(size_t pos) const = 0;
@@ -96,12 +98,14 @@ private:
}
};
+
struct VectorCurveData : public ArrayCurveData
{
std::vector<double>& refData() { return data; }
private:
double getValue(size_t pos) const override { return pos < data.size() ? data[pos] : 0; }
size_t getSize() const override { return data.size(); }
+
std::vector<double> data;
};
@@ -118,6 +122,7 @@ struct LabelFormatter
virtual wxString formatText(double value, double optimalBlockSize) const = 0;
};
+
double nextNiceNumber(double blockSize); //round to next number which is convenient to read, e.g. 2.13 -> 2; 2.7 -> 2.5
struct DecimalNumberFormatter : public LabelFormatter
@@ -172,8 +177,7 @@ public:
class CurveAttributes
{
public:
- CurveAttributes() : autoColor(true), drawCurveArea(false), lineWidth(2) {}
-
+ CurveAttributes() {} //required by GCC
CurveAttributes& setColor (const wxColour& col) { color = col; autoColor = false; return *this; }
CurveAttributes& fillCurveArea(const wxColour& col) { fillColor = col; drawCurveArea = true; return *this; }
CurveAttributes& setLineWidth(size_t width) { lineWidth = static_cast<int>(width); return *this; }
@@ -181,13 +185,13 @@ public:
private:
friend class Graph2D;
- bool autoColor;
+ bool autoColor = true;
wxColour color;
- bool drawCurveArea;
+ bool drawCurveArea = false;
wxColour fillColor;
- int lineWidth;
+ int lineWidth = 2;
};
void setCurve(const std::shared_ptr<CurveData>& data, const CurveAttributes& ca = CurveAttributes());
@@ -226,24 +230,6 @@ public:
class MainAttributes
{
public:
- MainAttributes() :
- minXauto(true),
- maxXauto(true),
- minX(0),
- maxX(0),
- minYauto(true),
- maxYauto(true),
- minY(0),
- maxY(0),
- labelposX(X_LABEL_BOTTOM),
- xLabelHeight(25),
- labelFmtX(std::make_shared<DecimalNumberFormatter>()),
- labelposY(Y_LABEL_LEFT),
- yLabelWidth(60),
- labelFmtY(std::make_shared<DecimalNumberFormatter>()),
- backgroundColor(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)),
- mouseSelMode(SELECT_RECTANGLE) {}
-
MainAttributes& setMinX(double newMinX) { minX = newMinX; minXauto = false; return *this; }
MainAttributes& setMaxX(double newMaxX) { maxX = newMaxX; maxXauto = false; return *this; }
@@ -278,28 +264,28 @@ public:
private:
friend class Graph2D;
- bool minXauto; //autodetect range for X value
- bool maxXauto;
- double minX; //x-range to visualize
- double maxX;
+ bool minXauto = true; //autodetect range for X value
+ bool maxXauto = true;
+ double minX = 0; //x-range to visualize
+ double maxX = 0; //
- bool minYauto; //autodetect range for Y value
- bool maxYauto;
- double minY; //y-range to visualize
- double maxY;
+ bool minYauto = true; //autodetect range for Y value
+ bool maxYauto = true;
+ double minY = 0; //y-range to visualize
+ double maxY = 0; //
- PosLabelX labelposX;
- int xLabelHeight;
- std::shared_ptr<LabelFormatter> labelFmtX;
+ PosLabelX labelposX = X_LABEL_BOTTOM;
+ int xLabelHeight = 25;
+ std::shared_ptr<LabelFormatter> labelFmtX = std::make_shared<DecimalNumberFormatter>();
- PosLabelY labelposY;
- int yLabelWidth;
- std::shared_ptr<LabelFormatter> labelFmtY;
+ PosLabelY labelposY = Y_LABEL_LEFT;
+ int yLabelWidth = 60;
+ std::shared_ptr<LabelFormatter> labelFmtY = std::make_shared<DecimalNumberFormatter>();
std::map<PosCorner, wxString> cornerTexts;
- wxColour backgroundColor;
- SelMode mouseSelMode;
+ wxColour backgroundColor = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
+ SelMode mouseSelMode = SELECT_RECTANGLE;
};
void setAttributes(const MainAttributes& newAttr) { attr = newAttr; Refresh(); }
MainAttributes getAttributes() const { return attr; }
diff --git a/wx+/grid.cpp b/wx+/grid.cpp
index 9eea2e28..c819763f 100644
--- a/wx+/grid.cpp
+++ b/wx+/grid.cpp
@@ -162,9 +162,9 @@ void drawTextLabelFitting(wxDC& dc, const wxString& text, const wxRect& rect, in
wxDC::GetMultiLineTextExtent() is implemented in terms of wxDC::GetTextExtent()
average total times:
- Windows Linux
- single wxDC::DrawText() 7µs 50µs
- wxDC::DrawLabel() + 10µs 90µs
+ Windows Linux
+ single wxDC::DrawText() 7µs 50µs
+ wxDC::DrawLabel() + 10µs 90µs
repeated GetTextExtent()
*/
@@ -581,8 +581,7 @@ public:
wnd_(wnd),
colFrom_(colFrom),
colTo_(colFrom),
- clientPosX_(clientPosX),
- singleClick_(true) { wnd_.CaptureMouse(); }
+ clientPosX_(clientPosX) { wnd_.CaptureMouse(); }
~ColumnMove() { if (wnd_.HasCapture()) wnd_.ReleaseMouse(); }
size_t getColumnFrom() const { return colFrom_; }
@@ -597,7 +596,7 @@ private:
const size_t colFrom_;
size_t colTo_;
const int clientPosX_;
- bool singleClick_;
+ bool singleClick_ = true;
};
}
@@ -695,10 +694,10 @@ private:
{
if (!event.LeftDClick()) //double-clicks never seem to arrive here; why is this checked at all???
if (Opt<int> colWidth = refParent().getColWidth(action->col))
- activeResizing = make_unique<ColumnResizing>(*this, action->col, *colWidth, event.GetPosition().x);
+ activeResizing = std::make_unique<ColumnResizing>(*this, action->col, *colWidth, event.GetPosition().x);
}
else //a move or single click
- activeMove = make_unique<ColumnMove>(*this, action->col, event.GetPosition().x);
+ activeMove = std::make_unique<ColumnMove>(*this, action->col, event.GetPosition().x);
}
event.Skip();
}
@@ -792,7 +791,7 @@ private:
{
if (const Opt<ColAction> action = refParent().clientPosToColumnAction(event.GetPosition()))
{
- highlightCol = make_unique<size_t>(action->col);
+ highlightCol = std::make_unique<size_t>(action->col);
if (action->wantResize)
SetCursor(wxCURSOR_SIZEWE); //set window-local only! :)
@@ -863,11 +862,8 @@ public:
RowLabelWin& rowLabelWin,
ColLabelWin& colLabelWin) : SubWindow(parent),
rowLabelWin_(rowLabelWin),
- colLabelWin_(colLabelWin),
- cursorRow(0),
- selectionAnchor(0),
- gridUpdatePending(false)
- {
+ colLabelWin_(colLabelWin)
+ {
Connect(EVENT_GRID_HAS_SCROLLED, wxEventHandler(MainWin::onRequestWindowUpdate), nullptr, this);
}
@@ -994,15 +990,15 @@ private:
if (!event.RightDown() || !refParent().isSelected(row)) //do NOT start a new selection if user right-clicks on a selected area!
{
if (event.ControlDown())
- activeSelection = make_unique<MouseSelection>(*this, row, !refParent().isSelected(row));
+ activeSelection = std::make_unique<MouseSelection>(*this, row, !refParent().isSelected(row));
else if (event.ShiftDown())
{
- activeSelection = make_unique<MouseSelection>(*this, selectionAnchor, true);
+ activeSelection = std::make_unique<MouseSelection>(*this, selectionAnchor, true);
refParent().clearSelection(ALLOW_GRID_EVENT);
}
else
{
- activeSelection = make_unique<MouseSelection>(*this, row, true);
+ activeSelection = std::make_unique<MouseSelection>(*this, row, true);
refParent().clearSelection(ALLOW_GRID_EVENT);
}
}
@@ -1096,9 +1092,7 @@ private:
{
public:
MouseSelection(MainWin& wnd, size_t rowStart, bool positiveSelect) :
- wnd_(wnd), rowStart_(rowStart), rowCurrent_(rowStart), positiveSelect_(positiveSelect), toScrollX(0), toScrollY(0),
- tickCountLast(getTicks()),
- ticksPerSec_(ticksPerSec())
+ wnd_(wnd), rowStart_(rowStart), rowCurrent_(rowStart), positiveSelect_(positiveSelect)
{
wnd_.CaptureMouse();
timer.Connect(wxEVT_TIMER, wxEventHandler(MouseSelection::onTimer), nullptr, this);
@@ -1121,8 +1115,7 @@ private:
tickCountLast = now;
}
- wxMouseState mouseState = wxGetMouseState();
- const wxPoint clientPos = wnd_.ScreenToClient(wxPoint(mouseState.GetX(), mouseState.GetY()));
+ const wxPoint clientPos = wnd_.ScreenToClient(wxGetMousePosition());
const wxSize clientSize = wnd_.GetClientSize();
assert(wnd_.GetClientAreaOrigin() == wxPoint());
@@ -1183,10 +1176,10 @@ private:
ptrdiff_t rowCurrent_;
const bool positiveSelect_;
wxTimer timer;
- double toScrollX; //count outstanding scroll units to scroll while dragging mouse
- double toScrollY; //
- TickVal tickCountLast;
- const std::int64_t ticksPerSec_;
+ double toScrollX = 0; //count outstanding scroll units to scroll while dragging mouse
+ double toScrollY = 0; //
+ TickVal tickCountLast = getTicks();
+ const std::int64_t ticksPerSec_ = ticksPerSec();
};
void ScrollWindow(int dx, int dy, const wxRect* rect) override
@@ -1224,9 +1217,9 @@ private:
std::unique_ptr<MouseSelection> activeSelection; //bound while user is selecting with mouse
- ptrdiff_t cursorRow;
- size_t selectionAnchor;
- bool gridUpdatePending;
+ ptrdiff_t cursorRow = 0;
+ size_t selectionAnchor = 0;
+ bool gridUpdatePending = false;
};
//----------------------------------------------------------------------------------------------------------------
@@ -1237,14 +1230,7 @@ Grid::Grid(wxWindow* parent,
const wxPoint& pos,
const wxSize& size,
long style,
- const wxString& name) : wxScrolledWindow(parent, id, pos, size, style | wxWANTS_CHARS, name),
- showScrollbarX(SB_SHOW_AUTOMATIC),
- showScrollbarY(SB_SHOW_AUTOMATIC),
- colLabelHeight(0), //dummy init
- drawRowLabel(true),
- allowColumnMove(true),
- allowColumnResize(true),
- rowCountOld(0)
+ const wxString& name) : wxScrolledWindow(parent, id, pos, size, style | wxWANTS_CHARS, name)
{
cornerWin_ = new CornerWin (*this); //
rowLabelWin_ = new RowLabelWin(*this); //owership handled by "this"
@@ -1278,24 +1264,24 @@ void Grid::updateWindowSizes(bool updateScrollbar)
{
/* We have to deal with TWO nasty circular dependencies:
1.
- rowLabelWidth
- /|\
- mainWin::client width
- /|\
- SetScrollbars -> show/hide horizontal scrollbar depending on client width
- /|\
- mainWin::client height -> possibly trimmed by horizontal scrollbars
- /|\
- rowLabelWidth
+ rowLabelWidth
+ /|\
+ mainWin::client width
+ /|\
+ SetScrollbars -> show/hide horizontal scrollbar depending on client width
+ /|\
+ mainWin::client height -> possibly trimmed by horizontal scrollbars
+ /|\
+ rowLabelWidth
2.
- mainWin_->GetClientSize()
- /|\
- SetScrollbars -> show/hide scrollbars depending on whether client size is big enough
- /|\
- GetClientSize(); -> possibly trimmed by scrollbars
- /|\
- mainWin_->GetClientSize() -> also trimmed, since it's a sub-window!
+ mainWin_->GetClientSize()
+ /|\
+ SetScrollbars -> show/hide scrollbars depending on whether client size is big enough
+ /|\
+ GetClientSize(); -> possibly trimmed by scrollbars
+ /|\
+ mainWin_->GetClientSize() -> also trimmed, since it's a sub-window!
*/
//break this vicious circle:
@@ -1379,27 +1365,27 @@ void Grid::updateWindowSizes(bool updateScrollbar)
------------------------ \|/ |
| | | |
------------------------ \|/
- gw := gross width
- nw := net width := gross width - sb size
- gh := gross height
- nh := net height := gross height - sb size
+ gw := gross width
+ nw := net width := gross width - sb size
+ gh := gross height
+ nh := net height := gross height - sb size
There are 6 cases that can occur:
---------------------------------
- lw := logical width
- lh := logical height
+ lw := logical width
+ lh := logical height
1. lw <= gw && lh <= gh => no scrollbars needed
2. lw > gw && lh > gh => need both scrollbars
3. lh > gh
- 4.1 lw <= nw => need vertical scrollbar only
- 4.2 nw < lw <= gw => need both scrollbars
+ 4.1 lw <= nw => need vertical scrollbar only
+ 4.2 nw < lw <= gw => need both scrollbars
4. lw > gw
- 3.1 lh <= nh => need horizontal scrollbar only
- 3.2 nh < lh <= gh => need both scrollbars
+ 3.1 lh <= nh => need horizontal scrollbar only
+ 3.2 nh < lh <= gh => need both scrollbars
*/
}
}
@@ -2051,11 +2037,11 @@ void Grid::scrollTo(size_t row)
}
- bool Grid::Enable(bool enable)
- {
- Refresh();
- return wxScrolledWindow::Enable(enable);
- }
+bool Grid::Enable(bool enable)
+{
+ Refresh();
+ return wxScrolledWindow::Enable(enable);
+}
size_t Grid::getGridCursor() const
diff --git a/wx+/grid.h b/wx+/grid.h
index 8523b698..5fef34e2 100644
--- a/wx+/grid.h
+++ b/wx+/grid.h
@@ -323,21 +323,21 @@ private:
ColLabelWin* colLabelWin_;
MainWin* mainWin_;
- ScrollBarStatus showScrollbarX;
- ScrollBarStatus showScrollbarY;
+ ScrollBarStatus showScrollbarX = SB_SHOW_AUTOMATIC;
+ ScrollBarStatus showScrollbarY = SB_SHOW_AUTOMATIC;
- int colLabelHeight;
- bool drawRowLabel;
+ int colLabelHeight = 0;
+ bool drawRowLabel = true;
std::shared_ptr<GridData> dataView_;
Selection selection;
- bool allowColumnMove;
- bool allowColumnResize;
+ bool allowColumnMove = true;
+ bool allowColumnResize = true;
std::vector<VisibleColumn> visibleCols; //individual widths, type and total column count
std::vector<ColumnAttribute> oldColAttributes; //visible + nonvisible columns; use for conversion in setColumnConfig()/getColumnConfig() *only*!
- size_t rowCountOld; //at the time of last Grid::Refresh()
+ size_t rowCountOld = 0; //at the time of last Grid::Refresh()
};
}
diff --git a/wx+/image_resources.cpp b/wx+/image_resources.cpp
index 7383f620..98cdc7a8 100644
--- a/wx+/image_resources.cpp
+++ b/wx+/image_resources.cpp
@@ -22,7 +22,7 @@ namespace
void loadAnimFromZip(wxZipInputStream& zipInput, wxAnimation& anim)
{
//work around wxWidgets bug:
- //construct seekable input stream (zip-input stream is non-seekable) for wxAnimation::Load()
+ //construct seekable input stream (zip-input stream is not seekable) for wxAnimation::Load()
//luckily this method call is very fast: below measurement precision!
std::vector<char> data;
data.reserve(10000);
diff --git a/wx+/image_tools.h b/wx+/image_tools.h
index 5e21bd40..43c1a625 100644
--- a/wx+/image_tools.h
+++ b/wx+/image_tools.h
@@ -33,7 +33,7 @@ wxImage stackImages(const wxImage& img1, const wxImage& img2, ImageStackLayout d
wxImage createImageFromText(const wxString& text, const wxFont& font, const wxColor& col);
-wxBitmap layOver(const wxBitmap& foreground, const wxBitmap& background); //merge
+wxBitmap layOver(const wxBitmap& background, const wxBitmap& foreground); //merge
wxImage greyScale(const wxImage& img); //greyscale + brightness adaption
wxBitmap greyScale(const wxBitmap& bmp); //
@@ -147,7 +147,7 @@ void adjustBrightness(wxImage& img, int targetLevel)
inline
-wxBitmap layOver(const wxBitmap& foreground, const wxBitmap& background)
+wxBitmap layOver(const wxBitmap& background, const wxBitmap& foreground)
{
assert(foreground.HasAlpha() == background.HasAlpha()); //we don't support mixed-mode brittleness!
diff --git a/wx+/popup_dlg.cpp b/wx+/popup_dlg.cpp
index 480021eb..188ad76d 100644
--- a/wx+/popup_dlg.cpp
+++ b/wx+/popup_dlg.cpp
@@ -145,7 +145,7 @@ public:
else
m_checkBoxCustom->Hide();
- Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(StandardPopupDialog::OnKeyPressed), nullptr, this);
+ Connect(wxEVT_CHAR_HOOK, wxKeyEventHandler(StandardPopupDialog::OnKeyPressed), nullptr, this); //dialog-specific local key events
}
private:
@@ -154,11 +154,19 @@ private:
void OnKeyPressed(wxKeyEvent& event)
{
- const int keyCode = event.GetKeyCode();
- if (keyCode == WXK_ESCAPE) //handle case where cancel button is hidden!
+ switch (event.GetKeyCode())
{
- EndModal(static_cast<int>(ConfirmationButton3::CANCEL));
- return;
+ case WXK_RETURN:
+ case WXK_NUMPAD_ENTER:
+ {
+ wxCommandEvent dummy(wxEVT_COMMAND_BUTTON_CLICKED);
+ OnButtonAffirmative(dummy);
+ return;
+ }
+
+ case WXK_ESCAPE: //handle case where cancel button is hidden!
+ EndModal(static_cast<int>(ConfirmationButton3::CANCEL));
+ return;
}
event.Skip();
}
diff --git a/wx+/rtl.h b/wx+/rtl.h
index 5f1c9321..84182b2c 100644
--- a/wx+/rtl.h
+++ b/wx+/rtl.h
@@ -55,7 +55,7 @@ void drawRtlImpl(wxDC& dc, const wxRect& rect, std::unique_ptr<wxBitmap>& buffer
if (dc.GetLayoutDirection() == wxLayout_RightToLeft)
{
if (!buffer || buffer->GetWidth() != rect.width || buffer->GetHeight() < rect.height) //[!] since we do a mirror, width needs to match exactly!
- buffer = zen::make_unique<wxBitmap>(rect.width, rect.height);
+ buffer = std::make_unique<wxBitmap>(rect.width, rect.height);
wxMemoryDC memDc(*buffer);
memDc.Blit(wxPoint(0, 0), rect.GetSize(), &dc, rect.GetTopLeft()); //blit in: background is mirrored due to memDc, dc having different layout direction!
bgstack15