xref: /trunk/main/sfx2/source/view/viewfrm2.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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