Mirror reflection library 0.5.13
|
00001 00011 #ifndef MIRROR_UTILS_WX_GUI_FACTORY_1011291729_HPP 00012 #define MIRROR_UTILS_WX_GUI_FACTORY_1011291729_HPP 00013 00014 #include <mirror/config.hpp> 00015 00016 // wx gui factory-related 00017 #include <mirror/utils/wx_gui_factory/dialog_interface.hpp> 00018 #include <mirror/utils/wx_gui_factory/data.hpp> 00019 #include <mirror/utils/wx_gui_factory/default.hpp> 00020 #include <mirror/utils/wx_gui_factory/basic.hpp> 00021 #include <mirror/utils/wx_gui_factory/boolean.hpp> 00022 #include <mirror/utils/wx_gui_factory/manager.hpp> 00023 #include <mirror/utils/wx_gui_factory/enumerator.hpp> 00024 #include <mirror/utils/wx_gui_factory/initlist.hpp> 00025 00026 #include <wx/dialog.h> 00027 #include <wx/filedlg.h> 00028 #include <wx/statline.h> 00029 00030 #include <stdexcept> 00031 00032 MIRROR_NAMESPACE_BEGIN 00033 namespace aux { 00034 00035 // Base template class for other factory dialogs 00036 template <class SourceTraits> 00037 class wx_gui_factory_dialog_base 00038 : public wxDialog 00039 { 00040 protected: 00041 // the ok button 00042 wxButton* ok_button; 00043 // 00044 // the input widgets data 00045 typedef wx_input_gui_data data_type; 00046 data_type input_data; 00047 // The input source traits 00048 SourceTraits source_traits; 00049 // data for the dialog buttons 00050 data_type button_data; 00051 private: 00052 00053 /* prepares the dialog and creates the necessary widgets 00054 * before creating the input widgets by the factory template 00055 * and the factory generator utility 00056 */ 00057 data_type make_input_data(void) 00058 { 00059 // 00060 // get the pointer to the dialog 00061 wxDialog* dialog = this; 00062 // 00063 // make the main panel of the dialog where all 00064 // the input controls are going to be 00065 wxPanel* main_panel = new wxPanel(dialog, wxID_ANY); 00066 main_panel->SetExtraStyle( 00067 main_panel->GetExtraStyle() | 00068 wxWS_EX_VALIDATE_RECURSIVELY 00069 ); 00070 // create the sizer for the input controls 00071 wxSizer* main_sizer = new wxBoxSizer(wxVERTICAL); 00072 main_panel->SetSizer(main_sizer); 00073 // 00074 // create the dialog's main sizer 00075 wxSizer* dialog_sizer = new wxBoxSizer(wxVERTICAL); 00076 // dialog top padding 00077 dialog_sizer->AddSpacer(SourceTraits::padding_top()); 00078 // the main panel where the input widgets 00079 // will be created and placed 00080 dialog_sizer->Add(main_panel, 1, wxEXPAND); 00081 // a horizontal line with minor spacers 00082 dialog_sizer->AddSpacer(SourceTraits::minor_spacer_width()); 00083 dialog_sizer->Add( 00084 new wxStaticLine( 00085 main_panel, 00086 wxID_ANY, 00087 wxDefaultPosition, 00088 wxDefaultSize, 00089 wxLI_HORIZONTAL 00090 ) 00091 ); 00092 dialog_sizer->AddSpacer(SourceTraits::minor_spacer_width()); 00093 // standard button set 00094 wxBoxSizer* button_sizer = new wxBoxSizer(wxHORIZONTAL); 00095 button_sizer->AddStretchSpacer(); 00096 button_sizer->Add(new wxButton(dialog, wxID_OPEN)); 00097 button_sizer->Add(new wxButton(dialog, wxID_SAVE)); 00098 button_sizer->AddSpacer(SourceTraits::major_spacer_width()); 00099 button_sizer->Add(new wxButton(dialog, wxID_CLEAR)); 00100 button_sizer->AddSpacer(SourceTraits::major_spacer_width()); 00101 ok_button = new wxButton(dialog, wxID_OK); 00102 button_sizer->Add(ok_button); 00103 button_sizer->AddSpacer(SourceTraits::minor_spacer_width()); 00104 button_sizer->Add(new wxButton(dialog, wxID_CANCEL)); 00105 // add the button sizer 00106 dialog_sizer->Add(button_sizer, 0, wxEXPAND); 00107 // bottom padding 00108 dialog_sizer->AddSpacer(SourceTraits::padding_bottom()); 00109 // 00110 // create the dialog's outer sizer 00111 wxSizer* dialog_outer_sizer = new wxBoxSizer(wxHORIZONTAL); 00112 // left padding 00113 dialog_outer_sizer->AddSpacer(SourceTraits::padding_left()); 00114 // the dialog vertical sizer 00115 dialog_outer_sizer->Add(dialog_sizer, 1, wxEXPAND); 00116 // right padding 00117 dialog_outer_sizer->AddSpacer(SourceTraits::padding_right()); 00118 // assign the sizer 00119 dialog->SetSizer(dialog_outer_sizer); 00120 // 00121 // return the data 00122 return data_type( 00123 main_panel, 00124 main_sizer, 00125 SourceTraits::make_root_data_id() 00126 ); 00127 } 00128 00129 void clear_input(wxCommandEvent& evt) 00130 { 00131 input_data->clear_input(); 00132 } 00133 00134 bool pick_state_file_path(wxString& path, bool saving) 00135 { 00136 wxFileDialog file_dialog( 00137 this, 00138 wxGetTranslation(wxT("Choose a file")), 00139 wxEmptyString, // default dir 00140 wxEmptyString, // default filename 00141 wxT("*.xml"), // default wildcard 00142 saving ? wxFD_SAVE : wxFD_OPEN 00143 ); 00144 if(file_dialog.ShowModal() == wxOK) 00145 { 00146 path = file_dialog.GetPath(); 00147 } 00148 return false; 00149 } 00150 00151 void load_state(wxCommandEvent& evt) 00152 { 00153 wxString file_path; 00154 if(pick_state_file_path(file_path, false)) 00155 { 00156 wxXmlDocument xmldoc(file_path); 00157 // TODO 00158 //input_data->load_state(xmldoc); 00159 } 00160 } 00161 00162 void save_state(wxCommandEvent& evt) 00163 { 00164 wxString file_path; 00165 if(pick_state_file_path(file_path, true)) 00166 { 00167 wxXmlDocument xmldoc; 00168 input_data->save_state(xmldoc); 00169 xmldoc.Save(file_path); 00170 } 00171 } 00172 protected: 00173 // creates the dialog and prepares the basic widgets 00174 wx_gui_factory_dialog_base( 00175 wxWindow* parent_window, 00176 const wxString& title 00177 ): wxDialog( 00178 parent_window, 00179 wxID_ANY, 00180 title, 00181 wxDefaultPosition, 00182 wxDefaultSize, 00183 wxDEFAULT_DIALOG_STYLE | 00184 wxRESIZE_BORDER 00185 ), ok_button(nullptr) 00186 , input_data(make_input_data()) 00187 , source_traits(input_data) 00188 { 00189 Connect( 00190 wxID_SAVE, 00191 wxEVT_COMMAND_BUTTON_CLICKED, 00192 wxCommandEventHandler( 00193 wx_gui_factory_dialog_base::save_state 00194 ) 00195 ); 00196 Connect( 00197 wxID_OPEN, 00198 wxEVT_COMMAND_BUTTON_CLICKED, 00199 wxCommandEventHandler( 00200 wx_gui_factory_dialog_base::load_state 00201 ) 00202 ); 00203 Connect( 00204 wxID_CLEAR, 00205 wxEVT_COMMAND_BUTTON_CLICKED, 00206 wxCommandEventHandler( 00207 wx_gui_factory_dialog_base::clear_input 00208 ) 00209 ); 00210 } 00211 00212 // post construction initialization 00213 /* Called by the derived classes after the construction 00214 * This function takes care of things like the final 00215 * size recalculation and enables recursive validation 00216 * for the input widgets 00217 */ 00218 void post_construct_init(void) 00219 { 00220 GetSizer()->SetSizeHints(this); 00221 SetMinSize(GetSize()); 00222 SetExtraStyle( 00223 GetExtraStyle() | 00224 wxWS_EX_VALIDATE_RECURSIVELY 00225 ); 00226 button_data = data_type( 00227 input_data, 00228 ok_button, 00229 input_data->child_count(), 00230 SourceTraits::make_helper_data_id() 00231 ); 00232 input_data->init_navigation(); 00233 } 00234 00235 // Shows the dialog and returns true if all input data is OK 00236 /* Note this works properly only if the validators for 00237 * the input widgets are set-up properly 00238 */ 00239 bool get_input(void) 00240 { 00241 Center(); 00242 return (ShowModal() == wxID_OK); 00243 } 00244 }; 00245 00246 } // namespace aux 00247 00249 00257 template <class Product, class SourceTraits> 00258 class wx_gui_factory_dialog 00259 : public aux::wx_gui_factory_dialog_base<SourceTraits> 00260 , public aux::wx_gui_factory_dialog_intf<Product> 00261 { 00262 private: 00263 static wxString make_title(wxString title) 00264 { 00265 if(title.empty()) 00266 { 00267 // TODO: make up some title if empty 00268 } 00269 return title; 00270 } 00271 00272 // we'll need the a factory maker 00273 typedef typename mirror::factory_maker< 00274 mirror::wx_input_gui, 00275 mirror::aux_input_source, 00276 mirror::wx_enum_gui, 00277 SourceTraits 00278 > make; 00279 00280 // the factory which will be used to create instances of Product 00281 typename make::template factory<Product>::type fact; 00282 public: 00283 wx_gui_factory_dialog( 00284 const wxString& dialog_title, 00285 wxWindow* parent_window = (wxWindow*)nullptr 00286 ): aux::wx_gui_factory_dialog_base<SourceTraits>( 00287 parent_window, 00288 make_title(dialog_title) 00289 ), fact(this->input_data) 00290 { 00291 // initialize the base dialog 00292 this->post_construct_init(); 00293 } 00294 00296 Product* new_(void) 00297 { 00298 // if we've got some input 00299 if(this->get_input()) 00300 { 00301 // use the factory to create 00302 // an instance of Product 00303 return fact.new_(); 00304 } 00305 return nullptr; 00306 } 00307 00308 Product create(void) 00309 { 00310 // if we've aint't got any input 00311 if(!this->get_input()) 00312 throw std::runtime_error("Aborted by user"); 00313 // use the factory to create 00314 // an instance of Product 00315 return fact(); 00316 } 00317 }; 00318 00319 namespace aux { 00320 00321 template <typename Product, class SourceTraits> 00322 inline wx_gui_factory_dialog_intf<Product>* make_wx_gui_factory_dialog( 00323 wxWindow* parent, 00324 const wxString& caption 00325 ) 00326 { 00327 return new mirror::wx_gui_factory_dialog<Product, SourceTraits>( 00328 caption, 00329 parent 00330 ); 00331 } 00332 00333 } // namespace aux 00334 MIRROR_NAMESPACE_END 00335 00336 #endif //include guard 00337