cgv
Loading...
Searching...
No Matches
provider.cxx
1#include <cgv/gui/provider.h>
2#include <cgv/gui/gui_driver.h>
3#include <cgv/gui/trigger.h>
4#include <cgv/base/base_generator.h>
5
6//#include <cgv/os/mutex.h>
7
8#include <iostream>
9#include <set>
10
11namespace cgv {
12 namespace gui {
13
14// update the parent group
16{
17 parent_group->set("label",get_gui_name());
18}
19
21view_ptr provider::add_view_void(const std::string& label, const void* value_ptr, const std::string& value_type, const std::string& gui_type, const std::string& options, const std::string& align)
22{
23 if (parent_group.empty())
24 return view_ptr();
25 return parent_group->add_view_void(label,value_ptr,value_type,gui_type,options,align);
26}
28control_ptr provider::add_control_void(const std::string& label, void* value_ptr, abst_control_provider* acp, const std::string& value_type, const std::string& gui_type, const std::string& options, const std::string& align, void* user_data)
29{
30 if (parent_group.empty())
31 return control_ptr();
32 return parent_group->add_control_void(label,value_ptr,acp,value_type,gui_type,options,align,user_data);
33}
34
35// send pure alignment information
36void provider::align(const std::string& _align)
37{
38 if (!parent_group.empty())
39 parent_group->align(_align);
40}
41
43std::string provider::concat_enum_def(const std::vector<std::string>& names, const std::string& additional_first_name, const std::string& additional_last_name)
44{
45 std::string result = "enums='";
46 if (!additional_first_name.empty())
47 result += additional_first_name + "=-1,";
48 for (unsigned i = 0; i < names.size(); ++i) {
49 if (i > 0)
50 result += ',';
51 result += names[i];
52 }
53 if (!additional_last_name.empty()) {
54 result += ',';
55 result += additional_last_name;
56 }
57 result += "'";
58 return result;
59}
60
61/*
62// add a new group to the given parent group, not supported yet
63gui_group_ptr provider::add_group(const std::string& label, const std::string& group_type, const std::string& options, const std::string& align)
64{
65 if (parent_group.empty())
66 return gui_group_ptr();
67 return parent_group->add_group(label, group_type, options, align);
68}
69*/
70
71// call this to update all views and controls of a member
72void provider::update_member(void* member_ptr)
73{
74 update_views(member_ptr);
75 /*
76 int i=0;
77 do {
78 cgv::gui::control_ptr cp = find_control_void(member_ptr, &i);
79 if (cp) {
80 cp->update();
81 cp->update_views();
82 }
83 else
84 break;
85 ++i;
86 } while (true);
87 i = 0;
88 do {
89 cgv::gui::view_ptr vp = find_view_void(member_ptr, &i);
90 if (vp) {
91 vp->update();
92 vp->update_views();
93 }
94 else
95 break;
96 ++i;
97 } while (true);
98 */
99}
100void update_group_members(cgv::base::group_ptr gp)
101{
102 if (!gp)
103 return;
104 for (unsigned i=0; i<gp->get_nr_children(); ++i) {
105 cgv::base::base_ptr bp = gp->get_child(i);
106 abst_view* v = bp->get_interface<abst_view>();
107 if (v)
108 v->update();
109 cgv::base::group_ptr cgp = bp->cast<cgv::base::group>();
110 if (cgp)
111 update_group_members(cgp);
112 }
113}
114
117{
118 update_group_members(parent_group);
119}
120
121gui_group_ptr provider::add_object_gui(cgv::base::base_ptr object, const std::string& label, const std::string& group_type, const std::string& options, const std::string& align)
122{
123 provider* p = object->get_interface<provider>();
124 if (!p)
125 return gui_group_ptr();
126
127
128 gui_group_ptr g = parent_group->add_group(label, group_type, options, align);
129
130// gui_group_ptr g = add_group(label,group_type,options,align);
132 // p->create_gui();
133 return g;
134}
135
136// inline the gui of another object that must be derived from provider.
138{
139 provider* p = object->get_interface<provider>();
140 if (!p)
141 return;
143 p->parent_provider = this;
144}
145
146// inline the gui of another object that must be derived from provider.
148{
149 provider* p = object->get_interface<provider>();
150 if (!p)
151 return;
152 if (p->get_parent_group() != parent_group) {
154 p->parent_provider = this;
155 }
156 p->create_gui();
157}
158
160gui_group_ptr provider::add_group(const std::string& label, const std::string& group_type, const std::string& options, const std::string& align)
161{
162 if (parent_group.empty())
163 return gui_group_ptr();
164 return parent_group->add_group(label, group_type, options, align);
165}
166
167// add a newly created decorator to the group, not implemented yet
168cgv::base::base_ptr provider::add_decorator(const std::string& label, const std::string& decorator_type, const std::string& options, const std::string& align)
169{
170 if (parent_group.empty())
171 return cgv::base::base_ptr();
172 return parent_group->add_decorator(label, decorator_type, options, align);
173}
174
175// use the current gui driver to append a new button with the given label
176button_ptr provider::add_button(const std::string& label, const std::string& options, const std::string& align)
177{
178 if (parent_group.empty())
179 return button_ptr();
180 return parent_group->add_button(label, options, align);
181}
182
183bool provider::add_tree_node(const std::string& label, bool& toggle, int level, const std::string& a, gui_group_ptr ggp)
184{
185 if (!ggp)
186 ggp = parent_group;
187 int ii = 0;
188 if (a.size() != 1 || a[0] != '\n') {
189 ii += 1;
190 }
191 int size = 24-4*level;
192 int off = size+12;
193 ggp->align(std::string("%x-=")+cgv::utils::to_string(off));
194 connect_copy(ggp->add_control(std::string(toggle?"-":"+"), toggle, "toggle", std::string("w=")+cgv::utils::to_string(size), " ")->value_change,
195 rebind(static_cast<provider*>(this), &provider::post_recreate_gui));
196 ggp->add_decorator(label, "heading", std::string("level=")+cgv::utils::to_string(level), a);
197 return toggle;
198}
199
200std::map<std::pair<const void*,int>, bool>& get_tree_node_toggle_map()
201{
202 static std::map<std::pair<const void*,int>, bool> tree_node_toggle_map;
203 return tree_node_toggle_map;
204}
205
207bool provider::begin_tree_node_void(const std::string& label, const void* value_ptr, int index, bool initial_visibility, const std::string& options, gui_group_ptr ggp)
208{
209 if (!ggp)
210 ggp = parent_group;
211 bool decorated = true; cgv::base::has_property(options, "decorated", decorated, true);
212 int level = 2; cgv::base::has_property(options, "level", level, true);
213 std::string align("\n"); cgv::base::has_property(options, "align", align, true);
214 std::string child_opt; cgv::base::has_property(options, "options", child_opt, true);
215 std::string button_opt; cgv::base::has_property(options, "button_options", button_opt, true);
216 int size = 20;/*- 4 *level*/; cgv::base::has_property(options, "size", size, true);
217 int relative_offset = 12; cgv::base::has_property(options, "relative_offset", relative_offset, true);
218 int off = size+relative_offset;
219
220 if (!button_opt.empty())
221 button_opt = std::string(";")+button_opt;
222 button_opt = std::string("w=")+cgv::utils::to_string(size) + button_opt;
223
224 std::map<std::pair<const void*,int>, bool>::iterator it = get_tree_node_toggle_map().find(std::pair<const void*,int>(value_ptr,index));
225 if (it == get_tree_node_toggle_map().end())
226 get_tree_node_toggle_map()[std::pair<const void*,int>(value_ptr,index)] = initial_visibility;
227
228 bool& toggle = get_tree_node_toggle_map()[std::pair<const void*,int>(value_ptr,index)];
229
231 if (decorated) {
232 ggp->align(std::string("%x-=")+cgv::utils::to_string(off));
233 control_ptr = ggp->add_control(std::string(toggle ? "@-6thinminus" : "@-6thinplus"), toggle, "toggle", button_opt, " ");
234
235 if (!child_opt.empty())
236 child_opt = std::string(";")+child_opt;
237 child_opt = std::string("level=")+cgv::utils::to_string(level) + child_opt;
238 ggp->add_decorator(label, "heading", child_opt, align);
239 }
240 else {
241 control_ptr = ggp->add_control(std::string(toggle ? "@-6thinminus" : "@-6thinplus"), toggle, "toggle", button_opt, align);
242 }
243
244 if (control_ptr) {
245 connect_copy(control_ptr->value_change, rebind(static_cast<provider*>(this), &provider::post_recreate_gui));
246 // if this class is derived from cgv::base::base
247 cgv::base::base* bp = dynamic_cast<cgv::base::base*>(this);
248 // connect to on_set callback
249 if (bp) {
250 connect_copy(control_ptr->value_change, rebind(bp, &cgv::base::base::on_set, cgv::signal::_c((void*)(&toggle))));
251 }
252 }
253 return toggle;
254}
255
257bool& provider::ref_tree_node_visible_flag_void(const void* value_ptr, int index)
258{
259 auto& map = get_tree_node_toggle_map();
260 std::pair<const void*, int> key(value_ptr, index);
261 auto iter = map.find(key);
262 if (iter == map.end())
263 return map[key] = false;
264 else
265 return iter->second;
266}
267
269void provider::end_tree_node_void(const void* value_ptr, int)
270{
271}
272
274bool provider::is_tree_node_visible_void(const void* value_ptr, int index) const
275{
276 return get_tree_node_toggle_map()[std::pair<const void*,int>(value_ptr,index)];
277}
278
280void provider::set_tree_node_visibility_void(const void* value_ptr, int index, bool is_visible)
281{
282 bool& toggle = get_tree_node_toggle_map()[std::pair<const void*,int>(value_ptr,index)];
283 if (toggle != is_visible) {
284 toggle = is_visible;
286 }
287}
288
289// remove a single element from the gui
291{
292 if (!parent_group.empty())
293 parent_group->remove_child(e);
294}
295
296// this method removes all elements in the gui and can be used in a method that rebuilds the complete gui
298{
299 if (!parent_group.empty()) {
300 parent_group->remove_all_children();
301 parent_group->release_all_managed_objects();
302 }
303}
304
307{
308 if (parent_group.empty())
309 return cgv::base::base_ptr();
310 return parent_group->find_element(name);
311}
312
313
314// access to control of untyped member pointer
315control_ptr provider::find_control_void(void* value_ptr, int* idx_ptr)
316{
317 if (parent_group.empty())
318 return control_ptr();
319 return parent_group->find_control_void(value_ptr,idx_ptr);
320}
321
322// access to view of untyped member pointer
323view_ptr provider::find_view_void(void* value_ptr, int* idx_ptr)
324{
325 if (parent_group.empty())
326 return view_ptr();
327 return parent_group->find_view_void(value_ptr,idx_ptr);
328}
329
330
331// default construction
333{
334 parent_provider = 0;
335}
336
337// called by selection_change_cb whenever the gui of this provider is selected
339{
340}
341
342// called by selection_change_cb whenever the gui of this provider is deselected
344{
345}
346
347
348// this is called by the gui group when the selection changes
350{
351 if (new_child == parent_group) {
352 if (selected)
353 on_select();
354 else
355 on_deselect();
356 }
357}
358
359// the gui window sets the parent group through this method
361{
362 if (parent_group) {
363 gui_group_ptr ctrl_grp = parent_group->get_parent()->get_interface<gui_group>();
364 if (ctrl_grp)
365 disconnect(ctrl_grp->on_selection_change, this, &provider::selection_change_cb);
366 }
367 parent_group = _parent_group;
368 gui_group_ptr ctrl_grp = parent_group->get_parent()->get_interface<gui_group>();
369 if (ctrl_grp)
370 connect(ctrl_grp->on_selection_change, this, &provider::selection_change_cb);
371}
372
373
383std::string provider::get_gui_name() const
384{
385 const cgv::base::base* bp = dynamic_cast<const cgv::base::base*>(this);
386 if (bp) {
387 if (const_cast<cgv::base::base*>(bp)->get_named())
388 return const_cast<cgv::base::base*>(bp)->get_named()->get_name();
389 }
390 std::string mp = get_menu_path();
391 if (!mp.empty()) {
392 size_t pos = mp.find_last_of('/');
393 if (pos == std::string::npos || pos == mp.size()-1)
394 return mp;
395 return mp.substr(pos+1);
396 }
397 if (bp)
398 return bp->get_type_name();
399 return "unnamed";
400}
401
402std::string provider::get_parent_type() const
403{
404 return "align_group";
405}
408{
410 if (my_group) {
411 cgv::gui::gui_group_ptr tab_group = my_group->get_parent()->cast<cgv::gui::gui_group>();
412 if (tab_group) {
413 cgv::base::base_ptr c = my_group;
414 if (c) {
415 tab_group->select_child(c, true);
416 return true;
417 }
418 }
419 }
420 return false;
421}
422
423// return a path in the main menu to select the gui
424std::string provider::get_menu_path() const
425{
426 return "";
427}
428
429// return a shortcut to activate the gui without menu navigation
431{
432 return shortcut();
433}
434
435// use this method to recreate the gui, dont call create gui directly
437{
438 if (!parent_group)
439 return;
440 // ensure that layout is available
441 parent_group->set("dolayout", true);
442 int xscroll = parent_group->get<int>("xscroll");
443 int yscroll = parent_group->get<int>("yscroll");
445 create_gui();
446 parent_group->set("dolayout", true);
447 parent_group->set("xscroll", xscroll);
448 parent_group->set("yscroll", yscroll);
449}
450
451std::set<provider*>& ref_providers()
452{
453 static std::set<provider*> providers;
454 return providers;
455}
456
457/*
458cgv::os::mutex& ref_mutex()
459{
460 static cgv::os::mutex m;
461 return m;
462}
463*/
464
465void trigger_callback(double,double)
466{
467
468 // ref_mutex().lock();
469
470 std::set<provider*>& ps = ref_providers();
471 while (ps.size() > 0) {
472 provider* p = *ps.begin();
473 p->recreate_gui();
474 ps.erase(p);
475 }
476
477 // ref_mutex().unlock();
478
479}
480
481trigger& ref_one_shot_trigger()
482{
483 static trigger t;
484 static bool initialized = false;
485 if (!initialized) {
486 initialized = true;
487 connect(t.shoot, &trigger_callback);
488 }
489 return t;
490}
491
492// ensure to remove posted recreation callbacks
494{
495 std::set<provider*>& ps = ref_providers();
496 if (ps.empty())
497 return;
498
499 // ref_mutex().lock();
500
501 if (ps.find(this) != ps.end())
502 ps.erase(this);
503
504 // ref_mutex().unlock();
505
506}
507
508// schedule the recreation of the gui for the next time the program is idle
510{
511 if (parent_provider)
512 parent_provider->post_recreate_gui();
513 else {
514 if (parent_group) {
515 // ref_mutex().lock();
516 std::set<provider*>& ps = ref_providers();
517 if (ps.find(this) == ps.end()) {
518 bool dont_insert = false;
519 if (!ref_one_shot_trigger().is_scheduled() && get_trigger_server())
520 if (!ref_one_shot_trigger().schedule_one_shot(0))
521 dont_insert = true;
522 if (!dont_insert)
523 ps.insert(this);
524 }
525 // ref_mutex().unlock();
526 }
527 }
528}
529
530
531 }
532}
base class for all classes that can be registered with support for dynamic properties (see also secti...
Definition base.h:75
virtual void update()
this virtual update allows for example to ask a view to update the viewed value. The default implemen...
Definition base.cxx:61
virtual data::ref_ptr< named, true > get_named()
perform downcast to named
Definition base.cxx:37
virtual void on_set(void *member_ptr)
this callback is called when the set_void method has changed a member and can be overloaded in derive...
Definition base.cxx:210
virtual std::string get_type_name() const
overload to return the type name of this object. By default the type interface is queried over get_ty...
Definition base.cxx:241
The group class is a node with children.
Definition group.h:20
reference counted pointer, which can work together with types that are derived from ref_counted,...
Definition ref_ptr.h:160
bool empty() const
check if pointer is not yet set
Definition ref_ptr.h:230
type independent &base class of all views
Definition view.h:13
gui independent group class which is a container for gui elements
Definition gui_group.h:38
derive from this class to provide a gui to the current viewer
Definition provider.h:64
gui_group_ptr get_parent_group() const
use the parent group to append to be managed elements that should be destroyed in a post_recreate_gui...
Definition provider.h:81
void remove_all_elements()
this method removes all elements from the gui and can be used in a method that rebuilds the complete ...
Definition provider.cxx:297
cgv::base::base_ptr add_decorator(const std::string &label, const std::string &decorator_type, const std::string &options="", const std::string &align="\n")
add a newly created decorator to the group
Definition provider.cxx:168
virtual void create_gui()=0
you must overload this for gui creation
virtual std::string get_menu_path() const
return a path in the main menu to select the gui
Definition provider.cxx:424
bool begin_tree_node_void(const std::string &label, const void *value_ptr, int index=-1, bool initial_visibility=false, const std::string &options="", gui_group_ptr ggp=gui_group_ptr())
void version of the templated functions
Definition provider.cxx:207
void align(const std::string &_align)
send pure alignment information
Definition provider.cxx:36
view_ptr find_view_void(void *value_ptr, int *idx_ptr)
access to view of untyped member pointer
Definition provider.cxx:323
virtual void update_all_members()
call this to update all views and controls of all member
Definition provider.cxx:116
view_ptr add_view_void(const std::string &label, const void *value_ptr, const std::string &value_type, const std::string &gui_type, const std::string &options, const std::string &align)
add a newly created view to the group
Definition provider.cxx:21
void remove_element(cgv::base::base_ptr)
remove a single element from the gui
Definition provider.cxx:290
provider()
default construction
Definition provider.cxx:332
virtual bool ensure_selected_in_tab_group_parent()
ensure that my UI is selected in the parent group in case this is a tab group, otherwise return false
Definition provider.cxx:407
void inline_object_gui(cgv::base::base_ptr object)
integrate (if not explicitly done before) and inline the gui of another object that must be derived f...
Definition provider.cxx:147
bool add_tree_node(const std::string &label, bool &toggle, int level, const std::string &a="\n", gui_group_ptr ggp=gui_group_ptr())
add a collapsable node to the gui (deprecated)
Definition provider.cxx:183
gui_group_ptr add_group(const std::string &label, const std::string &group_type, const std::string &options="", const std::string &align="\n")
add a newly created subgroup to the group
Definition provider.cxx:160
~provider()
ensure to remove posted recreation callbacks
Definition provider.cxx:493
virtual void update_member(void *member_ptr)
call this to update all views and controls of a member
Definition provider.cxx:72
void update_parent()
update the parent group
Definition provider.cxx:15
std::string concat_enum_def(const std::vector< std::string > &names, const std::string &additional_first_name="", const std::string &additional_last_name="")
add a new group to the given parent group, not supported yet
Definition provider.cxx:43
virtual std::string get_parent_type() const
Returns the group type that should be used by the class embedding the gui of the provider.
Definition provider.cxx:402
void set_parent(gui_group_ptr)
the gui window sets the parent group through this method
Definition provider.cxx:360
virtual void post_recreate_gui()
delayed recreation of gui
Definition provider.cxx:509
cgv::base::base_ptr find_element(const std::string &name)
find a gui element by name in the current group, return empty pointer if not found
Definition provider.cxx:306
virtual void recreate_gui()
Recreate the gui of this instance right now.
Definition provider.cxx:436
control_ptr add_control_void(const std::string &label, void *value_ptr, abst_control_provider *acp, const std::string &value_type, const std::string &gui_type, const std::string &options, const std::string &align, void *user_data)
add a newly created control to the group
Definition provider.cxx:28
virtual std::string get_gui_name() const
Derive a name for this instance that can be used in the gui as heading.
Definition provider.cxx:383
virtual void on_select()
called by selection_change_cb whenever the gui of this provider is selected
Definition provider.cxx:338
virtual void on_deselect()
called by selection_change_cb whenever the gui of this provider is deselected
Definition provider.cxx:343
void integrate_object_gui(cgv::base::base_ptr object)
call this in create_gui() function to integrate gui of another provider object by setting the parent ...
Definition provider.cxx:137
virtual shortcut get_shortcut() const
return a shortcut to activate the gui without menu navigation
Definition provider.cxx:430
button_ptr add_button(const std::string &label, const std::string &options="", const std::string &align="\n")
use the current gui driver to append a new button with the given label
Definition provider.cxx:176
virtual void selection_change_cb(cgv::base::base_ptr new_child, bool selected)
this is called by the gui group when the selection changes
Definition provider.cxx:349
control_ptr find_control_void(void *value_ptr, int *idx_ptr)
access to control of untyped member pointer
Definition provider.cxx:315
gui_group_ptr parent_group
driver specific handle for the group gui element managing the gui built in the provider
Definition provider.h:69
the shortcut class encapsulates a key with modifiers
Definition shortcut.h:84
data::ref_ptr< base, true > base_ptr
ref counted pointer to base
Definition base.h:37
bool has_property(const std::string &options, const std::string &property, T &value, bool report_error=true)
simple parsing support to access values of properties in a string of property assignment
data::ref_ptr< gui_group, true > gui_group_ptr
ref counted pointer to a gui group
Definition gui_group.h:31
trigger_server_ptr get_trigger_server()
returns the currently registered trigger server
Definition trigger.cxx:100
data::ref_ptr< button > button_ptr
ref counted pointer to button
Definition button.h:24
data::ref_ptr< abst_view > view_ptr
ref counted pointer to abst view
Definition view.h:36
data::ref_ptr< abst_control > control_ptr
ref counted pointer to abst control
Definition control.h:29
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
the cgv namespace
Definition print.h:11
type independent base class of control provider interface
Definition control.h:37