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