summaryrefslogtreecommitdiffstats
path: root/kig/misc/argsparser.h
diff options
context:
space:
mode:
Diffstat (limited to 'kig/misc/argsparser.h')
-rw-r--r--kig/misc/argsparser.h187
1 files changed, 187 insertions, 0 deletions
diff --git a/kig/misc/argsparser.h b/kig/misc/argsparser.h
new file mode 100644
index 00000000..001d9359
--- /dev/null
+++ b/kig/misc/argsparser.h
@@ -0,0 +1,187 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+
+// This program 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 General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+// 02110-1301, USA.
+
+#ifndef KIG_MISC_ARGSPARSER_H
+#define KIG_MISC_ARGSPARSER_H
+
+#include "../objects/common.h"
+
+#include <string>
+
+class ObjectImpType;
+
+/**
+ * This class is meant to take care of checking the types of the
+ * parents to ObjectCalcer's, and to put them in the correct order.
+ * An ObjectType should construct an ArgsParser with a specification
+ * of the arguments it wants. This specification is given as an array
+ * of ArgsParser::spec structs. This struct contains a pointer to an
+ * ObjectImpType ( which is the type you want the argument to have ),
+ * a string ( which is an I18N_NOOP'd string describing what you will
+ * be using the argument for ) and a boolean ( which says whether the
+ * constructed object is by construction on the curve argument ( if
+ * the constructed object is a point ), or whether the constructed
+ * object is by construction through the point argument ( if the
+ * constructed object is a curve ) ).
+ *
+ * An ObjectType using an ArgsParser to take care of the various
+ * things that it can handle ( impRequirement, the sortArgs functions
+ * and the isDefinedOnOrThrough stuff ), should inherit from
+ * ArgsParserObjectType, which takes care of calling the ArgsParser
+ * for these things... It also allows you to use a convenient
+ * ObjectConstructor for your type.
+ *
+ * E.g., let's see what CircleBCPType has for its arguments spec:
+ * here's some code:
+ * \code
+ * static const ArgsParser::spec argsspecTranslation[] =
+ * {
+ * { ObjectImp::stype(), I18N_NOOP("Translate this object"), false },
+ * { VectorImp::stype(), I18N_NOOP("Translate by this vector"), false }
+ * };
+ *
+ * TranslatedType::TranslatedType()
+ * : ArgsParserObjectType( "Translation", argsspecTranslation, 2 )
+ * {
+ * }
+ *
+ * ObjectImp* TranslatedType::calc( const Args& args, const KigDocument& ) const
+ * {
+ * if ( ! margsparser.checkArgs( args ) ) return new InvalidImp;
+ *
+ * Coordinate dir = static_cast<const VectorImp*>( args[1] )->dir();
+ * Transformation t = Transformation::translation( dir );
+ *
+ * return args[0]->transform( t );
+ * }
+ * \endcode
+ *
+ * As you can see above, the argsspec can be declared right in the
+ * cpp-file. The usetexts explain to the user what the argument in
+ * question will be used for. The boolean says that in this case, the
+ * constructed object is not by construction on or through one of its
+ * arguments. In the constructor, you simply call the
+ * ArgsParserObjectType with the argsspec struct you defined, and the
+ * number of arguments in the argsspec ( in this case 2 ).
+ *
+ * In the calc function, you can rely on the arguments already being
+ * in the correct order ( the same order as you put them in in the
+ * arguments spec. You should use the checkArgs function to check if
+ * all the arguments are valid, and if they aren't return a
+ * InvalidImp. All objects can always become invalid ( e.g. an
+ * intersection point of two non-intersecting conics can become valid
+ * again when the conics move ), and you should always check for this.
+ *
+ * An interesting to note here is that the first argument is of a more
+ * general type than the second. A VectorImp is *also* an ObjectImp.
+ * In general, when this happens, you should put the more general type
+ * first, as in general this produces the results that the user
+ * expects. I have no formal proof for this, just talking from
+ * experience. It might be that you experience different things, but
+ * unless you're sure of the results, put the more general type first.
+ *
+ * This class uses a pretty basic algorithm for doing the parsing (
+ * e.g. if a match fails in one order, it does not try a different
+ * order, which could perhaps be necessary in the case of having more
+ * general argument types in the same argument spec ). However, the
+ * current algorithm works in all the situation where I've tested it,
+ * and I don't feel the need to change it. Feel free to do so if you
+ * like, but even if you do, I'm not sure if I will include it in
+ * mainline Kig.
+ */
+class ArgsParser
+{
+public:
+ /**
+ * this are some enum values that we return from some functions.
+ */
+ enum { Invalid = 0, Valid = 1, Complete = 2 };
+ struct spec { const ObjectImpType* type; std::string usetext; std::string selectstat; bool onOrThrough;};
+private:
+ /**
+ * the args spec..
+ */
+ std::vector<spec> margs;
+
+ spec findSpec( const ObjectImp* o, const Args& parents ) const;
+public:
+ ArgsParser( const struct spec* args, int n );
+ ArgsParser( const std::vector<spec>& args );
+ ArgsParser();
+ ~ArgsParser();
+
+ void initialize( const std::vector<spec>& args );
+ void initialize( const struct spec* args, int n );
+
+ /**
+ * returns a new ArgsParser that wants the same args, except for the
+ * ones of the given type..
+ */
+ ArgsParser without( const ObjectImpType* type ) const;
+ // checks if os matches the argument list this parser should parse..
+ int check( const Args& os ) const;
+ int check( const std::vector<ObjectCalcer*>& os ) const;
+ /**
+ * returns the usetext for the argument that o would be used for,
+ * if sel were used as parents..
+ * \p o should be in \p sel ...
+ */
+ std::string usetext( const ObjectImp* o, const Args& sel ) const;
+
+ /**
+ * returns the select statement for the next selectable argument
+ * when the given args are selected.
+ */
+ std::string selectStatement( const Args& sel ) const;
+
+ // this reorders the objects or args so that they are in the same
+ // order as the requested arguments..
+ Args parse( const Args& os ) const;
+ std::vector<ObjectCalcer*> parse( const std::vector<ObjectCalcer*>& os ) const;
+
+ /**
+ * returns the minimal ObjectImp ID that \p o needs to inherit in order
+ * to be useful.. \p o should be part of \p parents .
+ */
+ const ObjectImpType* impRequirement( const ObjectImp* o, const Args& parents ) const;
+
+ /**
+ * Supposing that \p parents would be given as parents, this function
+ * returns whether the returned ObjectImp will be, by construction,
+ * on \p o ( if \p o is a curve ), or through \p o ( if \p o is a point ).
+ */
+ bool isDefinedOnOrThrough( const ObjectImp* o, const Args& parents ) const;
+
+ // Checks the args according to this args specification. If the
+ // objects should never have occurred, then an assertion failure
+ // will happen, if one of the args is invalid, then false will be
+ // returned, if all is fine, then true is returned..
+ // assert that the objects are of the right types, and in the right
+ // order as what would be returned by parse( os ).. If minobjects
+ // is provided, then not all objects are needed, and it is enough if
+ // at least minobjects are available.. Use this for object types
+ // that can calc a temporary example object using less than the
+ // required args. These args need to be at the end of argsspec +
+ // anyobjsspec. If minobjects is not provided, then it is assumed
+ // that all args are necessary.
+ bool checkArgs( const std::vector<ObjectCalcer*>& os ) const;
+ bool checkArgs( const std::vector<ObjectCalcer*>& os, uint minobjects ) const;
+ bool checkArgs( const Args& os ) const;
+ bool checkArgs( const Args& os, uint minobjects ) const;
+};
+
+#endif