    //------------------------------------------------------------------------------
    // emDialog.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 emDialog_h
    #define emDialog_h

    #ifndef emButton_h
    #include <emCore/emButton.h>
    #endif

    #ifndef emLinearLayout_h
    #include <emCore/emLinearLayout.h>
    #endif

    //==============================================================================
    //================================== emDialog ==================================
    //==============================================================================

    class emDialog : public emWindow {

    public:

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

            emDialog(
                    emContext & parentContext,
                    ViewFlags viewFlags=VF_POPUP_ZOOM|VF_ROOT_SAME_TALLNESS,
                    WindowFlags windowFlags=WF_MODAL,
                    const emString & wmResName="emDialog"
            );
                    // 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 ~emDialog();
                    // 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.

            emLinearLayout * GetContentPanel() const;
                    // This panel makes up the content area of the dialog, not
                    // including the buttons. For convenience, it is an emLinearLayout
                    // with default properties, except that the inner border is set
                    // to emBorder::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().

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

            emButton * GetButtonForResult(int result) const;
                    // Get the first button, whose result is the given result.

            emButton * GetOKButton() const;
                    // Get the first button with positive result.

            emButton * GetCancelButton() const;
                    // Get the first button with negative result.

            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.

            bool Finish(int result);
                    // Finish this dialog with the given result programmatically.
                    // Returns true on success, or false if the finishing was aborted
                    // by a call to CheckFinish(result).

            void EnableAutoDeletion(bool autoDelete=true);
            bool IsAutoDeletionEnabled() const;
                    // 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 emLabel 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 bool CheckFinish(int result);
                    // Check whether finishing is allowed with the given result at
                    // this moment. The default implementation always returns true.

            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 emButton {
            public:
                    DlgButton(
                            ParentArg parent, const emString & name,
                            const emString & caption,
                            const emString & description,
                            const emImage & icon,
                            int result
                    );
                    int GetResult() const;
            protected:
                    virtual void Clicked();
            private:
                    int Result;
            };

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

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

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

    inline emLinearLayout * emDialog::GetContentPanel() const
    {
            return ((DlgPanel*)GetRootPanel())->ContentPanel;
    }

    inline emButton * emDialog::GetOKButton() const
    {
            return GetButtonForResult(POSITIVE);
    }

    inline emButton * emDialog::GetCancelButton() const
    {
            return GetButtonForResult(NEGATIVE);
    }

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

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

    inline bool emDialog::IsAutoDeletionEnabled() const
    {
            return ADEnabled;
    }

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

    #endif