Power System Platform  2026w10a-beta
Loading...
Searching...
No Matches
ChartView.cpp
1/*
2 * Copyright (C) 2017 Thales Lima Oliveira <thales@ufu.br>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18#include "ChartView.h"
19#include "../utils/ElementPlotData.h"
20
21#include <sstream>
22#include <wx/mstream.h>
23
24ChartView::ChartView(wxWindow* parent, std::vector<ElementPlotData> epdList, std::vector<double> time, PlotLib plotLib)
25 : ChartViewBase(parent)
26{
27 m_epdList = epdList;
28 m_time = time;
29 m_xAxisValues = time;
30 m_plotLib = plotLib;
31
32 m_menuItemShowGrid->Check(m_hideGrid ? false : true);
33 m_menuItemShowLabel->Check(m_showLeg);
34 m_menuItemShowCoordinates->Check(m_showCoords);
35 m_menuItemDarkTheme->Check(m_darkTheme);
36
37 // Create color property.
38 m_pgPropColor = m_pgMgr->Insert(m_pgPropLineProp, 1, new wxColourProperty(_("Color")));
39 m_pgPropColor->SetEditor(wxT("ChoiceAndButton"));
40 m_pgPropColor->SetValue(static_cast<wxVariant>(static_cast<wxAny>(*wxBLACK)));
41
42 // Set margins and axis limit to composed mode.
43 m_pgPropMargins->SetValue(wxT("<composed>"));
44 m_pgMgr->Collapse(m_pgPropMargins);
45 m_pgPropAxisLimit->SetValue(wxT("<composed>"));
46 m_pgMgr->Collapse(m_pgPropAxisLimit);
47
48 // Add line type choices
49 m_pgProplineType->AddChoice(_("Solid"), wxPENSTYLE_SOLID);
50 m_pgProplineType->AddChoice(_("Dot"), wxPENSTYLE_DOT);
51 m_pgProplineType->AddChoice(_("Dash"), wxPENSTYLE_SHORT_DASH);
52 m_pgProplineType->AddChoice(_("Dot and dash"), wxPENSTYLE_DOT_DASH);
53 if (m_plotLib == PlotLib::wxMATH_PLOT) {
54 m_pgProplineType->AddChoice(_("Cross"), wxPENSTYLE_CROSS_HATCH);
55 m_pgProplineType->AddChoice(_("Driagonal cross"), wxPENSTYLE_CROSSDIAG_HATCH);
56 }
57
58 if (m_plotLib == PlotLib::wxMATH_PLOT) {
59 SetMPWindow();
60 GetSizer()->Add(m_mpWindow, 1, wxEXPAND, WXC_FROM_DIP(5));
61 }
62 else if (m_plotLib == PlotLib::wxCHART_DIR) {
63 m_chartViewerDir = new wxChartViewer(this, ID_CHARTVIEWER);
64 m_chartViewerDir->SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
65 m_chartViewerDir->SetMinSize(wxSize(400, 300));
66 m_chartViewerDir->setMouseUsage(Chart::MouseUsageZoomIn);
67 m_chartViewerDir->setSelectionBorderWidth(1);
68 m_chartViewerDir->setSelectionBorderColor(wxColour(0, 125, 255, 255));
69 m_chartViewerDir->setMouseWheelZoomRatio(1.1);
70 m_chartViewerDir->setZoomDirection(Chart::DirectionHorizontalVertical);
71 m_chartViewerDir->setScrollDirection(Chart::DirectionHorizontalVertical);
72 GetSizer()->Add(m_chartViewerDir, 1, wxEXPAND, WXC_FROM_DIP(5));
73
74 this->Bind(wxEVT_CHARTVIEWER_VIEWPORT_CHANGED, &ChartView::OnViewPortChanged, this, ID_CHARTVIEWER);
75 this->Bind(wxEVT_CHARTVIEWER_MOUSEMOVE_PLOTAREA, &ChartView::OnMouseMovePlotArea, this, ID_CHARTVIEWER);
76 m_chartViewerDir->Bind(wxEVT_RIGHT_DOWN, &ChartView::OnRightClickDown, this);
77
78 m_pgPropMarginsUp->SetValue(10);
79 m_pgPropMarginsLeft->SetValue(50);
80 m_pgPropMarginsRight->SetValue(40);
81 m_pgPropMarginsBot->SetValue(40);
82
83 m_pgPropXLabel->SetValue(_("auto"));
84 m_pgPropYLabel->SetValue(_("auto"));
85 }
86 SetTreectrl();
87 Layout();
88 SetInitialSize();
89
90 BuildColourList();
91
92 //if (m_plotLib == PlotLib::wxCHART_DIR) {
93 // DrawChartDir();
94 //}
95}
96
97ChartView::~ChartView()
98{
99 if (m_plotLib == PlotLib::wxCHART_DIR) {
100 this->Unbind(wxEVT_CHARTVIEWER_VIEWPORT_CHANGED, &ChartView::OnViewPortChanged, this, ID_CHARTVIEWER);
101 this->Unbind(wxEVT_CHARTVIEWER_MOUSEMOVE_PLOTAREA, &ChartView::OnMouseMovePlotArea, this, ID_CHARTVIEWER);
102 m_chartViewerDir->Unbind(wxEVT_RIGHT_DOWN, &ChartView::OnRightClickDown, this);
103 }
104}
105void ChartView::SetMPWindow()
106{
107 m_mpWindow = new mpWindow(this, wxID_ANY);
108
109 m_mpWindow->SetDoubleBuffered(true);
110
111 m_mpWindow->SetMargins(20, 10, 40, 60);
112 m_xaxis = new mpScaleX("", mpALIGN_BOTTOM, true);
113 m_yaxis = new mpScaleY("", mpALIGN_LEFT, true);
114 m_xaxis->SetDrawOutsideMargins(false);
115 m_yaxis->SetDrawOutsideMargins(false);
116 m_xaxis->SetTicks(m_hideGrid);
117 m_yaxis->SetTicks(m_hideGrid);
118
119 m_leg = new mpInfoLegend(wxRect(200, 20, 40, 40), wxWHITE_BRUSH);
120 m_coords = new mpInfoCoords(wxRect(0, 0, 0, 0), wxWHITE_BRUSH);
121
122 m_chartTitle = new mpText("", 50, 0);
123 wxFont chartTitleFont(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD);
124 m_chartTitle->SetFont(chartTitleFont);
125
126 m_mpWindow->AddLayer(m_xaxis);
127 m_mpWindow->AddLayer(m_yaxis);
128 m_mpWindow->AddLayer(m_leg);
129 m_mpWindow->AddLayer(m_coords);
130 m_mpWindow->AddLayer(m_chartTitle);
131
132 m_leg->SetVisible(m_showLeg);
133 m_coords->SetVisible(m_showCoords);
134
135 m_mpWindow->EnableDoubleBuffer(true);
136 m_mpWindow->LockAspect(false);
137 Fit();
138}
139
140void ChartView::SetTreectrl()
141{
142 wxTreeItemId rootID = m_treeCtrl->AddRoot(wxT("root"));
143 m_treeTimeID = m_treeCtrl->AppendItem(rootID, _("Time"));
144 m_treeCtrl->SetItemTextColour(m_treeTimeID, *wxRED);
145
146 bool firstElement[static_cast<unsigned int>(ElementPlotData::CurveType::NUM_ELEMENTS)];
147 for (int i = 0; i < static_cast<unsigned int>(ElementPlotData::CurveType::NUM_ELEMENTS); ++i) firstElement[i] = true;
148
149 wxString rootElementName[static_cast<unsigned int>(ElementPlotData::CurveType::NUM_ELEMENTS)];
150 rootElementName[static_cast<unsigned int>(ElementPlotData::CurveType::CT_BUS)] = _("Bus");
151 rootElementName[static_cast<unsigned int>(ElementPlotData::CurveType::CT_IND_MOTOR)] = _("Induction motor");
152 rootElementName[static_cast<unsigned int>(ElementPlotData::CurveType::CT_LINE)] = _("Line");
153 rootElementName[static_cast<unsigned int>(ElementPlotData::CurveType::CT_LOAD)] = _("Load");
154 rootElementName[static_cast<unsigned int>(ElementPlotData::CurveType::CT_SHUNT_CAPACITOR)] = _("Capacitor");
155 rootElementName[static_cast<unsigned int>(ElementPlotData::CurveType::CT_SHUNT_INDUCTOR)] = _("Inductor");
156 rootElementName[static_cast<unsigned int>(ElementPlotData::CurveType::CT_SYNC_COMPENSATOR)] = _("Synchronous compensator");
157 rootElementName[static_cast<unsigned int>(ElementPlotData::CurveType::CT_SYNC_GENERATOR)] = _("Synchronous generator");
158 rootElementName[static_cast<unsigned int>(ElementPlotData::CurveType::CT_TRANSFORMER)] = _("Transformer");
159 rootElementName[static_cast<unsigned int>(ElementPlotData::CurveType::CT_TEST)] = _("Test");
160
161 wxTreeItemId rootItemID[static_cast<unsigned int>(ElementPlotData::CurveType::NUM_ELEMENTS)];
162
163 for (auto it = m_epdList.begin(), itEnd = m_epdList.end(); it != itEnd; ++it) {
164 ElementPlotData data = *it;
165 unsigned int curveType = static_cast<unsigned int>(data.GetCurveType());
166
167 if (firstElement[curveType]) {
168 rootItemID[curveType] = m_treeCtrl->AppendItem(rootID, rootElementName[curveType]);
169 firstElement[curveType] = false;
170 }
171 wxTreeItemId itemID = m_treeCtrl->AppendItem(rootItemID[curveType], data.GetName());
172 for (int i = 0; i < data.GetElementDataNumber(); ++i) {
173 m_treeCtrl->AppendItem(itemID, data.GetDataName(i), -1, -1, data.GetPlotData(i));
174 }
175 }
176}
177
178void ChartView::OnPropertyGridChange(wxPropertyGridEvent& event)
179{
180 bool fit = false;
181 wxString pName = event.GetPropertyName();
182 if (pName.empty()) return;
183
184 if (m_treeCtrl->GetSelection()) {
185 if (PlotData* data = dynamic_cast<PlotData*>(m_treeCtrl->GetItemData(m_treeCtrl->GetSelection()))) {
186 if (pName == _("Draw")) {
187 bool isPlotting = m_pgPropDraw->GetValue();
188 data->SetPlot(isPlotting);
189 if (isPlotting) {
190 wxColour colour = GetNextColour();
191 data->SetColour(colour);
192 m_pgPropColor->SetValue(static_cast<wxVariant>(static_cast<wxAny>(colour)));
193 m_treeCtrl->SetItemBold(m_treeCtrl->GetSelection(), true);
194 }
195 else {
196 m_treeCtrl->SetItemBold(m_treeCtrl->GetSelection(), false);
197 }
198 fit = true;
199 }
200 else if (pName == _("Color")) {
201 wxColour colour;
202 colour << m_pgPropColor->GetValue();
203 data->SetColour(colour);
204 }
205 else if (pName == _("Thickness")) {
206 data->SetThick(m_pgProplineThick->GetValue().GetInteger());
207 }
208 else if (pName == _("Type")) {
209 data->SetPenType(static_cast<wxPenStyle>(m_pgProplineType->GetValue().GetInteger()));
210 }
211 else if (pName == _("Axis")) {
212 int axis = m_pgProplineAxis->GetValue().GetInteger();
213 if (axis == 1) { // Y
214 // All lines to Y axis
215 AllToYAxis(m_treeCtrl->GetRootItem());
216 // Select curve to X axis
217 m_treeCtrl->SetItemTextColour(m_treeCtrl->GetSelection(), *wxRED);
218 m_xAxisValues = data->GetValues();
219 m_sugestXLabel = data->GetName() + GetUnitFromMagText(data->GetName());
220 }
221 data->SetAxis(axis);
222 fit = true;
223 }
224 }
225 }
226
227 if (pName == _("Margins")) {
228 if (m_plotLib == PlotLib::wxMATH_PLOT) {
229 m_mpWindow->SetMargins(m_pgPropMarginsUp->GetValue().GetLong(), m_pgPropMarginsRight->GetValue().GetLong(),
230 m_pgPropMarginsBot->GetValue().GetLong(), m_pgPropMarginsLeft->GetValue().GetLong());
231 m_mpWindow->UpdateAll();
232 }
233 else if (m_plotLib == PlotLib::wxCHART_DIR) {
234 m_chartViewerDir->updateViewPort(true, false);
235 event.Skip();
236 }
237 }
238 if (pName == _("Axis limit")) {
239 if (m_plotLib == PlotLib::wxMATH_PLOT) {
240 m_mpWindow->Fit(m_pgPropXMin->GetValue().GetDouble(), m_pgPropXMax->GetValue().GetDouble(),
241 m_pgPropYMin->GetValue().GetDouble(), m_pgPropYMax->GetValue().GetDouble());
242 m_mpWindow->UpdateAll();
243 }
244 else if (m_plotLib == PlotLib::wxCHART_DIR) {
245 m_forceAxisLimits = true;
246 }
247 }
248 UpdatePlot(fit);
249 event.Skip();
250}
251
252void ChartView::OnRightClickDown(wxMouseEvent& event)
253{
254 Fit();
255}
256
257void ChartView::OnMenuDarkThemeClick(wxCommandEvent& event)
258{
259 m_darkTheme = event.IsChecked();
260
261 if (m_plotLib == PlotLib::wxMATH_PLOT) {
262 wxColour grey(96, 96, 96);
263
264 if (m_darkTheme) {
265 m_mpWindow->SetColourTheme(*wxBLACK, *wxWHITE, grey);
266 m_leg->SetBrush(*wxBLACK_BRUSH);
267 m_coords->SetBrush(*wxBLACK_BRUSH);
268 }
269 else {
270 m_mpWindow->SetColourTheme(*wxWHITE, *wxBLACK, grey);
271 m_leg->SetBrush(*wxWHITE_BRUSH);
272 m_coords->SetBrush(*wxWHITE_BRUSH);
273 }
274
275 m_mpWindow->UpdateAll();
276 }
277 else if (m_plotLib == PlotLib::wxCHART_DIR) {
278 DrawChartDir();
279 }
280}
281
282void ChartView::OnMenuSaveImageClick(wxCommandEvent& event)
283{
284 if (m_plotLib == PlotLib::wxMATH_PLOT) {
285 int x = m_mpWindow->GetScreenPosition().x;
286 int y = m_mpWindow->GetScreenPosition().y;
287 int width = m_mpWindow->GetSize().GetWidth();
288 int height = m_mpWindow->GetSize().GetHeight();
289
290 wxScreenDC dcScreen;
291 wxBitmap screenshot(width, height);
292
293 wxMemoryDC memDC;
294 memDC.SelectObject(screenshot);
295
296 memDC.Blit(0, 0, width, height, &dcScreen, x, y);
297 memDC.SelectObject(wxNullBitmap);
298
299 wxFileDialog saveFileDialog(
300 this, _("Save image"), "", "",
301 "PNG image file (*.png)|*.png|Bitmap image file (*.bmp)|*.bmp|JPEG image file (*.jpg)|*.jpg",
302 wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
303 if (saveFileDialog.ShowModal() == wxID_CANCEL) return;
304
305 wxFileName imagePath(saveFileDialog.GetPath());
306 wxBitmapType imageType = wxBITMAP_TYPE_BMP;
307
308 if (imagePath.GetExt() == "png")
309 imageType = wxBITMAP_TYPE_PNG;
310 else if (imagePath.GetExt() == "jpg")
311 imageType = wxBITMAP_TYPE_JPEG;
312
313 screenshot.SaveFile(imagePath.GetFullPath(), imageType);
314 }
315 else if (m_plotLib == PlotLib::wxCHART_DIR) {
316 wxFileDialog saveFileDialog(
317 this, _("Save image"), "", "",
318 "PNG (*.png)|*.png|JPG (*.jpg)|*.jpg|GIF (*.gif)|*.gif|BMP (*.bmp)|*.bmp|SVG (*.svg)|*.svg|PDF (*.pdf)|*.pdf",
319 wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
320 if (saveFileDialog.ShowModal() == wxID_CANCEL) return;
321
322 wxFileName imagePath(saveFileDialog.GetPath());
323 m_chartViewerDir->getChart()->makeChart(imagePath.GetFullPath().ToUTF8());
324 }
325}
326
327void ChartView::OnMenuSendClipClick(wxCommandEvent& event)
328{
329 wxBitmap screenshot;
330 if (m_plotLib == PlotLib::wxMATH_PLOT) {
331 int x = m_mpWindow->GetScreenPosition().x;
332 int y = m_mpWindow->GetScreenPosition().y;
333 int width = m_mpWindow->GetSize().GetWidth();
334 int height = m_mpWindow->GetSize().GetHeight();
335
336 wxScreenDC dcScreen;
337 screenshot = wxBitmap(width, height);
338
339 wxMemoryDC memDC;
340 memDC.SelectObject(screenshot);
341
342 memDC.Blit(0, 0, width, height, &dcScreen, x, y);
343 memDC.SelectObject(wxNullBitmap);
344 }
345 else if (m_plotLib == PlotLib::wxCHART_DIR) {
346 MemBlock memBl = m_chartViewerDir->getChart()->makeChart(Chart::BMP);
347 wxMemoryInputStream in(memBl.data, memBl.len);
348 screenshot = wxBitmap(wxImage(in, wxBITMAP_TYPE_BMP));
349 }
350
351 if (screenshot.IsOk()) {
352 if (wxTheClipboard->Open()) {
353 wxTheClipboard->SetData(new wxBitmapDataObject(screenshot));
354 wxTheClipboard->Close();
355
356 wxMessageDialog msgDialog(this, _("Chart send to clipboard"), _("Info"), wxOK | wxICON_INFORMATION,
357 wxDefaultPosition);
358 msgDialog.ShowModal();
359 }
360 else {
361 wxMessageDialog msgDialog(this, _("It was not possible to send to clipboard"), _("Error"), wxOK | wxICON_ERROR,
362 wxDefaultPosition);
363 msgDialog.ShowModal();
364 }
365 }
366 else {
367 wxMessageDialog msgDialog(this, _("It was not possible to create the screenshot"), _("Error"), wxOK | wxICON_ERROR,
368 wxDefaultPosition);
369 msgDialog.ShowModal();
370 }
371}
372
373void ChartView::OnMenuShowCoordinatesClick(wxCommandEvent& event)
374{
375 m_showCoords = event.IsChecked();
376 if (m_plotLib == PlotLib::wxMATH_PLOT) {
377 m_coords->SetVisible(m_showCoords);
378 m_mpWindow->UpdateAll();
379 }
380 else if (m_plotLib == PlotLib::wxCHART_DIR) {
381 if (m_showCoords) {
382 XYChart* chart = static_cast<XYChart*>(m_chartViewerDir->getChart());
383 m_trackLinePos = chart->getPlotArea()->getLeftX() + (int)(chart->getPlotArea()->getWidth() * 0.5);
384 }
385 DrawChartDir();
386 }
387}
388
389void ChartView::OnMenuShowGridClick(wxCommandEvent& event)
390{
391 m_hideGrid = event.IsChecked() ? false : true;
392 if (m_plotLib == PlotLib::wxMATH_PLOT) {
393 m_xaxis->SetTicks(m_hideGrid);
394 m_yaxis->SetTicks(m_hideGrid);
395 m_mpWindow->UpdateAll();
396 }
397 else if (m_plotLib == PlotLib::wxCHART_DIR) {
398 DrawChartDir();
399 }
400}
401
402void ChartView::OnMenuShowLabelClick(wxCommandEvent& event)
403{
404 m_showLeg = event.IsChecked();
405
406 if (m_plotLib == PlotLib::wxMATH_PLOT) {
407 m_leg->SetVisible(m_showLeg);
408 m_mpWindow->UpdateAll();
409 }
410 else if (m_plotLib == PlotLib::wxCHART_DIR) {
411 if (!m_showLeg) m_legendHeight = 0;
412 DrawChartDir();
413 }
414}
415
416void ChartView::Fit()
417{
418 if (m_plotLib == PlotLib::wxMATH_PLOT) {
419 m_mpWindow->Fit();
420 double bBox[4];
421 m_mpWindow->GetBoundingBox(bBox);
422
423 m_pgPropXMin->SetValue(bBox[0]);
424 m_pgPropXMax->SetValue(bBox[1]);
425 m_pgPropYMin->SetValue(bBox[2]);
426 m_pgPropYMax->SetValue(bBox[3]);
427 }
428 else if (m_plotLib == PlotLib::wxCHART_DIR) {
429 m_forceAxisLimits = false;
430 // Reset viewport
431 m_chartViewerDir->setFullRange("x", 0, 0);
432 m_chartViewerDir->setFullRange("y", 0, 0);
433 m_chartViewerDir->setViewPortLeft(0);
434 m_chartViewerDir->setViewPortTop(0);
435 m_chartViewerDir->setViewPortWidth(1);
436 m_chartViewerDir->setViewPortHeight(1);
437
438 // redraw the chart
439 m_chartViewerDir->updateViewPort(true, false);
440 }
441}
442
443void ChartView::UpdatePlot(bool fit)
444{
445 if (m_plotLib == PlotLib::wxMATH_PLOT) {
446 wxRect legRect = m_leg->GetRectangle();
447 wxRect coordsRect = m_coords->GetRectangle();
448 m_mpWindow->DelAllLayers(true, false);
449
450 // GoAllTrees(treeCtrl_ChartSelection->GetRootItem());
451 UpdateAllPlots(m_treeCtrl->GetRootItem());
452
453 m_xaxis = new mpScaleX(m_pgPropXLabel->GetValueAsString(), mpALIGN_BOTTOM, true);
454 m_yaxis = new mpScaleY(m_pgPropYLabel->GetValueAsString(), mpALIGN_LEFT, true);
455 m_leg = new mpInfoLegend(legRect, wxWHITE_BRUSH);
456 m_coords = new mpInfoCoords(coordsRect, wxWHITE_BRUSH);
457
458 m_xaxis->SetDrawOutsideMargins(false);
459 m_yaxis->SetDrawOutsideMargins(false);
460 m_xaxis->SetTicks(m_hideGrid);
461 m_yaxis->SetTicks(m_hideGrid);
462
463 mpText* chartTitle = new mpText(m_pgPropChartTitle->GetValueAsString(), 50, 0);
464 wxFont chartTitleFont(12, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD);
465 chartTitle->SetFont(chartTitleFont);
466
467 m_mpWindow->AddLayer(m_xaxis);
468 m_mpWindow->AddLayer(m_yaxis);
469 m_mpWindow->AddLayer(m_leg);
470 m_mpWindow->AddLayer(m_coords);
471 m_mpWindow->AddLayer(chartTitle);
472
473 m_leg->SetVisible(m_showLeg);
474 m_coords->SetVisible(m_showCoords);
475
476 if (fit) Fit();
477
478 wxColour grey(96, 96, 96);
479 if (m_darkTheme) {
480 m_mpWindow->SetColourTheme(*wxBLACK, *wxWHITE, grey);
481 m_leg->SetBrush(*wxBLACK_BRUSH);
482 m_coords->SetBrush(*wxBLACK_BRUSH);
483 }
484 else {
485 m_mpWindow->SetColourTheme(*wxWHITE, *wxBLACK, grey);
486 m_leg->SetBrush(*wxWHITE_BRUSH);
487 m_coords->SetBrush(*wxWHITE_BRUSH);
488 }
489 }
490 else if (m_plotLib == PlotLib::wxCHART_DIR) {
491 DrawChartDir();
492 if (fit) Fit();
493 }
494}
495
496void ChartView::OnTreeItemActivated(wxTreeEvent& event)
497{
498 if (PlotData* data = dynamic_cast<PlotData*>(m_treeCtrl->GetItemData(event.GetItem()))) {
499 bool isPlotting = data->IsPlot() ? false : true;
500 data->SetPlot(isPlotting);
501 m_pgPropDraw->SetValue(data->IsPlot());
502 if (isPlotting) {
503 wxColour colour = GetNextColour();
504 data->SetColour(colour);
505 m_pgPropColor->SetValue(static_cast<wxVariant>(static_cast<wxAny>(colour)));
506 m_treeCtrl->SetItemBold(m_treeCtrl->GetSelection(), true);
507 }
508 else {
509 m_treeCtrl->SetItemBold(m_treeCtrl->GetSelection(), false);
510 }
511 UpdatePlot(true);
512 }
513
514 if (event.GetItem() == m_treeTimeID) {
515 AllToYAxis(m_treeCtrl->GetRootItem());
516 m_treeCtrl->SetItemTextColour(m_treeTimeID, *wxRED);
517 m_xAxisValues = m_time;
518 m_sugestXLabel = _("Time (s)");
519 UpdatePlot(true);
520 }
521
522 event.Skip();
523}
524
525void ChartView::OnTreeItemSelectionChanged(wxTreeEvent& event)
526{
527 if (PlotData* data = dynamic_cast<PlotData*>(m_treeCtrl->GetItemData(m_selectedItemID)))
528 data->SetHighlight(false);
529
530 m_selectedItemID = event.GetItem();
531
532 if (PlotData* data = dynamic_cast<PlotData*>(m_treeCtrl->GetItemData(m_selectedItemID))) {
533 m_pgPropDraw->SetValue(data->IsPlot());
534 wxVariant colour;
535 colour << data->GetColour();
536 m_pgPropColor->SetValue(colour);
537 m_pgProplineThick->SetValue(data->GetThick());
538 m_pgProplineType->SetValue(data->GetPenType());
539 m_pgProplineAxis->SetValue(data->GetAxis());
540 data->SetHighlight(true);
541 }
542 if (m_plotLib == PlotLib::wxCHART_DIR) {
543 m_chartViewerDir->updateViewPort(true, false);
544 }
545 event.Skip();
546}
547
548void ChartView::BuildColourList()
549{
550 m_colourList.push_back(wxColour(255, 30, 0));
551 m_colourList.push_back(wxColour(0, 30, 255));
552 m_colourList.push_back(wxColour(0, 128, 0));
553 m_colourList.push_back(wxColour(100, 100, 100));
554 m_colourList.push_back(wxColour(255, 128, 0));
555 m_colourList.push_back(wxColour(128, 0, 255));
556 m_colourList.push_back(wxColour(0, 255, 128));
557 m_colourList.push_back(wxColour(255, 255, 0));
558 m_colourList.push_back(wxColour(255, 0, 255));
559 m_colourList.push_back(wxColour(0, 255, 255));
560 m_colourList.push_back(wxColour(128, 255, 0));
561 m_colourList.push_back(wxColour(255, 0, 128));
562 m_colourList.push_back(wxColour(0, 128, 255));
563 m_colourList.push_back(wxColour(128, 128, 128));
564 m_colourList.push_back(*wxBLACK);
565 m_itColourList = --m_colourList.end();
566}
567
568wxColour ChartView::GetNextColour()
569{
570 if (*m_itColourList == *wxBLACK)
571 m_itColourList = m_colourList.begin();
572 else
573 ++m_itColourList;
574
575 return *m_itColourList;
576}
577
578wxTreeItemId ChartView::AllToYAxis(wxTreeItemId root)
579{
580 wxTreeItemIdValue cookie;
581 wxTreeItemId item = m_treeCtrl->GetFirstChild(root, cookie);
582 wxTreeItemId child;
583
584 while (item.IsOk()) {
585 m_treeCtrl->SetItemTextColour(item, *wxBLACK);
586 if (PlotData* data = dynamic_cast<PlotData*>(m_treeCtrl->GetItemData(item))) data->SetAxis(0); // X axis.
587
588 if (m_treeCtrl->ItemHasChildren(item)) {
589 wxTreeItemId nextChild = AllToYAxis(item);
590 if (nextChild.IsOk()) return nextChild;
591 }
592 item = m_treeCtrl->GetNextChild(root, cookie);
593 }
594
595 wxTreeItemId dummyID;
596 return dummyID;
597}
598
599wxTreeItemId ChartView::UpdateAllPlots(wxTreeItemId root)
600{
601 wxTreeItemIdValue cookie;
602 wxTreeItemId item = m_treeCtrl->GetFirstChild(root, cookie);
603 wxTreeItemId child;
604
605 while (item.IsOk()) {
606 if (PlotData* data = dynamic_cast<PlotData*>(m_treeCtrl->GetItemData(item))) {
607 if (data->IsPlot()) {
608 wxString parentName = m_treeCtrl->GetItemText(m_treeCtrl->GetItemParent(item));
609 mpFXYVector* newLayer = new mpFXYVector(data->GetName() + " (" + parentName + ")");
610 newLayer->SetData(m_xAxisValues, data->GetValues());
611 newLayer->SetContinuity(true);
612 wxPen layerPen(data->GetColour(), data->GetThick(), data->GetPenType());
613 newLayer->SetPen(layerPen);
614 newLayer->SetDrawOutsideMargins(false);
615 newLayer->ShowName(false);
616
617 m_mpWindow->AddLayer(newLayer);
618 }
619 }
620
621 if (m_treeCtrl->ItemHasChildren(item)) {
622 wxTreeItemId nextChild = UpdateAllPlots(item);
623 if (nextChild.IsOk()) return nextChild;
624 }
625 item = m_treeCtrl->GetNextChild(root, cookie);
626 }
627
628 wxTreeItemId dummyID;
629 return dummyID;
630}
631
632wxTreeItemId ChartView::UpdateAllPlotsCharDir(wxTreeItemId root, XYChart* chartDir)
633{
634 wxTreeItemIdValue cookie;
635 wxTreeItemId item = m_treeCtrl->GetFirstChild(root, cookie);
636 wxTreeItemId child;
637
638 while (item.IsOk()) {
639 if (PlotData* data = dynamic_cast<PlotData*>(m_treeCtrl->GetItemData(item))) {
640 if (data->IsPlot()) {
641 wxString parentName = m_treeCtrl->GetItemText(m_treeCtrl->GetItemParent(item));
642
643 std::vector<double> yValues = data->GetValues();
644
645
646
647 LineLayer* layer = chartDir->addLineLayer();
648 layer->setFastLineMode();
649 layer->setLineWidth(data->GetThick());
650 layer->setXData(DoubleArray(&m_xAxisValues[0], m_xAxisValues.size()));
651
652 if (m_firstPlot) m_rawDataColour.clear();
653 int dataColour = (data->GetColour().Red() << 16) + (data->GetColour().Green() << 8) + data->GetColour().Blue();
654 int rawColour = dataColour;
655 //layer->addDataSet(DoubleArray(&data->GetValues()[0] + startIndex, endIndex - startIndex + 1), dataColour, data->GetName() + " (" + parentName + ")");
656 if (data->GetPenType() == wxPENSTYLE_DOT)
657 dataColour = chartDir->dashLineColor(dataColour, Chart::DotLine);
658 else if (data->GetPenType() == wxPENSTYLE_SHORT_DASH)
659 dataColour = chartDir->dashLineColor(dataColour, Chart::DashLine);
660 else if (data->GetPenType() == wxPENSTYLE_DOT_DASH)
661 dataColour = chartDir->dashLineColor(dataColour, Chart::DotDashLine);
662 m_rawDataColour[dataColour] = rawColour;
663
664 layer->addDataSet(DoubleArray(&yValues[0], yValues.size()), dataColour, data->GetName() + " (" + parentName + ")");
665
666 if (data->IsHighlighted()) {
667 int hlColor = 0x80FFFF00;
668 LineLayer* hlLayer = chartDir->addLineLayer();
669 hlLayer->setFastLineMode();
670 hlLayer->setLineWidth(data->GetThick() * 3);
671 hlLayer->setXData(DoubleArray(&m_xAxisValues[0], m_xAxisValues.size()));
672 hlLayer->addDataSet(DoubleArray(&yValues[0], yValues.size()), hlColor);
673 }
674
675 if (m_firstPlot) {
676 m_firstPlot = false;
677 m_sugestYLabel = data->GetName();
678 }
679 else {
680 if (m_sugestYLabel.IsEmpty() || (m_sugestYLabel != data->GetName())) m_sugestYLabel = "";
681 }
682 }
683 }
684
685 if (m_treeCtrl->ItemHasChildren(item)) {
686 wxTreeItemId nextChild = UpdateAllPlotsCharDir(item, chartDir);
687 if (nextChild.IsOk()) return nextChild;
688 }
689 item = m_treeCtrl->GetNextChild(root, cookie);
690 }
691
692
693 wxTreeItemId dummyID;
694 return dummyID;
695}
696
697void ChartView::OnMenuExpCSVClick(wxCommandEvent& event)
698{
699 wxFileDialog saveFileDialog(this, _("Save CSV file"), "", "", "CSV file (*.csv)|*.csv",
700 wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
701 if (saveFileDialog.ShowModal() == wxID_CANCEL) return;
702
703 wxTextFile csvFile(saveFileDialog.GetPath());
704 if (!csvFile.Create()) {
705 if (!csvFile.Open()) {
706 wxMessageDialog msgDialog(this, _("It was not possible to open or create the selected file."), _("Error"),
707 wxOK | wxCENTRE | wxICON_ERROR);
708 msgDialog.ShowModal();
709 }
710 }
711 else
712 csvFile.Open();
713 if (csvFile.IsOpened()) {
714 csvFile.Clear();
715 csvFile.AddLine(GetActiveCurvesCSV());
716 csvFile.Write();
717 csvFile.Close();
718 }
719}
720
721wxString ChartView::GetActiveCurvesCSV()
722{
723 std::vector<PlotData*> activePlotDataList;
724 GetActivePlotData(m_treeCtrl->GetRootItem(), activePlotDataList);
725
726 std::vector<double> xValues;
727 wxString xName = "";
728
729 // Find X axis curve, if none is found, X is the m_time.
730 bool foundXAxis = false;
731 for (auto it = activePlotDataList.begin(), itEnd = activePlotDataList.end(); it != itEnd; ++it) {
732 PlotData* data = *it;
733 if (data->GetAxis() == 1) {
734 xValues = data->GetValues();
735 xName = data->GetName();
736 foundXAxis = true;
737 activePlotDataList.erase(it);
738 delete data;
739 break;
740 }
741 }
742 if (!foundXAxis) {
743 xValues = m_time;
744 xName = _("Time");
745 }
746
747 // Build CSV text.
748 wxString csvText = xName + ";";
749 // Header
750 for (auto it = activePlotDataList.begin(), itEnd = activePlotDataList.end(); it != itEnd; ++it) {
751 PlotData* data = *it;
752 csvText += data->GetName() + ";";
753 }
754 csvText[csvText.length() - 1] = '\n';
755 // Values
756 for (unsigned int i = 0; i < xValues.size(); ++i) {
757 csvText += wxString::FromCDouble(xValues[i], 13) + ";";
758 for (unsigned int j = 0; j < activePlotDataList.size(); ++j) {
759 double value = 0.0;
760 if (i < activePlotDataList[j]->GetValues().size()) {
761 value = activePlotDataList[j]->GetValues()[i];
762 }
763 csvText += wxString::FromCDouble(value, 13) + ";";
764 }
765 csvText[csvText.length() - 1] = '\n';
766 }
767
768 // Clear active plot data vector.
769 for (auto it = activePlotDataList.begin(); it != activePlotDataList.end(); ++it) {
770 delete(*it);
771 }
772 activePlotDataList.clear();
773
774 return csvText;
775}
776
777wxTreeItemId ChartView::GetActivePlotData(wxTreeItemId root, std::vector<PlotData*>& plotDataList)
778{
779 wxTreeItemIdValue cookie;
780 wxTreeItemId item = m_treeCtrl->GetFirstChild(root, cookie);
781 wxTreeItemId child;
782
783 while (item.IsOk()) {
784 if (PlotData* data = dynamic_cast<PlotData*>(m_treeCtrl->GetItemData(item))) {
785 if (data->IsPlot() || data->GetAxis() == 1) {
786 wxString parentName = m_treeCtrl->GetItemText(m_treeCtrl->GetItemParent(item));
787
788 PlotData* dataCopy = new PlotData();
789 *dataCopy = *data;
790 dataCopy->SetName(data->GetName() + " (" + parentName + ")");
791 plotDataList.push_back(dataCopy);
792 }
793 }
794
795 if (m_treeCtrl->ItemHasChildren(item)) {
796 wxTreeItemId nextChild = GetActivePlotData(item, plotDataList);
797 if (nextChild.IsOk()) return nextChild;
798 }
799 item = m_treeCtrl->GetNextChild(root, cookie);
800 }
801
802 wxTreeItemId dummyID;
803 return dummyID;
804}
805void ChartView::DrawChartDir()
806{
807 int gridColour = 0xEAEAEA;
808 int bgColour = 0xFFFFFF;
809 int labelColour = 0x000000;
810 if (m_darkTheme) {
811 bgColour = 0x303030;
812 gridColour = 0x3D3D3D;
813 labelColour = 0xA0A0A0;
814 }
815 if (m_hideGrid) gridColour = Chart::Transparent;
816
817 XYChart* chartDir = new XYChart(std::max(400, m_chartViewerSize.GetWidth()), std::max(300, m_chartViewerSize.GetHeight()), bgColour);
818
819 wxString title = m_pgPropChartTitle->GetValueAsString();
820 int titleSize = 0;
821 if (!title.IsEmpty()) {
822 chartDir->addTitle(title, "arial.ttf", 12, labelColour);
823 titleSize = 12;
824 }
825
826 LegendBox* box = nullptr;
827 if (m_showLeg) {
828 box = chartDir->addLegend(0, 0, false, "arial.ttf", 10);
829 box->setBackground(Chart::Transparent, Chart::Transparent);
830 box->setPos(m_pgPropMarginsLeft->GetValue().GetLong(), m_pgPropMarginsUp->GetValue().GetLong() + titleSize);
831 box->setFontColor(labelColour);
832 box->setLineStyleKey();
833 }
834 m_firstPlot = true;
835 CalcXYLimits(m_treeCtrl->GetRootItem(), chartDir);
836 m_firstPlot = true;
837 UpdateAllPlotsCharDir(m_treeCtrl->GetRootItem(), chartDir);
838
839
840 wxString xLabel = m_pgPropXLabel->GetValueAsString();
841 if (xLabel == _("auto")) xLabel = m_sugestXLabel;
842 wxString yLabel = m_pgPropYLabel->GetValueAsString();
843 if (yLabel == _("auto")) yLabel = m_sugestYLabel + GetUnitFromMagText(m_sugestYLabel);
844 int xLabelSize = 10, yLabelSize = 10;
845 // If the label is empty, the size is 0.
846 if (xLabel.IsEmpty()) xLabelSize = 0;
847 if (yLabel.IsEmpty()) yLabelSize = 0;
848
849 chartDir->setPlotArea(
850 yLabelSize + m_pgPropMarginsLeft->GetValue().GetLong(),
851 titleSize + m_legendHeight + m_pgPropMarginsUp->GetValue().GetLong(),
852 chartDir->getWidth() - m_pgPropMarginsRight->GetValue().GetLong() - m_pgPropMarginsLeft->GetValue().GetLong() - yLabelSize,
853 chartDir->getHeight() - m_pgPropMarginsBot->GetValue().GetLong() - m_pgPropMarginsUp->GetValue().GetLong() - m_legendHeight - titleSize - xLabelSize,
854 bgColour, -1, -1, gridColour, gridColour);
855 chartDir->setClipping();
856
857 //DoubleArray timeArray(&m_time[0], m_time.size());
858 double xMin = 0, xMax = 0, yMin = 0, yMax = 0;
859 if (m_forceAxisLimits) {
860 xMin = m_pgPropXMin->GetValue().GetDouble();
861 xMax = m_pgPropXMax->GetValue().GetDouble();
862 yMin = m_pgPropYMin->GetValue().GetDouble();
863 yMax = m_pgPropYMax->GetValue().GetDouble();
864 }
865 else {
866 //xMin = m_xAxisValues[0];
867 xMin = m_xMin;
868 //xMax = m_time[m_time.size() - 1];
869 //xMax = m_xAxisValues[m_xAxisValues.size() - 1];
870 xMax = m_xMax;
871 yMin = m_yMin - 0.05 * (m_yMax - m_yMin);
872 yMax = m_yMax + 0.05 * (m_yMax - m_yMin);
873 m_pgPropXMin->SetValue(xMin);
874 m_pgPropXMax->SetValue(xMax);
875 m_pgPropYMin->SetValue(yMin);
876 m_pgPropYMax->SetValue(yMax);
877 }
878 m_chartViewerDir->setFullRange("x", xMin, xMax);
879 m_chartViewerDir->setFullRange("y", yMin, yMax);
880
881 // Get the start date and end date that are visible on the chart.
882 double viewPortStartTime = m_chartViewerDir->getValueAtViewPort("x", m_chartViewerDir->getViewPortLeft());
883 double viewPortEndTime = m_chartViewerDir->getValueAtViewPort("x", m_chartViewerDir->getViewPortLeft() + m_chartViewerDir->getViewPortWidth());
884
885 chartDir->xAxis()->setTickDensity(20);
886 chartDir->xAxis()->setLinearScale(viewPortStartTime, viewPortEndTime);
887 chartDir->xAxis()->setLabelFormat(wxString::Format("{value|2~%c}", DotOrComma()));
888 chartDir->xAxis()->setColors(labelColour, labelColour);
889 chartDir->xAxis()->setTitle(xLabel, "arial.ttf", 10, labelColour);
890
891 chartDir->yAxis()->setLabelFormat(wxString::Format("{value|2~%c}", DotOrComma()));
892 chartDir->yAxis()->setColors(labelColour, labelColour);
893 chartDir->yAxis()->setTitle(yLabel, "arial.ttf", 10, labelColour);
894 m_chartViewerDir->syncLinearAxisWithViewPort("y", chartDir->yAxis());
895
896 if (m_showCoords) {
897 DrawTrackLine(chartDir);
898 }
899
900 if (m_chartViewerDir->getChart() != nullptr)
901 {
902 delete m_chartViewerDir->getChart();
903 }
904 // Set the chart image to the WinChartViewer
905 m_chartViewerDir->setChart(chartDir);
906
907 if (m_showLeg && box != nullptr) {
908 if (std::abs(m_legendHeight - box->getHeight()) > 1) {
909 m_legendHeight = box->getHeight();
910 DrawChartDir();
911 }
912 }
913}
914
915void ChartView::OnViewPortChanged(wxCommandEvent& event)
916{
917 if (m_chartViewerDir->needUpdateChart()) DrawChartDir();
918 event.Skip();
919}
920
921void ChartView::OnMouseMovePlotArea(wxCommandEvent& event)
922{
923 if (m_showCoords) {
924 const int grabDist = 8;
925
926 int mouseX = m_chartViewerDir->getChartMouseX();
927 PlotArea* plotArea = static_cast<XYChart*>(m_chartViewerDir->getChart())->getPlotArea();
928 //m_trackLinePos = (std::min)(plotArea->getRightX(), (std::max)(plotArea->getLeftX(), mouseX - grabDist));
929
930 bool moveTrackLine = false;
931
932 if (m_chartViewerDir->getMouseUsage() == Chart::MouseUsageDefault && wxGetMouseState().LeftIsDown()) {
933 // Lock in move track line
934 SetCursor(wxCURSOR_SIZEWE);
935 moveTrackLine = true;
936 }
937
938 if (std::abs(mouseX - m_trackLinePos) <= grabDist && !m_chartViewerDir->IsSelectionRectVisible()) {
939 SetCursor(wxCURSOR_SIZEWE);
940 m_chartViewerDir->setMouseUsage(Chart::MouseUsageDefault);
941 }
942 else if (!wxGetMouseState().LeftIsDown()) {
943 SetCursor(wxCURSOR_ARROW);
944 m_chartViewerDir->setMouseUsage(Chart::MouseUsageZoomIn);
945 }
946
947 if (moveTrackLine) {
948 m_trackLinePos = mouseX;
949 DrawTrackLine(static_cast<XYChart*>(m_chartViewerDir->getChart()));
950 m_chartViewerDir->updateDisplay();
951 }
952
953 }
954 event.Skip();
955}
956
957void ChartView::DrawTrackLine(XYChart* chartDir)
958{
959 chartDir->initDynamicLayer();
960
961 double xValue = chartDir->getNearestXValue(m_trackLinePos);
962 int xCoor = chartDir->getXCoor(xValue);
963 chartDir->getDrawArea()->line(xCoor, chartDir->getPlotArea()->getTopY(), xCoor, chartDir->getPlotArea()->getBottomY(), 0x888888, 3);
964
965 std::ostringstream xlabel;
966
967 //xlabel << "<*font,bgColor=000000*> " << chartDir->xAxis()->getFormattedLabel(xValue) << " s <*/font*>";
968 xlabel << "<*font,bgColor=000000*> " << chartDir->formatValue(xValue, wxString::Format("{value|P4~%c}", DotOrComma())) << " <*/font*>";
969 TTFText* text = chartDir->getDrawArea()->text(xlabel.str().c_str(), "arialbd.ttf", 10);
970 int xLabelPos = std::max(0, std::min(xCoor - text->getWidth() / 2, chartDir->getWidth() - text->getWidth()));
971 text->draw(xLabelPos, chartDir->getPlotArea()->getBottomY() + 3, 0xffffff);
972 text->destroy();
973
974 for (int i = 0; i < chartDir->getLayerCount(); ++i)
975 {
976 Layer* layer = chartDir->getLayerByZ(i);
977
978 // The data array index of the x-value
979 int xIndex = layer->getXIndexOf(xValue);
980
981 // Iterate through all the data sets in the layer
982 for (int j = 0; j < layer->getDataSetCount(); ++j)
983 {
984 DataSet* dataSet = layer->getDataSetByZ(j);
985 const char* dataSetName = dataSet->getDataName();
986
987 // Get the color, name and position of the data label
988 int color = dataSet->getDataColor();
989 int yCoor = chartDir->getYCoor(dataSet->getPosition(xIndex), dataSet->getUseYAxis());
990
991 // Draw a track dot with a label next to it for visible data points in the plot area
992 if ((yCoor >= chartDir->getPlotArea()->getTopY()) && (yCoor <= chartDir->getPlotArea()->getBottomY()) &&
993 (color != Chart::Transparent) && dataSetName && *dataSetName)
994 {
995 chartDir->getDrawArea()->circle(xCoor, yCoor, 4, 4, color, color);
996
997 std::ostringstream label;
998
999 //wxMessageBox(wxString::Format("%d", i));
1000 label << "<*font,bgColor=" << std::hex << m_rawDataColour[color] << "*> " << chartDir->formatValue(dataSet->getValue(xIndex), wxString::Format("{value|P4~%c}", DotOrComma())) << " <*font*>";
1001 text = chartDir->getDrawArea()->text(label.str().c_str(), "arialbd.ttf", 10);
1002 //log[dataSetName] = dataSet->getValue(xIndex);
1003
1004 // Draw the label on the right side of the dot if the mouse is on the left side the
1005 // chart, and vice versa. This ensures the label will not go outside the chart image.
1006 if (xCoor <= (chartDir->getPlotArea()->getLeftX() + chartDir->getPlotArea()->getRightX()) / 2)
1007 {
1008 text->draw(xCoor + 6, yCoor, 0xffffff, Chart::Left);
1009 }
1010 else
1011 {
1012 text->draw(xCoor - 6, yCoor, 0xffffff, Chart::Right);
1013 }
1014 text->destroy();
1015 }
1016 }
1017 }
1018}
1019
1020wxString ChartView::GetUnitFromMagText(wxString magText)
1021{
1022 wxString unitText = " (p.u.)";
1023 if (magText.IsEmpty()) unitText = "";
1024 else if (magText == _("Angle")) unitText = " (°)";
1025 else if (magText == _("Delta")) unitText = " (°)";
1026 else if (magText == _("Frequency")) unitText = " (Hz)";
1027 else if (magText == _("Velocity")) unitText = " (rad/s)";
1028 else if (magText == _("Slip")) unitText = " (%)";
1029 return unitText;
1030}
1031
1032wxTreeItemId ChartView::CalcXYLimits(wxTreeItemId root, XYChart* chartDir)
1033{
1034 wxTreeItemIdValue cookie;
1035 wxTreeItemId item = m_treeCtrl->GetFirstChild(root, cookie);
1036 wxTreeItemId child;
1037
1038 while (item.IsOk()) {
1039 if (PlotData* data = dynamic_cast<PlotData*>(m_treeCtrl->GetItemData(item))) {
1040 if (data->IsPlot()) {
1041 wxString parentName = m_treeCtrl->GetItemText(m_treeCtrl->GetItemParent(item));
1042
1043 std::vector<double> yValues = data->GetValues();
1044 if (yValues.size() == 0) {
1045 item = m_treeCtrl->GetNextChild(root, cookie);
1046 continue;
1047 }
1048
1049 double minY = *std::min_element(yValues.begin(), yValues.end());
1050 double maxY = *std::max_element(yValues.begin(), yValues.end());
1051 if (m_firstPlot) {
1052 m_firstPlot = false;
1053 m_yMin = minY;
1054 m_yMax = maxY;
1055
1056 m_xMin = *std::min_element(m_xAxisValues.begin(), m_xAxisValues.end());
1057 m_xMax = *std::max_element(m_xAxisValues.begin(), m_xAxisValues.end());
1058 }
1059 else {
1060 if (minY < m_yMin) m_yMin = minY;
1061 if (maxY > m_yMax) m_yMax = maxY;
1062 }
1063 }
1064 }
1065
1066 if (m_treeCtrl->ItemHasChildren(item)) {
1067 wxTreeItemId nextChild = CalcXYLimits(item, chartDir);
1068 if (nextChild.IsOk()) return nextChild;
1069 }
1070 item = m_treeCtrl->GetNextChild(root, cookie);
1071 }
1072
1073 wxTreeItemId dummyID;
1074 return dummyID;
1075}
1076
1077void ChartView::OnResize(wxSizeEvent& event)
1078{
1079 if (m_plotLib == PlotLib::wxCHART_DIR) {
1080 m_chartViewerSize = event.GetSize() - wxSize(m_treeCtrl->GetSize().GetWidth(), 60);
1081 //m_chartViewerDir->Layout();
1082 m_chartViewerDir->updateViewPort(true, false);
1083 //DrawChartDir();
1084 }
1085 event.Skip();
1086}
This class is responsible to manage the graphical data of electromechanical result to be plotted on c...