/////////////////////////////////////////////////////////////////////////////
// Name:        No names yet.
// Purpose:     Contrib. demo
// Author:      Aleksandras Gluchovas
// Modified by:
// Created:     2000/02/08
// RCS-ID:      $Id: menuedit.h,v 1.3 2001/04/04 12:42:37 aleksandras Exp $
// Copyright:   (c) Aleksandras Gluchovas
// Licence:   	GPL (version 2.0 or later)
/////////////////////////////////////////////////////////////////////////////

#ifndef __MENUEDIT_G__
#define __MENUEDIT_G__

#include "dmcmn.h"
#include "wx/pmf/pm.h"
#include "txtrecset.h"
#include "strlist.h"

#include "wx/dynarray.h"
#include "wx/hash.h"

#include "XObject.h"

// imported

class wxDMNodePropertyPanel;

// class hierarcy

class wxObject;

	class wxME_VisItemData;	
	class wxME_NodeRenderer;

class wxDMCompositeNode;

	class wxME_Node;

class XObject;

	class wxME_VisItemContainer;

		class wxME_VertMenu;
		class wxME_HorizMenu;

class MenuEditorView;

class wxDMStructure;

	class wxME_Node; // holds non-visual (essential) data of menu-item
					 // and it's subitems, if any

// flags and constants

enum wxME_Node_FLAGS
{
	wxME_SEPARATOR = 0x01,
	wxME_DISABLED  = 0x02,
	wxME_CHECKED   = 0x04,
	wxME_BOLD      = 0x08,
	wxME_CHECKABLE = 0x10
};

enum wxME_VISUAL_ITEM_FLAGS
{
	wxME_VIS_SELECTED = 0x01,
	wxME_VIS_EDITED   = 0x02,
	wxME_VIS_TARGETED = 0x04,
	wxME_VIS_BLANK    = 0x08,
	wxME_VIS_OPENED   = 0x10
};

enum wxME_Node_COLUMNS
{
	wxME_CHECK_COLUMN = 0,
	wxME_IMAGE_COLUMN,
	wxME_NAME_COLUMN,
	wxME_HOTKEY_COLUMN,
	wxME_LAST_COLUMN,
};

class wxME_Node : public wxDMCompositeNode
{
public:
	wxME_Node( const wxString& title = "", 
			   const wxString& hotKey = "", 
			   int   flags = 0 );

	// overriden methods of wxDMNode

	virtual size_t GetGroupCount();
	virtual wxDMAttrGroupInfo* GetAttrGroupInfo( size_t index );
	virtual void* GetAttrGroupData( size_t index );
	virtual void* GetAttrGroupData( wxDMAttrGroupInfo* pForGroup );
	virtual wxString GetDisplayName();

	virtual wxDMNode* Clone( bool uniqueCopy, bool cloneChildren = FALSE );
	virtual void AssignData( wxDMNode* pCopy, bool uniqueCopy, bool cloneChildren );

	DECLARE_DYNAMIC_CLASS( wxME_Node )

public:
	wxString mName;
	wxString mTitle;
	wxString mHotKey;
	wxString mHelp;
	wxString mImageName;
	wxString mPlatform;
	int      mMenuFlags;

	MenuEditorView* mpView; // back-reference

	static wxDMAttrGroupInfo* mpsMENodeAttribGroup;
};

WX_DEFINE_ARRAY( wxME_Node*, ME_ItemListT );

// base class for menu renderers to a specifc look-&-feel standard,
// by default this base class renders MS-Windows look

class wxME_NodeRenderer : public wxObject
{
public:
	wxME_NodeRenderer( wxWindow* pWnd );
	~wxME_NodeRenderer();

	virtual wxSize GetItemColumnSize( wxME_Node& item, int columnNo );
	virtual wxSize GetBarPadding( bool isVertical );
	virtual wxSize GetItemPadding( wxME_Node& item, int visFlags, bool isVertical );
	virtual int GetInterColumnGap( bool isVertical );
	virtual int GetInterItemGap( bool isVertical );
	virtual void DrawBarBorder( wxDC& dc, const wxRect& bounds, bool isVertical );
	virtual void DrawItemColum( wxDC& dc, wxME_Node& item, 
								  const wxRect& bounds, int columnNo, 
								  int visFlags, bool isVertical );
	virtual void DrawItemContent( wxDC& dc, wxME_Node& item, 
								  const wxRect& bounds, int visFlags, bool isVertical );
	virtual void PostDrawContent( wxDC& dc, wxME_Node& item, 
								  const wxRect& bounds, int visFlags );

	virtual void SetDc( wxDC* pDc );

protected:
	// protected helpers

