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 //! SetDocumentName sollte schon im Sfx passieren ??? 229 //TODO/LATER: how "SetDocumentName"? 230 //xIPObj->SetDocumentName( GetViewData()->GetDocShell()->GetTitle() ); 231 232 return ( !(nErr & ERRCODE_ERROR_MASK) ); 233 } 234 235 ErrCode __EXPORT ScTabViewShell::DoVerb(long nVerb) 236 { 237 SdrView* pView = GetSdrView(); 238 if (!pView) 239 return ERRCODE_SO_NOTIMPL; // soll nicht sein 240 241 SdrOle2Obj* pOle2Obj = NULL; 242 SdrGrafObj* pGrafObj = NULL; 243 SdrObject* pObj = NULL; 244 ErrCode nErr = ERRCODE_NONE; 245 246 const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); 247 if (rMarkList.GetMarkCount() == 1) 248 { 249 pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); 250 if (pObj->GetObjIdentifier() == OBJ_OLE2) 251 pOle2Obj = (SdrOle2Obj*) pObj; 252 else if (pObj->GetObjIdentifier() == OBJ_GRAF) 253 { 254 pGrafObj = (SdrGrafObj*) pObj; 255 } 256 } 257 258 if (pOle2Obj) 259 { 260 ActivateObject( pOle2Obj, nVerb ); 261 } 262 else 263 { 264 DBG_ERROR("kein Objekt fuer Verb gefunden"); 265 } 266 267 return nErr; 268 } 269 270 void ScTabViewShell::DeactivateOle() 271 { 272 // deactivate inplace editing if currently active 273 274 ScModule* pScMod = SC_MOD(); 275 bool bUnoRefDialog = pScMod->IsRefDialogOpen() && pScMod->GetCurRefDlgId() == WID_SIMPLE_REF; 276 277 ScClient* pClient = (ScClient*) GetIPClient(); 278 if ( pClient && pClient->IsObjectInPlaceActive() && !bUnoRefDialog ) 279 pClient->DeactivateObject(); 280 } 281 282 void ScTabViewShell::ExecDrawIns(SfxRequest& rReq) 283 { 284 sal_uInt16 nSlot = rReq.GetSlot(); 285 if (nSlot != SID_OBJECTRESIZE ) 286 { 287 SC_MOD()->InputEnterHandler(); 288 UpdateInputHandler(); 289 } 290 291 // Rahmen fuer Chart einfuegen wird abgebrochen: 292 FuPoor* pPoor = GetDrawFuncPtr(); 293 if ( pPoor && pPoor->GetSlotID() == SID_DRAW_CHART ) 294 GetViewData()->GetDispatcher().Execute(SID_DRAW_CHART, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD); 295 296 MakeDrawLayer(); 297 298 SfxBindings& rBindings = GetViewFrame()->GetBindings(); 299 ScTabView* pTabView = GetViewData()->GetView(); 300 Window* pWin = pTabView->GetActiveWin(); 301 ScDrawView* pView = pTabView->GetScDrawView(); 302 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 303 ScDocument* pDoc = pDocSh->GetDocument(); 304 // SdrModel* pDrModel = pDocSh->MakeDrawLayer(); 305 SdrModel* pDrModel = pView->GetModel(); 306 307 switch ( nSlot ) 308 { 309 case SID_INSERT_GRAPHIC: 310 FuInsertGraphic(this, pWin, pView, pDrModel, rReq); 311 // shell is set in MarkListHasChanged 312 break; 313 314 case SID_INSERT_AVMEDIA: 315 FuInsertMedia(this, pWin, pView, pDrModel, rReq); 316 // shell is set in MarkListHasChanged 317 break; 318 319 case SID_INSERT_DIAGRAM: 320 FuInsertChart(this, pWin, pView, pDrModel, rReq); 321 //? SC_MOD()->SetFunctionDlg( NULL );//XXX 322 break; 323 324 case SID_INSERT_OBJECT: 325 case SID_INSERT_PLUGIN: 326 case SID_INSERT_SOUND: 327 case SID_INSERT_VIDEO: 328 case SID_INSERT_SMATH: 329 case SID_INSERT_FLOATINGFRAME: 330 FuInsertOLE(this, pWin, pView, pDrModel, rReq); 331 break; 332 333 case SID_OBJECTRESIZE: 334 { 335 // Der Server moechte die Clientgrosse verandern 336 337 SfxInPlaceClient* pClient = GetIPClient(); 338 339 if ( pClient && pClient->IsObjectInPlaceActive() ) 340 { 341 const SfxRectangleItem& rRect = 342 (SfxRectangleItem&)rReq.GetArgs()->Get(SID_OBJECTRESIZE); 343 Rectangle aRect( pWin->PixelToLogic( rRect.GetValue() ) ); 344 345 if ( pView->AreObjectsMarked() ) 346 { 347 const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); 348 349 if (rMarkList.GetMarkCount() == 1) 350 { 351 SdrMark* pMark = rMarkList.GetMark(0); 352 SdrObject* pObj = pMark->GetMarkedSdrObj(); 353 354 sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier(); 355 356 if (nSdrObjKind == OBJ_OLE2) 357 { 358 if ( ( (SdrOle2Obj*) pObj)->GetObjRef().is() ) 359 { 360 pObj->SetLogicRect(aRect); 361 } 362 } 363 } 364 } 365 } 366 } 367 break; 368 369 case SID_LINKS: 370 { 371 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); 372 SfxAbstractLinksDialog* pDlg = pFact->CreateLinksDialog( pWin, pDoc->GetLinkManager() ); 373 if ( pDlg ) 374 { 375 pDlg->Execute(); 376 rBindings.Invalidate( nSlot ); 377 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator 378 rReq.Done(); 379 } 380 } 381 break; 382 383 // #98721# 384 case SID_FM_CREATE_FIELDCONTROL: 385 { 386 SFX_REQUEST_ARG( rReq, pDescriptorItem, SfxUnoAnyItem, SID_FM_DATACCESS_DESCRIPTOR, sal_False ); 387 DBG_ASSERT( pDescriptorItem, "SID_FM_CREATE_FIELDCONTROL: invalid request args!" ); 388 389 if(pDescriptorItem) 390 { 391 //! merge with ScViewFunc::PasteDataFormat (SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE)? 392 393 ScDrawView* pDrView = GetScDrawView(); 394 SdrPageView* pPageView = pDrView ? pDrView->GetSdrPageView() : NULL; 395 if(pPageView) 396 { 397 ::svx::ODataAccessDescriptor aDescriptor(pDescriptorItem->GetValue()); 398 SdrObject* pNewDBField = pDrView->CreateFieldControl(aDescriptor); 399 400 if(pNewDBField) 401 { 402 Rectangle aVisArea = pWin->PixelToLogic(Rectangle(Point(0,0), pWin->GetOutputSizePixel())); 403 Point aObjPos(aVisArea.Center()); 404 Size aObjSize(pNewDBField->GetLogicRect().GetSize()); 405 aObjPos.X() -= aObjSize.Width() / 2; 406 aObjPos.Y() -= aObjSize.Height() / 2; 407 Rectangle aNewObjectRectangle(aObjPos, aObjSize); 408 409 pNewDBField->SetLogicRect(aNewObjectRectangle); 410 411 // controls must be on control layer, groups on front layer 412 if ( pNewDBField->ISA(SdrUnoObj) ) 413 pNewDBField->NbcSetLayer(SC_LAYER_CONTROLS); 414 else 415 pNewDBField->NbcSetLayer(SC_LAYER_FRONT); 416 if (pNewDBField->ISA(SdrObjGroup)) 417 { 418 SdrObjListIter aIter( *pNewDBField, IM_DEEPWITHGROUPS ); 419 SdrObject* pSubObj = aIter.Next(); 420 while (pSubObj) 421 { 422 if ( pSubObj->ISA(SdrUnoObj) ) 423 pSubObj->NbcSetLayer(SC_LAYER_CONTROLS); 424 else 425 pSubObj->NbcSetLayer(SC_LAYER_FRONT); 426 pSubObj = aIter.Next(); 427 } 428 } 429 430 pView->InsertObjectAtView(pNewDBField, *pPageView); 431 } 432 } 433 } 434 rReq.Done(); 435 } 436 break; 437 438 case SID_FONTWORK_GALLERY_FLOATER: 439 svx::FontworkBar::execute( pView, rReq, GetViewFrame()->GetBindings() ); 440 rReq.Ignore(); 441 break; 442 } 443 } 444 445 void ScTabViewShell::GetDrawInsState(SfxItemSet &rSet) 446 { 447 sal_Bool bOle = GetViewFrame()->GetFrame().IsInPlace(); 448 sal_Bool bTabProt = GetViewData()->GetDocument()->IsTabProtected(GetViewData()->GetTabNo()); 449 ScDocShell* pDocShell = ( GetViewData() ? GetViewData()->GetDocShell() : NULL ); 450 bool bShared = ( pDocShell ? pDocShell->IsDocShared() : false ); 451 452 SfxWhichIter aIter(rSet); 453 sal_uInt16 nWhich = aIter.FirstWhich(); 454 while ( nWhich ) 455 { 456 switch ( nWhich ) 457 { 458 case SID_INSERT_DIAGRAM: 459 if ( bOle || bTabProt || !SvtModuleOptions().IsChart() || bShared ) 460 rSet.DisableItem( nWhich ); 461 break; 462 463 case SID_INSERT_SMATH: 464 if ( bOle || bTabProt || !SvtModuleOptions().IsMath() || bShared ) 465 rSet.DisableItem( nWhich ); 466 break; 467 468 case SID_INSERT_OBJECT: 469 case SID_INSERT_PLUGIN: 470 case SID_INSERT_FLOATINGFRAME: 471 if ( bOle || bTabProt || bShared ) 472 rSet.DisableItem( nWhich ); 473 break; 474 475 case SID_INSERT_SOUND: 476 case SID_INSERT_VIDEO: 477 /* #i102735# discussed with NN: removed for performance reasons 478 || !SvxPluginFileDlg::IsAvailable(nWhich) 479 */ 480 if ( bOle || bTabProt || bShared ) 481 rSet.DisableItem( nWhich ); 482 break; 483 484 case SID_INSERT_GRAPHIC: 485 case SID_INSERT_AVMEDIA: 486 case SID_FONTWORK_GALLERY_FLOATER: 487 if ( bTabProt || bShared ) 488 rSet.DisableItem( nWhich ); 489 break; 490 491 case SID_LINKS: 492 { 493 if (GetViewData()->GetDocument()->GetLinkManager()->GetLinks().Count() == 0 ) 494 rSet.DisableItem( SID_LINKS ); 495 } 496 break; 497 } 498 nWhich = aIter.NextWhich(); 499 } 500 } 501 502 503 //------------------------------------------------------------------ 504 505 void ScTabViewShell::ExecuteUndo(SfxRequest& rReq) 506 { 507 SfxShell* pSh = GetViewData()->GetDispatcher().GetShell(0); 508 ::svl::IUndoManager* pUndoManager = pSh->GetUndoManager(); 509 510 const SfxItemSet* pReqArgs = rReq.GetArgs(); 511 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 512 513 sal_uInt16 nSlot = rReq.GetSlot(); 514 switch ( nSlot ) 515 { 516 case SID_UNDO: 517 case SID_REDO: 518 if ( pUndoManager ) 519 { 520 sal_Bool bIsUndo = ( nSlot == SID_UNDO ); 521 522 sal_uInt16 nCount = 1; 523 const SfxPoolItem* pItem; 524 if ( pReqArgs && pReqArgs->GetItemState( nSlot, sal_True, &pItem ) == SFX_ITEM_SET ) 525 nCount = ((const SfxUInt16Item*)pItem)->GetValue(); 526 527 // lock paint for more than one cell undo action (not for editing within a cell) 528 sal_Bool bLockPaint = ( nCount > 1 && pUndoManager == GetUndoManager() ); 529 if ( bLockPaint ) 530 pDocSh->LockPaint(); 531 532 try 533 { 534 for (sal_uInt16 i=0; i<nCount; i++) 535 { 536 if ( bIsUndo ) 537 pUndoManager->Undo(); 538 else 539 pUndoManager->Redo(); 540 } 541 } 542 catch ( const uno::Exception& ) 543 { 544 // no need to handle. By definition, the UndoManager handled this by clearing the 545 // Undo/Redo stacks 546 } 547 548 if ( bLockPaint ) 549 pDocSh->UnlockPaint(); 550 551 GetViewFrame()->GetBindings().InvalidateAll(sal_False); 552 } 553 break; 554 // default: 555 // GetViewFrame()->ExecuteSlot( rReq ); 556 } 557 } 558 559 void ScTabViewShell::GetUndoState(SfxItemSet &rSet) 560 { 561 SfxShell* pSh = GetViewData()->GetDispatcher().GetShell(0); 562 ::svl::IUndoManager* pUndoManager = pSh->GetUndoManager(); 563 564 SfxWhichIter aIter(rSet); 565 sal_uInt16 nWhich = aIter.FirstWhich(); 566 while ( nWhich ) 567 { 568 switch (nWhich) 569 { 570 case SID_GETUNDOSTRINGS: 571 case SID_GETREDOSTRINGS: 572 { 573 SfxStringListItem aStrLst( nWhich ); 574 if ( pUndoManager ) 575 { 576 List* pList = aStrLst.GetList(); 577 sal_Bool bIsUndo = ( nWhich == SID_GETUNDOSTRINGS ); 578 size_t nCount = bIsUndo ? pUndoManager->GetUndoActionCount() : pUndoManager->GetRedoActionCount(); 579 for (size_t i=0; i<nCount; i++) 580 pList->Insert( new String( bIsUndo ? pUndoManager->GetUndoActionComment(i) : 581 pUndoManager->GetRedoActionComment(i) ), 582 LIST_APPEND ); 583 } 584 rSet.Put( aStrLst ); 585 } 586 break; 587 default: 588 // get state from sfx view frame 589 GetViewFrame()->GetSlotState( nWhich, NULL, &rSet ); 590 } 591 592 nWhich = aIter.NextWhich(); 593 } 594 } 595 596 597 598