//------------------------------------------------------------------------------
// emTextField.h
//
// Copyright (C) 2005-2010,2014,2016 Oliver Hamann.
//
// Homepage: http://eaglemode.sourceforge.net/
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License version 3 as published by the
// Free Software Foundation.
//
// This program 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 General Public License version 3 for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------

#ifndef emTextField_h
#define emTextField_h

#ifndef emClipboard_h
#include <emCore/emClipboard.h>
#endif

#ifndef emBorder_h
#include <emCore/emBorder.h>
#endif


//==============================================================================
//================================ emTextField =================================
//==============================================================================

class emTextField : public emBorder {

public:

        // Class for a data field panel showing a single line of text which can
        // optionally be edited by the user. An optional multi-line mode is also
        // provided. Selection and clipboard functions are supported.

        emTextField(
                ParentArg parent, const emString & name,
                const emString & caption=emString(),
                const emString & description=emString(),
                const emImage & icon=emImage(),
                const emString & text=emString(),
                bool editable=false
        );
                // Constructor.
                // Arguments:
                //   parent      - Parent for this panel (emPanel or emView).
                //   name        - The name for this panel.
                //   caption     - The label's caption, or empty.
                //   description - The label's description, or empty.
                //   icon        - The label's icon, or empty.
                //   editable    - Whether the text can be edited by the user.

        virtual ~emTextField();
                // Destructor.

        bool IsEditable() const;
        void SetEditable(bool editable=true);
                // Whether the text can be edited by the user.

        bool GetMultiLineMode() const;
        void SetMultiLineMode(bool multiLineMode=true);
                // Whether the text may have multiple lines.

        bool GetPasswordMode() const;
        void SetPasswordMode(bool passwordMode=true);
                // Whether the text is a password that should not really be
                // shown.

        bool GetOverwriteMode() const;
        void SetOverwriteMode(bool overwriteMode=true);
                // Current mode of overwriting or inserting (can be changed with
                // the insert key).

        const emSignal & GetTextSignal() const;
                // Signaled whenever the text has changed.

        const emString & GetText() const;
        void SetText(const emString & text);
                // The text.

        int GetTextLen() const;
        int GetCursorIndex() const;
        void SetCursorIndex(int index);
        const emSignal & GetSelectionSignal() const;
        int GetSelectionStartIndex() const;
        int GetSelectionEndIndex() const;
        void Select(int startIndex, int endIndex, bool publish);
        bool IsSelectionEmpty() const;
        void EmptySelection();
        void SelectAll(bool publish);
        void PublishSelection();
        void CutSelectedTextToClipboard();
        void CopySelectedTextToClipboard();
        void PasteSelectedTextFromClipboard();
        void PasteSelectedText(const emString & text);
        void DeleteSelectedText();
        bool IsCursorBlinkOn() const;
                // Advanced stuff - still undocumented.

protected:

        virtual void TextChanged();
                // Called when the text has changed.

        virtual void SelectionChanged();
                // Called when the selection has changed.

        virtual bool Cycle();
        virtual void Notice(NoticeFlags flags);
        virtual void Input(emInputEvent & event, const emInputState & state,
                           double mx, double my);

        virtual bool HasHowTo() const;
        virtual emString GetHowTo() const;

        virtual void PaintContent(
                const emPainter & painter, double x, double y, double w,
                double h, emColor canvasColor
        ) const;

        virtual bool CheckMouse(double mx, double my,
                                double * pCol, double * pRow) const;

        // - - - - - - - - - - Depreciated methods - - - - - - - - - - - - - - -
        // The following virtual non-const methods have been replaced by const
        // methods (see above). The old versions still exist here with the
        // "final" keyword added, so that old overridings will fail to compile.
        // If you run into this, please adapt your overridings by adding "const".
        virtual bool CheckMouse(double mx, double my,
                                double * pCol, double * pRow) final;
        // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

private:

        enum DoTextFieldFunc {
                TEXT_FIELD_FUNC_PAINT,
                TEXT_FIELD_FUNC_XY2CR,
                TEXT_FIELD_FUNC_CR2XY
        };
        void DoTextField(
                DoTextFieldFunc func, const emPainter * painter,
                emColor canvasColor,
                double xIn, double yIn, double * pXOut, double * pYOut, bool * pHit
        ) const;

        enum DragModeType {
                DM_NONE,
                DM_SELECT,
                DM_SELECT_BY_WORDS,
                DM_SELECT_BY_ROWS,
                DM_INSERT,
                DM_MOVE
        };

        void SetDragMode(DragModeType dragMode);
        void RestartCursorBlinking();
        void ScrollToCursor();
        int ColRow2Index(double column, double row, bool forCursor) const;
        void Index2ColRow(int index, int * pColumn, int * pRow) const;
        void CalcTotalColsRows(int * pCols, int * pRows) const;
        int GetNormalizedIndex(int index) const;
        void ModifySelection(int oldColumn, int newColumn, bool publish);
        int GetNextIndex(int index) const;
        int GetPrevIndex(int index) const;
        int GetNextWordBoundaryIndex(int index, bool * pIsDelimiter=NULL) const;
        int GetPrevWordBoundaryIndex(int index, bool * pIsDelimiter=NULL) const;
        int GetNextWordIndex(int index) const;
        int GetPrevWordIndex(int index) const;
        int GetRowStartIndex(int index) const;
        int GetRowEndIndex(int index) const;
        int GetNextRowIndex(int index) const;
        int GetPrevRowIndex(int index) const;
        int GetNextParagraphIndex(int index) const;
        int GetPrevParagraphIndex(int index) const;

        emRef<emClipboard> Clipboard;
        emSignal TextSignal;
        emSignal SelectionSignal;
        bool Editable;
        bool MultiLineMode;
        bool PasswordMode;
        bool OverwriteMode;
        emString Text;
        int TextLen,CursorIndex,SelectionStartIndex,SelectionEndIndex;
        int MagicCursorColumn;
        emInt64 SelectionId;
        emUInt64 CursorBlinkTime;
        bool CursorBlinkOn;
        DragModeType DragMode;
        double DragPosC,DragPosR;

        static const char * HowToTextField;
        static const char * HowToMultiLineOff;
        static const char * HowToMultiLineOn;
        static const char * HowToReadOnly;
};

inline bool emTextField::IsEditable() const
{
        return Editable;
}

inline bool emTextField::GetMultiLineMode() const
{
        return MultiLineMode;
}

inline bool emTextField::GetPasswordMode() const
{
        return PasswordMode;
}

inline bool emTextField::GetOverwriteMode() const
{
        return OverwriteMode;
}

inline const emSignal & emTextField::GetTextSignal() const
{
        return TextSignal;
}

inline const emString & emTextField::GetText() const
{
        return Text;
}

inline int emTextField::GetTextLen() const
{
        return TextLen;
}

inline int emTextField::GetCursorIndex() const
{
        return CursorIndex;
}

inline const emSignal & emTextField::GetSelectionSignal() const
{
        return SelectionSignal;
}

inline int emTextField::GetSelectionStartIndex() const
{
        return SelectionStartIndex;
}

inline int emTextField::GetSelectionEndIndex() const
{
        return SelectionEndIndex;
}

inline bool emTextField::IsSelectionEmpty() const
{
        return SelectionStartIndex>=SelectionEndIndex;
}

inline bool emTextField::IsCursorBlinkOn() const
{
        return CursorBlinkOn;
}


#endif