summaryrefslogtreecommitdiffstats
path: root/lib/kformula/indexelement.h
blob: b8e567b8012a2bab2e96281933194711b57e6f0d (plain)
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
/* This file is part of the KDE project
   Copyright (C) 2001 Andrea Rizzi <rizzi@kde.org>
	              Ulrich Kuettler <ulrich.kuettler@mailbox.tu-dresden.de>

   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., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
*/

#ifndef INDEXELEMENT_H
#define INDEXELEMENT_H

// Formula include
#include "basicelement.h"

KFORMULA_NAMESPACE_BEGIN
class SequenceElement;


/**
 * The element with up to four indexes in the four corners.
 */
class IndexElement : public BasicElement {
    IndexElement& operator=( const IndexElement& ) { return *this; }
public:

    IndexElement(BasicElement* parent = 0);
    ~IndexElement();

    IndexElement( const IndexElement& );

    virtual IndexElement* clone() {
        return new IndexElement( *this );
    }

    virtual bool accept( ElementVisitor* visitor );

    /**
     * @returns the character that represents this element. Used for
     * parsing a sequence.
     * This is guaranteed to be TQChar::null for all non-text elements.
     */
    virtual TQChar getCharacter() const;

    /**
     * The cursor has entered one of our child sequences.
     * This is a good point to tell the user where he is.
     */
    virtual void entered( SequenceElement* child );

    /**
     * Sets the cursor and returns the element the point is in.
     * The handled flag shows whether the cursor has been set.
     * This is needed because only the innermost matching element
     * is allowed to set the cursor.
     */
    virtual BasicElement* goToPos( FormulaCursor*, bool& handled,
                                   const LuPixelPoint& point, const LuPixelPoint& parentOrigin );

    // drawing
    //
    // Drawing depends on a context which knows the required properties like
    // fonts, spaces and such.
    // It is essential to calculate elements size with the same context
    // before you draw.

    /**
     * Calculates our width and height and
     * our children's parentPosition.
     */
    virtual void calcSizes( const ContextStyle& cstyle,
						    ContextStyle::TextStyle tstyle,
						    ContextStyle::IndexStyle istyle,
							StyleAttributes& style );

    /**
     * Draws the whole element including its children.
     * The `parentOrigin' is the point this element's parent starts.
     * We can use our parentPosition to get our own origin then.
     */
    virtual void draw( TQPainter& painter, const LuPixelRect& r,
                       const ContextStyle& context,
                       ContextStyle::TextStyle tstyle,
                       ContextStyle::IndexStyle istyle,
					   StyleAttributes& style,
                       const LuPixelPoint& parentOrigin );

    /**
     * Dispatch this FontCommand to all our TextElement children.
     */
    virtual void dispatchFontCommand( FontCommand* cmd );

    // navigation
    //
    // The elements are responsible to handle cursor movement themselves.
    // To do this they need to know the direction the cursor moves and
    // the element it comes from.
    //
    // The cursor might be in normal or in selection mode.

    /**
     * Enters this element while moving to the left starting inside
     * the element `from'. Searches for a cursor position inside
     * this element or to the left of it.
     */
    virtual void moveLeft(FormulaCursor* cursor, BasicElement* from);

    /**
     * Enters this element while moving to the right starting inside
     * the element `from'. Searches for a cursor position inside
     * this element or to the right of it.
     */
    virtual void moveRight(FormulaCursor* cursor, BasicElement* from);

    /**
     * Enters this element while moving up starting inside
     * the element `from'. Searches for a cursor position inside
     * this element or above it.
     */
    virtual void moveUp(FormulaCursor* cursor, BasicElement* from);

    /**
     * Enters this element while moving down starting inside
     * the element `from'. Searches for a cursor position inside
     * this element or below it.
     */
    virtual void moveDown(FormulaCursor* cursor, BasicElement* from);

    // children

    /**
     * Removes the child. If this was the main child this element might
     * request its own removal.
     * The cursor is the one that caused the removal. It has to be moved
     * to the place any user expects the cursor after that particular
     * element has been removed.
     */
    //virtual void removeChild(FormulaCursor* cursor, BasicElement* child);


    // main child
    //
    // If an element has children one has to become the main one.

    virtual SequenceElement* getMainChild() { return content; }
    //SequenceElement* upperLeft;
    //SequenceElement* upperMiddle;
    SequenceElement* getExponent() { return upperRight; }
    //SequenceElement* lowerLeft;
    //SequenceElement* lowerMiddle;
    //SequenceElement* lowerRight;


    /**
     * Inserts all new children at the cursor position. Places the
     * cursor according to the direction.
     *
     * You only can insert one index at a time. So the list must contain
     * exactly on SequenceElement. And the index you want to insert
     * must not exist already.
     *
     * The list will be emptied but stays the property of the caller.
     */
    virtual void insert(FormulaCursor*, TQPtrList<BasicElement>&, Direction);

