8 #include <wx/checkbox.h>
9 #include <wx/dcclient.h>
13 #include <wx/aui/auibook.h>
21 const Size defaultSelectedIdx,
23 : wxPanel(parent, wxID_ANY, wxDefaultPosition, size)
26 , ticsParams(ticsParams) {
27 this->SetMinSize(size);
28 this->Connect(wxEVT_PAINT, wxPaintEventHandler(PlotView::onPaint));
29 this->Connect(wxEVT_RIGHT_UP, wxMouseEventHandler(PlotView::onRightUp));
30 this->Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(PlotView::onDoubleClick));
32 this->updatePlot(defaultSelectedIdx);
36 this->SetMinSize(wxSize(size.
x, size.
y));
52 const wxSize size = this->GetSize() - 2 * padding;
55 const Float scaleX = size.x / rangeX.
size();
56 const Float scaleY = -size.y / rangeY.
size();
59 const Float transX = padding.x - scaleX * rangeX.
lower();
60 const Float transY = size.y + padding.y - scaleY * rangeY.
lower();
62 return AffineMatrix2(scaleX, 0._f, 0._f, scaleY, transX, transY);
65 void PlotView::updatePlot(
const Size index) {
66 if (index >= list->size()) {
71 cached.color = data.
color;
75 cached.plot = data.
plot;
78 void PlotView::onRightUp(wxMouseEvent&
UNUSED(evt)) {
79 if (list->size() <= 1) {
87 menu.Append(index++, data.plot->getCaption());
90 menu.Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(PlotView::onMenu),
nullptr,
this);
91 this->PopupMenu(&menu);
94 void PlotView::onDoubleClick(wxMouseEvent&
UNUSED(evt)) {
102 const wxSize pad(25, 25);
103 const wxSize size = notebook->GetClientSize() - wxSize(15, 60);
106 const Size index = notebook->GetPageCount();
108 const std::string caption = cached.plot->getCaption();
109 notebook->AddPage(page, caption);
110 notebook->SetSelection(index);
113 void PlotView::onMenu(wxCommandEvent& evt) {
115 const Size index = evt.GetId();
117 this->updatePlot(index);
121 void PlotView::onPaint(wxPaintEvent&
UNUSED(evt)) {
123 wxSize canvasSize = dc.GetSize();
126 Rgba backgroundColor =
Rgba(this->GetParent()->GetBackgroundColour());
128 brush.SetColour(wxColour(backgroundColor.
darken(0.3f)));
130 dc.DrawRectangle(wxPoint(0, 0), canvasSize);
136 auto proxy = cached.plot.lock();
137 this->drawCaption(dc, *proxy);
141 if (rangeX.
size() <= 0._f || rangeY.
size() <= 0) {
147 pen.SetColour(*wxWHITE);
150 this->drawPlot(dc, *proxy, rangeX, rangeY);
153 void PlotView::drawPlot(wxPaintDC& dc,
IPlot& lockedPlot,
const Interval rangeX,
const Interval rangeY) {
156 context.setTransformMatrix(matrix);
158 lockedPlot.
plot(context);
162 const wxSize size = this->GetSize();
167 if (x0 >= 0._f && x0 <= 1._f) {
169 const int dcX = int(padding.x + x0 * (size.x - 2 * padding.x));
170 dc.DrawLine(dcX, size.y - padding.y, dcX, padding.y);
174 for (
const Float tic : tics) {
178 int(imagePoint.
x) - 2,
int(imagePoint.
y),
int(imagePoint.
x) + 2,
int(imagePoint.
y));
180 const wxSize extent = dc.GetTextExtent(text);
182 (imagePoint.
x > size.x / 2._f) ?
int(imagePoint.
x) - extent.x : int(imagePoint.
x);
189 if (y0 >= 0._f && y0 <= 1._f) {
191 const int dcY = int(size.y - padding.y - y0 * (size.y - 2 * padding.y));
192 dc.DrawLine(padding.x, dcY, size.x - padding.x, dcY);
195 for (
const Float tic : tics) {
199 int(imagePoint.
x),
int(imagePoint.
y) - 2,
int(imagePoint.
x),
int(imagePoint.
y) + 2);
201 const wxSize extent = dc.GetTextExtent(text);
203 (imagePoint.
y < size.y / 2._f) ?
int(imagePoint.
y) : int(imagePoint.
y) - extent.y;
210 void PlotView::drawCaption(wxDC& dc,
IPlot& lockedPlot) {
213 const wxString label = lockedPlot.
getCaption();
214 wxFont font = dc.GetFont();
217 const wxSize labelSize = dc.GetTextExtent(label);
218 dc.DrawText(label, dc.GetSize().x - labelSize.x, 0);
222 : wxPanel(parent, wxID_ANY)
225 this->SetMinSize(size);
229 wxBoxSizer* sizer =
new wxBoxSizer(wxVERTICAL);
230 const Size toolbarHeight = 20;
231 wxBoxSizer* toolbarSizer = this->createToolbar(toolbarHeight);
232 sizer->Add(toolbarSizer);
234 wxSize viewSize(size.x, size.y - toolbarHeight);
236 sizer->Add(plotView);
237 this->SetSizerAndFit(sizer);
239 this->Bind(wxEVT_SIZE, [
this](wxSizeEvent& evt) {
240 const wxSize size = evt.GetSize();
241 plotView->
resize(
Pixel(size.x, size.y - toolbarHeight));
245 wxBoxSizer* PlotPage::createToolbar(
const Size UNUSED(toolbarHeight)) {
246 wxBoxSizer* sizer =
new wxBoxSizer(wxHORIZONTAL);
248 wxButton* savePlotButton =
new wxButton(
this, wxID_ANY,
"Save Plot");
249 savePlotButton->Bind(wxEVT_BUTTON, [
this](wxCommandEvent&
UNUSED(evt)) {
252 {
"PNG image",
"png" },
253 {
"SVG image",
"svg" },
256 this->saveImage(path.
value());
259 sizer->Add(savePlotButton, 0, wxALIGN_CENTER_VERTICAL);
261 wxButton* saveDataButton =
new wxButton(
this, wxID_ANY,
"Save Data");
262 saveDataButton->Bind(wxEVT_BUTTON, [
this](wxCommandEvent&
UNUSED(evt)) {
265 {
"Text file",
"txt" },
268 this->saveData(path.
value());
271 sizer->Add(saveDataButton, 0, wxALIGN_CENTER_VERTICAL);
273 wxButton* refreshButton =
new wxButton(
this, wxID_ANY,
"Refresh");
274 refreshButton->Bind(wxEVT_BUTTON, [
this](wxCommandEvent&
UNUSED(evt)) { this->Refresh(); });
275 sizer->Add(refreshButton, 0, wxALIGN_CENTER_VERTICAL);
277 wxCheckBox* addZeroXBox =
new wxCheckBox(
this, wxID_ANY,
"Show zero X");
278 addZeroXBox->Bind(wxEVT_CHECKBOX, [
this, addZeroXBox](wxCommandEvent&
UNUSED(evt)) {
279 const bool checked = addZeroXBox->GetValue();
283 sizer->Add(addZeroXBox, 0, wxALIGN_CENTER_VERTICAL);
285 wxCheckBox* addZeroYBox =
new wxCheckBox(
this, wxID_ANY,
"Show zero Y");
286 addZeroYBox->Bind(wxEVT_CHECKBOX, [
this, addZeroYBox](wxCommandEvent&
UNUSED(evt)) {
287 const bool checked = addZeroYBox->GetValue();
291 sizer->Add(addZeroYBox, 0, wxALIGN_CENTER_VERTICAL);
295 void PlotPage::saveImage(
const Path& path) {
297 wxBitmap bitmap(800, 600, wxBITMAP_SCREEN_DEPTH);
298 wxMemoryDC dc(bitmap);
299 dc.SetBrush(*wxWHITE_BRUSH);
300 dc.DrawRectangle(0, 0, 800, 600);
302 auto proxy = plot.
lock();
304 const Interval actRangeX = extendRange(proxy->rangeX(), plotView->
addZeroX);
305 const Interval actRangeY = extendRange(proxy->rangeY(), plotView->
addZeroY);
307 gc.setTransformMatrix(matrix);
312 pen.SetColour(*wxBLACK);
314 plotView->
drawAxes(dc, actRangeX, actRangeY);
316 dc.SelectObject(wxNullBitmap);
318 bitmap.SaveFile(path.
native().c_str(), wxBITMAP_TYPE_PNG);
320 auto proxy = plot.
lock();
323 gc.setTransformMatrix(matrix);
339 logger.
write(point.
x,
" ", point.
y);
343 logger.
write(point.
x,
" ", point.
y);
366 return makeAuto<TextPath>();
379 void PlotPage::saveData(
const Path& path) {
381 auto proxy = plot.
lock();
383 proxy->plot(context);
#define SPH_ASSERT(x,...)
#define NOT_IMPLEMENTED
Helper macro marking missing implementation.
@ MAIN_THREAD
Function can only be executed from main thread.
#define CHECK_FUNCTION(flags)
uint32_t Size
Integral type used to index arrays (by default).
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Logging routines of the run.
wxAuiNotebook * findNotebook()
#define NAMESPACE_SPH_END
Object representing a path on a filesystem, similar to std::filesystem::path in c++17.
Array< Float > getLinearTics(const Interval &interval, const Size minCount)
Returns the tics to be drawn on a linear axis of a plot.
Implementation of IDrawingContext for creating vector images (.svg)
void drawTextWithSubscripts(wxDC &dc, const std::wstring &text, const wxPoint point)
std::wstring toPrintableString(const Float value, const Size precision, const Float decimalThreshold)
Converts the value to a printable string.
Optional< Path > doSaveFileDialog(const std::string &title, Array< FileFormat > &&formats)
Random utility functions for drawing stuff to DC.
PlotPoint transformPoint(const PlotPoint &p) const
Applies the affine transform on given point.
Generic dynamically allocated resizable storage.
INLINE TCounter size() const noexcept
Wrapper of pointer that deletes the resource from destructor.
Drawing context using wxWidgets implementation of Cairo backend.
Abstraction of a drawing context.
void write(TArgs &&... args)
Creates and logs a message by concatenating arguments.
Interface for constructing generic plots from quantities stored in storage.
virtual void plot(IDrawingContext &dc) const =0
Draws the plot into the drawing context.
virtual std::string getCaption() const =0
Returns the caption of the plot.
Object representing a 1D interval of real numbers.
INLINE Float lower() const
Returns lower bound of the interval.
INLINE void extend(const Float &value)
Extends the interval to contain given value.
INLINE Float size() const
Returns the size of the interval.
INLINE Type & value()
Returns the reference to the stored value.
Object representing a path on a filesystem.
std::string native() const
Returns the native version of the path.
Path extension() const
Returns the extension of the filename.
PlotPage(wxWindow *parent, const wxSize size, const wxSize padding, const LockingPtr< IPlot > &plot)
bool addZeroY
Include zero in y-range.
bool addZeroX
Include zero in x-range.
AffineMatrix2 getPlotTransformMatrix(const Interval &rangeX, const Interval &rangeY) const
Returns the transformation matrix for managed plot.
PlotView(wxWindow *parent, const wxSize size, const wxSize padding, const SharedPtr< Array< PlotData >> &list, const Size defaultSelectedIdx, Optional< TicsParams > ticsParams)
void resize(const Pixel size)
void drawAxes(wxDC &dc, const Interval rangeX, const Interval rangeY)
Rgba darken(const float amount) const
Returns a color darker by given factor.
virtual void closePath() override
Closes the path, connecting to the first point on the path.
virtual void endPath() override
Finalizes the path. Does not connect the last point to anything.
virtual void addPoint(const PlotPoint &UNUSED(point)) override
virtual void drawPoint(const PlotPoint &point) override
Adds a single point to the plot.
virtual void setTransformMatrix(const AffineMatrix2 &UNUSED(matrix)) override
virtual void setStyle(const Size UNUSED(index)) override
TextContext(const Path &path)
virtual void drawLine(const PlotPoint &UNUSED(from), const PlotPoint &UNUSED(to)) override
virtual void drawErrorPoint(const ErrorPlotPoint &point) override
Adds a point with error bars to the plot.
virtual AutoPtr< IDrawPath > drawPath() override
Draws a path connecting points.
Rgba color
Color of the plot.
LockingPtr< IPlot > plot
Plot to be drawn with associated mutex.