/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



#ifndef SC_GRIDWIN_HXX
#define SC_GRIDWIN_HXX

#include <tools/string.hxx>
#include <svtools/transfer.hxx>
#include "viewutil.hxx"
#include "viewdata.hxx"
#include "cbutton.hxx"
#include <svx/sdr/overlay/overlayobject.hxx>
#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
#include <basegfx/matrix/b2dhommatrix.hxx>

#include <vector>
#include <memory>
#include <boost/shared_ptr.hpp>

// ---------------------------------------------------------------------------

struct ScTableInfo;
class ScViewSelectionEngine;
class ScDPObject;
class ScDPFieldPopupWindow;
class ScDPFieldButton;
class ScOutputData;
class ScFilterListBox;
class AutoFilterPopup;
class SdrObject;
class SdrEditView;
class ScNoteMarker;
class FloatingWindow;
class SdrHdlList;
class ScTransferObj;
struct SpellCallbackInfo;

		//	Maus-Status (nMouseStatus)

#define SC_GM_NONE			0
#define SC_GM_TABDOWN		1
#define SC_GM_DBLDOWN		2
#define SC_GM_FILTER		3
#define SC_GM_IGNORE		4
#define SC_GM_WATERUNDO		5
#define SC_GM_URLDOWN		6

		//	Page-Drag-Modus

#define SC_PD_NONE			0
#define SC_PD_RANGE_L		1
#define SC_PD_RANGE_R		2
#define SC_PD_RANGE_T		4
#define SC_PD_RANGE_B		8
#define SC_PD_RANGE_TL		(SC_PD_RANGE_T|SC_PD_RANGE_L)
#define SC_PD_RANGE_TR		(SC_PD_RANGE_T|SC_PD_RANGE_R)
#define SC_PD_RANGE_BL		(SC_PD_RANGE_B|SC_PD_RANGE_L)
#define SC_PD_RANGE_BR		(SC_PD_RANGE_B|SC_PD_RANGE_R)
#define SC_PD_BREAK_H		16
#define SC_PD_BREAK_V		32


class ScHideTextCursor
{
private:
	ScViewData*	pViewData;
	ScSplitPos	eWhich;

public:
			ScHideTextCursor( ScViewData* pData, ScSplitPos eW );
			~ScHideTextCursor();
};

// ---------------------------------------------------------------------------
// predefines
namespace sdr { namespace overlay { class OverlayObjectList; }}

class ScGridWindow : public Window, public DropTargetHelper, public DragSourceHelper
{
	//	ScFilterListBox wird immer fuer Auswahlliste benutzt
	friend class ScFilterListBox;

private:
	// #114409#
	::sdr::overlay::OverlayObjectList*				mpOOCursors;
    ::sdr::overlay::OverlayObjectList*              mpOOSelection;
    ::sdr::overlay::OverlayObjectList*              mpOOAutoFill;
    ::sdr::overlay::OverlayObjectList*              mpOODragRect;
    ::sdr::overlay::OverlayObjectList*              mpOOHeader;
    ::sdr::overlay::OverlayObjectList*              mpOOShrink;

    ::boost::shared_ptr<Rectangle> mpAutoFillRect;

    /** 
     * Stores current visible column and row ranges, used to avoid expensive 
     * operations on objects that are outside visible area. 
     */
    struct VisibleRange
    {
        SCCOL mnCol1;
        SCCOL mnCol2;
        SCROW mnRow1;
        SCROW mnRow2;

        VisibleRange();

        bool isInside(SCCOL nCol, SCROW nRow) const;
    };
    VisibleRange maVisibleRange;

private:
	ScViewData*				pViewData;
	ScSplitPos				eWhich;
	ScHSplitPos				eHWhich;
	ScVSplitPos				eVWhich;

	ScNoteMarker*			pNoteMarker;

	ScFilterListBox*		pFilterBox;
	FloatingWindow*			pFilterFloat;
    ::std::auto_ptr<ScDPFieldPopupWindow> mpDPFieldPopup;
    ::std::auto_ptr<ScDPFieldButton>      mpFilterButton;

