CGII/framework/include/cgv/base/action.h
2018-05-17 15:50:03 +02:00

210 lines
8.9 KiB
C++

#pragma once
#include <string>
#include "group.h"
#include <cgv/type/cond/is_base_of.h>
#include "lib_begin.h"
namespace cgv {
namespace base {
class CGV_API traverse_policy;
/** The action class is used in tree traversals together with the traverser. It implements the interface needed
to perform an action on an arbitrary object. */
class CGV_API action
{
protected:
bool default_result_begin;
bool default_result_end;
public:
/// construct with default return values for the begin and end method
action(bool _default_result_begin, bool _default_result_end);
/// sets the value that is returned, whenever no result is obtained from the traversed methods
void set_default_results(bool _default_result);
/// sets the value that is returned for on_begin events
void set_default_result_begin(bool _default_result_begin);
/// sets the value that is returned for on_end events
void set_default_result_end(bool _default_result_end);
/// make the passed object current
virtual void select(base_ptr p);
/// check if the current object implements the interface needed for this action
virtual bool implements_action() const;
/// return the traverse_policy of the current object if available or 0 otherwise
virtual traverse_policy* get_policy() const;
/// perform the enter part of the action on the current object
virtual bool begin();
/// perform the leave part of the action on the current object
virtual bool end();
/// check whether the action has registered a single begin method or both begin and end methods
virtual bool has_begin_only() const;
};
template <bool is_derived, class X>
struct extract_policy_struct
{
static void extract_policy(X*, traverse_policy* &tp) { tp = 0; }
};
template <class X>
struct extract_policy_struct<true,X>
{
static void extract_policy(X* x, traverse_policy* &tp) { tp = static_cast<traverse_policy*>(x); }
};
/** base class for all actions that use methods of class X*/
template <class X>
class base_method_action : public action
{
protected:
traverse_policy* tp;
X* x;
public:
/// construct from default return values that are passed on to the base class
base_method_action(bool _default_result_begin, bool _default_result_end)
: action(_default_result_begin, _default_result_end), tp(0), x(0) {}
/// implement the select method and store pointers of type X* and traverse_policy*
void select(base_ptr p) {
x = p->get_interface<X>();
extract_policy_struct<type::cond::is_base_of<traverse_policy, X>::value,X>::extract_policy(x, tp);
}
/// simply return whether the stored pointer of type X* is not 0
bool implements_action() const {
return x != 0;
}
/// simply return the stored pointer of type traverse_policy*
traverse_policy* get_policy() const {
return tp;
}
};
/** base class for all method actions that take a single argument of type T1 in their signature*/
template <class X, typename T1>
class method_action : public base_method_action<X>
{
protected:
T1 v1;
public:
/// construct action from signature and default return values
method_action(T1 _v1, bool _default_result_begin, bool _default_result_end)
: base_method_action<X>(_default_result_begin, _default_result_end), v1(_v1) {}
/// set a new signature with which the methods of the traversed nodes are called
void set_signature(T1 _v1) { v1 = _v1; }
/// call a void method given a default return value
bool call_method(void (X::*mp)(T1), bool default_result) {
if (this->x && mp)
(this->x->*mp)(v1);
return default_result;
}
/// call a bool method given a default return value
bool call_method(bool (X::*mp)(T1), bool default_result) {
if (this->x && mp)
return (this->x->*mp)(v1);
return default_result;
}
};
/** complete implementation of method actions that only call one method when entering a node*/
template <class X, typename R, typename T1>
class single_method_action : public method_action<X,T1>
{
protected:
R (X::*on_begin)(T1);
public:
/// construct from signature, method pointer and default result values
single_method_action(T1 _v1, R (X::*_on_begin)(T1),
bool _default_result_begin = false, bool _default_result_end = false)
: method_action<X,T1>(_v1, _default_result_begin, _default_result_end), on_begin(_on_begin) {}
/// uses call_method of base class method_action to call the method refered to by the stored method pointer
bool begin() { return this->call_method(on_begin, this->default_result_begin); }
/// check whether the action has registered a single begin method or both begin and end methods
bool has_begin_only() const { return true; }
};
/** complete implementation of method actions that call a begin and end method when entering and leaving a node*/
template <class X, typename R1, typename R2, typename T1>
class matched_method_action : public method_action<X,T1>
{
protected:
R1 (X::*on_begin)(T1);
R2 (X::*on_end)(T1);
public:
/// construct from signature, method pointers and default result values
matched_method_action(T1 _v1, R1 (X::*_on_begin)(T1), R2 (X::*_on_end)(T1), bool _default_result_begin, bool _default_result_end)
: method_action<X,T1>(_v1, _default_result_begin, _default_result_end), on_begin(_on_begin), on_end(_on_end) {}
/// uses call_method of base class method_action to call the method refered to by the stored method pointer
bool begin() { return this->call_method(on_begin, this->default_result_begin); }
/// uses call_method of base class method_action to call the method refered to by the stored method pointer
bool end() { return this->call_method(on_end, this->default_result_end); }
};
/// helper function to construct an action from a signature and one method that is called when a node is entered
template <typename T1, class X, typename R>
single_method_action<X,R,T1> make_action(T1 _v1, R (X::*_on_begin)(T1), bool _default_result_begin = false, bool _default_result_end = false) {
return single_method_action<X,R,T1>(_v1, _on_begin, _default_result_begin, _default_result_end);
}
/// helper function to construct an action from a signature and two methods that are called when a node is entered and when it is left again
template <typename T1, class X, typename R1, typename R2>
matched_method_action<X,R1,R2,T1> make_action(T1 _v1, R1 (X::*_on_begin)(T1), R2 (X::*_on_end)(T1), bool _default_result_begin = false, bool _default_result_end = false) {
return matched_method_action<X,R1,R2,T1>(_v1, _on_begin, _on_end, _default_result_begin, _default_result_end);
}
/** base class for all method actions that take a single argument of type T1 in their signature*/
template <class X, typename T1, typename T2>
class method_action_2 : public base_method_action<X>
{
protected:
T1 v1;
T2 v2;
public:
/// construct action from signature and default return values
method_action_2(T1 _v1, T2 _v2, bool _default_result_begin, bool _default_result_end)
: base_method_action<X>(_default_result_begin, _default_result_end), v1(_v1), v2(_v2) {}
/// set a new signature with which the methods of the traversed nodes are called
void set_signature(T1 _v1, T2 _v2) { v1 = _v1; v2 = _v2; }
/// call a void method given a default return value
bool call_method(void (X::*mp)(T1, T2), bool default_result) {
if (this->x && mp)
(this->x->*mp)(v1,v2);
return default_result;
}
/// call a bool method given a default return value
bool call_method(bool (X::*mp)(T1, T2), bool default_result) {
if (this->x && mp)
return (this->x->*mp)(v1, v2);
return default_result;
}
};
/** complete implementation of method actions that only call one method when entering a node*/
template <class X, typename R, typename T1, typename T2>
class single_method_action_2 : public method_action_2<X,T1,T2>
{
protected:
R (X::*on_begin)(T1,T2);
public:
/// construct from signature, method pointer and default result values
single_method_action_2(T1 _v1, T2 _v2, R (X::*_on_begin)(T1,T2),
bool _default_result_begin = false, bool _default_result_end = false)
: method_action_2<X,T1,T2>(_v1, _v2, _default_result_begin, _default_result_end), on_begin(_on_begin) {}
/// uses call_method of base class method_action to call the method refered to by the stored method pointer
bool begin() { return this->call_method(on_begin, this->default_result_begin); }
/// check whether the action has registered a single begin method or both begin and end methods
bool has_begin_only() const { return true; }
};
/// helper function to construct an action from a signature and one method that is called when a node is entered
template <typename T1, typename T2, class X, typename R>
single_method_action_2<X,R,T1,T2> make_action_2(T1 _v1, T2 _v2, R (X::*_on_begin)(T1,T2), bool _default_result_begin = false, bool _default_result_end = false) {
return single_method_action_2<X,R,T1,T2>(_v1, _v2, _on_begin, _default_result_begin, _default_result_end);
}
}
}
#include <cgv/config/lib_end.h>