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