Power System Platform  2026w10a-beta
Loading...
Searching...
No Matches
MainFrame.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 "MainFrame.h"
19
31
32#include "forms/AboutForm.h"
33#include "forms/DataReport.h"
35#include "forms/ImportForm.h"
36#include "forms/ProjectPropertiesForm.h"
38#include "forms/StabilityEventList.h"
39#include "forms/LabelManager.h"
40
41#include "utils/FileHanding.h"
43
44#include "editors/ChartView.h"
45#include "editors/Workspace.h"
46#include "extLibs/artProvider/ArtMetro.h"
47 //#include "WorkspaceDC.h"
48
50MainFrame::MainFrame(wxWindow* parent, wxLocale* locale, PropertiesData* initProperties, wxString openPath)
51 : MainFrameBase(parent)
52{
53 m_locale = locale;
54 m_generalProperties = initProperties;
55
56 Init();
57
58 if (openPath != "") {
59 EnableCurrentProjectRibbon();
60 Workspace* newWorkspace = new Workspace(this, _("Open project"), this->GetStatusBar(), this->GetAuiNotebook());
61 //if (!m_sharedGLContext) m_sharedGLContext = newWorkspace->GetSharedGLContext();
62
63 FileHanding fileHandling(newWorkspace);
64 if (fileHandling.OpenProject(openPath)) {
65 newWorkspace->SetSavedPath(openPath);
66
67 m_workspaceList.push_back(newWorkspace);
68
69 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL, true);
70 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL, false);
71
72 m_auiNotebook->AddPage(newWorkspace, newWorkspace->GetName(), true);
73 m_auiNotebook->Layout();
74 newWorkspace->Redraw();
75 newWorkspace->SetJustOpened(true);
76 newWorkspace->Fit();
77 m_projectNumber++;
78 }
79 }
80}
81
83{
84 //if (!m_sharedGLContext && m_workspaceList.size() != 0) {
85 // m_sharedGLContext = m_workspaceList[0]->GetSharedGLContext();
86 //}
87 if (m_addElementsMenu) {
88 m_addElementsMenu->Disconnect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnAddElementsClick),
89 nullptr, this);
90 delete m_addElementsMenu;
91 }
92 if (m_stabilityMenu) {
93 m_stabilityMenu->Disconnect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnStabilityMenuClick),
94 nullptr, this);
95 delete m_stabilityMenu;
96 }
97 if (m_snapshotMenu) {
98 m_snapshotMenu->Disconnect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnSnapshotMenuClick),
99 nullptr, this);
100 delete m_snapshotMenu;
101 }
102
103 if (m_locale) delete m_locale;
104 if (m_generalProperties) delete m_generalProperties;
105}
106
107void MainFrame::Init()
108{
109 this->SetSize(800, 600);
110
111 CreateDropdownMenus();
112
113 EnableCurrentProjectRibbon(false);
114
115 m_artMetro = new wxRibbonMetroArtProvider();
116 m_ribbonBar->SetArtProvider(m_artMetro);
117 m_ribbonBar->Realize();
118
119 this->Layout();
120}
121
122void MainFrame::EnableCurrentProjectRibbon(bool enable)
123{
124 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_ADDELEMENT, enable);
125 m_ribbonButtonBarReports->EnableButton(ID_RIBBON_CHARTS, enable);
126 m_ribbonButtonBarCProject->EnableButton(ID_RIBBON_CLOSE, enable);
127 m_ribbonButtonBarClipboard->EnableButton(ID_RIBBON_COPY, enable);
128 m_ribbonButtonBarReports->EnableButton(ID_RIBBON_DATAREPORT, enable);
129 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_DELETE, enable);
130 m_ribbonButtonBarContinuous->EnableButton(ID_RIBBON_DISABLESOL, enable);
131 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_DRAG, enable);
132 m_ribbonButtonBarContinuous->EnableButton(ID_RIBBON_ENABLESOL, enable);
133 m_ribbonButtonBarSimulations->EnableButton(ID_RIBBON_FAULT, enable);
134 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_FIT, enable);
135 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_MOVE, enable);
136 m_ribbonButtonBarClipboard->EnableButton(ID_RIBBON_PASTE, enable);
137 m_ribbonButtonBarSimulations->EnableButton(ID_RIBBON_POWERFLOW, enable);
138 m_ribbonButtonBarClipboard->EnableButton(ID_RIBBON_REDO, enable);
139 m_ribbonButtonBarContinuous->EnableButton(ID_RIBBON_RESETVOLT, enable);
140 m_ribbonButtonBarSimulations->EnableButton(ID_RIBBON_RUNSTAB, enable);
141 m_ribbonButtonBarCProject->EnableButton(ID_RIBBON_SAVE, enable);
142 m_ribbonButtonBarCProject->EnableButton(ID_RIBBON_SAVEAS, enable);
143 m_ribbonButtonBarSimulations->EnableButton(ID_RIBBON_SCPOWER, enable);
144 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_PROJSETTINGS, enable);
145 m_ribbonButtonBarReports->EnableButton(ID_RIBBON_SNAPSHOT, enable);
146 m_ribbonButtonBarSimulations->EnableButton(ID_RIBBON_SIMULSETTINGS, enable);
147 m_ribbonButtonBarClipboard->EnableButton(ID_RIBBON_UNDO, enable);
148 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_ROTATEC, enable);
149 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_ROTATECC, enable);
150 m_ribbonButtonBarSimulations->EnableButton(ID_RIBBON_HARMDIST, enable);
151 m_ribbonButtonBarSimulations->EnableButton(ID_RIBBON_FREQRESP, enable);
152
153 //if (m_generalProperties->GetGeneralPropertiesData().useOpenGL)
154 // m_ribbonButtonBarReports->EnableButton(ID_RIBBON_HEATMAP, enable);
155 //else
156 // m_ribbonButtonBarReports->EnableButton(ID_RIBBON_HEATMAP, false);
157}
158
159void MainFrame::CreateDropdownMenus()
160{
161 m_addElementsMenu = new wxMenu();
162
163 wxMenuItem* busElement =
164 new wxMenuItem(m_addElementsMenu, ID_ADDMENU_BUS, _("&Bus\tB"), _("Adds a bus at the circuit"));
165 // busElement->SetBitmap(wxArtProvider::GetBitmap(wxART_WARNING));
166 wxMenuItem* lineElement =
167 new wxMenuItem(m_addElementsMenu, ID_ADDMENU_LINE, _("&Line\tL"), _("Adds a power line at the circuit"));
168 wxMenuItem* transformerElement = new wxMenuItem(m_addElementsMenu, ID_ADDMENU_TRANSFORMER, _("&Transformer\tT"),
169 _("Adds a transformer at the circuit"));
170 wxMenuItem* generatorElement = new wxMenuItem(m_addElementsMenu, ID_ADDMENU_GENERATOR, _("&Generator\tG"),
171 _("Adds a generator at the circuit"));
172 wxMenuItem* indMotorElement = new wxMenuItem(m_addElementsMenu, ID_ADDMENU_INDMOTOR, _("&Induction motor\tI"),
173 _("Adds an induction motor at the circuit"));
174 wxMenuItem* syncCompElement =
175 new wxMenuItem(m_addElementsMenu, ID_ADDMENU_SYNCCOMP, _("&Synchronous compensator \tK"),
176 _("Adds an induction motor at the circuit"));
177 wxMenuItem* loadElement =
178 new wxMenuItem(m_addElementsMenu, ID_ADDMENU_LOAD, _("&Load\tShift-L"), _("Adds a load at the circuit"));
179 wxMenuItem* capacitorElement = new wxMenuItem(m_addElementsMenu, ID_ADDMENU_CAPACITOR, _("&Capacitor\tShift-C"),
180 _("Adds a shunt capacitor at the circuit"));
181 wxMenuItem* inductorElement = new wxMenuItem(m_addElementsMenu, ID_ADDMENU_INDUCTOR, _("&Inductor\tShift-I"),
182 _("Adds a shunt inductor at the circuit"));
183 wxMenuItem* harmCurrentElement =
184 new wxMenuItem(m_addElementsMenu, ID_ADDMENU_HARMCURRENT, _("&Harmonic current\tShift-H"),
185 _("Adds a harmonic current source at the circuit"));
186 wxMenuItem* emtElement =
187 new wxMenuItem(m_addElementsMenu, ID_ADDMENU_EMTELEMENT, _("&Electromagnetic Transient Element\tShift-E"), _("Adds an electromagnetic transient element that connects with ATP"));
188 wxMenuItem* textElement =
189 new wxMenuItem(m_addElementsMenu, ID_ADDMENU_TEXT, _("&Label\tA"), _("Adds a linked element label"));
190
191
192 m_addElementsMenu->Append(busElement);
193 m_addElementsMenu->Append(lineElement);
194 m_addElementsMenu->Append(transformerElement);
195 m_addElementsMenu->Append(generatorElement);
196 m_addElementsMenu->Append(indMotorElement);
197 m_addElementsMenu->Append(syncCompElement);
198 m_addElementsMenu->Append(loadElement);
199 m_addElementsMenu->Append(capacitorElement);
200 m_addElementsMenu->Append(inductorElement);
201 m_addElementsMenu->Append(harmCurrentElement);
202 m_addElementsMenu->Append(emtElement);
203 m_addElementsMenu->Append(textElement);
204
205 m_addElementsMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, &MainFrame::OnAddElementsClick, this);
206
207 m_stabilityMenu = new wxMenu();
208
209 wxMenuItem* stabilityList = new wxMenuItem(m_stabilityMenu, ID_STABMENU_LIST, _("&Stability event list"),
210 _("Show the stability event list"));
211 m_stabilityMenu->Append(stabilityList);
212
213 m_stabilityMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, &MainFrame::OnStabilityMenuClick, this);
214
215 m_snapshotMenu = new wxMenu();
216
217 wxMenuItem* snapshotList = new wxMenuItem(m_stabilityMenu, ID_SNAPSHOTMENU_LIST, _("&Export as SVG"),
218 _("Export the diagram as SVG file."));
219 m_snapshotMenu->Append(snapshotList);
220
221 m_snapshotMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, &MainFrame::OnSnapshotMenuClick, this);
222}
223
224void MainFrame::OnNewClick(wxRibbonButtonBarEvent& event)
225{
226 EnableCurrentProjectRibbon();
227
228 Workspace* newWorkspace;
229 //if (m_generalProperties->GetGeneralPropertiesData().useOpenGL) {
230 newWorkspace = new Workspace(this, wxString::Format(_("New project %d"), m_projectNumber),
231 this->GetStatusBar(), this->GetAuiNotebook());
232 //if (!m_sharedGLContext) m_sharedGLContext = newWorkspace->GetSharedGLContext();
233//}
234//else {
235// newWorkspace = new WorkspaceDC(this, wxString::Format(_("New project %d"), m_projectNumber),
236// this->GetStatusBar());
237//}
238// Set general properties in new Workspace
239 newWorkspace->GetProperties()->SetGeneralPropertiesData(m_generalProperties->GetGeneralPropertiesData());
240
241 m_workspaceList.push_back(newWorkspace);
242
243 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL, true);
244 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL, false);
245
246 m_auiNotebook->AddPage(newWorkspace, newWorkspace->GetName(), true);
247 newWorkspace->Redraw();
248 newWorkspace->SetJustOpened(true);
249 m_projectNumber++;
250}
251
252void MainFrame::OnAboutClick(wxRibbonButtonBarEvent& event)
253{
254 AboutForm about(this);
255 about.ShowModal();
256}
257
258void MainFrame::OnAddElementDropdown(wxRibbonButtonBarEvent& event) { event.PopupMenu(m_addElementsMenu); }
259void MainFrame::OnChartsClick(wxRibbonButtonBarEvent& event)
260{
261 if (Workspace* workspace = dynamic_cast<Workspace*>(m_auiNotebook->GetCurrentPage())) {
262 std::vector<ElementPlotData> plotDataList;
263 auto elementList = workspace->GetElementList();
264 for (auto it = elementList.begin(), itEnd = elementList.end(); it != itEnd; ++it) {
265 if (PowerElement* powerElement = dynamic_cast<PowerElement*>(*it)) {
266 ElementPlotData plotData;
267 if (powerElement->GetPlotData(plotData)) plotDataList.push_back(plotData);
268 }
269 }
270 ChartView* cView = new ChartView(workspace, plotDataList, workspace->GetStabilityTimeVector(), m_generalProperties->GetGeneralPropertiesData().plotLib);
271 cView->Show();
272 }
273}
274
275void MainFrame::OnCloseClick(wxRibbonButtonBarEvent& event)
276{
277 auto it = m_workspaceList.begin();
278 while (it != m_workspaceList.end()) {
279 if (*it == m_auiNotebook->GetCurrentPage()) {
280 //if ((*it)->GetSharedGLContext() == m_sharedGLContext) m_sharedGLContext = nullptr;
281 m_workspaceList.erase(it);
282 m_auiNotebook->DeletePage(m_auiNotebook->GetPageIndex(m_auiNotebook->GetCurrentPage()));
283 break;
284 }
285 ++it;
286 }
287 //if (!m_sharedGLContext && !m_workspaceList.empty()) {
288 // m_sharedGLContext = m_workspaceList[0]->GetSharedGLContext();
289 //}
290 if (m_workspaceList.empty()) {
291 EnableCurrentProjectRibbon(false);
292 }
293}
294void MainFrame::OnCopyClick(wxRibbonButtonBarEvent& event)
295{
296 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
297 if (workspace) { workspace->CopySelection(); }
298}
299
300void MainFrame::OnDataReportClick(wxRibbonButtonBarEvent& event)
301{
302 if (Workspace* workspace = dynamic_cast<Workspace*>(m_auiNotebook->GetCurrentPage())) {
303 DataReport* dataReport = new DataReport(workspace, workspace);
304 dataReport->Show();
305 }
306}
307void MainFrame::OnDeleteClick(wxRibbonButtonBarEvent& event)
308{
309 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
310 if (workspace) { workspace->DeleteSelectedElements(); }
311}
312void MainFrame::OnDisableSolutionClick(wxRibbonButtonBarEvent& event)
313{
314 if (Workspace* workspace = dynamic_cast<Workspace*>(m_auiNotebook->GetCurrentPage())) {
315 workspace->SetContinuousCalculationActive(false);
316 }
317 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL, true);
318 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL, false);
319}
320
321void MainFrame::OnDragClick(wxRibbonButtonBarEvent& event)
322{
323 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
324 if (workspace) {
325 workspace->SetWorkspaceMode(Workspace::WorkspaceMode::MODE_DRAG);
326 }
327}
328
329void MainFrame::OnEnableSolutionClick(wxRibbonButtonBarEvent& event)
330{
331 if (Workspace* workspace = dynamic_cast<Workspace*>(m_auiNotebook->GetCurrentPage())) {
332 workspace->SetContinuousCalculationActive(true);
333 workspace->RunStaticStudies();
334 }
335 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL, true);
336 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL, false);
337}
338
339// void MainFrame::OnExpImpClick(wxRibbonButtonBarEvent& event) {}
340void MainFrame::OnFaultClick(wxRibbonButtonBarEvent& event)
341{
342 if (Workspace* workspace = dynamic_cast<Workspace*>(m_auiNotebook->GetCurrentPage())) { workspace->RunFault(); }
343}
344
345void MainFrame::OnFitClick(wxRibbonButtonBarEvent& event)
346{
347 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
348 if (workspace) { workspace->Fit(); }
349}
350
351void MainFrame::OnMoveClick(wxRibbonButtonBarEvent& event)
352{
353 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
354 if (workspace) {
355 auto elementList = workspace->GetAllElements();
356 // Calculate the average position of selected elements.
357 wxPoint2DDouble averagePos(0, 0);
358 int numSelElements = 0;
359 for (auto it = elementList.begin(), itEnd = elementList.end(); it != itEnd; ++it) {
360 Element* element = *it;
361 if (element->IsSelected()) {
362 averagePos += element->GetPosition();
363 numSelElements++;
364 }
365 }
366 averagePos = wxPoint2DDouble(averagePos.m_x / double(numSelElements), averagePos.m_y / double(numSelElements));
367 // Set the move position to the average of selected elements.
368 for (auto it = elementList.begin(), itEnd = elementList.end(); it != itEnd; ++it) {
369 Element* element = *it;
370 if (element->IsSelected()) { element->StartMove(averagePos); }
371 }
372 workspace->SetWorkspaceMode(Workspace::WorkspaceMode::MODE_MOVE_ELEMENT);
373 }
374}
375
376void MainFrame::OnOpenClick(wxRibbonButtonBarEvent& event)
377{
378 wxFileDialog openFileDialog(this, _("Open PSP file"), "", "", "PSP files (*.psp)|*.psp",
379 wxFD_OPEN | wxFD_FILE_MUST_EXIST);
380 if (openFileDialog.ShowModal() == wxID_CANCEL) return;
381
382 wxFileName fileName(openFileDialog.GetPath());
383
384 EnableCurrentProjectRibbon();
385
386 Workspace* newWorkspace;
387 //if (m_generalProperties->GetGeneralPropertiesData().useOpenGL) {
388 newWorkspace = new Workspace(this, wxString::Format(_("New project %d"), m_projectNumber),
389 this->GetStatusBar(), this->GetAuiNotebook());
390 // If none shared OpenGL context is loaded, get from this workspace.
391 //if (!m_sharedGLContext) m_sharedGLContext = newWorkspace->GetSharedGLContext();
392//}
393//else {
394// newWorkspace = new WorkspaceDC(this, wxString::Format(_("New project %d"), m_projectNumber),
395// this->GetStatusBar());
396//}
397
398// Set general properties in new workspace.
399 newWorkspace->GetProperties()->SetGeneralPropertiesData(m_generalProperties->GetGeneralPropertiesData());
400
401 FileHanding fileHandling(newWorkspace);
402 if (fileHandling.OpenProject(fileName)) {
403 newWorkspace->SetSavedPath(fileName);
404
405 m_workspaceList.push_back(newWorkspace);
406
407 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL, true);
408 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL, false);
409
410 m_auiNotebook->AddPage(newWorkspace, newWorkspace->GetName(), true);
411 m_auiNotebook->Layout();
412 newWorkspace->Redraw();
413 newWorkspace->SetJustOpened(true);
414 newWorkspace->SaveCurrentState();
415 newWorkspace->Fit();
416 m_projectNumber++;
417 }
418 else {
419 wxMessageDialog msgDialog(this, _("It was not possible to open the selected file."), _("Error"),
420 wxOK | wxCENTRE | wxICON_ERROR);
421 msgDialog.ShowModal();
422 delete newWorkspace;
423 }
424}
425
426void MainFrame::OnPSPGuideClick(wxRibbonButtonBarEvent& event)
427{
428 wxLaunchDefaultBrowser("https://thales1330.github.io/PSP/docs/");
429}
430void MainFrame::OnPasteClick(wxRibbonButtonBarEvent& event)
431{
432 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
433 if (workspace) { workspace->Paste(); }
434}
435
436void MainFrame::OnPowerFlowClick(wxRibbonButtonBarEvent& event)
437{
438 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
439 if (workspace) { workspace->RunPowerFlow(); }
440}
441
442void MainFrame::OnRedoClick(wxRibbonButtonBarEvent& event)
443{
444 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
445 if (workspace) {
446 workspace->SetNextState();
447 }
448}
449void MainFrame::OnResetVoltagesClick(wxRibbonButtonBarEvent& event)
450{
451 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
452 if (workspace) { workspace->ResetAllVoltages(); }
453}
454
455void MainFrame::OnRunStabilityClick(wxRibbonButtonBarEvent& event)
456{
457 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
458 if (workspace) { workspace->RunStability(); }
459}
460
461void MainFrame::OnSCPowerClick(wxRibbonButtonBarEvent& event)
462{
463 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
464 if (workspace) { workspace->RunSCPower(); }
465}
466
467void MainFrame::OnSaveAsClick(wxRibbonButtonBarEvent& event)
468{
469 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
470 if (workspace) {
471 FileHanding fileHandling(workspace);
472
473 wxFileDialog saveFileDialog(this, _("Save PSP file"), "", "", "PSP files (*.psp)|*.psp",
474 wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
475 if (saveFileDialog.ShowModal() == wxID_CANCEL) return;
476
477 fileHandling.SaveProject(saveFileDialog.GetPath());
478 wxFileName fileName(saveFileDialog.GetPath());
479 workspace->SetName(fileName.GetName());
480 m_auiNotebook->SetPageText(m_auiNotebook->GetPageIndex(workspace), workspace->GetName());
481 workspace->SetSavedPath(fileName);
482 }
483}
484
485void MainFrame::OnSaveClick(wxRibbonButtonBarEvent& event)
486{
487 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
488 if (workspace) {
489 FileHanding fileHandling(workspace);
490
491 if (workspace->GetSavedPath().IsOk()) {
492 fileHandling.SaveProject(workspace->GetSavedPath());
493 }
494 else {
495 wxFileDialog saveFileDialog(this, _("Save PSP file"), "", "", "PSP files (*.psp)|*.psp",
496 wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
497 if (saveFileDialog.ShowModal() == wxID_CANCEL) return;
498
499 fileHandling.SaveProject(saveFileDialog.GetPath());
500 wxFileName fileName(saveFileDialog.GetPath());
501 workspace->SetName(fileName.GetName());
502 m_auiNotebook->SetPageText(m_auiNotebook->GetPageIndex(workspace), workspace->GetName());
503 workspace->SetSavedPath(fileName);
504 }
505 }
506}
507
508void MainFrame::OnSnapshotClick(wxRibbonButtonBarEvent& event)
509{
510 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
511 if (workspace) {
512 workspace->CopyToClipboard();
513 }
514}
515
516void MainFrame::OnUndoClick(wxRibbonButtonBarEvent& event)
517{
518 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
519 if (workspace) {
520 workspace->SetPreviousState();
521 }
522}
523
524void MainFrame::OnAddElementsClick(wxCommandEvent& event)
525{
526 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
527
528 if (workspace) {
529 if (workspace->GetWorkspaceMode() != Workspace::WorkspaceMode::MODE_INSERT) {
530 auto elementList = workspace->GetElementSharedList();
531 auto textList = workspace->GetTextList();
532 wxString statusBarText = "";
533 bool newElement = false;
534 bool isText = false;
535
536 switch (event.GetId()) {
537 case ID_ADDMENU_BUS: {
538 auto newBus = std::make_shared<Bus>(wxPoint2DDouble(0, 0),
539 wxString::Format(_("Bus %d"), workspace->GetElementNumber(ID_BUS)));
540 workspace->IncrementElementNumber(ID_BUS);
541 elementList.push_back(newBus);
542 statusBarText = _("Insert Bus: Click to insert, ESC to cancel.");
543 newElement = true;
544 } break;
545 case ID_ADDMENU_LINE: {
546 auto newLine = std::make_shared<Line>(wxString::Format(_("Line %d"), workspace->GetElementNumber(ID_LINE)));
547 elementList.push_back(newLine);
548 workspace->IncrementElementNumber(ID_LINE);
549 statusBarText = _("Insert Line: Click on two buses, ESC to cancel.");
550 newElement = true;
551 } break;
552 case ID_ADDMENU_TRANSFORMER: {
553 auto newTransformer = std::make_shared <Transformer>(
554 wxString::Format(_("Transformer %d"), workspace->GetElementNumber(ID_TRANSFORMER)));
555 workspace->IncrementElementNumber(ID_TRANSFORMER);
556 elementList.push_back(newTransformer);
557 statusBarText = _("Insert Transformer: Click on two buses, ESC to cancel.");
558 newElement = true;
559 } break;
560 case ID_ADDMENU_GENERATOR: {
561 auto newGenerator = std::make_shared<SyncGenerator>(
562 wxString::Format(_("Generator %d"), workspace->GetElementNumber(ID_SYNCGENERATOR)));
563 workspace->IncrementElementNumber(ID_SYNCGENERATOR);
564 elementList.push_back(newGenerator);
565 statusBarText = _("Insert Generator: Click on a bus, ESC to cancel.");
566 newElement = true;
567 } break;
568 case ID_ADDMENU_LOAD: {
569 auto newLoad = std::make_shared<Load>(wxString::Format(_("Load %d"), workspace->GetElementNumber(ID_LOAD)));
570 workspace->IncrementElementNumber(ID_LOAD);
571 elementList.push_back(newLoad);
572 statusBarText = _("Insert Load: Click on a bus, ESC to cancel.");
573 newElement = true;
574 } break;
575 case ID_ADDMENU_CAPACITOR: {
576 auto newCapacitor = std::make_shared<Capacitor>(wxString::Format(_("Capacitor %d"), workspace->GetElementNumber(ID_CAPACITOR)));
577 workspace->IncrementElementNumber(ID_CAPACITOR);
578 elementList.push_back(newCapacitor);
579 statusBarText = _("Insert Capacitor: Click on a bus, ESC to cancel.");
580 newElement = true;
581 } break;
582 case ID_ADDMENU_INDUCTOR: {
583 auto newInductor = std::make_shared<Inductor>(wxString::Format(_("Inductor %d"), workspace->GetElementNumber(ID_INDUCTOR)));
584 workspace->IncrementElementNumber(ID_INDUCTOR);
585 elementList.push_back(newInductor);
586 statusBarText = _("Insert Inductor: Click on a bus, ESC to cancel.");
587 newElement = true;
588 } break;
589 case ID_ADDMENU_HARMCURRENT: {
590 auto newHarmCurrent = std::make_shared<HarmCurrent>(
591 wxString::Format(_("Harmonic Current %d"), workspace->GetElementNumber(ID_INDUCTOR)));
592 workspace->IncrementElementNumber(ID_HARMCURRENT);
593 elementList.push_back(newHarmCurrent);
594 statusBarText = _("Insert Harmonic Current Source: Click on a bus, ESC to cancel.");
595 newElement = true;
596 } break;
597 case ID_ADDMENU_INDMOTOR: {
598 auto newIndMotor = std::make_shared<IndMotor>(
599 wxString::Format(_("Induction motor %d"), workspace->GetElementNumber(ID_INDMOTOR)));
600 workspace->IncrementElementNumber(ID_INDMOTOR);
601 elementList.push_back(newIndMotor);
602 statusBarText = _("Insert Induction Motor: Click on a bus, ESC to cancel.");
603 newElement = true;
604 } break;
605 case ID_ADDMENU_SYNCCOMP: {
606 auto newSyncCondenser = std::make_shared<SyncMotor>(
607 wxString::Format(_("Synchronous condenser %d"), workspace->GetElementNumber(ID_SYNCMOTOR)));
608 workspace->IncrementElementNumber(ID_SYNCMOTOR);
609 elementList.push_back(newSyncCondenser);
610 statusBarText = _("Insert Synchronous Condenser: Click on a bus, ESC to cancel.");
611 newElement = true;
612 } break;
613 case ID_ADDMENU_EMTELEMENT: {
614 auto newEMTElement = std::make_shared<EMTElement>(wxString::Format(_("Electromagnetic Transient %d"), workspace->GetElementNumber(ID_EMTELEMENT)));
615 workspace->IncrementElementNumber(ID_EMTELEMENT);
616 elementList.push_back(newEMTElement);
617 statusBarText = _("Insert Electromagnetic Transient Element: Click on a bus, ESC to cancel.");
618 newElement = true;
619 } break;
620 case ID_ADDMENU_TEXT: {
621 //Text* newText = new Text();
622 auto newText = std::make_shared<Text>();
623 textList.push_back(newText);
624 statusBarText = _("Insert Label: Click to insert, ESC to cancel.");
625 newElement = true;
626 isText = true;
627 } break;
628 }
629 if (newElement) {
630 workspace->SetElementList(elementList);
631 workspace->SetTextList(textList);
632 if (!isText)
633 workspace->SetWorkspaceMode(Workspace::WorkspaceMode::MODE_INSERT);
634 else
635 workspace->SetWorkspaceMode(Workspace::WorkspaceMode::MODE_INSERT_TEXT);
636 workspace->SetStatusBarText(statusBarText);
637 workspace->Redraw();
638 }
639 }
640 }
641}
642
643void MainFrame::OnImportClick(wxRibbonButtonBarEvent& event)
644{
645 // Create a new workspace to import
646 //Workspace* impWorkspace = new Workspace(this, _("Imported project"), this->GetStatusBar(), m_sharedGLContext);
647
648
649 EnableCurrentProjectRibbon();
650
651 Workspace* newWorkspace;
652 //if (m_generalProperties->GetGeneralPropertiesData().useOpenGL) {
653 newWorkspace = new Workspace(this, wxString::Format(_("New project %d"), m_projectNumber),
654 this->GetStatusBar(), this->GetAuiNotebook());
655 //if (!m_sharedGLContext) m_sharedGLContext = newWorkspace->GetSharedGLContext();
656//}
657//else {
658// newWorkspace = new WorkspaceDC(this, wxString::Format(_("New project %d"), m_projectNumber),
659// this->GetStatusBar());
660//}
661// Set general properties in new Workspace
662 newWorkspace->GetProperties()->SetGeneralPropertiesData(m_generalProperties->GetGeneralPropertiesData());
663
664 m_workspaceList.push_back(newWorkspace);
665
666 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL, true);
667 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL, false);
668
669 m_auiNotebook->AddPage(newWorkspace, newWorkspace->GetName(), true);
670 newWorkspace->Redraw();
671 m_projectNumber++;
672
673
674 ImportForm importForm(this, newWorkspace);
675 if (importForm.ShowModal() == wxID_OK) {
676 m_auiNotebook->Layout();
677 newWorkspace->Redraw();
678 newWorkspace->SetJustOpened(true);
679 newWorkspace->Fit();
680 }
681}
682
683void MainFrame::NotebookPageClosed(wxAuiNotebookEvent& event)
684{
685 if (m_auiNotebook->GetPageCount() == 0) EnableCurrentProjectRibbon(false);
686 event.Skip();
687}
688
689void MainFrame::NotebookPageClosing(wxAuiNotebookEvent& event)
690{
691 auto it = m_workspaceList.begin();
692 while (it != m_workspaceList.end()) {
693 if (*it == m_auiNotebook->GetCurrentPage()) {
694 //if ((*it)->GetSharedGLContext() == m_sharedGLContext) m_sharedGLContext = nullptr;
695 m_workspaceList.erase(it);
696 break;
697 }
698 ++it;
699 }
700 //if (!m_sharedGLContext && m_workspaceList.size() != 0) {
701 // m_sharedGLContext = m_workspaceList[0]->GetSharedGLContext();
702 //}
703 event.Skip();
704}
705
706void MainFrame::OnRotClockClick(wxRibbonButtonBarEvent& event)
707{
708 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
709 if (workspace) { workspace->RotateSelectedElements(); }
710}
711
712void MainFrame::OnRotCounterClockClick(wxRibbonButtonBarEvent& event)
713{
714 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
715 if (workspace) { workspace->RotateSelectedElements(false); }
716}
717
718void MainFrame::OnGeneralSettingsClick(wxRibbonButtonBarEvent& event)
719{
720 GeneralPropertiesForm genPropForm(this, m_generalProperties);
721 genPropForm.SetInitialSize();
722 genPropForm.ShowModal();
723 for (auto& workspace : m_workspaceList) {
724 workspace->GetProperties()->SetGeneralPropertiesData(m_generalProperties->GetGeneralPropertiesData());
725 workspace->UpdateTextElements();
726 workspace->Redraw();
727 }
728}
729
730void MainFrame::OnSimulationSettingsClick(wxRibbonButtonBarEvent& event)
731{
732 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
733 if (workspace) {
734 SimulationsSettingsForm simulSettingsForm(this, workspace->GetProperties(), m_locale);
735 simulSettingsForm.SetInitialSize();
736 simulSettingsForm.ShowModal();
737 }
738}
739void MainFrame::OnFreqResponseClick(wxRibbonButtonBarEvent& event)
740{
741 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
742 if (workspace) { workspace->RunFrequencyResponse(); }
743}
744void MainFrame::OnHarmDistortionsClick(wxRibbonButtonBarEvent& event)
745{
746 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
747 if (workspace) { workspace->RunHarmonicDistortion(); }
748}
749
750void MainFrame::OnStabilityDropdown(wxRibbonButtonBarEvent& event) { event.PopupMenu(m_stabilityMenu); }
751
752void MainFrame::OnStabilityMenuClick(wxCommandEvent& event)
753{
754 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
755
756 if (workspace) {
757 auto elementList = workspace->GetElementList();
758
759 switch (event.GetId()) {
760 case ID_STABMENU_LIST: {
761 StabilityEventList stabEventList(this, elementList);
762 stabEventList.ShowModal();
763 } break;
764 }
765 }
766}
767
768void MainFrame::OnSnapshotMenuClick(wxCommandEvent& event)
769{
770 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
771
772 if (workspace) {
773 auto elementList = workspace->GetElementList();
774
775 switch (event.GetId()) {
776 case ID_SNAPSHOTMENU_LIST: {
777 // Save SVG file
778 wxFileDialog saveFileDialog(this, _("Save diagram as SVG"), "", "", "SVG files (*.svg)|*.svg",
779 wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
780 if (saveFileDialog.ShowModal() == wxID_CANCEL) return;
781 workspace->ExportAsSVG(saveFileDialog.GetPath());
782 } break;
783 }
784 }
785}
786
787int MainFrame::RunPSPTest()
788{
789 wxMessageOutput::Get()->Printf("Main frame setup OK!\n");
790
791 // Emulate new project creation
792 EnableCurrentProjectRibbon();
793
794 Workspace* newWorkspace = new Workspace(this, wxString::Format(_("New project %d"), m_projectNumber),
795 this->GetStatusBar(), this->GetAuiNotebook());
796 //if (!m_sharedGLContext) {
797 // m_sharedGLContext = newWorkspace->GetSharedGLContext();
798 //}
799 m_workspaceList.push_back(newWorkspace);
800
801 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL, true);
802 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL, false);
803
804 m_auiNotebook->AddPage(newWorkspace, newWorkspace->GetName(), true);
805 newWorkspace->Redraw();
806
807 wxMessageOutput::Get()->Printf("Project creation OK!\n");
808 wxMessageOutput::Get()->Printf("Test done!\n");
809
810 return 0;
811}
812void MainFrame::OnClose(wxCloseEvent& event)
813{
814 // Setup the workspace closing correctly
815
816 wxMessageDialog dialog(this,
817 _("Are you sure you want to close the program?\nAny unsaved changes will be lost."),
818 _("Closing PSP-UFU..."),
819 wxYES_NO | wxICON_EXCLAMATION);
820
821 if (dialog.ShowModal() == wxID_YES) {
822 if (!m_workspaceList.empty())
823 m_workspaceList[m_workspaceList.size() - 1]->Show();
824 event.Skip();
825 }
826 else event.Skip(false);
827}
828void MainFrame::OnHeatmapClick(wxRibbonButtonBarEvent& event)
829{
830 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
831 if (workspace) {
832 const bool enabled = workspace->IsHeatMapEnable();
833 m_ribbonButtonBarReports->ToggleButton(ID_RIBBON_HEATMAP, !enabled);
834 workspace->EnableHeatMap(!enabled);
835 }
836}
837void MainFrame::OnNotebookPageChanged(wxAuiNotebookEvent& event)
838{
839 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
840 if (workspace) {
841 m_ribbonButtonBarReports->ToggleButton(ID_RIBBON_HEATMAP, workspace->IsHeatMapEnable());
842 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL, workspace->IsContinuousCalculationActive());
843 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL, !workspace->IsContinuousCalculationActive());
844 }
845}
846void MainFrame::OnProjectSettingsClick(wxRibbonButtonBarEvent& event)
847{
848 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
849 if (workspace) {
850 ProjectPropertiesForm ppf(this, workspace);
851 ppf.ShowModal();
852 workspace->UpdateHeatMap();
853 workspace->Redraw();
854 }
855}
856void MainFrame::OnSnapshotDropdown(wxRibbonButtonBarEvent& event)
857{
858 event.PopupMenu(m_snapshotMenu);
859}
860void MainFrame::OnLabelMngrClick(wxRibbonButtonBarEvent& event)
861{
862 Workspace* workspace = static_cast<Workspace*>(m_auiNotebook->GetCurrentPage());
863 if (workspace) {
864 LabelManager labelMngr(this, workspace);
865
866 if (labelMngr.ShowModal() == wxID_OK) {
867 workspace->UpdateTextElements();
868 workspace->Redraw();
869 }
870 }
871}
Form to show some informations.
Definition AboutForm.h:33
This class is responsible to manage the charts generated in the transient electromechanical studies.
Definition ChartView.h:49
Form that shows the results of power flow and fault calculations.
Definition DataReport.h:34
Base class of all elements of the program. This class is responsible for manage graphical and his dat...
Definition Element.h:112
wxPoint2DDouble GetPosition() const
Get the element position.
Definition Element.h:186
virtual void StartMove(wxPoint2DDouble position)
Update the element attributes related to the movement.
Definition Element.cpp:329
bool IsSelected() const
Checks if the element is selected.
Definition Element.h:201
Save and opens the projects created on disk.
Definition FileHanding.h:43
Form to edit the software's general data.
Form to import other programs files to PSP.
Definition ImportForm.h:53
~MainFrame()
Default destructor.
Definition MainFrame.cpp:82
MainFrame()
Default constructor.
Definition MainFrame.cpp:49
Abstract class of power elements.
General and simulation data manager.
Form to edit the simulation data.
This class manages the graphical and power elements. It is responsible for handling the user's intera...
Definition Workspace.h:103