1#include "base_provider.h"
2#include <cgv/utils/file.h>
3#include <cgv/gui/application.h>
5#include <cgv/utils/tokenizer.h>
10using namespace cgv::signal;
20 textual_gui_definition = gui_def;
23 is_named_gui_assignment_m = _is_named_gui_assignment;
24 parent_type =
"align_group";
33 parent_type =
"align_group";
34 is_named_gui_assignment_m =
true;
35 read_gui_definition(file_name);
59std::string base_provider::error_start(
const char* ptr)
const
61 std::string error(
"error (");
62 const char* end = ptr;
63 if (&textual_gui_definition[textual_gui_definition.size()-1] < ptr)
64 end = &textual_gui_definition[textual_gui_definition.size()-1];
67 for (
const char* p = &textual_gui_definition[0]; p<end;++p)
80 return instance->get_type_name();
81 return "base_provider";
88 return instance->get_named();
93void base_provider::read_gui_definition(
const std::string& file_name)
96 if (cgv::utils::file::read(file_name, content,
true))
97 set_gui_definition(content);
99 std::cerr <<
"could not read gui definition from " << file_name.c_str() << std::endl;
103void base_provider::set_gui_definition(
const std::string& new_def)
105 textual_gui_definition = new_def;
116const std::string& base_provider::get_gui_definition()
const
118 return textual_gui_definition;
124 instance = _instance;
135 CMD_WINDOW, CMD_GROUP, CMD_ALIGN, CMD_DECORATOR, CMD_BUTTON, CMD_VIEW,
136 CMD_CONTROL, CMD_TREE_NODE, CMD_LAST };
161 { CMD_WINDOW,
"window",
"iisSS", 5,
true },
162 { CMD_GROUP,
"group",
"ssSS", 4,
true },
163 { CMD_ALIGN,
"align",
"s", 1,
false },
164 { CMD_DECORATOR,
"decorator",
"ssSS", 4,
false },
165 { CMD_BUTTON,
"button",
"sSS", 3,
false },
166 { CMD_VIEW,
"view",
"srSSS", 5,
false },
167 { CMD_CONTROL,
"control",
"srSSS", 5,
false },
168 { CMD_TREE_NODE,
"tree_node",
"sbiS", 4,
true },
169 { CMD_LAST,
"",
"", 0,
false }
174bool base_provider::find_member(
const std::string& name,
void*& member_ptr, std::string& member_type)
177 return member_ptr != 0;
181void base_provider::parse_definition(ParsingTasks pt)
183 std::vector<token> T;
184 std::stack<bool> visible;
185 std::stack<CommandId> block_cmd;
186 std::stack<gui_group_ptr> gui_group_stack;
188 bool expect_block_begin =
false;
190 tokenizer(textual_gui_definition).set_sep(
";,(){}").set_skip(
"'\"",
"'\"").bite_all(T);
191 const command_info* cis = get_command_infos();
199 if (expect_block_begin) {
201 expect_block_begin =
false;
206 std::cerr << error_start(T[i].begin) <<
"expected { after "
207 << get_command_infos()[block_cmd.top()].
command
208 <<
" command to enclose child elements" << std::endl;
211 block_cmd.push(CMD_LAST);
212 std::cerr << error_start(T[i].begin) <<
"{ only allowed after window / group or tree_node command" << std::endl;
216 expect_block_begin =
false;
218 if (block_cmd.empty())
219 std::cerr << error_start(T[i].begin) <<
"found unmatched }" << std::endl;
221 if (pt == PT_CREATE_GUI) {
222 switch (block_cmd.top()) {
223 case CMD_TREE_NODE : visible.pop();
break;
225 case CMD_WINDOW : gui_group_stack.pop();
break;
236 while (cis[j].cmd_id != CMD_LAST) {
237 if (T[i] == cis[j].command)
242 if (cis[j].cmd_id == CMD_LAST) {
243 std::cerr << error_start(T[i].begin) <<
"command " <<
to_string(T[i]).c_str() <<
" not known" << std::endl;
247 const command_info& ci = cis[j];
250 if (++i >= T.size()) {
251 std::cerr << error_start(T[i-1].begin) <<
"command " << ci.command <<
" incomplete" << std::endl;
255 std::cerr << error_start(T[i].begin) <<
"expected ( after command " << ci.command <<
" but found " <<
to_string(T[i]).c_str() <<
" instead" << std::endl;
258 bool terminate =
false;
259 std::vector<std::string> args;
260 bool last_was_argument =
false;
266 if (!last_was_argument && args.size() < ci.nr_arguments)
268 last_was_argument =
false;
270 else if (T[i] ==
")") {
271 if (!last_was_argument && args.size() < ci.nr_arguments)
273 last_was_argument =
false;
277 if (last_was_argument) {
281 else if (args.size() < ci.nr_arguments) {
282 if (
to_lower(ci.arguments[args.size()]) ==
's') {
283 if (*T[i].begin ==
'"' && T[i].size() > 1 && T[i].end[-1] ==
'"') {
287 if (*T[i].begin ==
'\'' && T[i].size() > 1 && T[i].end[-1] ==
'\'') {
294 last_was_argument =
true;
298 std::cerr << error_start(T[i-1].begin) <<
"did not find enclosing )" << std::endl;
303 if (args.size() < ci.nr_arguments) {
304 char c = ci.arguments[args.size()];
306 std::cerr << error_start(T[i-1].begin) <<
"not all necessary arguments provided for command " << ci.command << std::endl;
311 expect_block_begin = get_command_infos()[ci.cmd_id].
block_follows;
312 if (expect_block_begin)
313 block_cmd.push(ci.cmd_id);
317 if (ci.cmd_id == CMD_TREE_NODE)
320 case PT_INIT_TOGGLES:
321 if (ci.cmd_id == CMD_TREE_NODE) {
322 if (args[1] ==
"true")
323 toggles[nr_toggles] =
true;
324 else if (args[1] ==
"false")
325 toggles[nr_toggles] =
false;
327 toggles[nr_toggles] =
true;
328 std::cerr << error_start(T[i-1].begin) <<
"error parsing initial toggle value which must be true or false" << std::endl;
334 if (!visible.top()) {
335 if (ci.cmd_id == CMD_TREE_NODE)
340 std::string member_type;
342 if (!gui_group_stack.empty())
343 ggp = gui_group_stack.top();
357 atoi(args[1].c_str()), args[2],
358 args.size()>3 ? args[3] : std::string(
"viewer"));
360 wp->multi_set(args[4],
true);
361 gui_group_stack.push(wp);
366 gui_group_stack.push(ggp->add_group(args[0], args[1],
367 args.size()>2 ? args[2] : std::string(
""),
368 args.size()>3 ? args[3] : std::string(
"\n")));
374 ggp->add_decorator(args[0], args[1],
375 args.size()>2 ? args[2] : std::string(
""),
376 args.size()>3 ? args[3] : std::string(
"\n"));
379 ggp->add_button(args[0],
380 args.size()>1 ? args[1] : std::string(
""),
381 args.size()>2 ? args[2] : std::string(
"\n"));
384 if (find_member(args[1],member_ptr, member_type))
385 ggp->add_view_void(args[0],member_ptr,member_type,
386 args.size()>2 ? args[2] : std::string(
""),
387 args.size()>3 ? args[3] : std::string(
""),
388 args.size()>4 ? args[4] : std::string(
"\n"));
391 if (find_member(args[1],member_ptr, member_type)) {
425 >(instance.operator->(),
430 ggp->add_control_void(args[0],member_ptr,0,member_type,
431 args.size()>2 ? args[2] : std::string(
""),
432 args.size()>3 ? args[3] : std::string(
""),
433 args.size()>4 ? args[4] : std::string(
"\n"), 0)
434 ->attach_to_value_change(of.clone());
438 add_tree_node(args[0], toggles[nr_toggles], atoi(args[2].c_str()),
439 args.size() > 3 ? args[3] : std::string(
"\n"), ggp);
440 visible.push(toggles[nr_toggles]);
453 }
while (i < T.size());
459 if (!parent_options.empty())
461 if (nr_toggles == -1) {
463 parse_definition(PT_NR_TOGGLES);
464 if (nr_toggles > 0) {
467 toggles =
new bool[nr_toggles];
469 parse_definition(PT_INIT_TOGGLES);
473 parse_definition(PT_CREATE_GUI);
More advanced text processing for splitting text into lines or tokens.
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...
void * find_member_ptr(const std::string &property_name, std::string *type_name=0)
find a member pointer by name.
reference counted pointer, which can work together with types that are derived from ref_counted,...
static window_ptr create_window(int w, int h, const std::string &title, const std::string &window_type="viewer")
create a window of the given type, where all gui implementations must support the type "viewer"
data::ref_ptr< cgv::base::named, true > get_named()
perform downcast to named
std::string get_parent_type() const
Returns the group type that should be used by the class embedding the gui of the provider.
~base_provider()
destruct base provider
base_provider(cgv::base::base_ptr _instance=cgv::base::base_ptr(), const std::string &gui_def="", bool _is_named_gui_assignment=false)
construct from instance and gui definition
void create_gui()
you must overload this for gui creation
bool self_reflect(cgv::reflect::reflection_handler &rh)
used for simple self reflection
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...
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)
virtual void post_recreate_gui()
delayed recreation of gui
gui_group_ptr parent_group
driver specific handle for the group gui element managing the gui built in the provider
the self reflection handler is passed to the virtual self_reflect() method of cgv::base::base.
bool reflect_member(const std::string &member_name, T &member_ref, bool hard_cast=false)
call this to reflect a member by member name and reference to the member.
the base namespace holds the base hierarchy, support for plugin registration and signals
data::ref_ptr< base, true > base_ptr
ref counted pointer to base
data::ref_ptr< named, true > named_ptr
ref counted pointer to a node
namespace that holds the abstract gui interface
data::ref_ptr< window > window_ptr
ref counted pointer to &window
data::ref_ptr< gui_group, true > gui_group_ptr
ref counted pointer to a gui group
data::ref_ptr< abst_control > control_ptr
ref counted pointer to abst control
namespace that holds tools that dont fit any other namespace
std::string to_string(const std::string &v, unsigned int w, unsigned int p, bool)
specialization of conversion from string to strings
char to_lower(char c)
convert char to lower case
this header is dependency free
const char * arguments
lower case letters for necessary arguments and upper case for optional
bool block_follows
whether command is followed by a {}-block
CommandId cmd_id
id of command
unsigned nr_arguments
length of arguments string
const char * command
command name