File size: 37,346 Bytes
985c397 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 | // SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* 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
* \ingroup PATH
* Collections of macros for managing groups of parameters.
*
* \section motivation_groups_params 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, implementation", \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 parenthesis or comma. Then, you can use the CMake
* intermediate file target to get the preprocessor output for checking. For
* example, for a file located at \c src/Mod/CAM/App/Area.cpp,
* \code{.sh}
* cd <your_build_dir>/src/Mod/CAM/App
* make Area.cpp.i
* \endcode
*
* The preprocessed intermediate output will be at,
* \code{.sh}
* <your_build_dir>/src/Mod/CAM/App.CMakeFiles/Path.dir/Area.cpp.i
* \endcode
*
* \section intro_boost_preproc Introduction of Boost.Preprocessor
*
* The macros here make heavy use of the awesome
* [Boost.Preprocessor](http://www.boost.org/libs/preprocessor/) (short for
* Boost.PP). Here are is a brief introduction on Boost.PP concept 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 parenthesis, 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 relevant macros. It's quite trivial
* actually.
*
* - \c arg is the argument 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 argument. 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. Neither 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
* additional 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
* \ingroup PATH
* 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 should 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 should 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);
/**
* Declares 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);
/**
* Declares 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 parenthesis of \c _param is stripped,
* i.e. not double but single parenthesis
*/
#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
* specified 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)
/** Declare 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)
/** Declare 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 keywords 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)
#define PARAM_CAST_PYOBJ_short(_v) PyLong_FromLong(_v)
#define PARAM_CAST_PYOBJ_long(_v) PyLong_FromLong(_v)
#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
*/
#define PARAM_PY_STR(_field, _param) PyUnicode_FromString(PARAM_FIELD_STR(_field, _param))
/** 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 */
#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)) \
);
/** 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;
* ...
* \endcode
* \ingroup ParamProperty
*/
#define PARAM_PROP_TOUCHED(_seq) PARAM_FOREACH(PARAM_PROP_TOUCHED_, _seq)
#endif // PARAMS_HELPER_H
|