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

#ifndef __BMPEDITOR_G__
#define __BMPEDITOR_G__

#include "wx/pmf/pm.h"
#include "XObject.h"

#include "wx/dynarray.h"
#include "res_templ.h"
#include "res_doc.h"

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

	BmpEditorActionData( int nCols, int nRows, char* newPixels,
						 int nOrigCols, int nOrigRows, char* origPixels );

	~BmpEditorActionData();

public:
	int* mXPositions;
	int* mYPositions;
	char* mSetPixels;
	char* mOrigPixels;
	int mPixelCount;

	// contain -1s if action is not "resize"
	wxSize mNewSize;
	wxSize mOrigSize;
};

WX_DEFINE_ARRAY( BmpEditorActionData*, BmpEditorActionListT );

class BmpEditorData : public wxDMNode
{
public:
	BmpEditorData();
	~BmpEditorData();

	virtual void InitColours();
	virtual void InitPixels( int nCols, int nRows, char col, int pixelSize = 10 );
	virtual void SetPixelColour( int x, int y, char colour );
	virtual void DrawLine( int x1, int y1, int x2, int y2, char colour );

	virtual void DoFloodFill( int xPos, int yPos, char colour );
	virtual void FloodFill( int xPos, int yPos, char fillColour );
	virtual void FillRectangle( int xPos, int yPos, int width, int height, char fillColour );
	virtual void DrawEllipse( int x1, int y1, int x2, int y2, char colour );

	virtual void AddAction( BmpEditorActionData* pAction );
	virtual void Undo();
	virtual void Redo();
	virtual bool CanUndo();
	virtual bool CanRedo();

protected:
	virtual void DoApplyAction( BmpEditorActionData* pAction, bool reverse = FALSE );

public:
	char*	  mPixels;
	wxColour* mColours;
	wxBrush*  mBrushes;
	int mColourCount;
	int mRows;
	int mCols;
	int mPixelSize;

	// NOTE:: undo/redo mechanizim of DM-fmw is not used here, instead we
	//		  have our own optimized alg. and datastructure embedded directly
	//		  into the bitmap-node

	BmpEditorActionListT mActions;
	int mCmdHeadIndex;
};

class BitmapEditorDoc : public ResItemDocumentBase
{
public:
	BitmapEditorDoc();
	~BitmapEditorDoc();

	// overriden method of wxDocument
	virtual bool OnNewDocument();

	virtual BmpEditorData* GetData();

	// overriden methods of ResItemDocumentBase

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

	WidgetResTemplate* GetTemplateForNode( wxDMNode& node );

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

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

	DECLARE_DYNAMIC_CLASS( BitmapEditorDoc )

protected:
	BmpEditorData* mpData;
};

class XBitmapSurface;

class BitmapEditorView : public wxPMView
{
public:
	BitmapEditorView();
	~BitmapEditorView();

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

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

	// overriden method of wxView
	virtual void OnUpdate(wxView* sender, wxObject* hint);

	/*** event handlers ***/

	enum COMMAND_IDS
	{
		ID_UNDO = 100,
		ID_REDO,
		ID_ZOOM_IN,
		ID_ZOOM_OUT,

		ID_SET_CURSOR_MODE,
		ID_SET_SELECT_MODE,
		ID_SET_SELECT_COLOUR_MODE,
		ID_SET_ERASE_MODE,
		ID_SET_FILL_MODE,
		ID_SET_PENCIL_MODE,
		ID_SET_LINE_MODE,
		ID_SET_RECT_MODE,
		ID_SET_SOLID_RECT_MODE,
		ID_SET_ELLIPSE_MODE,
		ID_SET_SOLID_ELLIPSE_MODE
	};

	enum EDITOR_MODES
	{
		CURSOR_MODE,
		SELECT_MODE,
		SELECT_COLOUR_MODE,
		ERASE_MODE,
		FILL_MODE,
		PENCIL_MODE,
		LINE_MODE,
		RECT_MODE,
		SOLID_RECT_MODE,
		ELLIPSE_MODE,
		SOLID_ELLIPSE_MODE
	};

	void OnUndo( wxCommandEvent& event );
	void OnRedo( wxCommandEvent& event );

	void OnSetCursorMode( wxCommandEvent& event );
	void OnSetSelectMode( wxCommandEvent& event );
	void OnSetSelectColourMode( wxCommandEvent& event );
	void OnSetEraseMode( wxCommandEvent& event );
	void OnSetFillMode( wxCommandEvent& event );
	void OnZoomIn( wxCommandEvent& event );
	void OnZoomOut( wxCommandEvent& event );
	void OnSetPencilMode( wxCommandEvent& event );
	void OnSetLineMode( wxCommandEvent& event );
	void OnSetRectMode( wxCommandEvent& event );
	void OnSetSolidRectMode( wxCommandEvent& event );
	void OnSetEllipseMode( wxCommandEvent& event );
	void OnSetSolidEllipseMode( wxCommandEvent& event );

	// other methods

	virtual BmpEditorData& GetData();

	virtual int GetMode();
	virtual int GetBgColour();
	virtual int GetFgColour();

	virtual void SetMode( int mode );
	virtual void SetBgColour( int colour );
	virtual void SetFgColour( int colour );

	virtual BitmapEditorDoc& GetEditorDoc();

	DECLARE_EVENT_TABLE()
	DECLARE_DYNAMIC_CLASS( BitmapEditorView )

protected:
	void DoSetMode( int mode );
	void RefreshSurface();
	void RecreateScene();

protected:
	BmpEditorData*  mpData;
	XCollection*    mpScene;
	XBitmapSurface* mpSurface;

	// editing state
	int			   mMode;
	int			   mBgColour; // index for mpData->mColours array
	int			   mFgColour;
};

class XBitmapSurface : public XObject
{
public:
	XBitmapSurface( BitmapEditorView* pView );
	~XBitmapSurface();

	// overriden methods XObject
	virtual bool OnMouseDown( const XPoint& pos );
	virtual bool OnMouseUp  ( const XPoint& pos );
	virtual bool OnMouseMove( const XPoint& pos );
	virtual bool OnRightClick( const XPoint& pos );

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

	virtual bool OnStartEdit();
	virtual bool OnFinishEdit();

	virtual void Draw( wxDC& canvas );

protected:
	virtual void GetPixelPos( const XPoint& canvasPos, int& x, int& y );
	virtual void DoUpdate();
	virtual bool DoMouseDown( const XPoint& pos );
	virtual void SaveCheckPoint();

protected:
	BmpEditorData* mpData;
	BitmapEditorView* mpView;

	wxBrush mBgBrush;
	XRect mBounds;

	bool   mRightPressed;
	bool   mDragStared;
	XPoint mDragOrigin;
	char*  mpOrigPixels;
	int	   mOrigCols;
	int	   mOrigRows;
	bool   mEraseStarted;
};

#endif // __BMPEDITOR_G__