
/***************************************************************************
                          codeeditor.h  -  description
                             -------------------
    begin                : Fri Aug 1 2003
    copyright            : (C) 2003 by Brian Thomas
    email                : brian.thomas@gsfc.nasa.gov
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef CODEEDITOR_H
#define CODEEDITOR_H

#include <tqpopupmenu.h>
#include <tqstring.h>
#include <tqlabel.h>
#include <tqtextedit.h>
#include "../codeviewerstate.h"
#include "../textblocklist.h"

class UMLObject;

class CodeViewerDialog;
class CodeComment;
class CodeDocument;
class CodeClassFieldDeclarationBlock;
class CodeMethodBlock;
class CodeBlockWithComments;
class HierarchicalCodeBlock;

class TextBlockInfo;
class TextBlock;
class ParaInfo;

class CodeEditor : public TQTextEdit
{
    TQ_OBJECT
  
public:

    explicit CodeEditor ( const TQString & text, const TQString & context = TQString(), CodeViewerDialog * parent = 0, const char * name = 0 , CodeDocument * doc = 0);
    explicit CodeEditor ( CodeViewerDialog * parent, const char* name = 0, CodeDocument * doc = 0);
    ~CodeEditor ();

    // return code viewer state
    Settings::CodeViewerState getState( );

protected:

    bool close ( bool alsoDelete );

    // various methods for appending various types of text blocks in the editor.
    void appendText (TextBlock * tblock);
    void appendText (HierarchicalCodeBlock * hblock);
    void appendText (CodeClassFieldDeclarationBlock * db );
    void appendText (TextBlockList * items);
    void appendText (CodeMethodBlock * mb);
    void appendText (CodeComment * comment, TextBlock * parent, UMLObject * umlObj = 0, const TQString & compName="");
    void appendText (CodeBlockWithComments * cb );

    // Rebuild our view of the document. Happens whenever we change
    // some field/aspect of an underlying UML object used to create
    // the view.
    // If connections are right, then the UMLObject will send out the modified()
    // signal which will trigger a call to re-generate the appropriate code within
    // the code document. Our burden is to appropriately prepare the tool: we clear
    // out ALL the textblocks in the TQTextEdit widget and then re-show them
    // after the dialog disappears
    void rebuildView( int startCursorPos );

    // override the QT event so we can do appropriate things
    void contentsMouseMoveEvent ( TQMouseEvent * e );

    // implemented so we may capture certain key presses, namely backspace
    // and 'return' events.
    void keyPressEvent ( TQKeyEvent * e );

    // (re) load the parent code document into the editor
    void loadFromDocument();

    // specialized popup menu for our tool
    TQPopupMenu * createPopupMenu ( const TQPoint & pos );

private:

    TQString parentDocName;
    CodeDocument * m_parentDoc;
    CodeViewerDialog * m_parentDlg;

    int m_lastPara;
    int m_lastPos;

    bool m_newLinePressed;
    bool m_backspacePressed;
    bool m_isHighlighted;
    bool m_showHiddenBlocks;

    TextBlock * m_textBlockToPaste;
    TextBlock * m_selectedTextBlock;
    TextBlock * m_lastTextBlockToBeEdited;

    TQMap<TextBlock*, TextBlockInfo*> *m_tbInfoMap;
    TextBlockList m_textBlockList;

    // main insert routine. Will append if startline is not supplied.
    void insert (const TQString & text, TextBlock * parent, bool isEditable = false,
                 const TQColor & fgcolor = TQColor("black"), const TQColor & bgcolor = TQColor("white"),
                 UMLObject * umlobj = 0, const TQString & displayName = "", int startLine = -1);

    void editTextBlock(TextBlock * tBlock, int para);
    void clearText();
    TQLabel * getComponentLabel();
    bool paraIsNotSingleLine (int para);
    void expandSelectedParagraph( int where );
    void contractSelectedParagraph( int where );
    void updateTextBlockFromText (TextBlock * block);

    void initText ( CodeDocument * doc );
    void init ( CodeViewerDialog * parentDlg, CodeDocument * parentDoc );

    void changeTextBlockHighlighting(TextBlock * tb, bool selected);
    bool isParaEditable (int para);
    bool textBlockIsClickable(UMLObject * obj);

    // return whether or not the passed string is empty or
    // contains nothing but whitespace
    static bool StringIsBlank( const TQString &str );

public slots:

    void insertParagraph ( const TQString & text, int para );
    void removeParagraph ( int para );
    void changeHighlighting(int signal);
    void changeShowHidden (int signal);
    void slotRedrawText();

protected slots:

    void clicked(int para, int pos );
    void doubleClicked(int para, int pos );
    void cursorPositionChanged(int para, int pos );
    void slotCopyTextBlock ( );
    void slotCutTextBlock ( );
    void slotPasteTextBlock ( );
    void slotChangeSelectedBlockView();
    void slotChangeSelectedBlockCommentView();
    void slotInsertCodeBlockAfterSelected();
    void slotInsertCodeBlockBeforeSelected();

signals:

    /*
        void sigNewLinePressed ();
        void sigBackspacePressed ();
    */

};

class ParaInfo {
public:
    int start; // this is a relative offset from the beginning of the tblock
    int size;
    TQColor fgcolor;
    TQColor bgcolor;
    bool isEditable;

    ParaInfo () { isEditable = false; }
};

class TextBlockInfo {
public:
    TQPtrList<ParaInfo> m_paraList;
    UMLObject * m_parent;
    TQString displayName;
    bool isClickable;
    bool isCodeAccessorMethod;

    TextBlockInfo () { m_parent = 0; isClickable = false; isCodeAccessorMethod = false; }
    void setParent(UMLObject *p = 0) { m_parent = p; }
    UMLObject * getParent() { return m_parent; }

};

#endif // CODEEDITOR_H
