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 Size aDrawSize = aRect.GetSize(); 142 143 MapMode aMapMode( MAP_100TH_MM ); 144 Size aOleSize = pObj->GetOrigObjSize( &aMapMode ); 145 146 if ( pClient->GetAspect() != embed::Aspects::MSOLE_ICON 147 && ( xObj->getStatus( pClient->GetAspect() ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE ) ) 148 { 149 // scale must always be 1 - change VisArea if different from client size 150 151 if ( aDrawSize != aOleSize ) 152 { 153 MapUnit aUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( pClient->GetAspect() ) ); 154 aOleSize = OutputDevice::LogicToLogic( aDrawSize, 155 MAP_100TH_MM, aUnit ); 156 awt::Size aSz( aOleSize.Width(), aOleSize.Height() ); 157 xObj->setVisualAreaSize( pClient->GetAspect(), aSz ); 158 } 159 Fraction aOne( 1, 1 ); 160 pClient->SetSizeScale( aOne, aOne ); 161 } 162 else 163 { 164 // calculate scale from client and VisArea size 165 166 Fraction aScaleWidth (aDrawSize.Width(), aOleSize.Width() ); 167 Fraction aScaleHeight(aDrawSize.Height(), aOleSize.Height() ); 168 aScaleWidth.ReduceInaccurate(10); // kompatibel zum SdrOle2Obj 169 aScaleHeight.ReduceInaccurate(10); 170 pClient->SetSizeScale(aScaleWidth,aScaleHeight); 171 } 172 173 // sichtbarer Ausschnitt wird nur inplace veraendert! 174 // the object area must be set after the scaling since it triggers the resizing 175 aRect.SetSize( aOleSize ); 176 pClient->SetObjArea( aRect ); 177 178 ((ScClient*)pClient)->SetGrafEdit( NULL ); 179 180 nErr = pClient->DoVerb( nVerb ); 181 bErrorShown = sal_True; 182 // SfxViewShell::DoVerb zeigt seine Fehlermeldungen selber an 183 184 SetNewVisArea(); 185 186 // attach listener to selection changes in chart that affect cell 187 // ranges, so those can be highlighted 188 // note: do that after DoVerb, so that the chart controller exists 189 if ( SvtModuleOptions().IsChart() ) 190 { 191 SvGlobalName aObjClsId ( xObj->getClassID() ); 192 if (SotExchange::IsChart( aObjClsId )) 193 { 194 try 195 { 196 uno::Reference < embed::XComponentSupplier > xSup( xObj, uno::UNO_QUERY_THROW ); 197 uno::Reference< chart2::data::XDataReceiver > xDataReceiver( 198 xSup->getComponent(), uno::UNO_QUERY_THROW ); 199 uno::Reference< chart2::data::XRangeHighlighter > xRangeHightlighter( 200 xDataReceiver->getRangeHighlighter()); 201 if( xRangeHightlighter.is()) 202 { 203 uno::Reference< view::XSelectionChangeListener > xListener( 204 new ScChartRangeSelectionListener( this )); 205 xRangeHightlighter->addSelectionChangeListener( xListener ); 206 } 207 } 208 catch( const uno::Exception & ) 209 { 210 DBG_ERROR( "Exception caught while querying chart" ); 211 } 212 } 213 } 214 } 215 } 216 if (nErr != ERRCODE_NONE && !bErrorShown) 217 ErrorHandler::HandleError(nErr); 218 219 //! SetDocumentName sollte schon im Sfx passieren ??? 220 //TODO/LATER: how "SetDocumentName"? 221 //xIPObj->SetDocumentName( GetViewData()->GetDocShell()->GetTitle() ); 222 223 return ( !(nErr & ERRCODE_ERROR_MASK) ); 224 } 225 226 ErrCode __EXPORT ScTabViewShell::DoVerb(long nVerb) 227 { 228 SdrView* pView = GetSdrView(); 229 if (!pView) 230 return ERRCODE_SO_NOTIMPL; // soll nicht sein 231 232 SdrOle2Obj* pOle2Obj = NULL; 233 SdrGrafObj* pGrafObj = NULL; 234 SdrObject* pObj = NULL; 235 ErrCode nErr = ERRCODE_NONE; 236 237 const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); 238 if (rMarkList.GetMarkCount() == 1) 239 { 240 pObj = rMarkList.GetMark(0)->GetMarkedSdrObj(); 241 if (pObj->GetObjIdentifier() == OBJ_OLE2) 242 pOle2Obj = (SdrOle2Obj*) pObj; 243 else if (pObj->GetObjIdentifier() == OBJ_GRAF) 244 { 245 pGrafObj = (SdrGrafObj*) pObj; 246 } 247 } 248 249 if (pOle2Obj) 250 { 251 ActivateObject( pOle2Obj, nVerb ); 252 } 253 else 254 { 255 DBG_ERROR("kein Objekt fuer Verb gefunden"); 256 } 257 258 return nErr; 259 } 260 261 void ScTabViewShell::DeactivateOle() 262 { 263 // deactivate inplace editing if currently active 264 265 ScModule* pScMod = SC_MOD(); 266 bool bUnoRefDialog = pScMod->IsRefDialogOpen() && pScMod->GetCurRefDlgId() == WID_SIMPLE_REF; 267 268 ScClient* pClient = (ScClient*) GetIPClient(); 269 if ( pClient && pClient->IsObjectInPlaceActive() && !bUnoRefDialog ) 270 pClient->DeactivateObject(); 271 } 272 273 void ScTabViewShell::ExecDrawIns(SfxRequest& rReq) 274 { 275 sal_uInt16 nSlot = rReq.GetSlot(); 276 if (nSlot != SID_OBJECTRESIZE ) 277 { 278 SC_MOD()->InputEnterHandler(); 279 UpdateInputHandler(); 280 } 281 282 // Rahmen fuer Chart einfuegen wird abgebrochen: 283 FuPoor* pPoor = GetDrawFuncPtr(); 284 if ( pPoor && pPoor->GetSlotID() == SID_DRAW_CHART ) 285 GetViewData()->GetDispatcher().Execute(SID_DRAW_CHART, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD); 286 287 MakeDrawLayer(); 288 289 SfxBindings& rBindings = GetViewFrame()->GetBindings(); 290 ScTabView* pTabView = GetViewData()->GetView(); 291 Window* pWin = pTabView->GetActiveWin(); 292 ScDrawView* pView = pTabView->GetScDrawView(); 293 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 294 ScDocument* pDoc = pDocSh->GetDocument(); 295 // SdrModel* pDrModel = pDocSh->MakeDrawLayer(); 296 SdrModel* pDrModel = pView->GetModel(); 297 298 switch ( nSlot ) 299 { 300 case SID_INSERT_GRAPHIC: 301 FuInsertGraphic(this, pWin, pView, pDrModel, rReq); 302 // shell is set in MarkListHasChanged 303 break; 304 305 case SID_INSERT_AVMEDIA: 306 FuInsertMedia(this, pWin, pView, pDrModel, rReq); 307 // shell is set in MarkListHasChanged 308 break; 309 310 case SID_INSERT_DIAGRAM: 311 FuInsertChart(this, pWin, pView, pDrModel, rReq); 312 //? SC_MOD()->SetFunctionDlg( NULL );//XXX 313 break; 314 315 case SID_INSERT_OBJECT: 316 case SID_INSERT_PLUGIN: 317 case SID_INSERT_SOUND: 318 case SID_INSERT_VIDEO: 319 case SID_INSERT_SMATH: 320 case SID_INSERT_FLOATINGFRAME: 321 FuInsertOLE(this, pWin, pView, pDrModel, rReq); 322 break; 323 324 case SID_OBJECTRESIZE: 325 { 326 // Der Server moechte die Clientgrosse verandern 327 328 SfxInPlaceClient* pClient = GetIPClient(); 329 330 if ( pClient && pClient->IsObjectInPlaceActive() ) 331 { 332 const SfxRectangleItem& rRect = 333 (SfxRectangleItem&)rReq.GetArgs()->Get(SID_OBJECTRESIZE); 334 Rectangle aRect( pWin->PixelToLogic( rRect.GetValue() ) ); 335 336 if ( pView->AreObjectsMarked() ) 337 { 338 const SdrMarkList& rMarkList = pView->GetMarkedObjectList(); 339 340 if (rMarkList.GetMarkCount() == 1) 341 { 342 SdrMark* pMark = rMarkList.GetMark(0); 343 SdrObject* pObj = pMark->GetMarkedSdrObj(); 344 345 sal_uInt16 nSdrObjKind = pObj->GetObjIdentifier(); 346 347 if (nSdrObjKind == OBJ_OLE2) 348 { 349 if ( ( (SdrOle2Obj*) pObj)->GetObjRef().is() ) 350 { 351 pObj->SetLogicRect(aRect); 352 } 353 } 354 } 355 } 356 } 357 } 358 break; 359 360 case SID_LINKS: 361 { 362 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); 363 SfxAbstractLinksDialog* pDlg = pFact->CreateLinksDialog( pWin, pDoc->GetLinkManager() ); 364 if ( pDlg ) 365 { 366 pDlg->Execute(); 367 rBindings.Invalidate( nSlot ); 368 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator 369 rReq.Done(); 370 } 371 } 372 break; 373 374 // #98721# 375 case SID_FM_CREATE_FIELDCONTROL: 376 { 377 SFX_REQUEST_ARG( rReq, pDescriptorItem, SfxUnoAnyItem, SID_FM_DATACCESS_DESCRIPTOR, sal_False ); 378 DBG_ASSERT( pDescriptorItem, "SID_FM_CREATE_FIELDCONTROL: invalid request args!" ); 379 380 if(pDescriptorItem) 381 { 382 //! merge with ScViewFunc::PasteDataFormat (SOT_FORMATSTR_ID_SBA_FIELDDATAEXCHANGE)? 383 384 ScDrawView* pDrView = GetScDrawView(); 385 SdrPageView* pPageView = pDrView ? pDrView->GetSdrPageView() : NULL; 386 if(pPageView) 387 { 388 ::svx::ODataAccessDescriptor aDescriptor(pDescriptorItem->GetValue()); 389 SdrObject* pNewDBField = pDrView->CreateFieldControl(aDescriptor); 390 391 if(pNewDBField) 392 { 393 Rectangle aVisArea = pWin->PixelToLogic(Rectangle(Point(0,0), pWin->GetOutputSizePixel())); 394 Point aObjPos(aVisArea.Center()); 395 Size aObjSize(pNewDBField->GetLogicRect().GetSize()); 396 aObjPos.X() -= aObjSize.Width() / 2; 397 aObjPos.Y() -= aObjSize.Height() / 2; 398 Rectangle aNewObjectRectangle(aObjPos, aObjSize); 399 400 pNewDBField->SetLogicRect(aNewObjectRectangle); 401 402 // controls must be on control layer, groups on front layer 403 if ( pNewDBField->ISA(SdrUnoObj) ) 404 pNewDBField->NbcSetLayer(SC_LAYER_CONTROLS); 405 else 406 pNewDBField->NbcSetLayer(SC_LAYER_FRONT); 407 if (pNewDBField->ISA(SdrObjGroup)) 408 { 409 SdrObjListIter aIter( *pNewDBField, IM_DEEPWITHGROUPS ); 410 SdrObject* pSubObj = aIter.Next(); 411 while (pSubObj) 412 { 413 if ( pSubObj->ISA(SdrUnoObj) ) 414 pSubObj->NbcSetLayer(SC_LAYER_CONTROLS); 415 else 416 pSubObj->NbcSetLayer(SC_LAYER_FRONT); 417 pSubObj = aIter.Next(); 418 } 419 } 420 421 pView->InsertObjectAtView(pNewDBField, *pPageView); 422 } 423 } 424 } 425 rReq.Done(); 426 } 427 break; 428 429 case SID_FONTWORK_GALLERY_FLOATER: 430 svx::FontworkBar::execute( pView, rReq, GetViewFrame()->GetBindings() ); 431 rReq.Ignore(); 432 break; 433 } 434 } 435 436 void ScTabViewShell::GetDrawInsState(SfxItemSet &rSet) 437 { 438 sal_Bool bOle = GetViewFrame()->GetFrame().IsInPlace(); 439 sal_Bool bTabProt = GetViewData()->GetDocument()->IsTabProtected(GetViewData()->GetTabNo()); 440 ScDocShell* pDocShell = ( GetViewData() ? GetViewData()->GetDocShell() : NULL ); 441 bool bShared = ( pDocShell ? pDocShell->IsDocShared() : false ); 442 443 SfxWhichIter aIter(rSet); 444 sal_uInt16 nWhich = aIter.FirstWhich(); 445 while ( nWhich ) 446 { 447 switch ( nWhich ) 448 { 449 case SID_INSERT_DIAGRAM: 450 if ( bOle || bTabProt || !SvtModuleOptions().IsChart() || bShared ) 451 rSet.DisableItem( nWhich ); 452 break; 453 454 case SID_INSERT_SMATH: 455 if ( bOle || bTabProt || !SvtModuleOptions().IsMath() || bShared ) 456 rSet.DisableItem( nWhich ); 457 break; 458 459 case SID_INSERT_OBJECT: 460 case SID_INSERT_PLUGIN: 461 case SID_INSERT_FLOATINGFRAME: 462 if ( bOle || bTabProt || bShared ) 463 rSet.DisableItem( nWhich ); 464 break; 465 466 case SID_INSERT_SOUND: 467 case SID_INSERT_VIDEO: 468 /* #i102735# discussed with NN: removed for performance reasons 469 || !SvxPluginFileDlg::IsAvailable(nWhich) 470 */ 471 if ( bOle || bTabProt || bShared ) 472 rSet.DisableItem( nWhich ); 473 break; 474 475 case SID_INSERT_GRAPHIC: 476 case SID_INSERT_AVMEDIA: 477 case SID_FONTWORK_GALLERY_FLOATER: 478 if ( bTabProt || bShared ) 479 rSet.DisableItem( nWhich ); 480 break; 481 482 case SID_LINKS: 483 { 484 if (GetViewData()->GetDocument()->GetLinkManager()->GetLinks().Count() == 0 ) 485 rSet.DisableItem( SID_LINKS ); 486 } 487 break; 488 } 489 nWhich = aIter.NextWhich(); 490 } 491 } 492 493 494 //------------------------------------------------------------------ 495 496 void ScTabViewShell::ExecuteUndo(SfxRequest& rReq) 497 { 498 SfxShell* pSh = GetViewData()->GetDispatcher().GetShell(0); 499 ::svl::IUndoManager* pUndoManager = pSh->GetUndoManager(); 500 501 const SfxItemSet* pReqArgs = rReq.GetArgs(); 502 ScDocShell* pDocSh = GetViewData()->GetDocShell(); 503 504 sal_uInt16 nSlot = rReq.GetSlot(); 505 switch ( nSlot ) 506 { 507 case SID_UNDO: 508 case SID_REDO: 509 if ( pUndoManager ) 510 { 511 sal_Bool bIsUndo = ( nSlot == SID_UNDO ); 512 513 sal_uInt16 nCount = 1; 514 const SfxPoolItem* pItem; 515 if ( pReqArgs && pReqArgs->GetItemState( nSlot, sal_True, &pItem ) == SFX_ITEM_SET ) 516 nCount = ((const SfxUInt16Item*)pItem)->GetValue(); 517 518 // lock paint for more than one cell undo action (not for editing within a cell) 519 sal_Bool bLockPaint = ( nCount > 1 && pUndoManager == GetUndoManager() ); 520 if ( bLockPaint ) 521 pDocSh->LockPaint(); 522 523 try 524 { 525 for (sal_uInt16 i=0; i<nCount; i++) 526 { 527 if ( bIsUndo ) 528 pUndoManager->Undo(); 529 else 530 pUndoManager->Redo(); 531 } 532 } 533 catch ( const uno::Exception& ) 534 { 535 // no need to handle. By definition, the UndoManager handled this by clearing the 536 // Undo/Redo stacks 537 } 538 539 if ( bLockPaint ) 540 pDocSh->UnlockPaint(); 541 542 GetViewFrame()->GetBindings().InvalidateAll(sal_False); 543 } 544 break; 545 // default: 546 // GetViewFrame()->ExecuteSlot( rReq ); 547 } 548 } 549 550 void ScTabViewShell::GetUndoState(SfxItemSet &rSet) 551 { 552 SfxShell* pSh = GetViewData()->GetDispatcher().GetShell(0); 553 ::svl::IUndoManager* pUndoManager = pSh->GetUndoManager(); 554 555 SfxWhichIter aIter(rSet); 556 sal_uInt16 nWhich = aIter.FirstWhich(); 557 while ( nWhich ) 558 { 559 switch (nWhich) 560 { 561 case SID_GETUNDOSTRINGS: 562 case SID_GETREDOSTRINGS: 563 { 564 SfxStringListItem aStrLst( nWhich ); 565 if ( pUndoManager ) 566 { 567 List* pList = aStrLst.GetList(); 568 sal_Bool bIsUndo = ( nWhich == SID_GETUNDOSTRINGS ); 569 size_t nCount = bIsUndo ? pUndoManager->GetUndoActionCount() : pUndoManager->GetRedoActionCount(); 570 for (size_t i=0; i<nCount; i++) 571 pList->Insert( new String( bIsUndo ? pUndoManager->GetUndoActionComment(i) : 572 pUndoManager->GetRedoActionComment(i) ), 573 LIST_APPEND ); 574 } 575 rSet.Put( aStrLst ); 576 } 577 break; 578 default: 579 // get state from sfx view frame 580 GetViewFrame()->GetSlotState( nWhich, NULL, &rSet ); 581 } 582 583 nWhich = aIter.NextWhich(); 584 } 585 } 586 587 588 589