summaryrefslogtreecommitdiff
path: root/wx+/graph.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'wx+/graph.cpp')
-rw-r--r--wx+/graph.cpp130
1 files changed, 59 insertions, 71 deletions
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_;
bgstack15