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_sfx2.hxx" 30 31 #include "impviewframe.hxx" 32 #include "statcach.hxx" 33 #include "sfx2/viewfac.hxx" 34 #include "workwin.hxx" 35 36 #include "sfx2/app.hxx" 37 #include "sfx2/bindings.hxx" 38 #include "sfx2/ctrlitem.hxx" 39 #include "sfx2/dispatch.hxx" 40 #include "sfx2/docfac.hxx" 41 #include "sfx2/docfile.hxx" 42 #include "sfx2/objitem.hxx" 43 #include "sfx2/objsh.hxx" 44 #include "sfx2/request.hxx" 45 #include "sfx2/viewfrm.hxx" 46 #include "sfx2/viewsh.hxx" 47 48 #include <com/sun/star/beans/NamedValue.hpp> 49 #include <com/sun/star/beans/XMaterialHolder.hpp> 50 #include <com/sun/star/util/XCloseable.hpp> 51 52 #include <comphelper/componentcontext.hxx> 53 #include <comphelper/namedvaluecollection.hxx> 54 #include <comphelper/processfactory.hxx> 55 #include <svtools/asynclink.hxx> 56 #include <svl/eitem.hxx> 57 #include <svl/intitem.hxx> 58 #include <svl/rectitem.hxx> 59 #include <svl/stritem.hxx> 60 #include <tools/diagnose_ex.h> 61 #include <tools/urlobj.hxx> 62 #include <unotools/bootstrap.hxx> 63 #include <unotools/configmgr.hxx> 64 #include <vcl/window.hxx> 65 66 using namespace ::com::sun::star; 67 using namespace ::com::sun::star::uno; 68 using namespace ::com::sun::star::frame; 69 using namespace ::com::sun::star::util; 70 using namespace ::com::sun::star::container; 71 using namespace ::com::sun::star::beans; 72 using ::com::sun::star::lang::XMultiServiceFactory; 73 using ::com::sun::star::lang::XComponent; 74 75 //------------------------------------------------------------------------ 76 77 static ::rtl::OUString GetModuleName_Impl( const ::rtl::OUString& sDocService ) 78 { 79 uno::Reference< container::XNameAccess > xMM( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("com.sun.star.frame.ModuleManager")), uno::UNO_QUERY ); 80 ::rtl::OUString sVar; 81 if ( !xMM.is() ) 82 return sVar; 83 84 try 85 { 86 ::comphelper::NamedValueCollection aAnalyzer( xMM->getByName( sDocService ) ); 87 sVar = aAnalyzer.getOrDefault( "ooSetupFactoryUIName", ::rtl::OUString() ); 88 } 89 catch( uno::Exception& ) 90 { 91 sVar = ::rtl::OUString(); 92 } 93 94 return sVar; 95 } 96 97 //-------------------------------------------------------------------- 98 void SfxFrameViewWindow_Impl::StateChanged( StateChangedType nStateChange ) 99 { 100 if ( nStateChange == STATE_CHANGE_INITSHOW ) 101 { 102 SfxObjectShell* pDoc = pFrame->GetObjectShell(); 103 if ( pDoc && !pFrame->IsVisible() ) 104 pFrame->Show(); 105 106 pFrame->Resize(); 107 } 108 else 109 Window::StateChanged( nStateChange ); 110 } 111 112 void SfxFrameViewWindow_Impl::Resize() 113 { 114 if ( IsReallyVisible() || IsReallyShown() || GetOutputSizePixel().Width() ) 115 pFrame->Resize(); 116 } 117 118 static String _getTabString() 119 { 120 String result; 121 122 Reference < XMaterialHolder > xHolder( 123 ::comphelper::getProcessServiceFactory()->createInstance( 124 DEFINE_CONST_UNICODE("com.sun.star.tab.tabreg") ), UNO_QUERY ); 125 if (xHolder.is()) 126 { 127 rtl::OUString aTabString; 128 Sequence< NamedValue > sMaterial; 129 if (xHolder->getMaterial() >>= sMaterial) { 130 for (int i=0; i < sMaterial.getLength(); i++) { 131 if ((sMaterial[i].Name.equalsAscii("title")) && 132 (sMaterial[i].Value >>= aTabString)) 133 { 134 result += ' '; 135 result += String(aTabString); 136 } 137 } 138 } 139 } 140 return result; 141 } 142 143 //======================================================================== 144 145 //-------------------------------------------------------------------- 146 String SfxViewFrame::UpdateTitle() 147 148 /* [Beschreibung] 149 150 Mit dieser Methode kann der SfxViewFrame gezwungen werden, sich sofort 151 den neuen Titel vom der <SfxObjectShell> zu besorgen. 152 153 [Anmerkung] 154 155 Dies ist z.B. dann notwendig, wenn man der SfxObjectShell als SfxListener 156 zuh"ort und dort auf den <SfxSimpleHint> SFX_HINT_TITLECHANGED reagieren 157 m"ochte, um dann die Titel seiner Views abzufragen. Diese Views (SfxTopViewFrames) 158 jedoch sind ebenfalls SfxListener und da die Reihenfolge der Benachrichtigung 159 nicht feststeht, mu\s deren Titel-Update vorab erzwungen werden. 160 161 162 [Beispiel] 163 164 void SwDocShell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) 165 { 166 if ( rHint.IsA(TYPE(SfxSimpleHint)) ) 167 { 168 switch( ( (SfxSimpleHint&) rHint ).GetId() ) 169 { 170 case SFX_HINT_TITLECHANGED: 171 for ( SfxViewFrame *pTop = SfxViewFrame::GetFirst( this ); 172 pTop; 173 pTop = SfxViewFrame::GetNext( this ); 174 { 175 pTop->UpdateTitle(); 176 ... pTop->GetName() ... 177 } 178 break; 179 ... 180 } 181 } 182 } 183 */ 184 185 { 186 DBG_CHKTHIS(SfxViewFrame, 0); 187 188 const SfxObjectFactory &rFact = GetObjectShell()->GetFactory(); 189 pImp->aFactoryName = String::CreateFromAscii( rFact.GetShortName() ); 190 191 SfxObjectShell *pObjSh = GetObjectShell(); 192 if ( !pObjSh ) 193 return String(); 194 195 // if ( pObjSh->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED ) 196 // // kein UpdateTitle mit Embedded-ObjectShell 197 // return String(); 198 199 const SfxMedium *pMedium = pObjSh->GetMedium(); 200 String aURL; 201 GetFrame(); // -Wall required?? 202 if ( pObjSh->HasName() ) 203 { 204 INetURLObject aTmp( pMedium->GetName() ); 205 aURL = aTmp.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); 206 } 207 208 if ( aURL != pImp->aActualURL ) 209 // URL hat sich ge"andert 210 pImp->aActualURL = aURL; 211 212 // gibt es noch eine weitere View? 213 sal_uInt16 nViews=0; 214 for ( SfxViewFrame *pView= GetFirst(pObjSh); 215 pView && nViews<2; 216 pView = GetNext(*pView,pObjSh) ) 217 if ( ( pView->GetFrameType() & SFXFRAME_HASTITLE ) && 218 !IsDowning_Impl()) 219 nViews++; 220 221 // Titel des Fensters 222 String aTitle; 223 if ( nViews == 2 || pImp->nDocViewNo > 1 ) 224 // dann die Nummer dranh"angen 225 aTitle = pObjSh->UpdateTitle( NULL, pImp->nDocViewNo ); 226 else 227 aTitle = pObjSh->UpdateTitle(); 228 229 // Name des SbxObjects 230 String aSbxName = pObjSh->SfxShell::GetName(); 231 if ( IsVisible() ) 232 { 233 aSbxName += ':'; 234 aSbxName += String::CreateFromInt32(pImp->nDocViewNo); 235 } 236 237 SetName( aSbxName ); 238 pImp->aFrameTitle = aTitle; 239 GetBindings().Invalidate( SID_FRAMETITLE ); 240 GetBindings().Invalidate( SID_CURRENT_URL ); 241 242 ::rtl::OUString aProductName; 243 ::utl::ConfigManager::GetDirectConfigProperty(::utl::ConfigManager::PRODUCTNAME) >>= aProductName; 244 245 aTitle += String::CreateFromAscii( " - " ); 246 aTitle += String(aProductName); 247 aTitle += ' '; 248 ::rtl::OUString aDocServiceName( GetObjectShell()->GetFactory().GetDocumentServiceName() ); 249 aTitle += String( GetModuleName_Impl( aDocServiceName ) ); 250 #ifdef DBG_UTIL 251 ::rtl::OUString aDefault; 252 aTitle += DEFINE_CONST_UNICODE(" ["); 253 String aVerId( utl::Bootstrap::getBuildIdData( aDefault )); 254 aTitle += aVerId; 255 aTitle += ']'; 256 #endif 257 258 // append TAB string if available 259 aTitle += _getTabString(); 260 261 GetBindings().Invalidate( SID_NEWDOCDIRECT ); 262 263 /* AS_TITLE 264 Window* pWindow = GetFrame()->GetTopWindow_Impl(); 265 if ( pWindow && pWindow->GetText() != aTitle ) 266 pWindow->SetText( aTitle ); 267 */ 268 return aTitle; 269 } 270 271 void SfxViewFrame::Exec_Impl(SfxRequest &rReq ) 272 { 273 // Wenn gerade die Shells ausgetauscht werden... 274 if ( !GetObjectShell() || !GetViewShell() ) 275 return; 276 277 switch ( rReq.GetSlot() ) 278 { 279 case SID_SHOWPOPUPS : 280 { 281 SFX_REQUEST_ARG(rReq, pShowItem, SfxBoolItem, SID_SHOWPOPUPS, sal_False); 282 sal_Bool bShow = pShowItem ? pShowItem->GetValue() : sal_True; 283 SFX_REQUEST_ARG(rReq, pIdItem, SfxUInt16Item, SID_CONFIGITEMID, sal_False); 284 sal_uInt16 nId = pIdItem ? pIdItem->GetValue() : 0; 285 286 // ausfuehren 287 SfxWorkWindow *pWorkWin = GetFrame().GetWorkWindow_Impl(); 288 if ( bShow ) 289 { 290 // Zuerst die Floats auch anzeigbar machen 291 pWorkWin->MakeChildsVisible_Impl( bShow ); 292 GetDispatcher()->Update_Impl( sal_True ); 293 294 // Dann anzeigen 295 GetBindings().HidePopups( !bShow ); 296 } 297 else 298 { 299 // Alles hiden 300 SfxBindings *pBind = &GetBindings(); 301 while ( pBind ) 302 { 303 pBind->HidePopupCtrls_Impl( !bShow ); 304 pBind = pBind->GetSubBindings_Impl(); 305 } 306 307 pWorkWin->HidePopups_Impl( !bShow, sal_True, nId ); 308 pWorkWin->MakeChildsVisible_Impl( bShow ); 309 } 310 311 Invalidate( rReq.GetSlot() ); 312 rReq.Done(); 313 break; 314 } 315 316 case SID_ACTIVATE: 317 { 318 MakeActive_Impl( sal_True ); 319 rReq.SetReturnValue( SfxObjectItem( 0, this ) ); 320 break; 321 } 322 323 case SID_NEWDOCDIRECT : 324 { 325 SFX_REQUEST_ARG( rReq, pFactoryItem, SfxStringItem, SID_NEWDOCDIRECT, sal_False); 326 String aFactName; 327 if ( pFactoryItem ) 328 aFactName = pFactoryItem->GetValue(); 329 else if ( pImp->aFactoryName.Len() ) 330 aFactName = pImp->aFactoryName; 331 else 332 { 333 DBG_ERROR("Missing argument!"); 334 break; 335 } 336 337 SfxRequest aReq( SID_OPENDOC, SFX_CALLMODE_SYNCHRON, GetPool() ); 338 String aFact = String::CreateFromAscii("private:factory/"); 339 aFact += aFactName; 340 aReq.AppendItem( SfxStringItem( SID_FILE_NAME, aFact ) ); 341 aReq.AppendItem( SfxFrameItem( SID_DOCFRAME, &GetFrame() ) ); 342 aReq.AppendItem( SfxStringItem( SID_TARGETNAME, String::CreateFromAscii( "_blank" ) ) ); 343 SFX_APP()->ExecuteSlot( aReq ); 344 const SfxViewFrameItem* pItem = PTR_CAST( SfxViewFrameItem, aReq.GetReturnValue() ); 345 if ( pItem ) 346 rReq.SetReturnValue( SfxFrameItem( 0, pItem->GetFrame() ) ); 347 break; 348 } 349 350 case SID_CLOSEWIN: 351 { 352 // disable CloseWin, if frame is not a task 353 Reference < XCloseable > xTask( GetFrame().GetFrameInterface(), UNO_QUERY ); 354 if ( !xTask.is() ) 355 break; 356 357 if ( GetViewShell()->PrepareClose() ) 358 { 359 // weitere Views auf dasselbe Doc? 360 SfxObjectShell *pDocSh = GetObjectShell(); 361 int bOther = sal_False; 362 for ( const SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocSh ); 363 !bOther && pFrame; 364 pFrame = SfxViewFrame::GetNext( *pFrame, pDocSh ) ) 365 bOther = (pFrame != this); 366 367 // Doc braucht nur gefragt zu werden, wenn keine weitere View 368 sal_Bool bClosed = sal_False; 369 sal_Bool bUI = sal_True; 370 if ( ( bOther || pDocSh->PrepareClose( bUI ) ) ) 371 { 372 if ( !bOther ) 373 pDocSh->SetModified( sal_False ); 374 rReq.Done(); // unbedingt vor Close() rufen! 375 bClosed = sal_False; 376 try 377 { 378 xTask->close(sal_True); 379 bClosed = sal_True; 380 } 381 catch( CloseVetoException& ) 382 { 383 bClosed = sal_False; 384 } 385 } 386 387 rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bClosed )); 388 } 389 return; 390 } 391 } 392 393 rReq.Done(); 394 } 395 396 void SfxViewFrame::GetState_Impl( SfxItemSet &rSet ) 397 { 398 SfxObjectShell *pDocSh = GetObjectShell(); 399 400 if ( !pDocSh ) 401 return; 402 403 const sal_uInt16 *pRanges = rSet.GetRanges(); 404 DBG_ASSERT(pRanges, "Set ohne Bereich"); 405 while ( *pRanges ) 406 { 407 for ( sal_uInt16 nWhich = *pRanges++; nWhich <= *pRanges; ++nWhich ) 408 { 409 switch(nWhich) 410 { 411 case SID_NEWDOCDIRECT : 412 { 413 if ( pImp->aFactoryName.Len() ) 414 { 415 String aFact = String::CreateFromAscii("private:factory/"); 416 aFact += pImp->aFactoryName; 417 rSet.Put( SfxStringItem( nWhich, aFact ) ); 418 } 419 break; 420 } 421 422 case SID_NEWWINDOW: 423 rSet.DisableItem(nWhich); 424 break; 425 426 case SID_CLOSEWIN: 427 { 428 // disable CloseWin, if frame is not a task 429 Reference < XCloseable > xTask( GetFrame().GetFrameInterface(), UNO_QUERY ); 430 if ( !xTask.is() ) 431 rSet.DisableItem(nWhich); 432 break; 433 } 434 435 case SID_SHOWPOPUPS : 436 break; 437 438 case SID_OBJECT: 439 if ( GetViewShell() && GetViewShell()->GetVerbs().getLength() && !GetObjectShell()->IsInPlaceActive() ) 440 { 441 uno::Any aAny; 442 aAny <<= GetViewShell()->GetVerbs(); 443 rSet.Put( SfxUnoAnyItem( sal_uInt16( SID_OBJECT ), aAny ) ); 444 } 445 else 446 rSet.DisableItem( SID_OBJECT ); 447 break; 448 449 default: 450 DBG_ERROR( "invalid message-id" ); 451 } 452 } 453 ++pRanges; 454 } 455 } 456 457 void SfxViewFrame::INetExecute_Impl( SfxRequest &rRequest ) 458 { 459 sal_uInt16 nSlotId = rRequest.GetSlot(); 460 switch( nSlotId ) 461 { 462 case SID_BROWSE_FORWARD: 463 case SID_BROWSE_BACKWARD: 464 OSL_ENSURE( false, "SfxViewFrame::INetExecute_Impl: SID_BROWSE_FORWARD/BACKWARD are dead!" ); 465 break; 466 case SID_CREATELINK: 467 { 468 /*! (pb) we need new implementation to create a link 469 */ 470 break; 471 } 472 case SID_FOCUSURLBOX: 473 { 474 SfxStateCache *pCache = GetBindings().GetAnyStateCache_Impl( SID_OPENURL ); 475 if( pCache ) 476 { 477 SfxControllerItem* pCtrl = pCache->GetItemLink(); 478 while( pCtrl ) 479 { 480 pCtrl->StateChanged( SID_FOCUSURLBOX, SFX_ITEM_UNKNOWN, 0 ); 481 pCtrl = pCtrl->GetItemLink(); 482 } 483 } 484 } 485 } 486 487 // Recording 488 rRequest.Done(); 489 } 490 491 void SfxViewFrame::INetState_Impl( SfxItemSet &rItemSet ) 492 { 493 rItemSet.DisableItem( SID_BROWSE_FORWARD ); 494 rItemSet.DisableItem( SID_BROWSE_BACKWARD ); 495 496 // Add/SaveToBookmark bei BASIC-IDE, QUERY-EDITOR etc. disablen 497 SfxObjectShell *pDocSh = GetObjectShell(); 498 sal_Bool bPseudo = pDocSh && !( pDocSh->GetFactory().GetFlags() & SFXOBJECTSHELL_HASOPENDOC ); 499 sal_Bool bEmbedded = pDocSh && pDocSh->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED; 500 if ( !pDocSh || bPseudo || bEmbedded || !pDocSh->HasName() ) 501 rItemSet.DisableItem( SID_CREATELINK ); 502 } 503 504 void SfxViewFrame::SetZoomFactor( const Fraction &rZoomX, const Fraction &rZoomY ) 505 { 506 GetViewShell()->SetZoomFactor( rZoomX, rZoomY ); 507 } 508 509 void SfxViewFrame::Activate( sal_Bool bMDI ) 510 { 511 DBG_ASSERT(GetViewShell(), "Keine Shell"); 512 if ( bMDI ) 513 pImp->bActive = sal_True; 514 //(mba): hier evtl. wie in Beanframe NotifyEvent ?! 515 } 516 517 void SfxViewFrame::Deactivate( sal_Bool bMDI ) 518 { 519 DBG_ASSERT(GetViewShell(), "Keine Shell"); 520 if ( bMDI ) 521 pImp->bActive = sal_False; 522 //(mba): hier evtl. wie in Beanframe NotifyEvent ?! 523 } 524