/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: starmath_edit.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2006/10/27 19:56:19 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#pragma hdrstop




#include "starmath.hrc"
#define ITEMID_FONT 		1
#define ITEMID_FONTHEIGHT	2
#define ITEMID_LRSPACE		3
#define ITEMID_WEIGHT		4


#ifndef _MyEDITVIEW_HXX //autogen
#include <bf_svx/editview.hxx>
#endif
#ifndef _MyEDITENG_HXX //autogen
#include <bf_svx/editeng.hxx>
#endif
#ifndef _SFXDISPATCH_HXX //autogen
#include <bf_sfx2/dispatch.hxx>
#endif
#ifndef _SFXSTRITEM_HXX //autogen
#include <svtools/stritem.hxx>
#endif


#include "view.hxx"
#include "document.hxx"
#include "config.hxx"
namespace binfilter {

#define SCROLL_LINE 		24

#define MINWIDTH		200
#define MINHEIGHT		200
#define MINSPLIT		40
#define SPLITTERWIDTH	2


using namespace ::com::sun::star::accessibility;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

////////////////////////////////////////


/*N*/ void SmGetLeftSelectionPart(const ESelection aSel,
/*N*/ 							USHORT &nPara, USHORT &nPos)
/*N*/ 	// returns paragraph number and position of the selections left part
/*N*/ {
/*N*/ 	// compare start and end of selection and use the one that comes first
/*N*/ 	if (	aSel.nStartPara <  aSel.nEndPara
/*N*/ 		||	aSel.nStartPara == aSel.nEndPara  &&  aSel.nStartPos < aSel.nEndPos)
/*?*/ 	{	nPara = aSel.nStartPara;
/*?*/ 		nPos  = aSel.nStartPos;
/*N*/ 	}
/*N*/ 	else
/*N*/ 	{	nPara = aSel.nEndPara;
/*N*/ 		nPos  = aSel.nEndPos;
/*N*/ 	}
/*N*/ }

////////////////////////////////////////

/*N*/ SmEditWindow::SmEditWindow( SmCmdBoxWindow &rMyCmdBoxWin ) :
/*N*/     Window              (&rMyCmdBoxWin),
/*N*/     DropTargetHelper    ( this ),
/*N*/     rCmdBox             (rMyCmdBoxWin),
/*N*/ 	pEditView			(0),
/*N*/ 	pHScrollBar			(0),
/*N*/ 	pVScrollBar			(0),
/*N*/ 	pScrollBox			(0)
/*N*/ {
/*N*/ 	SetHelpId(HID_SMA_COMMAND_WIN_EDIT);
/*N*/ 	SetMapMode(MAP_PIXEL);
/*N*/
/*N*/     ApplyColorConfigValues( SM_MOD1()->GetColorConfig() );
/*N*/
/*N*/     // compare DataChanged
/*N*/ 	SetBackground( GetSettings().GetStyleSettings().GetWindowColor() );
/*N*/
/*N*/ 	aModifyTimer.SetTimeoutHdl(LINK(this, SmEditWindow, ModifyTimerHdl));
/*N*/ 	aModifyTimer.SetTimeout(2000);
/*N*/ 	aModifyTimer.Start();
/*N*/
/*N*/ 	aCursorMoveTimer.SetTimeoutHdl(LINK(this, SmEditWindow, CursorMoveTimerHdl));
/*N*/ 	aCursorMoveTimer.SetTimeout(500);
/*N*/
/*N*/     Show();
/*N*/ }


/*N*/ SmEditWindow::~SmEditWindow()
/*N*/ {
/*N*/ 	aCursorMoveTimer.Stop();
/*N*/ 	aModifyTimer.Stop();
/*N*/
/*N*/     if (pEditView)
/*N*/     {
/*N*/         EditEngine *pEditEngine = pEditView->GetEditEngine();
/*N*/         if (pEditEngine)
/*N*/         {
/*N*/             pEditEngine->SetStatusEventHdl( Link() );
/*N*/             pEditEngine->RemoveView( pEditView );
/*N*/         }
/*N*/     }
/*N*/ 	delete pEditView;
/*N*/ 	delete pHScrollBar;
/*N*/ 	delete pVScrollBar;
/*N*/ 	delete pScrollBox;
/*N*/
/*N*/     // Note: memory for pAccessible will be freed when the reference
/*N*/     // xAccessible is released.
/*N*/ }




/*N*/ SmDocShell * SmEditWindow::GetDoc()
/*N*/ {
/*N*/     SmViewShell *pView = rCmdBox.GetView();
/*N*/     return pView ? pView->GetDoc() : 0;
/*N*/ }


/*N*/ EditEngine * SmEditWindow::GetEditEngine()
/*N*/ {
/*N*/     EditEngine *pEditEng = 0;
/*N*/     if (pEditView)
/*N*/         pEditEng = pEditView->GetEditEngine();
/*N*/     else
/*N*/     {
/*N*/         SmDocShell *pDoc = GetDoc();
/*N*/         if (pDoc)
/*N*/             pEditEng = &pDoc->GetEditEngine();
/*N*/     }
/*N*/     return pEditEng;
/*N*/ }



/*N*/ void SmEditWindow::ApplyColorConfigValues( const svtools::ColorConfig &rColorCfg )
/*N*/ {
/*N*/     // Note: SetBackground still done in SmEditWindow::DataChanged
/*N*/ #if OSL_DEBUG_LEVEL > 1
/*N*/ 	ColorData nVal = rColorCfg.GetColorValue(svtools::FONTCOLOR).nColor;
/*N*/ #endif
/*N*/     SetTextColor( rColorCfg.GetColorValue(svtools::FONTCOLOR).nColor );
/*N*/     Invalidate();
/*N*/ }


/*N*/ IMPL_LINK( SmEditWindow, ModifyTimerHdl, Timer *, pTimer )
/*N*/ {
/*N*/ 	SmModule *pp = SM_MOD1();
/*N*/ 	if (pp->GetConfig()->IsAutoRedraw())
/*N*/ 		Flush();
/*N*/ 	aModifyTimer.Start();
/*N*/ 	return 0;
/*N*/ }


/*N*/ IMPL_LINK(SmEditWindow, CursorMoveTimerHdl, Timer *, pTimer)
/*N*/ 	// every once in a while check cursor position (selection) of edit
/*N*/ 	// window and if it has changed (try to) set the formula-cursor
/*N*/ 	// according to that.
/*N*/ {
/*N*/ 	ESelection	aNewSelection   (GetSelection());
/*N*/
/*N*/ 	if (!aNewSelection.IsEqual(aOldSelection))
/*N*/     {   SmViewShell *pView = rCmdBox.GetView();
/*N*/
/*N*/ 		if (pView)
/*N*/ 		{
/*N*/ 			// get row and column to look for
/*N*/ 			USHORT	nRow, nCol;
/*N*/ 			SmGetLeftSelectionPart(aNewSelection, nRow, nCol);
/*N*/ 			nRow++;
/*N*/ 			nCol++;
/*N*/
/*N*/ 			pView->GetGraphicWindow().SetCursorPos(nRow, nCol);
/*N*/
/*N*/ 			aOldSelection = aNewSelection;
/*N*/ 		}
/*N*/ 	}
/*N*/
/*N*/ 	return 0;
/*N*/ }


/*N*/ void SmEditWindow::Resize()
/*N*/ {
/*N*/ 	if (!pEditView)
/*N*/ 		CreateEditView();
/*N*/
/*N*/ 	if (pEditView)
/*N*/ 	{
/*N*/ 		pEditView->SetOutputArea(AdjustScrollBars());
/*N*/ 		pEditView->ShowCursor();
/*N*/
/*N*/         DBG_ASSERT( pEditView->GetEditEngine(), "EditEngine missing" );
/*N*/ 		const long nMaxVisAreaStart = pEditView->GetEditEngine()->GetTextHeight() -
/*N*/ 									  pEditView->GetOutputArea().GetHeight();
/*N*/ 		if (pEditView->GetVisArea().Top() > nMaxVisAreaStart)
/*N*/ 		{
/*?*/ 			Rectangle aVisArea(pEditView->GetVisArea() );
/*?*/ 			aVisArea.Top() = (nMaxVisAreaStart > 0 ) ? nMaxVisAreaStart : 0;
/*?*/ 			aVisArea.SetSize(pEditView->GetOutputArea().GetSize());
/*?*/ 			pEditView->SetVisArea(aVisArea);
/*?*/ 			pEditView->ShowCursor();
/*N*/ 		}
/*N*/ 		InitScrollBars();
/*N*/ 	}
/*N*/ 	Invalidate();
/*N*/ }





/*N*/ void SmEditWindow::KeyInput(const KeyEvent& rKEvt)
/*N*/ {
/*N*/ }


/*N*/ void SmEditWindow::CreateEditView()
/*N*/ {
/*N*/ }


/*N*/ IMPL_LINK( SmEditWindow, EditStatusHdl, EditStatus *, pStat )
/*N*/ {
/*N*/     if (!pEditView)
/*N*/ 		return 1;
/*N*/ 	else
/*N*/ 	{
/*N*/ 		SetScrollBarRanges();
/*N*/ 		return 0;
/*N*/ 	}
/*N*/ }

/*N*/ IMPL_LINK_INLINE_START( SmEditWindow, ScrollHdl, ScrollBar *, pScrollBar )
/*N*/ {DBG_BF_ASSERT(0, "STRIP"); //STRIP001
/*N*/ 	return 0;
/*N*/ }
/*N*/ IMPL_LINK_INLINE_END( SmEditWindow, ScrollHdl, ScrollBar *, pScrollBar )

/*N*/ Rectangle SmEditWindow::AdjustScrollBars()
/*N*/ {
/*N*/ 	const Size aOut( GetOutputSizePixel() );
/*N*/ 	Point aPoint;
/*N*/ 	Rectangle aRect( aPoint, aOut );
/*N*/
/*N*/ 	if (pVScrollBar && pHScrollBar && pScrollBox)
/*N*/ 	{
/*N*/ 		const long nTmp = GetSettings().GetStyleSettings().GetScrollBarSize();
/*N*/ 		Point aPt( aRect.TopRight() ); aPt.X() -= nTmp -1L;
/*N*/ 		pVScrollBar->SetPosSizePixel( aPt, Size(nTmp, aOut.Height() - nTmp));
/*N*/
/*N*/ 		aPt = aRect.BottomLeft(); aPt.Y() -= nTmp - 1L;
/*N*/ 		pHScrollBar->SetPosSizePixel( aPt, Size(aOut.Width() - nTmp, nTmp));
/*N*/
/*N*/ 		aPt.X() = pHScrollBar->GetSizePixel().Width();
/*N*/ 		aPt.Y() = pVScrollBar->GetSizePixel().Height();
/*N*/ 		pScrollBox->SetPosSizePixel(aPt, Size(nTmp, nTmp ));
/*N*/
/*N*/ 		aRect.Right()  = aPt.X() - 2;
/*N*/ 		aRect.Bottom() = aPt.Y() - 2;
/*N*/ 	}
/*N*/ 	return aRect;
/*N*/ }

/*N*/ void SmEditWindow::SetScrollBarRanges()
/*N*/ {
/*N*/ 	// Extra-Methode, nicht InitScrollBars, da auch fuer EditEngine-Events.
/*N*/     EditEngine *pEditEngine = GetEditEngine();
/*N*/ 	if (pVScrollBar && pHScrollBar && pEditEngine && pEditView)
/*N*/ 	{
/*N*/ 		long nTmp = pEditEngine->GetTextHeight();
/*N*/ 		pVScrollBar->SetRange(Range(0, nTmp));
/*N*/ 		pVScrollBar->SetThumbPos(pEditView->GetVisArea().Top());
/*N*/
/*N*/ 		nTmp = pEditEngine->GetPaperSize().Width();
/*N*/ 		pHScrollBar->SetRange(Range(0,nTmp));
/*N*/ 		pHScrollBar->SetThumbPos(pEditView->GetVisArea().Left());
/*N*/ 	}
/*N*/ }

/*N*/ void SmEditWindow::InitScrollBars()
/*N*/ {
/*N*/     if (pVScrollBar && pHScrollBar && pScrollBox && pEditView)
/*N*/ 	{
/*N*/ 		const Size aOut( pEditView->GetOutputArea().GetSize() );
/*N*/ 		pVScrollBar->SetVisibleSize(aOut.Height());
/*N*/ 		pVScrollBar->SetPageSize(aOut.Height() * 8 / 10);
/*N*/ 		pVScrollBar->SetLineSize(aOut.Height() * 2 / 10);
/*N*/
/*N*/ 		pHScrollBar->SetVisibleSize(aOut.Width());
/*N*/ 		pHScrollBar->SetPageSize(aOut.Width() * 8 / 10);
/*N*/ 		pHScrollBar->SetLineSize(SCROLL_LINE );
/*N*/
/*N*/ 		SetScrollBarRanges();
/*N*/
/*N*/ 		pVScrollBar->Show();
/*N*/ 		pHScrollBar->Show();
/*N*/ 		pScrollBox->Show();
/*N*/ 	}
/*N*/ }


/*N*/ XubString SmEditWindow::GetText()
/*N*/ {
/*N*/ 	String aText;
/*N*/     EditEngine *pEditEngine = GetEditEngine();
/*N*/ 	DBG_ASSERT( pEditEngine, "EditEngine missing" );
/*N*/ 	if (pEditEngine)
/*N*/ 		aText = pEditEngine->GetText( LINEEND_LF );
/*N*/ 	return aText;
/*N*/ }


/*N*/ void SmEditWindow::SetText(const XubString& rText)
/*N*/ {
/*N*/     EditEngine *pEditEngine = GetEditEngine();
/*N*/ 	DBG_ASSERT( pEditEngine, "EditEngine missing" );
/*N*/ 	if (pEditEngine  &&  !pEditEngine->IsModified())
/*N*/ 	{
/*N*/ 		if (!pEditView)
/*?*/ 			CreateEditView();
/*N*/
/*N*/ 		ESelection eSelection = pEditView->GetSelection();
/*N*/
/*N*/ 		pEditEngine->SetText(rText);
/*N*/ 		pEditEngine->ClearModifyFlag();
/*N*/
/*N*/       //! Hier die Timer neu zu starten verhindert, dass die Handler fuer andere
/*N*/ 		//! (im Augenblick nicht mehr aktive) Math Tasks aufgerufen werden.
/*N*/ 		aModifyTimer.Start();
/*N*/ 		aCursorMoveTimer.Start();
/*N*/
/*N*/ 		pEditView->SetSelection(eSelection);
/*N*/ 	}
/*N*/ }


/*N*/ void SmEditWindow::GetFocus()
/*N*/ {
/*N*/ 	Window::GetFocus();
/*N*/
/*N*/     if (!pEditView)
/*N*/          CreateEditView();
/*N*/     EditEngine *pEditEngine = GetEditEngine();
/*N*/ 	if (pEditEngine)
/*N*/ 		pEditEngine->SetStatusEventHdl( LINK(this, SmEditWindow, EditStatusHdl) );
/*N*/ }














/*N*/ ESelection SmEditWindow::GetSelection() const
/*N*/ {
/*N*/     // pointer may be 0 when reloading a document and the old view
/*N*/     // was already destroyed
/*N*/     //(DBG_ASSERT( pEditView, "NULL pointer" );
/*N*/ 	ESelection eSel;
/*N*/ 	if (pEditView)
/*N*/ 		eSel = pEditView->GetSelection();
/*N*/ 	return eSel;
/*N*/ }


/*N*/ BOOL SmEditWindow::IsEmpty() const
/*N*/ {
/*N*/     EditEngine *pEditEngine = ((SmEditWindow *) this)->GetEditEngine();
/*N*/     return pEditEngine ? pEditEngine->GetTextLen() == 0 : FALSE;
/*N*/ }

/*N*/ BOOL SmEditWindow::IsSelected() const
/*N*/ {
/*N*/     return pEditView ? pEditView->HasSelection() : FALSE;
/*N*/ }






/*N*/ void SmEditWindow::Flush()
/*N*/ {
/*N*/     EditEngine *pEditEngine = GetEditEngine();
/*N*/ 	if (pEditEngine  &&  pEditEngine->IsModified())
/*N*/ 	{
/*N*/ 		pEditEngine->ClearModifyFlag();
/*N*/         SmViewShell *pViewSh = rCmdBox.GetView();
/*N*/ 		if (pViewSh)
/*N*/ 			pViewSh->GetViewFrame()->GetDispatcher()->Execute(
/*N*/ 					SID_TEXT, SFX_CALLMODE_STANDARD,
/*N*/ 					new SfxStringItem(SID_TEXT, GetText()), 0L);
/*N*/ 	}
/*N*/
/*N*/ 	if (aCursorMoveTimer.IsActive())
/*N*/ 	{
/*N*/ 		aCursorMoveTimer.Stop();
/*N*/ 		// ggf noch die (neue) FormulaCursor Position setzen
/*N*/ 		CursorMoveTimerHdl(&aCursorMoveTimer);
/*N*/ 	}
/*N*/ }





}