	sal_uInt16					nCursorHideCount;

	sal_Bool					bMarking;

	sal_uInt16					nButtonDown;
	sal_Bool					bEEMouse;				// Edit-Engine hat Maus
	sal_uInt8					nMouseStatus;
    sal_uInt8                    nNestedButtonState;     // track nested button up/down calls

	sal_Bool					bDPMouse;				// DataPilot-D&D (neue Pivottabellen)
	long					nDPField;
	ScDPObject*				pDragDPObj;	//! name?

	sal_Bool					bRFMouse;				// RangeFinder-Drag
	sal_Bool					bRFSize;
	sal_uInt16					nRFIndex;
	SCsCOL					nRFAddX;
	SCsROW					nRFAddY;

	sal_uInt16					nPagebreakMouse;		// Pagebreak-Modus Drag
	SCCOLROW				nPagebreakBreak;
	SCCOLROW				nPagebreakPrev;
	ScRange					aPagebreakSource;
	ScRange					aPagebreakDrag;
	sal_Bool					bPagebreakDrawn;

	sal_uInt8					nPageScript;

	long					nLastClickX;
	long					nLastClickY;

	sal_Bool					bDragRect;
	SCCOL					nDragStartX;
	SCROW					nDragStartY;
	SCCOL					nDragEndX;
	SCROW					nDragEndY;
    InsCellCmd              meDragInsertMode;

	sal_uInt16					nCurrentPointer;

	sal_Bool					bIsInScroll;
	sal_Bool					bIsInPaint;

	ScDDComboBoxButton		aComboButton;

	Point					aCurMousePos;

	sal_uInt16					nPaintCount;
	Rectangle				aRepaintPixel;
	sal_Bool					bNeedsRepaint;

	sal_Bool					bAutoMarkVisible;
	ScAddress				aAutoMarkPos;

	sal_Bool					bListValButton;
	ScAddress				aListValPos;

	Rectangle				aInvertRect;

	DECL_LINK( PopupModeEndHdl, FloatingWindow* );
    DECL_LINK( PopupSpellingHdl, SpellCallbackInfo* );

	sal_Bool			TestMouse( const MouseEvent& rMEvt, sal_Bool bAction );

	sal_Bool			DoPageFieldSelection( SCCOL nCol, SCROW nRow );
    bool            DoAutoFilterButton( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt );
	void			DoPushButton( SCCOL nCol, SCROW nRow, const MouseEvent& rMEvt );

	void			DPMouseMove( const MouseEvent& rMEvt );
	void			DPMouseButtonUp( const MouseEvent& rMEvt );
	void			DPTestMouse( const MouseEvent& rMEvt, sal_Bool bMove );

    /** 
     * Check if the mouse click is on a field popup button. 
     *  
     * @return bool true if the field popup menu has been launched and no 
     *         further mouse event handling is necessary, false otherwise.
     */
    bool            DPTestFieldPopupArrow(const MouseEvent& rMEvt, const ScAddress& rPos, ScDPObject* pDPObj);
    void            DPLaunchFieldPopupMenu(
        const Point& rScrPos, const Size& rScrSize, const ScAddress& rPos, ScDPObject* pDPObj);

	void			RFMouseMove( const MouseEvent& rMEvt, sal_Bool bUp );

	void			PagebreakMove( const MouseEvent& rMEvt, sal_Bool bUp );

	void			UpdateDragRect( sal_Bool bShowRange, const Rectangle& rPosRect );

	sal_Bool 			IsAutoFilterActive( SCCOL nCol, SCROW nRow, SCTAB nTab );
	void			ExecFilter( sal_uLong nSel, SCCOL nCol, SCROW nRow,
                                const String& aValue, bool bCheckForDates );
	void			FilterSelect( sal_uLong nSel );

	void			ExecDataSelect( SCCOL nCol, SCROW nRow, const String& rStr );

