xref: /aoo41x/main/sfx2/source/view/frame2.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 "impframe.hxx"
32 #include "objshimp.hxx"
33 #include "sfx2/sfxhelp.hxx"
34 #include "workwin.hxx"
35 
36 #include "sfx2/app.hxx"
37 #include "sfx2/bindings.hxx"
38 #include "sfx2/dispatch.hxx"
39 #include "sfx2/docfac.hxx"
40 #include "sfx2/docfile.hxx"
41 #include "sfx2/event.hxx"
42 #include "sfx2/objface.hxx"
43 #include "sfx2/request.hxx"
44 
45 #include <com/sun/star/awt/XWindow2.hpp>
46 #include <com/sun/star/beans/XPropertySet.hpp>
47 #include <com/sun/star/frame/XComponentLoader.hpp>
48 #include <com/sun/star/frame/XFrame.hpp>
49 #include <com/sun/star/frame/XFramesSupplier.hpp>
50 #include <com/sun/star/frame/XLayoutManager.hpp>
51 
52 #include <comphelper/componentcontext.hxx>
53 #include <comphelper/namedvaluecollection.hxx>
54 #include <comphelper/processfactory.hxx>
55 #include <svl/eitem.hxx>
56 #include <svl/intitem.hxx>
57 #include <svl/itemset.hxx>
58 #include <svl/rectitem.hxx>
59 #include <svl/stritem.hxx>
60 #include <toolkit/helper/vclunohelper.hxx>
61 #include <tools/diagnose_ex.h>
62 
63 using namespace ::com::sun::star;
64 using namespace ::com::sun::star::uno;
65 using namespace ::com::sun::star::frame;
66 using namespace ::com::sun::star::util;
67 using namespace ::com::sun::star::container;
68 using namespace ::com::sun::star::beans;
69 using ::com::sun::star::lang::XMultiServiceFactory;
70 using ::com::sun::star::lang::XComponent;
71 using ::com::sun::star::frame::XComponentLoader;
72 
73 //------------------------------------------------------------------------
74 
75 class SfxFrameWindow_Impl : public Window
76 {
77 public:
78 	SfxFrame*           pFrame;
79 
80     SfxFrameWindow_Impl( SfxFrame* pF, Window& i_rContainerWindow );
81     ~SfxFrameWindow_Impl( );
82 
83     virtual void        DataChanged( const DataChangedEvent& rDCEvt );
84 	virtual void		StateChanged( StateChangedType nStateChange );
85 	virtual long 		PreNotify( NotifyEvent& rNEvt );
86 	virtual long		Notify( NotifyEvent& rEvt );
87 	virtual void        Resize();
88     virtual void        GetFocus();
89 	void				DoResize();
90 	DECL_LINK(			CloserHdl, void* );
91 };
92 
93 SfxFrameWindow_Impl::SfxFrameWindow_Impl( SfxFrame* pF, Window& i_rContainerWindow )
94         : Window( &i_rContainerWindow, WB_BORDER | WB_CLIPCHILDREN | WB_NODIALOGCONTROL | WB_3DLOOK )
95         , pFrame( pF )
96 {
97 }
98 
99 SfxFrameWindow_Impl::~SfxFrameWindow_Impl( )
100 {
101 }
102 
103 void SfxFrameWindow_Impl::DataChanged( const DataChangedEvent& rDCEvt )
104 {
105     Window::DataChanged( rDCEvt );
106     SfxWorkWindow *pWorkWin = pFrame->GetWorkWindow_Impl();
107     if ( pWorkWin )
108         pWorkWin->DataChanged_Impl( rDCEvt );
109 }
110 
111 long SfxFrameWindow_Impl::Notify( NotifyEvent& rNEvt )
112 {
113 	if ( pFrame->IsClosing_Impl() || !pFrame->GetFrameInterface().is() )
114 		return sal_False;
115 
116     SfxViewFrame* pView = pFrame->GetCurrentViewFrame();
117     if ( !pView || !pView->GetObjectShell() )
118         return Window::Notify( rNEvt );
119 
120     if ( rNEvt.GetType() == EVENT_GETFOCUS )
121     {
122         if ( pView->GetViewShell() && !pView->GetViewShell()->GetUIActiveIPClient_Impl() && !pFrame->IsInPlace() )
123         {
124             DBG_TRACE("SfxFrame: GotFocus");
125             pView->MakeActive_Impl( sal_False );
126         }
127 
128         // TODO/LATER: do we still need this code?
129         Window* pWindow = rNEvt.GetWindow();
130         rtl::OString sHelpId;
131         while ( !sHelpId.getLength() && pWindow )
132         {
133             sHelpId = pWindow->GetHelpId();
134             pWindow = pWindow->GetParent();
135         }
136 
137         if ( sHelpId.getLength() )
138             SfxHelp::OpenHelpAgent( pFrame, sHelpId );
139 
140 		// if focus was on an external window, the clipboard content might have been changed
141 		pView->GetBindings().Invalidate( SID_PASTE );
142 		pView->GetBindings().Invalidate( SID_PASTE_SPECIAL );
143 		return sal_True;
144 	}
145     else if( rNEvt.GetType() == EVENT_KEYINPUT )
146 	{
147         if ( pView->GetViewShell()->KeyInput( *rNEvt.GetKeyEvent() ) )
148             return sal_True;
149 	}
150     else if ( rNEvt.GetType() == EVENT_EXECUTEDIALOG /*|| rNEvt.GetType() == EVENT_INPUTDISABLE*/ )
151 	{
152         pView->SetModalMode( sal_True );
153 		return sal_True;
154 	}
155 	else if ( rNEvt.GetType() == EVENT_ENDEXECUTEDIALOG /*|| rNEvt.GetType() == EVENT_INPUTENABLE*/ )
156 	{
157 		//EnableInput( sal_True, sal_True );
158         pView->SetModalMode( sal_False );
159 		return sal_True;
160 	}
161 
162     return Window::Notify( rNEvt );
163 }
164 
165 long SfxFrameWindow_Impl::PreNotify( NotifyEvent& rNEvt )
166 {
167 	sal_uInt16 nType = rNEvt.GetType();
168 	if ( nType == EVENT_KEYINPUT || nType == EVENT_KEYUP )
169     {
170 		SfxViewFrame* pView = pFrame->GetCurrentViewFrame();
171 		SfxViewShell* pShell = pView ? pView->GetViewShell() : NULL;
172 		if ( pShell && pShell->HasKeyListeners_Impl() && pShell->HandleNotifyEvent_Impl( rNEvt ) )
173 			return sal_True;
174 	}
175 	else if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN )
176     {
177 		Window* pWindow = rNEvt.GetWindow();
178 		SfxViewFrame* pView = pFrame->GetCurrentViewFrame();
179 		SfxViewShell* pShell = pView ? pView->GetViewShell() : NULL;
180 		if ( pShell )
181 			if ( pWindow == pShell->GetWindow() || pShell->GetWindow()->IsChild( pWindow ) )
182 				if ( pShell->HasMouseClickListeners_Impl() && pShell->HandleNotifyEvent_Impl( rNEvt ) )
183 					return sal_True;
184 	}
185 
186 	if ( nType == EVENT_MOUSEBUTTONDOWN )
187     {
188         Window* pWindow = rNEvt.GetWindow();
189         const MouseEvent* pMEvent = rNEvt.GetMouseEvent();
190         Point aPos = pWindow->OutputToScreenPixel( pMEvent->GetPosPixel() );
191         SfxWorkWindow *pWorkWin = pFrame->GetWorkWindow_Impl();
192         if ( pWorkWin )
193             pWorkWin->EndAutoShow_Impl( aPos );
194     }
195 
196 	return Window::PreNotify( rNEvt );
197 }
198 
199 void SfxFrameWindow_Impl::GetFocus()
200 {
201     if ( pFrame && !pFrame->IsClosing_Impl() && pFrame->GetCurrentViewFrame() && pFrame->GetFrameInterface().is() )
202         pFrame->GetCurrentViewFrame()->MakeActive_Impl( sal_True );
203 }
204 
205 void SfxFrameWindow_Impl::Resize()
206 {
207     if ( IsReallyVisible() || IsReallyShown() || GetOutputSizePixel().Width() )
208 		DoResize();
209 }
210 
211 void SfxFrameWindow_Impl::StateChanged( StateChangedType nStateChange )
212 {
213 	if ( nStateChange == STATE_CHANGE_INITSHOW )
214 	{
215         pFrame->pImp->bHidden = sal_False;
216         if ( pFrame->IsInPlace() )
217             // TODO/MBA: workaround for bug in LayoutManager: the final resize does not get through because the
218             // LayoutManager works asynchronously and between resize and time execution the DockingAcceptor was exchanged so that
219             // the resize event never is sent to the component
220             SetSizePixel( GetParent()->GetOutputSizePixel() );
221 
222 		DoResize();
223         SfxViewFrame* pView = pFrame->GetCurrentViewFrame();
224         if ( pView )
225             pView->GetBindings().GetWorkWindow_Impl()->ShowChilds_Impl();
226 	}
227 
228     Window::StateChanged( nStateChange );
229 }
230 
231 void SfxFrameWindow_Impl::DoResize()
232 {
233     if ( !pFrame->pImp->bLockResize )
234         pFrame->Resize();
235 }
236 
237 Reference < XFrame > SfxFrame::CreateBlankFrame()
238 {
239     Reference < XFrame > xFrame;
240     try
241     {
242         ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
243         Reference < XFrame > xDesktop( aContext.createComponent( "com.sun.star.frame.Desktop" ), UNO_QUERY_THROW );
244         xFrame.set( xDesktop->findFrame( DEFINE_CONST_UNICODE("_blank"), 0 ), UNO_SET_THROW );
245     }
246     catch( const Exception& )
247     {
248     	DBG_UNHANDLED_EXCEPTION();
249     }
250     return xFrame;
251 }
252 
253 SfxFrame* SfxFrame::Create( SfxObjectShell& rDoc, Window& rWindow, sal_uInt16 nViewId, bool bHidden )
254 {
255     SfxFrame* pFrame = NULL;
256     try
257     {
258         // create and initialize new top level frame for this window
259         ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
260         Reference < XFramesSupplier > xDesktop( aContext.createComponent( "com.sun.star.frame.Desktop" ), UNO_QUERY_THROW );
261         Reference < XFrame > xFrame( aContext.createComponent( "com.sun.star.frame.Frame"), UNO_QUERY_THROW );
262 
263         Reference< awt::XWindow2 > xWin( VCLUnoHelper::GetInterface ( &rWindow ), uno::UNO_QUERY_THROW );
264         xFrame->initialize( xWin.get() );
265         xDesktop->getFrames()->append( xFrame );
266 
267 	    if ( xWin->isActive() )
268             xFrame->activate();
269 
270         // create load arguments
271         Sequence< PropertyValue > aLoadArgs;
272         TransformItems( SID_OPENDOC, *rDoc.GetMedium()->GetItemSet(), aLoadArgs );
273 
274         ::comphelper::NamedValueCollection aArgs( aLoadArgs );
275         aArgs.put( "Model", rDoc.GetModel() );
276         aArgs.put( "Hidden", bHidden );
277         if ( nViewId )
278             aArgs.put( "ViewId", nViewId );
279 
280         aLoadArgs = aArgs.getPropertyValues();
281 
282         // load the doc into that frame
283         ::rtl::OUString sLoaderURL( RTL_CONSTASCII_USTRINGPARAM( "private:object" ) );
284         Reference< XComponentLoader > xLoader( xFrame, UNO_QUERY_THROW );
285         xLoader->loadComponentFromURL(
286             sLoaderURL,
287             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_self" ) ),
288             0,
289             aLoadArgs
290         );
291 
292         for (   pFrame = SfxFrame::GetFirst();
293                 pFrame;
294                 pFrame = SfxFrame::GetNext( *pFrame )
295             )
296         {
297             if ( pFrame->GetFrameInterface() == xFrame )
298                 break;
299         }
300 
301         OSL_ENSURE( pFrame, "SfxFrame::Create: load succeeded, but no SfxFrame was created during this!" );
302     }
303     catch( const Exception& )
304     {
305     	DBG_UNHANDLED_EXCEPTION();
306     }
307 
308     return pFrame;
309 }
310 
311 SfxFrame* SfxFrame::Create( const Reference < XFrame >& i_rFrame )
312 {
313     // create a new TopFrame to an external XFrame object ( wrap controller )
314     ENSURE_OR_THROW( i_rFrame.is(), "NULL frame not allowed" );
315     Window* pWindow = VCLUnoHelper::GetWindow( i_rFrame->getContainerWindow() );
316     ENSURE_OR_THROW( pWindow, "frame without container window not allowed" );
317 
318     SfxFrame* pFrame = new SfxFrame( *pWindow, false );
319     pFrame->SetFrameInterface_Impl( i_rFrame );
320     return pFrame;
321 }
322 
323 SfxFrame::SfxFrame( Window& i_rContainerWindow, bool i_bHidden )
324     :pParentFrame( NULL )
325     ,pChildArr( NULL )
326     ,pImp( NULL )
327 	,pWindow( NULL )
328 {
329     Construct_Impl();
330 
331     pImp->bHidden = i_bHidden;
332 	InsertTopFrame_Impl( this );
333     pImp->pExternalContainerWindow = &i_rContainerWindow;
334 
335     pWindow = new SfxFrameWindow_Impl( this, i_rContainerWindow );
336 
337     // always show pWindow, which is the ComponentWindow of the XFrame we live in
338     // nowadays, since SfxFrames can be created with an XFrame only, hiding or showing the complete XFrame
339     // is not done at level of the container window, not at SFX level. Thus, the component window can
340     // always be visible.
341     pWindow->Show();
342 }
343 
344 void SfxFrame::SetPresentationMode( sal_Bool bSet )
345 {
346     if ( GetCurrentViewFrame() )
347         GetCurrentViewFrame()->GetWindow().SetBorderStyle( bSet ? WINDOW_BORDER_NOBORDER : WINDOW_BORDER_NORMAL );
348 
349     Reference< com::sun::star::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
350     Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
351 
352 	if ( xPropSet.is() )
353 	{
354 		Any aValue = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" )));
355 		aValue >>= xLayoutManager;
356     }
357 
358     if ( xLayoutManager.is() )
359         xLayoutManager->setVisible( !bSet ); // we don't want to have ui in presentation mode
360 
361     SetMenuBarOn_Impl( !bSet );
362     if ( GetWorkWindow_Impl() )
363         GetWorkWindow_Impl()->SetDockingAllowed( !bSet );
364     if ( GetCurrentViewFrame() )
365         GetCurrentViewFrame()->GetDispatcher()->Update_Impl( sal_True );
366 }
367 
368 SystemWindow* SfxFrame::GetSystemWindow() const
369 {
370 	return GetTopWindow_Impl();
371 }
372 
373 SystemWindow* SfxFrame::GetTopWindow_Impl() const
374 {
375     if ( pImp->pExternalContainerWindow->IsSystemWindow() )
376         return (SystemWindow*) pImp->pExternalContainerWindow;
377     else
378         return NULL;
379 }
380 
381 Window& SfxFrame::GetWindow() const
382 {
383     return *pWindow;
384 }
385 
386 sal_Bool SfxFrame::Close()
387 {
388 	delete this;
389 	return sal_True;
390 }
391 
392 void SfxFrame::LockResize_Impl( sal_Bool bLock )
393 {
394     pImp->bLockResize = bLock;
395 }
396 
397 IMPL_LINK( SfxFrameWindow_Impl, CloserHdl, void*, EMPTYARG )
398 {
399 	if ( pFrame && !pFrame->PrepareClose_Impl( sal_True ) )
400 		return 0L;
401 
402 	if ( pFrame )
403 		pFrame->GetCurrentViewFrame()->GetBindings().Execute( SID_CLOSEWIN, 0, 0, SFX_CALLMODE_ASYNCHRON );
404 	return 0L;
405 }
406 
407 void SfxFrame::SetMenuBarOn_Impl( sal_Bool bOn )
408 {
409     pImp->bMenuBarOn = bOn;
410 
411     Reference< com::sun::star::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY );
412     Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager;
413 
414 	if ( xPropSet.is() )
415 	{
416 		Any aValue = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" )));
417 		aValue >>= xLayoutManager;
418     }
419 
420     if ( xLayoutManager.is() )
421     {
422         rtl::OUString aMenuBarURL( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" ));
423 
424         if ( bOn )
425             xLayoutManager->showElement( aMenuBarURL );
426         else
427             xLayoutManager->hideElement( aMenuBarURL );
428     }
429 }
430 
431 sal_Bool SfxFrame::IsMenuBarOn_Impl() const
432 {
433     return pImp->bMenuBarOn;
434 }
435 
436 void SfxFrame::PositionWindow_Impl( const Rectangle& rWinArea ) const
437 {
438     Window *pWin = pImp->pExternalContainerWindow;
439 
440 	// Groesse setzen
441     const Size aAppWindow( pImp->pExternalContainerWindow->GetDesktopRectPixel().GetSize() );
442 	Point aPos( rWinArea.TopLeft() );
443 	Size aSz( rWinArea.GetSize() );
444 	if ( aSz.Width() && aSz.Height() )
445 	{
446 		aPos.X() = Min(aPos.X(),
447 						long(aAppWindow.Width() - aSz.Width() + aSz.Width() / 2) );
448 		aPos.Y() = Min(aPos.Y(),
449 						long( aAppWindow.Height() - aSz.Height() + aSz.Height() / 2) );
450 		if ( aPos.X() + aSz.Width() <
451 				aAppWindow.Width() + aSz.Width() / 2 &&
452 				aPos.Y() + aSz.Height() <
453 				aAppWindow.Height() + aSz.Height() / 2 )
454 		{
455 			pWin->SetPosPixel( aPos );
456 			pWin->SetOutputSizePixel( aSz );
457 		}
458 	}
459 }
460 
461 void SfxFrame::PrepareForDoc_Impl( SfxObjectShell& i_rDoc )
462 {
463     const ::comphelper::NamedValueCollection aDocumentArgs( i_rDoc.GetModel()->getArgs() );
464 
465     // hidden?
466     OSL_ENSURE( !pImp->bHidden, "when does this happen?" );
467     pImp->bHidden = aDocumentArgs.getOrDefault( "Hidden", pImp->bHidden );
468 
469     // update our descriptor
470     UpdateDescriptor( &i_rDoc );
471 
472     // plugin mode
473     sal_Int16 nPluginMode = aDocumentArgs.getOrDefault( "PluginMode", sal_Int16( 0 ) );
474     if ( nPluginMode && ( nPluginMode != 2 ) )
475         SetInPlace_Impl( sal_True );
476 }
477 
478 bool SfxFrame::IsMarkedHidden_Impl() const
479 {
480     return pImp->bHidden;
481 }
482