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