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