summaryrefslogtreecommitdiff
path: root/wx+/graph.h
diff options
context:
space:
mode:
authorDaniel Wilhelm <daniel@wili.li>2014-04-18 17:15:16 +0200
committerDaniel Wilhelm <daniel@wili.li>2014-04-18 17:15:16 +0200
commitbd6336c629841c6db3a6ca53a936d629d34db53b (patch)
tree3721ef997864108df175ce677a8a7d4342a6f1d2 /wx+/graph.h
parent4.0 (diff)
downloadFreeFileSync-bd6336c629841c6db3a6ca53a936d629d34db53b.tar.gz
FreeFileSync-bd6336c629841c6db3a6ca53a936d629d34db53b.tar.bz2
FreeFileSync-bd6336c629841c6db3a6ca53a936d629d34db53b.zip
4.1
Diffstat (limited to 'wx+/graph.h')
-rw-r--r--wx+/graph.h325
1 files changed, 325 insertions, 0 deletions
diff --git a/wx+/graph.h b/wx+/graph.h
new file mode 100644
index 00000000..61a90ca1
--- /dev/null
+++ b/wx+/graph.h
@@ -0,0 +1,325 @@
+// **************************************************************************
+// * This file is part of the zenXML project. It is distributed under the *
+// * Boost Software License, Version 1.0. See accompanying file *
+// * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt. *
+// * Copyright (C) 2011 ZenJu (zhnmju123 AT gmx.de) *
+// **************************************************************************
+
+#ifndef WX_PLOT_HEADER_2344252459
+#define WX_PLOT_HEADER_2344252459
+
+#include <vector>
+#include <memory>
+#include <wx/panel.h>
+#include <wx/dcbuffer.h>
+#include <zen/string_tools.h>
+
+//simple 2D graph as wxPanel specialization
+
+namespace zen
+{
+/*
+Example:
+ //init graph (optional)
+ m_panelGraph->setAttributes(Graph2D::GraphAttributes().
+ setLabelX(Graph2D::POSLX_BOTTOM, 20, std::make_shared<LabelFormatterTimeElapsed>()).
+ setLabelY(Graph2D::POSLY_RIGHT, 60, std::make_shared<LabelFormatterBytes>()));
+ //set graph data
+ std::shared_ptr<GraphData>() graphDataBytes = ...
+ m_panelGraph->setData(graphDataBytes, Graph2D::LineAttributes().setLineWidth(2).setColor(wxColor(0, 192, 0)));
+*/
+
+//------------------------------------------------------------------------------------------------------------
+struct GraphData
+{
+ virtual ~GraphData() {}
+ virtual double getValue(double x) const = 0;
+ virtual double getXBegin() const = 0;
+ virtual double getXEnd() const = 0; //upper bound for x, getValue() is NOT evaluated at this position! Similar to std::vector::end()
+};
+
+
+//reference data implementation
+
+class RangeData : public GraphData
+{
+public:
+ std::vector<double>& refData() { return data; }
+
+private:
+ virtual double getValue(double x) const
+ {
+ const size_t pos = static_cast<size_t>(x);
+ return pos < data.size() ? data[pos] : 0;
+ }
+ virtual double getXBegin() const { return 0; }
+ virtual double getXEnd() const { return data.size(); } //example: two-element range is accessible within [0, 2)
+
+ std::vector<double> data;
+};
+
+
+//reference data implementation
+class VectorData : public GraphData
+{
+public:
+ operator std::vector<double>& () { return data; }
+
+private:
+ virtual double getValue(double x) const
+ {
+ const size_t pos = static_cast<size_t>(x);
+ return pos < data.size() ? data[pos] : 0;
+ }
+ virtual double getXBegin() const { return 0; }
+ virtual double getXEnd() const { return data.size(); } //example: two-element range is accessible within [0, 2)
+
+ std::vector<double> data;
+};
+
+//------------------------------------------------------------------------------------------------------------
+struct LabelFormatter
+{
+ virtual ~LabelFormatter() {}
+
+ //determine convenient graph label block size in unit of data: usually some small deviation on "sizeProposed"
+ virtual double getOptimalBlockSize(double sizeProposed) const = 0;
+
+ //create human-readable text for x or y-axis position
+ 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; 7 -> 5
+
+struct DecimalNumberFormatter : public LabelFormatter
+{
+ virtual double getOptimalBlockSize(double sizeProposed) const { return nextNiceNumber(sizeProposed); }
+ virtual wxString formatText(double value, double optimalBlockSize) const { return zen::toString<wxString>(value); }
+};
+
+//------------------------------------------------------------------------------------------------------------
+//emit data selection event
+//usage: wnd.Connect(wxEVT_GRAPH_SELECTION, GraphSelectEventHandler(MyDlg::OnGraphSelection), NULL, this);
+// void MyDlg::OnGraphSelection(GraphSelectEvent& event);
+
+
+extern const wxEventType wxEVT_GRAPH_SELECTION;
+
+struct SelectionBlock
+{
+ struct Point
+ {
+ Point() : x(0), y(0) {}
+ Point(double xVal, double yVal) : x(xVal), y(yVal) {}
+ double x;
+ double y;
+ };
+
+ Point from;
+ Point to;
+};
+
+class GraphSelectEvent : public wxCommandEvent
+{
+public:
+ GraphSelectEvent(const SelectionBlock& selBlock) : wxCommandEvent(wxEVT_GRAPH_SELECTION), selBlock_(selBlock_) {}
+
+ virtual wxEvent* Clone() const { return new GraphSelectEvent(selBlock_); }
+
+ SelectionBlock getSelection() { return selBlock_; }
+
+private:
+ SelectionBlock selBlock_;
+};
+
+typedef void (wxEvtHandler::*GraphSelectEventFunction)(GraphSelectEvent&);
+
+#define GraphSelectEventHandler(func) \
+ (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(GraphSelectEventFunction, &func)
+
+
+//------------------------------------------------------------------------------------------------------------
+class Graph2D : public wxPanel
+{
+public:
+ Graph2D(wxWindow* parent,
+ wxWindowID winid = wxID_ANY,
+ const wxPoint& pos = wxDefaultPosition,
+ const wxSize& size = wxDefaultSize,
+ long style = wxTAB_TRAVERSAL | wxNO_BORDER,
+ const wxString& name = wxPanelNameStr);
+
+ class LineAttributes
+ {
+ public:
+ LineAttributes() : autoColor(true), lineWidth(2) {}
+
+ LineAttributes& setColor(const wxColour& col) { color = col; autoColor = false; return *this; }
+ LineAttributes& setLineWidth(size_t width) { lineWidth = width; return *this; }
+
+ private:
+ friend class Graph2D;
+
+ bool autoColor;
+ wxColour color;
+ size_t lineWidth;
+ };
+
+ void setData(const std::shared_ptr<GraphData>& data, const LineAttributes& attr = LineAttributes());
+ void addData(const std::shared_ptr<GraphData>& data, const LineAttributes& attr = LineAttributes());
+
+ enum PosLabelY
+ {
+ Y_LABEL_LEFT,
+ Y_LABEL_RIGHT,
+ Y_LABEL_NONE
+ };
+
+ enum PosLabelX
+ {
+ X_LABEL_TOP,
+ X_LABEL_BOTTOM,
+ X_LABEL_NONE
+ };
+
+ enum SelMode
+ {
+ SELECT_NONE,
+ SELECT_RECTANGLE,
+ SELECT_X_AXIS,
+ SELECT_Y_AXIS,
+ };
+
+ class GraphAttributes
+ {
+ public:
+ GraphAttributes() :
+ minXauto(true),
+ maxXauto(true),
+ minX(0),
+ maxX(0),
+ minYauto(true),
+ maxYauto(true),
+ minY(0),
+ maxY(0),
+ labelposX(X_LABEL_BOTTOM),
+ labelHeightX(25),
+ labelFmtX(new DecimalNumberFormatter()),
+ labelposY(Y_LABEL_LEFT),
+ labelWidthY(60),
+ labelFmtY(new DecimalNumberFormatter()),
+ mouseSelMode(SELECT_RECTANGLE) {}
+
+
+ GraphAttributes& setMinX(double newMinX) { minX = newMinX; minXauto = false; return *this; }
+ GraphAttributes& setMaxX(double newMaxX) { maxX = newMaxX; maxXauto = false; return *this; }
+
+ GraphAttributes& setMinY(double newMinY) { minY = newMinY; minYauto = false; return *this; }
+ GraphAttributes& setMaxY(double newMaxY) { maxY = newMaxY; maxYauto = false; return *this; }
+
+ GraphAttributes& setAutoSize() { minXauto = true; maxXauto = true; minYauto = true; maxYauto = true; return *this; }
+
+ GraphAttributes& setLabelX(PosLabelX posX, size_t height = 25, const std::shared_ptr<LabelFormatter>& newLabelFmt = std::shared_ptr<LabelFormatter>(new DecimalNumberFormatter()))
+ {
+ labelposX = posX;
+ labelHeightX = height;
+ labelFmtX = newLabelFmt;
+ return *this;
+ }
+ GraphAttributes& setLabelY(PosLabelY posY, size_t width = 60, const std::shared_ptr<LabelFormatter>& newLabelFmt = std::shared_ptr<LabelFormatter>(new DecimalNumberFormatter()))
+ {
+ labelposY = posY;
+ labelWidthY = width;
+ labelFmtY = newLabelFmt;
+ return *this;
+ }
+
+ GraphAttributes& setSelectionMode(SelMode mode) { mouseSelMode = mode; return *this; }
+
+ private:
+ friend class Graph2D;
+
+ bool minXauto; //autodetect range for X value
+ bool maxXauto;
+ double minX; //x-range to visualize
+ double maxX;
+
+ bool minYauto; //autodetect range for Y value
+ bool maxYauto;
+ double minY; //y-range to visualize
+ double maxY;
+
+ PosLabelX labelposX;
+ size_t labelHeightX;
+ std::shared_ptr<LabelFormatter> labelFmtX;
+
+ PosLabelY labelposY;
+ size_t labelWidthY;
+ std::shared_ptr<LabelFormatter> labelFmtY;
+
+ SelMode mouseSelMode;
+ };
+ void setAttributes(const GraphAttributes& newAttr) { attr = newAttr; Refresh(); }
+ GraphAttributes getAttributes() const { return attr; }
+
+
+ std::vector<SelectionBlock> getSelections() const { return oldSel; }
+ void setSelections(const std::vector<SelectionBlock>& sel)
+ {
+ oldSel = sel;
+ activeSel.reset();
+ Refresh();
+ }
+ void clearSelection() { oldSel.clear(); Refresh(); }
+
+private:
+ void OnMouseLeftDown(wxMouseEvent& event);
+ void OnMouseMovement(wxMouseEvent& event);
+ void OnMouseLeftUp (wxMouseEvent& event);
+ void OnMouseCaptureLost(wxMouseCaptureLostEvent& event);
+
+ void onPaintEvent(wxPaintEvent& evt)
+ {
+ wxAutoBufferedPaintDC dc(this); //double-buffer only on systems that require it
+ render(dc);
+ }
+
+ void onRefreshRequired(wxEvent& evt)
+ {
+ Refresh();
+ evt.Skip();
+ }
+
+ void onEraseBackGround(wxEraseEvent& evt) {}
+
+ void render(wxDC& dc) const;
+
+ class MouseSelection
+ {
+ public:
+ MouseSelection(wxWindow& wnd, const wxPoint& posDragStart) : wnd_(wnd), posDragStart_(posDragStart), posDragCurrent(posDragStart) { wnd_.CaptureMouse(); }
+ ~MouseSelection() { if (wnd_.HasCapture()) wnd_.ReleaseMouse(); }
+
+ wxPoint getStartPos() const { return posDragStart_; }
+ wxPoint& refCurrentPos() { return posDragCurrent; }
+
+ SelectionBlock& refSelection() { return selBlock; } //set when selection is drawn: this is fine, 'cause only what's shown should be selected!
+
+ private:
+ wxWindow& wnd_;
+ const wxPoint posDragStart_;
+ wxPoint posDragCurrent;
+ SelectionBlock selBlock;
+ };
+ std::vector<SelectionBlock> oldSel; //applied selections
+ std::shared_ptr<MouseSelection> activeSel; //set during mouse selection
+
+ GraphAttributes attr; //global attributes
+
+ typedef std::vector<std::pair<std::shared_ptr<GraphData>, LineAttributes>> GraphList;
+ GraphList curves_;
+};
+}
+
+
+#endif //WX_PLOT_HEADER_2344252459
bgstack15