20#include <wx/settings.h>
38#include "forms/ProjectPropertiesForm.h"
40#include "forms/StabilityEventList.h"
41#include "forms/LabelManager.h"
42#include "forms/ElementsToolBar.h"
49#include "extLibs/artProvider/ArtMetro.h"
50#include "utils/Path.h"
58 m_generalProperties = initProperties;
63 EnableCurrentProjectRibbon();
64 Workspace* newWorkspace =
new Workspace(
this, _(
"Open project"), this->GetStatusBar(), this->GetAuiNotebook());
68 if (fileHandling.OpenProject(openPath)) {
69 newWorkspace->SetSavedPath(openPath);
71 m_workspaceList.push_back(newWorkspace);
73 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL,
true);
74 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL,
false);
76 m_auiNotebook->AddPage(newWorkspace, newWorkspace->GetName(),
true);
77 m_auiNotebook->Layout();
78 newWorkspace->Redraw();
79 newWorkspace->SetJustOpened(
true);
91 if (m_addElementsMenu) {
92 m_addElementsMenu->Disconnect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnAddElementsClick),
94 delete m_addElementsMenu;
96 if (m_stabilityMenu) {
97 m_stabilityMenu->Disconnect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnStabilityMenuClick),
99 delete m_stabilityMenu;
101 if (m_snapshotMenu) {
102 m_snapshotMenu->Disconnect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::OnSnapshotMenuClick),
104 delete m_snapshotMenu;
107 if (m_locale)
delete m_locale;
108 if (m_generalProperties)
delete m_generalProperties;
111void MainFrame::Init()
113 this->SetSize(800, 600);
115 m_generalProperties->SetGUIColourTheme();
117 CreateDropdownMenus();
119 EnableCurrentProjectRibbon(
false);
121 if (wxSystemSettings::GetAppearance().IsDark())
123 auto* darkArt = m_ribbonBar->GetArtProvider();
124 wxColour stdBlue = wxColour(53, 132, 228);
125 wxColour darkBlue = wxColour(6, 68, 140);
126 wxColour stdGrey = wxColour(59, 59, 59);
127 wxColour darkGrey = wxColour(40, 40, 40);
129 darkArt->SetColor(wxRIBBON_ART_PAGE_BACKGROUND_TOP_COLOUR, stdGrey);
130 darkArt->SetColor(wxRIBBON_ART_PAGE_BACKGROUND_TOP_GRADIENT_COLOUR, stdGrey);
131 darkArt->SetColor(wxRIBBON_ART_PAGE_BACKGROUND_COLOUR, stdGrey);
132 darkArt->SetColor(wxRIBBON_ART_PAGE_BACKGROUND_GRADIENT_COLOUR, stdGrey);
134 darkArt->SetColor(wxRIBBON_ART_PAGE_HOVER_BACKGROUND_TOP_COLOUR, darkGrey);
135 darkArt->SetColor(wxRIBBON_ART_PAGE_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR, darkGrey);
136 darkArt->SetColor(wxRIBBON_ART_PAGE_HOVER_BACKGROUND_COLOUR, darkGrey);
137 darkArt->SetColor(wxRIBBON_ART_PAGE_HOVER_BACKGROUND_GRADIENT_COLOUR, darkGrey);
139 darkArt->SetColor(wxRIBBON_ART_TAB_HOVER_BACKGROUND_TOP_COLOUR, stdBlue);
140 darkArt->SetColor(wxRIBBON_ART_TAB_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR, stdBlue);
141 darkArt->SetColor(wxRIBBON_ART_TAB_HOVER_BACKGROUND_COLOUR, stdBlue);
142 darkArt->SetColor(wxRIBBON_ART_TAB_HOVER_BACKGROUND_GRADIENT_COLOUR, stdBlue);
144 darkArt->SetColor(wxRIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_TOP_COLOUR, stdBlue);
145 darkArt->SetColor(wxRIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_TOP_GRADIENT_COLOUR, stdBlue);
146 darkArt->SetColor(wxRIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_COLOUR, stdBlue);
147 darkArt->SetColor(wxRIBBON_ART_BUTTON_BAR_ACTIVE_BACKGROUND_GRADIENT_COLOUR, stdBlue);
149 darkArt->SetColor(wxRIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_TOP_COLOUR, darkBlue);
150 darkArt->SetColor(wxRIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_TOP_GRADIENT_COLOUR, darkBlue);
151 darkArt->SetColor(wxRIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_COLOUR, darkBlue);
152 darkArt->SetColor(wxRIBBON_ART_BUTTON_BAR_HOVER_BACKGROUND_GRADIENT_COLOUR, darkBlue);
153 m_ribbonBar->Realize();
157 m_artMetro =
new wxRibbonMetroArtProvider();
158 m_ribbonBar->SetArtProvider(m_artMetro);
159 m_ribbonBar->Realize();
164 if (!m_generalProperties)
return;
168 if (m_generalProperties->GetGeneralPropertiesData().elementsToolbar != NONE) {
170 BuildElementsToolBar(m_generalProperties->GetGeneralPropertiesData().elementsToolbar);
171 m_elementsToolBar->EnableTools(
false);
176void MainFrame::EnableCurrentProjectRibbon(
bool enable)
178 if (m_elementsToolBar) {
179 m_elementsToolBar->EnableTools(enable);
181 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_ADDELEMENT, enable);
182 m_ribbonButtonBarReports->EnableButton(ID_RIBBON_CHARTS, enable);
183 m_ribbonButtonBarCProject->EnableButton(ID_RIBBON_CLOSE, enable);
184 m_ribbonButtonBarClipboard->EnableButton(ID_RIBBON_COPY, enable);
185 m_ribbonButtonBarReports->EnableButton(ID_RIBBON_DATAREPORT, enable);
186 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_DELETE, enable);
187 m_ribbonButtonBarContinuous->EnableButton(ID_RIBBON_DISABLESOL, enable);
188 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_DRAG, enable);
189 m_ribbonButtonBarContinuous->EnableButton(ID_RIBBON_ENABLESOL, enable);
190 m_ribbonButtonBarSimulations->EnableButton(ID_RIBBON_FAULT, enable);
191 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_FIT, enable);
192 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_MOVE, enable);
193 m_ribbonButtonBarClipboard->EnableButton(ID_RIBBON_PASTE, enable);
194 m_ribbonButtonBarSimulations->EnableButton(ID_RIBBON_POWERFLOW, enable);
195 m_ribbonButtonBarClipboard->EnableButton(ID_RIBBON_REDO, enable);
196 m_ribbonButtonBarContinuous->EnableButton(ID_RIBBON_RESETVOLT, enable);
197 m_ribbonButtonBarSimulations->EnableButton(ID_RIBBON_RUNSTAB, enable);
198 m_ribbonButtonBarCProject->EnableButton(ID_RIBBON_SAVE, enable);
199 m_ribbonButtonBarCProject->EnableButton(ID_RIBBON_SAVEAS, enable);
200 m_ribbonButtonBarSimulations->EnableButton(ID_RIBBON_SCPOWER, enable);
201 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_PROJSETTINGS, enable);
202 m_ribbonButtonBarReports->EnableButton(ID_RIBBON_HEATMAP, enable);
203 m_ribbonButtonBarReports->EnableButton(ID_RIBBON_SNAPSHOT, enable);
204 m_ribbonButtonBarSimulations->EnableButton(ID_RIBBON_SIMULSETTINGS, enable);
205 m_ribbonButtonBarClipboard->EnableButton(ID_RIBBON_UNDO, enable);
206 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_ROTATEC, enable);
207 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_ROTATECC, enable);
208 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_GRID, enable);
209 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_ALIGN, enable);
210 m_ribbonButtonBarCircuit->EnableButton(ID_RIBBON_LABELMNGR, enable);
211 m_ribbonButtonBarSimulations->EnableButton(ID_RIBBON_HARMDIST, enable);
212 m_ribbonButtonBarSimulations->EnableButton(ID_RIBBON_FREQRESP, enable);
215void MainFrame::CreateDropdownMenus()
217 m_addElementsMenu =
new wxMenu();
224 const std::vector<ElementIcon> elementIcons = {
225 { ID_ADDMENU_BUS,
"bus.png" },
226 { ID_ADDMENU_CAPACITOR,
"capacitor.png" },
227 { ID_ADDMENU_EMTELEMENT,
"emtelement.png" },
228 { ID_ADDMENU_GENERATOR,
"generator.png" },
229 { ID_ADDMENU_HARMCURRENT,
"harmcurrent.png" },
230 { ID_ADDMENU_INDMOTOR,
"indmotor.png" },
231 { ID_ADDMENU_INDUCTOR,
"inductor.png" },
232 { ID_ADDMENU_LINE,
"line.png" },
233 { ID_ADDMENU_LOAD,
"load.png" },
234 { ID_ADDMENU_SYNCCOMP,
"synccomp.png" },
235 { ID_ADDMENU_TEXT,
"text.png" },
236 { ID_ADDMENU_TRANSFORMER,
"transformer.png" }
239 std::map<int, wxBitmap> elementBitmaps;
241 const int iconSize = FromDIP(16);
243 for (
const auto& icon : elementIcons) {
244 wxImage image(Paths::GetDataPath() +
"/images/elements/" + icon.file, wxBITMAP_TYPE_PNG);
247 image.Rescale(iconSize, iconSize, wxIMAGE_QUALITY_HIGH);
248 elementBitmaps[icon.id] = wxBitmap(image);
252 wxMenuItem* busElement =
253 new wxMenuItem(m_addElementsMenu, ID_ADDMENU_BUS, _(
"&Bus\tB"), _(
"Adds a bus at the circuit"));
254 busElement->SetBitmap(elementBitmaps.at(ID_ADDMENU_BUS));
256 wxMenuItem* lineElement =
257 new wxMenuItem(m_addElementsMenu, ID_ADDMENU_LINE, _(
"&Line\tL"), _(
"Adds a power line at the circuit"));
258 lineElement->SetBitmap(elementBitmaps.at(ID_ADDMENU_LINE));
260 wxMenuItem* transformerElement =
new wxMenuItem(m_addElementsMenu, ID_ADDMENU_TRANSFORMER, _(
"&Transformer\tT"),
261 _(
"Adds a transformer at the circuit"));
262 transformerElement->SetBitmap(elementBitmaps.at(ID_ADDMENU_TRANSFORMER));
264 wxMenuItem* generatorElement =
new wxMenuItem(m_addElementsMenu, ID_ADDMENU_GENERATOR, _(
"&Generator\tG"),
265 _(
"Adds a generator at the circuit"));
266 generatorElement->SetBitmap(elementBitmaps.at(ID_ADDMENU_GENERATOR));
268 wxMenuItem* indMotorElement =
new wxMenuItem(m_addElementsMenu, ID_ADDMENU_INDMOTOR, _(
"&Induction motor\tI"),
269 _(
"Adds an induction motor at the circuit"));
270 indMotorElement->SetBitmap(elementBitmaps.at(ID_ADDMENU_INDMOTOR));
272 wxMenuItem* syncCompElement =
273 new wxMenuItem(m_addElementsMenu, ID_ADDMENU_SYNCCOMP, _(
"&Synchronous compensator \tK"),
274 _(
"Adds an induction motor at the circuit"));
275 syncCompElement->SetBitmap(elementBitmaps.at(ID_ADDMENU_SYNCCOMP));
277 wxMenuItem* loadElement =
278 new wxMenuItem(m_addElementsMenu, ID_ADDMENU_LOAD, _(
"&Load\tShift-L"), _(
"Adds a load at the circuit"));
279 loadElement->SetBitmap(elementBitmaps.at(ID_ADDMENU_LOAD));
281 wxMenuItem* capacitorElement =
new wxMenuItem(m_addElementsMenu, ID_ADDMENU_CAPACITOR, _(
"&Capacitor\tShift-C"),
282 _(
"Adds a shunt capacitor at the circuit"));
283 capacitorElement->SetBitmap(elementBitmaps.at(ID_ADDMENU_CAPACITOR));
285 wxMenuItem* inductorElement =
new wxMenuItem(m_addElementsMenu, ID_ADDMENU_INDUCTOR, _(
"&Inductor\tShift-I"),
286 _(
"Adds a shunt inductor at the circuit"));
287 inductorElement->SetBitmap(elementBitmaps.at(ID_ADDMENU_INDUCTOR));
289 wxMenuItem* harmCurrentElement =
290 new wxMenuItem(m_addElementsMenu, ID_ADDMENU_HARMCURRENT, _(
"&Harmonic current\tShift-H"),
291 _(
"Adds a harmonic current source at the circuit"));
292 harmCurrentElement->SetBitmap(elementBitmaps.at(ID_ADDMENU_HARMCURRENT));
294 wxMenuItem* emtElement =
295 new wxMenuItem(m_addElementsMenu, ID_ADDMENU_EMTELEMENT, _(
"&Electromagnetic Transient Element\tShift-E"), _(
"Adds an electromagnetic transient element that connects with ATP"));
296 emtElement->SetBitmap(elementBitmaps.at(ID_ADDMENU_EMTELEMENT));
298 wxMenuItem* textElement =
299 new wxMenuItem(m_addElementsMenu, ID_ADDMENU_TEXT, _(
"&Label\tA"), _(
"Adds a linked element label"));
300 textElement->SetBitmap(elementBitmaps.at(ID_ADDMENU_TEXT));
303 m_addElementsMenu->Append(busElement);
304 m_addElementsMenu->Append(lineElement);
305 m_addElementsMenu->Append(transformerElement);
306 m_addElementsMenu->Append(generatorElement);
307 m_addElementsMenu->Append(indMotorElement);
308 m_addElementsMenu->Append(syncCompElement);
309 m_addElementsMenu->Append(loadElement);
310 m_addElementsMenu->Append(capacitorElement);
311 m_addElementsMenu->Append(inductorElement);
312 m_addElementsMenu->Append(harmCurrentElement);
313 m_addElementsMenu->Append(emtElement);
314 m_addElementsMenu->Append(textElement);
316 m_addElementsMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, &MainFrame::OnAddElementsClick,
this);
318 m_stabilityMenu =
new wxMenu();
320 wxMenuItem* stabilityList =
new wxMenuItem(m_stabilityMenu, ID_STABMENU_LIST, _(
"&Stability event list"),
321 _(
"Show the stability event list"));
322 m_stabilityMenu->Append(stabilityList);
324 m_stabilityMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, &MainFrame::OnStabilityMenuClick,
this);
326 m_snapshotMenu =
new wxMenu();
328 wxMenuItem* snapshotList =
new wxMenuItem(m_stabilityMenu, ID_SNAPSHOTMENU_LIST, _(
"&Export as SVG"),
329 _(
"Export the diagram as SVG file."));
330 m_snapshotMenu->Append(snapshotList);
332 m_snapshotMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, &MainFrame::OnSnapshotMenuClick,
this);
335void MainFrame::OnNewClick(wxRibbonButtonBarEvent& event)
337 EnableCurrentProjectRibbon();
341 newWorkspace =
new Workspace(m_auiNotebook, wxString::Format(_(
"New project %d"), m_projectNumber), this->GetStatusBar(), this->GetAuiNotebook());
343 newWorkspace->GetProperties()->SetGeneralPropertiesData(m_generalProperties->GetGeneralPropertiesData());
344 newWorkspace->SetColourTheme();
346 m_workspaceList.push_back(newWorkspace);
348 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL,
true);
349 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL,
false);
351 m_auiNotebook->AddPage(newWorkspace, newWorkspace->GetName(),
true);
352 newWorkspace->Redraw();
353 newWorkspace->SetJustOpened(
true);
357void MainFrame::OnAboutClick(wxRibbonButtonBarEvent& event)
363void MainFrame::OnAddElementDropdown(wxRibbonButtonBarEvent& event) {
event.PopupMenu(m_addElementsMenu); }
364void MainFrame::OnChartsClick(wxRibbonButtonBarEvent& event)
366 if (
Workspace* workspace =
dynamic_cast<Workspace*
>(m_auiNotebook->GetCurrentPage())) {
367 std::vector<ElementPlotData> plotDataList;
368 auto elementList = workspace->GetElementList();
369 for (
auto it = elementList.begin(), itEnd = elementList.end(); it != itEnd; ++it) {
372 if (powerElement->GetPlotData(plotData)) plotDataList.push_back(plotData);
375 ChartView* cView =
new ChartView(workspace, plotDataList, workspace->GetStabilityTimeVector(), m_generalProperties->GetGeneralPropertiesData().plotLib);
380void MainFrame::OnCloseClick(wxRibbonButtonBarEvent& event)
382 auto it = m_workspaceList.begin();
383 while (it != m_workspaceList.end()) {
384 if (*it == m_auiNotebook->GetCurrentPage()) {
386 m_workspaceList.erase(it);
387 m_auiNotebook->DeletePage(m_auiNotebook->GetPageIndex(m_auiNotebook->GetCurrentPage()));
395 if (m_workspaceList.empty()) {
396 EnableCurrentProjectRibbon(
false);
399void MainFrame::OnCopyClick(wxRibbonButtonBarEvent& event)
402 if (workspace) { workspace->CopySelection(); }
405void MainFrame::OnDataReportClick(wxRibbonButtonBarEvent& event)
407 if (
Workspace* workspace =
dynamic_cast<Workspace*
>(m_auiNotebook->GetCurrentPage())) {
412void MainFrame::OnDeleteClick(wxRibbonButtonBarEvent& event)
415 if (workspace) { workspace->DeleteSelectedElements(); }
417void MainFrame::OnDisableSolutionClick(wxRibbonButtonBarEvent& event)
419 if (
Workspace* workspace =
dynamic_cast<Workspace*
>(m_auiNotebook->GetCurrentPage())) {
420 workspace->SetContinuousCalculationActive(
false);
422 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL,
true);
423 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL,
false);
426void MainFrame::OnDragClick(wxRibbonButtonBarEvent& event)
430 workspace->SetWorkspaceMode(Workspace::WorkspaceMode::MODE_DRAG);
434void MainFrame::OnEnableSolutionClick(wxRibbonButtonBarEvent& event)
436 if (
Workspace* workspace =
dynamic_cast<Workspace*
>(m_auiNotebook->GetCurrentPage())) {
437 workspace->SetContinuousCalculationActive(
true);
438 workspace->RunStaticStudies();
440 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL,
true);
441 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL,
false);
445void MainFrame::OnFaultClick(wxRibbonButtonBarEvent& event)
447 if (
Workspace* workspace =
dynamic_cast<Workspace*
>(m_auiNotebook->GetCurrentPage())) { workspace->RunFault(); }
450void MainFrame::OnFitClick(wxRibbonButtonBarEvent& event)
453 if (workspace) { workspace->Fit(); }
456void MainFrame::OnMoveClick(wxRibbonButtonBarEvent& event)
460 auto elementList = workspace->GetAllElements();
462 wxPoint2DDouble averagePos(0, 0);
463 int numSelElements = 0;
464 for (
auto it = elementList.begin(), itEnd = elementList.end(); it != itEnd; ++it) {
471 averagePos = wxPoint2DDouble(averagePos.m_x /
double(numSelElements), averagePos.m_y /
double(numSelElements));
473 for (
auto it = elementList.begin(), itEnd = elementList.end(); it != itEnd; ++it) {
477 workspace->SetWorkspaceMode(Workspace::WorkspaceMode::MODE_MOVE_ELEMENT);
481void MainFrame::OnOpenClick(wxRibbonButtonBarEvent& event)
483 wxFileDialog openFileDialog(
this, _(
"Open PSP file"),
"",
"",
"PSP files (*.psp)|*.psp",
484 wxFD_OPEN | wxFD_FILE_MUST_EXIST);
485 if (openFileDialog.ShowModal() == wxID_CANCEL)
return;
487 wxFileName fileName(openFileDialog.GetPath());
489 EnableCurrentProjectRibbon();
492 Workspace* newWorkspace =
new Workspace(m_auiNotebook, wxString::Format(_(
"New project %d"), m_projectNumber), this->GetStatusBar(), this->GetAuiNotebook());
495 newWorkspace->GetProperties()->SetGeneralPropertiesData(m_generalProperties->GetGeneralPropertiesData());
496 newWorkspace->SetColourTheme();
499 if (fileHandling.OpenProject(fileName)) {
500 newWorkspace->SetSavedPath(fileName);
502 m_workspaceList.push_back(newWorkspace);
504 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL,
true);
505 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL,
false);
507 m_auiNotebook->AddPage(newWorkspace, newWorkspace->GetName(),
true);
508 m_auiNotebook->Layout();
509 newWorkspace->Redraw();
510 newWorkspace->SetJustOpened(
true);
511 newWorkspace->SaveCurrentState();
516 wxMessageDialog msgDialog(
this, _(
"It was not possible to open the selected file."), _(
"Error"),
517 wxOK | wxCENTRE | wxICON_ERROR);
518 msgDialog.ShowModal();
523void MainFrame::OnPSPGuideClick(wxRibbonButtonBarEvent& event)
525 wxLaunchDefaultBrowser(
"https://thales1330.github.io/PSP/docs/");
527void MainFrame::OnPasteClick(wxRibbonButtonBarEvent& event)
530 if (workspace) { workspace->Paste(); }
533void MainFrame::OnPowerFlowClick(wxRibbonButtonBarEvent& event)
536 if (workspace) { workspace->RunPowerFlow(); }
539void MainFrame::OnRedoClick(wxRibbonButtonBarEvent& event)
543 workspace->SetNextState();
546void MainFrame::OnResetVoltagesClick(wxRibbonButtonBarEvent& event)
549 if (workspace) { workspace->ResetAllVoltages(); }
552void MainFrame::OnRunStabilityClick(wxRibbonButtonBarEvent& event)
555 if (workspace) { workspace->RunStability(); }
558void MainFrame::OnSCPowerClick(wxRibbonButtonBarEvent& event)
561 if (workspace) { workspace->RunSCPower(); }
564void MainFrame::OnSaveAsClick(wxRibbonButtonBarEvent& event)
570 wxFileDialog saveFileDialog(
this, _(
"Save PSP file"),
"",
"",
"PSP files (*.psp)|*.psp",
571 wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
572 if (saveFileDialog.ShowModal() == wxID_CANCEL)
return;
574 fileHandling.SaveProject(saveFileDialog.GetPath());
575 wxFileName fileName(saveFileDialog.GetPath());
576 workspace->SetName(fileName.GetName());
577 m_auiNotebook->SetPageText(m_auiNotebook->GetPageIndex(workspace), workspace->GetName());
578 workspace->SetSavedPath(fileName);
582void MainFrame::OnSaveClick(wxRibbonButtonBarEvent& event)
588 if (workspace->GetSavedPath().IsOk()) {
589 fileHandling.SaveProject(workspace->GetSavedPath());
592 wxFileDialog saveFileDialog(
this, _(
"Save PSP file"),
"",
"",
"PSP files (*.psp)|*.psp",
593 wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
594 if (saveFileDialog.ShowModal() == wxID_CANCEL)
return;
596 fileHandling.SaveProject(saveFileDialog.GetPath());
597 wxFileName fileName(saveFileDialog.GetPath());
598 workspace->SetName(fileName.GetName());
599 m_auiNotebook->SetPageText(m_auiNotebook->GetPageIndex(workspace), workspace->GetName());
600 workspace->SetSavedPath(fileName);
605void MainFrame::OnSnapshotClick(wxRibbonButtonBarEvent& event)
609 workspace->CopyToClipboard();
613void MainFrame::OnUndoClick(wxRibbonButtonBarEvent& event)
617 workspace->SetPreviousState();
621void MainFrame::OnAddElementsClick(wxCommandEvent& event)
626 if (workspace->GetWorkspaceMode() != Workspace::WorkspaceMode::MODE_INSERT) {
627 auto elementList = workspace->GetElementSharedList();
628 auto textList = workspace->GetTextList();
629 wxString statusBarText =
"";
630 bool newElement =
false;
633 switch (event.GetId()) {
634 case ID_ADDMENU_BUS: {
635 auto newBus = std::make_shared<Bus>(wxPoint2DDouble(0, 0),
636 wxString::Format(_(
"Bus %d"), workspace->GetElementNumber(ID_BUS)));
637 workspace->IncrementElementNumber(ID_BUS);
638 elementList.push_back(newBus);
639 statusBarText = _(
"Insert Bus: Click to insert, ESC to cancel.");
642 case ID_ADDMENU_LINE: {
643 auto newLine = std::make_shared<Line>(wxString::Format(_(
"Line %d"), workspace->GetElementNumber(ID_LINE)));
644 elementList.push_back(newLine);
645 workspace->IncrementElementNumber(ID_LINE);
646 statusBarText = _(
"Insert Line: Click on two buses, ESC to cancel.");
649 case ID_ADDMENU_TRANSFORMER: {
650 auto newTransformer = std::make_shared <Transformer>(
651 wxString::Format(_(
"Transformer %d"), workspace->GetElementNumber(ID_TRANSFORMER)));
652 workspace->IncrementElementNumber(ID_TRANSFORMER);
653 elementList.push_back(newTransformer);
654 statusBarText = _(
"Insert Transformer: Click on two buses, ESC to cancel.");
657 case ID_ADDMENU_GENERATOR: {
658 auto newGenerator = std::make_shared<SyncGenerator>(
659 wxString::Format(_(
"Generator %d"), workspace->GetElementNumber(ID_SYNCGENERATOR)));
660 workspace->IncrementElementNumber(ID_SYNCGENERATOR);
661 elementList.push_back(newGenerator);
662 statusBarText = _(
"Insert Generator: Click on a bus, ESC to cancel.");
665 case ID_ADDMENU_LOAD: {
666 auto newLoad = std::make_shared<Load>(wxString::Format(_(
"Load %d"), workspace->GetElementNumber(ID_LOAD)));
667 workspace->IncrementElementNumber(ID_LOAD);
668 elementList.push_back(newLoad);
669 statusBarText = _(
"Insert Load: Click on a bus, ESC to cancel.");
672 case ID_ADDMENU_CAPACITOR: {
673 auto newCapacitor = std::make_shared<Capacitor>(wxString::Format(_(
"Capacitor %d"), workspace->GetElementNumber(ID_CAPACITOR)));
674 workspace->IncrementElementNumber(ID_CAPACITOR);
675 elementList.push_back(newCapacitor);
676 statusBarText = _(
"Insert Capacitor: Click on a bus, ESC to cancel.");
679 case ID_ADDMENU_INDUCTOR: {
680 auto newInductor = std::make_shared<Inductor>(wxString::Format(_(
"Inductor %d"), workspace->GetElementNumber(ID_INDUCTOR)));
681 workspace->IncrementElementNumber(ID_INDUCTOR);
682 elementList.push_back(newInductor);
683 statusBarText = _(
"Insert Inductor: Click on a bus, ESC to cancel.");
686 case ID_ADDMENU_HARMCURRENT: {
687 auto newHarmCurrent = std::make_shared<HarmCurrent>(
688 wxString::Format(_(
"Harmonic Current %d"), workspace->GetElementNumber(ID_INDUCTOR)));
689 workspace->IncrementElementNumber(ID_HARMCURRENT);
690 elementList.push_back(newHarmCurrent);
691 statusBarText = _(
"Insert Harmonic Current Source: Click on a bus, ESC to cancel.");
694 case ID_ADDMENU_INDMOTOR: {
695 auto newIndMotor = std::make_shared<IndMotor>(
696 wxString::Format(_(
"Induction motor %d"), workspace->GetElementNumber(ID_INDMOTOR)));
697 workspace->IncrementElementNumber(ID_INDMOTOR);
698 elementList.push_back(newIndMotor);
699 statusBarText = _(
"Insert Induction Motor: Click on a bus, ESC to cancel.");
702 case ID_ADDMENU_SYNCCOMP: {
703 auto newSyncCondenser = std::make_shared<SyncMotor>(
704 wxString::Format(_(
"Synchronous condenser %d"), workspace->GetElementNumber(ID_SYNCMOTOR)));
705 workspace->IncrementElementNumber(ID_SYNCMOTOR);
706 elementList.push_back(newSyncCondenser);
707 statusBarText = _(
"Insert Synchronous Condenser: Click on a bus, ESC to cancel.");
710 case ID_ADDMENU_EMTELEMENT: {
711 auto newEMTElement = std::make_shared<EMTElement>(wxString::Format(_(
"Electromagnetic Transient %d"), workspace->GetElementNumber(ID_EMTELEMENT)));
712 workspace->IncrementElementNumber(ID_EMTELEMENT);
713 elementList.push_back(newEMTElement);
714 statusBarText = _(
"Insert Electromagnetic Transient Element: Click on a bus, ESC to cancel.");
717 case ID_ADDMENU_TEXT: {
719 auto newText = std::make_shared<Text>();
720 textList.push_back(newText);
721 statusBarText = _(
"Insert Label: Click to insert, ESC to cancel.");
727 workspace->SetElementList(elementList);
728 workspace->SetTextList(textList);
730 workspace->SetWorkspaceMode(Workspace::WorkspaceMode::MODE_INSERT);
732 workspace->SetWorkspaceMode(Workspace::WorkspaceMode::MODE_INSERT_TEXT);
733 workspace->SetStatusBarText(statusBarText);
740void MainFrame::OnImportClick(wxRibbonButtonBarEvent& event)
743 EnableCurrentProjectRibbon();
746 Workspace* newWorkspace =
new Workspace(m_auiNotebook, wxString::Format(_(
"New project %d"), m_projectNumber), this->GetStatusBar(), this->GetAuiNotebook());
748 newWorkspace->GetProperties()->SetGeneralPropertiesData(m_generalProperties->GetGeneralPropertiesData());
749 newWorkspace->SetColourTheme();
751 m_workspaceList.push_back(newWorkspace);
753 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL,
true);
754 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL,
false);
756 m_auiNotebook->AddPage(newWorkspace, newWorkspace->GetName(),
true);
757 newWorkspace->Redraw();
762 if (importForm.ShowModal() == wxID_OK) {
763 m_auiNotebook->Layout();
764 newWorkspace->Redraw();
765 newWorkspace->SetJustOpened(
true);
770void MainFrame::NotebookPageClosed(wxAuiNotebookEvent& event)
772 if (m_auiNotebook->GetPageCount() == 0) EnableCurrentProjectRibbon(
false);
776void MainFrame::NotebookPageClosing(wxAuiNotebookEvent& event)
778 auto it = m_workspaceList.begin();
779 while (it != m_workspaceList.end()) {
780 if (*it == m_auiNotebook->GetCurrentPage()) {
782 m_workspaceList.erase(it);
793void MainFrame::OnRotClockClick(wxRibbonButtonBarEvent& event)
796 if (workspace) { workspace->RotateSelectedElements(); }
799void MainFrame::OnRotCounterClockClick(wxRibbonButtonBarEvent& event)
802 if (workspace) { workspace->RotateSelectedElements(
false); }
805void MainFrame::OnGeneralSettingsClick(wxRibbonButtonBarEvent& event)
808 genPropForm.SetInitialSize();
809 if (genPropForm.ShowModal() == wxID_OK) {
810 BuildElementsToolBar(m_generalProperties->GetGeneralPropertiesData().elementsToolbar);
812 for (
auto& workspace : m_workspaceList) {
813 workspace->GetProperties()->SetGeneralPropertiesData(m_generalProperties->GetGeneralPropertiesData());
814 workspace->GetProperties()->SetGUIColourTheme();
815 workspace->SetColourTheme();
816 workspace->UpdateTextElements();
821void MainFrame::OnSimulationSettingsClick(wxRibbonButtonBarEvent& event)
826 simulSettingsForm.SetInitialSize();
827 simulSettingsForm.ShowModal();
830void MainFrame::OnFreqResponseClick(wxRibbonButtonBarEvent& event)
833 if (workspace) { workspace->RunFrequencyResponse(); }
835void MainFrame::OnHarmDistortionsClick(wxRibbonButtonBarEvent& event)
838 if (workspace) { workspace->RunHarmonicDistortion(); }
841void MainFrame::OnStabilityDropdown(wxRibbonButtonBarEvent& event) {
event.PopupMenu(m_stabilityMenu); }
843void MainFrame::OnStabilityMenuClick(wxCommandEvent& event)
848 auto elementList = workspace->GetElementList();
850 switch (event.GetId()) {
851 case ID_STABMENU_LIST: {
853 stabEventList.ShowModal();
859void MainFrame::OnSnapshotMenuClick(wxCommandEvent& event)
864 auto elementList = workspace->GetElementList();
866 switch (event.GetId()) {
867 case ID_SNAPSHOTMENU_LIST: {
869 wxFileDialog saveFileDialog(
this, _(
"Save diagram as SVG"),
"",
"",
"SVG files (*.svg)|*.svg",
870 wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
871 if (saveFileDialog.ShowModal() == wxID_CANCEL)
return;
872 workspace->ExportAsSVG(saveFileDialog.GetPath());
878int MainFrame::RunPSPTest()
880 wxMessageOutput::Get()->Printf(
"Main frame setup OK!\n");
883 EnableCurrentProjectRibbon();
885 Workspace* newWorkspace =
new Workspace(
this, wxString::Format(_(
"New project %d"), m_projectNumber),
886 this->GetStatusBar(), this->GetAuiNotebook());
890 m_workspaceList.push_back(newWorkspace);
892 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL,
true);
893 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL,
false);
895 m_auiNotebook->AddPage(newWorkspace, newWorkspace->GetName(),
true);
896 newWorkspace->Redraw();
898 wxMessageOutput::Get()->Printf(
"Project creation OK!\n");
899 wxMessageOutput::Get()->Printf(
"Test done!\n");
903void MainFrame::OnClose(wxCloseEvent& event)
907 wxMessageDialog dialog(
this,
908 _(
"Are you sure you want to close the program?\nAny unsaved changes will be lost."),
909 _(
"Closing PSP-UFU..."),
910 wxYES_NO | wxICON_EXCLAMATION);
912 if (dialog.ShowModal() == wxID_YES) {
913 if (!m_workspaceList.empty())
914 m_workspaceList[m_workspaceList.size() - 1]->Show();
917 else event.Skip(
false);
919void MainFrame::OnHeatmapClick(wxRibbonButtonBarEvent& event)
923 const bool enabled = workspace->IsHeatMapEnable();
924 m_ribbonButtonBarReports->ToggleButton(ID_RIBBON_HEATMAP, !enabled);
925 workspace->EnableHeatMap(!enabled);
928void MainFrame::OnGridClick(wxRibbonButtonBarEvent& event)
932 const bool enabled = workspace->IsGridEnabled();
933 m_ribbonButtonBarCircuit->ToggleButton(ID_RIBBON_GRID, !enabled);
934 workspace->EnableGrid(!enabled);
938void MainFrame::OnAlignClick(wxRibbonButtonBarEvent& event)
942 workspace->AlignSelectedToGrid();
945void MainFrame::OnNotebookPageChanged(wxAuiNotebookEvent& event)
949 m_ribbonButtonBarCircuit->ToggleButton(ID_RIBBON_GRID, workspace->IsGridEnabled());
950 m_ribbonButtonBarReports->ToggleButton(ID_RIBBON_HEATMAP, workspace->IsHeatMapEnable());
951 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_ENABLESOL, workspace->IsContinuousCalculationActive());
952 m_ribbonButtonBarContinuous->ToggleButton(ID_RIBBON_DISABLESOL, !workspace->IsContinuousCalculationActive());
955void MainFrame::OnProjectSettingsClick(wxRibbonButtonBarEvent& event)
961 workspace->UpdateHeatMap();
965void MainFrame::OnSnapshotDropdown(wxRibbonButtonBarEvent& event)
967 event.PopupMenu(m_snapshotMenu);
969void MainFrame::OnLabelMngrClick(wxRibbonButtonBarEvent& event)
975 if (labelMngr.ShowModal() == wxID_OK) {
976 workspace->UpdateTextElements();
982void MainFrame::PositionElementsToolBar()
984 if (!m_elementsToolBar)
return;
995 wxPoint pos = GetPosition() + wxPoint(20, m_ribbonBar->GetSize().GetHeight() + 70);
996 m_elementsToolBar->Move(pos);
999void MainFrame::BuildElementsToolBar(ElementsToolbar style)
1001 if (style != NONE) {
1002 delete m_elementsToolBar;
1005 PositionElementsToolBar();
1006 m_elementsToolBarPositioned =
true;
1008 m_elementsToolBar->Show();
1009 m_elementsToolBar->Raise();
1012 if (!m_elementsToolBar)
return;
1013 m_elementsToolBar->Hide();
1017void MainFrame::OnElementsToolBarClosed()
1019 if (m_generalProperties) {
1020 auto data = m_generalProperties->GetGeneralPropertiesData();
1021 data.elementsToolbar = NONE;
1022 m_generalProperties->SetGeneralPropertiesData(data);
1023 PropertiesData::SaveConfigFile(data);
This class is responsible to manage the charts generated in the transient electromechanical studies.
Form that shows the results of power flow and fault calculations.
Base class of all elements of the program. This class is responsible for manage graphical and his dat...
wxPoint2DDouble GetPosition() const
Get the element position.
virtual void StartMove(wxPoint2DDouble position)
Update the element attributes related to the movement.
bool IsSelected() const
Checks if the element is selected.
Save and opens the projects created on disk.
~MainFrame()
Default destructor.
MainFrame()
Default constructor.
Abstract class of power elements.
General and simulation data manager.
This class manages the graphical and power elements. It is responsible for handling the user's intera...