	virtual wxString StripControlChars( const wxString& txt );
	virtual wxFont& GetItemFont( wxME_Node& item );
	virtual int GetSeparatorHeight();
	virtual wxRect ExcludePadding( const wxRect& fromRect, const wxSize& pad );
	virtual bool GetNextSubstring( const wxString& text, wxString& subStr, 
								   size_t& i, bool& underline );

protected:
	wxFont  mNormalFont;
	wxFont  mBoldFont;
	wxFont  mNormalFontUL; // underlined
	wxFont  mBoldFontUL;
	wxBrush mBgBrush;
	wxDC*   mpDc;
};

class wxME_VisItemData : public wxObject
{
public:
	wxME_VisItemData();

	wxME_Node* mpItem;

	int		   mVisFlags;
	int        mColX[5]; // NOTE:: size should be adjusted each time
						 //		   wxME_Node_COLUMNS enum changed
	wxRect     mBounds;
};

WX_DEFINE_ARRAY( wxME_VisItemData*, MEVisItemDataListT );

class wxME_VisItemContainer : public XObject
{
public:
	wxME_VisItemContainer();
	~wxME_VisItemContainer();

	virtual bool OnMouseDown( const XPoint& pos );
	virtual bool OnMouseUp  ( const XPoint& pos );
	virtual bool OnMouseMove( const XPoint& pos );
	virtual bool OnKeyDown  ( const wxKeyEvent& keyInfo );
	virtual bool OnDblClick  ( const XPoint& pos );
	virtual bool OnRightClick( const XPoint& pos );

	virtual void SetRenderer( wxME_NodeRenderer* pRenderer );
	virtual void SetView( MenuEditorView* pView );
	virtual void SetHighlight( wxME_VisItemData* pData );

	virtual void AddVisItem( wxME_VisItemData* pData );
	virtual void Draw( wxDC& dc );
	virtual wxME_VisItemData* HitTestItem( const XPoint& pos );
	virtual void Layout( wxDC& dc );

	virtual XRect GetBounds();
	virtual void SetBounds( const XRect& bounds );

	// overridables
	virtual void LayoutVisItems( wxDC& dc );
	virtual bool IsVertical();


	MEVisItemDataListT mVisItems;

protected:
	wxME_NodeRenderer* mpRenderer;
	MenuEditorView*    mpView;
	wxRect			   mBounds;
	wxME_VisItemData*  mpHiglightedItem;

};
							 
class wxME_VertMenu : public wxME_VisItemContainer
{
public:
	wxME_VertMenu();

	virtual void LayoutVisItems( wxDC& dc );
	virtual bool IsVertical();
};

class wxME_HorizMenu : public wxME_VisItemContainer
{
public:
	wxME_HorizMenu();

	virtual void LayoutVisItems( wxDC& dc );
	virtual bool IsVertical();
};

/*** Dov/View classes ***/

class MenuEditorDoc : public wxPMDocument
{
public:
	MenuEditorDoc();
	~MenuEditorDoc();

	// overriden methods of wxPMDocument
	virtual bool CanHaveFile();
	virtual bool SavePMDocument();
	virtual bool LoadPMDocument();

	virtual bool IsModified() const;
	virtual void Modify(bool modify);

	void SetRootNode( wxME_Node* pRoot );
	wxME_Node* GetRootNode();

	DECLARE_DYNAMIC_CLASS( MenuEditorDoc )

protected:
	bool LoadNodesRecursively( Record& rec, wxME_Node* pParent );

	bool StoreNodesRecursively( Record& rec, wxME_Node* pNode );

protected:
	wxDMCommandProcessor*   mpDMCmdProcessor;
	wxME_Node*				mpRootNode;
	Record*					mpRecord;
};

class MenuEditorView : public wxPMView, public wxDMListener
{
public:
	MenuEditorView();
	~MenuEditorView();

	// overriden methods of wxView
	virtual void OnUpdate(wxView* sender, wxObject* hint);
    virtual void OnActivateView(bool activate, wxView *activeView, wxView *deactiveView);

	// overriden method wxView and wxPMView
	virtual bool OnCreate(wxDocument* doc, long flags);

	// overriden method of wxPMService
	virtual wxPMMergableMenuChain* GetMergableMenuChain();

	// overriden notifications of wxDMListener

	virtual void OnNodeRemoved( wxDMNode& node );
	virtual void OnNodeAdded( wxDMNode& node );
	virtual void OnNodeChanged( wxDMNode& node );
	virtual void OnNodeOrderChanged( wxDMNode& node );
	virtual void OnNodeReplaced( wxDMNode& node, wxDMNode& withNode );
	
	virtual void OnFocusChanged( wxDMNode& node );
	virtual void OnFocusRemoved();

	virtual void OnSelectionSet( DMNodeListT& nodes );
	virtual void OnNodeAddedToSelection( wxDMNode& node );
	virtual void OnNodeDeselected( wxDMNode& node );

