    //------------------------------------------------------------------------------
    // emToolkit.h
    //
    // Copyright (C) 2005-2010 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 emToolkit_h
    #define emToolkit_h

    #ifndef emVarModel_h
    #include <emCore/emVarModel.h>
    #endif

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

    #ifndef emPanel_h
    #include <emCore/emPanel.h>
    #endif

    //==============================================================================
    //================================== emTkLook ==================================
    //==============================================================================

    class emTkLook {

    public:

            // Class for the look of toolkit panels. Currently, the look consists of
            // a set of colors only. Objects of this class have copy-on-write
            // behavior.

            emTkLook();
                    // Construct a default look.

            emTkLook(const emTkLook & look);
                    // Construct a copied look.

            ~emTkLook();
                    // Destructor.

            emTkLook & operator = (const emTkLook & look);
                    // Copy a look.

            bool operator == (const emTkLook & look) const;
            bool operator != (const emTkLook & look) const;
                    // Compare two looks.

            void Apply(emPanel * panel, bool recursively) const;
                    // Apply this look to a panel or to all panels in a sub-tree.
                    // Applying actually works for panels of class emTkBorder and
                    // its derivatives only, but the recursion is not stopped by
                    // other panel classes. However, the recursion can be stopped by
                    // an overloaded implementation of emTkBorder::SetLook.
                    // Arguments:
                    //   panel       - The panel.
                    //   recursively - Whether to recurse ancestor panels.

            emColor GetBgColor() const;
            emColor GetFgColor() const;
            void SetBgColor(emColor bgColor);
            void SetFgColor(emColor fgColor);
                    // Get/set back- and foreground colors of borders, labels,
                    // groups and similar things.

            emColor GetButtonBgColor() const;
            emColor GetButtonFgColor() const;
            void SetButtonBgColor(emColor buttonBgColor);
            void SetButtonFgColor(emColor buttonFgColor);
                    // Get/set back- and foreground colors of button faces.

            emColor GetInputBgColor() const;
            emColor GetInputFgColor() const;
            emColor GetInputHlColor() const;
            void SetInputBgColor(emColor inputBgColor);
            void SetInputFgColor(emColor inputFgColor);
            void SetInputHlColor(emColor inputHlColor);
                    // Get/set background, foreground and highlight (=selection)
                    // colors of editable data fields.

            emColor GetOutputBgColor() const;
            emColor GetOutputFgColor() const;
            emColor GetOutputHlColor() const;
            void SetOutputBgColor(emColor outputBgColor);
            void SetOutputFgColor(emColor outputFgColor);
            void SetOutputHlColor(emColor outputHlColor);
                    // Get/set background, foreground and highlight (=selection)
                    // colors of read-only data fields.

            unsigned int GetDataRefCount() const;
                    // Get number of references to the internal data of this object.

            void MakeNonShared();
                    // This must be called before handing the look to another
                    // thread.

    private:

            void DeleteData();
            void MakeWritable();

            struct SharedData {
                    SharedData();
                    SharedData(const SharedData & sd);
                    unsigned int RefCount;
                    emColor BgColor;
                    emColor FgColor;
                    emColor ButtonBgColor;
                    emColor ButtonFgColor;
                    emColor InputBgColor;
                    emColor InputFgColor;
                    emColor InputHlColor;
                    emColor OutputBgColor;
                    emColor OutputFgColor;
                    emColor OutputHlColor;
            };

            SharedData * Data;

            static SharedData DefaultData;
    };

    #ifndef EM_NO_DATA_EXPORT
    inline emTkLook::emTkLook()
    {
            Data=&DefaultData;
    }
    #endif

    inline emTkLook::emTkLook(const emTkLook & look)
    {
            Data=look.Data;
            Data->RefCount++;
    }

    inline emTkLook::~emTkLook()
    {
            if (!--Data->RefCount) DeleteData();
    }

    inline emTkLook & emTkLook::operator = (const emTkLook & look)
    {
            look.Data->RefCount++;
            if (!--Data->RefCount) DeleteData();
            Data=look.Data;
            return *this;
    }

    inline bool emTkLook::operator != (const emTkLook & look) const
    {
            return !(*this==look);
    }

    inline emColor emTkLook::GetBgColor() const
    {
            return Data->BgColor;
    }

    inline emColor emTkLook::GetFgColor() const
    {
            return Data->FgColor;
    }

    inline emColor emTkLook::GetButtonBgColor() const
    {
            return Data->ButtonBgColor;
    }

    inline emColor emTkLook::GetButtonFgColor() const
    {
            return Data->ButtonFgColor;
    }

    inline emColor emTkLook::GetInputBgColor() const
    {
            return Data->InputBgColor;
    }

    inline emColor emTkLook::GetInputFgColor() const
    {
            return Data->InputFgColor;
    }

    inline emColor emTkLook::GetInputHlColor() const
    {
            return Data->InputHlColor;
    }

    inline emColor emTkLook::GetOutputBgColor() const
    {
            return Data->OutputBgColor;
    }

    inline emColor emTkLook::GetOutputFgColor() const
    {
            return Data->OutputFgColor;
    }

    inline emColor emTkLook::GetOutputHlColor() const
    {
            return Data->OutputHlColor;
    }

    inline void emTkLook::MakeNonShared()
    {
            MakeWritable();
    }

    //==============================================================================
    //================================= emTkBorder =================================
    //==============================================================================

    class emTkBorder : public emPanel {

    public:

            // This is the base class of all toolkit panels. A panel of this class
            // can have a border, a label, a how-to text and an auxiliary area. And
            // it has a content area. The label can consist of a caption, a
            // description and an icon. The how-to text describes how to use the
            // type of panel in general, and maybe something about its state. The
            // auxiliary area is for showing a custom panel with additional things
            // like a configuration or an extended help text. The label, the how-to
            // text and the auxiliary area are shown in the border. Alternatively, a
            // derived class can manage to move the label into the content area.

            emTkBorder(
                    ParentArg parent, const emString & name,
                    const emString & caption=emString(),
                    const emString & description=emString(),
                    const emImage & icon=emImage()
            );
                    // 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.

            virtual ~emTkBorder();
                    // Destructor.

            const emString & GetCaption() const;
            void SetCaption(const emString & caption);
                    // The caption to be shown in the label.

            const emString & GetDescription() const;
            void SetDescription(const emString & description);
                    // The description to be shown in the label.

            const emImage & GetIcon() const;
            void SetIcon(const emImage & icon);
                    // The icon to be shown in the label.

            void SetLabel(
                    const emString & caption=emString(),
                    const emString & description=emString(),
                    const emImage & icon=emImage()
            );
                    // Set all three things which are making up the label.

            emAlignment GetLabelAlignment() const;
            void SetLabelAlignment(emAlignment labelAlignment);
                    // Alignment of the label as a whole within its available space.

            emAlignment GetCaptionAlignment() const;
            void SetCaptionAlignment(emAlignment captionAlignment);
                    // Horizontal alignment of lines within the caption text of the
                    // label. The top and bottom flags are ignored.

            emAlignment GetDescriptionAlignment() const;
            void SetDescriptionAlignment(emAlignment descriptionAlignment);
                    // Horizontal alignment of lines within the description text of
                    // the label. The top and bottom flags are ignored.

            enum OuterBorderType {
                    // Possibles types for the outer border line. This even
                    // specifies whether the background of the panel should be
                    // filled or not.
                    OBT_NONE,
                            // Do not have an outer border line, do not have a
                            // margin and do not fill the background.
                    OBT_FILLED,
                            // Like OBT_NONE, but fill the whole background with
                            // background color.
                    OBT_MARGIN,
                            // Like OBT_NONE, but have a small margin (for example,
                            // this is used by emTkLabel and emTkCheckBox). Larger
                            // margins should be solved through the parent panel,
                            // e.g. see emTkTiling::SetSpace.
                    OBT_MARGIN_FILLED,
                            // Like OBT_MARGIN, but fill the whole background.
                    OBT_RECT,
                            // Have a rectangular outer border line and fill the
                            // rectangle with background color. Have a small margin.
                    OBT_ROUND_RECT,
                            // Like OBT_RECT but with round corners.
                    OBT_GROUP,
                            // Have a small special outer border for groups (used by
                            // emTkGroup).
                    OBT_INSTRUMENT,
                            // Like OBT_GROUP, but the border line is thicker (for
                            // example, this is used by emTkTextField).
                    OBT_INSTRUMENT_MORE_ROUND,
                            // Like OBT_INSTRUMENT, but with a larger corner radius
                            // (this is used by emTkButton).
                    OBT_POPUP_ROOT
                            // Have a special border for root panels of views which
                            // have the VF_POPUP_ZOOM flag set (should not be used
                            // for something else).
            };

            enum InnerBorderType {
                    // Possibles types for the inner border line.
                    IBT_NONE,
                            // Do not have an inner border line.
                    IBT_GROUP,
                            // Have a special round inner border line for groups.
                    IBT_INPUT_FIELD,
                            // Have a special round inner border and background for
                            // editable fields.
                    IBT_OUTPUT_FIELD,
                            // Have a special round inner border and background for
                            // non-editable fields.
                    IBT_CUSTOM_RECT
                            // Have a special rectangular inner border for custom
                            // stuff. Herewith, the content rectangle never has
                            // round corners.
            };

            OuterBorderType GetOuterBorderType() const;
            InnerBorderType GetInnerBorderType() const;
            void SetOuterBorderType(OuterBorderType obt);
            void SetInnerBorderType(InnerBorderType ibt);
            void SetBorderType(OuterBorderType obt, InnerBorderType ibt);
                    // Outer and inner border types. The default is OBT_NONE and
                    // IBT_NONE.

            double GetBorderScaling() const;
            void SetBorderScaling(double borderScaling);
                    // Scale factor for the size of the border. The default is 1.0.

            const emTkLook & GetLook() const;
            virtual void SetLook(const emTkLook & look, bool recursively=false);
                    // Look of this toolkit panel. At construction of a panel, the
                    // look is copied from the parent panel (if the parent is not
                    // emTkBorder, the grand parent is asked, and so on). When
                    // setting the look with the argument recursively=true, all
                    // descendant panels of class emTkBorder are even set through
                    // calling emTkLook::Apply for every child panel.

            void HaveAux(const emString & panelName, double tallness);
                    // Make this border having a rectangular area for auxiliary
                    // stuff. It could be a user interface for configuring this
                    // panel, or an extended function, or some additional help or
                    // what ever you want. Either you could show the things through
                    // a child panel or through custom painting, but doing it with a
                    // child panel is easier. Whenever you create that panel. It is
                    // laid out automatically into the auxiliary area.
                    // Arguments:
                    //   panelName - Name of the child panel to be laid out in the
                    //               auxiliary area.
                    //   tallness  - Height/width ratio of the auxiliary area.

            void RemoveAux();
                    // Inversion of HaveAux (does not delete the auxiliary panel).

            bool HasAux() const;
                    // Whether this border has an area for auxiliary stuff.

            const emString & GetAuxPanelName() const;
            double GetAuxTallness() const;
                    // Properties of the auxiliary area set with HaveAux. Valid only
                    // if HasAux()==true.

            emPanel * GetAuxPanel();
                    // Returns the auxiliary child panel, or NULL if not present.

            void GetAuxRect(
                    double * pX, double * pY, double * pW, double * pH,
                    emColor * pCanvasColor=NULL
            );
                    // Get the coordinates and canvas color of the auxiliary area.
                    // Valid only if HasAux()==true.

            virtual void GetContentRect(
                    double * pX, double * pY, double * pW, double * pH,
                    emColor * pCanvasColor=NULL
            );
                    // Get the coordinates and canvas color of the content area as a
                    // rectangle. If the inner border has round corners, the
                    // rectangle returned here is smaller than with
                    // GetContentRoundRect, so that it fits completely into the
                    // content area.

            virtual void GetContentRoundRect(
                    double * pX, double * pY, double * pW, double * pH, double * pR,
                    emColor * pCanvasColor=NULL
            );
                    // Get the coordinates and canvas color of the content area as a
                    // round rectangle (argument pR is for returning the radius of
                    // the corners).

    protected:

            virtual void Notice(NoticeFlags flags);
            virtual bool IsOpaque();
            virtual void Paint(const emPainter & painter, emColor canvasColor);
            virtual void LayoutChildren();
                    // See emPanel. Hint: For painting the content area, please
                    // overload PaintContent instead of Paint, because with certain
                    // border types, a shadow is painted over the content area.

            virtual bool HasHowTo();
            virtual emString GetHowTo();
                    // This is about a text describing how to use this panel. If
                    // HasHowTo()==true, the text returned by GetHowTo() is shown
                    // very small in the center of the left edge of the border. When
                    // overloading GetHowTo(), please do not forget to call the
                    // original version and to include that text at the beginning.
                    // The default implementation of GetHowTo() returns a preface,
                    // and optionally a description of the disable state (if
                    // disabled) and optionally a description of the keyboard focus
                    // (if focusable). The default implementation of HasHowTo()
                    // return false, because the default text alone is not so
                    // helpful, and because the text would disturb some panel types.

            virtual void PaintContent(
                    const emPainter & painter, double x, double y, double w,
                    double h, emColor canvasColor
            );
                    // This can be overloaded for painting the content area. The
                    // default implementation does nothing. The coordinates x,y,w,h
                    // are like from GetContentRect, but you could even use the
                    // coordinates returned by GetContentRoundRect.

            virtual bool HasLabel();
                    // Whether this panel has a label. The default implementation
                    // checks whether at least one of caption, description and icon
                    // is not empty.

            virtual double GetBestLabelTallness();
                    // Get the ideal tallness for the label area. The default
                    // implementation calculates this for the default implementation
                    // of PaintLabel.

            virtual void PaintLabel(
                    const emPainter & painter, double x, double y, double w,
                    double h, emColor color, emColor canvasColor
            );
                    // Paint the label. The default implementation paints the
                    // caption, description and icon. This could be overloaded to
                    // paint something else for the label.

            bool IsLabelInBorder() const;
            void SetLabelInBorder(bool labelInBorder);
                    // Whether to show the label as part of the border. The default
                    // is true. If a derived class wants to have the label as part
                    // of the content, it should set false here and call PaintLabel
                    // itself.

            struct TkResources {
                    TkResources();
                    ~TkResources();
                    emImage ImgButton;
                    emImage ImgButtonBorder;
                    emImage ImgButtonChecked;
                    emImage ImgButtonPressed;
                    emImage ImgCheckBox;
                    emImage ImgCheckBoxPressed;
                    emImage ImgCustomRectBorder;
                    emImage ImgGroupBorder;
                    emImage ImgGroupInnerBorder;
                    emImage ImgIOField;
                    emImage ImgPopupBorder;
                    emImage ImgRadioBox;
                    emImage ImgRadioBoxPressed;
                    emImage ImgSplitter;
                    emImage ImgSplitterPressed;
                    emImage ImgTunnel;
            };
            const TkResources & GetTkResources() const;
                    // Shared resources used by the toolkit panel implementations.
                    // This is more or less private stuff - do not use in custom
                    // classes.

    private:

            enum DoBorderFunc {
                    BORDER_FUNC_PAINT,
                    BORDER_FUNC_CONTENT_RECT,
                    BORDER_FUNC_CONTENT_ROUND_RECT,
                    BORDER_FUNC_AUX_RECT
            };
            void DoBorder(
                    DoBorderFunc func, const emPainter * painter,
                    emColor canvasColor, double * pX, double * pY, double * pW,
                    double * pH, double * pR, emColor * pCanvasColor
            );

            enum DoLabelFunc {
                    LABEL_FUNC_PAINT,
                    LABEL_FUNC_GET_BEST_TALLNESS
            };
            void DoLabel(
                    DoLabelFunc func, const emPainter * painter, double x, double y,
                    double w, double h, emColor color, emColor canvasColor,
                    double * pBestTallness
            );

            struct AuxData {
                    emString PanelName;
                    double Tallness;
                    emCrossPtr<emPanel> PanelPointerCache;
            };

            emRef<emVarModel<TkResources> > TkResVarModel;
            emString Caption;
            emString Description;
            emImage Icon;
            AuxData * Aux;
            emTkLook Look;
            double BorderScaling;
            emAlignment LabelAlignment;
            emAlignment CaptionAlignment;
            emAlignment DescriptionAlignment;
            emByte OuterBorder;
            emByte InnerBorder;
            bool LabelInBorder;

            static const char * HowToPreface;
            static const char * HowToDisabled;
            static const char * HowToFocus;
    };

    inline const emString & emTkBorder::GetCaption() const
    {
            return Caption;
    }

    inline const emString & emTkBorder::GetDescription() const
    {
            return Description;
    }

    inline const emImage & emTkBorder::GetIcon() const
    {
            return Icon;
    }

    inline emAlignment emTkBorder::GetLabelAlignment() const
    {
            return LabelAlignment;
    }

    inline emAlignment emTkBorder::GetCaptionAlignment() const
    {
            return CaptionAlignment;
    }

    inline emAlignment emTkBorder::GetDescriptionAlignment() const
    {
            return DescriptionAlignment;
    }

    inline emTkBorder::OuterBorderType emTkBorder::GetOuterBorderType() const
    {
            return (OuterBorderType)OuterBorder;
    }

    inline emTkBorder::InnerBorderType emTkBorder::GetInnerBorderType() const
    {
            return (InnerBorderType)InnerBorder;
    }

    inline double emTkBorder::GetBorderScaling() const
    {
            return BorderScaling;
    }

    inline const emTkLook & emTkBorder::GetLook() const
    {
            return Look;
    }

    inline bool emTkBorder::HasAux() const
    {
            return Aux!=NULL;
    }

    inline bool emTkBorder::IsLabelInBorder() const
    {
            return LabelInBorder;
    }

    inline const emTkBorder::TkResources & emTkBorder::GetTkResources() const
    {
            return TkResVarModel->Var;
    }

    //==============================================================================
    //================================= emTkLabel ==================================
    //==============================================================================

    class emTkLabel : public emTkBorder {

    public:

            // A panel of this class simply shows the label as the content, and it
            // is not focusable by default.

            emTkLabel(
                    ParentArg parent, const emString & name,
                    const emString & caption=emString(),
                    const emString & description=emString(),
                    const emImage & icon=emImage()
            );
                    // Like emTkBorder, but it performs:
                    //  SetOuterBorderType(OBT_MARGIN);
                    //  SetLabelInBorder(false);
                    //  SetFocusable(false);

    protected:

            virtual void PaintContent(
                    const emPainter & painter, double x, double y, double w,
                    double h, emColor canvasColor
            );
                    // Paints the label.
    };

    //==============================================================================
    //================================= emTkTiling =================================
    //==============================================================================

    class emTkTiling : public emTkBorder {

    public:

            // A panel of this class automatically lays out any child panels within
            // the content area, just like in a rectangular tiling. By default, the
            // panel itself is not focusable and has no border, because it is meant
            // as a pure layout programming tool. For other use, see the derived
            // class emTkGroup.

            emTkTiling(
                    ParentArg parent, const emString & name,
                    const emString & caption=emString(),
                    const emString & description=emString(),
                    const emImage & icon=emImage()
            );
                    // Like emTkBorder, but sets non-focusable.

            virtual ~emTkTiling();
                    // Destructor.

            bool IsRowByRow() const;
            void SetRowByRow(bool rowByRow=true);
                    // Whether to layout the child panels column-by-column (false,
                    // the default) or row-by-row (true). Here is an example for the
                    // order of 10 panels in a 4x3 grid:
                    //   column-by-column      row-by-row
                    //      1  4  7 10         1  2  3  4
                    //      2  5  8            5  6  7  8
                    //      3  6  9            9 10

            int GetFixedColumnCount() const;
            int GetFixedRowCount() const;
            void SetFixedColumnCount(int fixedColumnCount);
            void SetFixedRowCount(int fixedRowCount);
                    // Whether to have a fixed number of columns or rows, and how
                    // many. A value less or equal zero means to have no fixed
                    // number of columns or rows and to let the layout algorithm
                    // decide it. If both are fixed and if there are more child
                    // panels than cells, the row count is increased accordingly.
                    // The default is zero for both.

            int GetMinCellCount() const;
            void SetMinCellCount(int minCellCount);
                    // Minimum number of cells to be generated. The layout algorithm
                    // behaves like if there were at least this number of child
                    // panels. The additional cells are simply making up unused
                    // space. The default is zero.

            void SetChildTallness(double ct);
                    // Set the demanded tallness of child panels (height/width
                    // ratio). This method is a short cut for:
                    //   SetPrefChildTallness(ct);
                    //   SetChildTallnessForced();

            void SetPrefChildTallness(double pct);
                    // Set the preferred tallness of child panels (height/width
                    // ratio). The child panels may get another tallness, for
                    // filling the available space best possible. This method is a
                    // short cut for: SetPrefChildTallness(pct,0,true);

            double GetPrefChildTallness(int idx) const;
            void SetPrefChildTallness(double pct, int idx, bool allFurther=true);
                    // Preferred tallness of child panels in the first row and in
                    // the first column. The index idx denotes a cell. It is a cell
                    // in the first row (idx>0) or in the first column (idx<0), or
                    // both (idx==0). Other cells cannot be set, because they are
                    // sized implicitly by the first row and column. Here is a chart
                    // showing the meaning of idx, and the effect of different
                    // tallnesses:
                    //
                    //   +--------+-------+-------------+-----+----
                    //   | idx  0 | idx 1 |    idx 2    |idx 3| ...
                    //   +--------+-------+-------------+-----+----
                    //   |        |       |             |     |
                    //   | idx -1 |       |             |     |
                    //   |        |       |             |     |
                    //   +--------+-------+-------------+-----+----
                    //   | idx -2 |       |             |     |
                    //   +--------+-------+-------------+-----+----
                    //   |        |       |             |     |
                    //   |        |       |             |     |
                    //   | idx -3 |       |             |     |
                    //   |        |       |             |     |
                    //   |        |       |             |     |
                    //   +--------+-------+-------------+-----+----
                    //   | ...    |       |             |     |
                    //
                    // Now to the important trick argument "allFurther": If true
                    // (the default), all further cells in the row and/or column are
                    // even set. For example, SetPrefChildTallness(1.0,3) means to
                    // set the cells 3, 4, 5, ... INT_MAX. And
                    // SetPrefChildTallness(1.0,-2) means to set the cells -2, -3,
                    // -4, ... INT_MIN. And SetPrefChildTallness(1.0,-3,false) means
                    // to set cell -3 only. And SetPrefChildTallness(1.0,0) means to
                    // set all cells at once.
                    //
                    // There is no limit for idx except through the memory required
                    // by internal arrays.
                    //
                    // The default preferred child tallness is: 0.2

            void SetChildTallnessForced(bool forced=true);
                    // Whether the preferred child tallness has to be applied in any
                    // case, instead of deviating for filling the whole available
                    // space. This method is a short cut for:
                    //   SetForcedChildTallnessColumn(forced ? 0 : -1);
                    //   SetForcedChildTallnessRow(forced ? 0 : -1);

            int GetForcedChildTallnessColumn() const;
            int GetForcedChildTallnessRow() const;
            void SetForcedChildTallnessColumn(int column);
            void SetForcedChildTallnessRow(int row);
                    // Index of a single column or row, in which the preferred child
                    // tallness has to be applied in any case. -1 means to have no
                    // such column or row (this is the default). Understand that if
                    // both a row and a column are forced, all cells of the whole
                    // grid are forced implicitly.

            emAlignment GetAlignment() const;
            void SetAlignment(emAlignment alignment);
                    // Alignment of the child panels as a whole within the available
                    // space. This applies only if the available space cannot be
                    // filled completely, with respect to forced child tallness. The
                    // default is EM_ALIGN_CENTER.

            double GetSpaceL() const;
            double GetSpaceT() const;
            double GetSpaceH() const;
            double GetSpaceV() const;
            double GetSpaceR() const;
            double GetSpaceB() const;
            void SetSpaceL(double l);
            void SetSpaceT(double t);
            void SetSpaceH(double h);
            void SetSpaceV(double v);
            void SetSpaceR(double r);
            void SetSpaceB(double b);
            void SetSpace(double l, double t, double h, double v, double r,
                          double b);
            void SetSpace(double lr, double tb, double h, double v);
            void SetInnerSpace(double h, double v);
            void SetOuterSpace(double l, double t, double r, double b);
            void SetOuterSpace(double lr, double tb);
                    // Left, top, horizontal, vertical, right and bottom space (l,
                    // t, h, v, r, b). This defines space between child panels, and
                    // between child panels and borders. Here is a chart showing the
                    // meaning of the six parameters:
                    //
                    //   +-------------------- border -------------------+
                    //   |         t             t             t         |
                    //   |     +-------+     +-------+     +-------+     |
                    //   |  l  + panel +  h  + panel +  h  + panel +  r  |
                    //   |     +-------+     +-------+     +-------+     |
                    //   |         v             v             v         |
                    //   |     +-------+     +-------+     +-------+     |
                    //   |  l  + panel +  h  + panel +  h  + panel +  r  |
                    //   |     +-------+     +-------+     +-------+     |
                    //   |         b             b             b         |
                    //   +-----------------------------------------------+
                    //
                    // The method argument lr means to set l and r to the same
                    // value, same with tb for t and b.
                    //
                    // The values are relative to the average size of the child
                    // panels. For example, v=0.5 means that the vertical space
                    // between child panels gets half as tall as an average child
                    // panel. The default is zero for all parameters.

    protected:

            virtual void LayoutChildren();
                    // Tiles all child panels in the content area (except for an
                    // auxiliary panel, which is laid out in the border).

    private:

            double SpaceL,SpaceT,SpaceH,SpaceV,SpaceR,SpaceB;
            double PCT;
            emArray<double> PCTPos, PCTNeg;
            int FixedColumnCount,FixedRowCount,MinCellCount,FCTColumn,FCTRow;
            emAlignment Alignment;
            bool RowByRow;
    };

    inline bool emTkTiling::IsRowByRow() const
    {
            return RowByRow;
    }

    inline int emTkTiling::GetFixedColumnCount() const
    {
            return FixedColumnCount;
    }

    inline int emTkTiling::GetFixedRowCount() const
    {
            return FixedRowCount;
    }

    inline int emTkTiling::GetMinCellCount() const
    {
            return MinCellCount;
    }

    inline int emTkTiling::GetForcedChildTallnessColumn() const
    {
            return FCTColumn;
    }

    inline int emTkTiling::GetForcedChildTallnessRow() const
    {
            return FCTRow;
    }

    inline emAlignment emTkTiling::GetAlignment() const
    {
            return Alignment;
    }

    inline double emTkTiling::GetSpaceL() const
    {
            return SpaceL;
    }

    inline double emTkTiling::GetSpaceT() const
    {
            return SpaceT;
    }

    inline double emTkTiling::GetSpaceH() const
    {
            return SpaceH;
    }

    inline double emTkTiling::GetSpaceV() const
    {
            return SpaceV;
    }

    inline double emTkTiling::GetSpaceR() const
    {
            return SpaceR;
    }

    inline double emTkTiling::GetSpaceB() const
    {
            return SpaceB;
    }

    //==============================================================================
    //================================= emTkGroup ==================================
    //==============================================================================

    class emTkGroup : public emTkTiling {

    public:

            // Class for a group of panels. Any user-created child panels are laid
            // out automatically. This is just like emTkTiling, but it has a group
            // border and it is focusable.

            emTkGroup(
                    ParentArg parent, const emString & name,
                    const emString & caption=emString(),
                    const emString & description=emString(),
                    const emImage & icon=emImage()
            );
    };

    //==============================================================================
    //================================= emTkTunnel =================================
    //==============================================================================

    class emTkTunnel : public emTkBorder {

    public:

            // This panel shows a single child panel very small. Around that, a
            // decoration is painted which looks like a tunnel. Therefore the name
            // of this class. The single child panel is laid out automatically
            // whenever it is created by the user of this class.

            emTkTunnel(
                    ParentArg parent, const emString & name,
                    const emString & caption=emString(),
                    const emString & description=emString(),
                    const emImage & icon=emImage()
            );
                    // Constructor.

            double GetChildTallness() const;
            void SetChildTallness(double childTallness);
                    // Tallness for the child panel (end of tunnel). A value <=0.0
                    // means to take the tallness of the content rectangle. That is
                    // the default.

            double GetDepth() const;
            void SetDepth(double depth);
                    // Depth of the tunnel. The formula is more or less:
                    //   AreaOfEnd = AreaOfEntrance/((Depth+1)*(Depth+1))
                    // The default is 10.0.

            virtual void GetChildRect(
                    double * pX, double * pY, double * pW, double * pH,
                    emColor * pCanvasColor=NULL
            );
                    // Get coordinates and canvas color of the end of the tunnel.

    protected:

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

            virtual void LayoutChildren();

    private:

            enum DoTunnelFunc {
                    TUNNEL_FUNC_PAINT,
                    TUNNEL_FUNC_CHILD_RECT
            };
            void DoTunnel(
                    DoTunnelFunc func, const emPainter * painter,
                    emColor canvasColor, double * pX, double * pY, double * pW,
                    double * pH, emColor * pCanvasColor
            );

            double ChildTallness,Depth;
    };

    inline double emTkTunnel::GetChildTallness() const
    {
            return ChildTallness;
    }

    inline double emTkTunnel::GetDepth() const
    {
            return Depth;
    }

    //==============================================================================
    //================================= emTkButton =================================
    //==============================================================================

    class emTkButton : public emTkBorder {

    public:

            // Class for a button. Buttons can be triggered (clicked) by the user to
            // perform a function. The label is shown in the button face.

            emTkButton(
                    ParentArg parent, const emString & name,
                    const emString & caption=emString(),
                    const emString & description=emString(),
                    const emImage & icon=emImage()
            );
                    // 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.

            virtual ~emTkButton();
                    // Destructor.

            bool IsNoEOI() const;
            void SetNoEOI(bool noEOI=true);
                    // Whether clicking this button is not an "End Of Interaction".
                    // If false (the default), GetView().SignalEOIDelayed() is
                    // called on every click.

            const emSignal & GetClickSignal() const;
                    // This signal is signaled when the button has been clicked.

            const emSignal & GetPressStateSignal() const;
                    // This signal is signaled when the press state has changed (see
                    // IsPressed()).

            bool IsPressed() const;
                    // Whether the button is currently pressed or not.

            void Click(bool shift=false);
                    // Perform a button click programmatically.

    protected:

            virtual void Clicked();
                    // Called when the button has been clicked.

            virtual void PressStateChanged();
                    // Called when the press state has changed.

            virtual void Input(emInputEvent & event, const emInputState & state,
                               double mx, double my);

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

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

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

            virtual bool CheckMouse(double mx, double my);

            bool IsShownChecked() const;
            bool IsShownBoxed() const;
            bool IsShownRadioed() const;
            void SetShownChecked(bool shownChecked);
            void SetShownBoxed(bool shownBoxed);
            void SetShownRadioed(bool shownRadioed);
                    // Yes, this class has the ability to paint all our button
                    // types.

    private:

            enum DoButtonFunc {
                    BUTTON_FUNC_PAINT,
                    BUTTON_FUNC_CHECK_MOUSE
            };
            void DoButton(
                    DoButtonFunc func, const emPainter * painter,
                    emColor canvasColor,
                    double mx, double my, bool * pHit
            );

            emSignal ClickSignal;
            emSignal PressStateSignal;
            unsigned Pressed : 1;
            unsigned NoEOI : 1;
            unsigned ShownChecked : 1;
            unsigned ShownBoxed : 1;
            unsigned ShownRadioed : 1;

            static const char * HowToButton;
            static const char * HowToEOIButton;
    };

    inline bool emTkButton::IsNoEOI() const
    {
            return NoEOI;
    }

    inline const emSignal & emTkButton::GetClickSignal() const
    {
            return ClickSignal;
    }

    inline const emSignal & emTkButton::GetPressStateSignal() const
    {
            return PressStateSignal;
    }

    inline bool emTkButton::IsPressed() const
    {
            return Pressed;
    }

    inline bool emTkButton::IsShownChecked() const
    {
            return ShownChecked;
    }

    inline bool emTkButton::IsShownBoxed() const
    {
            return ShownBoxed;
    }

    inline bool emTkButton::IsShownRadioed() const
    {
            return ShownRadioed;
    }

    //==============================================================================
    //============================== emTkCheckButton ===============================
    //==============================================================================

    class emTkCheckButton : public emTkButton {

    public:

            // Class for a check button. This is like emTkButton, but a check state
            // is managed and shown. The check state toggles on every click of the
            // button, for switching something on and off.

            emTkCheckButton(
                    ParentArg parent, const emString & name,
                    const emString & caption=emString(),
                    const emString & description=emString(),
                    const emImage & icon=emImage()
            );
                    // Like emTkButton. The initial check state is false.

            virtual ~emTkCheckButton();
                    // Destructor.

            const emSignal & GetCheckSignal() const;
                    // This signal is signaled when the check state has changed.

            bool IsChecked() const;
            void SetChecked(bool checked=true);
                    // Get/set the check state of this button.

    protected:

            virtual void Clicked();
                    // See emTkButton. This implements the toggling of the check
                    // state.

            virtual void CheckChanged();
                    // Called when the check state has changed.

            virtual emString GetHowTo();

    private:

            emSignal CheckSignal;
            bool Checked;

            static const char * HowToCheckButton;
            static const char * HowToChecked;
            static const char * HowToNotChecked;
    };

    inline const emSignal & emTkCheckButton::GetCheckSignal() const
    {
            return CheckSignal;
    }

    inline bool emTkCheckButton::IsChecked() const
    {
            return Checked;
    }

    //==============================================================================
    //============================== emTkRadioButton ===============================
    //==============================================================================

    class emTkRadioButton : public emTkCheckButton {

    public:

            // Class for a radio button. This is similar to a check button, but in a
            // set of radio buttons, only one button can have checked state, and the
            // user can unchecked a button only by checking another. That is the
            // usual behavior. Actually an emTkRadioButton does not modify its check
            // state on any click, as long as it is not a member of an
            // emTkRadioButton::Mechanism or emTkRadioButton::Group (it's not a must
            // to use these helper classes).

            emTkRadioButton(
                    ParentArg parent, const emString & name,
                    const emString & caption=emString(),
                    const emString & description=emString(),
                    const emImage & icon=emImage()
            );
                    // Like emTkCheckButton.

            virtual ~emTkRadioButton();
                    // Destructor. Removes the button from any Mechanism.

            class Mechanism : public emUncopyable {

            public:

                    // Class for the mechanism of a set of radio buttons.

                    Mechanism();
                    virtual ~Mechanism();

                    void Add(emTkRadioButton * radioButton);
                            // Add a radio button to this mechanism. If the button
                            // is already a member of another mechanism, it is
                            // removed from that mechanism automatically.

                    void AddAll(emPanel * parent);
                            // Add all radio buttons which are children of the given
                            // panel.

                    void Remove(emTkRadioButton * radioButton);
                    void RemoveByIndex(int index);
                            // Remove a radio button from this mechanism.

                    void RemoveAll();
                            // Remove all radio buttons from this mechanism.

                    const emSignal & GetCheckSignal() const;
                            // This signal is signaled whenever there was a change
                            // in the result of GetChecked().

                    emTkRadioButton * GetChecked();
                    const emTkRadioButton * GetChecked() const;
                    void SetChecked(emTkRadioButton * radioButton);
                            // Get/set the member button which is currently checked.
                            // NULL means to have no member button checked.

                    int GetCheckIndex();
                    void SetCheckIndex(int index);
                            // Get/set the index of the member button which is
                            // currently checked. -1 means to have no member button
                            // checked.

                    int GetCount();
                            // Get number of member buttons.

                    int GetIndexOf(const emTkRadioButton * button) const;
                            // Get the index of a member button, or -1 if not found.

            protected:

                    virtual void CheckChanged();
                            // Called whenever there was a change in the result of
                            // GetChecked().

            private:

                    emArray<emTkRadioButton *> Array;
                    emSignal CheckSignal;
                    int CheckIndex;
            };

            class Group : public emTkGroup, public Mechanism {

            public:

                    // Combination of emTkGroup and Mechanism. Any radio buttons
                    // created as children of such a group are added automatically
                    // to the mechanism (this magic happens in the constructor of
                    // emTkRadioButton).

                    Group(
                            ParentArg parent, const emString & name,
                            const emString & caption=emString(),
                            const emString & description=emString(),
                            const emImage & icon=emImage()
                    );
                            // Like the constructor of emTkGroup.

                    virtual ~Group();
                            // Destructor.
            };

    protected:

            virtual void Clicked();

            virtual void CheckChanged();

            virtual emString GetHowTo();

    private:

            friend class Mechanism;

            Mechanism * Mech;
            int MechIndex;

            static const char * HowToRadioButton;
    };

    inline const emSignal & emTkRadioButton::Mechanism::GetCheckSignal() const
    {
            return CheckSignal;
    }

    inline emTkRadioButton * emTkRadioButton::Mechanism::GetChecked()
    {
            return CheckIndex>=0 ? Array[CheckIndex] : NULL;
    }

    inline const emTkRadioButton * emTkRadioButton::Mechanism::GetChecked() const
    {
            return CheckIndex>=0 ? Array[CheckIndex] : NULL;
    }

    inline int emTkRadioButton::Mechanism::GetCheckIndex()
    {
            return CheckIndex;
    }

    inline int emTkRadioButton::Mechanism::GetCount()
    {
            return Array.GetCount();
    }

    inline int emTkRadioButton::Mechanism::GetIndexOf(
            const emTkRadioButton * button
    ) const
    {
            return button && button->Mech==this ? button->MechIndex : -1;
    }

    //==============================================================================
    //================================ emTkCheckBox ================================
    //==============================================================================

    class emTkCheckBox : public emTkCheckButton {

    public:

            // This is like emTkCheckButton, but with a different visualization:
            // Instead of a push button, a small check box is shown with the label
            // on the right.

            emTkCheckBox(
                    ParentArg parent, const emString & name,
                    const emString & caption=emString(),
                    const emString & description=emString(),
                    const emImage & icon=emImage()
            );
    };

    //==============================================================================
    //================================ emTkRadioBox ================================
    //==============================================================================

    class emTkRadioBox : public emTkRadioButton {

    public:

            // This is like emTkRadioButton, but with a different visualization:
            // Instead of a push button, a small check box is shown with the label
            // on the right.

            emTkRadioBox(
                    ParentArg parent, const emString & name,
                    const emString & caption=emString(),
                    const emString & description=emString(),
                    const emImage & icon=emImage()
            );
    };

    //==============================================================================
    //=============================== emTkTextField ================================
    //==============================================================================

    class emTkTextField : public emTkBorder {

    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.

            emTkTextField(
                    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 ~emTkTextField();
                    // 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(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();
            virtual emString GetHowTo();

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

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

    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
            );

            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 emTkTextField::IsEditable() const
    {
            return Editable;
    }

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

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

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

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

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

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

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

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

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

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

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

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

    //==============================================================================
    //============================== emTkScalarField ===============================
    //==============================================================================

    class emTkScalarField : public emTkBorder {

    public:

            // Class for a data field panel showing a scalar value which can
            // optionally be edited by the user. The scalar value is a 64-bit signed
            // integer number, but on the shown scale the values can be translated
            // to any texts (e.g. rational numbers, names ,...).

            emTkScalarField(
                    ParentArg parent, const emString & name,
                    const emString & caption=emString(),
                    const emString & description=emString(),
                    const emImage & icon=emImage(),
                    emInt64 minValue=0, emInt64 maxValue=10, emInt64 value=0,
                    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.
                    //   minValue    - Minimum allowed value.
                    //   maxValue    - Maximum allowed value.
                    //   value       - Initial value.
                    //   editable    - Whether the value can be edited by the user.

            virtual ~emTkScalarField();
                    // Destructor.

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

            emInt64 GetMinValue() const;
            emInt64 GetMaxValue() const;
            void SetMinValue(emInt64 minValue);
            void SetMaxValue(emInt64 maxValue);
            void SetMinMaxValues(emInt64 minValue, emInt64 maxValue);
                    // Get/set the range of possible values.

            const emSignal & GetValueSignal() const;
                    // This signal is signaled after each change of the value.

            emInt64 GetValue() const;
            void SetValue(emInt64 value);
                    // Get/set the value.

            const emArray<emUInt64> & GetScaleMarkIntervals() const;
            void SetScaleMarkIntervals(const emArray<emUInt64> & intervals);
            void SetScaleMarkIntervals(unsigned interval1, unsigned interval2, ...);
                    // Get/set the layout of scale marks. It is an array of
                    // intervals between the scale marks of different size levels.
                    // The first interval is for the largest scale marks, the second
                    // is for the second-largest scale marks and so on. Thus, the
                    // array must be sorted from large to small. For example, a
                    // classic centimeter rule would have {10,5,1}, with the values
                    // in millimeters. The default is {1}. The arguments to the
                    // ellipse version method must be terminated by a 0. Note that
                    // the ellipse version can take only 32-bit intervals (I am not
                    // sure whether an ellipse on emUInt64 would be portable).

            bool IsNeverHidingMarks() const;
            void SetNeverHideMarks(bool neverHide);
                    // By default, marks with an interval greater than
                    // (MaxValue - MinValue) are automatically not shown, so that
                    // the other marks can be seen better. Setting true here
                    // disables that automatism.

            virtual void TextOfValue(char * buf, int bufSize, emInt64 value,
                                     emUInt64 markInterval) const;
                    // Convert a scale mark value to a null-terminated character
                    // string for display on the scale. The default implementation
                    // uses the callback function set with SetTextOfValueFunc.

            void SetTextOfValueFunc(
                    void(*textOfValueFunc)(
                            char * buf, int bufSize, emInt64 value,
                            emUInt64 markInterval, void * context
                    ),
                    void * context=NULL
            );
                    // Set a function for converting a scale mark value to a
                    // null-terminated character string for display on the scale.
                    // The context argument is forwarded to the function for any
                    // use. The default performs simple decimal conversion.

            static void DefaultTextOfValue(
                    char * buf, int bufSize, emInt64 value, emUInt64 markInterval,
                    void * context
            );
                    // This is the default text-of-value-function. It performs
                    // decimal conversion.

            double GetTextBoxTallness() const;
            void SetTextBoxTallness(double textBoxTallness);
                    // Tallness of the text box of a scale mark. The default is 0.5.

            emUInt64 GetKeyboardInterval() const;
            void SetKeyboardInterval(emUInt64 kbInterval);
                    // How much to add and sub to the value by '+' and '-' keys. The
                    // default is zero which means to choose a good interval
                    // automatically.

    protected:

            virtual void ValueChanged();
                    // Called when the value has changed.

            virtual void Input(emInputEvent & event, const emInputState & state,
                               double mx, double my);

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

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

            virtual bool CheckMouse(double mx, double my, emInt64 * pValue);

    private:

            enum DoScalarFieldFunc {
                    SCALAR_FIELD_FUNC_PAINT,
                    SCALAR_FIELD_FUNC_CHECK_MOUSE
            };
            void DoScalarField(
                    DoScalarFieldFunc func, const emPainter * painter,
                    emColor canvasColor,
                    double mx, double my, emInt64 * pValue, bool * pHit
            );

            void StepByKeyboard(int dir);

            bool Editable;
            emSignal ValueSignal;
            emInt64 MinValue,MaxValue;
            emInt64 Value;
            emArray<emUInt64> ScaleMarkIntervals;
            bool MarksNeverHidden;
            void(*TextOfValueFunc)(
                    char * buf, int bufSize, emInt64 value, emUInt64 markInterval,
                    void * context
            );
            void * TextOfValueFuncContext;
            double TextBoxTallness;
            emUInt64 KBInterval;
            bool Pressed;

            static const char * HowToScalarField;
            static const char * HowToReadOnly;
    };

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

    inline emInt64 emTkScalarField::GetMinValue() const
    {
            return MinValue;
    }

    inline emInt64 emTkScalarField::GetMaxValue() const
    {
            return MaxValue;
    }

    inline const emSignal & emTkScalarField::GetValueSignal() const
    {
            return ValueSignal;
    }

    inline emInt64 emTkScalarField::GetValue() const
    {
            return Value;
    }

    inline const emArray<emUInt64> & emTkScalarField::GetScaleMarkIntervals() const
    {
            return ScaleMarkIntervals;
    }

    inline bool emTkScalarField::IsNeverHidingMarks() const
    {
            return MarksNeverHidden;
    }

    inline double emTkScalarField::GetTextBoxTallness() const
    {
            return TextBoxTallness;
    }

    inline emUInt64 emTkScalarField::GetKeyboardInterval() const
    {
            return KBInterval;
    }

    //==============================================================================
    //=============================== emTkColorField ===============================
    //==============================================================================

    class emTkColorField : public emTkBorder {

    public:

            // Class for a data field panel showing a color which can optionally be
            // edited by the user.

            emTkColorField(
                    ParentArg parent, const emString & name,
                    const emString & caption=emString(),
                    const emString & description=emString(),
                    const emImage & icon=emImage(),
                    emColor color=0x000000ff, bool editable=false,
                    bool alphaEnabled=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.
                    //   color        - Initial color.
                    //   editable     - Whether the color can be edited by the user.
                    //   alphaEnabled - Whether the alpha channel of the color is
                    //                  relevant.

            virtual ~emTkColorField();
                    // Destructor.

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

            bool IsAlphaEnabled() const;
            void SetAlphaEnabled(bool alphaEnabled=true);
                    // Whether the alpha channel of the color is relevant.

            const emSignal & GetColorSignal() const;
                    // This signal is signaled after each change of the color.

            emColor GetColor() const;
            void SetColor(emColor value);
                    // Get/set the color.

    protected:

            virtual void ColorChanged();
                    // Called when the color has changed.

            virtual bool Cycle();

            virtual void AutoExpand();
            virtual void AutoShrink();
            virtual void LayoutChildren();

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

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

    private:

            void UpdateRGBAOutput();
            void UpdateHSVOutput(bool initial=false);
            void UpdateNameOutput();
            void UpdateExpAppearance();

            static void TextOfPercentValue(
                    char * buf, int bufSize, emInt64 value, emUInt64 markInterval,
                    void * context
            );
            static void TextOfHueValue(
                    char * buf, int bufSize, emInt64 value, emUInt64 markInterval,
                    void * context
            );

            struct Expansion {
                    emTkTiling * Tiling;
                    emTkScalarField * SfRed;
                    emTkScalarField * SfGreen;
                    emTkScalarField * SfBlue;
                    emTkScalarField * SfAlpha;
                    emTkScalarField * SfHue;
                    emTkScalarField * SfSat;
                    emTkScalarField * SfVal;
                    emTkTextField * TfName;
                    emInt64 RedOut,GreenOut,BlueOut,AlphaOut,HueOut,SatOut,ValOut;
                    emString NameOut;
            };

            emSignal ColorSignal;
            Expansion * Exp;
            emColor Color;
            bool Editable;
            bool AlphaEnabled;
            bool Pressed;

            static const char * HowToColorField;
            static const char * HowToReadOnly;
    };

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

    inline bool emTkColorField::IsAlphaEnabled() const
    {
            return AlphaEnabled;
    }

    inline const emSignal & emTkColorField::GetColorSignal() const
    {
            return ColorSignal;
    }

    inline emColor emTkColorField::GetColor() const
    {
            return Color;
    }

    //==============================================================================
    //================================ emTkSplitter ================================
    //==============================================================================

    class emTkSplitter : public emTkBorder {

    public:

            // Class for a splitter panel. Such a panel can get two child panels
            // which are laid out automatically, either horizontally or vertically,
            // filling the whole content area. Between the two child panels is a
            // grip which can be dragged by the user, for making one of the panels
            // larger while the other gets smaller.

            emTkSplitter(
                    ParentArg parent, const emString & name,
                    const emString & caption=emString(),
                    const emString & description=emString(),
                    const emImage & icon=emImage(),
                    bool vertical=false, double minPos=0.0, double maxPos=1.0,
                    double pos=0.5
            );
                    // 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.
                    //   vertical    - See SetVertical.
                    //   minPos      - See SetMinMaxPos.
                    //   maxPos      - See SetMinMaxPos.
                    //   pos         - See SetPos.

            virtual ~emTkSplitter();
                    // Destructor.

            bool IsVertical() const;
            void SetVertical(bool vertical=true);
                    // Whether the child panels are laid out left-right (false) or
                    // on top of each other (true).

            double GetMinPos() const;
            double GetMaxPos() const;
            double GetPos() const;
            void SetMinMaxPos(double minPos, double maxPos);
            void SetPos(double pos);
                    // Get/set minimum, maximum and current position of the grip.
                    // The position ranges from 0.0 to 1.0 (0.0 = first child panel
                    // collapsed, 1.0 = second child panel collapsed).

            const emSignal & GetPosSignal() const;
                    // This signal is signaled after each change of the grip
                    // position.

    protected:

            virtual void Input(emInputEvent & event, const emInputState & state,
                               double mx, double my);
            virtual emCursor GetCursor();
            virtual void PaintContent(
                    const emPainter & painter, double x, double y, double w,
                    double h, emColor canvasColor
            );
            virtual void LayoutChildren();

    private:

            void CalcGripRect(
                    double contentX, double contentY, double contentW,
                    double contentH, double * pX, double * pY, double * pW,
                    double * pH
            );

            bool Vertical;
            double MinPos;
            double MaxPos;
            double Pos;
            emSignal PosSignal;
            bool Pressed;
            double MousePosInGrip;
            bool MouseInGrip;
    };

    inline bool emTkSplitter::IsVertical() const
    {
            return Vertical;
    }

    inline double emTkSplitter::GetMinPos() const
    {
            return MinPos;
    }

    inline double emTkSplitter::GetMaxPos() const
    {
            return MaxPos;
    }

    inline double emTkSplitter::GetPos() const
    {
            return Pos;
    }

    inline const emSignal & emTkSplitter::GetPosSignal() const
    {
            return PosSignal;
    }

    //==============================================================================
    //================================= emTkDialog =================================
    //==============================================================================

    class emTkDialog : public emWindow {

    public:

            // Class for a dialog window. Such a dialog has a content area and a
            // button area. The content area is an emTkTiling which can be given
            // individual child panels. The button area can have buttons like "OK"
            // and "Cancel" for finishing the dialog.

            emTkDialog(
                    emContext & parentContext,
                    ViewFlags viewFlags=VF_POPUP_ZOOM|VF_ROOT_SAME_TALLNESS,
                    WindowFlags windowFlags=WF_MODAL,
                    const emString & wmResName="emTkDialog"
            );
                    // Like the constructor of emWindow, but see that the default
                    // argument values are different (it's a modal dialog with
                    // popup-zoom by default).

            virtual ~emTkDialog();
                    // Destructor.

            void SetRootTitle(const emString & title);
                    // Set the title for this dialog. More precise, set the title
                    // for the private root panel of this view. If you create some
                    // content panel with another title, and if it gets focus, that
                    // title is shown. The default title is an empty string.

            emTkTiling * GetContentTiling();
                    // This panel makes up the content area of the dialog, not
                    // including the buttons. For convenience, it is an emTkTiling
                    // with default properties, except that the inner border is set
                    // to emTkBorder::IBT_CUSTOM_RECT. You may change the properties
                    // as you wish, and you should give it one or more child panels
                    // as the content.

            void AddPositiveButton(
                    const emString & caption,
                    const emString & description=emString(),
                    const emImage & icon=emImage()
            );
            void AddNegativeButton(
                    const emString & caption,
                    const emString & description=emString(),
                    const emImage & icon=emImage()
            );
            void AddCustomButton(
                    const emString & caption,
                    const emString & description=emString(),
                    const emImage & icon=emImage()
            );
                    // Add a button to the button area. These buttons are finishing
                    // the dialog. For the meaning of "Positive", "Negative" and
                    // "Custom", please see GetResult().

            void AddOKButton();
            void AddCancelButton();
            void AddOKCancelButtons();
                    // AddOKButton() is like AddPositiveButton("OK").
                    // AddCancelButton() is like AddNegativeButton("Cancel").
                    // AddOKCancelButtons() is like AddOKButton() plus
                    // AddCancelButton().

            emTkButton * GetButton(int index);
                    // Get a button. The index is: 0 for the first added button, 1
                    // for the second added button, and so on.

            const emSignal & GetFinishSignal() const;
                    // Signaled when any of the buttons has been triggered, or by
                    // pressing the Enter key or the Escape key, or by the window
                    // close signal. It is okay not to destruct the dialog and to
                    // wait for another finish signal.

            enum {
                    // Possible results:
                    POSITIVE=1, // Positive button triggered or Enter key pressed.
                    NEGATIVE=0, // Negative button triggered or Escape key pressed
                                // or window-closing commanded (see GetCloseSignal).
                    CUSTOM1 =2, // First custom button triggered.
                    CUSTOM2 =3, // Second custom button triggered.
                    CUSTOM3 =4  // ...
                    // Continued (customIndex=result+1-CUSTOM1)
            };
            int GetResult() const;
                    // The result should be asked after the finish signal has been
                    // signaled. Before that, the result is not valid.

            void Finish(int result);
                    // Finish this dialog with the given result programmatically.

            void EnableAutoDeletion(bool autoDelete=true);
            bool IsAutoDeletionEnabled();
                    // Whether to delete this object automatically a few time slices
                    // after the dialog has finished.

            static void ShowMessage(
                    emContext & parentContext,
                    const emString & title,
                    const emString & message,
                    const emString & description=emString(),
                    const emImage & icon=emImage()
            );
                    // This function creates a modal dialog with an emTkLabel as the
                    // content, and with an OK button. The dialog deletes itself
                    // when finished. The argument 'message' is the caption of the
                    // label.

    protected:

            virtual void Finished(int result);
                    // Like the finish signal. Default implementation does nothing.
                    // It's allowed to delete (destruct) this dialog herein.

    private:

            bool PrivateCycle();

            class DlgButton : public emTkButton {
            public:
                    DlgButton(
                            ParentArg parent, const emString & name,
                            const emString & caption,
                            const emString & description,
                            const emImage & icon,
                            int result
                    );
            protected:
                    virtual void Clicked();
            private:
                    int Result;
            };

            class DlgPanel : public emTkBorder {
            public:
                    DlgPanel(ParentArg parent, const emString & name);
                    virtual ~DlgPanel();
                    void SetTitle(emString title);
                    virtual emString GetTitle();
                    emString Title;
                    emTkTiling * ContentTiling;
                    emTkTiling * ButtonTiling;
            protected:
                    virtual void Input(
                            emInputEvent & event, const emInputState & state,
                            double mx, double my
                    );
                    virtual void LayoutChildren();
            };

            class PrivateEngineClass : public emEngine {
            public:
                    PrivateEngineClass(emTkDialog & dlg);
            protected:
                    virtual bool Cycle();
                    emTkDialog & Dlg;
            };
            friend class PrivateEngineClass;

            PrivateEngineClass PrivateEngine;
            emSignal FinishSignal;
            int Result;
            int ButtonNum,CustomRes;
            int FinishState;
            bool ADEnabled;
    };

    inline emTkTiling * emTkDialog::GetContentTiling()
    {
            return ((DlgPanel*)GetRootPanel())->ContentTiling;
    }

    inline const emSignal & emTkDialog::GetFinishSignal() const
    {
            return FinishSignal;
    }

    inline int emTkDialog::GetResult() const
    {
            return Result;
    }

    inline bool emTkDialog::IsAutoDeletionEnabled()
    {
            return ADEnabled;
    }

    #endif