text: /**************************************************************
   * 
   * 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.
   * 
   *************************************************************/
  
  
  
  // MARKER(update_precomp.py): autogen include statement, do not remove
  #include "precompiled_sc.hxx"
  
  
  
  // INCLUDE ---------------------------------------------------------------
  
  #ifdef _MSC_VER
  #pragma optimize ("", off)
  #endif
  
  #include <sfx2/bindings.hxx>
  #include <sfx2/viewfrm.hxx>
  #include <svl/aeitem.hxx>
  #include <svl/whiter.hxx>
  #include <unotools/moduleoptions.hxx>
  #include <svl/languageoptions.hxx>
  #include <sfx2/dispatch.hxx>
  
  #include "tabvwsh.hxx"
  #include "drawattr.hxx"
  #include "drawsh.hxx"
  #include "drawview.hxx"
  #include "fupoor.hxx"
  #include "fuconrec.hxx"
  #include "fuconpol.hxx"
  #include "fuconarc.hxx"
  #include "fuconuno.hxx"
  #include "fusel.hxx"
  #include "futext.hxx"
  #include "fumark.hxx"
  #include "fuinsert.hxx"
  #include "global.hxx"
  #include "sc.hrc"
  #include "scmod.hxx"
  #include "appoptio.hxx"
  
  // #98185# Create default drawing objects via keyboard
  #include <svx/svdpagv.hxx>
  #include <svl/stritem.hxx>
  #include <svx/svdpage.hxx>
  #include <fuconcustomshape.hxx>
  
  // -----------------------------------------------------------------------
  
  SdrView* __EXPORT ScTabViewShell::GetDrawView() const
  {
  	return ((ScTabViewShell*)this)->GetScDrawView();	// GetScDrawView ist nicht-const
  }
  
  void ScTabViewShell::WindowChanged()
  {
  	Window* pWin = GetActiveWin();
  
  	ScDrawView* pDrView = GetScDrawView();
  	if (pDrView)
  		pDrView->SetActualWin(pWin);
  
  	FuPoor*	pFunc = GetDrawFuncPtr();
  	if (pFunc)
  		pFunc->SetWindow(pWin);
  
  	//	when font from InputContext is used,
  	//	this must be moved to change of cursor position:
  	UpdateInputContext();
  }
  
  void ScTabViewShell::ExecDraw(SfxRequest& rReq)
  {
  	SC_MOD()->InputEnterHandler();
  	UpdateInputHandler();
  
  	MakeDrawLayer();
  
  	ScTabView* pTabView = GetViewData()->GetView();
  	SfxBindings& rBindings = GetViewFrame()->GetBindings();
  
  	Window* 	pWin	= pTabView->GetActiveWin();
  	ScDrawView*	pView	= pTabView->GetScDrawView();
  	SdrModel*	pDoc	= pView->GetModel();
  
  	const SfxItemSet *pArgs = rReq.GetArgs();
  	sal_uInt16 nNewId = rReq.GetSlot();
  
      if ( nNewId == SID_DRAW_CHART )
      {
          // #i71254# directly insert a chart instead of drawing its output rectangle
          FuInsertChart(this, pWin, pView, pDoc, rReq);
          return;
      }
  
  	//
  	//	Pseudo-Slots von Draw-Toolbox auswerten
  	//!	wird das ueberhaupt noch gebraucht ?????
  	//
  
      if (nNewId == SID_INSERT_DRAW && pArgs)
  	{
  		const SfxPoolItem* pItem;
  		if ( pArgs->GetItemState( SID_INSERT_DRAW, sal_True, &pItem ) == SFX_ITEM_SET &&
  			 pItem->ISA( SvxDrawToolItem ) )
  		{
  			SvxDrawToolEnum eSel = (SvxDrawToolEnum)((const SvxDrawToolItem*)pItem)->GetValue();
  			switch (eSel)
  			{
  				case SVX_SNAP_DRAW_SELECT:			nNewId = SID_OBJECT_SELECT; 		break;
  				case SVX_SNAP_DRAW_LINE:			nNewId = SID_DRAW_LINE; 			break;
  				case SVX_SNAP_DRAW_RECT:			nNewId = SID_DRAW_RECT; 			break;
  				case SVX_SNAP_DRAW_ELLIPSE: 		nNewId = SID_DRAW_ELLIPSE;			break;
  				case SVX_SNAP_DRAW_POLYGON_NOFILL:	nNewId = SID_DRAW_POLYGON_NOFILL;	break;
  				case SVX_SNAP_DRAW_BEZIER_NOFILL:	nNewId = SID_DRAW_BEZIER_NOFILL;	break;
  				case SVX_SNAP_DRAW_FREELINE_NOFILL:	nNewId = SID_DRAW_FREELINE_NOFILL;	break;
  				case SVX_SNAP_DRAW_ARC: 			nNewId = SID_DRAW_ARC;				break;
  				case SVX_SNAP_DRAW_PIE: 			nNewId = SID_DRAW_PIE;				break;
  				case SVX_SNAP_DRAW_CIRCLECUT:		nNewId = SID_DRAW_CIRCLECUT;		break;
  				case SVX_SNAP_DRAW_TEXT:			nNewId = SID_DRAW_TEXT; 			break;
  				case SVX_SNAP_DRAW_TEXT_VERTICAL:	nNewId = SID_DRAW_TEXT_VERTICAL;	break;
  				case SVX_SNAP_DRAW_TEXT_MARQUEE:	nNewId = SID_DRAW_TEXT_MARQUEE;		break;
  				case SVX_SNAP_DRAW_CAPTION: 		nNewId = SID_DRAW_CAPTION;			break;
  				case SVX_SNAP_DRAW_CAPTION_VERTICAL: nNewId = SID_DRAW_CAPTION_VERTICAL; break;
  			}
  		}
          else                    // sal_uInt16-Item vom Controller
          {
              rReq.Done();
              return;
          }
  	}
  
      if ( nNewId == SID_DRAW_SELECT )
  		nNewId = SID_OBJECT_SELECT;
  
  	sal_uInt16 nNewFormId = 0;
  	if ( nNewId == SID_FM_CREATE_CONTROL && pArgs )
  	{
  		const SfxPoolItem* pItem;
  		if ( pArgs->GetItemState( SID_FM_CONTROL_IDENTIFIER, sal_True, &pItem ) == SFX_ITEM_SET &&
  			 pItem->ISA( SfxUInt16Item ) )
  			nNewFormId = ((const SfxUInt16Item*)pItem)->GetValue();
  	}
  
      String sStringItemValue;
      if ( pArgs )
      {
          const SfxPoolItem* pItem;
          if ( pArgs->GetItemState( nNewId, sal_True, &pItem ) == SFX_ITEM_SET && pItem->ISA( SfxStringItem ) )
              sStringItemValue = static_cast<const SfxStringItem*>(pItem)->GetValue();
      }
      bool bSwitchCustom = ( sStringItemValue.Len() && sDrawCustom.Len() && sStringItemValue != sDrawCustom );
  
  	if (nNewId == SID_INSERT_FRAME)						// vom Tbx-Button
  		nNewId = SID_DRAW_TEXT;
  
  	//	#97016# CTRL-SID_OBJECT_SELECT is used to select the first object,
  	//	but not if SID_OBJECT_SELECT is the result of clicking a create function again,
  	//	so this must be tested before changing nNewId below.
  	sal_Bool bSelectFirst = ( nNewId == SID_OBJECT_SELECT && (rReq.GetModifier() & KEY_MOD1) );
  
  	sal_Bool bEx = IsDrawSelMode();
  	if ( rReq.GetModifier() & KEY_MOD1 )
  	{
  		//	#97016# always allow keyboard selection also on background layer
  		//	#98185# also allow creation of default objects if the same object type
  		//	was already active
  		bEx = sal_True;
  	}
  	else if ( nNewId == nDrawSfxId && ( nNewId != SID_FM_CREATE_CONTROL ||
                                      nNewFormId == nFormSfxId || nNewFormId == 0 ) && !bSwitchCustom )
  	{
          //  #i52871# if a different custom shape is selected, the slot id can be the same,
          //  so the custom shape type string has to be compared, too.
  
  		//	SID_FM_CREATE_CONTROL mit nNewFormId==0 (ohne Parameter) kommt beim Deaktivieren
  		//	aus FuConstruct::SimpleMouseButtonUp
  		//	#59280# Execute fuer die Form-Shell, um im Controller zu deselektieren
  		if ( nNewId == SID_FM_CREATE_CONTROL )
  		{
  			GetViewData()->GetDispatcher().Execute(SID_FM_LEAVE_CREATE);
  			GetViewFrame()->GetBindings().InvalidateAll(sal_False);
  			//!	was fuer einen Slot braucht der komische Controller wirklich, um das anzuzeigen????
  		}
  
  		bEx = !bEx;
  		nNewId = SID_OBJECT_SELECT;
  	}
  	else
  		bEx = sal_True;
  
  	if ( nDrawSfxId == SID_FM_CREATE_CONTROL && nNewId != nDrawSfxId )
  	{
  		//	Wechsel von Control- zu Zeichenfunktion -> im Control-Controller deselektieren
  		GetViewData()->GetDispatcher().Execute(SID_FM_LEAVE_CREATE);
  		GetViewFrame()->GetBindings().InvalidateAll(sal_False);
  		//!	was fuer einen Slot braucht der komische Controller wirklich, um das anzuzeigen????
  	}
  
  	SetDrawSelMode(bEx);
  
  	pView->LockBackgroundLayer( !bEx );
  
  	if ( bSelectFirst )
  	{
  		//	#97016# select first draw object if none is selected yet
  		if(!pView->AreObjectsMarked())
  		{
  			// select first object
  			pView->UnmarkAllObj();
  			pView->MarkNextObj(sal_True);
  
  			// ...and make it visible
  			if(pView->AreObjectsMarked())
  				pView->MakeVisible(pView->GetAllMarkedRect(), *pWin);
  		}
  	}
  
  	nDrawSfxId = nNewId;
      sDrawCustom.Erase();    // value is set below for custom shapes
  
  	if ( nNewId != SID_DRAW_CHART )				// Chart nicht mit DrawShell
  	{
  		if ( nNewId == SID_DRAW_TEXT || nNewId == SID_DRAW_TEXT_VERTICAL ||
  				nNewId == SID_DRAW_TEXT_MARQUEE || nNewId == SID_DRAW_NOTEEDIT )
  			SetDrawTextShell( sal_True );
  		else
  		{
  			if ( bEx || pView->GetMarkedObjectList().GetMarkCount() != 0 )
  				SetDrawShellOrSub();
  			else
  				SetDrawShell( sal_False );
  		}
  	}
  
  	if (pTabView->GetDrawFuncPtr())
  	{
  		if (pTabView->GetDrawFuncOldPtr() != pTabView->GetDrawFuncPtr())
  			delete pTabView->GetDrawFuncOldPtr();
  
  		pTabView->GetDrawFuncPtr()->Deactivate();
  		pTabView->SetDrawFuncOldPtr(pTabView->GetDrawFuncPtr());
  		pTabView->SetDrawFuncPtr(NULL);
  	}
  
  	SfxRequest aNewReq(rReq);
  	aNewReq.SetSlot(nDrawSfxId);
  
  	switch (nNewId)
  	{
  		case SID_OBJECT_SELECT:
  			//@#70206# Nicht immer zurueckschalten
  			if(pView->GetMarkedObjectList().GetMarkCount() == 0) SetDrawShell(bEx);
  			pTabView->SetDrawFuncPtr(new FuSelection(this, pWin, pView, pDoc, aNewReq));
  			break;
  
  		case SID_DRAW_LINE:
  		case SID_DRAW_RECT:
  		case SID_DRAW_ELLIPSE:
  			pTabView->SetDrawFuncPtr(new FuConstRectangle(this, pWin, pView, pDoc, aNewReq));
  			break;
  
  		case SID_DRAW_CAPTION:
  		case SID_DRAW_CAPTION_VERTICAL:
  			pTabView->SetDrawFuncPtr(new FuConstRectangle(this, pWin, pView, pDoc, aNewReq));
  			pView->SetFrameDragSingles( sal_False );
  			rBindings.Invalidate( SID_BEZIER_EDIT );
  			break;
  
  		case SID_DRAW_POLYGON:
  		case SID_DRAW_POLYGON_NOFILL:
  		case SID_DRAW_BEZIER_NOFILL:
  		case SID_DRAW_FREELINE_NOFILL:
  			pTabView->SetDrawFuncPtr(new FuConstPolygon(this, pWin, pView, pDoc, aNewReq));
  			break;
  
  		case SID_DRAW_ARC:
  		case SID_DRAW_PIE:
  		case SID_DRAW_CIRCLECUT:
  			pTabView->SetDrawFuncPtr(new FuConstArc(this, pWin, pView, pDoc, aNewReq));
  			break;
  
  		case SID_DRAW_TEXT:
  		case SID_DRAW_TEXT_VERTICAL:
  		case SID_DRAW_TEXT_MARQUEE:
  		case SID_DRAW_NOTEEDIT:
  			pTabView->SetDrawFuncPtr(new FuText(this, pWin, pView, pDoc, aNewReq));
  			break;
  
  		case SID_FM_CREATE_CONTROL:
  			SetDrawFormShell(sal_True);
  			pTabView->SetDrawFuncPtr(new FuConstUnoControl(this, pWin, pView, pDoc, aNewReq));
  			nFormSfxId = nNewFormId;
  			break;
  
  		case SID_DRAW_CHART:
  //UNUSED2008-05  bChartDlgIsEdit = sal_False;
  			pTabView->SetDrawFuncPtr(new FuMarkRect(this, pWin, pView, pDoc, aNewReq));
  			break;
  
  		case SID_DRAWTBX_CS_BASIC :
  		case SID_DRAWTBX_CS_SYMBOL :
  		case SID_DRAWTBX_CS_ARROW :
  		case SID_DRAWTBX_CS_FLOWCHART :
  		case SID_DRAWTBX_CS_CALLOUT :
  		case SID_DRAWTBX_CS_STAR :
  		case SID_DRAW_CS_ID :
  		{
  			pTabView->SetDrawFuncPtr( new FuConstCustomShape( this, pWin, pView, pDoc, aNewReq ));
              if ( nNewId != SID_DRAW_CS_ID )
              {
                  SFX_REQUEST_ARG( rReq, pEnumCommand, SfxStringItem, nNewId, sal_False );
                  if ( pEnumCommand )
                  {
                      aCurrShapeEnumCommand[ nNewId - SID_DRAWTBX_CS_BASIC ] = pEnumCommand->GetValue();
  		            SfxBindings& rBind = GetViewFrame()->GetBindings();
  		            rBind.Invalidate( nNewId );
  		            rBind.Update( nNewId );
  
                      sDrawCustom = pEnumCommand->GetValue();  // to detect when a different shape type is selected
                  }
              }
  		}
  		break;
  
          default:
  			break;
  	}
  
  	if (pTabView->GetDrawFuncPtr())
  		pTabView->GetDrawFuncPtr()->Activate();
  
  	rReq.Done();
  
  	rBindings.Invalidate( SID_INSERT_DRAW );
  	rBindings.Update( SID_INSERT_DRAW );
  
  	// #98185# Create default drawing objects via keyboard
  	// with qualifier construct directly
  	FuPoor*	pFuActual = GetDrawFuncPtr();
  
  	if(pFuActual && (rReq.GetModifier() & KEY_MOD1))
  	{
  		// #98185# Create default drawing objects via keyboard
  		const ScAppOptions& rAppOpt = SC_MOD()->GetAppOptions();
  		sal_uInt32 nDefaultObjectSizeWidth = rAppOpt.GetDefaultObjectSizeWidth();
  		sal_uInt32 nDefaultObjectSizeHeight = rAppOpt.GetDefaultObjectSizeHeight();
  
  		// calc position and size
  		Rectangle aVisArea = pWin->PixelToLogic(Rectangle(Point(0,0), pWin->GetOutputSizePixel()));
  		Point aPagePos = aVisArea.Center();
  		aPagePos.X() -= nDefaultObjectSizeWidth / 2;
  		aPagePos.Y() -= nDefaultObjectSizeHeight / 2;
  		Rectangle aNewObjectRectangle(aPagePos, Size(nDefaultObjectSizeWidth, nDefaultObjectSizeHeight));
  
  		ScDrawView* pDrView = GetScDrawView();
  
  		if(pDrView)
  		{
  			SdrPageView* pPageView = pDrView->GetSdrPageView();
  
  			if(pPageView)
  			{
  				// create the default object
  				SdrObject* pObj = pFuActual->CreateDefaultObject(nNewId, aNewObjectRectangle);
  
  				if(pObj)
  				{
  					// insert into page
  					pView->InsertObjectAtView(pObj, *pPageView);
  
  					if ( nNewId == SID_DRAW_CAPTION || nNewId == SID_DRAW_CAPTION_VERTICAL )
  					{
  						//	#105815# use KeyInput to start edit mode (FuText is created).
  						//	For FuText objects, edit mode is handled within CreateDefaultObject.
  						//	KEY_F2 is handled in FuDraw::KeyInput.
  
  						pFuActual->KeyInput( KeyEvent( 0, KeyCode( KEY_F2 ) ) );
  					}
  				}
  			}
  		}
  	}
  }
  
  void ScTabViewShell::GetDrawState(SfxItemSet &rSet)
  {
  	SfxWhichIter	aIter(rSet);
  	sal_uInt16			nWhich = aIter.FirstWhich();
  
  	while ( nWhich )
  	{
  		switch ( nWhich )
  		{
  			case SID_INSERT_DRAW:
  				{
  					//	SID_OBJECT_SELECT nur, wenn "harter" Selektionsmodus
  					sal_uInt16 nPutId = nDrawSfxId;
  					if ( nPutId == SID_OBJECT_SELECT && !IsDrawSelMode() )
  						nPutId = USHRT_MAX;
  					// nur die Images, die auch auf dem Controller liegen
  					if ( nPutId != SID_OBJECT_SELECT &&
  						 nPutId != SID_DRAW_LINE &&
  						 nPutId != SID_DRAW_RECT &&
  						 nPutId != SID_DRAW_ELLIPSE &&
  						 nPutId != SID_DRAW_POLYGON_NOFILL &&
  						 nPutId != SID_DRAW_BEZIER_NOFILL &&
  						 nPutId != SID_DRAW_FREELINE_NOFILL &&
  						 nPutId != SID_DRAW_ARC &&
  						 nPutId != SID_DRAW_PIE &&
  						 nPutId != SID_DRAW_CIRCLECUT &&
  						 nPutId != SID_DRAW_TEXT &&
  						 nPutId != SID_DRAW_TEXT_VERTICAL &&
  						 nPutId != SID_DRAW_TEXT_MARQUEE &&
  						 nPutId != SID_DRAW_CAPTION &&
  						 nPutId != SID_DRAW_CAPTION_VERTICAL )
  						nPutId = USHRT_MAX;
  					SfxAllEnumItem aItem( nWhich, nPutId );
  					if ( !SvtLanguageOptions().IsVerticalTextEnabled() )
  					{
  						aItem.DisableValue( SID_DRAW_TEXT_VERTICAL );
  						aItem.DisableValue( SID_DRAW_CAPTION_VERTICAL );
  					}
  					rSet.Put( aItem );
  				}
  				break;
  
  			case SID_DRAW_CHART:
  				{
                      sal_Bool bOle = GetViewFrame()->GetFrame().IsInPlace();
  					if ( bOle || !SvtModuleOptions().IsChart() )
  						rSet.DisableItem( nWhich );
  				}
  				break;
  
  			case SID_OBJECT_SELECT:		// wichtig fuer den ollen Control-Controller
  				rSet.Put( SfxBoolItem( nWhich, nDrawSfxId == SID_OBJECT_SELECT && IsDrawSelMode() ) );
  				break;
  		}
  		nWhich = aIter.NextWhich();
  	}
  }
  
  sal_Bool ScTabViewShell::SelectObject( const String& rName )
  {
  	ScDrawView* pView = GetViewData()->GetScDrawView();
  	if (!pView)
  		return sal_False;
  
  	sal_Bool bFound = pView->SelectObject( rName );
  	// DrawShell etc. is handled in MarkListHasChanged
  
  	return bFound;
  }
  
  
  
  