summaryrefslogtreecommitdiffstats
path: root/kword/KWCanvas.h
blob: 955ea605f3f63ad8a1fb07f50b804890638f7bb1 (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
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
/* This file is part of the KDE project
   Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
   Copyright (C) 2002-2006 David Faure <faure@kde.org>
   Copyright (C) 2005 Thomas Zander <zander@kde.org>

   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 KWCANVAS_H
#define KWCANVAS_H

#include <kprinter.h>
#include <KoRect.h>
#include <tqscrollview.h>
#include <tqstylesheet.h>
#include <KoRichText.h>
#include <KoQueryTrader.h>
#include <KoPicture.h>

#include "KWTextParag.h"
#include "KWFrame.h"
#include "KWVariable.h"
#include "KWCommand.h"

class KWTextFrameSetEdit;
class KWDocument;
class KWFrame;
class KWFrameSet;
class KWFrameSetEdit;
class KWTableFrameSet;
class KWFrameMoveCommand;
class KWViewMode;
class KWFrameViewManager;
class KWGUI;
class KWTableTemplate;
class KoTextParag;
class TQTimer;
class InteractionPolicy;
class KWFrameView;

/**
 * Class: KWCanvas
 * This class is responsible for the rendering of the frames to
 * the screen as well as the interaction with the user via mouse
 * and keyboard. There is one per view.
 */
class KWCanvas : public TQScrollView
{
    Q_OBJECT
  TQ_OBJECT

public:
    KWCanvas(const TQString& viewMode, TQWidget *parent, KWDocument *d, KWGUI *lGui);
    virtual ~KWCanvas();

    KWDocument * kWordDocument() const { return m_doc; }
    KWGUI * gui() const { return m_gui; }
    KWFrameViewManager* frameViewManager() { return m_frameViewManager; }
    KWFrameSetEdit *currentFrameSetEdit() const { return m_currentFrameSetEdit; }

    void switchViewMode( const TQString& newViewMode );
    KWViewMode *viewMode() const { return m_viewMode; }

    void repaintAll( bool erase = false );
    /**
     * Only tqrepaint the frameset @p fs.
     * @p resetChanged should only be true for the last view
     * (see KWFrameSet::drawContents)
     */
    void repaintChanged( KWFrameSet * fs, bool resetChanged );

    /** We need to tqrepaint if the window is resized. */
    void viewportResizeEvent( TQResizeEvent * );

    void print( TQPainter *painter, KPrinter *printer );
    bool eventFilter( TQObject *o, TQEvent *e );
    bool focusNextPrevChild( bool next);

    void setFrameBackgroundColor( const TQBrush &backColor );

    void editFrameProperties();
    void editFrameProperties( KWFrameSet * frameset );

    void pasteFrames();

    // Mouse press
    void mpCreate( const TQPoint& normalPoint, bool noGrid );
    void mpCreatePixmap( const TQPoint& normalPoint, bool noGrid  );
    // Mouse move
    void mmCreate( const TQPoint& normalPoint, bool noGrid );
    // Mouse release
    void mrEditFrame();
    void mrCreateText();
    void mrCreatePixmap();
    void mrCreatePart();
    void mrCreateFormula();
    void mrCreateTable();

    enum MouseMode {
        MM_EDIT = 0,
        MM_CREATE_TEXT = 2,
        MM_CREATE_PIX = 3,
        MM_CREATE_TABLE = 5,
        MM_CREATE_FORMULA = 6,
        MM_CREATE_PART = 7
    };
    void setMouseMode( MouseMode _mm );
    MouseMode mouseMode()const { return m_mouseMode; }

    // makes the user draw the rect for inserting the picture
    void insertPicture( const KoPicture& newPicture, TQSize pixmapSize, bool _keepRatio );
    void insertPart( const KoDocumentEntry &entry );
    void pasteImage( TQMimeSource *e, const KoPoint &docPoint );
    // insert a (non-inline) picture at the given position; used by dnd and dcop
    void insertPictureDirect( const KoPicture& picture, const KoPoint& pos, const TQSize& sz = TQSize() );

    void updateCurrentFormat();

    void updateFrameFormat();

    // Table creation support - methods used by KWView to reuse the last settings
    unsigned int tableRows() const { return m_table.rows; }
    void setTableRows( unsigned int rows ) { m_table.rows=rows; }
    unsigned int tableCols() const { return m_table.cols; }
    void setTableCols( unsigned int cols ) { m_table.cols=cols; }
    int tableWidthMode()const { return m_table.width; }
    int tableHeightMode()const { return m_table.height; }
    bool tableIsFloating()const { return m_table.floating; }
    int tableFormat()const { return m_table.format;}

    void setTableFormat(int _nb){ m_table.format=_nb;}

    TQString tableTemplateName()const { return m_table.tableTemplateName;}
    void setTableTemplateName(const TQString &_name) { m_table.tableTemplateName=_name;}

    void setPictureInline( bool _inline) { m_picture.pictureInline = _inline;}
    bool pictureInline() const { return m_picture.pictureInline; }

    void setPictureKeepRatio( bool _keep) { m_picture.keepRatio = _keep;}
    bool pictureKeepRatio() const { return m_picture.keepRatio; }

    void createTable( unsigned int rows, unsigned int cols,
                      int /*KWTableFrameSet::CellSize*/ wid, int /*KWTableFrameSet::CellSize*/ hei,
                      bool isFloating,
                      KWTableTemplate *tt=0L, int format=31 );

    /// The current table (either because one or more cells are selected,
    /// or because the cursor is in a table cell
    KWTableFrameSet *getCurrentTable()const { return m_currentTable; }
    /// When the cursor is in a table cell, this returns the row
    int currentTableRow() const;
    /// When the cursor is in a table cell, this returns the column
    int currentTableCol() const;

    //move canvas to show point dPoint (in doc coordinates)
    void scrollToOffset( const KoPoint & dPoint );

    //for KWTextFrameSetEdit
    void dragStarted() { m_mousePressed = false; }

    void setXimPosition( int x, int y, int w, int h );

    void updateRulerOffsets( int cx = -1, int cy = -1 );

    void inlinePictureStarted();

    void ensureCursorVisible();

    void editFrameSet( KWFrameSet * frameSet, bool onlyText = false );
    /**
     * Starting editing @p fs if we're not yet doing it.
     * In all cases, position the cursor at @p parag and @p index.
     */
    void editTextFrameSet( KWFrameSet * fs, KoTextParag* parag, int index );
    bool checkCurrentEdit( KWFrameSet * fs, bool onlyText = false);


    NoteType footNoteType()const{return m_footEndNote.noteType;}
    KWFootNoteVariable::Numbering numberingFootNoteType() const { return m_footEndNote.numberingType;}

    void setFootNoteType( NoteType _type ) { m_footEndNote.noteType = _type; }
    void setNumberingFootNoteType(KWFootNoteVariable::Numbering _type) { m_footEndNote.numberingType = _type; }

    void tableSelectCell(KWTableFrameSet *table, KWFrameSet *cell);
    void selectAllFrames( bool select );

    KCommand * createTextBox(const KoRect & rect );

    // Called by KWTextFrameSetEdit when pgup/pgdown can't go further
    // or directly called by pgup/pgdown if not using 'moves caret' feature.
    void viewportScroll( bool up );

    /// Resets the status bar text
    void resetStatusBarText();

    /** Returns the caret position in document coordinates.
        The current frame must be editable, i.e., a caret is possible. */
    KoPoint caretPos();
    void applyGrid( KoPoint &p );

    bool overwriteMode() const { return m_overwriteMode; }

    // Returns the current text edit object, or 0 if
    // - no frame is being edited
    // - a non-text frame is being edited
    KWTextFrameSetEdit* currentTextEdit() const;

    bool insertInlinePicture();

protected:
    void drawGrid( TQPainter &p, const TQRect& rect );

    /**
     * Reimplemented from TQScrollView, to draw the contents of the canvas
     */
    virtual void drawContents( TQPainter *p, int cx, int cy, int cw, int ch );
    /**
     * The main drawing method.
     * @param painter guess
     * @param crect the area to be repainted, in contents coordinates
     * @param viewMode the view mode to be used (usually m_viewMode, except when printing)
     */
    void drawDocument( TQPainter *painter, const TQRect &crect, KWViewMode* viewMode );
    /**
     * Draw page borders, but also clear up the space between the frames and the page borders,
     * draw the page shadow, and the gray area.
     */
    void drawPageBorders( TQPainter * painter, const TQRect & crect, const TQRegion & emptySpaceRegion );

    virtual void keyPressEvent( TQKeyEvent *e );
    virtual void contentsMousePressEvent( TQMouseEvent *e );
    virtual void contentsMouseMoveEvent( TQMouseEvent *e );
    virtual void contentsMouseReleaseEvent( TQMouseEvent *e );
    virtual void contentsMouseDoubleClickEvent( TQMouseEvent *e );
    virtual void contentsDragEnterEvent( TQDragEnterEvent *e );
    virtual void contentsDragMoveEvent( TQDragMoveEvent *e );
    virtual void contentsDragLeaveEvent( TQDragLeaveEvent *e );
    virtual void contentsDropEvent( TQDropEvent *e );
    virtual void resizeEvent( TQResizeEvent *e );

    KWTableFrameSet * createTable(); // uses m_insRect and m_table to create the table

    void terminateCurrentEdit();
    bool insertInlineTable();

signals:
    // Emitted when the current frameset edit changes
    void currentFrameSetEditChanged();
    // Emitted by the current frameset edit when its selection changes
    void selectionChanged( bool hasSelection );
    // Emitted when Mouse Mode changed
    void currentMouseModeChanged(int newMouseMode);
    // Emitted when frames have been selected or unselected (to disable/enable the UI in kwview)
    void frameSelectedChanged();
    // Emitted when the document structure has changed
    // ### DF: IMHO this should be only emitted by KWDocument (e.g. addFrameSet)
    void docStructChanged(int _type);
    // Emitted when the insert key is pressed
    void overwriteModeChanged( bool m_overwriteMode );

    void viewTransformationsChanged();

    void updateRuler();

private slots:
    void slotContentsMoving( int, int );
    void slotNewContentsSize();
    void slotMainTextHeightChanged();
    void doAutoScroll();

    //Terminate editing this frameset, if we were editing it.
    void terminateEditing( KWFrameSet *fs );

private:
    /**
     * Draw the contents of one frameset
     * @param resetChanged whether the changed flag should be reset to false while redrawing
     */
    void drawFrameSet( KWFrameSet * frameset, TQPainter * painter,
                       const TQRect & crect, bool onlyChanged, bool resetChanged, KWViewMode* viewMode );

    void drawMovingRect( TQPainter & p );
    void deleteMovingRect();
    /**
     * make the parag rectangle have the aspect ratio by changing either the height
     * or the width of the ratio.
     * @param ratio the ratio the rectangle should have afterwards.
     * @param insRect the rectangle that is to be changed in-place
     */
    void applyAspectRatio( double ratio, KoRect& insRect );

#ifndef NDEBUG
    void printRTDebug( int );
#endif

    KWFrameViewManager *m_frameViewManager;
    KWDocument *m_doc;
    KWFrameSetEdit *m_currentFrameSetEdit;
    KWGUI *m_gui;
    TQTimer *m_scrollTimer;
    bool m_mousePressed;
    bool m_printing;
    bool m_imageDrag;

    //define type of frame (for set inline frame)
    bool m_frameInline;
    FrameSetType m_frameInlineType;

    // Warning: the viewmode is stored here for good design ;)
    // but it's owned by the document, since we currently have one viewmode for all views.
    KWViewMode *m_viewMode;

    // Frame stuff
    MouseMode m_mouseMode;
    MouseMeaning m_mouseMeaning; // set by mousePress, used by mouseMove
    KoRect m_resizedFrameInitialSize; // when resizing a frame
    double m_resizedFrameInitialMinHeight; // when resizing a frame
    KoRect m_insRect;  ///< variable updated and painted to represent the to insert frame
    bool m_deleteMovingRect;
    KoPicture m_kopicture; // The picture
    TQSize m_pixmapSize; // size when inserting a picture (not necessarily the size of the picture)
    bool m_keepRatio;//when inserting a picture
    KoDocumentEntry m_partEntry; // when inserting a part
    int m_rowColResized; // when resizing a row or column
    bool m_temporaryStatusBarTextShown; // Indicates if the temporary is shown
    double m_previousTableSize; //previous column or row size before resizing it
    KoPoint m_lastCaretPos; // position of caret when editing stopped in document coordinates
    bool m_overwriteMode;

    // Table creation support.
    // Having this as a member variable allows to remember and reuse the last settings
    struct
    {
        unsigned int cols;
        unsigned int rows;
        int format;
        int /*KWTableFrameSet::CellSize*/ width;
        int /*KWTableFrameSet::CellSize*/ height;
        bool floating;
        TQString tableTemplateName;
        KWTableTemplate *tt;
    } m_table;
    KWTableFrameSet *m_currentTable;
    InteractionPolicy *m_interactionPolicy;

    struct
    {
        NoteType noteType;
        KWFootNoteVariable::Numbering numberingType;
    } m_footEndNote;

    struct
    {
        bool pictureInline;
        bool keepRatio;
    }m_picture;
};

/**
 * Interaction policy defines the behavior in case the user clicks or drags the mouse.
 * The InteractionPolicy is created in the createPolicy() function which defines the
 * resulting behavior and initiates a frame-move or a frame-resize, for example.
 * The canvas forwards mouseMove events to the handleMouseMove() method and the interaction
 * is either finished with finishInteraction() or cancelInteraction() (never both).
 */
class InteractionPolicy {
    public:
        /**
         * Extending classes should implement this method to alter the frames or other data
         * based on the new mouse position.
         * @param keyState the orred-data of the Shift/Alt/Control buttons being held down
         *   during the mousemove.
         * @param point the new point where the mouse if at.  This is in the document (pt-based)
         *  coordinate system.
         */
        virtual void handleMouseMove(TQt::ButtonState keyState, const KoPoint &point) = 0;
        /**
         * For interactions that are undo-able this method should be implemented to return such
         * a command.  Implementations should return 0 otherwise.
         * @return a command, or 0.
         */
        virtual KCommand* createCommand() = 0;
        /**
         * This method will undo frames based interactions by calling createCommand()
         * and unexecuting that.
         */
        void cancelInteraction();
        /**
         * Override to make final changes to the data on the end of an interaction.
         */
        virtual void finishInteraction() = 0;

        /**
         * This instanciates a new policy object and decides which policy is created based on the params.
         * @param parent the parent canvas for things like redraw commands.
         * @param meaning the mouseMeaning of as it is at 'point'
         * @param point the place where the mouseDown is registred.
         * @param buttonState which button is used to click, like Qt::LeftButton
         * @param keyState which keys are held down at the click, like TQt::ControlButton
         */
        static InteractionPolicy* createPolicy(KWCanvas *parent, MouseMeaning meaning, KoPoint &point, TQt::ButtonState buttonState, TQt::ButtonState keyState);

        void hadDragEvents() { m_gotDragEvents = true; }
        bool gotDragEvents() { return m_gotDragEvents; }

    protected:
        /**
         * Constructor.
         * @param parent the parent canvas.
         * @param doInit if true this will initialize the m_frames and m_indexFrame variables.
         * @param includeInlineFrames if true the m_frames will include inline frames
         */
        InteractionPolicy(KWCanvas *parent, bool doInit = true, bool includeInlineFrames = false);

        TQValueList<FrameIndex> m_indexFrame;
        KWCanvas *m_parent;
        TQValueList<KWFrame*> m_frames;

    private:
        void init();
        bool m_gotDragEvents;
};

/**
 * A policy that handles resizes of any number of frames.
 * Includes support for undo/redo and support for scale from center plus various other
 * usability features.
 */
class FrameResizePolicy : public InteractionPolicy {
    public:
        FrameResizePolicy(KWCanvas *parent, MouseMeaning meaning, KoPoint &point);
        void handleMouseMove(TQt::ButtonState keyState, const KoPoint &point);
        KCommand *createCommand();
        void finishInteraction();

    private:
        TQValueList<FrameResizeStruct> m_frameResize;
        bool m_top, m_bottom, m_left, m_right;
        KoRect m_boundingRect;
        KoPoint m_hotSpot;
};

/**
 * A policy that handles frame moves of any number of frames.
 * Includes support for undo/redo and linear moves (moves constrained to one axis)
 * plus various other usability features.
 */
class FrameMovePolicy : public InteractionPolicy {
    public:
        FrameMovePolicy(KWCanvas *parent, KoPoint &point);
        void handleMouseMove(TQt::ButtonState keyState, const KoPoint &point);
        KCommand *createCommand();
        void finishInteraction();
    private:
        TQValueList<FrameMoveStruct> m_frameMove;
        KoPoint m_hotSpot;
        KoPoint m_startPoint;
        KoRect m_boundingRect;
};

/**
 * A policy to select frames.
 */
class FrameSelectPolicy : public InteractionPolicy {
    public:
        FrameSelectPolicy(KWCanvas *parent, MouseMeaning meaning, KoPoint &point, TQt::ButtonState state, TQt::ButtonState keyState);
        void handleMouseMove(TQt::ButtonState keyState, const KoPoint &point);
        KCommand *createCommand();
        void finishInteraction();
        bool isValid() { return m_validSelection; }

    private:
        bool m_validSelection;
};

#endif