/* This file is part of the KDE project Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer Copyright (C) 2005 Thomas Zander 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 frame_set_h #define frame_set_h #include "KWFrame.h" #include #include #include "tqdom.h" class KWAnchor; class KWFrame; class KWFrameSetEdit; class KWPageManager; class KWTableFrameSet; class KWTextFrameSet; class KWTextFrameSetEdit; class KWTextParag; class KWView; class KWordFrameSetIface; class KWFrameViewManager; class KoSavingContext; class KoTextDocument; class KoTextFormat; class KoTextParag; class KoXmlWriter; class KCommand; class TQPoint; class TQProgressDialog; /** * Class: KWFrameSet * Base type, a frameset holds content as well as frames to show that * content. * The different types of content are implemented in the different * types of frameSet implementations (see below) * @see KWTextFrameSet, KWPartFrameSet, KWPictureFrameSet, * KWFormulaFrameSet, KWTableFrameSet */ class KWFrameSet : public TQObject { TQ_OBJECT public: /// constructor KWFrameSet( KWDocument *doc ); /// destructor virtual ~KWFrameSet(); virtual KWordFrameSetIface* dcopObject(); /** The type of frameset. Use this to differentiate between different instantiations of * the framesets. Each implementation will return a different frameType. */ virtual FrameSetType type() const { return FT_BASE; } virtual void addTextFrameSets( TQPtrList & /*lst*/, bool /*onlyReadWrite*/ = false ) {}; virtual bool ownLine() const { return FALSE;} /** The different types of textFramesets (that TEXT is important here!) * FI_BODY = normal text frames.
* FI_FIRST_HEADER = Header on page 1
* FI_EVEN_HEADER = header on any even page
* FI_ODD_HEADER = header on any odd page (can be including page 1)
* FI_FIRST_FOOTER = footer on page 1
* FI_EVEN_FOOTER = footer on any even page
* FI_ODD_FOOTER = footer on any odd page (can be including page 1)
* FI_FOOTNOTE = a footnote frame. */ enum Info { FI_BODY = 0, FI_FIRST_HEADER = 1, FI_EVEN_HEADER = 2, FI_ODD_HEADER = 3, FI_FIRST_FOOTER = 4, FI_EVEN_FOOTER = 5, FI_ODD_FOOTER = 6, FI_FOOTNOTE = 7 }; /** Returns the type of TextFrameSet this is */ Info frameSetInfo()const { return m_info; } /** Set the type of TextFrameSet this is */ void setFrameSetInfo( Info fi ) { m_info = fi; } bool isAHeader() const; bool isAFooter() const; bool isHeaderOrFooter() const { return isAHeader() || isAFooter(); } bool isFootEndNote() const; const char* headerFooterTag() const; // for OASIS saving virtual bool isFootNote() const { return false; } virtual bool isEndNote() const { return false; } bool isMainFrameset() const; bool isMoveable() const; // frame management virtual void addFrame( KWFrame *_frame, bool recalc = true ); /** Delete a frame from the set of frames this frameSet has. * @param num The frameNumber to be removed. * @param remove passing true means that there can not be an undo of the action. * @param recalc do an updateFrames() */ virtual void deleteFrame( unsigned int num, bool remove = true, bool recalc = true ); /** Delete a frame from the set of frames this frameSet has. * @param frm The frame that should be deleted * @param remove passing true means that there can not be an undo of the action. * @param recalc do an updateFrames() */ void deleteFrame( KWFrame *frm, bool remove = true, bool recalc = true ); // calls the virtual one /// Called by deleteFrame when it really deletes a frame (remove=true), to remove it from the table too virtual void frameDeleted( KWFrame* /*frm*/, bool /*recalc*/ ) {} void deleteAllFrames(); void deleteAllCopies(); /// \note for headers/footers only /** retrieve frame from x and y coords (unzoomed coords) */ KWFrame *frameAtPos( double _x, double _y ) const; /** Return if the point is on the frame. * @param nPoint the point in normal coordinates. * @param borderOfFrameOnly when true an additional check is done if the point * is on the border. * @param frame the frame to check inside of */ bool isFrameAtPos( const KWFrame* frame, const TQPoint& nPoint, bool borderOfFrameOnly=false ) const; /** get a frame by number */ KWFrame *frame( unsigned int _num ) const; /** * Returns the original frame that the param frame is a copy off, or the frame itself. * For changing a frame that is a copy of another (as found in KWFrame::isCopy()) you * need a so called settings frame, or original frame. This method can savely be called * on any frame to make sure you are dealing with the original frame. * @param frame the frame to find the settings frame for. * @return the frame itself if its not a copy, or the original frame if it is one. */ static KWFrame * settingsFrame( const KWFrame* frame ); /** Iterator over the child frames */ const TQPtrList &frameIterator() const { return m_frames; } /** Get frame number */ int frameFromPtr( KWFrame *frame ); /** Get number of child frames */ unsigned int frameCount() const { return m_frames.count(); } /** True if the frameset was deleted (but not destroyed, since it's in the undo/redo) */ bool isDeleted() const { return m_frames.isEmpty(); } /** Create a framesetedit object to edit this frameset in @p canvas */ virtual KWFrameSetEdit * createFrameSetEdit( KWCanvas * ) { return 0; } /** * Let the caller know which parts of @p emptyRegion we do not claim, and thus the caller is * free to paint on without interfering with later paints from us. * For painting all frames of all framesets the painter needs to find out what area we * will fill with a background color and possibly paint over. * What this method does is fill an TQRegion with all the areas we are going to fill, which * typically means we will paint the background of a frame there. * @param emptyRegion The region is modified to subtract the areas painted, thus * allowing the caller to determine which areas remain to be painted. * Framesets that can be transparent should reimplement this and make it a no-op, * so that the background is painted below the transparent frame. * @param crect the cliprect; only parts inside this rect are of interrest to us * @param viewMode For coordinate conversion, always set. */ virtual void createEmptyRegion( const TQRect & crect, TQRegion & emptyRegion, KWViewMode *viewMode ); /** * Paint this frameset * @param painter The painter in which to draw the contents of the frameset * @param crect The rectangle (in scrollview "contents coordinates", i.e. "view coords") * to be painted * @param cg The colorgroup from which to get the colors * @param onlyChanged If true, only redraw what has changed (see KWCanvas::repaintChanged) * @param resetChanged If true, set the changed flag to false after drawing. * @param edit If set, this frameset is being edited, so a cursor is needed. * @param viewMode For coordinate conversion, always set. * @param frameViewManager the frameViewManager; * * The way this "onlyChanged/resetChanged" works is: when something changes, * all views are asked to redraw themselves with onlyChanged=true. * But all views except the last one shouldn't reset the changed flag to false, * otherwise the other views wouldn't repaint anything. * So resetChanged is called with "false" for all views except the last one, * and with "true" for the last one, so that it resets the flag. * * Framesets shouldn't reimplement this one in theory [but KWTableFrameSet has to]. */ virtual void drawContents( TQPainter *painter, const TQRect &crect, const TQColorGroup &cg, bool onlyChanged, bool resetChanged, KWFrameSetEdit *edit, KWViewMode *viewMode, KWFrameViewManager *frameViewManager ); /** * This one is called by drawContents for each frame. * It sets up clip rect and painter translation, and calls drawFrame, drawFrameBorder and drawMargins * * @param drawUnderlyingFrames if the frame implements it, then it should draw underlying frames. * This is set to false by the default drawFrame implementation, so that the frames under a * transparent frame are simply drawn, without transparency handling (nor their own * double-buffering). * @param frame the frame to draw * @param painter the painter to draw to * @param settingsFrame The frame from which we take the settings (usually @p frame, but not with Copy behaviour) * @param cg The colorgroup from which to get the colors * @param edit If set, this frameset is being edited, so a cursor is needed. * @param viewMode For coordinate conversion, always set. * @param crect rectangle to be repainted, in view coordinates. Includes padding. */ void drawFrameAndBorders( KWFrame *frame, TQPainter *painter, const TQRect &crect, const TQColorGroup &cg, bool, bool, KWFrameSetEdit *edit, KWViewMode *viewMode, KWFrame *settingsFrame, bool drawUnderlyingFrames ); /** * Paint the borders for one frame of this frameset. * @param painter The painter in which to draw the contents of the frameset * @param frame The frame to be drawn * @param settingsFrame The frame from which we take the settings (usually @p frame, but not with Copy behaviour) * @param crect The rectangle (in "contents coordinates") to be painted * @param viewMode For coordinate conversion, always set. */ void drawFrameBorder( TQPainter *painter, KWFrame *frame, KWFrame *settingsFrame, const TQRect &crect, KWViewMode *viewMode ); /** * Draw a particular frame of this frameset. * This is called by drawContents and is what framesets must reimplement. * @param fcrect rectangle to be repainted, in the _frame_'s coordinate system, in pixels. * Doesn't include padding. * * @param crect rectangle to be repainted, in view coordinates. Includes padding. * Default implementation does double-buffering and calls drawFrameContents. * @param frame the frame to draw * @param painter the painter to draw to * @param settingsFrame The frame from which we take the settings (usually @p frame, but not with Copy behaviour) * @param cg The colorgroup from which to get the colors * @param onlyChanged If true, only redraw what has changed (see KWCanvas::repaintChanged) * @param resetChanged If true, set the changed flag to false after drawing. * @param edit If set, this frameset is being edited, so a cursor is needed. * @param viewMode For coordinate conversion, always set. * @param drawUnderlyingFrames if the frame implements it, then it should draw underlying frames. * @param translationOffset offset this method will translate the paiter before doing its work. */ virtual void drawFrame( KWFrame *frame, TQPainter *painter, const TQRect &fcrect, const TQRect &crect, const TQPoint& translationOffset, KWFrame *settingsFrame, const TQColorGroup &cg, bool onlyChanged, bool resetChanged, KWFrameSetEdit *edit, KWViewMode *viewMode, bool drawUnderlyingFrames ); /** * Implement this one instead of drawFrame to benefit from double-buffering * AND transparency handling (painting frames below this one) automatically. * You MUST reimplement one or the other, or you'll get infinite recursion ;) * * In this method, the painter has been translated to the frame's coordinate system * @param fcrect rectangle to be repainted, in the _frame_'s coordinate system, in pixels. * Doesn't include padding. * @param frame the frame to draw * @param painter the painter to draw to * @param cg The colorgroup from which to get the colors * @param onlyChanged If true, only redraw what has changed (see KWCanvas::repaintChanged) * @param resetChanged If true, set the changed flag to false after drawing. * @param edit If set, this frameset is being edited, so a cursor is needed. * @param viewMode For coordinate conversion, always set. */ virtual void drawFrameContents( KWFrame * frame, TQPainter *painter, const TQRect& fcrect, const TQColorGroup &cg, bool onlyChanged, bool resetChanged, KWFrameSetEdit * edit, KWViewMode *viewMode ); /** * Draw the padding area inside of a specific frame of this frameSet */ virtual void drawPadding( KWFrame *frame, TQPainter *p, const TQRect &fcrect, const TQColorGroup &cg, KWViewMode *viewMode); enum UpdateFramesFlags { UpdateFramesInPage = 1, SortFrames = 2 ///< kwtextframeset only // next one is 4, not 3 ;) }; /** * Called when our frames change, or when another frameset's frames change. * Framesets can reimplement it, but should always call the parent method. */ virtual void updateFrames( int flags = 0xff ); /** Return list of frames in page @p pageNum. * This is fast since it uses the m_framesInPage array.*/ const TQPtrList & framesInPage( int pageNum ) const; /** Allows to detect that updateFrames() hasn't been called yet (e.g. on loading) */ bool hasFramesInPageArray() const { return !m_framesInPage.isEmpty(); } /** relayout text in frames, so that it flows correctly around other frames */ virtual void layout() {} virtual void invalidate() {} /// save to XML - when saving virtual TQDomElement save( TQDomElement &parentElem, bool saveFrames = true ) = 0; /// save to XML - when copying to clipboard virtual TQDomElement toXML( TQDomElement &parentElem, bool saveFrames = true ) { return save( parentElem, saveFrames ); } /// Save to OASIS format virtual void saveOasis( KoXmlWriter& writer, KoSavingContext& context, bool saveFrames ) const = 0; /// If the frameset is inline, is it ok to save it inside an oasis ? /// If not, KWAnchor will create a textbox around it. virtual bool canBeSavedAsInlineCharacter() const { return true; } /// load from XML - when loading virtual void load( TQDomElement &framesetElem, bool loadFrames = true ); KWFrame* loadOasisFrame( const TQDomElement& tag, KoOasisContext& context ); /// load from XML - when pasting from clipboard virtual void fromXML( TQDomElement &framesetElem, bool loadFrames = true, bool /*useNames*/ = true ) { load( framesetElem, loadFrames ); } virtual TQString toPlainText() const { return TQString(); } //virtual void preparePrinting( TQPainter *, TQProgressDialog *, int & ) { } /** Called once the frameset has been completely loaded or constructed. * The default implementation calls updateFrames() and zoom(). Call the parent :) */ virtual void finalize(); virtual int paragraphs() { return 0; } virtual int paragraphsSelected() { return 0; } virtual bool statistics( TQProgressDialog * /*progress*/, ulong & /*charsWithSpace*/, ulong & /*charsWithoutSpace*/, ulong & /*words*/, ulong & /*sentences*/, ulong & /*syllables*/, ulong & /*lines*/, bool /*process only selected */ ) { return true; } KWDocument* kWordDocument() const { return m_doc; } /// Return true if page @p num can be removed, as far as this frameset is concerned virtual bool canRemovePage( int num ); //Note: none of those floating-frameset methods creates undo/redo //They are _called_ by the undo/redo commands. /// Make this frameset floating (anchored), as close to its current position as possible. void setFloating(); /** * Make this frameset anchored, with the anchor at @p paragId,@p index in the text frameset @p textfs. * Also used during OASIS loading (placeHolderExists=true) */ void setAnchored( KWTextFrameSet* textfs, KoTextParag* parag, int index, bool placeHolderExists = false, bool repaint = true ); /** Make this frameset floating, with the anchor at @p paragId,@p index in the text frameset @p textfs. * \deprecated */ void setAnchored( KWTextFrameSet* textfs, int paragId, int index, bool placeHolderExists = false, bool repaint = true ); /** Note that this frameset has been made floating already, and store anchor position */ void setAnchored( KWTextFrameSet* textfs ); /// Make this frameset fixed, i.e. not anchored void setFixed(); /// Return true if this frameset is floating (inline), false if it's fixed bool isFloating() const { return m_anchorTextFs; } /// Return the frameset in which our anchor is - assuming isFloating() KWTextFrameSet * anchorFrameset() const { return m_anchorTextFs; } /// Sets the frameset in which we are about to become inline. Used for OASIS loading. void setAnchorFrameset(KWTextFrameSet * textfs) { m_anchorTextFs = textfs; } /// Return the anchor object for this frame number KWAnchor * findAnchor( int frameNum ); /// Tell this frame the format of it's anchor virtual void setAnchorFormat( KoTextFormat* /*format*/, int /*frameNum*/ ) {} /// Create an anchor for the floating frame identified by frameNum virtual KWAnchor * createAnchor( KoTextDocument *txt, int frameNum ); /** Move the frame frameNum to the given position - this is called when the frame is anchored and the anchor moves (see KWAnchor). */ virtual void moveFloatingFrame( int frameNum, const KoPoint &position ); /** Get the size of the "floating frame" identified by frameNum. By default a real frame but not for tables. */ virtual KoSize floatingFrameSize( int frameNum = 0 ); /** Get the rect of the "floating frame" identified by frameNum, in coordinates RELATIVE TO THE PARENT FRAMESET. This is especially important for multi-parent inline frames. */ KoRect floatingFrameRect( int frameNum = 0 ); /** Get the 'baseline' to use for the "floating frame" identified by frameNum. -1 means same as the height (usual case) */ virtual int floatingFrameBaseline( int /*frameNum*/ ) { return -1; } /// Store command for creating an anchored object virtual KCommand * anchoredObjectCreateCommand( int frameNum ); /// Store command for deleting an anchored object virtual KCommand * anchoredObjectDeleteCommand( int frameNum ); /** make this frameset part of a groupmanager * @see KWTableFrameSet */ void setGroupManager( KWTableFrameSet *gm ) { m_groupmanager = gm; } /** returns the groupManager this frameset belongs to. A Groupmanager is better known as a table */ KWTableFrameSet *groupmanager()const { return m_groupmanager; } bool isProtectSize()const { return m_protectSize; } void setProtectSize( bool _b); /** * Returns true if the frameset is visible. * A frameset is visible if setVisible(false) wasn't called, * but also, for a header frameset, if m_doc->isHeaderVisible is true, etc. * For an "even pages header" frameset, the corresponding headerType setting * must be selected (i.e. different headers for even and odd pages). * @param viewMode pass the current viewmode when using this method for any visual * stuff (drawing, handling input etc.). Frameset visibility depends on the viewmode. */ bool isVisible( KWViewMode* viewMode = 0L ) const; /// set the visibility of the frameset. virtual void setVisible( bool v ); /// get/set frameset name. For tables in particular, this _must_ be unique TQString name() const { return m_name; } void setName( const TQString &name ); /// set frameBehavior on all frames, see KWFrame for specifics void setFrameBehavior( KWFrame::FrameBehavior fb ); /// set newFrameBehavior on all frames, see KWFrame for specifics void setNewFrameBehavior( KWFrame::NewFrameBehavior nfb ); #ifndef NDEBUG virtual void printDebug(); virtual void printDebug( KWFrame * ); #endif virtual KWTextFrameSet* nextTextObject( KWFrameSet * ) { return 0L;} bool isPaintedBy( KWFrameSet* fs ) const; /// set z-order for all frames virtual void setZOrder(); virtual void setProtectContent ( bool protect ) = 0; virtual bool protectContent() const = 0; void setPageManager(KWPageManager *pm) { m_pageManager = pm; } KWPageManager* pageManager() const { return m_pageManager; } signals: /// Emitted when something has changed in this frameset, /// so that all views repaint it. KWDocument connects to it, /// and KWCanvas connects to KWDocument. void repaintChanged( KWFrameSet * frameset ); void sigFrameAdded(KWFrame*); void sigFrameRemoved(KWFrame*); void sigNameChanged(KWFrameSet*); protected: /// save the common attributes for the frameset void saveCommon( TQDomElement &parentElem, bool saveFrames ); /**Determine the clipping rectangle for drawing the contents of @p frame with @p painter * in the rectangle delimited by @p crect. * This determines where to clip the painter to draw the contents of a given frame */ TQRegion frameClipRegion( TQPainter * painter, KWFrame *frame, const TQRect & crect, KWViewMode * viewMode ); void deleteAnchor( KWAnchor * anchor ); virtual void deleteAnchors(); virtual void createAnchors( KoTextParag * parag, int index, bool placeHolderExists = false, bool repaint = true ); KWDocument *m_doc; // Document TQPtrList m_frames; // Our frames // Cached info for optimization /// This array provides a direct access to the frames on page N TQPtrVector< TQPtrList > m_framesInPage; /// always equal to m_framesInPage[0].first()->pageNumber() :) int m_firstPage; /// always empty, for convenience in @ref framesInPage TQPtrList m_emptyList; // ## make static pointer to save memory ? Info m_info; KWTableFrameSet *m_groupmanager; bool m_visible; bool m_protectSize; TQString m_name; KWTextFrameSet * m_anchorTextFs; KWordFrameSetIface *m_dcop; KWPageManager *m_pageManager; }; #endif