	void			ExecPageFieldSelect( SCCOL nCol, SCROW nRow, sal_Bool bHasSelection, const String& rStr );

	sal_Bool			HasScenarioButton( const Point& rPosPixel, ScRange& rScenRange );
	sal_Bool			HasScenarioRange( sal_uInt16 nCol, sal_Int32 nRow, ScRange& rScenRange ); 
	sal_Bool			DropScroll( const Point& rMousePos );

	sal_Int8		AcceptPrivateDrop( const AcceptDropEvent& rEvt );
	sal_Int8		ExecutePrivateDrop( const ExecuteDropEvent& rEvt );
	sal_Int8		DropTransferObj( ScTransferObj* pTransObj, SCCOL nDestPosX, SCROW nDestPosY,
									const Point& rLogicPos, sal_Int8 nDndAction );

    void            HandleMouseButtonDown( const MouseEvent& rMEvt );

	sal_Bool			DrawMouseButtonDown(const MouseEvent& rMEvt);
	sal_Bool			DrawMouseButtonUp(const MouseEvent& rMEvt);
	sal_Bool			DrawMouseMove(const MouseEvent& rMEvt);
	sal_Bool			DrawKeyInput(const KeyEvent& rKEvt);
	sal_Bool			DrawCommand(const CommandEvent& rCEvt);
	sal_Bool			DrawHasMarkedObj();
	void			DrawEndAction();
	void			DrawMarkDropObj( SdrObject* pObj );
	SdrObject*		GetEditObject();
	sal_Bool			IsMyModel(SdrEditView* pSdrView);
	//void			DrawStartTimer();

	void			DrawRedraw( ScOutputData& rOutputData, ScUpdateMode eMode, sal_uLong nLayer );
    void            DrawSdrGrid( const Rectangle& rDrawingRect, OutputDevice* pContentDev );
	//sal_Bool			DrawBeforeScroll();
	void			DrawAfterScroll(/*sal_Bool bVal*/);
	//void			DrawMarks();
	//sal_Bool			NeedDrawMarks();
	void 			DrawComboButton( const Point&	rCellPos,
									 long			nCellSizeX,
									 long			nCellSizeY,
                                     sal_Bool           bArrowState,
									 sal_Bool			bBtnIn  = sal_False );
	Rectangle		GetListValButtonRect( const ScAddress& rButtonPos );

    void            DrawPagePreview( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2, OutputDevice* pContentDev );

	sal_Bool			GetEditUrl( const Point& rPos,
								String* pName=0, String* pUrl=0, String* pTarget=0 );
	sal_Bool			GetEditUrlOrError( sal_Bool bSpellErr, const Point& rPos,
								String* pName=0, String* pUrl=0, String* pTarget=0 );

	sal_Bool			HitRangeFinder( const Point& rMouse, sal_Bool& rCorner, sal_uInt16* pIndex = NULL,
										SCsCOL* pAddX = NULL, SCsROW* pAddY = NULL );

	sal_uInt16			HitPageBreak( const Point& rMouse, ScRange* pSource = NULL,
									SCCOLROW* pBreak = NULL, SCCOLROW* pPrev = NULL );

	void			PasteSelection( const Point& rPosPixel );

    void			SelectForContextMenu( const Point& rPosPixel, SCsCOL nCellX, SCsROW nCellY );

    void            GetSelectionRects( ::std::vector< Rectangle >& rPixelRects );

protected:
    using Window::Resize;
	virtual void 	Resize( const Size& rSize );
	virtual void 	PrePaint();
	virtual void 	Paint( const Rectangle& rRect );
	virtual void	KeyInput(const KeyEvent& rKEvt);
	virtual void	GetFocus();
	virtual void	LoseFocus();

	virtual void	RequestHelp( const HelpEvent& rEvt );
	virtual void	Command( const CommandEvent& rCEvt );

