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