1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp> 31 #include <com/sun/star/chart2/data/XDataReceiver.hpp> 32 33 34 35 //------------------------------------------------------------------ 36 37 #ifdef _MSC_VER 38 #pragma optimize ("", off) 39 #endif 40 41 // INCLUDE --------------------------------------------------------------- 42 43 #include <com/sun/star/embed/EmbedMisc.hpp> 44 #include <com/sun/star/embed/EmbedStates.hpp> 45 #include <sfx2/app.hxx> 46 #include <toolkit/helper/vclunohelper.hxx> 47 #include <svx/svxdlg.hxx> 48 #include <svx/dataaccessdescriptor.hxx> 49 #include <svx/pfiledlg.hxx> 50 #include <svx/svditer.hxx> 51 #include <svx/svdmark.hxx> 52 #include <svx/svdograf.hxx> 53 #include <svx/svdogrp.hxx> 54 #include <svx/svdoole2.hxx> 55 #include <svx/svdouno.hxx> 56 #include <svx/svdview.hxx> 57 #include <sfx2/linkmgr.hxx> 58 #include <svx/fontworkbar.hxx> 59 #include <sfx2/bindings.hxx> 60 #include <sfx2/dispatch.hxx> 61 #include <sfx2/viewfrm.hxx> 62 #include <svtools/soerr.hxx> 63 #include <svl/rectitem.hxx> 64 #include <svl/slstitm.hxx> 65 #include <svl/whiter.hxx> 66 #include <unotools/moduleoptions.hxx> 67 #include <sot/exchange.hxx> 68 #include <tools/diagnose_ex.h> 69 70 #include "tabvwsh.hxx" 71 #include "globstr.hrc" 72 #include "scmod.hxx" 73 #include "document.hxx" 74 #include "sc.hrc" 75 #include "client.hxx" 76 #include "fuinsert.hxx" 77 #include "docsh.hxx" 78 #include "chartarr.hxx" 79 #include "drawview.hxx" 80 #include "ChartRangeSelectionListener.hxx" 81 82 using namespace com::sun::star; 83 84 // STATIC DATA ----------------------------------------------------------- 85 86 void ScTabViewShell::ConnectObject( SdrOle2Obj* pObj ) 87 { 88 // wird aus dem Paint gerufen 89 90 uno::Reference < embed::XEmbeddedObject > xObj = pObj->GetObjRef(); 91 Window* pWin = GetActiveWin(); 92 93 // #41412# wenn schon connected ist, nicht nochmal SetObjArea/SetSizeScale 94 95 SfxInPlaceClient* pClient = FindIPClient( xObj, pWin ); 96 if ( !pClient ) 97 { 98 pClient = new ScClient( this, pWin, GetSdrView()->GetModel(), pObj ); 99 Rectangle aRect = pObj->GetLogicRect(); 100 Size aDrawSize = aRect.GetSize(); 101 102 Size aOleSize = pObj->GetOrigObjSize(); 103 104 Fraction aScaleWidth (aDrawSize.Width(), aOleSize.Width() ); 105 Fraction aScaleHeight(aDrawSize.Height(), aOleSize.Height() ); 106 aScaleWidth.ReduceInaccurate(10); // kompatibel zum SdrOle2Obj 107 aScaleHeight.ReduceInaccurate(10); 108 pClient->SetSizeScale(aScaleWidth,aScaleHeight); 109 110 // sichtbarer Ausschnitt wird nur inplace veraendert! 111 // the object area must be set after the scaling since it triggers the resizing 112 aRect.SetSize( aOleSize ); 113 pClient->SetObjArea( aRect ); 114 115 ((ScClient*)pClient)->SetGrafEdit( NULL ); 116 } 117 } 118 119 sal_Bool ScTabViewShell::ActivateObject( SdrOle2Obj* pObj, long nVerb ) 120 { 121 // #41081# Gueltigkeits-Hinweisfenster nicht ueber dem Objekt stehenlassen 122 RemoveHintWindow(); 123 124 uno::Reference < embed::XEmbeddedObject > xObj = pObj->GetObjRef(); 125 Window* pWin = GetActiveWin(); 126 ErrCode nErr = ERRCODE_NONE; 127 sal_Bool bErrorShown = sal_False; 128 129 // linked objects aren't supported 130 // if ( xIPObj->IsLink() ) 131 // nErr = xIPObj->DoVerb(nVerb); // gelinkt -> ohne Client etc. 132 // else 133 { 134 SfxInPlaceClient* pClient = FindIPClient( xObj, pWin ); 135 if ( !pClient ) 136 pClient = new ScClient( this, pWin, GetSdrView()->GetModel(), pObj ); 137 138 if ( !(nErr & ERRCODE_ERROR_MASK) && xObj.is() ) 139 { 140 Rectangle aRect = pObj->GetLogicRect(); 141 142 { 143 // #i118485# center on BoundRect for activation, 144 // OLE may be sheared/rotated now 145 const Rectangle& rBoundRect = pObj->GetCurrentBoundRect(); 146 const Point aDelta(rBoundRect.Center() - aRect.Center()); 147 aRect.Move(aDelta.X(), aDelta.Y()); 148 } 149 150 Size aDrawSize = aRect.GetSize(); 151 152 MapMode aMapMode( MAP_100TH_MM ); 153 Size aOleSize = pObj->GetOrigObjSize( &aMapMode ); 154 155 if ( pClient->GetAspect() != embed::Aspects::MSOLE_ICON 156 && ( xObj->getStatus( pClient->GetAspect() ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE ) ) 157 { 158 // scale must always be 1 - change VisArea if different from client size 159 160 if ( aDrawSize != aOleSize ) 161 { 162 MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( pClient->GetAspect() ) ); 163 aOleSize = OutputDevice::LogicToLogic( aDrawSize, 164 MAP_100TH_MM, aUnit ); 165 awt::Size aSz( aOleSize.Width(), aOleSize.Height() ); 166 xObj->setVisualAreaSize( pClient->GetAspect(), aSz ); 167 } 168 Fraction aOne( 1, 1 ); 169 pClient->SetSizeScale( aOne, aOne ); 170 } 171 else 172 { 173 // calculate scale from client and VisArea size 174 175 Fraction aScaleWidth (aDrawSize.Width(), aOleSize.Width() ); 176 Fraction aScaleHeight(aDrawSize.Height(), aOleSize.Height() ); 177 aScaleWidth.ReduceInaccurate(10); // kompatibel zum SdrOle2Obj 178 aScaleHeight.ReduceInaccurate(10); 179 pClient->SetSizeScale(aScaleWidth,aScaleHeight); 180 } 181 182 // sichtbarer Ausschnitt wird nur inplace veraendert! 183 // the object area must be set after the scaling since it triggers the resizing 184 aRect.SetSize( aOleSize ); 185 pClient->SetObjArea( aRect ); 186 187 ((ScClient*)pClient)->SetGrafEdit( NULL ); 188 189 nErr = pClient->DoVerb( nVerb ); 190 bErrorShown = sal_True; 191 // SfxViewShell::DoVerb zeigt seine Fehlermeldungen selber an 192 193 SetNewVisArea(); 194 195 // attach listener to selection changes in chart that affect cell 196 // ranges, so those can be highlighted 197 // note: do that after DoVerb, so that the chart controller exists 198 if ( SvtModuleOptions().IsChart() ) 199 { 200 SvGlobalName aObjClsId ( xObj->getClassID() ); 201 if (SotExchange::IsChart( aObjClsId )) 202 { 203 try 204 { 205 uno::Reference < embed::XComponentSupplier > xSup( xObj, uno::UNO_QUERY_THROW ); 206 uno::Reference< chart2::data::XDataReceiver > xDataReceiver( 207 xSup->getComponent(), uno::UNO_QUERY_THROW ); 208 uno::Reference< chart2::data::XRangeHighlighter > xRangeHightlighter( 209 xDataReceiver->getRangeHighlighter()); 210 if( xRangeHightlighter.is()) 211 { 212 uno::Reference< view::XSelectionChangeListener > xListener( 213 new ScChartRangeSelectionListener( this )); 214 xRangeHightlighter->addSelectionChangeListener( xListener ); 215 } 216 } 217 catch( const uno::Exception & ) 218 { 219 DBG_ERROR( "Exception caught while querying chart" ); 220 } 221 } 222 } 223 } 224 } 225 if (nErr != ERRCODE_NONE && !bErrorShown) 226 ErrorHandler::HandleError(nErr); 227 228 // #i118524# refresh handles to suppress for activated OLE 229 if(GetSdrView()) 230 { 231 GetSdrView()->AdjustMarkHdl(); 232 } 233 //! SetDocumentName sollte schon im Sfx passieren ??? 234 //TODO/LATER: how "SetDocumentName"? 235 //xIPObj->SetDocumentName( GetViewData()->GetDocShell()->GetTitle() ); 236 237 return ( !(nErr & ERRCODE_ERROR_MASK) ); 238 } 239 240 ErrCode __EXPORT ScTabViewShell::DoVerb(long nVerb) 241 { 242 SdrView* pView = GetSdrView(); 243 if (!pView) 244 return ERRCODE_SO_NOTIMPL; // soll nicht sein 245 246 SdrOle2Obj* pOle2Obj = NULL; 247 SdrGrafObj* pGrafObj = NULL; 248 SdrObject* pObj = NULL; 249 ErrCode nErr = ERRCODE_NONE; 250 251 const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); 252 if (rMarkList.GetMarkCount() == 1) 253 { 254 pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); 255 if (pObj->GetObjIdentifier() == OBJ_OLE2) 256 pOle2Obj = (SdrOle2Obj*) pObj; 257 else if (pObj->GetObjIdentifier() == OBJ_GRAF) 258 { 259 pGrafObj = (SdrGrafObj*) pObj; 260 } 261 } 262 263 if (pOle2Obj) 264 { 265 ActivateObject( pOle2Obj, nVerb ); 266 } 267 else 268 { 269 DBG_ERROR("kein Objekt fuer Verb gefunden"); 270 } 271 272 return nErr; 273 } 274 275 void ScTabViewShell::DeactivateOle() 276 { 277 // deactivate inplace editing if currently active 278 279 ScModule* pScMod = SC_MOD(); 280 bool bUnoRefDialog = pScMod->IsRefDialogOpen() && pScMod->GetCurRefDlgId() == WID_SIMPLE_REF; 281 282 ScClient* pClient = (ScClient*) GetIPClient(); 283 if ( pClient && pClient->IsObjectInPlaceActive() && !bUnoRefDialog ) 284 pClient->DeactivateObject(); 285 } 286 287 void ScTabViewShell::ExecDrawIns(SfxRequest& rReq) 288 { 289 sal_uInt16 nSlot = rReq.GetSlot(); 290 if (nSlot != SID_OBJECTRESIZE ) 291 { 292 SC_MOD()->InputEnterHandler(); 293 UpdateInputHandler(); 294 } 295 296 // Rahmen fuer Chart einfuegen wird abgebrochen: 297 FuPoor* pPoor = GetDrawFuncPtr(); 298 if ( pPoor && pPoor->GetSlotID() == SID_DRAW_CHART ) 299 GetViewData()->GetDispatcher().Execute(SID_DRAW_CHART, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD); 300 301 MakeDrawLayer(); 302 303 SfxBindings& rBindings = GetViewFrame()->GetBindings(); 304 ScTabView* pTabView = GetViewData()->GetView(); 305 Window* pWin = pTabView->GetActiveWin(); 306 ScDrawView* pView = pTabView->GetScDrawView(); 307 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 308 ScDocument* pDoc = pDocSh->GetDocument(); 309 // SdrModel* pDrModel = pDocSh->MakeDrawLayer(); 310 SdrModel* pDrModel = pView->GetModel(); 311 312 switch ( nSlot ) 313 { 314 case SID_INSERT_GRAPHIC: 315 FuInsertGraphic(this, pWin, pView, pDrModel, rReq); 316 // shell is set in MarkListHasChanged 317 break; 318 319 case SID_INSERT_AVMEDIA: 320 FuInsertMedia(this, pWin, pView, pDrModel, rReq); 321 // shell is set in MarkListHasChanged 322 break; 323 324 case SID_INSERT_DIAGRAM: 325 FuInsertChart(this, pWin, pView, pDrModel, rReq); 326 //? SC_MOD()->SetFunctionDlg( NULL );//XXX 327 break; 328 329 case SID_INSERT_OBJECT: 330 case SID_INSERT_PLUGIN: 331 case SID_INSERT_SOUND: 332 case SID_INSERT_VIDEO: 333 case SID_INSERT_SMATH: 334 case SID_INSERT_FLOATINGFRAME: 335 FuInsertOLE(this, pWin, pView, pDrModel, rReq); 336 break; 337 338 case SID_OBJECTRESIZE: 339 { 340 // Der Server moechte die Clientgrosse verandern 341 342 SfxInPlaceClient* pClient = GetIPClient(); 343 344 if ( pClient && pClient->IsObjectInPlaceActive() ) 345 { 346 const SfxRectangleItem& rRect = 347 (SfxRectangleItem&)rReq.GetArgs()->Get(SID_OBJECTRESIZE); 348 Rectangle aRect( pWin->PixelToLogic( rRect.GetValue() ) ); 349 350 if ( pView->AreObjectsMarked() ) 351 { 352 const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); 353 354 if (rMarkList.GetMarkCount() == 1) 355 { 356 SdrMark* pMark = rMarkList.GetMark(0); 357 SdrObject* pObj = pMark->GetMarkedSdrObj(); 358 359 sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier(); 360 361 if (nSdrObjKind == OBJ_OLE2) 362 { 363 if ( ( (SdrOle2Obj*) pObj)->GetObjRef().is() ) 364 { 365 pObj->SetLogicRect(aRect); 366 } 367 } 368 } 369 } 370 } 371 } 372 break; 373 374 case SID_LINKS: 375 { 376 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); 377 SfxAbstractLinksDialog* pDlg = pFact->CreateLinksDialog( pWin, pDoc->GetLinkManager() ); 378 if ( pDlg ) 379 { 380 pDlg->Execute(); 381 rBindings.Invalidate( nSlot ); 382 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator 383 rReq.Done(); 384 } 385 } 386 break; 387 388 // #98721# 389 case SID_FM_CREATE_FIELDCONTROL: 390 { 391 SFX_REQUEST_ARG( rReq, pDescriptorItem, SfxUnoAnyItem, SID_FM_DATACCESS_DESCRIPTOR, sal_False ); 392 DBG_ASSERT( pDescriptorItem, "SID_FM_CREATE_FIELDCONTROL: invalid request args!" ); 393 394 if(pDescriptorItem) 395 { 396 //! merge with ScViewFunc::PasteDataFormat (SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE)? 397 398 ScDrawView* pDrView = GetScDrawView(); 399 SdrPageView* pPageView = pDrView ? pDrView->GetSdrPageView() : NULL; 400 if(pPageView) 401 { 402 ::svx::ODataAccessDescriptor aDescriptor(pDescriptorItem->GetValue()); 403 SdrObject* pNewDBField = pDrView->CreateFieldControl(aDescriptor); 404 405 if(pNewDBField) 406 { 407 Rectangle aVisArea = pWin->PixelToLogic(Rectangle(Point(0,0), pWin->GetOutputSizePixel())); 408 Point aObjPos(aVisArea.Center()); 409 Size aObjSize(pNewDBField->GetLogicRect().GetSize()); 410 aObjPos.X() -= aObjSize.Width() / 2; 411 aObjPos.Y() -= aObjSize.Height() / 2; 412 Rectangle aNewObjectRectangle(aObjPos, aObjSize); 413 414 pNewDBField->SetLogicRect(aNewObjectRectangle); 415 416 // controls must be on control layer, groups on front layer 417 if ( pNewDBField->ISA(SdrUnoObj) ) 418 pNewDBField->NbcSetLayer(SC_LAYER_CONTROLS); 419 else 420 pNewDBField->NbcSetLayer(SC_LAYER_FRONT); 421 if (pNewDBField->ISA(SdrObjGroup)) 422 { 423 SdrObjListIter aIter( *pNewDBField, IM_DEEPWITHGROUPS ); 424 SdrObject* pSubObj = aIter.Next(); 425 while (pSubObj) 426 { 427 if ( pSubObj->ISA(SdrUnoObj) ) 428 pSubObj->NbcSetLayer(SC_LAYER_CONTROLS); 429 else 430 pSubObj->NbcSetLayer(SC_LAYER_FRONT); 431 pSubObj = aIter.Next(); 432 } 433 } 434 435 pView->InsertObjectAtView(pNewDBField, *pPageView); 436 } 437 } 438 } 439 rReq.Done(); 440 } 441 break; 442 443 case SID_FONTWORK_GALLERY_FLOATER: 444 svx::FontworkBar::execute( pView, rReq, GetViewFrame()->GetBindings() ); 445 rReq.Ignore(); 446 break; 447 } 448 } 449 450 void ScTabViewShell::GetDrawInsState(SfxItemSet &rSet) 451 { 452 sal_Bool bOle = GetViewFrame()->GetFrame().IsInPlace(); 453 sal_Bool bTabProt = GetViewData()->GetDocument()->IsTabProtected(GetViewData()->GetTabNo()); 454 ScDocShell* pDocShell = ( GetViewData() ? GetViewData()->GetDocShell() : NULL ); 455 bool bShared = ( pDocShell ? pDocShell->IsDocShared() : false ); 456 457 SfxWhichIter aIter(rSet); 458 sal_uInt16 nWhich = aIter.FirstWhich(); 459 while ( nWhich ) 460 { 461 switch ( nWhich ) 462 { 463 case SID_INSERT_DIAGRAM: 464 if ( bOle || bTabProt || !SvtModuleOptions().IsChart() || bShared ) 465 rSet.DisableItem( nWhich ); 466 break; 467 468 case SID_INSERT_SMATH: 469 if ( bOle || bTabProt || !SvtModuleOptions().IsMath() || bShared ) 470 rSet.DisableItem( nWhich ); 471 break; 472 473 case SID_INSERT_OBJECT: 474 case SID_INSERT_PLUGIN: 475 case SID_INSERT_FLOATINGFRAME: 476 if ( bOle || bTabProt || bShared ) 477 rSet.DisableItem( nWhich ); 478 break; 479 480 case SID_INSERT_SOUND: 481 case SID_INSERT_VIDEO: 482 /* #i102735# discussed with NN: removed for performance reasons 483 || !SvxPluginFileDlg::IsAvailable(nWhich) 484 */ 485 if ( bOle || bTabProt || bShared ) 486 rSet.DisableItem( nWhich ); 487 break; 488 489 case SID_INSERT_GRAPHIC: 490 case SID_INSERT_AVMEDIA: 491 case SID_FONTWORK_GALLERY_FLOATER: 492 if ( bTabProt || bShared ) 493 rSet.DisableItem( nWhich ); 494 break; 495 496 case SID_LINKS: 497 { 498 if (GetViewData()->GetDocument()->GetLinkManager()->GetLinks().Count() == 0 ) 499 rSet.DisableItem( SID_LINKS ); 500 } 501 break; 502 } 503 nWhich = aIter.NextWhich(); 504 } 505 } 506 507 508 //------------------------------------------------------------------ 509 510 void ScTabViewShell::ExecuteUndo(SfxRequest& rReq) 511 { 512 SfxShell* pSh = GetViewData()->GetDispatcher().GetShell(0); 513 ::svl::IUndoManager* pUndoManager = pSh->GetUndoManager(); 514 515 const SfxItemSet* pReqArgs = rReq.GetArgs(); 516 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 517 518 sal_uInt16 nSlot = rReq.GetSlot(); 519 switch ( nSlot ) 520 { 521 case SID_UNDO: 522 case SID_REDO: 523 if ( pUndoManager ) 524 { 525 sal_Bool bIsUndo = ( nSlot == SID_UNDO ); 526 527 sal_uInt16 nCount = 1; 528 const SfxPoolItem* pItem; 529 if ( pReqArgs && pReqArgs->GetItemState( nSlot, sal_True, &pItem ) == SFX_ITEM_SET ) 530 nCount = ((const SfxUInt16Item*)pItem)->GetValue(); 531 532 // lock paint for more than one cell undo action (not for editing within a cell) 533 sal_Bool bLockPaint = ( nCount > 1 && pUndoManager == GetUndoManager() ); 534 if ( bLockPaint ) 535 pDocSh->LockPaint(); 536 537 try 538 { 539 for (sal_uInt16 i=0; i<nCount; i++) 540 { 541 if ( bIsUndo ) 542 pUndoManager->Undo(); 543 else 544 pUndoManager->Redo(); 545 } 546 } 547 catch ( const uno::Exception& ) 548 { 549 // no need to handle. By definition, the UndoManager handled this by clearing the 550 // Undo/Redo stacks 551 } 552 553 if ( bLockPaint ) 554 pDocSh->UnlockPaint(); 555 556 GetViewFrame()->GetBindings().InvalidateAll(sal_False); 557 } 558 break; 559 // default: 560 // GetViewFrame()->ExecuteSlot( rReq ); 561 } 562 } 563 564 void ScTabViewShell::GetUndoState(SfxItemSet &rSet) 565 { 566 SfxShell* pSh = GetViewData()->GetDispatcher().GetShell(0); 567 ::svl::IUndoManager* pUndoManager = pSh->GetUndoManager(); 568 569 SfxWhichIter aIter(rSet); 570 sal_uInt16 nWhich = aIter.FirstWhich(); 571 while ( nWhich ) 572 { 573 switch (nWhich) 574 { 575 case SID_GETUNDOSTRINGS: 576 case SID_GETREDOSTRINGS: 577 { 578 SfxStringListItem aStrLst( nWhich ); 579 if ( pUndoManager ) 580 { 581 List* pList = aStrLst.GetList(); 582 sal_Bool bIsUndo = ( nWhich == SID_GETUNDOSTRINGS ); 583 size_t nCount = bIsUndo ? pUndoManager->GetUndoActionCount() : pUndoManager->GetRedoActionCount(); 584 for (size_t i=0; i<nCount; i++) 585 pList->Insert( new String( bIsUndo ? pUndoManager->GetUndoActionComment(i) : 586 pUndoManager->GetRedoActionComment(i) ), 587 LIST_APPEND ); 588 } 589 rSet.Put( aStrLst ); 590 } 591 break; 592 default: 593 // get state from sfx view frame 594 GetViewFrame()->GetSlotState( nWhich, NULL, &rSet ); 595 } 596 597 nWhich = aIter.NextWhich(); 598 } 599 } 600 601 602 603