summaryrefslogtreecommitdiff
path: root/wx+
diff options
context:
space:
mode:
Diffstat (limited to 'wx+')
-rw-r--r--wx+/dc.h4
-rw-r--r--wx+/font_size.h4
-rw-r--r--wx+/graph.cpp12
-rw-r--r--wx+/grid.cpp19
-rw-r--r--wx+/grid.h2
-rw-r--r--wx+/image_resources.cpp6
-rw-r--r--wx+/image_tools.cpp48
-rw-r--r--wx+/image_tools.h2
-rw-r--r--wx+/no_flicker.h42
-rw-r--r--wx+/popup_dlg.cpp7
10 files changed, 66 insertions, 80 deletions
diff --git a/wx+/dc.h b/wx+/dc.h
index fabd382b..6769b779 100644
--- a/wx+/dc.h
+++ b/wx+/dc.h
@@ -66,7 +66,7 @@ void drawFilledRectangle(wxDC& dc, wxRect rect, int borderWidth, const wxColor&
macOS: wxWidgets uses DIP (note: wxScreenDC().GetPPI() returns 72 x 72 which is a lie; looks like 96 x 96) */
inline
-int fastFromDIP(double d) //like wxWindow::FromDIP (but tied to primary monitor and buffered)
+int fastFromDIP(int d) //like wxWindow::FromDIP (but tied to primary monitor and buffered)
{
#ifndef wxHAVE_DPI_INDEPENDENT_PIXELS
#error why is wxHAVE_DPI_INDEPENDENT_PIXELS not defined?
@@ -77,7 +77,7 @@ int fastFromDIP(double d) //like wxWindow::FromDIP (but tied to primary monitor
//https://github.com/wxWidgets/wxWidgets/blob/d9d05c2bb201078f5e762c42458ca2f74af5b322/include/wx/window.h#L2060
return d; //e.g. macOS, GTK3
}
-
+int fastFromDIP(double d) = delete;
diff --git a/wx+/font_size.h b/wx+/font_size.h
index d25dfede..da74eada 100644
--- a/wx+/font_size.h
+++ b/wx+/font_size.h
@@ -33,7 +33,7 @@ inline
void setRelativeFontSize(wxWindow& control, double factor)
{
wxFont font = control.GetFont();
- font.SetPointSize(numeric::round(wxNORMAL_FONT->GetPointSize() * factor));
+ font.SetPointSize(std::round(wxNORMAL_FONT->GetPointSize() * factor));
control.SetFont(font);
}
@@ -42,7 +42,7 @@ inline
void setMainInstructionFont(wxWindow& control)
{
wxFont font = control.GetFont();
- font.SetPointSize(numeric::round(wxNORMAL_FONT->GetPointSize() * 12.0 / 11));
+ font.SetPointSize(std::round(wxNORMAL_FONT->GetPointSize() * 12.0 / 11));
font.SetWeight(wxFONTWEIGHT_BOLD);
control.SetFont(font);
diff --git a/wx+/graph.cpp b/wx+/graph.cpp
index bb320db6..ba87299e 100644
--- a/wx+/graph.cpp
+++ b/wx+/graph.cpp
@@ -87,7 +87,7 @@ public:
{
//catch large double values: if double is larger than what int can represent => undefined behavior!
realPos = std::clamp(realPos, outOfBoundsLow_, outOfBoundsHigh_);
- return numeric::round(realToScreen(realPos));
+ return std::round(realToScreen(realPos));
}
private:
@@ -123,7 +123,7 @@ int widenRange(double& valMin, double& valMax, //in/out
double blockMin = std::floor(valMin / valRangePerBlock); //store as double, not int: truncation possible, e.g. if valRangePerBlock == 1
double blockMax = std::ceil (valMax / valRangePerBlock); //
- int blockCount = numeric::round(blockMax - blockMin);
+ int blockCount = std::round(blockMax - blockMin);
assert(blockCount >= 0);
//handle valMin == valMax == integer
@@ -770,10 +770,10 @@ void Graph2D::render(wxDC& dc) const
screenToX = std::clamp(screenToX, 0.0, graphArea.width - 1.0);
screenToY = std::clamp(screenToY, 0.0, graphArea.height - 1.0);
- const wxPoint pixelFrom = wxPoint(numeric::round(screenFromX),
- numeric::round(screenFromY)) + graphAreaOrigin;
- const wxPoint pixelTo = wxPoint(numeric::round(screenToX),
- numeric::round(screenToY)) + graphAreaOrigin;
+ const wxPoint pixelFrom = wxPoint(std::round(screenFromX),
+ std::round(screenFromY)) + graphAreaOrigin;
+ const wxPoint pixelTo = wxPoint(std::round(screenToX),
+ std::round(screenToY)) + graphAreaOrigin;
switch (attr_.mouseSelMode)
{
case GraphSelMode::none:
diff --git a/wx+/grid.cpp b/wx+/grid.cpp
index 46195a52..cd91b1af 100644
--- a/wx+/grid.cpp
+++ b/wx+/grid.cpp
@@ -13,6 +13,7 @@
#include <wx/tooltip.h>
#include <wx/timer.h>
#include <wx/utils.h>
+#include <zen/basic_math.h>
#include <zen/string_tools.h>
#include <zen/scope_guard.h>
#include <zen/utf.h>
@@ -198,12 +199,12 @@ void GridData::drawCellText(wxDC& dc, const wxRect& rect, const std::wstring& te
if (alignment & wxALIGN_RIGHT) //note: wxALIGN_LEFT == 0!
pt.x += rect.width - extentTrunc.GetWidth();
else if (alignment & wxALIGN_CENTER_HORIZONTAL)
- pt.x += static_cast<int>(std::floor((rect.width - extentTrunc.GetWidth()) / 2.0)); //round down negative values, too!
+ pt.x += numeric::intDivFloor(rect.width - extentTrunc.GetWidth(), 2); //round down negative values, too!
if (alignment & wxALIGN_BOTTOM) //note: wxALIGN_TOP == 0!
pt.y += rect.height - extentTrunc.GetHeight();
else if (alignment & wxALIGN_CENTER_VERTICAL)
- pt.y += static_cast<int>(std::floor((rect.height - extentTrunc.GetHeight()) / 2.0)); //round down negative values, too!
+ pt.y += numeric::intDivFloor(rect.height - extentTrunc.GetHeight(), 2); //round down negative values, too!
//std::unique_ptr<RecursiveDcClipper> clip; -> redundant!? RecursiveDcClipper already used during grid cell rendering
//if (extentTrunc.GetWidth() > rect.width)
@@ -268,13 +269,9 @@ public:
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);
+ //SetDoubleBuffered(true); -> slow as hell!
- 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!
Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& event) { onMouseLeftDown (event); });
@@ -328,8 +325,6 @@ protected:
private:
virtual void render(wxDC& dc, const wxRect& rect) = 0;
- virtual void onFocus(wxFocusEvent& event) { event.Skip(); }
-
virtual void onMouseLeftDown (wxMouseEvent& event) { event.Skip(); }
virtual void onMouseLeftUp (wxMouseEvent& event) { event.Skip(); }
virtual void onMouseLeftDouble(wxMouseEvent& event) { event.Skip(); }
@@ -1312,9 +1307,6 @@ private:
event.Skip();
}
- warn_static("Refresh() needed!? focus shouldn't affect grid rendering => test + remove it for a while: if not needed scrap onFocus()")
- //void onFocus(wxFocusEvent& event) override { Refresh(); event.Skip(); }
-
class MouseSelection : private wxEvtHandler
{
public:
@@ -2183,8 +2175,7 @@ void Grid::makeRowVisible(size_t row)
{
auto execScroll = [&](int clientHeight)
{
- const int scrollPosNewY = std::ceil((labelRect.y - clientHeight +
- labelRect.height) / static_cast<double>(pixelsPerUnitY));
+ const int scrollPosNewY = numeric::intDivCeil(labelRect.y + labelRect.height - clientHeight, pixelsPerUnitY);
Scroll(scrollPosOld.x, scrollPosNewY);
updateWindowSizes(); //may show horizontal scroll bar if row column gets wider
Refresh();
diff --git a/wx+/grid.h b/wx+/grid.h
index 83b06c63..8d68ffd7 100644
--- a/wx+/grid.h
+++ b/wx+/grid.h
@@ -12,7 +12,7 @@
#include <optional>
#include <set>
#include <vector>
-#include <zen/basic_math.h>
+//#include <zen/basic_math.h>
#include <wx/scrolwin.h>
diff --git a/wx+/image_resources.cpp b/wx+/image_resources.cpp
index 6931e82e..42114ebb 100644
--- a/wx+/image_resources.cpp
+++ b/wx+/image_resources.cpp
@@ -210,7 +210,7 @@ ImageBuffer::ImageBuffer(const Zstring& zipPath) //throw FileError
wxImage::AddHandler(new wxPNGHandler); //ownership passed
//do we need xBRZ scaling for high quality DPI images?
- const int hqScale = std::clamp<int>(std::ceil(fastFromDIP(1000) / 1000.0), 1, xbrz::SCALE_FACTOR_MAX);
+ const int hqScale = std::clamp(numeric::intDivCeil(fastFromDIP(1000), 1000), 1, xbrz::SCALE_FACTOR_MAX);
//even for 125% DPI scaling, "2xBRZ + bilinear downscale" gives a better result than mere "125% bilinear upscale"!
if (hqScale > 1)
hqScaler_ = std::make_unique<HqParallelScaler>(hqScale);
@@ -283,7 +283,7 @@ const wxImage& ImageBuffer::getImage(const std::string& name, int maxWidth /*opt
int outHeight = dpiSize.y;
if (maxWidth >= 0 && maxWidth < dpiSize.x)
- outHeight = rawImg.GetHeight() * maxWidth / rawImg.GetWidth();
+ outHeight = numeric::intDivRound(maxWidth * rawImg.GetHeight(), rawImg.GetWidth());
if (maxHeight >= 0 && maxHeight < outHeight)
outHeight = maxHeight;
@@ -297,7 +297,7 @@ const wxImage& ImageBuffer::getImage(const std::string& name, int maxWidth /*opt
it = imagesOut_.emplace(imkey, shrinkImage(rawImg, -1 /*maxWidth*/, outHeight)).first;
else if (rawImg.GetHeight() >= 0.9 * outHeight) //almost there: also no need for xBRZ-scale
//however: for 125% DPI scaling, "2xBRZ + bilinear downscale" gives a better result than mere "125% bilinear upscale"!
- it = imagesOut_.emplace(imkey, rawImg.Scale(rawImg.GetWidth() * outHeight / rawImg.GetHeight(), outHeight, wxIMAGE_QUALITY_BILINEAR)).first;
+ it = imagesOut_.emplace(imkey, rawImg.Scale(numeric::intDivRound(outHeight * rawImg.GetWidth(), rawImg.GetHeight()), outHeight, wxIMAGE_QUALITY_BILINEAR)).first;
else
it = imagesOut_.emplace(imkey, shrinkImage(getScaledImage(name), -1 /*maxWidth*/, outHeight)).first;
}
diff --git a/wx+/image_tools.cpp b/wx+/image_tools.cpp
index 4569a2a7..6ba95c5e 100644
--- a/wx+/image_tools.cpp
+++ b/wx+/image_tools.cpp
@@ -37,14 +37,14 @@ void copySubImage(const wxImage& src, wxPoint srcPos,
std::clamp(pos.x, 0, img.GetWidth ()),
std::clamp(pos.y, 0, img.GetHeight())};
};
- auto pointMinus = [](const wxPoint& lhs, const wxPoint& rhs) { return wxSize{lhs.x - rhs.x, lhs.y - rhs.y}; };
+ auto subtract = [](const wxPoint& lhs, const wxPoint& rhs) { return wxSize{lhs.x - rhs.x, lhs.y - rhs.y}; };
//work around yet another wxWidgets screw up: WTF does "operator-(wxPoint, wxPoint)" return wxPoint instead of wxSize!??
const wxPoint trgPos2 = pointClamp(trgPos, trg);
const wxPoint trgPos2End = pointClamp(trgPos + blockSize, trg);
- blockSize = pointMinus(trgPos2End, trgPos2);
- srcPos += pointMinus(trgPos2, trgPos);
+ blockSize = subtract(trgPos2End, trgPos2);
+ srcPos += subtract(trgPos2, trgPos);
trgPos = trgPos2;
if (blockSize.x <= 0 || blockSize.y <= 0)
return;
@@ -52,8 +52,8 @@ void copySubImage(const wxImage& src, wxPoint srcPos,
const wxPoint srcPos2 = pointClamp(srcPos, src);
const wxPoint srcPos2End = pointClamp(srcPos + blockSize, src);
- blockSize = pointMinus(srcPos2End, srcPos2);
- trgPos += pointMinus(srcPos2, srcPos);
+ blockSize = subtract(srcPos2End, srcPos2);
+ trgPos += subtract(srcPos2, srcPos);
srcPos = srcPos2;
if (blockSize.x <= 0 || blockSize.y <= 0)
return;
@@ -181,12 +181,7 @@ wxImage zen::createImageFromText(const wxString& text, const wxFont& font, const
//assert(!contains(text, L"&")); //accelerator keys not supported here
wxString textFmt = replaceCpy(text, L"&", L"", false);
- //for some reason wxDC::DrawText messes up "weak" bidi characters even when wxLayout_RightToLeft is set! (--> arrows in hebrew/arabic)
- //=> use mark characters instead:
- if (wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft)
- textFmt = RTL_MARK + textFmt + RTL_MARK;
-
- const std::vector<std::pair<wxString, wxSize>> lineInfo = getTextExtentInfo(textFmt, font);
+ const std::vector<std::pair<wxString, wxSize>> lineInfo = getTextExtentInfo(textFmt, font);
int maxWidth = 0;
int lineHeight = 0;
@@ -201,6 +196,10 @@ wxImage zen::createImageFromText(const wxString& text, const wxFont& font, const
wxBitmap newBitmap(maxWidth, lineHeight * lineInfo.size()); //seems we don't need to pass 24-bit depth here even for high-contrast color schemes
{
wxMemoryDC dc(newBitmap);
+
+ if (wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft)
+ dc.SetLayoutDirection(wxLayout_RightToLeft); //handle e.g. "weak" bidi characters: -> arrows in hebrew/arabic
+
dc.SetBackground(*wxWHITE_BRUSH);
dc.Clear();
@@ -296,12 +295,12 @@ wxImage zen::resizeCanvas(const wxImage& img, wxSize newSize, int alignment)
if (alignment & wxALIGN_RIGHT) //note: wxALIGN_LEFT == 0!
newPos.x = newSize.GetWidth() - img.GetWidth();
else if (alignment & wxALIGN_CENTER_HORIZONTAL)
- newPos.x = static_cast<int>(std::floor((newSize.GetWidth() - img.GetWidth()) / 2)); //consistency: round down negative values, too!
+ newPos.x = numeric::intDivFloor(newSize.GetWidth() - img.GetWidth(), 2); //consistency: round down negative values, too!
if (alignment & wxALIGN_BOTTOM) //note: wxALIGN_TOP == 0!
newPos.y = newSize.GetHeight() - img.GetHeight();
else if (alignment & wxALIGN_CENTER_VERTICAL)
- newPos.y = static_cast<int>(std::floor((newSize.GetHeight() - img.GetHeight()) / 2)); //consistency: round down negative values, too!
+ newPos.y = numeric::intDivFloor(newSize.GetHeight() - img.GetHeight(), 2); //consistency: round down negative values, too!
wxImage output(newSize);
output.SetAlpha();
@@ -317,19 +316,16 @@ wxImage zen::shrinkImage(const wxImage& img, int maxWidth /*optional*/, int maxH
{
wxSize newSize = img.GetSize();
- if (maxWidth >= 0)
- if (maxWidth < newSize.x)
- {
- newSize.y = newSize.y * maxWidth / newSize.x;
- newSize.x = maxWidth;
- }
- if (maxHeight >= 0)
- if (maxHeight < newSize.y)
- {
- newSize = img.GetSize(); //avoid loss of precision
- newSize.x = newSize.x * maxHeight / newSize.y; //
- newSize.y = maxHeight;
- }
+ if (0 <= maxWidth && maxWidth < newSize.x)
+ {
+ newSize.x = maxWidth;
+ newSize.y = numeric::intDivRound(maxWidth * img.GetHeight(), img.GetWidth());
+ }
+ if (0 <= maxHeight && maxHeight < newSize.y)
+ {
+ newSize.x = numeric::intDivRound(maxHeight * img.GetWidth(), img.GetHeight()); //avoid loss of precision
+ newSize.y = maxHeight;
+ }
if (newSize == img.GetSize())
return img;
diff --git a/wx+/image_tools.h b/wx+/image_tools.h
index 1b4fbb43..0f0fb9c2 100644
--- a/wx+/image_tools.h
+++ b/wx+/image_tools.h
@@ -177,7 +177,7 @@ wxColor hsvColor(double h, double s, double v) //h within [0, 360), s, v within
auto polish = [](double val) -> unsigned char
{
- int result = numeric::round(val * 255);
+ int result = std::round(val * 255);
numeric::confine(result, 0, 255);
return static_cast<unsigned char>(result);
};
diff --git a/wx+/no_flicker.h b/wx+/no_flicker.h
index 53e47bb5..a84a7228 100644
--- a/wx+/no_flicker.h
+++ b/wx+/no_flicker.h
@@ -79,28 +79,28 @@ void setTextWithUrls(wxRichTextCtrl& richCtrl, const wxString& newText)
richCtrl.Clear();
+ wxRichTextAttr urlStyle;
+ urlStyle.SetTextColour(*wxBLUE);
+ urlStyle.SetFontUnderlined(true);
+
+ for (const auto& [type, text] : blocks)
+ switch (type)
+ {
+ case BlockType::text:
+ richCtrl.WriteText(text);
+ break;
+
+ case BlockType::url:
+ richCtrl.BeginStyle(urlStyle);
+ ZEN_ON_SCOPE_EXIT(richCtrl.EndStyle());
+ richCtrl.BeginURL(text);
+ ZEN_ON_SCOPE_EXIT(richCtrl.EndURL());
+ richCtrl.WriteText(text);
+ break;
+ }
+
if (std::any_of(blocks.begin(), blocks.end(), [](const auto& item) { return item.first == BlockType::url; }))
{
- wxRichTextAttr urlStyle;
- urlStyle.SetTextColour(*wxBLUE);
- urlStyle.SetFontUnderlined(true);
-
- for (const auto& [type, text] : blocks)
- switch (type)
- {
- case BlockType::text:
- richCtrl.WriteText(text);
- break;
-
- case BlockType::url:
- richCtrl.BeginStyle(urlStyle);
- ZEN_ON_SCOPE_EXIT(richCtrl.EndStyle());
- richCtrl.BeginURL(text);
- ZEN_ON_SCOPE_EXIT(richCtrl.EndURL());
- richCtrl.WriteText(text);
- break;
- }
-
//register only once! => use a global function pointer, so that Unbind() works correctly:
using LaunchUrlFun = void(*)(wxTextUrlEvent& event);
static const LaunchUrlFun launchUrl = [](wxTextUrlEvent& event) { wxLaunchDefaultBrowser(event.GetString()); };
@@ -108,8 +108,6 @@ void setTextWithUrls(wxRichTextCtrl& richCtrl, const wxString& newText)
[[maybe_unused]] const bool unbindOk = richCtrl.Unbind(wxEVT_TEXT_URL, launchUrl);
richCtrl.Bind(wxEVT_TEXT_URL, launchUrl);
}
- else
- richCtrl.WriteText(newText);
}
}
}
diff --git a/wx+/popup_dlg.cpp b/wx+/popup_dlg.cpp
index 0a1ff2a0..88ed590b 100644
--- a/wx+/popup_dlg.cpp
+++ b/wx+/popup_dlg.cpp
@@ -5,6 +5,7 @@
// *****************************************************************************
#include "popup_dlg.h"
+#include <zen/basic_math.h>
#include <wx/app.h>
#include <wx/display.h>
#include "no_flicker.h"
@@ -38,7 +39,7 @@ void setBestInitialSize(wxRichTextCtrl& ctrl, const wxString& text, wxSize maxSi
{
maxLineWidth = std::max(maxLineWidth, sz.x);
- const int wrappedRows = numeric::integerDivideRoundUp(sz.x, maxSize.x - scrollbarWidth); //integer round up: consider line-wraps!
+ const int wrappedRows = numeric::intDivCeil(sz.x, maxSize.x - scrollbarWidth); //round up: consider line-wraps!
rowCount += wrappedRows;
rowHeight = std::max(rowHeight, sz.y); //all rows *should* have same height
if (wrappedRows > 1)
@@ -71,8 +72,8 @@ void setBestInitialSize(wxRichTextCtrl& ctrl, const wxString& text, wxSize maxSi
const int extraHeight = 0;
#endif
int extraWidth = 0;
- if (haveLineWrap) //compensate for trivial integerDivideRoundUp() not
- extraWidth += ctrl.GetTextExtent(L"FreeFileSync").x / 2; //understanding line wrap algorithm
+ if (haveLineWrap) //compensate for trivial intDivCeil() not...
+ extraWidth += ctrl.GetTextExtent(L"FreeFileSync").x / 2; //...understanding line wrap algorithm
const wxSize bestSize(std::min(maxLineWidth, maxSize.x) + extraWidth,
std::min(rowCount * (rowHeight + rowGap) + extraHeight, maxSize.y));
bgstack15