00001
00002
00003
00004
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& ,
00114 const sheet_t::monitor_value_t& set_proc,
00115 const ModelType& new_value,
00116 touch_set_t ,
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
00135
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 }
00175
00176
00177
00178 template <class AP, class P>
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
00358
00359 platform_display_type display_token(insert(get_main_display(),
00360 parent.display_token_m, *widget));
00361
00362
00363
00364
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
00380
00381
00382
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
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& ,
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
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
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
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 }
00550
00551
00552
00553 #endif
00554
00555