diff options
Diffstat (limited to 'wx+')
-rw-r--r-- | wx+/dc.h | 2 | ||||
-rw-r--r-- | wx+/graph.cpp | 14 | ||||
-rw-r--r-- | wx+/grid.cpp | 28 | ||||
-rw-r--r-- | wx+/grid.h | 1 | ||||
-rw-r--r-- | wx+/image_resources.cpp | 16 | ||||
-rw-r--r-- | wx+/no_flicker.h | 10 | ||||
-rw-r--r-- | wx+/popup_dlg.cpp | 1 | ||||
-rw-r--r-- | wx+/rtl.h | 24 |
8 files changed, 57 insertions, 39 deletions
@@ -136,7 +136,7 @@ wxBitmap toScaledBitmap(const wxImage& img /*expected to be DPI-scaled!*/) //all this shit just because wxDC::SetScaleFactor() is missing: -inline +inline void setScaleFactor(wxDC& dc, double scale) { struct wxDcSurgeon : public wxDCImpl diff --git a/wx+/graph.cpp b/wx+/graph.cpp index eb9256f4..f9094386 100644 --- a/wx+/graph.cpp +++ b/wx+/graph.cpp @@ -232,7 +232,7 @@ void drawCornerText(wxDC& dc, const wxRect& graphArea, const wxString& txt, Grap //calculate intersection of polygon with half-plane template <class Function, class Function2> -void cutPoints(std::vector<CurvePoint>& curvePoints, std::vector<char>& oobMarker, Function isInside, Function2 getIntersection, bool doPolygonCut) +void cutPoints(std::vector<CurvePoint>& curvePoints, std::vector<unsigned char>& oobMarker, Function isInside, Function2 getIntersection, bool doPolygonCut) { assert(curvePoints.size() == oobMarker.size()); @@ -240,8 +240,8 @@ void cutPoints(std::vector<CurvePoint>& curvePoints, std::vector<char>& oobMarke auto isMarkedOob = [&](size_t index) { return oobMarker[index] != 0; }; //test if point is start of an OOB line - std::vector<CurvePoint> curvePointsTmp; - std::vector<char> oobMarkerTmp; + std::vector<CurvePoint> curvePointsTmp; + std::vector<unsigned char> oobMarkerTmp; curvePointsTmp.reserve(curvePoints.size()); //allocating memory for these containers is one oobMarkerTmp .reserve(oobMarker .size()); //of the more expensive operations of Graph2D! @@ -308,13 +308,13 @@ private: const double y_; }; -void cutPointsOutsideX(std::vector<CurvePoint>& curvePoints, std::vector<char>& oobMarker, double minX, double maxX, bool doPolygonCut) +void cutPointsOutsideX(std::vector<CurvePoint>& curvePoints, std::vector<unsigned char>& oobMarker, double minX, double maxX, bool doPolygonCut) { cutPoints(curvePoints, oobMarker, [&](const CurvePoint& pt) { return pt.x >= minX; }, GetIntersectionX(minX), doPolygonCut); cutPoints(curvePoints, oobMarker, [&](const CurvePoint& pt) { return pt.x <= maxX; }, GetIntersectionX(maxX), doPolygonCut); } -void cutPointsOutsideY(std::vector<CurvePoint>& curvePoints, std::vector<char>& oobMarker, double minY, double maxY, bool doPolygonCut) +void cutPointsOutsideY(std::vector<CurvePoint>& curvePoints, std::vector<unsigned char>& oobMarker, double minY, double maxY, bool doPolygonCut) { cutPoints(curvePoints, oobMarker, [&](const CurvePoint& pt) { return pt.y >= minY; }, GetIntersectionY(minY), doPolygonCut); cutPoints(curvePoints, oobMarker, [&](const CurvePoint& pt) { return pt.y <= maxY; }, GetIntersectionY(maxY), doPolygonCut); @@ -615,8 +615,8 @@ void Graph2D::render(wxDC& dc) const double minY = attr_.minY ? *attr_.minY : std::numeric_limits<double>::infinity(); //automatic: ensure values are initialized by first curve double maxY = attr_.maxY ? *attr_.maxY : -std::numeric_limits<double>::infinity(); // - std::vector<std::vector<CurvePoint>> curvePoints(curves_.size()); - std::vector<std::vector<char>> oobMarker (curves_.size()); //effectively a std::vector<bool> marking points that start an out-of-bounds line + std::vector<std::vector<CurvePoint>> curvePoints(curves_.size()); + std::vector<std::vector<unsigned char>> oobMarker (curves_.size()); //effectively a std::vector<bool> marking points that start an out-of-bounds line for (size_t index = 0; index < curves_.size(); ++index) { diff --git a/wx+/grid.cpp b/wx+/grid.cpp index a32de84e..5d2adc1a 100644 --- a/wx+/grid.cpp +++ b/wx+/grid.cpp @@ -164,7 +164,7 @@ void GridData::drawCellText(wxDC& dc, const wxRect& rect, const std::wstring& te if (extentTrunc.GetWidth() > rect.width) { - //unlike Windows Explorer, we truncate UTF-16 correctly: e.g. CJK-Ideogramm encodes to TWO wchar_t: utfTo<std::wstring>("\xf0\xa4\xbd\x9c"); + //unlike Windows Explorer, we truncate UTF-16 correctly: e.g. CJK-Ideograph encodes to TWO wchar_t: utfTo<std::wstring>("\xf0\xa4\xbd\x9c"); size_t low = 0; //number of unicode chars! size_t high = unicodeLength(text); // if (high > 1) @@ -285,7 +285,7 @@ public: Bind(wxEVT_MOUSE_CAPTURE_LOST, [this](wxMouseCaptureLostEvent& event) { onMouseCaptureLost(event); }); Bind(wxEVT_KEY_DOWN, [this](wxKeyEvent& event) { onKeyDown(event); }); - Bind(wxEVT_KEY_UP, [this](wxKeyEvent& event) { onKeyUp (event); }); + //Bind(wxEVT_KEY_UP, [this](wxKeyEvent& event) { onKeyUp (event); }); -> superfluous? assert(GetClientAreaOrigin() == wxPoint()); //generally assumed when dealing with coordinates below } @@ -340,12 +340,6 @@ private: event.Skip(); } - void onKeyUp(wxKeyEvent& event) - { - if (!sendEventToParent(event)) //let parent collect all key events - event.Skip(); - } - void onMouseWheel(wxMouseEvent& event) { /* MSDN, WM_MOUSEWHEEL: "Sent to the focus window when the mouse wheel is rotated. @@ -969,6 +963,17 @@ public: colLabelWin_(colLabelWin) { Bind(EVENT_GRID_HAS_SCROLLED, [this](wxCommandEvent& event) { onRequestWindowUpdate(event); }); + + Bind(wxEVT_KEY_DOWN, [this](wxKeyEvent& event) + { + if (event.GetKeyCode() == WXK_ESCAPE && activeSelection_) //allow Escape key to cancel active selection! + { + wxMouseCaptureLostEvent evt; + GetEventHandler()->ProcessEvent(evt); //better integrate into event handling rather than calling onMouseCaptureLost() directly!? + } + else + event.Skip(); + }); } ~MainWin() { assert(!gridUpdatePending_); } @@ -1099,6 +1104,13 @@ private: void onMouseDown(wxMouseEvent& event) //handle left and right mouse button clicks (almost) the same { + if (activeSelection_) //allow other mouse button to cancel active selection! + { + wxMouseCaptureLostEvent evt; + GetEventHandler()->ProcessEvent(evt); + return; + } + if (auto prov = refParent().getDataProvider()) { evalMouseMovement(event.GetPosition()); //update highlight in obscure cases (e.g. right-click while other context menu is open) @@ -10,7 +10,6 @@ #include <memory> #include <numeric> #include <optional> -//#include <set> #include <vector> #include <zen/stl_tools.h> #include <wx/scrolwin.h> diff --git a/wx+/image_resources.cpp b/wx+/image_resources.cpp index 36055f3f..58ae4d25 100644 --- a/wx+/image_resources.cpp +++ b/wx+/image_resources.cpp @@ -70,7 +70,7 @@ ImageHolder xbrzScale(int width, int height, const unsigned char* imageRgb, cons } -auto getScalerTask(const std::string& imageName, const wxImage& img, int hqScale, Protected<std::vector<std::pair<std::string, ImageHolder>>>& result) +auto createScalerTask(const std::string& imageName, const wxImage& img, int hqScale, Protected<std::vector<std::pair<std::string, ImageHolder>>>& result) { assert(runningOnMainThread()); return [imageName, @@ -97,7 +97,7 @@ public: { assert(runningOnMainThread()); imgKeeper_.push_back(img); //retain (ref-counted) wxImage so that the rgb/alpha pointers remain valid after passed to threads - threadGroup_->run(getScalerTask(imageName, img, hqScale_, result_)); + threadGroup_->run(createScalerTask(imageName, img, hqScale_, result_)); } std::unordered_map<std::string, wxImage> waitAndGetResult() @@ -125,7 +125,7 @@ private: std::vector<wxImage> imgKeeper_; Protected<std::vector<std::pair<std::string, ImageHolder>>> result_; - using TaskType = FunctionReturnTypeT<decltype(&getScalerTask)>; + using TaskType = FunctionReturnTypeT<decltype(&createScalerTask)>; 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" }; @@ -192,11 +192,13 @@ ImageBuffer::ImageBuffer(const Zstring& zipPath) //throw FileError else assert(false); } - catch (FileError&) //fall back to folder + catch (FileError&) //fall back to folder: dev build (only!?) { const Zstring fallbackFolder = beforeLast(zipPath, Zstr(".zip"), IfNotFoundReturn::none); - if (dirAvailable(fallbackFolder)) //Debug build (only!?) - traverseFolder(fallbackFolder, [&](const FileInfo& fi) + if (!itemStillExists(fallbackFolder)) //throw FileError + throw; + + traverseFolder(fallbackFolder, [&](const FileInfo& fi) { if (endsWith(fi.fullPath, Zstr(".png"))) { @@ -204,8 +206,6 @@ ImageBuffer::ImageBuffer(const Zstring& zipPath) //throw FileError streams.emplace_back(fi.itemName, std::move(stream)); } }, nullptr, nullptr, [](const std::wstring& errorMsg) { throw FileError(errorMsg); }); - else - throw; } //-------------------------------------------------------------------- diff --git a/wx+/no_flicker.h b/wx+/no_flicker.h index d8f2d6cd..7fa4ae23 100644 --- a/wx+/no_flicker.h +++ b/wx+/no_flicker.h @@ -85,20 +85,26 @@ void setTextWithUrls(wxRichTextCtrl& richCtrl, const wxString& newText) urlStyle.SetTextColour(*wxBLUE); urlStyle.SetFontUnderlined(true); - for (const auto& [type, text] : blocks) + for (auto& [type, text] : blocks) switch (type) { case BlockType::text: + if (endsWith(text, L"\n\n")) //bug: multiple newlines before a URL are condensed to only one; + //Why? fuck knows why! no such issue with double newlines *after* URL => hack this shit + text.RemoveLast().Append(ZERO_WIDTH_SPACE).Append(L'\n'); + 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; + } + break; } if (std::any_of(blocks.begin(), blocks.end(), [](const auto& item) { return item.first == BlockType::url; })) diff --git a/wx+/popup_dlg.cpp b/wx+/popup_dlg.cpp index 0a4c75c0..dfa5494f 100644 --- a/wx+/popup_dlg.cpp +++ b/wx+/popup_dlg.cpp @@ -10,6 +10,7 @@ #include <wx/app.h> #include <wx/display.h> #include <wx/sound.h> +#include "app_main.h" #include "bitmap_button.h" #include "no_flicker.h" #include "font_size.h" @@ -66,22 +66,22 @@ void drawBitmapRtlMirror(wxDC& dc, const wxImage& img, const wxRect& rect, int a case wxLayout_RightToLeft: if (rect.GetWidth() > 0 && rect.GetHeight() > 0) - { - if (!buffer || buffer->GetSize() != rect.GetSize()) //[!] since we do a mirror, width needs to match exactly! - buffer.emplace(rect.GetSize()); + { + if (!buffer || buffer->GetSize() != rect.GetSize()) //[!] since we do a mirror, width needs to match exactly! + buffer.emplace(rect.GetSize()); - if (buffer->GetScaleFactor() != dc.GetContentScaleFactor()) //needed here? - buffer->SetScaleFactor(dc.GetContentScaleFactor()); // + if (buffer->GetScaleFactor() != dc.GetContentScaleFactor()) //needed here? + buffer->SetScaleFactor(dc.GetContentScaleFactor()); // - wxMemoryDC memDc(*buffer); //copies scale factor from wxBitmap - memDc.Blit(wxPoint(0, 0), rect.GetSize(), &dc, rect.GetTopLeft()); //blit in: background is mirrored due to memDc, dc having different layout direction! + wxMemoryDC memDc(*buffer); //copies scale factor from wxBitmap + memDc.Blit(wxPoint(0, 0), rect.GetSize(), &dc, rect.GetTopLeft()); //blit in: background is mirrored due to memDc, dc having different layout direction! - impl::drawBitmapAligned(memDc, img, wxRect(0, 0, rect.width, rect.height), alignment); - //note: we cannot simply use memDc.SetLayoutDirection(wxLayout_RightToLeft) due to some strange 1 pixel bug! 2022-04-04: maybe fixed in wxWidgets 3.1.6? + impl::drawBitmapAligned(memDc, img, wxRect(0, 0, rect.width, rect.height), alignment); + //note: we cannot simply use memDc.SetLayoutDirection(wxLayout_RightToLeft) due to some strange 1 pixel bug! 2022-04-04: maybe fixed in wxWidgets 3.1.6? - dc.Blit(rect.GetTopLeft(), rect.GetSize(), &memDc, wxPoint(0, 0)); //blit out: mirror once again - } - break; + dc.Blit(rect.GetTopLeft(), rect.GetSize(), &memDc, wxPoint(0, 0)); //blit out: mirror once again + } + break; case wxLayout_Default: //CAVEAT: wxPaintDC/wxMemoryDC on wxGTK/wxMAC does not implement SetLayoutDirection()!!! => GetLayoutDirection() == wxLayout_Default if (wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft) |