// -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*-
/* This file is part of the KDE project
   Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
   Copyright (C) 2005-2006 Thorsten Zachmann <zachmann@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 kptextobject_h
#define kptextobject_h

#include "KPrObject.h"
#include "KoRichText.h"
#include <KoTextView.h>
#include <KoStyleCollection.h> // for KoStyleChangeDefMap
#include <KoStyleStack.h>

class TQDragObject;

class KoSavingContext;
class KPrView;
class KPrDocument;
class TQDomElement;
class TextCmd;
class KPrGradient;

class KoTextView;
class KoTextObject;
class KPrTextView;
class KCommand;
class KPrCanvas;
class KoPoint;
class KoVariable;
class KPrTextDocument;
class DCOPObject;
class KPrPage;
class KoParagStyle;

class KPrTextObject :  public TQObject, public KPr2DObject, public KoTextFlow
{
    Q_OBJECT
  
public:
    KPrTextObject( KPrDocument *doc );
    virtual ~KPrTextObject();

    virtual DCOPObject* dcopObject();

    virtual void setSize( double _width, double _height );

    virtual void setDrawEditRect( bool b )
        { drawEditRect = b; }
    virtual void setDrawEmpty( bool b )
        { drawEmpty = b; }

    virtual ObjType getType() const
        { return OT_TEXT; }
    virtual TQString getTypeString() const
        { return i18n("Text"); }

    virtual bool getDrawEditRect() const
        { return drawEditRect; }
    virtual bool getDrawEmpty() const
        { return drawEmpty; }
    virtual int getSubPresSteps() const;

    virtual TQBrush getBrush() const;

    virtual void setShadowParameter(int _distance,ShadowDirection _direction,const TQColor &_color);

    virtual TQDomDocumentFragment save( TQDomDocument& doc, double offset );
    virtual double load(const TQDomElement &element);
    virtual void loadOasis(const TQDomElement &element, KoOasisContext& context, KPrLoadingInfo *info);
    virtual void saveOasisMarginElement( KoGenStyle &styleobjectauto ) const;

    virtual void paint( TQPainter *_painter, KoTextZoomHandler*_zoomHandler,
                        int pageNum, bool drawingShadow, bool drawContour );
    void paint( TQPainter *_painter, KoTextZoomHandler*_zoomHandler, bool onlyChanged, KoTextCursor* cursor,
                bool resetChanged, bool drawContour );
    void paintEdited( TQPainter *_painter, KoTextZoomHandler*_zoomHandler,
                      bool onlyChanged, KoTextCursor* cursor, bool resetChanged );

    void drawCursor( TQPainter *p, KoTextCursor *cursor, bool cursorVisible, KPrCanvas* /*canvas*/ );

    void recalcPageNum( KPrPage *page );
    /// Return the current text cursor position
    TQPoint cursorPos(KPrCanvas*, KoTextCursor *) const;


    /** Return the contained text object */
    KoTextObject * textObject() const { return m_textobj; }
    virtual void addTextObjects( TQPtrList<KoTextObject> &lst ) const {
        if ( !isProtectContent() )
            lst.append( m_textobj );
    }

    KPrTextDocument *textDocument() const;

    KPrDocument* kPresenterDocument() const { return m_doc; }

    KPrTextView * createKPTextView( KPrCanvas *,bool temp=false );
    void applyStyleChange( KoStyleChangeDefMap changed );

    void removeHighlight();
    void highlightPortion( KoTextParag * parag, int index, int length, KPrCanvas *canvas, bool repaint, KDialogBase* dialog = 0 );

    KCommand * pasteOasis( KoTextCursor * cursor, const TQByteArray & data, bool removeSelected );

    void saveParagraph( TQDomDocument& doc,
                        KoTextParag * parag,
                        TQDomElement &parentElem,
                        int from /* default 0 */,
                        int to /* default length()-2 */ );
    KoParagLayout loadParagLayout( TQDomElement & parentElem, KPrDocument *doc, bool useRefStyle);

    static KoTextFormat loadFormat( TQDomElement &n, KoTextFormat * refFormat, const TQFont & defaultFont,
                                    const TQString & defaultLanguage, bool hyphen );

    void setEditingTextObj( bool _edit ) { editingTextObj = _edit; }

    KCommand *textContentsToHeight();
    KCommand *textObjectToContents();
    void setProtectContent ( bool _protect ) { textObject()->setProtectContent(_protect);}
    bool isProtectContent() const { return textObject()->protectContent();}
    void loadVariable( TQValueList<TQDomElement> & listVariable,KoTextParag *lastParag, int offset=0 );

    void layout();

    /** Reimplemented from KoTextFlow */
    int availableHeight() const;

    /** set left margin size */
    void setBLeft( double b ) { bleft = b; }
    /** set right margin size */
    void setBRight( double b ) { bright = b; }
    /** set top margin size */
    void setBTop( double b ) { btop = b; }
    /** set bottom margin size */
    void setBBottom( double b ) { bbottom = b; }

    /** get left margin size */
    double bLeft()const { return bleft; }
    /** get right margin size */
    double bRight()const { return bright; }
    /** get top margin size */
    double bTop()const { return btop; }
    /** get bottom margin size */
    double bBottom()const { return bbottom; }

    void setTextMargins( double _left, double _top, double right, double bottom);

    KoRect innerRect() const;
    double innerWidth() const;
    double innerHeight() const;
    void resizeTextDocument( bool widthChanged = true, bool heightChanged = true );

    VerticalAlignmentType verticalAlignment() const { return m_textVertAlign; }
    void setVerticalAligment( VerticalAlignmentType _type) ;
    double alignmentValue() const {  return alignVertical; }
    virtual KPrTextObject *nextTextObject() { return this;}
    static void saveFormat( TQDomElement & element, KoTextFormat*lastFormat );

    TQPoint viewToInternal( const TQPoint & pos, KPrCanvas* canvas ) const;