	virtual void OnUpdateFinished();

	void SetRootNode( wxME_Node* pRoot );
	wxME_Node* GetRootNode();

	/*** event handlers ***/

	enum EDITOR_VIEW_COMMAND_IDS
	{
		ID_INSERT = 200,
		ID_INSERT_SUBITEM,
		ID_INSERT_AFTER,
		ID_INSERT_SEPARATOR,
		ID_PREPEND,
		ID_APPEND,
		ID_MOVE_UP,
		ID_MOVE_DOWN,
		ID_MOVE_TOP,
		ID_MOVE_BOTTOM,
		ID_UNDO,
		ID_REDO,
		ID_COPY,
		ID_PASTE,
		ID_CUT,
		ID_REMOVE,
		ID_POPUP_VIEW,
		ID_BAR_VIEW
	};

	void OnInsert( wxCommandEvent& event );
	void OnInsertSubItem( wxCommandEvent& event );
	void OnInsertAfter( wxCommandEvent& event );
	void OnInsertSeparator( wxCommandEvent& event );
	void OnPrepend( wxCommandEvent& event );
	void OnAppend( wxCommandEvent& event );
	void OnMoveUp( wxCommandEvent& event );
	void OnMoveDown( wxCommandEvent& event );
	void OnMoveTop( wxCommandEvent& event );
	void OnMoveBottom( wxCommandEvent& event );
	
	void OnUndo( wxCommandEvent& event );
	void OnRedo( wxCommandEvent& event );
	void OnUndoUI( wxUpdateUIEvent& event );
	void OnRedoUI( wxUpdateUIEvent& event );

	void OnCopy( wxCommandEvent& event );
	void OnPaste( wxCommandEvent& event );
	void OnCut( wxCommandEvent& event );
	void OnRemove( wxCommandEvent& event );

	void OnPopupView( wxCommandEvent& event );
	void OnBarView( wxCommandEvent& event );

	DECLARE_EVENT_TABLE()
	DECLARE_DYNAMIC_CLASS( MenuEditorView )

public:
	virtual void RecreateVisualItems();
	virtual void SetPopupView( bool on );
	virtual bool IsPopupView()
		;
	virtual void SetEditedNodeName( const wxString& name );
	virtual const wxString& GetEditedNodeName();

	StrListT& GetOpenedItems();

	virtual void CreateSampleMenuTree();
	virtual void AddSimpleItemsRecursively( wxME_Node* pParent, int depth );

	virtual void OpenItem( wxME_Node* pItem, wxME_VisItemContainer* pCont );
	virtual void SetRenderer( wxME_NodeRenderer* pRenderer );
	virtual wxME_NodeRenderer* GetRenderer();

	virtual wxString GenerateNewId();
	virtual wxME_Node* CreateNewNode();

	virtual void RehashItemIds();
	virtual void RehashItemIdsRecursive( wxME_Node* pNode );

	virtual void OpenNode( wxME_Node* pNode );

protected:
	StrListT mOpenedNodeNames; // contains names of opened items
	wxString mEditedNodeName;

	bool		 mIsPopupView;

	wxME_NodeRenderer* mpRenderer;
	XCollection* mpScene;

	wxDMNodePropertyPanel* mpPropPane;

	wxHashTable mIdsHash;
	int			mIdCounter;
};


class wxME_AttrInfo : public wxDMAttrInfo
{
public:
	wxME_AttrInfo( int attrId, const wxString& name, const wxString& displayName );

	// overriden methods of wxDMAttrInfo

	virtual wxString GetStringValue( void* pGroupData );
	virtual void SetStringValue( const wxString& value, void* pGroupData );
	virtual bool ValidateStringValue( const wxString& value, const wxString* pErrMsg = NULL );

	virtual bool HasRestrictedValues( void* pGroupData );
	virtual bool SetRestrictedValues( wxStringList& list );
	virtual void GetRestrictedValues( wxStringList& toLst, void* pGroupData );

	virtual bool HasMultipleValues( void* pGroupData );

	virtual bool ShownAsBooleanField();

	virtual void CopyValue( void* pDestData, void* pSrcData );

	enum ATTRIBUTE_IDS
	{
		ATTR_NAME = 0,
		ATTR_TITLE,
		ATTR_HOTKEY,
		ATTR_HELP,
		ATTR_PLATFORM,
		ATTR_IS_SEPARATOR,
		ATTR_IS_DISABLED,
		ATTR_IS_CHECKABLE,
		ATTR_IS_CHECKED,
		ATTR_IS_BOLD,
	};

protected:
	wxString FlagToStr( wxME_Node& node, int flag );
	void StrToFlag( wxME_Node& node, int flag, const wxString& boolStr );

protected:
	int mId;
};

#endif // __MENUEDIT_G__
