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
GetModuleName_Impl(const::rtl::OUString & sDocService)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 //--------------------------------------------------------------------
StateChanged(StateChangedType nStateChange)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
Resize()108 void SfxFrameViewWindow_Impl::Resize()
109 {
110 if ( IsReallyVisible() || IsReallyShown() || GetOutputSizePixel().Width() )
111 pFrame->Resize();
112 }
113
_getTabString()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 //--------------------------------------------------------------------
UpdateTitle()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
Exec_Impl(SfxRequest & rReq)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
GetState_Impl(SfxItemSet & rSet)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
INetExecute_Impl(SfxRequest & rRequest)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
INetState_Impl(SfxItemSet & rItemSet)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
SetZoomFactor(const Fraction & rZoomX,const Fraction & rZoomY)500 void SfxViewFrame::SetZoomFactor( const Fraction &rZoomX, const Fraction &rZoomY )
501 {
502 GetViewShell()->SetZoomFactor( rZoomX, rZoomY );
503 }
504
Activate(sal_Bool bMDI)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
Deactivate(sal_Bool bMDI)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