signals:
    void repaintChanged( KPrTextObject* );

protected slots:
    void slotFormatChanged(const KoTextFormat &);
    void slotAfterFormatting( int, KoTextParag*, bool* );
    void slotParagraphDeleted(KoTextParag*_parag);
protected:
    virtual const char * getOasisElementName() const;
    virtual bool saveOasisObjectAttributes( KPOasisSaveContext &sc ) const;

    virtual TQDomElement saveKTextObject( TQDomDocument& doc );
    TQDomElement saveHelper(const TQString &tmpText,KoTextFormat*lastFormat ,TQDomDocument &doc);

    virtual void fillStyle( KoGenStyle& styleObjectAuto, KoGenStyles& mainStyles ) const;

    virtual void loadKTextObject( const TQDomElement &e );
    void drawText( TQPainter* _painter, KoTextZoomHandler* zoomHandler, bool onlyChanged, KoTextCursor* cursor, bool resetChanged );
    void drawParags( TQPainter *p, KoTextZoomHandler* zoomHandler, const TQColorGroup& cg, int from, int to );
    void saveParagLayout( const KoParagLayout& layout, TQDomElement & parentElem );
    void invalidate();
    void recalcVerticalAlignment();
    virtual KoPen defaultPen() const;
protected slots:
    void slotNewCommand( KCommand *cmd );
    void slotAvailableHeightNeeded();
    void slotRepaintChanged();
private:
    KPrTextObject &operator=( const KPrTextObject & );
    void shadowCompatibility();
    static const TQString &tagTEXTOBJ, &attrLineSpacing, &attrParagSpacing,
        &attrMargin, &attrBulletType1, &attrBulletType2,
        &attrBulletType3, &attrBulletType4, &attrBulletColor1,
        &attrBulletColor2, &attrBulletColor3, &attrBulletColor4,
        &attrObjType, &tagP, &attrAlign, &attrType,
        &attrDepth, &tagTEXT, &attrFamily, &attrPointSize,
        &attrBold, &attrItalic, & attrUnderline,& attrStrikeOut,
        &attrColor, &attrWhitespace, &attrTextBackColor,
        &attrVertAlign, &attrLinkName, &attrHrefName;

    /** The contained text object */
    KoTextObject *m_textobj;
    KPrDocument *m_doc;
    KoParagLayout m_paragLayout;
    VerticalAlignmentType m_textVertAlign;
    double bleft, bright, btop, bbottom; // margins
    double alignVertical;
    bool drawEditRect, drawEmpty;
    bool editingTextObj;
};


