stlab.adobe.com Adobe Systems Incorporated

widget_factory.hpp

Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2007 Adobe Systems Incorporated
00003     Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
00004     or a copy at http://stlab.adobe.com/licenses.html)
00005 */
00006 
00007 /*************************************************************************************************/
00008 
00009 #ifndef ADOBE_WIDGET_FACTORY_HPP
00010 #define ADOBE_WIDGET_FACTORY_HPP
00011 
00012 /*************************************************************************************************/
00013 
00014 #include <boost/concept_check.hpp>
00015 #include <boost/utility/enable_if.hpp>
00016 #include <boost/type_traits.hpp>
00017 #include <boost/mpl/bool_fwd.hpp>
00018 #include <boost/signals/connection.hpp>
00019 
00020 #include <adobe/adam.hpp>
00021 #include <adobe/any_regular.hpp>
00022 #include <adobe/eve.hpp>
00023 #include <adobe/eve_evaluate.hpp>
00024 #include <adobe/poly_controller.hpp>
00025 #include <adobe/poly_placeable.hpp>
00026 #include <adobe/poly_view.hpp>
00027 
00028 #include <adobe/future/widgets/headers/factory.hpp>
00029 #include <adobe/future/widgets/headers/widget_tokens.hpp>
00030 
00031 /*************************************************************************************************/
00032 
00033 namespace adobe {
00034 
00035 /*************************************************************************************************/
00036 
00037 typedef std::vector<name_t> touch_set_t;
00038 
00039 struct factory_token_t;
00040 
00041 /*************************************************************************************************/
00042 
00043 template <typename FactoryToken>
00044 sheet_t& token_layout_sheet(const FactoryToken& token)
00045 {
00046     return token.client_holder_m.layout_sheet_m;
00047 }
00048 
00049 /*************************************************************************************************/
00050 
00051 template <typename FactoryToken>
00052 sheet_t& token_property_model(const FactoryToken& token)
00053 {
00054     return token.sheet_m;
00055 }
00056 
00057 /*************************************************************************************************/
00058 
00059 template <typename FactoryToken>
00060 assemblage_t& token_assemblage(const FactoryToken& token)
00061 {
00062     return token.client_holder_m.assemblage_m;
00063 }
00064 
00065 /*************************************************************************************************/
00066 
00067 template <typename FactoryToken>
00068 behavior_t& token_layout_behavior(const FactoryToken& token)
00069 {
00070     return token.client_holder_m.root_behavior_m;
00071 }
00072 
00073 /****************************************************************************************************/
00074 
00075 namespace implementation {
00076 
00077 /*************************************************************************************************/
00078 
00079 inline void sheet_set(sheet_t*             sheet,
00080                       name_t               name,
00081                       const any_regular_t& value)
00082 {
00083     sheet->set(name, value);
00084     sheet->update();
00085 }
00086 
00087 /*************************************************************************************************/
00088 
00089 size_enum_t enumerate_size(const name_t& size);
00090 
00091 /*************************************************************************************************/
00092 
00093 theme_t size_to_theme(size_enum_t size);
00094 
00095 /*************************************************************************************************/
00096 
00097 touch_set_t touch_set(const dictionary_t& parameters);
00098 
00099 /*************************************************************************************************/
00100 
00101 template <typename ModelType>
00102 inline void touch_set_update(sheet_t&                sheet,
00103                      const sheet_t::monitor_value_t& set_proc,
00104                      const ModelType&                new_value,
00105                      touch_set_t                     touch_set,
00106                      behavior_t&                     layout_behavior)
00107 {
00108     if (!touch_set.empty())
00109         sheet.touch(&touch_set.front(), &touch_set.front() + touch_set.size());
00110 
00111     set_proc(any_regular_t(new_value));
00112 
00113     layout_behavior();
00114 }
00115 
00116 /*************************************************************************************************/
00117 
00118 inline sheet_t::monitor_value_t obtain_set_cell_from_controller_proc(sheet_t& sheet, name_t cell)
00119 {
00120     return boost::bind(&implementation::sheet_set,
00121                        &sheet,
00122                        cell,
00123                        _1);
00124 }
00125 
00126 /*************************************************************************************************/
00127 
00128 } // namespace implementation
00129 
00130 /*************************************************************************************************/
00131 
00132 template <class AP, class P> // P models poly_placeable_t or poly_placeable_twopass_t,
00133 inline eve_t::iterator attach_placeable(eve_t::iterator     parent_token,
00134                                                P&                         widget,
00135                                                const dictionary_t&        parameters,
00136                                                const factory_token_t&     token,
00137                                                bool                       is_container,
00138                                                const layout_attributes_t& layout_attributes)
00139 {
00140     AP* element = new AP(&widget);
00141     token.client_holder_m.assemblage_m.cleanup(boost::bind(delete_ptr(), element));
00142 
00143     layout_attributes_t attributes = layout_attributes;
00144     apply_layout_parameters(attributes, parameters);
00145 
00146     return token.client_holder_m.eve_m.add_placeable(   parent_token,
00147                                                         attributes,
00148                                                         is_container,
00149                                                         poly_cast<poly_placeable_t&>(*element));
00150 }
00151 
00152 /*************************************************************************************************/
00153 
00154 template <typename Controller, typename FactoryToken>
00155 void attach_monitor(Controller&         controller,
00156                     name_t              cell,
00157                     sheet_t&              sheet,
00158                     const FactoryToken& token,
00159                     const dictionary_t& parameters)
00160 {
00161     sheet_t::monitor_value_t set_cell_from_controller_proc =
00162         implementation::obtain_set_cell_from_controller_proc(sheet, cell);
00163 
00164     typedef typename ControllerConcept<Controller>::model_type controller_model_type;
00165 
00166     boost::function<void (const controller_model_type&)> setter
00167         (boost::bind(&implementation::touch_set_update<controller_model_type>,
00168                                                        boost::ref(sheet),
00169                                                        set_cell_from_controller_proc,
00170                                                        _1,
00171                                                        implementation::touch_set(parameters),
00172                                                        boost::ref(token_layout_behavior(token))));
00173 
00174      controller.monitor(setter);
00175 }
00176 
00177 /*************************************************************************************************/
00183 template <typename ModelType>
00184 class splitter_controller_adaptor
00185 {
00186 public:
00187     typedef ModelType model_type;
00188 
00189     splitter_controller_adaptor(sheet_t&       sheet,
00190                                 behavior_t&    layout_behavior,
00191                                 const array_t& cell_set,
00192                                 modifiers_t    pass_thru = modifiers_t()) :
00193         sheet_m(&sheet),
00194         layout_behavior_m(&layout_behavior),
00195         cell_set_m(cell_set),
00196         pass_thru_m(pass_thru)
00197     { }
00198 
00199     void operator()(const model_type& value,
00200                     modifiers_t       modifiers = modifiers_t())
00201     {
00202         if ((pass_thru_m & modifiers) == 0)
00203             return;
00204 
00205         array_t::iterator iter(cell_set_m.begin());
00206         array_t::iterator last(cell_set_m.end());
00207 
00208         while (iter != last)
00209         {
00210             sheet_m->set(iter->cast<name_t>(), value);
00211 
00212             ++iter;
00213         }
00214 
00215         sheet_m->update();
00216 
00217         (*layout_behavior_m)();
00218     }
00219 
00220 private:
00221     sheet_t*       sheet_m;
00222     behavior_t*    layout_behavior_m;
00223     array_t        cell_set_m;
00224     modifiers_t    pass_thru_m;
00225 };
00226 
00227 /*************************************************************************************************/
00228 
00229 template <typename View>
00230 struct force_relayout_view_adaptor
00231 {
00232     typedef typename ViewConcept<View>::model_type model_type;
00233 
00234     force_relayout_view_adaptor(View& view, visible_change_queue_t& queue) :
00235         view_m(&view),
00236         queue_m(&queue)
00237     { }
00238 
00239     void display(const model_type& value)
00240     {
00241         assert(view_m && queue_m);
00242 
00243         ViewConcept<View>::display(*view_m, value);
00244 
00245         queue_m->force_m = true;
00246     }
00247 
00248     View*                   view_m;
00249     visible_change_queue_t* queue_m;
00250 };
00251 
00252 /*************************************************************************************************/
00253 
00254 template <class View, class Sheet>
00255 void attach_view(assemblage_t& assemblage,
00256                  name_t        cell,
00257                  View&         control,
00258                  Sheet&        sheet)
00259 {
00260     poly_view_t* view(new poly_view_t(boost::ref(control)));
00261     assemblage_cleanup_ptr(assemblage, view);
00262     sheet_t::monitor_value_t m(boost::bind(&ViewConcept<poly_view_t>::display,
00263                                            boost::ref(*view), _1));
00264     typename Sheet::connection_t c(sheet.monitor_value(cell, m));
00265     assemblage_cleanup_connection(assemblage, c);
00266 }
00267 
00268 /*************************************************************************************************/
00269 
00270 template <class Controller>
00271 void attach_enabler(assemblage_t& assemblage, name_t cell, Controller& control, sheet_t& sheet,
00272                     const dictionary_t& parameters)
00273 {
00274     poly_controller_t* controller(new poly_controller_t(&control));
00275     assemblage_cleanup_ptr(assemblage, controller);
00276     touch_set_t v(implementation::touch_set(parameters));
00277     sheet_t::monitor_enabled_t
00278         m(boost::bind(&ControllerConcept<poly_controller_t>::enable, boost::ref(*controller), _1));
00279 
00280     typename sheet_t::connection_t c;
00281     if(v.empty()) c = sheet.monitor_enabled(cell, NULL, NULL, m);
00282     else c = sheet.monitor_enabled(cell, &v[0], &v[0] + v.size(), m);
00283     assemblage_cleanup_connection(assemblage, c);
00284 }
00285 
00286 /*************************************************************************************************/
00287 
00288 template <typename T, typename P>
00289 inline widget_node_t create_and_hookup_widget(const dictionary_t& parameters,
00290                                        const widget_node_t&       parent,
00291                                        const factory_token_t&     token,
00292                                        bool                       is_container,
00293                                        const layout_attributes_t& layout_attributes)
00294 {
00295     size_enum_t   size(parameters.count(key_size) ?
00296                        implementation::enumerate_size(
00297                            get_value(parameters, key_size).cast<name_t>()) : parent.size_m);
00298 
00299     T*              widget(NULL);
00300     create_widget(parameters, size, widget);
00301     token.client_holder_m.assemblage_m.cleanup(boost::bind(delete_ptr(),widget));
00302 
00303     //
00304     // Call display_insertion to embed the new widget within the view heirarchy
00305     //
00306     platform_display_type display_token(insert(get_main_display(),
00307                                                parent.display_token_m, *widget));
00308 
00309     //
00310     // As per SF.net bug 1428833, we want to attach the poly_placeable_t
00311     // to Eve before we attach the controller and view to the model
00312     //
00313 
00314     eve_t::iterator eve_token;
00315 
00316     eve_token = attach_placeable<P>(parent.eve_token_m,
00317                                            *widget,
00318                                            parameters,
00319                                            token,
00320                                            is_container,
00321                                            layout_attributes);
00322 
00323     attach_view_and_controller(*widget, parameters, token);
00324 
00325     //
00326     // Return the widget_node_t that comprises the tokens created for
00327     // this widget by the various components
00328     //
00329     //revist: MM, hook up keyboard insertion mechanism
00330     return widget_node_t(size, eve_token, display_token, parent.keyboard_token_m);
00331 }
00332 
00333 /****************************************************************************************************/
00334 
00335 template <typename Controller, typename FactoryToken>
00336 void couple_controller_to_cell(Controller&           controller,
00337                                name_t                cell,
00338                                sheet_t&              sheet,
00339                                const FactoryToken&   token,
00340                                const dictionary_t&   parameters)
00341 
00342 {
00343     attach_enabler(token_assemblage(token), cell, controller, sheet, parameters);
00344     attach_monitor(controller, cell, sheet, token, parameters);
00345 }
00346 
00347 /*************************************************************************************************/
00348 
00349 template <typename T, typename FactoryToken>
00350 void attach_controller_direct(T&                            control,
00351                               const adobe::dictionary_t&    parameters,
00352                               const FactoryToken&           token,
00353                               adobe::name_t                 cell)
00354 {
00355     if (cell == name_t())
00356         return;
00357 
00358     sheet_t& layout_sheet(token_layout_sheet(token));
00359     sheet_t& property_model(token_property_model(token));
00360 
00361     // is the cell in the layout sheet or the Adam sheet?
00362     if (layout_sheet.count_interface(cell) != 0)
00363         couple_controller_to_cell(control, cell, layout_sheet,
00364                                   token, parameters);
00365     else
00366         couple_controller_to_cell(control, cell, property_model,
00367                                   token, parameters);
00368 }
00369 
00370 /*************************************************************************************************/
00371 
00372 template <typename T, typename FactoryToken>
00373 void attach_controller(T&                         control,
00374                        const adobe::dictionary_t& parameters,
00375                        const FactoryToken&        token,
00376                        adobe::name_t              key_name = key_bind)
00377 {
00378     name_t cell;
00379 
00380     get_value(parameters, key_name, cell);
00381 
00382     attach_controller_direct(control,parameters,token,cell);
00383 }
00384 
00385 /*************************************************************************************************/
00386 
00387 template <typename T, typename FactoryToken>
00388 void attach_view_direct(T&                          control,
00389                         const adobe::dictionary_t&  /*parameters*/,
00390                         const FactoryToken&         token,
00391                         adobe::name_t               cell)
00392 {
00393     if (cell == name_t())
00394         return;
00395 
00396     sheet_t&        layout_sheet(token_layout_sheet(token));
00397     assemblage_t&   assemblage(token_assemblage(token));
00398 
00399     // is the cell in the layout sheet or the Adam sheet?
00400     if (layout_sheet.count_interface(cell) != 0)
00401         attach_view(assemblage, cell, control, layout_sheet);
00402     else
00403         attach_view(assemblage, cell, control, token_property_model(token));
00404 }
00405 
00406 /*************************************************************************************************/
00407 
00408 template <typename T, typename FactoryToken>
00409 void attach_view(T&                         control,
00410                  const adobe::dictionary_t& parameters,
00411                  const FactoryToken&        token,
00412                  adobe::name_t              key_name = key_bind)
00413 {
00414     name_t cell;
00415 
00416     get_value(parameters, key_name, cell);
00417 
00418     attach_view_direct(control, parameters, token, cell);
00419 }
00420 
00421 /*************************************************************************************************/
00422 
00423 template <typename T, typename FactoryToken>
00424 void attach_view_and_controller_direct(T&                           control,
00425                                        const adobe::dictionary_t&   parameters,
00426                                        const FactoryToken&          token,
00427                                        adobe::name_t                widget_cell = name_t(),
00428                                        adobe::name_t                view_cell = name_t(),
00429                                        adobe::name_t                controller_cell = name_t())
00430 {
00431     if (widget_cell == name_t() && view_cell== name_t() && controller_cell== name_t())
00432         return;
00433 
00434     sheet_t& layout_sheet(token_layout_sheet(token));
00435     sheet_t& property_model(token_property_model(token));
00436 
00437     if (widget_cell != name_t())
00438     {
00439         controller_cell = widget_cell;
00440         view_cell = widget_cell;
00441     }
00442 
00443     if (controller_cell != name_t())
00444     {
00445         // is the cell in the layout sheet or the Adam sheet?
00446 
00447         if (layout_sheet.count_interface(controller_cell) != 0)
00448             couple_controller_to_cell(control, controller_cell, layout_sheet,
00449                                       token, parameters);
00450         else
00451             couple_controller_to_cell(control, controller_cell, property_model,
00452                                       token, parameters);
00453     }
00454 
00455     if (view_cell != name_t())
00456     {
00457         // is the cell in the layout sheet or the Adam sheet?
00458 
00459         assemblage_t& assemblage(token_assemblage(token));
00460 
00461         if (layout_sheet.count_interface(view_cell) != 0)
00462             attach_view(assemblage, view_cell, control, layout_sheet);
00463         else
00464             attach_view(assemblage, view_cell, control, token_property_model(token));
00465     }
00466 }
00467 
00468 /*************************************************************************************************/
00469 
00470 template <typename T, typename FactoryToken>
00471 void attach_view_and_controller(T&                  control,
00472                                 const dictionary_t& parameters,
00473                                 const FactoryToken& token,
00474                                 adobe::name_t       bind_cell_name = key_bind,
00475                                 adobe::name_t       bind_view_cell_name = key_bind_view,
00476                                 adobe::name_t       bind_controller_cell_name = key_bind_controller)
00477 {
00478     if (parameters.count(bind_cell_name) == 0 &&
00479         parameters.count(bind_view_cell_name) == 0 &&
00480         parameters.count(bind_controller_cell_name) == 0)
00481         return;
00482 
00483     name_t controller_cell;
00484     name_t view_cell;
00485     name_t widget_cell;
00486 
00487     get_value(parameters, bind_controller_cell_name, controller_cell);
00488     get_value(parameters, bind_view_cell_name, view_cell);
00489     get_value(parameters, bind_cell_name, widget_cell);
00490 
00491     attach_view_and_controller_direct(control, parameters, token, widget_cell, view_cell, controller_cell);
00492 }
00493 
00494 /*************************************************************************************************/
00495 
00496 } // namespace adobe
00497 
00498 /*************************************************************************************************/
00499 
00500 #endif
00501 
00502 /*************************************************************************************************/

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google