Mirror reflection library 0.5.13

mirror/utils/wx_gui_factory.hpp

Go to the documentation of this file.
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 

Copyright © 2006-2011 Matus Chochlik, University of Zilina, Zilina, Slovakia.
<matus.chochlik -at- fri.uniza.sk>
<chochlik -at -gmail.com>
Documentation generated on Fri Dec 16 2011 by Doxygen (version 1.7.3).
Important note: Although the 'boostified' version of Mirror uses the Boost C++ libraries Coding Guidelines and is implemented inside of the boost namespace, it IS NOT an officially reviewed and accepted Boost library. Mirror is being developed with the intention to be submitted for review for inclusion to the Boost C++ libraries.