1071 lines
37 KiB
C
1071 lines
37 KiB
C
/****************************************************************************
|
|
* Copyright (c) 2017 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>*
|
|
* *
|
|
* This file is part of the FreeCAD CAx development system. *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU Library General Public *
|
|
* License as published by the Free Software Foundation; either *
|
|
* version 2 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU Library General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Library General Public *
|
|
* License along with this library; see the file COPYING.LIB. If not, *
|
|
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
|
* Suite 330, Boston, MA 02111-1307, USA *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
#ifndef PARAMS_HELPER_H
|
|
#define PARAMS_HELPER_H
|
|
|
|
/** \page ParamPage Parameter helper macros
|
|
* Collections of macros for managing groups of parameters.
|
|
*
|
|
* \section Motivation
|
|
*
|
|
* For an application like FreeCAD, there are often cases where the same set of
|
|
* parameters are referred in dozons of different places. The macros here is
|
|
* designed to help managing those parameters, so that you can define groups of
|
|
* parameters once, and refer them everywhere in groups with simple macro calls for
|
|
* all kinds of purposes. Any changing, adding and removing of parameters in the
|
|
* group become much easier. And by everywhere, I mean \ref ParamCommon
|
|
* "class definition, impelentation", \ref ParamProperty "document object properties",
|
|
* \ref ParamPy "python c++ classes", and even \ref ParamDoc "doc string",
|
|
* pretty much everything except the python code, which although not implemented
|
|
* yet, is in fact also possible to be done using C preprocessor (No one says C
|
|
* preprocessor must produce C code :). It is also possible (not implemented
|
|
* yet) to use macros to generate python wrapper class instead of using
|
|
* FreeCAD's current xml python export.
|
|
*
|
|
* \section Debugging
|
|
*
|
|
* Extensive use of macros has one noticeable disadvantage, though. If some thing
|
|
* goes wrong, the compiler error message is kind of cryptic. If so, first
|
|
* double check your macro definition of the parameter is correctly, not missing
|
|
* or having extra parathesis or comma. Then, you can use the CMake
|
|
* intermeidate file target to get the preprocessor output for checking. For
|
|
* example, for a file located at \c src/Mod/Path/App/Area.cpp,
|
|
* \code{.sh}
|
|
* cd <your_build_dir>/src/Mod/Path/App
|
|
* make Area.cpp.i
|
|
* \endcode
|
|
*
|
|
* The preprocessed intermediate output will be at,
|
|
* \code{.sh}
|
|
* <your_build_dir>/src/Mod/Path/App.CMakeFiles/Path.dir/Area.cpp.i
|
|
* \endcode
|
|
*
|
|
* \section Intrudction of Boost.Preprocessor
|
|
*
|
|
* The macros here make heavy use of the awsome
|
|
* [Boost.Preprocessor](http://www.boost.org/libs/preprocessor/) (short for
|
|
* Boost.PP). Here are some brief introduction on Boost.PP conecept in order to
|
|
* explain why this marco library is designed the way it is.
|
|
*
|
|
* In Boost.PP, a sequence is defined as,
|
|
* \code{.sh}
|
|
* (a)(b)(c)...
|
|
* \endcode
|
|
*
|
|
* A sequence cannot be empty. Thus, \c () is not a sequence. And also those
|
|
* <tt>a, b, c</tt> here cannot directly contain <tt>,</tt>. These restriction
|
|
* is due to the fact that <tt>( ) ,</tt> are among those very few special
|
|
* characters recognized by the preprocssor. \c a can itself be a sequence or
|
|
* other Boost.PP types, so by right, our parameter can be defined as something
|
|
* like
|
|
* \code{.sh}
|
|
* ((type)(name)(default)...)
|
|
* \endcode
|
|
*
|
|
* A bit awkward to write. So another Boost.PP type is chosen, tuple, to define
|
|
* each individual parameter. A tuple is defined as
|
|
* \code{.sh}
|
|
* (a,b,c ...)
|
|
* \endcode
|
|
*
|
|
* This is why the parameter definition requires a double parathesis, as shown
|
|
* in the following section.
|
|
*
|
|
* \section Library Overview
|
|
*
|
|
* In this macro library, a parameter is defined using a tuple inside a sequence,
|
|
* \code{.sh}
|
|
* ((<type>, <arg>, <name>, <default>, <doc>, <seq>, <info>))
|
|
* \endcode
|
|
*
|
|
* - \c type is the type of the parameter. Currently only five types of
|
|
* parameters are defined, <tt>short, long, double, bool, enum, enum2</tt>.
|
|
* \enum2 type is the same as \enum with additional information to be able to
|
|
* map to a user defined C enum type. To add more types, search this file for
|
|
* keyword \a _short, and supply all relavant macros. It's quite trivial
|
|
* actually.
|
|
*
|
|
* - \c arg is the agument name. It is intended to be used as function argument.
|
|
* By convention, the name shall be all small cases, but that's not required.
|
|
* This \c arg can be repurposed, if the parameter is not going to be used as
|
|
* function agument. The #AREA_PARAMS_CAREA parameters repurposed this field
|
|
* to CArea internal setting variables to implement save, apply and restore
|
|
* function using CAreaConfig class.
|
|
*
|
|
* - \c name is normally a %CamelCase name which are used as member variable and
|
|
* property name. Because of this, make sure the names are unique to avoid
|
|
* conflicts.
|
|
*
|
|
* - \c default is the default value of this parameter. Right now, you must
|
|
* supply a default value. Boost.PP has trouble dealing with empty values.
|
|
* Remember that a sequence cannot be empty. Neight can tuple. Only array,
|
|
* something like <tt>(0,())</tt> for an empty array. It is awkward to write,
|
|
* and didn't add much functionality I want, hence the restriction of
|
|
* non-empty defaults here.
|
|
*
|
|
* - \c doc is a string to describe the variable.
|
|
*
|
|
* - \c seq \anchor ParamSeq. Right now this field is used by \c enum and
|
|
* \c enum2 type parameter to define its enumerations. As the name suggests,
|
|
* it must be a sequence. It is not a tuple because looping through tuple is
|
|
* not as easy as sequence. Other type of parameter do not need to have this
|
|
* field
|
|
*
|
|
* - \c info is used to provide the supplimentery information for \c enum2 type
|
|
* of parameter, which can be converted to a user defined enum type by
|
|
* #PARAM_ENUM_CONVERT. \c info must be a tuple, with the user defined enum
|
|
* type as the first element, and a prefix as the second element. For \c enum2
|
|
* type of parameter, this field is mandatory.
|
|
*
|
|
* The common usage is that you define a macro of a group of parameters. And use
|
|
* the macro helper here to do operation on each parameter in the group. See
|
|
* AreaParams.h file for an example of parameter definitions.
|
|
*
|
|
* Area.h, Area.cpp, FeatureArea.h, FeatureArea.cpp for usage of variouse macros.
|
|
*
|
|
* See struct AreaDoc for an example of doc string generation.
|
|
*
|
|
* Each field of the parameter can be referred to with various
|
|
* \ref ParamAccessor "various accessor macros", and can be easily
|
|
* \ref ParamStringizer "stringified".
|
|
*
|
|
* \anchor ParamField You can also use #PARAM_FIELD(_field,_param) to refer to
|
|
* each field, where \a _field is one of <tt>TYPE, ARG, NAME, DEF, DOC, or SEQ</tt>.
|
|
* And #PARAM_FIELD_STR to stringify.
|
|
*
|
|
* Here \a _param is the parameter definition described above in the form of a
|
|
* Boost.PP tuple, and is usually supplied by various \ref ParamLooper "looper macros"
|
|
*
|
|
* You can of course directly use various Boost.PP sequence looper to pass
|
|
* aditional arguments to the operation macro. See #PARAM_PY_DICT_SET_VALUE for
|
|
* an example of using tuple, and the more complex example #PARAM_ENUM_CONVERT
|
|
*
|
|
* Note that when generating comma separated list, the first and last comma are
|
|
* conveniently omitted, so that the macros can be mixed with others intuitively
|
|
*/
|
|
|
|
#include <boost/preprocessor/cat.hpp>
|
|
#include <boost/preprocessor/seq/seq.hpp>
|
|
#include <boost/preprocessor/seq/elem.hpp>
|
|
#include <boost/preprocessor/seq/for_each.hpp>
|
|
#include <boost/preprocessor/seq/for_each_i.hpp>
|
|
#include <boost/preprocessor/seq/pop_front.hpp>
|
|
#include <boost/preprocessor/stringize.hpp>
|
|
#include <boost/preprocessor/logical/not.hpp>
|
|
#include <boost/preprocessor/tuple/elem.hpp>
|
|
#include <boost/preprocessor/tuple/enum.hpp>
|
|
#include <boost/preprocessor/punctuation/comma_if.hpp>
|
|
#include <boost/preprocessor/comparison/greater.hpp>
|
|
|
|
/** \defgroup ParamHelper Parameters helper macros
|
|
* Collections of macros for managing groups of parameters */
|
|
|
|
/**
|
|
* \defgroup ParamAccessor Field accessors
|
|
* To abstract parameter field details
|
|
* \ingroup ParamHelper
|
|
* @{
|
|
*/
|
|
#define PARAM_ITYPE 0
|
|
#define PARAM_IARG 1
|
|
#define PARAM_INAME 2
|
|
#define PARAM_IDEF 3
|
|
#define PARAM_IDOC 4
|
|
#define PARAM_ISEQ 5
|
|
#define PARAM_IPROP 5
|
|
#define PARAM_IINFO 6
|
|
|
|
#define PARAM_FIELD(_idx,_param) BOOST_PP_TUPLE_ELEM(PARAM_I##_idx,_param)
|
|
|
|
#define PARAM_FTYPE(_param) PARAM_FIELD(TYPE,_param)
|
|
#define PARAM_FARG(_param) PARAM_FIELD(ARG,_param)
|
|
#define PARAM_FNAME(_param) PARAM_FIELD(NAME,_param)
|
|
#define PARAM_FDEF(_param) PARAM_FIELD(DEF,_param)
|
|
#define PARAM_FDOC(_param) PARAM_FIELD(DOC,_param)
|
|
#define PARAM_FSEQ(_param) PARAM_FIELD(SEQ,_param)
|
|
#define PARAM_FPROP(_param) PARAM_FIELD(PROP,_param)
|
|
#define PARAM_FINFO(_param) PARAM_FIELD(INFO,_param)
|
|
#define PARAM_FENUM_TYPE(_param) BOOST_PP_TUPLE_ELEM(0,PARAM_FINFO(_param))
|
|
#define PARAM_FENUM_PREFIX(_param) BOOST_PP_TUPLE_ELEM(1,PARAM_FINFO(_param))
|
|
/** @} */
|
|
|
|
|
|
/**
|
|
* \defgroup ParamStringizer Field stringizers
|
|
* \ingroup ParamHelper
|
|
* @{ */
|
|
#define PARAM_FIELD_STR(_idx,_param) \
|
|
BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(PARAM_I##_idx,_param))
|
|
|
|
#define PARAM_FTYPE_STR(_param) PARAM_FIELD_STR(TYPE,_param)
|
|
#define PARAM_FARG_STR(_param) PARAM_FIELD_STR(ARG,_param)
|
|
#define PARAM_FNAME_STR(_param) PARAM_FIELD_STR(NAME,_param)
|
|
#define PARAM_FDEF_STR(_param) PARAM_FIELD_STR(DEF,_param)
|
|
/** @} */
|
|
|
|
/** Helper for #PARAM_FSEQ_STR */
|
|
#define PARAM_FSEQ_STR_(_i,_elem) \
|
|
BOOST_PP_COMMA_IF(_i) BOOST_PP_STRINGIZE(_elem)
|
|
|
|
/** \c SEQ stringizer will stringify each element separately
|
|
*
|
|
* Expands to:
|
|
* #seq[0], #seq[1] ...
|
|
* \ingroup ParamHelper
|
|
*/
|
|
#define PARAM_FSEQ_STR(_param) \
|
|
PARAM_FOREACH_I(PARAM_FSEQ_STR_,PARAM_FSEQ(_param))
|
|
|
|
|
|
/** \defgroup ParamLooper Looper macros
|
|
* Macros for looping through sequence to parameters
|
|
* \ingroup ParamHelper
|
|
*/
|
|
|
|
/** Helper for #PARAM_FOREACH */
|
|
#define PARAM_FOREACH_(_,_op,_param) _op(_param)
|
|
|
|
/** Apply macro \a _op to each parameter in sequence \a _seq
|
|
*
|
|
* Operation macro \a _op shoud be defined as,
|
|
* \code
|
|
* _op(_param)
|
|
* \endcode
|
|
* \ingroup ParamLooper
|
|
*/
|
|
#define PARAM_FOREACH(_op,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH(PARAM_FOREACH_,_op,_seq)
|
|
|
|
/** Helper for #PARAM_FOREACH_I */
|
|
#define PARAM_FOREACH_I_(_,_op,_i,_param) _op(_i,_param)
|
|
|
|
/** Apply macro \a _op to each parameter in sequence \a _seq with additional index
|
|
*
|
|
* Operation macro \a _op shoud be defined as,
|
|
* \code
|
|
* _op(_i,_param)
|
|
* \endcode
|
|
* \ingroup ParamLooper
|
|
* */
|
|
#define PARAM_FOREACH_I(_op,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH_I(PARAM_FOREACH_I_,_op,_seq)
|
|
|
|
|
|
/** Helper for #PARAM_TYPED_FOREACH */
|
|
#define PARAM_TYPED_FOREACH_(_1,_op,_param) \
|
|
PARAM_TYPED(_op,_param)(_param)
|
|
|
|
/** Type depended macro construction
|
|
*
|
|
* Convert macro \a _op to \a _op##\<type\>. Note that it only converts the
|
|
* macro name, not contsucts a macro call. To expand to a macro call, simply
|
|
* \code
|
|
* PARAM_TYPED(_op,_param)(_param)
|
|
* \endcode
|
|
* \ingroup ParamLooper
|
|
*/
|
|
#define PARAM_TYPED(_op,_param) \
|
|
BOOST_PP_CAT(_op,PARAM_FTYPE(_param))
|
|
|
|
/** Apply type dependent macro call to a sequence of parameters
|
|
*
|
|
* \a _op will be converted to \a _op##\<type\> for each parameter
|
|
* \ingroup ParamLooper
|
|
*/
|
|
#define PARAM_TYPED_FOREACH(_op,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH(PARAM_TYPED_FOREACH_,_op,_seq)
|
|
|
|
|
|
/** \defgroup ParamCommon Common helpers
|
|
* \ingroup ParamHelper
|
|
*/
|
|
|
|
#define PARAM_TYPE_short short
|
|
#define PARAM_TYPE_long long
|
|
#define PARAM_TYPE_double double
|
|
#define PARAM_TYPE_bool bool
|
|
#define PARAM_TYPE_enum short
|
|
#define PARAM_TYPE_enum2 short
|
|
|
|
/** Obtain parameter type
|
|
*
|
|
* The main purpose is to alias enum type to short
|
|
* \ingroup ParamCommon
|
|
*/
|
|
#define PARAM_TYPE(_param) \
|
|
PARAM_TYPED(PARAM_TYPE_,_param)
|
|
|
|
|
|
/** Helper for #PARAM_DECLARE */
|
|
#define PARAM_DECLARE_(_1,_src,_param) \
|
|
PARAM_TYPE(_param) _src(_param);
|
|
|
|
/**
|
|
* Delcares parameters using the given field as name
|
|
*
|
|
* \arg \c _src: \anchor ParamSrc Macro to generate source variable. The
|
|
* signature must be <tt>_src(_param)<\tt>, where \c _param is the tuple
|
|
* defining the parameter. You pass any of the \ref ParamAccessor "parameter
|
|
* accessors" to directly access the field. Or, supply your own macro to append
|
|
* any prefix as you like. For example:
|
|
* \code{.unparsed}
|
|
* #define MY_SRC(_param) BOOST_PP_CAT(my,PARAM_FNAME(_param))
|
|
* ->
|
|
* my##<name>
|
|
* \endcode
|
|
*
|
|
* Expands to:
|
|
* \code{.unparsed}
|
|
* type1 _src(_param1);type2 _src(_param2); ...
|
|
* \endcode
|
|
* \ingroup ParamCommon
|
|
*/
|
|
#define PARAM_DECLARE(_src,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH(PARAM_DECLARE_,_src,_seq)
|
|
|
|
|
|
/** Helper for #PARAM_DECLARE_INIT */
|
|
#define PARAM_DECLARE_INIT_(_1,_src,_param) \
|
|
PARAM_TYPE(_param) _src(_param) = PARAM_FDEF(_param);
|
|
|
|
/**
|
|
* Delcares parameters with initialization to default using the given field as
|
|
* name
|
|
*
|
|
* \arg \c _src: macro to generate source field. See \ref ParamSrc "here" for
|
|
* more details
|
|
*
|
|
* Expands to:
|
|
* \code{.unparsed}
|
|
* type1 _src(_param1)=_def1;type2 _src(_param2)=_def2; ...
|
|
* \endcode
|
|
* \ingroup ParamCommon
|
|
*/
|
|
#define PARAM_DECLARE_INIT(_src,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH(PARAM_DECLARE_INIT_,_src,_seq)
|
|
|
|
|
|
#define PARAM_ENUM_DECLARE_enum_(_1,_name,_i,_elem) \
|
|
BOOST_PP_COMMA_IF(_i) BOOST_PP_CAT(_name,_elem)
|
|
|
|
#define PARAM_ENUM_DECLARE_enum(_param) \
|
|
enum {BOOST_PP_SEQ_FOR_EACH_I(PARAM_ENUM_DECLARE_enum_,PARAM_FNAME(_param),PARAM_FSEQ(_param))};
|
|
|
|
#define PARAM_ENUM_DECLARE_short(_param)
|
|
#define PARAM_ENUM_DECLARE_long(_param)
|
|
#define PARAM_ENUM_DECLARE_double(_param)
|
|
#define PARAM_ENUM_DECLARE_bool(_param)
|
|
#define PARAM_ENUM_DECLARE_enum2 PARAM_ENUM_DECLARE_enum
|
|
|
|
/** \defgroup ParamEnumHelper Enum convert helpers
|
|
* \ingroup ParamCommon
|
|
*/
|
|
|
|
/** Make anonymous \c enum type
|
|
*
|
|
* Make anonymous \c enum type for \c enum type parameters in \a _seq. All other
|
|
* types are ignored. The enum member is prefixed with \a _name. Expand to:
|
|
* \code{.unparsed}
|
|
* enum {_name1##_seq1[0], _name1##_seq1[1] ...};
|
|
* enum {_name2##_seq2[0], _name2##_seq2[1] ...};
|
|
* ...
|
|
* \endcode
|
|
* \ingroup ParamEnumHelper*/
|
|
#define PARAM_ENUM_DECLARE(_seq) \
|
|
PARAM_TYPED_FOREACH(PARAM_ENUM_DECLARE_,_seq)
|
|
|
|
|
|
/** \addgroup ParamEnumHelper Enum convert helpers
|
|
* @{ */
|
|
#define PARAM_ENUM_CONVERT_short(...)
|
|
#define PARAM_ENUM_CONVERT_long(...)
|
|
#define PARAM_ENUM_CONVERT_double(...)
|
|
#define PARAM_ENUM_CONVERT_bool(...)
|
|
#define PARAM_ENUM_CONVERT_enum(...)
|
|
#define PARAM_ENUM_CONVERT_enum2 PARAM_ENUM_CONVERT_SINGLE
|
|
|
|
#define PARAM_ENUM_CONVERT_enum_(_dst,_name,_prefix,_elem) \
|
|
case BOOST_PP_CAT(_name,_elem):\
|
|
_dst = BOOST_PP_CAT(_prefix,_elem);\
|
|
break;
|
|
|
|
#define PARAM_ENUM_CONVERT__(_1,_args,_i,_elem) \
|
|
PARAM_ENUM_CONVERT_enum_(BOOST_PP_TUPLE_ELEM(0,_args),\
|
|
BOOST_PP_TUPLE_ELEM(1,_args),\
|
|
BOOST_PP_TUPLE_ELEM(2,_args),\
|
|
_elem);
|
|
|
|
#define PARAM_ENUM_CONVERT_(_1,_args,_param) \
|
|
PARAM_TYPED(PARAM_ENUM_CONVERT_,_param)(BOOST_PP_TUPLE_ELEM(0,_args),\
|
|
BOOST_PP_TUPLE_ELEM(1,_args),\
|
|
BOOST_PP_TUPLE_ELEM(2,_args),\
|
|
_param)
|
|
|
|
/** Convert single enum parameter value into user defined enum type
|
|
*
|
|
* This macro is used by #PARAM_ENUM_CONVERT to convert each parameter, but
|
|
* you can use it directly for a single parameter. Check #PARAM_NUM_CONVERT
|
|
* for more detail. Make sure the outer parathesis of \c _param is stripped,
|
|
* i.e. not double but single parathesis
|
|
*/
|
|
#define PARAM_ENUM_CONVERT_SINGLE(_src,_dst,_default,_param) \
|
|
PARAM_FENUM_TYPE(_param) _dst(_param);\
|
|
switch(_src(_param)) {\
|
|
BOOST_PP_SEQ_FOR_EACH_I(PARAM_ENUM_CONVERT__,\
|
|
(_dst(_param),PARAM_FNAME(_param),PARAM_FENUM_PREFIX(_param)),PARAM_FSEQ(_param))\
|
|
default: \
|
|
_default(_param);\
|
|
}
|
|
|
|
/** Default handling in #PARAM_ENUM_CONVERT and #PARAM_ENUM_CHECK*/
|
|
#define PARAM_ENUM_EXCEPT(_param) \
|
|
throw Base::ValueError("invalid value for enum " PARAM_FNAME_STR(_param))
|
|
|
|
/** @} */
|
|
|
|
/* Convert ParamHelper defined enum type to user defined ones
|
|
*
|
|
* This assumes the user defined enum type is given in \ref ParamSeq "seq_type"
|
|
* of the parameter definition, and it has the same postfix as the ones
|
|
* speficied in \ref ParamSeq "seq" member of the parameter definition. See
|
|
* \ref ParamEnumHelper "here" for implementations
|
|
*
|
|
* \ingroup ParamEnumHelper
|
|
*
|
|
* \arg \c _src: Macro to generate source variable. The signature must be
|
|
* <tt>_src(_param)<\tt>, where \c _param is the tuple defining the parameter.
|
|
* You pass any of the \ref ParamAccessor "parameter accessors" to directly
|
|
* access the field. Or, supply your own macro to append any prefix as you
|
|
* like.
|
|
* \arg \c _dst: Same as above.
|
|
* \arg \c _default: A macro to call for invalid value. Signature should be
|
|
* <tt>_default(_param)<\tt>, where \c _param is the parameter definition. You
|
|
* can use #PARAM_ENUM_EXCEPT to throw Base::ValueError exception in FreeCAD
|
|
* \arg \c _seq: Parameter sequence
|
|
*
|
|
* For example, with the following parameter definition
|
|
* \code{.unparsed}
|
|
* #define MY_PARAM_TEST \
|
|
* ((enum,test1,Test1,0,"it's a test",(Foo)(Bar),(MyEnum1,myEnum1)) \
|
|
* ((enum,test2,Test2,0,"it's a test",(Foo)(Bar),(MyEnum2,myEnum2)))
|
|
*
|
|
* #define MY_DST(_param) BOOST_PP_CAT(my,PARAM_FNAME(_param))
|
|
* \code{.unparsed}
|
|
*
|
|
* calling
|
|
* \code{.unparsed}
|
|
* PARAM_ENUM_CONVERT(PARAM_FNAME,MY_DST,My,PARAM_ENUM_EXCEP,MY_PARAM_TEST)
|
|
* \code{.unparsed}
|
|
*
|
|
* expands to
|
|
* \code{.unparsed}
|
|
* MyEnum1 myTest1;
|
|
* switch(Test1) {
|
|
* case Test1Foo:
|
|
* myTest1 = myEnum1Foo;
|
|
* break;
|
|
* case Test1Bar:
|
|
* myTest1 = myEnum1Bar;
|
|
* break;
|
|
* default:
|
|
* throw Base::ValueError("invalid value for enum Test1");
|
|
* }
|
|
* MyEnum2 myTest2;
|
|
* switch(Test2) {
|
|
* case Test1Foo:
|
|
* myTest2 = myEnum2Foo;
|
|
* break;
|
|
* case Test2Bar:
|
|
* myTest2 = myEnum2Bar;
|
|
* break;
|
|
* default:
|
|
* throw Base::ValueError("invalid value for enum Test2");
|
|
* }
|
|
* \endcode
|
|
*
|
|
* The above code assumes you've already defined \a Test1 and \a Test2 some
|
|
* where as the source variable.
|
|
*/
|
|
#define PARAM_ENUM_CONVERT(_src,_dst,_default,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH(PARAM_ENUM_CONVERT_,(_src,_dst,_default),_seq)
|
|
|
|
|
|
#define PARAM_ENUM_CHECK_short(...)
|
|
#define PARAM_ENUM_CHECK_long(...)
|
|
#define PARAM_ENUM_CHECK_double(...)
|
|
#define PARAM_ENUM_CHECK_bool(...)
|
|
#define PARAM_ENUM_CHECK_enum PARAM_ENUM_CHECK_SINGLE
|
|
#define PARAM_ENUM_CHECK_enum2 PARAM_ENUM_CHECK_SINGLE
|
|
|
|
#define PARAM_ENUM_CHECK_enum_(_1,_name,_i,_elem) \
|
|
case BOOST_PP_CAT(_name,_elem): break;
|
|
|
|
#define PARAM_ENUM_CHECK_(_1,_args,_param) \
|
|
PARAM_TYPED(PARAM_ENUM_CHECK_,_param)(BOOST_PP_TUPLE_ELEM(0,_args),\
|
|
BOOST_PP_TUPLE_ELEM(1,_args),\
|
|
_param)
|
|
|
|
#define PARAM_ENUM_CHECK_SINGLE(_src,_default,_param) \
|
|
switch(_src(_param)) {\
|
|
BOOST_PP_SEQ_FOR_EACH_I(PARAM_ENUM_CHECK_enum_,\
|
|
PARAM_FNAME(_param),PARAM_FSEQ(_param))\
|
|
default: \
|
|
_default(_param);\
|
|
}
|
|
|
|
/* Validate enum type parameters
|
|
*
|
|
* This macro validates the value a variable of enum type parameters. See
|
|
* similar macro #PARAM_ENUM_CONVERT for detail usage.
|
|
*
|
|
* \ingroup ParamEnumHelper
|
|
*
|
|
* \arg \c _src: Macro to generate source variable. The signature must be
|
|
* <tt>_src(_param)<\tt>, where \c _param is the tuple defining the parameter.
|
|
* You pass any of the \ref ParamAccessor "parameter accessors" to directly
|
|
* access the field. Or, supply your own macro to append any prefix as you
|
|
* like.
|
|
*
|
|
* \arg \c _default: A macro to call for invalid value. Signature should be
|
|
* <tt>_default(_param)<\tt>, where \c _param is the parameter definition. You
|
|
* can use #PARAM_ENUM_EXCEPT to throw Base::ValueError exception in FreeCAD
|
|
*
|
|
* \arg \c _seq: Parameter sequence
|
|
*/
|
|
#define PARAM_ENUM_CHECK(_src,_default,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH(PARAM_ENUM_CHECK_,(_src,_default),_seq)
|
|
|
|
|
|
#define PARAM_ENUM_STRING_DECLARE_short(...)
|
|
#define PARAM_ENUM_STRING_DECLARE_long(...)
|
|
#define PARAM_ENUM_STRING_DECLARE_double(...)
|
|
#define PARAM_ENUM_STRING_DECLARE_bool(...)
|
|
#define PARAM_ENUM_STRING_DECLARE_enum2 PARAM_ENUM_STRING_DECLARE_enum
|
|
|
|
/** Helper for #PARAM_ENUM_STRING_DECLARE */
|
|
#define PARAM_ENUM_STRING_DECLARE_enum(_prefix,_param) \
|
|
BOOST_PP_CAT(_prefix,PARAM_FNAME(_param))[] = {PARAM_FSEQ_STR(_param),NULL};
|
|
|
|
/** Helper for #PARAM_ENUM_STRING_DECLARE */
|
|
#define PARAM_ENUM_STRING_DECLARE_(_1,_prefix,_param) \
|
|
PARAM_TYPED(PARAM_ENUM_STRING_DECLARE_,_param)(_prefix,_param)
|
|
|
|
/** Make \c enum string list
|
|
*
|
|
* Roughly translated:
|
|
* \code{.unparsed}
|
|
* _prefix##_name1[] = {#seq1[0], #seq1[1], ...,NULL};
|
|
* _prefix##_name2[] = {#seq2[0], #seq2[1], ...,NULL};
|
|
* ...
|
|
* \endcode
|
|
* Example usage:
|
|
* PARAM_ENUM_STRING_DECLARE(static const char *Enum, MyParamsSeq)
|
|
* \ingroup ParamEnumHelper
|
|
*/
|
|
#define PARAM_ENUM_STRING_DECLARE(_prefix,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH(PARAM_ENUM_STRING_DECLARE_,_prefix,_seq)
|
|
|
|
|
|
/** Helper for #PARAM_INIT */
|
|
#define PARAM_INIT_(_,_src,_i,_param) \
|
|
BOOST_PP_COMMA_IF(_i) _src(_param)(PARAM_FDEF(_param))
|
|
|
|
/** Constructor initialization
|
|
*
|
|
* \arg \c _src: macro to generate source field. See \ref ParamSrc "here" for
|
|
* more details
|
|
*
|
|
* Expand to,
|
|
* \code{.unparsed}
|
|
* _src(_param1)(def1), _src(_param1)(def2)...
|
|
* \endcode
|
|
* \ingroup ParamCommon
|
|
*/
|
|
#define PARAM_INIT(_src,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH_I(PARAM_INIT_,_src,_seq)
|
|
|
|
|
|
/** Helper for #PARAM_OP */
|
|
#define PARAM_OP_(_,_args,_param) \
|
|
BOOST_PP_TUPLE_ELEM(0,_args)(_param) BOOST_PP_TUPLE_ELEM(1,_args) \
|
|
BOOST_PP_TUPLE_ELEM(2,_args)(_param);
|
|
|
|
/** Perform operation on two instance of each parameter in a sequence
|
|
*
|
|
* \arg \c _src: Macro to generate source variable. The signature must be
|
|
* <tt>_src(_param)<\tt>, where \c _param is the tuple defining the parameter.
|
|
* You pass any of the \ref ParamAccessor "parameter accessors" to directly
|
|
* access the field. Or, supply your own macro to append any prefix as you
|
|
* like.
|
|
* \arg \c _op: a boolean operator
|
|
* \arg \c _dst: Same as \c _src above.
|
|
*
|
|
* Expands to:
|
|
* \code{.unparsed}
|
|
* _src(_param1) _op _src(_param2);
|
|
* \endcode
|
|
*
|
|
* \ingroup ParamCommon
|
|
*/
|
|
#define PARAM_OP(_src,_op,_dst,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH(PARAM_COPY_,(_src,_op,_dst),_seq)
|
|
|
|
|
|
/** Helper for #PARAM_ARGS_DEF */
|
|
#define PARAM_ARGS_DEF_(_,_src,_i,_param) \
|
|
BOOST_PP_COMMA_IF(_i) PARAM_TYPE(_param) _src(_param)=PARAM_FDEF(_param)
|
|
|
|
/** Delcare the parameters as function argument list with defaults.
|
|
*
|
|
* \arg \c _src: macro to generate source field. See \ref ParamSrc "here" for
|
|
* more details
|
|
*
|
|
* Expand to:
|
|
* \code{.unparsed}
|
|
* type1 _src(_param1)=def1, type2 _src(_param1)=def2 ...
|
|
* \endcode
|
|
* \ingroup ParamCommon
|
|
*/
|
|
#define PARAM_ARGS_DEF(_src,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH_I(PARAM_ARGS_DEF_,_src,_seq)
|
|
|
|
|
|
/** Helper for #PARAM_ARGS */
|
|
#define PARAM_ARGS_(_,_src,_i,_param) \
|
|
BOOST_PP_COMMA_IF(_i) PARAM_TYPE(_param) _src(_param)
|
|
|
|
/** Delcare the parameters as function argument list without defaults.
|
|
*
|
|
* \arg \c _src: macro to generate source field. See \ref ParamSrc "here" for
|
|
* more details
|
|
*
|
|
* Expand to:
|
|
* \code{.unparsed}
|
|
* type1 _src(_param1), type2 _src(_param2) ...
|
|
* \endcode
|
|
* \ingroup ParamCommon
|
|
*/
|
|
#define PARAM_ARGS(_src,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH_I(PARAM_ARGS_,_src,_seq)
|
|
|
|
|
|
/** \defgroup ParamPy Python helper
|
|
* Helper macros for Python bindings
|
|
* \ingroup ParamHelper
|
|
*/
|
|
|
|
/** \defgroup ParamDoc Python doc helper
|
|
* Generate argument doc string for Python
|
|
* \ingroup ParamPy
|
|
*/
|
|
|
|
/** Helper for #PARAM_PY_DOC_enum */
|
|
#define PARAM_PY_DOC_enum_(_i,_elem) \
|
|
BOOST_PP_IF(_i,","," ") #_i "=" #_elem
|
|
|
|
/** Generate doc for an enum parameter */
|
|
#define PARAM_PY_DOC_enum(_field,_param) \
|
|
"\n* " PARAM_FIELD_STR(_field,_param) "(" PARAM_FDEF_STR(_param)"):" \
|
|
PARAM_FOREACH_I(PARAM_PY_DOC_enum_, PARAM_FSEQ(_param)) ". " \
|
|
PARAM_FDOC(_param) "\n"
|
|
|
|
/* Generate doc for other type of parameter */
|
|
#define PARAM_PY_DOC_short(_field,_param) \
|
|
"\n* " PARAM_FIELD_STR(_field,_param) "(" PARAM_FDEF_STR(_param)"): " \
|
|
PARAM_FDOC(_param) "\n"
|
|
#define PARAM_PY_DOC_long PARAM_PY_DOC_short
|
|
#define PARAM_PY_DOC_double PARAM_PY_DOC_short
|
|
#define PARAM_PY_DOC_bool PARAM_PY_DOC_short
|
|
#define PARAM_PY_DOC_enum2 PARAM_PY_DOC_enum
|
|
|
|
#define PARAM_PY_DOC_(_,_field,_param) \
|
|
PARAM_TYPED(PARAM_PY_DOC_,_param)(_field,_param)
|
|
|
|
/* Generate document of a sequence of parameters
|
|
* \ingroup ParamDoc
|
|
*/
|
|
#define PARAM_PY_DOC(_field,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DOC_,_field,_seq)
|
|
|
|
|
|
/** Helper for #PARAM_PY_ARGS_DOC */
|
|
#define PARAM_PY_ARGS_DOC_(_,_field,_i,_param) \
|
|
BOOST_PP_IF(_i,", "," ") PARAM_FIELD_STR(_field,_param) "=" PARAM_FDEF_STR(_param)
|
|
|
|
/** Generate argument list string
|
|
* \arg \c _field: specifies the \ref ParamField "field" to use as name
|
|
*
|
|
* Expand to a single string:
|
|
* \code{.unparsed}
|
|
* "_field1=_def1,_field2=_def2 ..."
|
|
* \endcode
|
|
*
|
|
* \ingroup ParamDoc
|
|
*/
|
|
#define PARAM_PY_ARGS_DOC(_field,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH_I(PARAM_PY_ARGS_DOC_,_field,_seq)
|
|
|
|
|
|
/** Helper for #PARAM_FIELDS */
|
|
#define PARAM_FIELDS_(_1,_src,_i,_param) \
|
|
BOOST_PP_COMMA_IF(_i) _src(_param)
|
|
|
|
/** Expand to a list of the given field in the parameter sequence
|
|
*
|
|
* \arg \c _src: macro to generate source field. See \ref ParamSrc "here" for
|
|
* more details
|
|
*
|
|
* For example, PARAM_FIELDS(PARAM_FARG, _seq) expands to:
|
|
* \code{.unparsed}
|
|
* arg1,arg2 ...
|
|
* \endcode
|
|
* \ingroup ParamCommon ParamPy
|
|
*/
|
|
#define PARAM_FIELDS(_src,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH_I(PARAM_FIELDS_,_src,_seq)
|
|
|
|
|
|
#define PARAM_PY_CAST_short(_v) (_v)
|
|
#define PARAM_PY_CAST_long(_v) (_v)
|
|
#define PARAM_PY_CAST_double(_v) (_v)
|
|
#define PARAM_PY_CAST_bool(_v) ((_v)?Py_True:Py_False)
|
|
#define PARAM_PY_CAST_enum(_v) (_v)
|
|
#define PARAM_PY_CAST_enum2(_v) (_v)
|
|
|
|
#define PARAM_CAST_PY_short(_v) (_v)
|
|
#define PARAM_CAST_PY_long(_v) (_v)
|
|
#define PARAM_CAST_PY_double(_v) (_v)
|
|
#define PARAM_CAST_PY_bool(_v) (PyObject_IsTrue(_v)?true:false)
|
|
#define PARAM_CAST_PY_enum(_v) (_v)
|
|
#define PARAM_CAST_PY_enum2(_v) (_v)
|
|
|
|
|
|
/** Helper for #PARAM_PY_FIELDS */
|
|
#define PARAM_PY_FIELDS_(_1,_src,_i,_param) \
|
|
BOOST_PP_COMMA_IF(_i) PARAM_TYPED(PARAM_CAST_PY_,_param)(_src(_param))
|
|
|
|
/** Expand to a comma separated list of the given field in the sequence
|
|
*
|
|
* \arg \c _src: macro to generate source field. See \ref ParamSrc "here" for
|
|
* more details
|
|
*
|
|
* The field will be casted from python C to C type
|
|
* \ingroup ParamCommon ParamPy
|
|
*/
|
|
#define PARAM_PY_FIELDS(_src,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH_I(PARAM_PY_FIELDS_,_src,_seq)
|
|
|
|
|
|
/** Helper for #PARAM_FIELD_STRINGS */
|
|
#define PARAM_FIELD_STRINGS_(_1,_field,_i,_param) \
|
|
BOOST_PP_COMMA_IF(_i) PARAM_FIELD_STR(_field,_param)
|
|
|
|
/** Expand to a list of stringified fields
|
|
* \ingroup ParamStringizer ParamPy
|
|
*/
|
|
#define PARAM_FIELD_STRINGS(_field,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH_I(PARAM_FIELD_STRINGS_,_field,_seq)
|
|
|
|
|
|
#define PARAM_PYARG_short "h"
|
|
#define PARAM_PYARG_long "l"
|
|
#define PARAM_PYARG_double "d"
|
|
#define PARAM_PYARG_bool "O"
|
|
#define PARAM_PYARG_enum "h"
|
|
#define PARAM_PYARG_enum2 "h"
|
|
|
|
/** Helper for #PARAM_PY_KWDS */
|
|
#define PARAM_PY_KWDS_(_param) \
|
|
PARAM_TYPED(PARAM_PYARG_,_param)
|
|
|
|
/** Generate a format string for kewords based argument
|
|
* \ingroup ParamPy
|
|
*/
|
|
#define PARAM_PY_KWDS(_seq) \
|
|
PARAM_FOREACH(PARAM_PY_KWDS_,_seq)
|
|
|
|
#define PARAM_PY_TYPE_short short
|
|
#define PARAM_PY_TYPE_long long
|
|
#define PARAM_PY_TYPE_double double
|
|
#define PARAM_PY_TYPE_bool PyObject*
|
|
#define PARAM_PY_TYPE_enum short
|
|
#define PARAM_PY_TYPE_enum2 short
|
|
|
|
/** Helper for #PARAM_PY_DECLARE */
|
|
#define PARAM_PY_DECLARE_(_1,_src,_param) \
|
|
PARAM_TYPED(PARAM_PY_TYPE_,_param) _src(_param);
|
|
|
|
/** Declare field variables for Python C type without initialization
|
|
* \ingroup ParamPy
|
|
*/
|
|
#define PARAM_PY_DECLARE(_src,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DECLARE_,_src,_seq)
|
|
|
|
#define PARAM_PY_INIT_short(_v) _v
|
|
#define PARAM_PY_INIT_long(_v) _v
|
|
#define PARAM_PY_INIT_double(_v) _v
|
|
#define PARAM_PY_INIT_bool(_v) ((_v)?Py_True:Py_False)
|
|
#define PARAM_PY_INIT_enum(_v) _v
|
|
#define PARAM_PY_INIT_enum2(_v) _v
|
|
|
|
/** Helper for #PARAM_PY_DECLARE_INIT */
|
|
#define PARAM_PY_DECLARE_INIT_(_1,_src,_param) \
|
|
PARAM_TYPED(PARAM_PY_TYPE_,_param) _src(_param) = \
|
|
PARAM_TYPED(PARAM_PY_INIT_,_param)(PARAM_FDEF(_param));
|
|
|
|
/** Declare field variables of Python c type with initialization to default
|
|
* \ingroup ParamPy
|
|
*/
|
|
#define PARAM_PY_DECLARE_INIT(_src,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DECLARE_INIT_,_src,_seq)
|
|
|
|
|
|
/** Helper for #PARAM_REF */
|
|
#define PARAM_REF_(_1,_src,_i,_param) \
|
|
BOOST_PP_COMMA_IF(_i) &_src(_param)
|
|
|
|
/** Generate a list of field references
|
|
*
|
|
* \arg \c _src: macro to generate source field. See \ref ParamSrc "here" for
|
|
*
|
|
* more details
|
|
* Expand to:
|
|
* \code{.unparsed}
|
|
* &_src(_param1), &_src(_param1) ...
|
|
* \endcode
|
|
* \ingroup ParamPy
|
|
*/
|
|
#define PARAM_REF(_src,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH_I(PARAM_REF_,_src,_seq)
|
|
|
|
#if PY_MAJOR_VERSION < 3
|
|
#define PARAM_CAST_PYOBJ_short(_v) PyInt_FromLong(_v)
|
|
#define PARAM_CAST_PYOBJ_long(_v) PyInt_FromLong(_v)
|
|
#else
|
|
#define PARAM_CAST_PYOBJ_short(_v) PyLong_FromLong(_v)
|
|
#define PARAM_CAST_PYOBJ_long(_v) PyLong_FromLong(_v)
|
|
#endif
|
|
|
|
#define PARAM_CAST_PYOBJ_double(_v) PyFloat_FromDouble(_v)
|
|
#define PARAM_CAST_PYOBJ_bool(_v) ((_v)?Py_True:Py_False)
|
|
#define PARAM_CAST_PYOBJ_enum PARAM_CAST_PYOBJ_short
|
|
#define PARAM_CAST_PYOBJ_enum2 PARAM_CAST_PYOBJ_short
|
|
|
|
|
|
/** Stringize field to a Python string
|
|
* \ingroup ParamPy ParamStringizer
|
|
*/
|
|
#if PY_MAJOR_VERSION < 3
|
|
#define PARAM_PY_STR(_field,_param) \
|
|
PyString_FromString(PARAM_FIELD_STR(_field,_param))
|
|
#else
|
|
#define PARAM_PY_STR(_field,_param) \
|
|
PyUnicode_FromString(PARAM_FIELD_STR(_field,_param))
|
|
#endif
|
|
/** Helper for #PARAM_PY_DICT_SET_VALUE */
|
|
#define PARAM_PY_DICT_SET_VALUE_(_1,_args,_param) \
|
|
PyDict_SetItem(BOOST_PP_TUPLE_ELEM(0,_args), \
|
|
PARAM_PY_STR(BOOST_PP_TUPLE_ELEM(1,_args),_param),\
|
|
PARAM_TYPED(PARAM_CAST_PYOBJ_,_param)(\
|
|
BOOST_PP_TUPLE_ELEM(2,_args)(_param)));
|
|
|
|
/** Populate a Python dict with a structure variable
|
|
*
|
|
* \arg \c _dict: the Python dictionary object
|
|
* \arg \c _field: specifies the \ref ParamField "field" to use as key
|
|
* \arg \c _src: macro to generate source field. See \ref ParamSrc "here" for
|
|
* more details
|
|
*
|
|
* Roughly translated to:
|
|
* \code{.unparsed}
|
|
* PyDict_SetItem(_dict,#_field1,_src(_param));
|
|
* PyDict_SetItem(_dict,#_field2,_src(_param));
|
|
* ...
|
|
* \endcode
|
|
* \ingroup ParamPy
|
|
*/
|
|
#define PARAM_PY_DICT_SET_VALUE(_dict,_field,_src,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DICT_SET_VALUE_,(_dict,_field,_src),_seq)
|
|
|
|
|
|
#define PARAM_PY_DICT_DOC_enum_(_i,_elem) \
|
|
BOOST_PP_IF(_i,","," ") #_i "=" #_elem
|
|
|
|
/** Generate doc for an enum parameter */
|
|
#define PARAM_PY_DICT_DOC_enum(_param) \
|
|
"(" PARAM_FDEF_STR(_param) ") - " \
|
|
PARAM_FOREACH_I(PARAM_PY_DOC_enum_, PARAM_FSEQ(_param)) ".\n" \
|
|
PARAM_FDOC(_param) "\n"
|
|
|
|
/* Generate doc for other type of parameter */
|
|
#define PARAM_PY_DICT_DOC_(_param) \
|
|
"(" PARAM_FDEF_STR(_param) ") - " PARAM_FDOC(_param) "\n"
|
|
|
|
|
|
#define PARAM_PY_DICT_DOC_short PARAM_PY_DICT_DOC_
|
|
#define PARAM_PY_DICT_DOC_long PARAM_PY_DICT_DOC_
|
|
#define PARAM_PY_DICT_DOC_double PARAM_PY_DICT_DOC_
|
|
#define PARAM_PY_DICT_DOC_bool PARAM_PY_DICT_DOC_
|
|
#define PARAM_PY_DICT_DOC_enum2 PARAM_PY_DICT_DOC_enum
|
|
|
|
/** Helper for #PARAM_PY_DICT_SET_DOC */
|
|
#if PY_MAJOR_VERSION < 3
|
|
#define PARAM_PY_DICT_SET_DOC_(_1,_args,_param) \
|
|
PyDict_SetItem(BOOST_PP_TUPLE_ELEM(0,_args), \
|
|
PARAM_PY_STR(BOOST_PP_TUPLE_ELEM(1,_args),_param),\
|
|
PyString_FromString(PARAM_TYPED(PARAM_PY_DICT_DOC_,_param)(_param)));
|
|
#else
|
|
#define PARAM_PY_DICT_SET_DOC_(_1,_args,_param) \
|
|
PyDict_SetItem(BOOST_PP_TUPLE_ELEM(0,_args), \
|
|
PARAM_PY_STR(BOOST_PP_TUPLE_ELEM(1,_args),_param),\
|
|
PyUnicode_FromString(PARAM_TYPED(PARAM_PY_DICT_DOC_,_param)(_param)));
|
|
#endif
|
|
|
|
/** Populate a Python dict with the doc field of the parameter sequence
|
|
*
|
|
* \arg \c _dict: the Python dictionary object
|
|
* \arg \c _field: specifies the \ref ParamField "field" to use as key
|
|
*
|
|
* Roughly translated to:
|
|
* \code{.unparsed}
|
|
* PyDict_SetItem(_dict,#_field1,doc1);
|
|
* PyDict_SetItem(_dict,#_field1,doc2);
|
|
* ...
|
|
* \endcode
|
|
* \ingroup ParamDoc
|
|
*/
|
|
#define PARAM_PY_DICT_SET_DOC(_dict,_field,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH(PARAM_PY_DICT_SET_DOC_,(_dict,_field),_seq)
|
|
|
|
|
|
/** \defgroup ParamProperty Property Macros
|
|
* Helper macros for FreeCAD properties
|
|
* \ingroup ParamHelper
|
|
* @{*/
|
|
#define PARAM_PROP_bool(_param) App::PropertyBool PARAM_FNAME(_param)
|
|
#define PARAM_PROP_double(_param) PARAM_FPROP(_param) PARAM_FNAME(_param)
|
|
#define PARAM_PROP_short(_param) App::PropertyInteger PARAM_FNAME(_param)
|
|
#define PARAM_PROP_long(_param) App::PropertyInteger PARAM_FNAME(_param)
|
|
#define PARAM_PROP_enum(_param) App::PropertyEnumeration PARAM_FNAME(_param)
|
|
#define PARAM_PROP_enum2(_param) App::PropertyEnumeration PARAM_FNAME(_param)
|
|
/** @} */
|
|
|
|
/** Helper for #PARAM_PROP_DECLARE */
|
|
#define PARAM_PROP_DECLARE_(_param) \
|
|
PARAM_TYPED(PARAM_PROP_,_param)(_param);
|
|
|
|
/** Declare FreeCAD properties
|
|
* \ingroup ParamProperty
|
|
*/
|
|
#define PARAM_PROP_DECLARE(_seq) \
|
|
PARAM_FOREACH(PARAM_PROP_DECLARE_,_seq)
|
|
|
|
/** Replace FreeCAD #ADD_PROPERTY_TYPE to fix singifying macro */
|
|
#define PARAM_ADD_PROPERTY_TYPE(_prop_, _defaultval_, _group_,_type_,_Docu_) \
|
|
do { \
|
|
this->_prop_.setValue _defaultval_;\
|
|
this->_prop_.setContainer(this); \
|
|
propertyData.addProperty(static_cast<App::PropertyContainer*>(this), BOOST_PP_STRINGIZE(_prop_), &this->_prop_, (_group_),(_type_),(_Docu_)); \
|
|
} while (0)
|
|
|
|
/** Generic property adding */
|
|
#define PARAM_PROP_ADD_(_group,_param) \
|
|
PARAM_ADD_PROPERTY_TYPE(PARAM_FNAME(_param), (PARAM_FDEF(_param)),\
|
|
_group,App::Prop_None,PARAM_FDOC(_param));
|
|
|
|
#define PARAM_PROP_ADD_short PARAM_PROP_ADD_
|
|
#define PARAM_PROP_ADD_long PARAM_PROP_ADD_
|
|
#define PARAM_PROP_ADD_double PARAM_PROP_ADD_
|
|
#define PARAM_PROP_ADD_bool PARAM_PROP_ADD_
|
|
#define PARAM_PROP_ADD_enum2 PARAM_PROP_ADD_enum
|
|
|
|
/** Add \c enum type parameter as property */
|
|
#define PARAM_PROP_ADD_enum(_group,_param) \
|
|
PARAM_ADD_PROPERTY_TYPE(PARAM_FNAME(_param), ((long)PARAM_FDEF(_param)),\
|
|
_group,App::Prop_None,PARAM_FDOC(_param));
|
|
|
|
/** Helper for #PARAM_PROP_ADD */
|
|
#define PARAM_PROP_ADD_TYPED(_1,_group,_i,_param) \
|
|
PARAM_TYPED(PARAM_PROP_ADD_,_param)(_group,_param)
|
|
|
|
/** Add FreeCAD properties
|
|
* \ingroup ParamProperty
|
|
*/
|
|
#define PARAM_PROP_ADD(_group,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH_I(PARAM_PROP_ADD_TYPED,_group,_seq)
|
|
|
|
#define PARAM_PROP_SET_ENUM_short(...)
|
|
#define PARAM_PROP_SET_ENUM_long(...)
|
|
#define PARAM_PROP_SET_ENUM_bool(...)
|
|
#define PARAM_PROP_SET_ENUM_double(...)
|
|
#define PARAM_PROP_SET_ENUM_enum2 PARAM_PROP_SET_ENUM_enum
|
|
|
|
/** Setup \c enum type parameter */
|
|
#define PARAM_PROP_SET_ENUM_enum(_prefix,_param) \
|
|
PARAM_FNAME(_param).setEnums(BOOST_PP_CAT(_prefix,PARAM_FNAME(_param)));
|
|
|
|
/** Helper for #PARAM_PROP_SET_ENUM */
|
|
#define PARAM_PROP_SET_ENUM_TYPED(_1,_prefix,_param) \
|
|
PARAM_TYPED(PARAM_PROP_SET_ENUM_,_param)(_prefix,_param)
|
|
|
|
/* Setup the \c enum string list for \c enum type properties
|
|
* \ingroup ParamProperty
|
|
*/
|
|
#define PARAM_PROP_SET_ENUM(_prefix,_seq) \
|
|
BOOST_PP_SEQ_FOR_EACH(PARAM_PROP_SET_ENUM_TYPED,_prefix,_seq)
|
|
|
|
|
|
/** Helper for #PARAM_PROP_ARGS */
|
|
#define PARAM_PROP_ARGS_(_i,_param) \
|
|
BOOST_PP_COMMA_IF(_i) PARAM_FNAME(_param).getValue()
|
|
|
|
/** Expand the property list as function arguments
|
|
*
|
|
* Expand to:
|
|
* \code{.unparsed}
|
|
* name1.getValue(), name2.getValue() ...
|
|
* \endcode
|
|
* \ingroup ParamProperty
|
|
*/
|
|
#define PARAM_PROP_ARGS(_seq) \
|
|
PARAM_FOREACH_I(PARAM_PROP_ARGS_,_seq)
|
|
|
|
|
|
/** Helper for #PARAM_PROP_TOUCHED */
|
|
#define PARAM_PROP_TOUCHED_(_param) \
|
|
if(PARAM_FNAME(_param).isTouched()) return 1;
|
|
|
|
/** Returns 1 if any properties is touched
|
|
*
|
|
* Expand to:
|
|
* \code{.unparsed}
|
|
* if(name1.isTouched()) return 1;
|
|
* if(name2.isTouched()) return 1;
|
|
* ...
|
|
* \ingroup ParamProperty
|
|
*/
|
|
#define PARAM_PROP_TOUCHED(_seq) \
|
|
PARAM_FOREACH(PARAM_PROP_TOUCHED_,_seq)
|
|
|
|
#endif // PARAMS_HELPER_H
|