class KPrTextView : public KoTextView
{
    Q_OBJECT
  
public:
    KPrTextView( KPrTextObject * txtObj, KPrCanvas *_canvas, bool temp=false );
    virtual ~KPrTextView();

    virtual KoTextViewIface* dcopObject();

    KoTextView * textView() { return this; }
    KPrTextObject * kpTextObject() const { return m_kptextobj; }

    void keyPressEvent( TQKeyEvent * );
    void keyReleaseEvent( TQKeyEvent * );
    void imStartEvent( TQIMEvent * );
    void imComposeEvent( TQIMEvent * );
    void imEndEvent( TQIMEvent * );
    void mousePressEvent( TQMouseEvent *, const TQPoint &);
    void mouseMoveEvent( TQMouseEvent *, const TQPoint & );
    void mouseReleaseEvent( TQMouseEvent *, const TQPoint & );
    void mouseDoubleClickEvent( TQMouseEvent *, const TQPoint &);
    void dragEnterEvent( TQDragEnterEvent * );
    void dragMoveEvent( TQDragMoveEvent *, const TQPoint & );
    void dropEvent( TQDropEvent * );

    void clearSelection();
    void selectAll(bool select = true);
    virtual void drawCursor( bool b );

    const KoParagLayout & currentParagLayout() const { return m_paragLayout; }
    void showPopup( KPrView *view, const TQPoint &point, TQPtrList<TDEAction> &actionList );
    void insertVariable( int type, int subtype = 0 );
    void insertCustomVariable( const TQString &name);
    void insertLink(const TQString &_linkName, const TQString & hrefName);
    void insertVariable( KoVariable *var, KoTextFormat *format =0,
                         bool refreshCustomMenu =false /*don't refresh variable custom menu all the time */);

    void terminate(bool removeSelection=true);
    void insertComment(const TQString &_note);

    /** return true if some text is selected */
    bool hasSelection() const;

    virtual void removeToolTipCompletion();
    bool isLinkVariable(const TQPoint &);
    void openLink();
    TQPoint viewToInternal( const TQPoint & pos ) const;

public slots:
    void cut();
    void copy();
    void paste();
    // Reimplemented from KoTextView
    virtual void updateUI( bool updateFormat, bool force = false );
    virtual void ensureCursorVisible();


protected slots:
    virtual void startDrag();

protected:
    bool canDecode( TQMimeSource *e );
    TQDragObject * newDrag( TQWidget * parent );
    // Reimplemented from KoTextView
    virtual void doAutoFormat( KoTextCursor* cursor, KoTextParag *parag, int index, TQChar ch );
    virtual bool doIgnoreDoubleSpace(KoTextParag * parag, int index,TQChar ch );
    virtual bool doCompletion( KoTextCursor* cursor, KoTextParag *parag, int index );
    virtual bool doToolTipCompletion( KoTextCursor* , KoTextParag *, int, int  );
    virtual void showToolTipBox(KoTextParag *parag, int index, TQWidget *widget, const TQPoint &pos);
    virtual void textIncreaseIndent();
    virtual bool textDecreaseIndent();
    virtual void showFormat( KoTextFormat *format ) ;

    virtual bool pgUpKeyPressed();
    virtual bool pgDownKeyPressed();

    KPrTextObject *m_kptextobj;
    KPrCanvas *m_canvas;
    KoParagLayout m_paragLayout;
    TQPtrList<TDEAction> m_actionList; // for the kodatatools
};


#endif