moved kdeaccessibility kdeaddons kdeadmin kdeartwork kdebindings kdeedu kdegames...
[kdeedu.git] / kig / misc / argsparser.h
blob56d0eb79080d31e0c0a25c02a4aaa44bab3be00b
1 // Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License
5 // as published by the Free Software Foundation; either version 2
6 // of the License, or (at your option) any later version.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
16 // 02111-1307, USA.
18 #ifndef KIG_MISC_ARGSPARSER_H
19 #define KIG_MISC_ARGSPARSER_H
21 #include "../objects/common.h"
23 #include <string>
25 class ObjectImpType;
27 /**
28 * This class is meant to take care of checking the types of the
29 * parents to ObjectCalcer's, and to put them in the correct order.
30 * An ObjectType should construct an ArgsParser with a specification
31 * of the arguments it wants. This specification is given as an array
32 * of ArgsParser::spec structs. This struct contains a pointer to an
33 * ObjectImpType ( which is the type you want the argument to have ),
34 * a string ( which is an I18N_NOOP'd string describing what you will
35 * be using the argument for ) and a boolean ( which says whether the
36 * constructed object is by construction on the curve argument ( if
37 * the constructed object is a point ), or whether the constructed
38 * object is by construction through the point argument ( if the
39 * constructed object is a curve ) ).
41 * An ObjectType using an ArgsParser to take care of the various
42 * things that it can handle ( impRequirement, the sortArgs functions
43 * and the isDefinedOnOrThrough stuff ), should inherit from
44 * ArgsParserObjectType, which takes care of calling the ArgsParser
45 * for these things... It also allows you to use a convenient
46 * ObjectConstructor for your type.
48 * E.g., let's see what CircleBCPType has for its arguments spec:
49 * here's some code:
50 * <code>
51 * static const ArgsParser::spec argsspecTranslation[] =
52 * {
53 * { ObjectImp::stype(), I18N_NOOP("Translate this object"), false },
54 * { VectorImp::stype(), I18N_NOOP("Translate by this vector"), false }
55 * };
57 * TranslatedType::TranslatedType()
58 * : ArgsParserObjectType( "Translation", argsspecTranslation, 2 )
59 * {
60 * }
62 * ObjectImp* TranslatedType::calc( const Args& args, const KigDocument& ) const
63 * {
64 * if ( ! margsparser.checkArgs( args ) ) return new InvalidImp;
66 * Coordinate dir = static_cast<const VectorImp*>( args[1] )->dir();
67 * Transformation t = Transformation::translation( dir );
69 * return args[0]->transform( t );
70 * }
71 * </code>
73 * As you can see above, the argsspec can be declared right in the
74 * cpp-file. The usetexts explain to the user what the argument in
75 * question will be used for. The boolean says that in this case, the
76 * constructed object is not by construction on or through one of its
77 * arguments. In the constructor, you simply call the
78 * ArgsParserObjectType with the argsspec struct you defined, and the
79 * number of arguments in the argsspec ( in this case 2 ).
81 * In the calc function, you can rely on the arguments already being
82 * in the correct order ( the same order as you put them in in the
83 * arguments spec. You should use the checkArgs function to check if
84 * all the arguments are valid, and if they aren't return a
85 * InvalidImp. All objects can always become invalid ( e.g. an
86 * intersection point of two non-intersecting conics can become valid
87 * again when the conics move ), and you should always check for this.
89 * An interesting to note here is that the first argument is of a more
90 * general type than the second. A VectorImp is *also* an ObjectImp.
91 * In general, when this happens, you should put the more general type
92 * first, as in general this produces the results that the user
93 * expects. I have no formal proof for this, just talking from
94 * experience. It might be that you experience different things, but
95 * unless you're sure of the results, put the more general type first.
97 * This class uses a pretty basic algorithm for doing the parsing (
98 * e.g. if a match fails in one order, it does not try a different
99 * order, which could perhaps be necessary in the case of having more
100 * general argument types in the same argument spec ). However, the
101 * current algorithm works in all the situation where I've tested it,
102 * and I don't feel the need to change it. Feel free to do so if you
103 * like, but even if you do, I'm not sure if I will include it in
104 * mainline Kig.
106 class ArgsParser
108 public:
109 // this are some enum values that we return from some functions.
110 enum { Invalid = 0, Valid = 1, Complete = 2 };
111 struct spec { const ObjectImpType* type; std::string usetext; std::string selectstat; bool onOrThrough;};
112 private:
113 // the args spec..
114 std::vector<spec> margs;
116 spec findSpec( const ObjectImp* o, const Args& parents ) const;
117 public:
118 ArgsParser( const struct spec* args, int n );
119 ArgsParser( const std::vector<spec>& args );
120 ArgsParser();
121 ~ArgsParser();
123 void initialize( const std::vector<spec>& args );
124 void initialize( const struct spec* args, int n );
126 // returns a new ArgsParser that wants the same args, except for the
127 // ones of the given type..
128 ArgsParser without( const ObjectImpType* type ) const;
129 // checks if os matches the argument list this parser should parse..
130 int check( const Args& os ) const;
131 int check( const std::vector<ObjectCalcer*>& os ) const;
132 // returns the usetext for the argument that o would be used for,
133 // if sel were used as parents..
134 // o should be in sel...
135 std::string usetext( const ObjectImp* o, const Args& sel ) const;
137 // returns the select statement for the next selectable argument
138 // when the given args are selected.
139 std::string selectStatement( const Args& sel ) const;
141 // this reorders the objects or args so that they are in the same
142 // order as the requested arguments..
143 Args parse( const Args& os ) const;
144 std::vector<ObjectCalcer*> parse( const std::vector<ObjectCalcer*>& os ) const;
146 // returns the minimal ObjectImp ID that o needs to inherit in order
147 // to be useful.. o should be part of parents.
148 const ObjectImpType* impRequirement( const ObjectImp* o, const Args& parents ) const;
150 // Supposing that parents would be given as parents, this function
151 // returns whether the returned ObjectImp will be, by construction,
152 // on o ( if o is a curve ), or through o ( if o is a point ).
153 bool isDefinedOnOrThrough( const ObjectImp* o, const Args& parents ) const;
155 // Checks the args according to this args specification. If the
156 // objects should never have occurred, then an assertion failure
157 // will happen, if one of the args is invalid, then false will be
158 // returned, if all is fine, then true is returned..
159 // assert that the objects are of the right types, and in the right
160 // order as what would be returned by parse( os ).. If minobjects
161 // is provided, then not all objects are needed, and it is enough if
162 // at least minobjects are available.. Use this for object types
163 // that can calc a temporary example object using less than the
164 // required args. These args need to be at the end of argsspec +
165 // anyobjsspec. If minobjects is not provided, then it is assumed
166 // that all args are necessary.
167 bool checkArgs( const std::vector<ObjectCalcer*>& os ) const;
168 bool checkArgs( const std::vector<ObjectCalcer*>& os, uint minobjects ) const;
169 bool checkArgs( const Args& os ) const;
170 bool checkArgs( const Args& os, uint minobjects ) const;
173 #endif