/*==LICENSE==*

CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011  Cyan Worlds, Inc.

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

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 for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

You can contact Cyan Worlds, Inc. by email legal@cyan.com
 or by snail mail at:
      Cyan Worlds, Inc.
      14617 N Newport Hwy
      Mead, WA   99021

*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
//                                                                          //
//  pfGUIListBoxMod Header                                                  //
//                                                                          //
//////////////////////////////////////////////////////////////////////////////

#ifndef _pfGUIListBoxMod_h
#define _pfGUIListBoxMod_h

#include "pfGUIControlMod.h"

class plMessage;
class hsGMaterial;
class plTextGenerator;
class pfGUIListElement;
class pfScrollProc;
class pfGUIValueCtrl;

class pfGUIListBoxMod : public pfGUIControlMod
{
    friend class pfScrollProc;

    protected:

        struct plSmallRect
        {
            Int16   fLeft, fTop, fRight, fBottom;

            void    Set( Int16 l, Int16 t, Int16 r, Int16 b );
            hsBool  Contains( Int16 x, Int16 y );

            plSmallRect& operator=(const int zero) { fLeft = fTop = fRight = fBottom = 0; return *this; }
        };

        pfGUIValueCtrl  *fScrollControl;

        pfScrollProc    *fScrollProc;

        hsTArray<pfGUIListElement *>    fElements;
        Int32                           fCurrClick, fScrollPos, fCurrHover;
        UInt8                           fModsAtDragTime;
        Int32                           fMinSel, fMaxSel;
        hsBool                          fCheckScroll, fClicking;
        Int32                           fSingleSelElement;
        hsBool                          fScrollRangeUpdateDeferred;
        hsBool                          fLocked, fReadyToRoll;
        hsTArray<plSmallRect>           fElementBounds;
        hsTArray<Int16>                 fWrapStartIdxs;


        virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()

        void    ICalcScrollRange( void );
        void    ICalcWrapStarts( void );

        virtual void    IUpdate( void );
        virtual void    IPostSetUpDynTextMap( void );
        virtual UInt32  IGetDesiredCursor( void ) const;

        Int32   IGetItemFromPoint( hsPoint3 &mousePt );
        void    IFindSelectionRange( Int32 *min, Int32 *max );
        void    ISelectRange( Int8 min, Int8 max, hsBool select );

    public:

        pfGUIListBoxMod();
        virtual ~pfGUIListBoxMod();

        CLASSNAME_REGISTER( pfGUIListBoxMod );
        GETINTERFACE_ANY( pfGUIListBoxMod, pfGUIControlMod );

        enum OurFlags
        {
            kSingleSelect = kDerivedFlagsStart,
            kDragAndDropCapable,
            kDisableSelection,
            kDisableKeyActions,
            kAllowMultipleElementsPerRow,
            kScrollLeftToRight,
            kAllowMousePassThrough,
            kGrowLeavesAndProcessOxygen,
            kHandsOffMultiSelect,       // Do multiselect w/o needing ctrl or shift
            kForbidNoSelection
        };

        // Extended event types
        enum ExtendedEvents
        {
            kScrollPosChanged,
            kItemAdded,
            kItemRemoved,
            kListCleared
        };

        enum
        {
            kRefScrollCtrl = kRefDerivedStart
        };

        virtual hsBool  MsgReceive( plMessage* pMsg );
        
        virtual void Read( hsStream* s, hsResMgr* mgr );
        virtual void Write( hsStream* s, hsResMgr* mgr );

        virtual void    HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers );
        virtual void    HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers );
        virtual void    HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers );
        virtual void    HandleMouseHover( hsPoint3 &mousePt, UInt8 modifiers );
        virtual void    HandleMouseDblClick( hsPoint3 &mousePt, UInt8 modifiers );

        virtual hsBool  HandleKeyPress( wchar_t key, UInt8 modifiers );
        virtual hsBool  HandleKeyEvent( pfGameGUIMgr::EventType event, plKeyDef key, UInt8 modifiers );

        virtual hsBool  FilterMousePosition( hsPoint3 &mousePt );

        virtual void PurgeDynaTextMapImage();

        // Returns selected element. Only valid for kSingleSelect list boxes
        Int32   GetSelection( void ) { return fSingleSelElement; }
        void    SetSelection( Int32 item );
        void    RemoveSelection( Int32 item );
        void    AddSelection( Int32 item );
        
        virtual void    ScrollToBegin( void );
        virtual void    ScrollToEnd( void );
        virtual void    SetScrollPos( Int32 pos );
        virtual Int32   GetScrollPos( void );
        virtual Int32   GetScrollRange( void );


        void    Refresh( void ) { IUpdate(); }

        virtual void        SetColorScheme( pfGUIColorScheme *newScheme );

        // Element manipulation

        UInt16  AddElement( pfGUIListElement *el );
        void    RemoveElement( UInt16 index );
        Int16   FindElement( pfGUIListElement *toCompareTo );
        void    ClearAllElements( void );

        void    LockList( void );
        void    UnlockList( void );

        UInt16              GetNumElements( void );
        pfGUIListElement    *GetElement( UInt16 idx );

        UInt16  AddString( const char *string );
        UInt16  AddString( const wchar_t *string );
        Int16   FindString( const char *toCompareTo );
        Int16   FindString( const wchar_t *toCompareTo );

        // Export only
        void    SetScrollCtrl( pfGUIValueCtrl *ctrl ) { fScrollControl = ctrl; }
        void    SetSingleSelect( hsBool yes ) { if( yes ) SetFlag( kSingleSelect ); else ClearFlag( kSingleSelect ); }
};

#endif // _pfGUIListBoxMod_h