| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sfx2.hxx" |
| |
| #include "impframe.hxx" |
| #include "objshimp.hxx" |
| #include "sfx2/sfxhelp.hxx" |
| #include "workwin.hxx" |
| |
| #include "sfx2/app.hxx" |
| #include "sfx2/bindings.hxx" |
| #include "sfx2/dispatch.hxx" |
| #include "sfx2/docfac.hxx" |
| #include "sfx2/docfile.hxx" |
| #include "sfx2/event.hxx" |
| #include "sfx2/objface.hxx" |
| #include "sfx2/request.hxx" |
| |
| #include <com/sun/star/awt/XWindow2.hpp> |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #include <com/sun/star/frame/XComponentLoader.hpp> |
| #include <com/sun/star/frame/XFrame.hpp> |
| #include <com/sun/star/frame/XFramesSupplier.hpp> |
| #include <com/sun/star/frame/XLayoutManager.hpp> |
| |
| #include <comphelper/componentcontext.hxx> |
| #include <comphelper/namedvaluecollection.hxx> |
| #include <comphelper/processfactory.hxx> |
| #include <svl/eitem.hxx> |
| #include <svl/intitem.hxx> |
| #include <svl/itemset.hxx> |
| #include <svl/rectitem.hxx> |
| #include <svl/stritem.hxx> |
| #include <toolkit/helper/vclunohelper.hxx> |
| #include <tools/diagnose_ex.h> |
| |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::frame; |
| using namespace ::com::sun::star::util; |
| using namespace ::com::sun::star::container; |
| using namespace ::com::sun::star::beans; |
| using ::com::sun::star::lang::XMultiServiceFactory; |
| using ::com::sun::star::lang::XComponent; |
| using ::com::sun::star::frame::XComponentLoader; |
| |
| //------------------------------------------------------------------------ |
| |
| class SfxFrameWindow_Impl : public Window |
| { |
| public: |
| SfxFrame* pFrame; |
| |
| SfxFrameWindow_Impl( SfxFrame* pF, Window& i_rContainerWindow ); |
| ~SfxFrameWindow_Impl( ); |
| |
| virtual void DataChanged( const DataChangedEvent& rDCEvt ); |
| virtual void StateChanged( StateChangedType nStateChange ); |
| virtual long PreNotify( NotifyEvent& rNEvt ); |
| virtual long Notify( NotifyEvent& rEvt ); |
| virtual void Resize(); |
| virtual void GetFocus(); |
| void DoResize(); |
| DECL_LINK( CloserHdl, void* ); |
| }; |
| |
| SfxFrameWindow_Impl::SfxFrameWindow_Impl( SfxFrame* pF, Window& i_rContainerWindow ) |
| : Window( &i_rContainerWindow, WB_BORDER | WB_CLIPCHILDREN | WB_NODIALOGCONTROL | WB_3DLOOK ) |
| , pFrame( pF ) |
| { |
| } |
| |
| SfxFrameWindow_Impl::~SfxFrameWindow_Impl( ) |
| { |
| } |
| |
| void SfxFrameWindow_Impl::DataChanged( const DataChangedEvent& rDCEvt ) |
| { |
| Window::DataChanged( rDCEvt ); |
| SfxWorkWindow *pWorkWin = pFrame->GetWorkWindow_Impl(); |
| if ( pWorkWin ) |
| pWorkWin->DataChanged_Impl( rDCEvt ); |
| } |
| |
| long SfxFrameWindow_Impl::Notify( NotifyEvent& rNEvt ) |
| { |
| if ( pFrame->IsClosing_Impl() || !pFrame->GetFrameInterface().is() ) |
| return sal_False; |
| |
| SfxViewFrame* pView = pFrame->GetCurrentViewFrame(); |
| if ( !pView || !pView->GetObjectShell() ) |
| return Window::Notify( rNEvt ); |
| |
| if ( rNEvt.GetType() == EVENT_GETFOCUS ) |
| { |
| if ( pView->GetViewShell() && !pView->GetViewShell()->GetUIActiveIPClient_Impl() && !pFrame->IsInPlace() ) |
| { |
| DBG_TRACE("SfxFrame: GotFocus"); |
| pView->MakeActive_Impl( sal_False ); |
| } |
| |
| // TODO/LATER: do we still need this code? |
| Window* pWindow = rNEvt.GetWindow(); |
| rtl::OString sHelpId; |
| while ( !sHelpId.getLength() && pWindow ) |
| { |
| sHelpId = pWindow->GetHelpId(); |
| pWindow = pWindow->GetParent(); |
| } |
| |
| if ( sHelpId.getLength() ) |
| SfxHelp::OpenHelpAgent( pFrame, sHelpId ); |
| |
| // if focus was on an external window, the clipboard content might have been changed |
| pView->GetBindings().Invalidate( SID_PASTE ); |
| pView->GetBindings().Invalidate( SID_PASTE_SPECIAL ); |
| return sal_True; |
| } |
| else if( rNEvt.GetType() == EVENT_KEYINPUT ) |
| { |
| if ( pView->GetViewShell()->KeyInput( *rNEvt.GetKeyEvent() ) ) |
| return sal_True; |
| } |
| else if ( rNEvt.GetType() == EVENT_EXECUTEDIALOG /*|| rNEvt.GetType() == EVENT_INPUTDISABLE*/ ) |
| { |
| pView->SetModalMode( sal_True ); |
| return sal_True; |
| } |
| else if ( rNEvt.GetType() == EVENT_ENDEXECUTEDIALOG /*|| rNEvt.GetType() == EVENT_INPUTENABLE*/ ) |
| { |
| //EnableInput( sal_True, sal_True ); |
| pView->SetModalMode( sal_False ); |
| return sal_True; |
| } |
| |
| return Window::Notify( rNEvt ); |
| } |
| |
| long SfxFrameWindow_Impl::PreNotify( NotifyEvent& rNEvt ) |
| { |
| sal_uInt16 nType = rNEvt.GetType(); |
| if ( nType == EVENT_KEYINPUT || nType == EVENT_KEYUP ) |
| { |
| SfxViewFrame* pView = pFrame->GetCurrentViewFrame(); |
| SfxViewShell* pShell = pView ? pView->GetViewShell() : NULL; |
| if ( pShell && pShell->HasKeyListeners_Impl() && pShell->HandleNotifyEvent_Impl( rNEvt ) ) |
| return sal_True; |
| } |
| else if ( nType == EVENT_MOUSEBUTTONUP || nType == EVENT_MOUSEBUTTONDOWN ) |
| { |
| Window* pWindow = rNEvt.GetWindow(); |
| SfxViewFrame* pView = pFrame->GetCurrentViewFrame(); |
| SfxViewShell* pShell = pView ? pView->GetViewShell() : NULL; |
| if ( pShell ) |
| if ( pWindow == pShell->GetWindow() || pShell->GetWindow()->IsChild( pWindow ) ) |
| if ( pShell->HasMouseClickListeners_Impl() && pShell->HandleNotifyEvent_Impl( rNEvt ) ) |
| return sal_True; |
| } |
| |
| if ( nType == EVENT_MOUSEBUTTONDOWN ) |
| { |
| Window* pWindow = rNEvt.GetWindow(); |
| const MouseEvent* pMEvent = rNEvt.GetMouseEvent(); |
| Point aPos = pWindow->OutputToScreenPixel( pMEvent->GetPosPixel() ); |
| SfxWorkWindow *pWorkWin = pFrame->GetWorkWindow_Impl(); |
| if ( pWorkWin ) |
| pWorkWin->EndAutoShow_Impl( aPos ); |
| } |
| |
| return Window::PreNotify( rNEvt ); |
| } |
| |
| void SfxFrameWindow_Impl::GetFocus() |
| { |
| if ( pFrame && !pFrame->IsClosing_Impl() && pFrame->GetCurrentViewFrame() && pFrame->GetFrameInterface().is() ) |
| pFrame->GetCurrentViewFrame()->MakeActive_Impl( sal_True ); |
| } |
| |
| void SfxFrameWindow_Impl::Resize() |
| { |
| if ( IsReallyVisible() || IsReallyShown() || GetOutputSizePixel().Width() ) |
| DoResize(); |
| } |
| |
| void SfxFrameWindow_Impl::StateChanged( StateChangedType nStateChange ) |
| { |
| if ( nStateChange == STATE_CHANGE_INITSHOW ) |
| { |
| pFrame->pImp->bHidden = sal_False; |
| if ( pFrame->IsInPlace() ) |
| // TODO/MBA: workaround for bug in LayoutManager: the final resize does not get through because the |
| // LayoutManager works asynchronously and between resize and time execution the DockingAcceptor was exchanged so that |
| // the resize event never is sent to the component |
| SetSizePixel( GetParent()->GetOutputSizePixel() ); |
| |
| DoResize(); |
| SfxViewFrame* pView = pFrame->GetCurrentViewFrame(); |
| if ( pView ) |
| pView->GetBindings().GetWorkWindow_Impl()->ShowChilds_Impl(); |
| } |
| |
| Window::StateChanged( nStateChange ); |
| } |
| |
| void SfxFrameWindow_Impl::DoResize() |
| { |
| if ( !pFrame->pImp->bLockResize ) |
| pFrame->Resize(); |
| } |
| |
| Reference < XFrame > SfxFrame::CreateBlankFrame() |
| { |
| Reference < XFrame > xFrame; |
| try |
| { |
| ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); |
| Reference < XFrame > xDesktop( aContext.createComponent( "com.sun.star.frame.Desktop" ), UNO_QUERY_THROW ); |
| xFrame.set( xDesktop->findFrame( DEFINE_CONST_UNICODE("_blank"), 0 ), UNO_SET_THROW ); |
| } |
| catch( const Exception& ) |
| { |
| DBG_UNHANDLED_EXCEPTION(); |
| } |
| return xFrame; |
| } |
| |
| SfxFrame* SfxFrame::Create( SfxObjectShell& rDoc, Window& rWindow, sal_uInt16 nViewId, bool bHidden ) |
| { |
| SfxFrame* pFrame = NULL; |
| try |
| { |
| // create and initialize new top level frame for this window |
| ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); |
| Reference < XFramesSupplier > xDesktop( aContext.createComponent( "com.sun.star.frame.Desktop" ), UNO_QUERY_THROW ); |
| Reference < XFrame > xFrame( aContext.createComponent( "com.sun.star.frame.Frame"), UNO_QUERY_THROW ); |
| |
| Reference< awt::XWindow2 > xWin( VCLUnoHelper::GetInterface ( &rWindow ), uno::UNO_QUERY_THROW ); |
| xFrame->initialize( xWin.get() ); |
| xDesktop->getFrames()->append( xFrame ); |
| |
| if ( xWin->isActive() ) |
| xFrame->activate(); |
| |
| // create load arguments |
| Sequence< PropertyValue > aLoadArgs; |
| TransformItems( SID_OPENDOC, *rDoc.GetMedium()->GetItemSet(), aLoadArgs ); |
| |
| ::comphelper::NamedValueCollection aArgs( aLoadArgs ); |
| aArgs.put( "Model", rDoc.GetModel() ); |
| aArgs.put( "Hidden", bHidden ); |
| if ( nViewId ) |
| aArgs.put( "ViewId", nViewId ); |
| |
| aLoadArgs = aArgs.getPropertyValues(); |
| |
| // load the doc into that frame |
| ::rtl::OUString sLoaderURL( RTL_CONSTASCII_USTRINGPARAM( "private:object" ) ); |
| Reference< XComponentLoader > xLoader( xFrame, UNO_QUERY_THROW ); |
| xLoader->loadComponentFromURL( |
| sLoaderURL, |
| ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "_self" ) ), |
| 0, |
| aLoadArgs |
| ); |
| |
| for ( pFrame = SfxFrame::GetFirst(); |
| pFrame; |
| pFrame = SfxFrame::GetNext( *pFrame ) |
| ) |
| { |
| if ( pFrame->GetFrameInterface() == xFrame ) |
| break; |
| } |
| |
| OSL_ENSURE( pFrame, "SfxFrame::Create: load succeeded, but no SfxFrame was created during this!" ); |
| } |
| catch( const Exception& ) |
| { |
| DBG_UNHANDLED_EXCEPTION(); |
| } |
| |
| return pFrame; |
| } |
| |
| SfxFrame* SfxFrame::Create( const Reference < XFrame >& i_rFrame ) |
| { |
| // create a new TopFrame to an external XFrame object ( wrap controller ) |
| ENSURE_OR_THROW( i_rFrame.is(), "NULL frame not allowed" ); |
| Window* pWindow = VCLUnoHelper::GetWindow( i_rFrame->getContainerWindow() ); |
| ENSURE_OR_THROW( pWindow, "frame without container window not allowed" ); |
| |
| SfxFrame* pFrame = new SfxFrame( *pWindow, false ); |
| pFrame->SetFrameInterface_Impl( i_rFrame ); |
| return pFrame; |
| } |
| |
| SfxFrame::SfxFrame( Window& i_rContainerWindow, bool i_bHidden ) |
| :pParentFrame( NULL ) |
| ,pChildArr( NULL ) |
| ,pImp( NULL ) |
| ,pWindow( NULL ) |
| { |
| Construct_Impl(); |
| |
| pImp->bHidden = i_bHidden; |
| InsertTopFrame_Impl( this ); |
| pImp->pExternalContainerWindow = &i_rContainerWindow; |
| |
| pWindow = new SfxFrameWindow_Impl( this, i_rContainerWindow ); |
| |
| // always show pWindow, which is the ComponentWindow of the XFrame we live in |
| // nowadays, since SfxFrames can be created with an XFrame only, hiding or showing the complete XFrame |
| // is not done at level of the container window, not at SFX level. Thus, the component window can |
| // always be visible. |
| pWindow->Show(); |
| } |
| |
| void SfxFrame::SetPresentationMode( sal_Bool bSet ) |
| { |
| if ( GetCurrentViewFrame() ) |
| GetCurrentViewFrame()->GetWindow().SetBorderStyle( bSet ? WINDOW_BORDER_NOBORDER : WINDOW_BORDER_NORMAL ); |
| |
| Reference< com::sun::star::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY ); |
| Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager; |
| |
| if ( xPropSet.is() ) |
| { |
| Any aValue = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ))); |
| aValue >>= xLayoutManager; |
| } |
| |
| if ( xLayoutManager.is() ) |
| xLayoutManager->setVisible( !bSet ); // we don't want to have ui in presentation mode |
| |
| SetMenuBarOn_Impl( !bSet ); |
| if ( GetWorkWindow_Impl() ) |
| GetWorkWindow_Impl()->SetDockingAllowed( !bSet ); |
| if ( GetCurrentViewFrame() ) |
| GetCurrentViewFrame()->GetDispatcher()->Update_Impl( sal_True ); |
| } |
| |
| SystemWindow* SfxFrame::GetSystemWindow() const |
| { |
| return GetTopWindow_Impl(); |
| } |
| |
| SystemWindow* SfxFrame::GetTopWindow_Impl() const |
| { |
| if ( pImp->pExternalContainerWindow->IsSystemWindow() ) |
| return (SystemWindow*) pImp->pExternalContainerWindow; |
| else |
| return NULL; |
| } |
| |
| Window& SfxFrame::GetWindow() const |
| { |
| return *pWindow; |
| } |
| |
| sal_Bool SfxFrame::Close() |
| { |
| delete this; |
| return sal_True; |
| } |
| |
| void SfxFrame::LockResize_Impl( sal_Bool bLock ) |
| { |
| pImp->bLockResize = bLock; |
| } |
| |
| IMPL_LINK( SfxFrameWindow_Impl, CloserHdl, void*, EMPTYARG ) |
| { |
| if ( pFrame && !pFrame->PrepareClose_Impl( sal_True ) ) |
| return 0L; |
| |
| if ( pFrame ) |
| pFrame->GetCurrentViewFrame()->GetBindings().Execute( SID_CLOSEWIN, 0, 0, SFX_CALLMODE_ASYNCHRON ); |
| return 0L; |
| } |
| |
| void SfxFrame::SetMenuBarOn_Impl( sal_Bool bOn ) |
| { |
| pImp->bMenuBarOn = bOn; |
| |
| Reference< com::sun::star::beans::XPropertySet > xPropSet( GetFrameInterface(), UNO_QUERY ); |
| Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager; |
| |
| if ( xPropSet.is() ) |
| { |
| Any aValue = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ))); |
| aValue >>= xLayoutManager; |
| } |
| |
| if ( xLayoutManager.is() ) |
| { |
| rtl::OUString aMenuBarURL( RTL_CONSTASCII_USTRINGPARAM( "private:resource/menubar/menubar" )); |
| |
| if ( bOn ) |
| xLayoutManager->showElement( aMenuBarURL ); |
| else |
| xLayoutManager->hideElement( aMenuBarURL ); |
| } |
| } |
| |
| sal_Bool SfxFrame::IsMenuBarOn_Impl() const |
| { |
| return pImp->bMenuBarOn; |
| } |
| |
| void SfxFrame::PositionWindow_Impl( const Rectangle& rWinArea ) const |
| { |
| Window *pWin = pImp->pExternalContainerWindow; |
| |
| // Groesse setzen |
| const Size aAppWindow( pImp->pExternalContainerWindow->GetDesktopRectPixel().GetSize() ); |
| Point aPos( rWinArea.TopLeft() ); |
| Size aSz( rWinArea.GetSize() ); |
| if ( aSz.Width() && aSz.Height() ) |
| { |
| aPos.X() = Min(aPos.X(), |
| long(aAppWindow.Width() - aSz.Width() + aSz.Width() / 2) ); |
| aPos.Y() = Min(aPos.Y(), |
| long( aAppWindow.Height() - aSz.Height() + aSz.Height() / 2) ); |
| if ( aPos.X() + aSz.Width() < |
| aAppWindow.Width() + aSz.Width() / 2 && |
| aPos.Y() + aSz.Height() < |
| aAppWindow.Height() + aSz.Height() / 2 ) |
| { |
| pWin->SetPosPixel( aPos ); |
| pWin->SetOutputSizePixel( aSz ); |
| } |
| } |
| } |
| |
| void SfxFrame::PrepareForDoc_Impl( SfxObjectShell& i_rDoc ) |
| { |
| const ::comphelper::NamedValueCollection aDocumentArgs( i_rDoc.GetModel()->getArgs() ); |
| |
| // hidden? |
| OSL_ENSURE( !pImp->bHidden, "when does this happen?" ); |
| pImp->bHidden = aDocumentArgs.getOrDefault( "Hidden", pImp->bHidden ); |
| |
| // update our descriptor |
| UpdateDescriptor( &i_rDoc ); |
| |
| // plugin mode |
| sal_Int16 nPluginMode = aDocumentArgs.getOrDefault( "PluginMode", sal_Int16( 0 ) ); |
| if ( nPluginMode && ( nPluginMode != 2 ) ) |
| SetInPlace_Impl( sal_True ); |
| } |
| |
| bool SfxFrame::IsMarkedHidden_Impl() const |
| { |
| return pImp->bHidden; |
| } |