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

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