    /**
     * Removes all selected children and returns them. Places the
     * cursor to where the children have been.
     *
     * The cursor has to be inside one of our indexes which is supposed
     * to be empty. The index will be removed and the cursor will
     * be placed to the removed index so it can be inserted again.
     * This methode is called by SequenceElement::remove only.
     *
     * The ownership of the list is passed to the caller.
     */
    virtual void remove(FormulaCursor*, TQPtrList<BasicElement>&, Direction);

    /**
     * Moves the cursor to a normal place where new elements
     * might be inserted.
     */
    virtual void normalize(FormulaCursor*, Direction);

    /**
     * Returns the child at the cursor.
     */
    virtual BasicElement* getChild(FormulaCursor*, Direction = beforeCursor);

    /**
     * Sets the cursor to select the child. The mark is placed before,
     * the position behind it.
     */
    virtual void selectChild(FormulaCursor* cursor, BasicElement* child);

    /**
     * Moves the cursor away from the given child. The cursor is
     * guaranteed to be inside this element.
     */
    //virtual void childWillVanish(FormulaCursor* cursor, BasicElement* child) = 0;

    /**
     * Returns wether the element has no more useful
     * children (except its main child) and should therefore
     * be replaced by its main child's content.
     */
    virtual bool isSenseless();


    bool hasUpperLeft()   const { return upperLeft   != 0; }
    bool hasUpperMiddle() const { return upperMiddle != 0; }
    bool hasUpperRight()  const { return upperRight  != 0; }
    bool hasLowerLeft()   const { return lowerLeft   != 0; }
    bool hasLowerMiddle() const { return lowerMiddle != 0; }
    bool hasLowerRight()  const { return lowerRight  != 0; }

    // If we want to create an index we need a cursor that points there.

    void setToUpperLeft(FormulaCursor* cursor);
    void setToUpperMiddle(FormulaCursor* cursor);
    void setToUpperRight(FormulaCursor* cursor);
    void setToLowerLeft(FormulaCursor* cursor);
    void setToLowerMiddle(FormulaCursor* cursor);
    void setToLowerRight(FormulaCursor* cursor);

    // If the index is there we need a way to move into it.

    void moveToUpperLeft(FormulaCursor* cursor, Direction direction);
    void moveToUpperMiddle(FormulaCursor* cursor, Direction direction);
    void moveToUpperRight(FormulaCursor* cursor, Direction direction);
    void moveToLowerLeft(FormulaCursor* cursor, Direction direction);
    void moveToLowerMiddle(FormulaCursor* cursor, Direction direction);
    void moveToLowerRight(FormulaCursor* cursor, Direction direction);

    // Generic access to each index.

    ElementIndexPtr getUpperLeft() { return ElementIndexPtr( new UpperLeftIndex( this ) ); }
    ElementIndexPtr getLowerLeft() { return ElementIndexPtr( new LowerLeftIndex( this ) ); }
    ElementIndexPtr getUpperMiddle() { return ElementIndexPtr( new UpperMiddleIndex( this ) ); }
    ElementIndexPtr getLowerMiddle() { return ElementIndexPtr( new LowerMiddleIndex( this ) ); }
    ElementIndexPtr getUpperRight() { return ElementIndexPtr( new UpperRightIndex( this ) ); }
    ElementIndexPtr getLowerRight() { return ElementIndexPtr( new LowerRightIndex( this ) ); }

    /**
     * Returns the index at the position. Defaults to upperRight.
     */
    ElementIndexPtr getIndex( int position );

    /**
     * @returns the latex representation of the element and
     * of the element's children
     */
    virtual TQString toLatex();

    // the upper right index is the only one we show
    virtual TQString formulaString();

protected:

    //Save/load support

    /**
     * Returns the tag name of this element type.
     */
    virtual TQString getTagName() const { return "INDEX"; }

    /**
     * Appends our attributes to the dom element.
     */
    virtual void writeDom(TQDomElement element);

    virtual TQString getElementName() const ;
    virtual void writeMathMLAttributes( TQDomElement& element ) const ;
    virtual void writeMathMLContent( TQDomDocument& doc, 
                                     TQDomElement& element,
                                     bool oasisFormat ) const ;
    /**
     * Reads our attributes from the element.
     * Returns false if it failed.
     */
    virtual bool readAttributesFromDom(TQDomElement element);

    /**
     * Reads our content from the node. Sets the node to the next node
     * that needs to be read.
     * Returns false if it failed.
     */
    virtual bool readContentFromDom(TQDomNode& node);

    virtual bool readAttributesFromMathMLDom( const TQDomElement& element );
    /**
     * Reads our content from the MathML node. Sets the node to the next node
     * that needs to be read. It is sometimes needed to read more than one node
     * (e. g. for fence operators).
     * Returns the number of nodes processed or -1 if it failed.
     */
    virtual int readContentFromMathMLDom( TQDomNode& node );

private:

