1 #include "gui/windows/Widgets.h"
2 #include "gui/MainLoop.h"
3 #include "gui/Utils.h"
4 #include "thread/CheckFunction.h"
5 #include <wx/msgdlg.h>
6 #include <wx/propgrid/propgrid.h>
7 #include <wx/propgrid/props.h>
8 #include <wx/sizer.h>
9 #include <wx/stattext.h>
10 
11 NAMESPACE_SPH_BEGIN
12 
FloatTextCtrl(wxWindow * parent,const double value,const Interval range)13 FloatTextCtrl::FloatTextCtrl(wxWindow* parent, const double value, const Interval range)
14     : value(value)
15     , range(range) {
16 
17     lastValidValue = value;
18 
19     wxValidator* validator = wxFloatProperty::GetClassValidator();
20     this->Create(parent,
21         wxID_ANY,
22         std::to_string(value),
23         wxDefaultPosition,
24         wxSize(100, 25),
25         wxTE_PROCESS_ENTER | wxTE_RIGHT,
26         *validator);
27 
28     this->Bind(wxEVT_TEXT_ENTER, [this](wxCommandEvent& evt) {
29         this->validate();
30         evt.Skip();
31     });
32     this->Bind(wxEVT_KILL_FOCUS, [this](wxFocusEvent& evt) {
33         this->validate();
34         evt.Skip();
35     });
36 
37     this->validate();
38 }
39 
setValue(double newValue)40 void FloatTextCtrl::setValue(double newValue) {
41     value = range.clamp(newValue);
42     lastValidValue = value;
43 
44     wxFloatProperty prop;
45     wxVariant variant(value);
46     this->ChangeValue(prop.ValueToString(variant));
47 }
48 
validate()49 void FloatTextCtrl::validate() {
50     wxFloatProperty prop;
51     wxVariant variant = this->GetValue();
52     wxPGValidationInfo info;
53     if (!prop.ValidateValue(variant, info)) {
54         value = lastValidValue;
55     } else {
56         value = float(variant.GetDouble());
57     }
58 
59     value = range.clamp(value);
60 
61     if (onValueChanged && value != lastValidValue) {
62         const bool validated = onValueChanged(value);
63         if (!validated) {
64             value = lastValidValue;
65         }
66     }
67 
68     lastValidValue = value;
69     variant = double(value);
70     this->ChangeValue(prop.ValueToString(variant));
71 }
72 
73 class WaitDialog : public wxDialog {
74 public:
WaitDialog(wxWindow * parent,const String & message)75     WaitDialog(wxWindow* parent, const String& message)
76         : wxDialog(parent, wxID_ANY, "Info", wxDefaultPosition, wxDefaultSize, wxCAPTION | wxSYSTEM_MENU) {
77         const wxSize size = wxSize(320, 90);
78         this->SetSize(size);
79         wxStaticText* text = new wxStaticText(this, wxID_ANY, message.toUnicode());
80         wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
81         sizer->AddStretchSpacer();
82         sizer->Add(text, 1, wxALIGN_CENTER_HORIZONTAL);
83         sizer->AddStretchSpacer();
84         this->SetSizer(sizer);
85         this->Layout();
86         this->CentreOnScreen();
87     }
88 };
89 
ClosablePage(wxWindow * parent,const String & label)90 ClosablePage::ClosablePage(wxWindow* parent, const String& label)
91     : wxPanel(parent, wxID_ANY)
92     , label(label) {}
93 
close()94 bool ClosablePage::close() {
95     CHECK_FUNCTION(CheckFunction::MAIN_THREAD | CheckFunction::NO_THROW);
96     if (this->isRunning()) {
97         const int retval = messageBox(
98             capitalize(label) + " is currently in progress. Do you want to stop it and close the window?",
99             "Stop?",
100             wxYES_NO | wxCENTRE);
101         if (retval == wxYES) {
102             this->stop();
103             dialog = new WaitDialog(this, "Waiting for " + label + " to finish ...");
104             dialog->ShowModal();
105             this->quit();
106             return true;
107         } else {
108             return false;
109         }
110     } else {
111         return true;
112     }
113 }
114 
onStopped()115 void ClosablePage::onStopped() {
116     if (dialog) {
117         executeOnMainThread([weakDialog = wxWeakRef<WaitDialog>(dialog)] {
118             if (weakDialog) {
119                 weakDialog->EndModal(0);
120             }
121         });
122     }
123 }
124 
125 
126 NAMESPACE_SPH_END
127