	virtual sal_Int8 AcceptDrop( const AcceptDropEvent& rEvt );
	virtual sal_Int8 ExecuteDrop( const ExecuteDropEvent& rEvt );
	virtual void	StartDrag( sal_Int8 nAction, const Point& rPosPixel );

public:
	ScGridWindow( Window* pParent, ScViewData* pData, ScSplitPos eWhichPos );
	~ScGridWindow();

	// #i70788# flush and get overlay
	::sdr::overlay::OverlayManager* getOverlayManager();
	void flushOverlayManager();

	virtual void	DataChanged( const DataChangedEvent& rDCEvt );

	virtual void 	MouseButtonDown( const MouseEvent& rMEvt );
	virtual void	MouseButtonUp( const MouseEvent& rMEvt );
	virtual void	MouseMove( const MouseEvent& rMEvt );
    virtual long    PreNotify( NotifyEvent& rNEvt );
    virtual void	Tracking( const TrackingEvent& rTEvt );

	virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible();

	void			FakeButtonUp();

	Point			GetMousePosPixel() const;
	void			UpdateStatusPosSize();

	void			ClickExtern();

	void			SetPointer( const Pointer& rPointer );

	void			MoveMouseStatus( ScGridWindow &rDestWin );

	void			ScrollPixel( long nDifX, long nDifY );
	void			UpdateEditViewPos();

	void			UpdateFormulas();

	void			DoAutoFilterMenue( SCCOL nCol, SCROW nRow, sal_Bool bDataSelect );
	void			DoScenarioMenue( const ScRange& rScenRange );

    void            LaunchPageFieldMenu( SCCOL nCol, SCROW nRow );
    void            LaunchDPFieldMenu( SCCOL nCol, SCROW nRow );

    ::com::sun::star::sheet::DataPilotFieldOrientation GetDPFieldOrientation( SCCOL nCol, SCROW nRow ) const;

	void			DrawButtons( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
                                    ScTableInfo& rTabInfo, OutputDevice* pContentDev );

    using Window::Draw;
	void			Draw( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
						ScUpdateMode eMode = SC_UPDATE_ALL );

	void			InvertSimple( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
									sal_Bool bTestMerge = sal_False, sal_Bool bRepeat = sal_False );

//UNUSED2008-05  void			DrawDragRect( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2 );

	void			CreateAnchorHandle(SdrHdlList& rHdl, const ScAddress& rAddress);

	void			HideCursor();
	void			ShowCursor();
	void 			DrawCursor();
	void			DrawAutoFillMark();
	void			UpdateAutoFillMark(sal_Bool bMarked, const ScRange& rMarkRange);

	void			UpdateListValPos( sal_Bool bVisible, const ScAddress& rPos );

	sal_Bool			ShowNoteMarker( SCsCOL nPosX, SCsROW nPosY, sal_Bool bKeyboard );
	void			HideNoteMarker();

	MapMode			GetDrawMapMode( sal_Bool bForce = sal_False );

	void			ContinueDrag();

	void			StopMarking();
	void			UpdateInputContext();

	void			CheckInverted()		{ if (nPaintCount) bNeedsRepaint = sal_True; }

	void			DoInvertRect( const Rectangle& rPixel );

	void			CheckNeedsRepaint();
	virtual void SwitchView();

    void            UpdateDPFromFieldPopupMenu();

    void            UpdateVisibleRange();

	// #114409#
	void CursorChanged();
	void DrawLayerCreated();

    void            DeleteCursorOverlay();
    void            UpdateCursorOverlay();
    void            DeleteSelectionOverlay();
    void            UpdateSelectionOverlay();
    void            DeleteAutoFillOverlay();
    void            UpdateAutoFillOverlay();
    void            DeleteDragRectOverlay();
    void            UpdateDragRectOverlay();
    void            DeleteHeaderOverlay();
    void            UpdateHeaderOverlay();
    void            DeleteShrinkOverlay();
    void            UpdateShrinkOverlay();
    void            UpdateAllOverlays();

protected:
	// #114409#
	void ImpCreateOverlayObjects();
	void ImpDestroyOverlayObjects();

};



#endif