    /**
     * An index that belongs to us.
     */
    class IndexElementIndex : public ElementIndex {
    public:
        IndexElementIndex(IndexElement* p) : parent(p) {}
        virtual IndexElement* getElement() { return parent; }
    protected:
        IndexElement* parent;
    };

    // We have a (very simple) type for every index.

    class UpperLeftIndex : public IndexElementIndex {
    public:
        UpperLeftIndex(IndexElement* parent) : IndexElementIndex(parent) {}
        virtual void moveToIndex(FormulaCursor* cursor, Direction direction)
            { parent->moveToUpperLeft(cursor, direction); }
        virtual void setToIndex(FormulaCursor* cursor)
            { parent->setToUpperLeft(cursor); }
        virtual bool hasIndex() const
            { return parent->hasUpperLeft(); }
    };

    class LowerLeftIndex : public IndexElementIndex {
    public:
        LowerLeftIndex(IndexElement* parent) : IndexElementIndex(parent) {}
        virtual void moveToIndex(FormulaCursor* cursor, Direction direction)
            { parent->moveToLowerLeft(cursor, direction); }
        virtual void setToIndex(FormulaCursor* cursor)
            { parent->setToLowerLeft(cursor); }
        virtual bool hasIndex() const
            { return parent->hasLowerLeft(); }
    };

    class UpperMiddleIndex : public IndexElementIndex {
    public:
        UpperMiddleIndex(IndexElement* parent) : IndexElementIndex(parent) {}
        virtual void moveToIndex(FormulaCursor* cursor, Direction direction)
            { parent->moveToUpperMiddle(cursor, direction); }
        virtual void setToIndex(FormulaCursor* cursor)
            { parent->setToUpperMiddle(cursor); }
        virtual bool hasIndex() const
            { return parent->hasUpperMiddle(); }
    };

    class LowerMiddleIndex : public IndexElementIndex {
    public:
        LowerMiddleIndex(IndexElement* parent) : IndexElementIndex(parent) {}
        virtual void moveToIndex(FormulaCursor* cursor, Direction direction)
            { parent->moveToLowerMiddle(cursor, direction); }
        virtual void setToIndex(FormulaCursor* cursor)
            { parent->setToLowerMiddle(cursor); }
        virtual bool hasIndex() const
            { return parent->hasLowerMiddle(); }
    };

    class UpperRightIndex : public IndexElementIndex {
    public:
        UpperRightIndex(IndexElement* parent) : IndexElementIndex(parent) {}
        virtual void moveToIndex(FormulaCursor* cursor, Direction direction)
            { parent->moveToUpperRight(cursor, direction); }
        virtual void setToIndex(FormulaCursor* cursor)
            { parent->setToUpperRight(cursor); }
        virtual bool hasIndex() const
            { return parent->hasUpperRight(); }
    };

    class LowerRightIndex : public IndexElementIndex {
    public:
        LowerRightIndex(IndexElement* parent) : IndexElementIndex(parent) {}
        virtual void moveToIndex(FormulaCursor* cursor, Direction direction)
            { parent->moveToLowerRight(cursor, direction); }
        virtual void setToIndex(FormulaCursor* cursor)
            { parent->setToLowerRight(cursor); }
        virtual bool hasIndex() const
            { return parent->hasLowerRight(); }
    };


    /**
     * Sets the x value of the three middle elements. (Two indexes and the content.)
     */
    void setMiddleX(int xOffset, int middleWidth);

    /**
     * @returns the position describtion to the provided element.
     */
    int getFromPos(BasicElement* from);

    /**
     * Sets the cursor to point to the place where the content is.
     * There always is a content so this is not a useful place.
     * No insertion or removal will succeed as long as the cursor is
     * there.
     */
    void setToContent(FormulaCursor* cursor);

    /**
     * Our main child. This is guaranteed not to be null.
     */
    SequenceElement* content;

    /**
     * The six indexes. Each one might be null.
     * If the last one is removed the whole IndexElement
     * should be replaced by its main child.
     */
    SequenceElement* upperLeft;
    SequenceElement* upperMiddle;
    SequenceElement* upperRight;
    SequenceElement* lowerLeft;
    SequenceElement* lowerMiddle;
    SequenceElement* lowerRight;

    /**
     * MathML attributes.
     */
    SizeType m_subScriptShiftType;
    double m_subScriptShift;
    SizeType m_superScriptShiftType;
    double m_superScriptShift;
    bool m_accentUnder;
    bool m_customAccentUnder;
    bool m_accent;
    bool m_customAccent;
};

KFORMULA_NAMESPACE_END

#endif // INDEXELEMENT_H