diff options
Diffstat (limited to 'sfx2/source/view')
-rw-r--r-- | sfx2/source/view/frame.cxx | 985 | ||||
-rw-r--r-- | sfx2/source/view/frame2.cxx | 482 | ||||
-rw-r--r-- | sfx2/source/view/frmload.cxx | 716 | ||||
-rw-r--r-- | sfx2/source/view/impframe.hxx | 102 | ||||
-rw-r--r-- | sfx2/source/view/impviewframe.hxx | 100 | ||||
-rw-r--r-- | sfx2/source/view/ipclient.cxx | 1156 | ||||
-rw-r--r-- | sfx2/source/view/orgmgr.cxx | 794 | ||||
-rw-r--r-- | sfx2/source/view/printer.cxx | 311 | ||||
-rw-r--r-- | sfx2/source/view/sfxbasecontroller.cxx | 1544 | ||||
-rw-r--r-- | sfx2/source/view/userinputinterception.cxx | 281 | ||||
-rwxr-xr-x | sfx2/source/view/view.hrc | 120 | ||||
-rw-r--r-- | sfx2/source/view/view.src | 190 | ||||
-rw-r--r-- | sfx2/source/view/viewfac.cxx | 90 | ||||
-rw-r--r-- | sfx2/source/view/viewfrm.cxx | 3467 | ||||
-rw-r--r-- | sfx2/source/view/viewfrm2.cxx | 516 | ||||
-rw-r--r-- | sfx2/source/view/viewimp.hxx | 87 | ||||
-rw-r--r-- | sfx2/source/view/viewprn.cxx | 938 | ||||
-rw-r--r-- | sfx2/source/view/viewsh.cxx | 2299 |
18 files changed, 14178 insertions, 0 deletions
diff --git a/sfx2/source/view/frame.cxx b/sfx2/source/view/frame.cxx new file mode 100644 index 000000000000..938165549bf4 --- /dev/null +++ b/sfx2/source/view/frame.cxx @@ -0,0 +1,985 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/util/CloseVetoException.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/container/XChild.hpp> + +#include <vcl/menu.hxx> +#include <svl/intitem.hxx> +#include <vcl/splitwin.hxx> +#include <svl/eitem.hxx> +#include <svl/stritem.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <com/sun/star/awt/PosSize.hpp> +#include <comphelper/processfactory.hxx> +#include <vcl/msgbox.hxx> + +// wg. pTopFrames +#include "appdata.hxx" +#include <sfx2/app.hxx> +#include <sfx2/event.hxx> +#include <sfx2/unoctitm.hxx> +#include <sfx2/frame.hxx> +#include "arrdecl.hxx" +#include <sfx2/objsh.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/frmdescr.hxx> +#include "openflag.hxx" +#include <sfx2/viewsh.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/request.hxx> +#include <sfx2/fcontnr.hxx> +#include "impframe.hxx" +#include <sfx2/appuno.hxx> +#include <sfx2/viewfrm.hxx> +#include "workwin.hxx" +#include <sfx2/sfxuno.hxx> +#include <sfx2/msgpool.hxx> +#include "objshimp.hxx" +#include <sfx2/ipclient.hxx> + +#ifdef DBG_UTIL +#include <sfx2/frmhtmlw.hxx> +#endif + +using namespace com::sun::star; + +static SfxFrameArr_Impl* pFramesArr_Impl=0; + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::container; + +TYPEINIT1(SfxFrame, SfxListener); +TYPEINIT1_AUTOFACTORY(SfxFrameItem, SfxPoolItem); +TYPEINIT1(SfxUsrAnyItem, SfxPoolItem); +TYPEINIT1_AUTOFACTORY(SfxUnoFrameItem, SfxPoolItem); + +SvCompatWeakHdl* SfxFrame::GetHdl() +{ + return pImp->GetHdl(); +} + +//-------------------------------------------------------------------- +void SfxFrame::Construct_Impl() +{ + pImp = new SfxFrame_Impl( this ); + if ( !pFramesArr_Impl ) + pFramesArr_Impl = new SfxFrameArr_Impl; + pFramesArr_Impl->Insert( this, pFramesArr_Impl->Count() ); +} + +//-------------------------------------------------------------------- + +SfxFrame::~SfxFrame() +{ + RemoveTopFrame_Impl( this ); + DELETEZ( pWindow ); + + pFramesArr_Impl->Remove( pFramesArr_Impl->GetPos( this ) ); + + if ( pParentFrame ) + { + pParentFrame->RemoveChildFrame_Impl( this ); + pParentFrame = 0; + } + + delete pImp->pDescr; + + if ( pChildArr ) + { + DBG_ASSERT( !pChildArr->Count(), "Children are not removed!" ); + delete pChildArr; + } + + delete pImp; +} + +sal_Bool SfxFrame::DoClose() +{ + // Actually, one more PrepareClose is still needed! + sal_Bool bRet = sal_False; + if ( !pImp->bClosing ) + { + pImp->bClosing = sal_True; + CancelTransfers(); + + // now close frame; it will be deleted if this call is successful, so don't use any members after that! + bRet = sal_True; + try + { + Reference< XCloseable > xCloseable ( pImp->xFrame, UNO_QUERY ); + if ( (!GetCurrentDocument() || !GetCurrentDocument()->Get_Impl()->bDisposing ) && xCloseable.is()) + xCloseable->close(sal_True); + else if ( pImp->xFrame.is() ) + { + Reference < XFrame > xFrame = pImp->xFrame; + xFrame->setComponent( Reference < com::sun::star::awt::XWindow >(), Reference < XController >() ); + xFrame->dispose(); + } + else + bRet = DoClose_Impl(); + } + catch( ::com::sun::star::util::CloseVetoException& ) + { + pImp->bClosing = sal_False; + bRet = sal_False; + } + catch( ::com::sun::star::lang::DisposedException& ) + { + } + } + + return bRet; +} + +sal_Bool SfxFrame::DoClose_Impl() +{ + sal_Bool bRet = sal_True; + SfxBindings* pBindings = NULL; + if ( pImp->pCurrentViewFrame ) + pBindings = &pImp->pCurrentViewFrame->GetBindings(); + + // For internal tasks Controllers and Tools must be cleared + if ( pImp->pWorkWin ) + pImp->pWorkWin->DeleteControllers_Impl(); + + if ( pImp->pCurrentViewFrame ) + bRet = pImp->pCurrentViewFrame->Close(); + + if ( pImp->bOwnsBindings ) + DELETEZ( pBindings ); + + bRet = Close(); + DBG_ASSERT( bRet, "Impossible state: frame closes, but controller refuses!"); + return bRet; +} + +sal_Bool SfxFrame::DocIsModified_Impl() +{ + if ( pImp->pCurrentViewFrame && pImp->pCurrentViewFrame->GetObjectShell() && + pImp->pCurrentViewFrame->GetObjectShell()->IsModified() ) + return sal_True; + for( sal_uInt16 nPos = GetChildFrameCount(); nPos--; ) + if( pChildArr->GetObject( nPos )->DocIsModified_Impl() ) + return sal_True; + return sal_False; +} + +sal_uInt16 SfxFrame::PrepareClose_Impl( sal_Bool bUI, sal_Bool bForBrowsing ) +{ + sal_uInt16 nRet = RET_OK; + + // prevent recursive calls + if( !pImp->bPrepClosing ) + { + pImp->bPrepClosing = sal_True; + + SfxObjectShell* pCur = GetCurrentDocument() ; + if( pCur ) + { + // SFX components have a known behaviour + // First check if this frame is the only view to its current document + int bOther = sal_False; + for ( const SfxViewFrame *pFrame = SfxViewFrame::GetFirst( pCur ); + !bOther && pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, pCur ) ) + { + bOther = ( &pFrame->GetFrame() != this ); + } + + SFX_APP()->NotifyEvent( SfxViewEventHint(SFX_EVENT_PREPARECLOSEVIEW, GlobalEventConfig::GetEventName( STR_EVENT_PREPARECLOSEVIEW ), pCur, GetController() ) ); + + if ( bOther ) + // if there are other views only the current view of this frame must be asked + nRet = GetCurrentViewFrame()->GetViewShell()->PrepareClose( bUI, bForBrowsing ); + else + // otherwise ask the document + nRet = pCur->PrepareClose( bUI, bForBrowsing ); + } + + if ( nRet == RET_OK ) + { + // if this frame has child frames, ask them too + for( sal_uInt16 nPos = GetChildFrameCount(); nRet == RET_OK && nPos--; ) + nRet = pChildArr->GetObject( nPos )->PrepareClose_Impl( bUI, bForBrowsing ); + } + + pImp->bPrepClosing = sal_False; + } + + if ( nRet == RET_OK && pImp->pWorkWin ) + // if closing was accepted by the component the UI subframes must be asked also + nRet = pImp->pWorkWin->PrepareClose_Impl(); + + return nRet; +} + +//-------------------------------------------------------------------- + +SfxFrame* SfxFrame::GetChildFrame( sal_uInt16 nPos ) const +{ + if ( pChildArr && pChildArr->Count() > nPos ) + { + DBG_ASSERT( nPos < pChildArr->Count(), "Wrong Index!"); + return (*pChildArr)[nPos]; + } + + return 0L; +} + +void SfxFrame::RemoveChildFrame_Impl( SfxFrame* pFrame ) +{ + DBG_ASSERT( pChildArr, "Unknown Frame!"); + sal_uInt16 nPos = pChildArr->GetPos(pFrame); + pChildArr->Remove( nPos ); +}; + +SfxFrame& SfxFrame::GetTopFrame() const +{ + const SfxFrame* pParent = this; + while ( pParent->pParentFrame ) + pParent = pParent->pParentFrame; + return *const_cast< SfxFrame* >( pParent ); +} + +sal_Bool SfxFrame::IsClosing_Impl() const +{ + return pImp->bClosing; +} + +void SfxFrame::SetIsClosing_Impl() +{ + pImp->bClosing = sal_True; +} + +sal_uInt16 SfxFrame::GetChildFrameCount() const +{ + return pChildArr ? pChildArr->Count() : 0; +} + +void SfxFrame::CancelTransfers( sal_Bool /*bCancelLoadEnv*/ ) +{ + if( !pImp->bInCancelTransfers ) + { + pImp->bInCancelTransfers = sal_True; + SfxObjectShell* pObj = GetCurrentDocument(); + if( pObj ) //&& !( pObj->Get_Impl()->nLoadedFlags & SFX_LOADED_ALL )) + { + SfxViewFrame* pFrm; + for( pFrm = SfxViewFrame::GetFirst( pObj ); + pFrm && &pFrm->GetFrame() == this; + pFrm = SfxViewFrame::GetNext( *pFrm, pObj ) ) ; + // No more Frame in Document -> Cancel + if( !pFrm ) + { + pObj->CancelTransfers(); + GetCurrentDocument()->Broadcast( SfxSimpleHint(SFX_HINT_TITLECHANGED) ); + } + } + + // First stop multiload Frames + sal_uInt16 nCount = GetChildFrameCount(); + for( sal_uInt16 n = 0; n<nCount; n++ ) + GetChildFrame( n )->CancelTransfers(); + + // Check if StarOne-Loader should be canceled + SfxFrameWeak wFrame( this ); + if (wFrame.Is()) + pImp->bInCancelTransfers = sal_False; + } +} + +SfxViewFrame* SfxFrame::GetCurrentViewFrame() const +{ + return pImp->pCurrentViewFrame; +} + +SfxDispatcher* SfxFrame::GetDispatcher_Impl() const +{ + if ( pImp->pCurrentViewFrame ) + return pImp->pCurrentViewFrame->GetDispatcher(); + return GetParentFrame()->GetDispatcher_Impl(); +} + +SfxObjectShell* SfxFrame::GetCurrentDocument() const +{ + return pImp->pCurrentViewFrame ? + pImp->pCurrentViewFrame->GetObjectShell() : + NULL; +} + +void SfxFrame::SetCurrentViewFrame_Impl( SfxViewFrame *pFrame ) +{ + pImp->pCurrentViewFrame = pFrame; +} + +sal_uInt32 SfxFrame::GetFrameType() const +{ + return pImp->nType; +} + +void SfxFrame::SetFrameType_Impl( sal_uInt32 n ) +{ + pImp->nType = n; +} + +void SfxFrame::GetViewData_Impl() +{ + // Update all modifiable data between load and unload, the + // fixed data is only processed once (after PrepareForDoc_Impl in + // updateDescriptor) to save time. + + SfxViewFrame* pViewFrame = GetCurrentViewFrame(); + if( pViewFrame && pViewFrame->GetViewShell() ) + { + const SfxMedium *pMed = GetCurrentDocument()->GetMedium(); + sal_Bool bReadOnly = pMed->GetOpenMode() == SFX_STREAM_READONLY; + GetDescriptor()->SetReadOnly( bReadOnly ); + + SfxItemSet *pSet = GetDescriptor()->GetArgs(); + sal_Bool bGetViewData = sal_False; + if ( GetController().is() && pSet->GetItemState( SID_VIEW_DATA ) != SFX_ITEM_SET ) + { + ::com::sun::star::uno::Any aData = GetController()->getViewData(); + pSet->Put( SfxUsrAnyItem( SID_VIEW_DATA, aData ) ); + bGetViewData = sal_True; + } + + if ( pViewFrame->GetCurViewId() ) + pSet->Put( SfxUInt16Item( SID_VIEW_ID, pViewFrame->GetCurViewId() ) ); + if ( pChildArr ) + { + // For Framesets also the data from the ChildViews hace to be processed + sal_uInt16 nCount = pChildArr->Count(); + for ( sal_uInt16 n=nCount; n>0; n--) + { + SfxFrame* pFrame = (*pChildArr)[n-1]; + if ( bGetViewData ) + pFrame->GetDescriptor()->GetArgs()->ClearItem( SID_VIEW_DATA ); + pFrame->GetViewData_Impl(); + } + } + } +} + +void SfxFrame::UpdateDescriptor( SfxObjectShell *pDoc ) +{ + // For PrepareForDoc_Impl frames, the descriptor of the updated + // and new itemset to be initialized. All data fir restoring the view + // are thus saved. If the document be replaced, GetViewData_Impl (so) + // the latest information hinzugef by "added. All together then the + // browser-history saved in. When you activate such frame pick entry + // is complete itemsets and the descriptor in the OpenDoc sent;. + // Here only the fixed properties identified "other adjustable, the + // retrieved by GetViewData (saves time). + + DBG_ASSERT( pDoc, "NULL-Document inserted ?!" ); + + GetParentFrame(); + const SfxMedium *pMed = pDoc->GetMedium(); + GetDescriptor()->SetActualURL( pMed->GetOrigURL() ); + + SFX_ITEMSET_ARG( pMed->GetItemSet(), pItem, SfxBoolItem, SID_EDITDOC, sal_False ); + sal_Bool bEditable = ( !pItem || pItem->GetValue() ); + + GetDescriptor()->SetEditable( bEditable ); + + // Mark FileOpen parameter + SfxItemSet* pItemSet = pMed->GetItemSet(); + String aMedName( pMed->GetName() ); + + const SfxFilter* pFilter = pMed->GetOrigFilter(); + String aFilter; + if ( pFilter ) + aFilter = pFilter->GetFilterName(); + + SFX_ITEMSET_ARG( pItemSet, pRefererItem, SfxStringItem, SID_REFERER, sal_False); + SFX_ITEMSET_ARG( pItemSet, pOptionsItem, SfxStringItem, SID_FILE_FILTEROPTIONS, sal_False); + SFX_ITEMSET_ARG( pItemSet, pTitle1Item, SfxStringItem, SID_DOCINFO_TITLE, sal_False); + + SfxItemSet *pSet = GetDescriptor()->GetArgs(); + + // Delete all old Items + pSet->ClearItem(); + + if ( pRefererItem ) + pSet->Put( *pRefererItem ); + else + pSet->Put( SfxStringItem( SID_REFERER, String() ) ); + + if ( pOptionsItem ) + pSet->Put( *pOptionsItem ); + + if ( pTitle1Item ) + pSet->Put( *pTitle1Item ); + + pSet->Put( SfxStringItem( SID_FILTER_NAME, aFilter )); +} + +//------------------------------------------------------------------------- + +void SfxFrame::SetDescriptor( SfxFrameDescriptor *pD ) +{ + DBG_ASSERT( pD, "No Descriptor!" ); + DBG_ASSERT( pD != pImp->pDescr, "Descriptor is already set!" ); + + if ( pImp->pDescr ) + { + // Only TopLevel-Frames handels their Descriptor, for the others + // this is done by the Frameset + if ( !pParentFrame ) + delete pImp->pDescr; + } + pImp->pDescr = pD; +} + +//------------------------------------------------------------------------- + +SfxFrameDescriptor* SfxFrame::GetDescriptor() const +{ + // Create a FrameDescriptor On Demand; if there is no TopLevel-Frame + // will result in an error, as no valid link is created. + + if ( !pImp->pDescr ) + { + DBG_ASSERT( !GetParentFrame(), "No TopLevel-Frame, but no Descriptor!" ); + pImp->pDescr = new SfxFrameDescriptor; + if ( GetCurrentDocument() ) + pImp->pDescr->SetURL( GetCurrentDocument()->GetMedium()->GetOrigURL() ); + } + return pImp->pDescr; +} + +//------------------------------------------------------------------------- + +void SfxFrame::GetTargetList( TargetList& rList ) const +{ + if ( !GetParentFrame() ) + { + // An empty string for 'No Target' + rList.push_back( new String() ); + rList.push_back( new String( DEFINE_CONST_UNICODE( "_top" ) ) ); + rList.push_back( new String( DEFINE_CONST_UNICODE( "_parent" ) ) ); + rList.push_back( new String( DEFINE_CONST_UNICODE( "_blank" ) ) ); + rList.push_back( new String( DEFINE_CONST_UNICODE( "_self" ) ) ); + } + + SfxViewFrame* pView = GetCurrentViewFrame(); + if( pView && pView->GetViewShell() && pChildArr ) + { + sal_uInt16 nCount = pChildArr->Count(); + for ( sal_uInt16 n=0; n<nCount; n++) + { + SfxFrame* pFrame = (*pChildArr)[n]; + pFrame->GetTargetList( rList ); + } + } +} + +//------------------------------------------------------------------------- + +SfxBroadcaster& SfxFrame::GetBroadcaster() const +{ + return *pImp; +} + +sal_Bool SfxFrame::IsParent( SfxFrame *pFrame ) const +{ + SfxFrame *pParent = pParentFrame; + while ( pParent ) + { + if ( pParent == pFrame ) + return sal_True; + pParent = pParent->pParentFrame; + } + + return sal_False; +} + +void SfxFrame::InsertTopFrame_Impl( SfxFrame* pFrame ) +{ + SfxFrameArr_Impl& rArr = *SFX_APP()->Get_Impl()->pTopFrames; + rArr.Insert( pFrame, rArr.Count() ); +} + +void SfxFrame::RemoveTopFrame_Impl( SfxFrame* pFrame ) +{ + SfxFrameArr_Impl& rArr = *SFX_APP()->Get_Impl()->pTopFrames; + rArr.Remove( rArr.GetPos( pFrame ) ); +} + +SfxFrameItem::SfxFrameItem( sal_uInt16 nWhichId, SfxViewFrame *p ) + : SfxPoolItem( nWhichId ), pFrame( p ? &p->GetFrame() : NULL ) +{ + wFrame = pFrame; +} + +SfxFrameItem::SfxFrameItem( sal_uInt16 nWhichId, SfxFrame *p ): + SfxPoolItem( nWhichId ), + pFrame( p ), wFrame( p ) +{ +} + +SfxFrameItem::SfxFrameItem( SfxFrame *p ): + SfxPoolItem( 0 ), + pFrame( p ), wFrame( p ) +{ +} + +int SfxFrameItem::operator==( const SfxPoolItem &rItem ) const +{ + return ((SfxFrameItem&)rItem).pFrame == pFrame && + ((SfxFrameItem&)rItem).wFrame == wFrame; +} + +//-------------------------------------------------------------------- + +String SfxFrameItem::GetValueText() const +{ + return String(); +} + +SfxPoolItem* SfxFrameItem::Clone( SfxItemPool *) const +{ + SfxFrameItem* pNew = new SfxFrameItem( wFrame); + pNew->SetFramePtr_Impl( pFrame ); + return pNew; +} + +bool SfxFrameItem::QueryValue( com::sun::star::uno::Any& rVal, sal_uInt8 ) const +{ + if ( wFrame ) + { + rVal <<= wFrame->GetFrameInterface(); + return sal_True; + } + + return sal_False; +} + +bool SfxFrameItem::PutValue( const com::sun::star::uno::Any& rVal, sal_uInt8 ) +{ + Reference < XFrame > xFrame; + if ( (rVal >>= xFrame) && xFrame.is() ) + { + SfxFrame* pFr = SfxFrame::GetFirst(); + while ( pFr ) + { + if ( pFr->GetFrameInterface() == xFrame ) + { + wFrame = pFrame = pFr; + return sal_True; + } + + pFr = SfxFrame::GetNext( *pFr ); + } + return sal_True; + } + + return sal_False; +} + + +SfxUsrAnyItem::SfxUsrAnyItem( sal_uInt16 nWhichId, const ::com::sun::star::uno::Any& rAny ) + : SfxPoolItem( nWhichId ) +{ + aValue = rAny; +} + +int SfxUsrAnyItem::operator==( const SfxPoolItem& /*rItem*/ ) const +{ + return sal_False; +} + +SfxPoolItem* SfxUsrAnyItem::Clone( SfxItemPool *) const +{ + return new SfxUsrAnyItem( Which(), aValue ); +} + +bool SfxUsrAnyItem::QueryValue( com::sun::star::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const +{ + rVal = aValue; + return sal_True; +} + +bool SfxUsrAnyItem::PutValue( const com::sun::star::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) +{ + aValue = rVal; + return sal_True; +} + +SfxUnoFrameItem::SfxUnoFrameItem() + : SfxPoolItem() + , m_xFrame() +{ +} + +SfxUnoFrameItem::SfxUnoFrameItem( sal_uInt16 nWhichId, const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& i_rFrame ) + : SfxPoolItem( nWhichId ) + , m_xFrame( i_rFrame ) +{ +} + +int SfxUnoFrameItem::operator==( const SfxPoolItem& i_rItem ) const +{ + return i_rItem.ISA( SfxUnoFrameItem ) && static_cast< const SfxUnoFrameItem& >( i_rItem ).m_xFrame == m_xFrame; +} + +SfxPoolItem* SfxUnoFrameItem::Clone( SfxItemPool* ) const +{ + return new SfxUnoFrameItem( Which(), m_xFrame ); +} + +bool SfxUnoFrameItem::QueryValue( com::sun::star::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const +{ + rVal <<= m_xFrame; + return sal_True; +} + +bool SfxUnoFrameItem::PutValue( const com::sun::star::uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) +{ + return ( rVal >>= m_xFrame ); +} + +SfxFrameIterator::SfxFrameIterator( const SfxFrame& rFrame, sal_Bool bRecur ) + : pFrame( &rFrame ) + , bRecursive( bRecur ) +{} + +SfxFrame* SfxFrameIterator::FirstFrame() +{ + // GetFirst starts the iteration at the first child frame + return pFrame->GetChildFrame( 0 ); +} + +SfxFrame* SfxFrameIterator::NextFrame( SfxFrame& rPrev ) +{ + // If recursion is requested testing is done first on Children. + SfxFrame *pRet = NULL; + if ( bRecursive ) + pRet = rPrev.GetChildFrame( 0 ); + if ( !pRet ) + { + // In other case continue with the siblings of rPrev + pRet = NextSibling_Impl( rPrev ); + } + + return pRet; +} + + +SfxFrame* SfxFrameIterator::NextSibling_Impl( SfxFrame& rPrev ) +{ + SfxFrame *pRet = NULL; + if ( &rPrev != pFrame ) + { + SfxFrameArr_Impl& rArr = *rPrev.pParentFrame->pChildArr; + sal_uInt16 nPos = rArr.GetPos( &rPrev ); + if ( nPos+1 < rArr.Count() ) + pRet = rArr[nPos+1]; + + if ( !pRet && rPrev.pParentFrame->pParentFrame ) + pRet = NextSibling_Impl( *rPrev.pParentFrame ); + } + + return pRet; +} + +sal_Bool SfxFrame::IsTop() const +{ + return GetFrameInterface().is() ? GetFrameInterface()->isTop() : sal_False; +} + +sal_Bool SfxFrame::HasComponent() const +{ + return sal_False; +} + +::com::sun::star::uno::Reference< ::com::sun::star::frame::XController > SfxFrame::GetController() const +{ + if ( pImp->pCurrentViewFrame && pImp->pCurrentViewFrame->GetViewShell() ) + return pImp->pCurrentViewFrame->GetViewShell()->GetController(); + else + return ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController > (); +} + +::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > SfxFrame::GetFrameInterface() const +{ + return pImp->xFrame; +} + +void SfxFrame::SetFrameInterface_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame ) +{ + pImp->xFrame = rFrame; + com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder; + if ( !rFrame.is() && GetCurrentViewFrame() ) + GetCurrentViewFrame()->GetBindings().SetRecorder_Impl( xRecorder ); +} + +void SfxFrame::Appear() +{ + if ( GetCurrentViewFrame() ) + { + GetCurrentViewFrame()->Show(); + GetWindow().Show(); + pImp->xFrame->getContainerWindow()->setVisible( sal_True ); + if ( pParentFrame ) + pParentFrame->Appear(); + Reference < ::com::sun::star::awt::XTopWindow > xTopWindow( pImp->xFrame->getContainerWindow(), UNO_QUERY ); + if ( xTopWindow.is() ) + xTopWindow->toFront(); + } +} + +void SfxFrame::AppearWithUpdate() +{ + Appear(); + if ( GetCurrentViewFrame() ) + GetCurrentViewFrame()->GetDispatcher()->Update_Impl( sal_True ); +} + +void SfxFrame::SetOwnsBindings_Impl( sal_Bool bSet ) +{ + pImp->bOwnsBindings = bSet; +} + +sal_Bool SfxFrame::OwnsBindings_Impl() const +{ + return pImp->bOwnsBindings; +} + +void SfxFrame::SetToolSpaceBorderPixel_Impl( const SvBorder& rBorder ) +{ + pImp->aBorder = rBorder; + SfxViewFrame *pF = GetCurrentViewFrame(); + if ( pF ) + { + Point aPos ( rBorder.Left(), rBorder.Top() ); + Size aSize( GetWindow().GetOutputSizePixel() ); + long nDeltaX = rBorder.Left() + rBorder.Right(); + if ( aSize.Width() > nDeltaX ) + aSize.Width() -= nDeltaX; + else + aSize.Width() = 0; + + long nDeltaY = rBorder.Top() + rBorder.Bottom(); + if ( aSize.Height() > nDeltaY ) + aSize.Height() -= nDeltaY; + else + aSize.Height() = 0; + + if ( GetParentFrame() ) + { + sal_Bool bHasTools = rBorder.Left() != rBorder.Right() || rBorder.Top() != rBorder.Bottom(); + pF->GetWindow().SetBorderStyle( bHasTools ? WINDOW_BORDER_NORMAL : WINDOW_BORDER_NOBORDER ); + } + + pF->GetWindow().SetPosSizePixel( aPos, aSize ); + } +} + +Rectangle SfxFrame::GetTopOuterRectPixel_Impl() const +{ + Size aSize( GetWindow().GetOutputSizePixel() ); + Point aPoint; + return ( Rectangle ( aPoint, aSize ) ); +} + +SfxWorkWindow* SfxFrame::GetWorkWindow_Impl() const +{ + if ( pImp->pWorkWin ) + return pImp->pWorkWin; + else if ( pParentFrame ) + return pParentFrame->GetWorkWindow_Impl(); + else + return NULL; +} + +void SfxFrame::SetWorkWindow_Impl( SfxWorkWindow* pWorkwin ) +{ + pImp->pWorkWin = pWorkwin; +} + +void SfxFrame::CreateWorkWindow_Impl() +{ + SfxFrame* pFrame = this; + + if ( IsInPlace() ) + { + // this makes sence only for inplace activated objects + try + { + Reference < XChild > xChild( GetCurrentDocument()->GetModel(), UNO_QUERY ); + if ( xChild.is() ) + { + Reference < XModel > xParent( xChild->getParent(), UNO_QUERY ); + if ( xParent.is() ) + { + Reference< XController > xParentCtrler = xParent->getCurrentController(); + if ( xParentCtrler.is() ) + { + Reference < XFrame > xFrame( xParentCtrler->getFrame() ); + SfxFrame* pFr = SfxFrame::GetFirst(); + while ( pFr ) + { + if ( pFr->GetFrameInterface() == xFrame ) + { + pFrame = pFr; + break; + } + + pFr = SfxFrame::GetNext( *pFr ); + } + } + } + } + } + catch(Exception&) + { + OSL_FAIL("SfxFrame::CreateWorkWindow_Impl: Exception cachted. Please try to submit a repoducable bug !"); + } + } + + pImp->pWorkWin = new SfxFrameWorkWin_Impl( &pFrame->GetWindow(), this, pFrame ); +} + +void SfxFrame::GrabFocusOnComponent_Impl() +{ + if ( pImp->bReleasingComponent ) + { + GetWindow().GrabFocus(); + return; + } + + Window* pFocusWindow = &GetWindow(); + if ( GetCurrentViewFrame() && GetCurrentViewFrame()->GetViewShell() && GetCurrentViewFrame()->GetViewShell()->GetWindow() ) + pFocusWindow = GetCurrentViewFrame()->GetViewShell()->GetWindow(); + + if( !pFocusWindow->HasChildPathFocus() ) + pFocusWindow->GrabFocus(); +} + +void SfxFrame::ReleasingComponent_Impl( sal_Bool bSet ) +{ + pImp->bReleasingComponent = bSet; +} + +sal_Bool SfxFrame::IsInPlace() const +{ + return pImp->bInPlace; +} + +void SfxFrame::SetInPlace_Impl( sal_Bool bSet ) +{ + pImp->bInPlace = bSet; +} + +void SfxFrame::Resize() +{ + if ( IsClosing_Impl() ) + return; + + if ( OwnsBindings_Impl() ) + { + if ( IsInPlace() ) + { + SetToolSpaceBorderPixel_Impl( SvBorder() ); + } + else + { + // check for IPClient that contains UIactive object or object that is currently UI activating + SfxWorkWindow *pWork = GetWorkWindow_Impl(); + SfxInPlaceClient* pClient = GetCurrentViewFrame()->GetViewShell() ? GetCurrentViewFrame()->GetViewShell()->GetUIActiveIPClient_Impl() : 0; + if ( pClient ) + { + uno::Reference < lang::XUnoTunnel > xObj( pClient->GetObject()->getComponent(), uno::UNO_QUERY ); + uno::Sequence < sal_Int8 > aSeq( SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence() ); + sal_Int64 nHandle = (xObj.is()? xObj->getSomething( aSeq ): 0); + if ( nHandle ) + { + SfxObjectShell* pDoc = reinterpret_cast< SfxObjectShell* >( sal::static_int_cast< sal_IntPtr >( nHandle )); + pWork = SfxViewFrame::GetFirst( pDoc )->GetFrame().GetWorkWindow_Impl(); + } + } + + if ( pWork ) + { + pWork->ArrangeChilds_Impl(); + pWork->ShowChilds_Impl(); + } + + // problem in presence of UIActive object: when the window is resized, but the toolspace border + // remains the same, setting the toolspace border at the ContainerEnvironment doesn't force a + // resize on the IPEnvironment; without that no resize is called for the SfxViewFrame. So always + // set the window size of the SfxViewFrame explicit. + SetToolSpaceBorderPixel_Impl( pImp->aBorder ); + } + } + else if ( pImp->pCurrentViewFrame ) + { + pImp->pCurrentViewFrame->GetWindow().SetSizePixel( GetWindow().GetOutputSizePixel() ); + } + +} + +SfxFrame* SfxFrame::GetFirst() +{ + if ( !pFramesArr_Impl ) + return 0; + return pFramesArr_Impl->Count() ? pFramesArr_Impl->GetObject(0) : 0; +} + +SfxFrame* SfxFrame::GetNext( SfxFrame& rFrame ) +{ + sal_uInt16 nPos = pFramesArr_Impl->GetPos( &rFrame ); + if ( nPos+1 < pFramesArr_Impl->Count() ) + return pFramesArr_Impl->GetObject(nPos+1); + else + return NULL; +} + +const SfxPoolItem* SfxFrame::OpenDocumentSynchron( SfxItemSet& i_rSet, const Reference< XFrame >& i_rTargetFrame ) +{ + i_rSet.Put( SfxUnoFrameItem( SID_FILLFRAME, i_rTargetFrame ) ); + i_rSet.ClearItem( SID_TARGETNAME ); + return SFX_APP()->GetDispatcher_Impl()->Execute( SID_OPENDOC, SFX_CALLMODE_SYNCHRON, i_rSet ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/frame2.cxx b/sfx2/source/view/frame2.cxx new file mode 100644 index 000000000000..924d2bd7e557 --- /dev/null +++ b/sfx2/source/view/frame2.cxx @@ -0,0 +1,482 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 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() ) + { + OSL_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*/ ) + { + 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; + + 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; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/frmload.cxx b/sfx2/source/view/frmload.cxx new file mode 100644 index 000000000000..a72b49ad1dc6 --- /dev/null +++ b/sfx2/source/view/frmload.cxx @@ -0,0 +1,716 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#include <sal/macros.h> +#include "frmload.hxx" +#include "objshimp.hxx" +#include "sfx2/app.hxx" +#include "sfx2/dispatch.hxx" +#include "sfx2/docfac.hxx" +#include "sfx2/docfile.hxx" +#include "sfx2/docfilt.hxx" +#include "sfx2/doctempl.hxx" +#include "sfx2/fcontnr.hxx" +#include "sfx2/frame.hxx" +#include "sfx2/request.hxx" +#include "sfx2/sfx.hrc" +#include "sfx2/sfxsids.hrc" +#include "sfx2/sfxuno.hxx" +#include "sfx2/viewfrm.hxx" +#include "sfx2/viewsh.hxx" +#include "sfx2/viewfac.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/container/XContainerQuery.hpp> +#include <com/sun/star/document/XTypeDetection.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XLoadable.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/task/XInteractionHandler2.hpp> +#include <com/sun/star/document/XViewDataSupplier.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +/** === end UNO includes === **/ + +#include <comphelper/interaction.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <framework/interaction.hxx> +#include <rtl/logfile.hxx> +#include <rtl/ustring.h> +#include <sot/storinfo.hxx> +#include <svtools/ehdl.hxx> +#include <svl/eitem.hxx> +#include <svl/itemset.hxx> +#include <unotools/moduleoptions.hxx> +#include <svtools/sfxecode.hxx> +#include <svl/stritem.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <tools/diagnose_ex.h> +#include <ucbhelper/simpleinteractionrequest.hxx> +#include <osl/mutex.hxx> + +/** === begin UNO using === **/ +using ::com::sun::star::beans::PropertyValue; +using ::com::sun::star::container::XContainerQuery; +using ::com::sun::star::container::XEnumeration; +using ::com::sun::star::document::XTypeDetection; +using ::com::sun::star::frame::XFrame; +using ::com::sun::star::frame::XLoadable; +using ::com::sun::star::frame::XModel; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::task::XInteractionHandler; +using ::com::sun::star::task::XInteractionHandler2; +using ::com::sun::star::task::XInteractionRequest; +using ::com::sun::star::task::XStatusIndicator; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::UNO_SET_THROW; +using ::com::sun::star::uno::makeAny; +using ::com::sun::star::util::XCloseable; +using ::com::sun::star::document::XViewDataSupplier; +using ::com::sun::star::container::XIndexAccess; +using ::com::sun::star::frame::XController2; +using ::com::sun::star::frame::XController; +using ::com::sun::star::frame::XModel2; +/** === end UNO using === **/ + +SfxFrameLoader_Impl::SfxFrameLoader_Impl( const Reference< XMultiServiceFactory >& _rxFactory ) + :m_aContext( _rxFactory ) +{ +} + +SfxFrameLoader_Impl::~SfxFrameLoader_Impl() +{ +} + +// -------------------------------------------------------------------------------------------------------------------- +const SfxFilter* SfxFrameLoader_Impl::impl_detectFilterForURL( const ::rtl::OUString& sURL, + const ::comphelper::NamedValueCollection& i_rDescriptor, const SfxFilterMatcher& rMatcher ) const +{ + ::rtl::OUString sFilter; + try + { + if ( !sURL.getLength() ) + return 0; + + Reference< XTypeDetection > xDetect( + m_aContext.createComponent( "com.sun.star.document.TypeDetection" ), + UNO_QUERY_THROW); + + ::comphelper::NamedValueCollection aNewArgs; + aNewArgs.put( "URL", sURL ); + + if ( i_rDescriptor.has( "InteractionHandler" ) ) + aNewArgs.put( "InteractionHandler", i_rDescriptor.get( "InteractionHandler" ) ); + if ( i_rDescriptor.has( "StatusIndicator" ) ) + aNewArgs.put( "StatusIndicator", i_rDescriptor.get( "StatusIndicator" ) ); + + Sequence< PropertyValue > aQueryArgs( aNewArgs.getPropertyValues() ); + ::rtl::OUString sType = xDetect->queryTypeByDescriptor( aQueryArgs, sal_True ); + if ( sType.getLength() ) + { + const SfxFilter* pFilter = rMatcher.GetFilter4EA( sType ); + if ( pFilter ) + sFilter = pFilter->GetName(); + } + } + catch ( const RuntimeException& ) + { + throw; + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + sFilter = ::rtl::OUString(); + } + + const SfxFilter* pFilter = 0; + if (sFilter.getLength()) + pFilter = rMatcher.GetFilter4FilterName(sFilter); + return pFilter; +} + +// -------------------------------------------------------------------------------------------------------------------- +const SfxFilter* SfxFrameLoader_Impl::impl_getFilterFromServiceName_nothrow( const ::rtl::OUString& i_rServiceName ) const +{ + try + { + ::comphelper::NamedValueCollection aQuery; + aQuery.put( "DocumentService", i_rServiceName ); + + const Reference< XContainerQuery > xQuery( + m_aContext.createComponent( "com.sun.star.document.FilterFactory" ), + UNO_QUERY_THROW ); + + const SfxFilterMatcher& rMatcher = SFX_APP()->GetFilterMatcher(); + const SfxFilterFlags nMust = SFX_FILTER_IMPORT; + const SfxFilterFlags nDont = SFX_FILTER_NOTINSTALLED; + + Reference < XEnumeration > xEnum( xQuery->createSubSetEnumerationByProperties( + aQuery.getNamedValues() ), UNO_SET_THROW ); + while ( xEnum->hasMoreElements() ) + { + ::comphelper::NamedValueCollection aType( xEnum->nextElement() ); + ::rtl::OUString sFilterName = aType.getOrDefault( "Name", ::rtl::OUString() ); + if ( !sFilterName.getLength() ) + continue; + + const SfxFilter* pFilter = rMatcher.GetFilter4FilterName( sFilterName ); + if ( !pFilter ) + continue; + + SfxFilterFlags nFlags = pFilter->GetFilterFlags(); + if ( ( ( nFlags & nMust ) == nMust ) + && ( ( nFlags & nDont ) == 0 ) + ) + { + return pFilter; + } + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + return NULL; +} + +// -------------------------------------------------------------------------------------------------------------------- +::rtl::OUString SfxFrameLoader_Impl::impl_askForFilter_nothrow( const Reference< XInteractionHandler >& i_rxHandler, + const ::rtl::OUString& i_rDocumentURL ) const +{ + ENSURE_OR_THROW( i_rxHandler.is(), "invalid interaction handler" ); + + ::rtl::OUString sFilterName; + try + { + ::framework::RequestFilterSelect aRequest( i_rDocumentURL ); + i_rxHandler->handle( aRequest.GetRequest() ); + if( !aRequest.isAbort() ) + sFilterName = aRequest.getFilter(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + return sFilterName; +} + +// -------------------------------------------------------------------------------------------------------------------- +namespace +{ + sal_Bool lcl_getDispatchResult( const SfxPoolItem* _pResult ) + { + if ( !_pResult ) + return sal_False; + + // default must be set to true, because some return values + // cant be checked, but nonetheless indicate "success"! + sal_Bool bSuccess = sal_True; + + // On the other side some special slots return a boolean state, + // which can be set to FALSE. + SfxBoolItem *pItem = PTR_CAST( SfxBoolItem, _pResult ); + if ( pItem ) + bSuccess = pItem->GetValue(); + + return bSuccess; + } +} + +// -------------------------------------------------------------------------------------------------------------------- +sal_Bool SfxFrameLoader_Impl::impl_createNewDocWithSlotParam( const sal_uInt16 _nSlotID, const Reference< XFrame >& i_rxFrame, + const bool i_bHidden ) +{ + SfxRequest aRequest( _nSlotID, SFX_CALLMODE_SYNCHRON, SFX_APP()->GetPool() ); + aRequest.AppendItem( SfxUnoFrameItem( SID_FILLFRAME, i_rxFrame ) ); + if ( i_bHidden ) + aRequest.AppendItem( SfxBoolItem( SID_HIDDEN, sal_True ) ); + return lcl_getDispatchResult( SFX_APP()->ExecuteSlot( aRequest ) ); +} + +// -------------------------------------------------------------------------------------------------------------------- +void SfxFrameLoader_Impl::impl_determineFilter( ::comphelper::NamedValueCollection& io_rDescriptor ) const +{ + const ::rtl::OUString sURL = io_rDescriptor.getOrDefault( "URL", ::rtl::OUString() ); + const ::rtl::OUString sTypeName = io_rDescriptor.getOrDefault( "TypeName", ::rtl::OUString() ); + const ::rtl::OUString sFilterName = io_rDescriptor.getOrDefault( "FilterName", ::rtl::OUString() ); + const ::rtl::OUString sServiceName = io_rDescriptor.getOrDefault( "DocumentService", ::rtl::OUString() ); + const Reference< XInteractionHandler > + xInteraction = io_rDescriptor.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ); + + const SfxFilterMatcher& rMatcher = SFX_APP()->GetFilterMatcher(); + const SfxFilter* pFilter = NULL; + + // get filter by its name directly ... + if ( sFilterName.getLength() ) + pFilter = rMatcher.GetFilter4FilterName( sFilterName ); + + // or search the preferred filter for the detected type ... + if ( !pFilter && sTypeName.getLength() ) + pFilter = rMatcher.GetFilter4EA( sTypeName ); + + // or use given document service for detection, too + if ( !pFilter && sServiceName.getLength() ) + pFilter = impl_getFilterFromServiceName_nothrow( sServiceName ); + + // or use interaction to ask user for right filter. + if ( !pFilter && xInteraction.is() && sURL.getLength() ) + { + ::rtl::OUString sSelectedFilter = impl_askForFilter_nothrow( xInteraction, sURL ); + if ( sSelectedFilter.getLength() ) + pFilter = rMatcher.GetFilter4FilterName( sSelectedFilter ); + } + + if ( pFilter ) + { + io_rDescriptor.put( "FilterName", ::rtl::OUString( pFilter->GetFilterName() ) ); + + // If detected filter indicates using of an own template format + // add property "AsTemplate" to descriptor. But suppress this step + // if such property already exists. + if ( pFilter->IsOwnTemplateFormat() && !io_rDescriptor.has( "AsTemplate" ) ) + io_rDescriptor.put( "AsTemplate", sal_Bool( sal_True ) ); + + // The DocumentService property will finally be used to determine the document type to create, so + // override it with the service name as indicated by the found filter. + io_rDescriptor.put( "DocumentService", ::rtl::OUString( pFilter->GetServiceName() ) ); + } +} + +// -------------------------------------------------------------------------------------------------------------------- +SfxObjectShellRef SfxFrameLoader_Impl::impl_findObjectShell( const Reference< XModel2 >& i_rxDocument ) const +{ + for ( SfxObjectShell* pDoc = SfxObjectShell::GetFirst( NULL, sal_False ); pDoc; pDoc = SfxObjectShell::GetNext( *pDoc, NULL, sal_False ) ) + { + if ( i_rxDocument == pDoc->GetModel() ) + { + return pDoc; + } + } + + OSL_FAIL( "SfxFrameLoader_Impl::impl_findObjectShell: model is not based on SfxObjectShell - wrong frame loader usage!" ); + return NULL; +} + +// -------------------------------------------------------------------------------------------------------------------- +bool SfxFrameLoader_Impl::impl_determineTemplateDocument( ::comphelper::NamedValueCollection& io_rDescriptor ) const +{ + const ::rtl::OUString sTemplateRegioName = io_rDescriptor.getOrDefault( "TemplateRegionName", ::rtl::OUString() ); + const ::rtl::OUString sTemplateName = io_rDescriptor.getOrDefault( "TemplateName", ::rtl::OUString() ); + const ::rtl::OUString sServiceName = io_rDescriptor.getOrDefault( "DocumentService", ::rtl::OUString() ); + const ::rtl::OUString sURL = io_rDescriptor.getOrDefault( "URL", ::rtl::OUString() ); + + // determine the full URL of the template to use, if any + String sTemplateURL; + if ( sTemplateRegioName.getLength() && sTemplateName.getLength() ) + { + SfxDocumentTemplates aTmpFac; + aTmpFac.GetFull( sTemplateRegioName, sTemplateName, sTemplateURL ); + } + else + { + if ( sServiceName.getLength() ) + sTemplateURL = SfxObjectFactory::GetStandardTemplate( sServiceName ); + else + sTemplateURL = SfxObjectFactory::GetStandardTemplate( SfxObjectShell::GetServiceNameFromFactory( sURL ) ); + } + + if ( sTemplateURL.Len() > 0 ) + { + // detect the filter for the template. Might still be NULL (if the template is broken, or does not + // exist, or some such), but this is handled by our caller the same way as if no template/URL was present. + const SfxFilter* pTemplateFilter = impl_detectFilterForURL( sTemplateURL, io_rDescriptor, SFX_APP()->GetFilterMatcher() ); + if ( pTemplateFilter ) + { + // load the template document, but, well, "as template" + io_rDescriptor.put( "FilterName", ::rtl::OUString( pTemplateFilter->GetName() ) ); + io_rDescriptor.put( "FileName", ::rtl::OUString( sTemplateURL ) ); + io_rDescriptor.put( "AsTemplate", sal_True ); + + // #i21583# + // the DocumentService property will finally be used to create the document. Thus, override any possibly + // present value with the document service of the template. + io_rDescriptor.put( "DocumentService", ::rtl::OUString( pTemplateFilter->GetServiceName() ) ); + return true; + } + } + return false; +} + +// -------------------------------------------------------------------------------------------------------------------- +sal_uInt16 SfxFrameLoader_Impl::impl_findSlotParam( const ::rtl::OUString& i_rFactoryURL ) const +{ + ::rtl::OUString sSlotParam; + const sal_Int32 nParamPos = i_rFactoryURL.indexOf( '?' ); + if ( nParamPos >= 0 ) + { + // currently only the "slot" parameter is supported + const sal_Int32 nSlotPos = i_rFactoryURL.indexOfAsciiL( RTL_CONSTASCII_STRINGPARAM( "slot=" ), nParamPos ); + if ( nSlotPos > 0 ) + sSlotParam = i_rFactoryURL.copy( nSlotPos + 5 ); + } + + if ( sSlotParam.getLength() ) + return sal_uInt16( sSlotParam.toInt32() ); + + return 0; +} + +// -------------------------------------------------------------------------------------------------------------------- +void SfxFrameLoader_Impl::impl_handleCaughtError_nothrow( const Any& i_rCaughtError, const ::comphelper::NamedValueCollection& i_rDescriptor ) const +{ + try + { + const Reference< XInteractionHandler > xInteraction = + i_rDescriptor.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ); + if ( !xInteraction.is() ) + return; + ::rtl::Reference< ::comphelper::OInteractionRequest > pRequest( new ::comphelper::OInteractionRequest( i_rCaughtError ) ); + ::rtl::Reference< ::comphelper::OInteractionApprove > pApprove( new ::comphelper::OInteractionApprove ); + pRequest->addContinuation( pApprove.get() ); + + const Reference< XInteractionHandler2 > xHandler( xInteraction, UNO_QUERY ); + #if OSL_DEBUG_LEVEL > 0 + const sal_Bool bHandled = + #endif + xHandler.is() && xHandler->handleInteractionRequest( pRequest.get() ); + + #if OSL_DEBUG_LEVEL > 0 + if ( !bHandled ) + // the interaction handler couldn't deal with this error + // => report it as assertion, at least (done in the DBG_UNHANDLED_EXCEPTION below) + ::cppu::throwException( i_rCaughtError ); + #endif + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +// -------------------------------------------------------------------------------------------------------------------- +void SfxFrameLoader_Impl::impl_removeLoaderArguments( ::comphelper::NamedValueCollection& io_rDescriptor ) +{ + // remove the arguments which are for the loader only, and not for a call to attachResource + io_rDescriptor.remove( "StatusIndicator" ); + io_rDescriptor.remove( "Model" ); +} + +// -------------------------------------------------------------------------------------------------------------------- +::comphelper::NamedValueCollection SfxFrameLoader_Impl::impl_extractViewCreationArgs( ::comphelper::NamedValueCollection& io_rDescriptor ) +{ + const sal_Char* pKnownViewArgs[] = { + "JumpMark" + }; + + ::comphelper::NamedValueCollection aViewArgs; + for ( size_t i=0; i < SAL_N_ELEMENTS( pKnownViewArgs ); ++i ) + { + if ( io_rDescriptor.has( pKnownViewArgs[i] ) ) + { + aViewArgs.put( pKnownViewArgs[i], io_rDescriptor.get( pKnownViewArgs[i] ) ); + io_rDescriptor.remove( pKnownViewArgs[i] ); + } + } + return aViewArgs; +} + +// -------------------------------------------------------------------------------------------------------------------- +sal_Int16 SfxFrameLoader_Impl::impl_determineEffectiveViewId_nothrow( const SfxObjectShell& i_rDocument, const ::comphelper::NamedValueCollection& i_rDescriptor ) +{ + sal_Int16 nViewId = i_rDescriptor.getOrDefault( "ViewId", sal_Int16( 0 ) ); + try + { + if ( nViewId == 0 ) do + { + Reference< XViewDataSupplier > xViewDataSupplier( i_rDocument.GetModel(), UNO_QUERY ); + Reference< XIndexAccess > xViewData; + if ( xViewDataSupplier.is() ) + xViewData.set( xViewDataSupplier->getViewData() ); + + if ( !xViewData.is() || ( xViewData->getCount() == 0 ) ) + // no view data stored together with the model + break; + + // obtain the ViewID from the view data + Sequence< PropertyValue > aViewData; + if ( !( xViewData->getByIndex( 0 ) >>= aViewData ) ) + break; + + ::comphelper::NamedValueCollection aNamedViewData( aViewData ); + ::rtl::OUString sViewId = aNamedViewData.getOrDefault( "ViewId", ::rtl::OUString() ); + if ( !sViewId.getLength() ) + break; + + // somewhat weird convention here ... in the view data, the ViewId is a string, effectively describing + // a view name. In the document load descriptor, the ViewId is in fact the numeric ID. + + SfxViewFactory* pViewFactory = i_rDocument.GetFactory().GetViewFactoryByViewName( sViewId ); + if ( pViewFactory ) + nViewId = sal_Int16( pViewFactory->GetOrdinal() ); + } + while ( false ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + if ( nViewId == 0 ) + nViewId = i_rDocument.GetFactory().GetViewFactory( 0 ).GetOrdinal(); + return nViewId; +} + +// -------------------------------------------------------------------------------------------------------------------- +Reference< XController2 > SfxFrameLoader_Impl::impl_createDocumentView( const Reference< XModel2 >& i_rModel, + const Reference< XFrame >& i_rFrame, const ::comphelper::NamedValueCollection& i_rViewFactoryArgs, + const ::rtl::OUString& i_rViewName ) +{ + // let the model create a new controller + const Reference< XController2 > xController( i_rModel->createViewController( + i_rViewName, + i_rViewFactoryArgs.getPropertyValues(), + i_rFrame + ), UNO_SET_THROW ); + + // introduce model/view/controller to each other + xController->attachModel( i_rModel.get() ); + i_rModel->connectController( xController.get() ); + i_rFrame->setComponent( xController->getComponentWindow(), xController.get() ); + xController->attachFrame( i_rFrame ); + i_rModel->setCurrentController( xController.get() ); + + return xController; +} + +// -------------------------------------------------------------------------------------------------------------------- +sal_Bool SAL_CALL SfxFrameLoader_Impl::load( const Sequence< PropertyValue >& rArgs, + const Reference< XFrame >& _rTargetFrame ) + throw( RuntimeException ) +{ + ENSURE_OR_THROW( _rTargetFrame.is(), "illegal NULL frame" ); + + SolarMutexGuard aGuard; + + RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mb93783) ::SfxFrameLoader::load" ); + + ::comphelper::NamedValueCollection aDescriptor( rArgs ); + + // ensure the descriptor contains a referrer + if ( !aDescriptor.has( "Referer" ) ) + aDescriptor.put( "Referer", ::rtl::OUString() ); + + // TODO: is this needed? finally, when loading is successfull, then there should be no need for this item, + // as the document can always obtain its frame. In particular, there might be situations where this frame + // is accessed, but already disposed: Imagine the user loading a document, opening a second view on it, and + // then closing the first view/frame. + aDescriptor.put( "Frame", _rTargetFrame ); + + // did the caller already pass a model? + Reference< XModel2 > xModel = aDescriptor.getOrDefault( "Model", Reference< XModel2 >() ); + const bool bExternalModel = xModel.is(); + + // check for factory URLs to create a new doc, instead of loading one + const ::rtl::OUString sURL = aDescriptor.getOrDefault( "URL", ::rtl::OUString() ); + const bool bIsFactoryURL = ( sURL.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "private:factory/" ) ) == 0 ); + bool bInitNewModel = bIsFactoryURL; + if ( bIsFactoryURL && !bExternalModel ) + { + const ::rtl::OUString sFactory = sURL.copy( sizeof( "private:factory/" ) -1 ); + // special handling for some weird factory URLs a la private:factory/swriter?slot=21053 + const sal_uInt16 nSlotParam = impl_findSlotParam( sFactory ); + if ( nSlotParam != 0 ) + { + return impl_createNewDocWithSlotParam( nSlotParam, _rTargetFrame, aDescriptor.getOrDefault( "Hidden", false ) ); + } + + const bool bDescribesValidTemplate = impl_determineTemplateDocument( aDescriptor ); + if ( bDescribesValidTemplate ) + { + // if the media descriptor allowed us to determine a template document to create the new document + // from, then do not init a new document model from scratch (below), but instead load the + // template document + bInitNewModel = false; + } + else + { + const ::rtl::OUString sServiceName = SfxObjectShell::GetServiceNameFromFactory( sFactory ); + aDescriptor.put( "DocumentService", sServiceName ); + } + } + else + { + // compatibility + aDescriptor.put( "FileName", aDescriptor.get( "URL" ) ); + } + + sal_Bool bLoadSuccess = sal_False; + try + { + // extract view releant arguments from the loader args + ::comphelper::NamedValueCollection aViewCreationArgs( impl_extractViewCreationArgs( aDescriptor ) ); + + // no model passed from outside? => create one from scratch + if ( !xModel.is() ) + { + // beforehand, determine the filter to use, and update the descriptor with its information + if ( !bInitNewModel ) + { + impl_determineFilter( aDescriptor ); + } + + // create the new doc + const ::rtl::OUString sServiceName = aDescriptor.getOrDefault( "DocumentService", ::rtl::OUString() ); + xModel.set( m_aContext.createComponent( sServiceName ), UNO_QUERY_THROW ); + + // load resp. init it + const Reference< XLoadable > xLoadable( xModel, UNO_QUERY_THROW ); + if ( bInitNewModel ) + { + xLoadable->initNew(); + + impl_removeLoaderArguments( aDescriptor ); + xModel->attachResource( ::rtl::OUString(), aDescriptor.getPropertyValues() ); + } + else + { + xLoadable->load( aDescriptor.getPropertyValues() ); + } + } + else + { + // tell the doc its (current) load args. + impl_removeLoaderArguments( aDescriptor ); + xModel->attachResource( xModel->getURL(), aDescriptor.getPropertyValues() ); + } + + // get the SfxObjectShell (still needed at the moment) + // SfxObjectShellRef is used here ( instead of ...Lock ) since the model is closed below if necessary + // SfxObjectShellLock would be even dangerous here, since the lifetime control should be done outside in case of success + const SfxObjectShellRef xDoc = impl_findObjectShell( xModel ); + ENSURE_OR_THROW( xDoc.Is(), "no SfxObjectShell for the given model" ); + + // ensure the ID of the to-be-created view is in the descriptor, if possible + const sal_Int16 nViewId = impl_determineEffectiveViewId_nothrow( *xDoc, aDescriptor ); + const sal_Int16 nViewNo = xDoc->GetFactory().GetViewNo_Impl( nViewId, 0 ); + const ::rtl::OUString sViewName( xDoc->GetFactory().GetViewFactory( nViewNo ).GetAPIViewName() ); + + // plug the document into the frame + impl_createDocumentView( xModel, _rTargetFrame, aViewCreationArgs, sViewName ); + bLoadSuccess = sal_True; + } + catch ( Exception& ) + { + const Any aError( ::cppu::getCaughtException() ); + if ( !aDescriptor.getOrDefault( "Silent", sal_False ) ) + impl_handleCaughtError_nothrow( aError, aDescriptor ); + } + + // if loading was not successful, close the document + if ( !bLoadSuccess && !bExternalModel ) + { + try + { + const Reference< XCloseable > xCloseable( xModel, UNO_QUERY_THROW ); + xCloseable->close( sal_True ); + } + catch ( Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + return bLoadSuccess; +} + +void SfxFrameLoader_Impl::cancel() throw( RuntimeException ) +{ +} + +SFX_IMPL_SINGLEFACTORY( SfxFrameLoader_Impl ) + +/* XServiceInfo */ +UNOOUSTRING SAL_CALL SfxFrameLoader_Impl::getImplementationName() throw( RuntimeException ) +{ + return impl_getStaticImplementationName(); +} + \ +/* XServiceInfo */ +sal_Bool SAL_CALL SfxFrameLoader_Impl::supportsService( const UNOOUSTRING& sServiceName ) throw( RuntimeException ) +{ + UNOSEQUENCE< UNOOUSTRING > seqServiceNames = getSupportedServiceNames(); + const UNOOUSTRING* pArray = seqServiceNames.getConstArray(); + for ( sal_Int32 nCounter=0; nCounter<seqServiceNames.getLength(); nCounter++ ) + { + if ( pArray[nCounter] == sServiceName ) + { + return sal_True ; + } + } + return sal_False ; +} + +/* XServiceInfo */ +UNOSEQUENCE< UNOOUSTRING > SAL_CALL SfxFrameLoader_Impl::getSupportedServiceNames() throw( RuntimeException ) +{ + return impl_getStaticSupportedServiceNames(); +} + +/* Helper for XServiceInfo */ +UNOSEQUENCE< UNOOUSTRING > SfxFrameLoader_Impl::impl_getStaticSupportedServiceNames() +{ + UNOMUTEXGUARD aGuard( UNOMUTEX::getGlobalMutex() ); + UNOSEQUENCE< UNOOUSTRING > seqServiceNames( 1 ); + seqServiceNames.getArray() [0] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.SynchronousFrameLoader" )); + return seqServiceNames ; +} + +/* Helper for XServiceInfo */ +UNOOUSTRING SfxFrameLoader_Impl::impl_getStaticImplementationName() +{ + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.office.FrameLoader" )); +} + +/* Helper for registry */ +UNOREFERENCE< UNOXINTERFACE > SAL_CALL SfxFrameLoader_Impl::impl_createInstance( const UNOREFERENCE< UNOXMULTISERVICEFACTORY >& xServiceManager ) throw( UNOEXCEPTION ) +{ + return UNOREFERENCE< UNOXINTERFACE >( *new SfxFrameLoader_Impl( xServiceManager ) ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/impframe.hxx b/sfx2/source/view/impframe.hxx new file mode 100644 index 000000000000..b49f9dd777a4 --- /dev/null +++ b/sfx2/source/view/impframe.hxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SFX_IMPFRAME_HXX +#define _SFX_IMPFRAME_HXX + +#include <sfx2/frame.hxx> +#include <sfx2/viewfrm.hxx> // SvBorder + +class SfxViewFrame; +class SfxObjectShell; +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/awt/XTopWindow.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <cppuhelper/weak.hxx> + +#include <sfx2/viewsh.hxx> +#include <sfx2/sfxuno.hxx> + +#ifndef FRAME_SEARCH_PARENT +#define FRAME_SEARCH_PARENT 0x00000001 +#define FRAME_SEARCH_SELF 0x00000002 +#define FRAME_SEARCH_CHILDREN 0x00000004 +#define FRAME_SEARCH_CREATE 0x00000008 +#endif + +class SfxFrame_Impl : public SfxBroadcaster, public SvCompatWeakBase +{ +public: + ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > xFrame; + sal_uInt32 nType; + SfxViewFrame* pCurrentViewFrame; + SfxFrameDescriptor* pDescr; + sal_uInt16 nLocks; + sal_Bool bClosing : 1; + sal_Bool bPrepClosing : 1; + sal_Bool bInCancelTransfers : 1; + sal_Bool bOwnsBindings : 1; + sal_Bool bReleasingComponent : 1; + sal_Bool bInPlace : 1; + SfxFrame* pFrame; + SfxWorkWindow* pWorkWin; + SvBorder aBorder; + // formerly SfxTopFrame + Window* pExternalContainerWindow; + bool bHidden; + bool bLockResize; + bool bMenuBarOn; + + SfxFrame_Impl( SfxFrame* pAntiImplP ) + :SvCompatWeakBase( pAntiImplP ) + ,nType( 0L ) + ,pCurrentViewFrame( NULL ) + ,pDescr( NULL ) + ,nLocks( 0 ) + ,bClosing(sal_False) + ,bPrepClosing(sal_False) + ,bInCancelTransfers( sal_False ) + ,bOwnsBindings( sal_False ) + ,bReleasingComponent( sal_False ) + ,bInPlace( sal_False ) + ,pFrame( pAntiImplP ) + ,pWorkWin( 0 ) + ,pExternalContainerWindow( NULL ) + ,bHidden( false ) + ,bLockResize( false ) + ,bMenuBarOn( true ) + { + } + + virtual ~SfxFrame_Impl() { } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/impviewframe.hxx b/sfx2/source/view/impviewframe.hxx new file mode 100644 index 000000000000..c4b3d081843e --- /dev/null +++ b/sfx2/source/view/impviewframe.hxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* Copyright 2009 by Sun Microsystems, Inc. +* +* OpenOffice.org - a multi-platform office productivity suite +* +* This file is part of OpenOffice.org. +* +* OpenOffice.org is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License version 3 +* only, as published by the Free Software Foundation. +* +* OpenOffice.org is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License version 3 for more details +* (a copy is included in the LICENSE file that accompanied this code). +* +* You should have received a copy of the GNU Lesser General Public License +* version 3 along with OpenOffice.org. If not, see +* <http://www.openoffice.org/license.html> +* for a copy of the LGPLv3 License. +************************************************************************/ + +#ifndef SFX2_IMPVIEWFRAME_HXX +#define SFX2_IMPVIEWFRAME_HXX + +#include "sfx2/viewfrm.hxx" + +#include <svtools/asynclink.hxx> +#include <vcl/window.hxx> + +#include <boost/optional.hpp> + +struct SfxViewFrame_Impl +{ + SvBorder aBorder; + Size aMargin; + Size aSize; + String aFrameTitle; + TypeId aLastType; + String aActualURL; + SfxFrame& rFrame; + svtools::AsynchronLink* pReloader; + Window* pWindow; + SfxViewFrame* pActiveChild; + Window* pFocusWin; + sal_uInt16 nDocViewNo; + sal_uInt16 nCurViewId; + sal_Bool bResizeInToOut:1; + sal_Bool bDontOverwriteResizeInToOut:1; + sal_Bool bObjLocked:1; + sal_Bool bReloading:1; + sal_Bool bIsDowning:1; + sal_Bool bModal:1; + sal_Bool bEnabled:1; + sal_Bool bWindowWasEnabled:1; + sal_Bool bActive; + String aFactoryName; + ::boost::optional< bool > + aHasToolPanels; + + SfxViewFrame_Impl( SfxFrame& i_rFrame ) + : rFrame( i_rFrame ) + , pReloader(0 ) + , pWindow( 0 ) + , bWindowWasEnabled(sal_True) + , bActive( sal_False ) + { + } + + ~SfxViewFrame_Impl() + { + delete pReloader; + } +}; + +class SfxFrameViewWindow_Impl : public Window +{ + sal_Bool bActive; + SfxViewFrame* pFrame; + +public: + SfxFrameViewWindow_Impl( SfxViewFrame* p, Window& rParent, WinBits nBits=0 ) : + Window( &rParent, nBits | WB_BORDER | WB_CLIPCHILDREN ), + bActive( sal_False ), + pFrame( p ) + { + p->GetFrame().GetWindow().SetBorderStyle( WINDOW_BORDER_NOBORDER ); + } + + virtual void Resize(); + virtual void StateChanged( StateChangedType nStateChange ); +}; + +#endif // SFX2_IMPVIEWFRAME_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/ipclient.cxx b/sfx2/source/view/ipclient.cxx new file mode 100644 index 000000000000..bcbb1e349058 --- /dev/null +++ b/sfx2/source/view/ipclient.cxx @@ -0,0 +1,1156 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/embed/XVisualObject.hpp> +#include <com/sun/star/embed/XEmbeddedClient.hpp> +#include <com/sun/star/embed/XInplaceClient.hpp> +#include <com/sun/star/embed/XInplaceObject.hpp> +#include <com/sun/star/embed/XComponentSupplier.hpp> +#include <com/sun/star/embed/XWindowSupplier.hpp> +#include <com/sun/star/embed/XEmbedPersist.hpp> +#include <com/sun/star/embed/EmbedVerbs.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/embed/XStateChangeListener.hpp> +#include <com/sun/star/embed/StateChangeInProgressException.hpp> +#include <com/sun/star/embed/XLinkageSupport.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/task/XStatusIndicatorFactory.hpp> +#include <com/sun/star/task/XStatusIndicator.hpp> + +#include <com/sun/star/embed/EmbedMisc.hpp> +#include <svtools/embedhlp.hxx> +#include <vcl/svapp.hxx> + +#include <sfx2/ipclient.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/dispatch.hxx> +#include "workwin.hxx" +#include "guisaveas.hxx" +#include <sfx2/viewfrm.hxx> +#include <cppuhelper/implbase5.hxx> +#include <vcl/salbtype.hxx> +#include <svtools/ehdl.hxx> + +#include <vcl/timer.hxx> +#include <vcl/window.hxx> +#include <toolkit/awt/vclxwindow.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <toolkit/helper/convert.hxx> +#include <tools/fract.hxx> +#include <tools/gen.hxx> +#include <svl/rectitem.hxx> +#include <svtools/soerr.hxx> +#include <comphelper/processfactory.hxx> + +#define SFX_CLIENTACTIVATE_TIMEOUT 100 + +using namespace com::sun::star; + +//==================================================================== +// SfxEmbedResizeGuard +class SfxBooleanFlagGuard +{ + sal_Bool& m_rFlag; + sal_Bool m_bLifeValue; +public: + SfxBooleanFlagGuard( sal_Bool& bFlag, sal_Bool bLifeValue ) + : m_rFlag( bFlag ) + , m_bLifeValue( bLifeValue ) + { + m_rFlag = m_bLifeValue; + } + + ~SfxBooleanFlagGuard() + { + m_rFlag = !m_bLifeValue; + } +}; + +//==================================================================== +// SfxInPlaceClient_Impl + +//-------------------------------------------------------------------- +class SfxInPlaceClient_Impl : public ::cppu::WeakImplHelper5< embed::XEmbeddedClient, + embed::XInplaceClient, + document::XEventListener, + embed::XStateChangeListener, + embed::XWindowSupplier > +{ +public: + Timer m_aTimer; // activation timeout, starts after object connection + Rectangle m_aObjArea; // area of object in coordinate system of the container (without scaling) + Fraction m_aScaleWidth; // scaling that was applied to the object when it was not active + Fraction m_aScaleHeight; + SfxInPlaceClient* m_pClient; + sal_Int64 m_nAspect; // ViewAspect that is assigned from the container + Rectangle m_aLastObjAreaPixel; // area of object in coordinate system of the container (without scaling) + sal_Bool m_bStoreObject; + sal_Bool m_bUIActive; // set and cleared when notification for UI (de)activation is sent + sal_Bool m_bResizeNoScale; + + uno::Reference < embed::XEmbeddedObject > m_xObject; + uno::Reference < embed::XEmbeddedClient > m_xClient; + + + SfxInPlaceClient_Impl() + : m_pClient( NULL ) + , m_nAspect( 0 ) + , m_bStoreObject( sal_True ) + , m_bUIActive( sal_False ) + , m_bResizeNoScale( sal_False ) + {} + + ~SfxInPlaceClient_Impl(); + + void SizeHasChanged(); + DECL_LINK (TimerHdl, Timer*); + uno::Reference < frame::XFrame > GetFrame() const; + + // XEmbeddedClient + virtual void SAL_CALL saveObject() throw ( embed::ObjectSaveVetoException, uno::Exception, uno::RuntimeException ); + virtual void SAL_CALL visibilityChanged( sal_Bool bVisible ) throw ( embed::WrongStateException, uno::RuntimeException ); + + // XInplaceClient + virtual sal_Bool SAL_CALL canInplaceActivate() throw ( uno::RuntimeException ); + virtual void SAL_CALL activatingInplace() throw ( embed::WrongStateException, uno::RuntimeException ); + virtual void SAL_CALL activatingUI() throw ( embed::WrongStateException, uno::RuntimeException ); + virtual void SAL_CALL deactivatedInplace() throw ( embed::WrongStateException, uno::RuntimeException ); + virtual void SAL_CALL deactivatedUI() throw ( embed::WrongStateException, uno::RuntimeException ); + virtual uno::Reference< ::com::sun::star::frame::XLayoutManager > SAL_CALL getLayoutManager() throw ( embed::WrongStateException, uno::RuntimeException ); + virtual uno::Reference< frame::XDispatchProvider > SAL_CALL getInplaceDispatchProvider() throw ( embed::WrongStateException, uno::RuntimeException ); + virtual awt::Rectangle SAL_CALL getPlacement() throw ( embed::WrongStateException, uno::RuntimeException ); + virtual awt::Rectangle SAL_CALL getClipRectangle() throw ( embed::WrongStateException, uno::RuntimeException ); + virtual void SAL_CALL translateAccelerators( const uno::Sequence< awt::KeyEvent >& aKeys ) throw ( embed::WrongStateException, uno::RuntimeException ); + virtual void SAL_CALL scrollObject( const awt::Size& aOffset ) throw ( embed::WrongStateException, uno::RuntimeException ); + virtual void SAL_CALL changedPlacement( const awt::Rectangle& aPosRect ) throw ( embed::WrongStateException, uno::Exception, uno::RuntimeException ); + + // XComponentSupplier + virtual uno::Reference< util::XCloseable > SAL_CALL getComponent() throw ( uno::RuntimeException ); + + // XWindowSupplier + virtual uno::Reference< awt::XWindow > SAL_CALL getWindow() throw ( uno::RuntimeException ); + + // document::XEventListener + virtual void SAL_CALL notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException ); + + // XStateChangeListener + virtual void SAL_CALL changingState( const ::com::sun::star::lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (::com::sun::star::embed::WrongStateException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL stateChanged( const ::com::sun::star::lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException); +}; + +SfxInPlaceClient_Impl::~SfxInPlaceClient_Impl() +{ +} + +void SAL_CALL SfxInPlaceClient_Impl::changingState( + const ::com::sun::star::lang::EventObject& /*aEvent*/, + ::sal_Int32 /*nOldState*/, + ::sal_Int32 /*nNewState*/ ) +throw (::com::sun::star::embed::WrongStateException, ::com::sun::star::uno::RuntimeException) +{ +} + +void SAL_CALL SfxInPlaceClient_Impl::stateChanged( + const ::com::sun::star::lang::EventObject& /*aEvent*/, + ::sal_Int32 nOldState, + ::sal_Int32 nNewState ) +throw (::com::sun::star::uno::RuntimeException) +{ + if ( m_pClient && nOldState != embed::EmbedStates::LOADED && nNewState == embed::EmbedStates::RUNNING ) + { + // deactivation of object + uno::Reference< frame::XModel > xDocument; + if ( m_pClient->GetViewShell()->GetObjectShell() ) + xDocument = m_pClient->GetViewShell()->GetObjectShell()->GetModel(); + SfxObjectShell::SetCurrentComponent( xDocument ); + } +} + +void SAL_CALL SfxInPlaceClient_Impl::notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException ) +{ + SolarMutexGuard aGuard; + + if ( m_pClient && aEvent.EventName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("OnVisAreaChanged")) && m_nAspect != embed::Aspects::MSOLE_ICON ) + { + m_pClient->FormatChanged(); // for Writer when format of the object is changed with the area + m_pClient->ViewChanged(); + m_pClient->Invalidate(); + } +} + +void SAL_CALL SfxInPlaceClient_Impl::disposing( const ::com::sun::star::lang::EventObject& /*aEvent*/ ) +throw (::com::sun::star::uno::RuntimeException) +{ + DELETEZ( m_pClient ); +} + +// XEmbeddedClient +//-------------------------------------------------------------------- +uno::Reference < frame::XFrame > SfxInPlaceClient_Impl::GetFrame() const +{ + if ( !m_pClient ) + throw uno::RuntimeException(); + return m_pClient->GetViewShell()->GetViewFrame()->GetFrame().GetFrameInterface(); +} + +void SAL_CALL SfxInPlaceClient_Impl::saveObject() + throw ( embed::ObjectSaveVetoException, + uno::Exception, + uno::RuntimeException ) +{ + if ( !m_bStoreObject ) + // client wants to discard the object (usually it means the container document is closed while an object is active + // and the user didn't request saving the changes + return; + + // the common persistance is supported by objects and links + uno::Reference< embed::XCommonEmbedPersist > xPersist( m_xObject, uno::UNO_QUERY ); + if ( !xPersist.is() ) + throw uno::RuntimeException(); + + uno::Reference< frame::XFrame > xFrame; + uno::Reference< task::XStatusIndicator > xStatusIndicator; + uno::Reference< frame::XModel > xModel( m_xObject->getComponent(), uno::UNO_QUERY ); + uno::Reference< lang::XMultiServiceFactory > xSrvMgr( ::comphelper::getProcessServiceFactory() ); + + if ( xModel.is() ) + { + uno::Reference< frame::XController > xController = xModel->getCurrentController(); + if ( xController.is() ) + xFrame = xController->getFrame(); + } + + if ( xSrvMgr.is() && xFrame.is() ) + { + // set non-reschedule progress to prevent problems when asynchronous calls are made + // during storing of the embedded object + uno::Reference< lang::XInitialization > xInit( + xSrvMgr->createInstance( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.framework.StatusIndicatorFactory" ))), + uno::UNO_QUERY_THROW ); + beans::PropertyValue aProperty; + uno::Sequence< uno::Any > aArgs( 2 ); + aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DisableReschedule" )); + aProperty.Value = uno::makeAny( sal_True ); + aArgs[0] = uno::makeAny( aProperty ); + aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" )); + aProperty.Value = uno::makeAny( xFrame ); + aArgs[1] = uno::makeAny( aProperty ); + + xInit->initialize( aArgs ); + + uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY ); + if ( xPropSet.is() ) + { + try + { + uno::Reference< task::XStatusIndicatorFactory > xStatusIndicatorFactory( xInit, uno::UNO_QUERY_THROW ); + xStatusIndicator = xStatusIndicatorFactory->createStatusIndicator(); + xPropSet->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IndicatorInterception" )), uno::makeAny( xStatusIndicator )); + } + catch ( uno::RuntimeException& e ) + { + throw e; + } + catch ( uno::Exception& ) + { + } + } + } + + try + { + xPersist->storeOwn(); + m_xObject->update(); + } + catch ( uno::Exception& ) + { + //TODO/LATER: what should happen if object can't be saved?! + } + + // reset status indicator interception after storing + try + { + uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY ); + if ( xPropSet.is() ) + { + xStatusIndicator.clear(); + xPropSet->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IndicatorInterception" )), uno::makeAny( xStatusIndicator )); + } + } + catch ( uno::RuntimeException& e ) + { + throw e; + } + catch ( uno::Exception& ) + { + } + + // the client can exist only in case there is a view shell + if ( !m_pClient || !m_pClient->GetViewShell() ) + throw uno::RuntimeException(); + + SfxObjectShell* pDocShell = m_pClient->GetViewShell()->GetObjectShell(); + if ( !pDocShell ) + throw uno::RuntimeException(); + + pDocShell->SetModified( sal_True ); + + //TODO/LATER: invalidation might be necessary when object was modified, but is not + //saved through this method + // m_pClient->Invalidate(); +} + +//-------------------------------------------------------------------- +void SAL_CALL SfxInPlaceClient_Impl::visibilityChanged( sal_Bool bVisible ) + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + SolarMutexGuard aGuard; + + if ( !m_pClient || !m_pClient->GetViewShell() ) + throw uno::RuntimeException(); + + m_pClient->GetViewShell()->OutplaceActivated( bVisible, m_pClient ); + m_pClient->Invalidate(); +} + + +// XInplaceClient +//-------------------------------------------------------------------- +sal_Bool SAL_CALL SfxInPlaceClient_Impl::canInplaceActivate() + throw ( uno::RuntimeException ) +{ + if ( !m_xObject.is() ) + throw uno::RuntimeException(); + + // we don't want to switch directly from outplace to inplace mode + if ( m_xObject->getCurrentState() == embed::EmbedStates::ACTIVE || m_nAspect == embed::Aspects::MSOLE_ICON ) + return sal_False; + + return sal_True; +} + +//-------------------------------------------------------------------- +void SAL_CALL SfxInPlaceClient_Impl::activatingInplace() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + if ( !m_pClient || !m_pClient->GetViewShell() ) + throw uno::RuntimeException(); + + m_pClient->GetViewShell()->InplaceActivating( m_pClient ); +} + +//-------------------------------------------------------------------- +void SAL_CALL SfxInPlaceClient_Impl::activatingUI() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + if ( !m_pClient || !m_pClient->GetViewShell() ) + throw uno::RuntimeException(); + + m_pClient->GetViewShell()->ResetAllClients_Impl(m_pClient); + m_bUIActive = sal_True; + m_pClient->GetViewShell()->UIActivating( m_pClient ); +} + +//-------------------------------------------------------------------- +void SAL_CALL SfxInPlaceClient_Impl::deactivatedInplace() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + if ( !m_pClient || !m_pClient->GetViewShell() ) + throw uno::RuntimeException(); + + m_pClient->GetViewShell()->InplaceDeactivated( m_pClient ); +} + +//-------------------------------------------------------------------- +void SAL_CALL SfxInPlaceClient_Impl::deactivatedUI() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + if ( !m_pClient || !m_pClient->GetViewShell() ) + throw uno::RuntimeException(); + + m_pClient->GetViewShell()->UIDeactivated( m_pClient ); + m_bUIActive = sal_False; +} + +//-------------------------------------------------------------------- +uno::Reference< ::com::sun::star::frame::XLayoutManager > SAL_CALL SfxInPlaceClient_Impl::getLayoutManager() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + uno::Reference < beans::XPropertySet > xFrame( GetFrame(), uno::UNO_QUERY ); + if ( !xFrame.is() ) + throw uno::RuntimeException(); + + uno::Reference< ::com::sun::star::frame::XLayoutManager > xMan; + try + { + uno::Any aAny = xFrame->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("LayoutManager")) ); + aAny >>= xMan; + } + catch ( uno::Exception& ) + { + throw uno::RuntimeException(); + } + + return xMan; +} + +//-------------------------------------------------------------------- +uno::Reference< frame::XDispatchProvider > SAL_CALL SfxInPlaceClient_Impl::getInplaceDispatchProvider() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + return uno::Reference < frame::XDispatchProvider >( GetFrame(), uno::UNO_QUERY_THROW ); +} + +//-------------------------------------------------------------------- +awt::Rectangle SAL_CALL SfxInPlaceClient_Impl::getPlacement() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + if ( !m_pClient || !m_pClient->GetViewShell() ) + throw uno::RuntimeException(); + + // apply scaling to object area and convert to pixels + Rectangle aRealObjArea( m_aObjArea ); + aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_aScaleWidth, + Fraction( aRealObjArea.GetHeight() ) * m_aScaleHeight ) ); + + aRealObjArea = m_pClient->GetEditWin()->LogicToPixel( aRealObjArea ); + return AWTRectangle( aRealObjArea ); +} + +//-------------------------------------------------------------------- +awt::Rectangle SAL_CALL SfxInPlaceClient_Impl::getClipRectangle() + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + if ( !m_pClient || !m_pClient->GetViewShell() ) + throw uno::RuntimeException(); + + // currently(?) same as placement + Rectangle aRealObjArea( m_aObjArea ); + aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_aScaleWidth, + Fraction( aRealObjArea.GetHeight() ) * m_aScaleHeight ) ); + + aRealObjArea = m_pClient->GetEditWin()->LogicToPixel( aRealObjArea ); + return AWTRectangle( aRealObjArea ); +} + +//-------------------------------------------------------------------- +void SAL_CALL SfxInPlaceClient_Impl::translateAccelerators( const uno::Sequence< awt::KeyEvent >& /*aKeys*/ ) + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + if ( !m_pClient || !m_pClient->GetViewShell() ) + throw uno::RuntimeException(); + + // TODO/MBA: keyboard accelerators +} + +//-------------------------------------------------------------------- +void SAL_CALL SfxInPlaceClient_Impl::scrollObject( const awt::Size& /*aOffset*/ ) + throw ( embed::WrongStateException, + uno::RuntimeException ) +{ + if ( !m_pClient || !m_pClient->GetViewShell() ) + throw uno::RuntimeException(); +} + +//-------------------------------------------------------------------- +void SAL_CALL SfxInPlaceClient_Impl::changedPlacement( const awt::Rectangle& aPosRect ) + throw ( embed::WrongStateException, + uno::Exception, + uno::RuntimeException ) +{ + uno::Reference< embed::XInplaceObject > xInplace( m_xObject, uno::UNO_QUERY ); + if ( !xInplace.is() || !m_pClient || !m_pClient->GetEditWin() || !m_pClient->GetViewShell() ) + throw uno::RuntimeException(); + + // check if the change is at least one pixel in size + awt::Rectangle aOldRect = getPlacement(); + Rectangle aNewPixelRect = VCLRectangle( aPosRect ); + Rectangle aOldPixelRect = VCLRectangle( aOldRect ); + if ( aOldPixelRect == aNewPixelRect ) + // nothing has changed + return; + + // new scaled object area + Rectangle aNewLogicRect = m_pClient->GetEditWin()->PixelToLogic( aNewPixelRect ); + + // all the size changes in this method should happen without scaling + // SfxBooleanFlagGuard aGuard( m_bResizeNoScale, sal_True ); + + // allow container to apply restrictions on the requested new area; + // the container might change the object view during size calculation; + // currently only writer does it + m_pClient->RequestNewObjectArea( aNewLogicRect); + + if ( aNewLogicRect != m_pClient->GetScaledObjArea() ) + { + // the calculation of the object area has not changed the object size + // it should be done here then + SfxBooleanFlagGuard aGuard( m_bResizeNoScale, sal_True ); + + // new size of the object area without scaling + Size aNewObjSize( Fraction( aNewLogicRect.GetWidth() ) / m_aScaleWidth, + Fraction( aNewLogicRect.GetHeight() ) / m_aScaleHeight ); + + // now remove scaling from new placement and keep this a the new object area + aNewLogicRect.SetSize( aNewObjSize ); + m_aObjArea = aNewLogicRect; + + // let the window size be recalculated + SizeHasChanged(); + } + + // notify container view about changes + m_pClient->ObjectAreaChanged(); +} + +// XComponentSupplier +//-------------------------------------------------------------------- +uno::Reference< util::XCloseable > SAL_CALL SfxInPlaceClient_Impl::getComponent() + throw ( uno::RuntimeException ) +{ + if ( !m_pClient || !m_pClient->GetViewShell() ) + throw uno::RuntimeException(); + + SfxObjectShell* pDocShell = m_pClient->GetViewShell()->GetObjectShell(); + if ( !pDocShell ) + throw uno::RuntimeException(); + + // all the components must implement XCloseable + uno::Reference< util::XCloseable > xComp( pDocShell->GetModel(), uno::UNO_QUERY ); + if ( !xComp.is() ) + throw uno::RuntimeException(); + + return xComp; +} + + +// XWindowSupplier +//-------------------------------------------------------------------- +uno::Reference< awt::XWindow > SAL_CALL SfxInPlaceClient_Impl::getWindow() + throw ( uno::RuntimeException ) +{ + if ( !m_pClient || !m_pClient->GetEditWin() ) + throw uno::RuntimeException(); + + uno::Reference< awt::XWindow > xWin( m_pClient->GetEditWin()->GetComponentInterface(), uno::UNO_QUERY ); + return xWin; +} + +//-------------------------------------------------------------------- +// notification to the client implementation that either the object area or the scaling has been changed +// as a result the logical size of the window has changed also +void SfxInPlaceClient_Impl::SizeHasChanged() +{ + if ( !m_pClient || !m_pClient->GetViewShell() ) + throw uno::RuntimeException(); + + try { + if ( m_xObject.is() + && ( m_xObject->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE + || m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE ) ) + { + // only possible in active states + uno::Reference< embed::XInplaceObject > xInplace( m_xObject, uno::UNO_QUERY ); + if ( !xInplace.is() ) + throw uno::RuntimeException(); + + if ( m_bResizeNoScale ) + { + // the resizing should be done without scaling + // set the correct size to the object to avoid the scaling + MapMode aObjectMap( VCLUnoHelper::UnoEmbed2VCLMapUnit( m_xObject->getMapUnit( m_nAspect ) ) ); + MapMode aClientMap( m_pClient->GetEditWin()->GetMapMode().GetMapUnit() ); + + // convert to logical coordinates of the embedded object + Size aNewSize = m_pClient->GetEditWin()->LogicToLogic( m_aObjArea.GetSize(), &aClientMap, &aObjectMap ); + m_xObject->setVisualAreaSize( m_nAspect, awt::Size( aNewSize.Width(), aNewSize.Height() ) ); + } + + xInplace->setObjectRectangles( getPlacement(), getClipRectangle() ); + } + } + catch( uno::Exception& ) + { + // TODO/LATER: handle error + } +} + +//-------------------------------------------------------------------- +IMPL_LINK( SfxInPlaceClient_Impl, TimerHdl, Timer*, EMPTYARG ) +{ + if ( m_pClient && m_xObject.is() ) + m_pClient->GetViewShell()->CheckIPClient_Impl( m_pClient, m_pClient->GetViewShell()->GetObjectShell()->GetVisArea() ); + return 0; +} + + +//==================================================================== +// SfxInPlaceClient + +//-------------------------------------------------------------------- +SfxInPlaceClient::SfxInPlaceClient( SfxViewShell* pViewShell, Window *pDraw, sal_Int64 nAspect ) : + m_pImp( new SfxInPlaceClient_Impl ), + m_pViewSh( pViewShell ), + m_pEditWin( pDraw ) +{ + m_pImp->acquire(); + m_pImp->m_pClient = this; + m_pImp->m_nAspect = nAspect; + m_pImp->m_aScaleWidth = m_pImp->m_aScaleHeight = Fraction(1,1); + m_pImp->m_xClient = static_cast< embed::XEmbeddedClient* >( m_pImp ); + pViewShell->NewIPClient_Impl(this); + m_pImp->m_aTimer.SetTimeout( SFX_CLIENTACTIVATE_TIMEOUT ); + m_pImp->m_aTimer.SetTimeoutHdl( LINK( m_pImp, SfxInPlaceClient_Impl, TimerHdl ) ); +} + +//-------------------------------------------------------------------- + +SfxInPlaceClient::~SfxInPlaceClient() +{ + m_pViewSh->IPClientGone_Impl(this); + + // deleting the client before storing the object means discarding all changes + m_pImp->m_bStoreObject = sal_False; + SetObject(0); + + m_pImp->m_pClient = NULL; + + // the next call will destroy m_pImp if no other reference to it exists + m_pImp->m_xClient = uno::Reference < embed::XEmbeddedClient >(); + m_pImp->release(); + + // TODO/LATER: + // the class is not intended to be used in multithreaded environment; + // if it will this disconnection and all the parts that use the m_pClient + // must be guarded with mutex +} + +//-------------------------------------------------------------------- +void SfxInPlaceClient::SetObjectState( sal_Int32 nState ) +{ + if ( GetObject().is() ) + { + if ( m_pImp->m_nAspect == embed::Aspects::MSOLE_ICON + && ( nState == embed::EmbedStates::UI_ACTIVE || nState == embed::EmbedStates::INPLACE_ACTIVE ) ) + { + OSL_FAIL( "Iconified object should not be activated inplace!\n" ); + return; + } + + try + { + GetObject()->changeState( nState ); + } + catch ( uno::Exception& ) + {} + } +} + +//-------------------------------------------------------------------- +sal_Int64 SfxInPlaceClient::GetObjectMiscStatus() const +{ + if ( GetObject().is() ) + return GetObject()->getStatus( m_pImp->m_nAspect ); + return 0; +} + +//-------------------------------------------------------------------- +uno::Reference < embed::XEmbeddedObject > SfxInPlaceClient::GetObject() const +{ + return m_pImp->m_xObject; +} + +//-------------------------------------------------------------------- +void SfxInPlaceClient::SetObject( const uno::Reference < embed::XEmbeddedObject >& rObject ) +{ + if ( m_pImp->m_xObject.is() && rObject != m_pImp->m_xObject ) + { + DBG_ASSERT( GetObject()->getClientSite() == m_pImp->m_xClient, "Wrong ClientSite!" ); + if ( GetObject()->getClientSite() == m_pImp->m_xClient ) + { + if ( GetObject()->getCurrentState() != embed::EmbedStates::LOADED ) + SetObjectState( embed::EmbedStates::RUNNING ); + m_pImp->m_xObject->removeEventListener( uno::Reference < document::XEventListener >( m_pImp->m_xClient, uno::UNO_QUERY ) ); + m_pImp->m_xObject->removeStateChangeListener( uno::Reference < embed::XStateChangeListener >( m_pImp->m_xClient, uno::UNO_QUERY ) ); + try + { + m_pImp->m_xObject->setClientSite( 0 ); + } + catch( uno::Exception& ) + { + OSL_FAIL( "Can not clean the client site!\n" ); + } + } + } + + if ( !m_pViewSh || m_pViewSh->GetViewFrame()->GetFrame().IsClosing_Impl() ) + // sometimes applications reconnect clients on shutting down because it happens in their Paint methods + return; + + m_pImp->m_xObject = rObject; + + if ( rObject.is() ) + { + // as soon as an object was connected to a client it has to be checked wether the object wants + // to be activated + rObject->addStateChangeListener( uno::Reference < embed::XStateChangeListener >( m_pImp->m_xClient, uno::UNO_QUERY ) ); + rObject->addEventListener( uno::Reference < document::XEventListener >( m_pImp->m_xClient, uno::UNO_QUERY ) ); + + try + { + rObject->setClientSite( m_pImp->m_xClient ); + } + catch( uno::Exception& ) + { + OSL_FAIL( "Can not set the client site!\n" ); + } + + m_pImp->m_aTimer.Start(); + } + else + m_pImp->m_aTimer.Stop(); +} + +//-------------------------------------------------------------------- +sal_Bool SfxInPlaceClient::SetObjArea( const Rectangle& rArea ) +{ + if( rArea != m_pImp->m_aObjArea ) + { + m_pImp->m_aObjArea = rArea; + m_pImp->SizeHasChanged(); + + Invalidate(); + return sal_True; + } + + return sal_False; +} + +//-------------------------------------------------------------------- +Rectangle SfxInPlaceClient::GetObjArea() const +{ + return m_pImp->m_aObjArea; +} + +Rectangle SfxInPlaceClient::GetScaledObjArea() const +{ + Rectangle aRealObjArea( m_pImp->m_aObjArea ); + aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_pImp->m_aScaleWidth, + Fraction( aRealObjArea.GetHeight() ) * m_pImp->m_aScaleHeight ) ); + return aRealObjArea; +} + +//-------------------------------------------------------------------- +void SfxInPlaceClient::SetSizeScale( const Fraction & rScaleWidth, const Fraction & rScaleHeight ) +{ + if ( m_pImp->m_aScaleWidth != rScaleWidth || m_pImp->m_aScaleHeight != rScaleHeight ) + { + m_pImp->m_aScaleWidth = rScaleWidth; + m_pImp->m_aScaleHeight = rScaleHeight; + + m_pImp->SizeHasChanged(); + + // TODO/LATER: Invalidate seems to trigger (wrong) recalculations of the ObjArea, so it's better + // not to call it here, but maybe it sounds reasonable to do so. + //Invalidate(); + } +} + +//-------------------------------------------------------------------- +sal_Bool SfxInPlaceClient::SetObjAreaAndScale( const Rectangle& rArea, const Fraction& rScaleWidth, const Fraction& rScaleHeight ) +{ + if( rArea != m_pImp->m_aObjArea || m_pImp->m_aScaleWidth != rScaleWidth || m_pImp->m_aScaleHeight != rScaleHeight ) + { + m_pImp->m_aObjArea = rArea; + m_pImp->m_aScaleWidth = rScaleWidth; + m_pImp->m_aScaleHeight = rScaleHeight; + + m_pImp->SizeHasChanged(); + + Invalidate(); + return sal_True; + } + + return sal_False; +} + +//-------------------------------------------------------------------- +const Fraction& SfxInPlaceClient::GetScaleWidth() const +{ + return m_pImp->m_aScaleWidth; +} + +//-------------------------------------------------------------------- +const Fraction& SfxInPlaceClient::GetScaleHeight() const +{ + return m_pImp->m_aScaleHeight; +} + +//-------------------------------------------------------------------- +void SfxInPlaceClient::Invalidate() +{ + // TODO/LATER: do we need both? + + // the object area is provided in logical coordinates of the window but without scaling applied + Rectangle aRealObjArea( m_pImp->m_aObjArea ); + aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_pImp->m_aScaleWidth, + Fraction( aRealObjArea.GetHeight() ) * m_pImp->m_aScaleHeight ) ); + m_pEditWin->Invalidate( aRealObjArea ); + + ViewChanged(); +} + +//-------------------------------------------------------------------- +sal_Bool SfxInPlaceClient::IsObjectUIActive() const +{ + try { + return ( m_pImp->m_xObject.is() && ( m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE ) ); + } + catch( uno::Exception& ) + {} + + return sal_False; +} + +//-------------------------------------------------------------------- +sal_Bool SfxInPlaceClient::IsObjectInPlaceActive() const +{ + try { + return( + ( + m_pImp->m_xObject.is() && + (m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE) + ) || + ( + m_pImp->m_xObject.is() && + (m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE) + ) + ); + } + catch( uno::Exception& ) + {} + + return sal_False; +} + +//-------------------------------------------------------------------- +sal_Bool SfxInPlaceClient::IsObjectActive() const +{ + try { + return ( m_pImp->m_xObject.is() && ( m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::ACTIVE ) ); + } + catch( uno::Exception& ) + {} + + return sal_False; +} + +//-------------------------------------------------------------------- +Window* SfxInPlaceClient::GetActiveWindow( SfxObjectShell* pDoc, const com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject >& xObject ) +{ + SfxInPlaceClient* pClient = GetClient( pDoc, xObject ); + if ( pClient ) + return pClient->GetEditWin(); + return NULL; +} + +//-------------------------------------------------------------------- +SfxInPlaceClient* SfxInPlaceClient::GetClient( SfxObjectShell* pDoc, const com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject >& xObject ) +{ + for ( SfxViewFrame* pFrame = SfxViewFrame::GetFirst(pDoc); pFrame; pFrame=SfxViewFrame::GetNext(*pFrame,pDoc) ) + { + if( pFrame->GetViewShell() ) + { + SfxInPlaceClient* pClient = pFrame->GetViewShell()->FindIPClient( xObject, NULL ); + if ( pClient ) + return pClient; + } + } + + return NULL; +} + +sal_Int64 SfxInPlaceClient::GetAspect() const +{ + return m_pImp->m_nAspect; +} + +ErrCode SfxInPlaceClient::DoVerb( long nVerb ) +{ + SfxErrorContext aEc( ERRCTX_SO_DOVERB, m_pViewSh->GetWindow(), RID_SO_ERRCTX ); + ErrCode nError = ERRCODE_NONE; + + if ( m_pImp->m_xObject.is() ) + { + sal_Bool bSaveCopyAs = sal_False; + if ( nVerb == -8 ) // "Save Copy as..." + { + svt::EmbeddedObjectRef::TryRunningState( m_pImp->m_xObject ); + // TODO/LATER: this special verb should disappear when outplace activation is completely available + uno::Reference< frame::XModel > xEmbModel( m_pImp->m_xObject->getComponent(), uno::UNO_QUERY ); + if ( xEmbModel.is() ) + { + bSaveCopyAs = sal_True; + + try + { + uno::Reference< lang::XMultiServiceFactory > xEmptyFactory; + SfxStoringHelper aHelper( xEmptyFactory ); + uno::Sequence< beans::PropertyValue > aDispatchArgs( 1 ); + aDispatchArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SaveTo" ) ); + aDispatchArgs[0].Value <<= (sal_Bool)sal_True; + + aHelper.GUIStoreModel( xEmbModel, + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SaveAs" ) ), + aDispatchArgs, + sal_False, + ::rtl::OUString() ); + } + catch( task::ErrorCodeIOException& aErrorEx ) + { + nError = (sal_uInt32)aErrorEx.ErrCode; + } + catch( uno::Exception& ) + { + nError = ERRCODE_IO_GENERAL; + // TODO/LATER: better error handling + } + } + } + + if ( !bSaveCopyAs ) + { + if ( m_pImp->m_nAspect == embed::Aspects::MSOLE_ICON ) + { + if ( nVerb == embed::EmbedVerbs::MS_OLEVERB_PRIMARY || nVerb == embed::EmbedVerbs::MS_OLEVERB_SHOW ) + nVerb = embed::EmbedVerbs::MS_OLEVERB_OPEN; // outplace activation + else if ( nVerb == embed::EmbedVerbs::MS_OLEVERB_UIACTIVATE + || nVerb == embed::EmbedVerbs::MS_OLEVERB_IPACTIVATE ) + nError = ERRCODE_SO_GENERALERROR; + } + + if ( !nError ) + { + + if ( m_pViewSh ) + m_pViewSh->GetViewFrame()->GetTopFrame().LockResize_Impl(sal_True); + try + { + m_pImp->m_xObject->setClientSite( m_pImp->m_xClient ); + + m_pImp->m_xObject->doVerb( nVerb ); + } + catch ( embed::UnreachableStateException& ) + { + if ( nVerb == 0 || nVerb == embed::EmbedVerbs::MS_OLEVERB_OPEN ) + { + // a workaround for the default verb, usually makes sence for alien objects + try + { + m_pImp->m_xObject->doVerb( -9 ); // open own view, a workaround verb that is not visible + + if ( m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE ) + { + // the object was converted to OOo object + awt::Size aSize = m_pImp->m_xObject->getVisualAreaSize( m_pImp->m_nAspect ); + MapMode aObjectMap( VCLUnoHelper::UnoEmbed2VCLMapUnit( m_pImp->m_xObject->getMapUnit( m_pImp->m_nAspect ) ) ); + MapMode aClientMap( GetEditWin()->GetMapMode().GetMapUnit() ); + Size aNewSize = GetEditWin()->LogicToLogic( Size( aSize.Width, aSize.Height ), &aObjectMap, &aClientMap ); + + Rectangle aScaledArea = GetScaledObjArea(); + m_pImp->m_aObjArea.SetSize( aNewSize ); + m_pImp->m_aScaleWidth = Fraction( aScaledArea.GetWidth(), aNewSize.Width() ); + m_pImp->m_aScaleHeight = Fraction( aScaledArea.GetHeight(), aNewSize.Height() ); + } + } + catch ( uno::Exception& ) + { + nError = ERRCODE_SO_GENERALERROR; + } + } + } + catch ( embed::StateChangeInProgressException& ) + { + // TODO/LATER: it would be nice to be able to provide the current target state outside + nError = ERRCODE_SO_CANNOT_DOVERB_NOW; + } + catch ( uno::Exception& ) + { + nError = ERRCODE_SO_GENERALERROR; + //TODO/LATER: better error handling + } + + if ( m_pViewSh ) + { + SfxViewFrame* pFrame = m_pViewSh->GetViewFrame(); + pFrame->GetTopFrame().LockResize_Impl(sal_False); + pFrame->GetTopFrame().Resize(); + } + } + } + } + + if( nError ) + ErrorHandler::HandleError( nError ); + + return nError; +} + +void SfxInPlaceClient::VisAreaChanged() +{ + uno::Reference < embed::XInplaceObject > xObj( m_pImp->m_xObject, uno::UNO_QUERY ); + uno::Reference < embed::XInplaceClient > xClient( m_pImp->m_xClient, uno::UNO_QUERY ); + if ( xObj.is() && xClient.is() ) + m_pImp->SizeHasChanged(); +} + +void SfxInPlaceClient::ObjectAreaChanged() +{ + // dummy implementation +} + +void SfxInPlaceClient::RequestNewObjectArea( Rectangle& ) +{ + // dummy implementation +} + +void SfxInPlaceClient::ViewChanged() +{ + // dummy implementation +} + +void SfxInPlaceClient::MakeVisible() +{ + // dummy implementation +} + +void SfxInPlaceClient::FormatChanged() +{ + // dummy implementation +} + +void SfxInPlaceClient::DeactivateObject() +{ + if ( GetObject().is() ) + { + try + { + m_pImp->m_bUIActive = sal_False; + sal_Bool bHasFocus = sal_False; + uno::Reference< frame::XModel > xModel( m_pImp->m_xObject->getComponent(), uno::UNO_QUERY ); + if ( xModel.is() ) + { + uno::Reference< frame::XController > xController = xModel->getCurrentController(); + if ( xController.is() ) + { + Window* pWindow = VCLUnoHelper::GetWindow( xController->getFrame()->getContainerWindow() ); + bHasFocus = pWindow->HasChildPathFocus( sal_True ); + } + } + + if ( m_pViewSh ) + m_pViewSh->GetViewFrame()->GetTopFrame().LockResize_Impl(sal_True); + + if ( m_pImp->m_xObject->getStatus( m_pImp->m_nAspect ) & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE ) + { + m_pImp->m_xObject->changeState( embed::EmbedStates::INPLACE_ACTIVE ); + if ( bHasFocus && m_pViewSh ) + m_pViewSh->GetWindow()->GrabFocus(); + } + else + { + // the links should not stay in running state for long time because of locking + uno::Reference< embed::XLinkageSupport > xLink( m_pImp->m_xObject, uno::UNO_QUERY ); + if ( xLink.is() && xLink->isLink() ) + m_pImp->m_xObject->changeState( embed::EmbedStates::LOADED ); + else + m_pImp->m_xObject->changeState( embed::EmbedStates::RUNNING ); + } + + if ( m_pViewSh ) + { + SfxViewFrame* pFrame = m_pViewSh->GetViewFrame(); + SfxViewFrame::SetViewFrame( pFrame ); + pFrame->GetTopFrame().LockResize_Impl(sal_False); + pFrame->GetTopFrame().Resize(); + } + } + catch (com::sun::star::uno::Exception& ) + {} + } +} + +void SfxInPlaceClient::ResetObject() +{ + if ( GetObject().is() ) + { + try + { + m_pImp->m_bUIActive = sal_False; + if ( m_pImp->m_xObject->getStatus( m_pImp->m_nAspect ) & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE ) + m_pImp->m_xObject->changeState( embed::EmbedStates::INPLACE_ACTIVE ); + else + { + // the links should not stay in running state for long time because of locking + uno::Reference< embed::XLinkageSupport > xLink( m_pImp->m_xObject, uno::UNO_QUERY ); + if ( xLink.is() && xLink->isLink() ) + m_pImp->m_xObject->changeState( embed::EmbedStates::LOADED ); + else + m_pImp->m_xObject->changeState( embed::EmbedStates::RUNNING ); + } + } + catch (com::sun::star::uno::Exception& ) + {} + } +} + +sal_Bool SfxInPlaceClient::IsUIActive() +{ + return m_pImp->m_bUIActive; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/orgmgr.cxx b/sfx2/source/view/orgmgr.cxx new file mode 100644 index 000000000000..2ed26e48cde3 --- /dev/null +++ b/sfx2/source/view/orgmgr.cxx @@ -0,0 +1,794 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/XTransactedObject.hpp> +#include <com/sun/star/embed/ElementModes.hpp> + +#include <vcl/msgbox.hxx> +#include <tools/urlobj.hxx> + +#include <comphelper/processfactory.hxx> +#include <unotools/intlwrapper.hxx> + +#include <comphelper/storagehelper.hxx> + +#include <sfx2/app.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/docfac.hxx> +#include <sfx2/doctempl.hxx> +#include "docvor.hxx" +#include "orgmgr.hxx" +#include "sfxtypes.hxx" +#include "sfx2/sfxresid.hxx" +#include "view.hrc" +#include <sfx2/docfilt.hxx> +#include "fltfnc.hxx" + +using namespace ::com::sun::star; + +//========================================================================= + +/* [Description] + + Implementation class, single entry in the file view. +*/ + +struct _FileListEntry +{ + String aFileName; // File Name with complete path + String aBaseName; // File Name + const CollatorWrapper* pCollator; + SfxObjectShellLock aDocShell; // ObjectShell as reference class + + sal_Bool bFile; // As File on disk + // (!= not processed, not loaded as document + // these are not saved!) + sal_Bool bOwner; // self-generated + sal_Bool bNoName; + sal_Bool bOwnFormat; + + _FileListEntry( const String& rFileName, + const CollatorWrapper* pColl, const String* pTitle = NULL ); + ~_FileListEntry(); + + int operator==( const _FileListEntry &rCmp) const; + int operator< ( const _FileListEntry &rCmp) const; + sal_Bool DeleteObjectShell(); +}; + +//------------------------------------------------------------------------- + +inline int _FileListEntry::operator==(const _FileListEntry &rCmp) const +{ + DBG_ASSERT( pCollator, "invalid CollatorWrapper" ); + return COMPARE_EQUAL == pCollator->compareString(aBaseName, rCmp.aBaseName); +} + +//------------------------------------------------------------------------- + +inline int _FileListEntry::operator< (const _FileListEntry &rCmp) const +{ + DBG_ASSERT( pCollator, "invalid CollatorWrapper" ); + return COMPARE_LESS == pCollator->compareString(aBaseName, rCmp.aBaseName); +} + +//------------------------------------------------------------------------- + +_FileListEntry::_FileListEntry( const String& rFileName, + const CollatorWrapper* pColl, const String* pTitle ) : + + aFileName ( rFileName ), + pCollator ( pColl ), + bFile ( sal_False ), + bOwner ( sal_False ), + bNoName ( sal_True ), + bOwnFormat ( sal_True ) +{ + if ( pTitle ) + aBaseName = *pTitle; + else + { + INetURLObject aObj( rFileName, INET_PROT_FILE ); + aBaseName = aObj.getName( INetURLObject::LAST_SEGMENT, true, + INetURLObject::DECODE_WITH_CHARSET ); + } +} + +//------------------------------------------------------------------------- + +_FileListEntry::~_FileListEntry() +{ + DeleteObjectShell(); +} + +//------------------------------------------------------------------------- + +SV_IMPL_OP_PTRARR_SORT(_SfxObjectList, _FileListEntry*) + +//========================================================================= + +sal_Bool _FileListEntry::DeleteObjectShell() + +/* [Description] + + Release of ther DocumentShell + + [Return value] TRUE: Everything is ok + FALSE: An error occured + (the document could not be saved) +*/ + +{ + sal_Bool bRet = sal_True; + + if(bOwner && aDocShell.Is() && aDocShell->IsModified()) + { + // Converted? + if( bOwnFormat ) + { + if(!aDocShell->Save() ) + bRet = sal_False; + else + { + try { + uno::Reference< embed::XTransactedObject > xTransact( aDocShell->GetStorage(), uno::UNO_QUERY ); + OSL_ENSURE( xTransact.is(), "Storage must implement XTransactedObject!\n" ); + if ( !xTransact.is() ) + throw uno::RuntimeException(); + + xTransact->commit(); + } + catch( uno::Exception& ) + { + } + + } + } + else + { + // If converted save in native format + INetURLObject aObj( aFileName ); + String aTitle = aObj.getName( INetURLObject::LAST_SEGMENT, true, + INetURLObject::DECODE_WITH_CHARSET ); + bRet = aDocShell->PreDoSaveAs_Impl( + aTitle, aDocShell->GetFactory().GetFilterContainer()->GetAnyFilter( SFX_FILTER_IMPORT | SFX_FILTER_EXPORT )->GetFilterName(), 0 ); + } + } + + if( bOwner) + { + aDocShell.Clear(); + } + + return bRet; +} + +//------------------------------------------------------------------------- + +SfxObjectList::SfxObjectList() +{ +} + +//------------------------------------------------------------------------- + +SfxObjectList::~SfxObjectList() +{ + DeleteAndDestroy(0, Count()); +} + +//------------------------------------------------------------------------- + +const String &SfxObjectList::GetBaseName(sal_uInt16 i) const +{ + return (*this)[i]->aBaseName; +} + +//------------------------------------------------------------------------- + +const String& SfxObjectList::GetFileName( sal_uInt16 i ) const +{ + return (*this)[i]->aFileName; +} + +//------------------------------------------------------------------------- + +SfxOrganizeMgr::SfxOrganizeMgr( SfxOrganizeListBox_Impl *pLeft, + SfxOrganizeListBox_Impl *pRight, + SfxDocumentTemplates *pTempl) : + pImpl(new SfxOrganizeMgr_Impl), + pTemplates(pTempl? pTempl: new SfxDocumentTemplates), + pLeftBox(pLeft), + pRightBox(pRight), + bDeleteTemplates(pTempl == 0), + bModified(0) + +/* [Description] + + Constructor. The current document is added to the list of documents. +*/ +{ + pImpl->pDocList = new SfxObjectList; + pImpl->pIntlWrapper = new IntlWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() ); + const CollatorWrapper* pCollator = pImpl->pIntlWrapper->getCaseCollator(); + for ( SfxObjectShell* pTmp = SfxObjectShell::GetFirst(); pTmp; pTmp = SfxObjectShell::GetNext(*pTmp) ) + { + if ( pTmp->GetCreateMode() != SFX_CREATE_MODE_STANDARD || + !( pTmp->GetFlags() & SFXOBJECTSHELL_HASOPENDOC ) || !pTmp->GetStyleSheetPool() ) + continue; + _FileListEntry* pNewEntry = NULL; + String aTitle = pTmp->GetTitle( SFX_TITLE_TITLE ); + pNewEntry = new _FileListEntry( pTmp->GetMedium()->GetName(), pCollator, &aTitle ); + pNewEntry->aDocShell = pTmp; + pImpl->pDocList->C40_PTR_INSERT( _FileListEntry, pNewEntry ); + } +} + +//------------------------------------------------------------------------- + +SfxOrganizeMgr::~SfxOrganizeMgr() +{ + if ( bDeleteTemplates ) + delete pTemplates; + delete pImpl->pDocList; + delete pImpl->pIntlWrapper; + delete pImpl; + pLeftBox = pRightBox = NULL; +} + +//------------------------------------------------------------------------- + +SfxObjectShellRef SfxOrganizeMgr::CreateObjectShell( sal_uInt16 nIdx ) + +/* [Description] + + Access to the DocumentShell at the position nIdx. + + [Return value] Reference to the DocumentShell + +*/ + +{ + _FileListEntry* pEntry = (*pImpl->pDocList)[nIdx]; + // otherwise create Doc-Shell + if ( !pEntry->aDocShell.Is() ) + { + INetURLObject aFileObj( pEntry->aFileName ); + sal_Bool bDum = sal_False; + SfxApplication* pSfxApp = SFX_APP(); + String aFilePath = aFileObj.GetMainURL( INetURLObject::NO_DECODE ); + pEntry->aDocShell = pSfxApp->DocAlreadyLoaded( aFilePath, sal_False, bDum ); + if ( !pEntry->aDocShell.Is() ) + { + pEntry->bOwner = sal_True; + SfxMedium* pMed = new SfxMedium( + aFilePath, ( STREAM_READ | STREAM_SHARE_DENYWRITE ), sal_False, 0 ); + const SfxFilter* pFilter = NULL; + pMed->UseInteractionHandler(sal_True); + if ( + pSfxApp->GetFilterMatcher().GuessFilter(*pMed, &pFilter, SFX_FILTER_TEMPLATE, 0) || + (pFilter && !pFilter->IsOwnFormat()) || + (pFilter && !pFilter->UsesStorage()) + ) + { + pSfxApp->LoadTemplate( pEntry->aDocShell, aFilePath ); + pEntry->bOwnFormat = sal_False; + delete pMed; + if ( pEntry->aDocShell.Is() ) + return (SfxObjectShellRef)(SfxObjectShell*)(pEntry->aDocShell); + } + else + { + if ( pFilter ) + { + pEntry->bOwnFormat = sal_True; + pEntry->aDocShell = SfxObjectShell::CreateObject( pFilter->GetServiceName(), SFX_CREATE_MODE_ORGANIZER ); + if ( pEntry->aDocShell.Is() ) + { + pEntry->aDocShell->DoInitNew(0); + pEntry->aDocShell->LoadFrom( *pMed ); + // Medium is now owned by DocShell + pEntry->aDocShell->DoSaveCompleted( pMed ); + } + } + } + } + } + return ( SfxObjectShellRef )(SfxObjectShell*)(pEntry->aDocShell); +} + +//------------------------------------------------------------------------- + +sal_Bool SfxOrganizeMgr::DeleteObjectShell(sal_uInt16 nIdx) + +/* [Description] + + Release DocumentShell at position nIdx + + [Return value] TRUE: Everything is ok + FALSE: An error occured + (the document could not be saved) +*/ +{ + return (*pImpl->pDocList)[nIdx]->DeleteObjectShell(); +} + +//------------------------------------------------------------------------- + +SfxObjectShellRef SfxOrganizeMgr::CreateObjectShell(sal_uInt16 nRegion, + sal_uInt16 nIdx) +/* [Description] + + Access to the DocumentShell at Position nIdx in Region + nRegion (Document template) + + [Return value] Reference to the DocumentShell + +*/ +{ + return pTemplates->CreateObjectShell(nRegion, nIdx); +} + +//------------------------------------------------------------------------- + +sal_Bool SfxOrganizeMgr::DeleteObjectShell(sal_uInt16 nRegion, sal_uInt16 nIdx) + +/* [Description] + + Release of the DocumentShell at Position nIdx in Region + nRegion (Document template) + + [Return value] TRUE: Everything is ok + FALSE: An error occured + (the document could not be saved) +*/ + +{ + return pTemplates->DeleteObjectShell(nRegion, nIdx); +} + +//------------------------------------------------------------------------- + +sal_Bool SfxOrganizeMgr::Copy(sal_uInt16 nTargetRegion, + sal_uInt16 nTargetIdx, + sal_uInt16 nSourceRegion, + sal_uInt16 nSourceIdx) + +/* [Description] + + Copy of a Document Template + + [Parameter] + + sal_uInt16 nTargetRegion Index of the Target Region + sal_uInt16 nTargetIdx Index of the Target Position + sal_uInt16 nSourceRegion Index of the Source Region + sal_uInt16 nSourceIdx Index of the template to be + copied/moved. + + [Return value] Success (TRUE) or Failure (FALSE) + + + [Cross-reference] + + <SfxDocumentTemplates::Copy(sal_uInt16 nTargetRegion, + sal_uInt16 nTargetIdx, + sal_uInt16 nSourceRegion, + sal_uInt16 nSourceIdx)> + +*/ + +{ + if(nSourceIdx == USHRT_MAX) // No directories copied + return sal_False ; + const sal_Bool bOk = pTemplates->Copy(nTargetRegion, nTargetIdx, + nSourceRegion, nSourceIdx); + if(bOk) + bModified = 1; + return bOk; +} + +//------------------------------------------------------------------------- + +sal_Bool SfxOrganizeMgr::Move(sal_uInt16 nTargetRegion, + sal_uInt16 nTargetIdx, + sal_uInt16 nSourceRegion, + sal_uInt16 nSourceIdx) + +/* [Description] + + Moving a template + + [Parameter] + + sal_uInt16 nTargetRegion Index of the Target Region + sal_uInt16 nTargetIdx Index of the Target Position + sal_uInt16 nSourceRegion Index of the Source Region + sal_uInt16 nSourceIdx Index of the template to be + copied/moved. + + [Return value] Success (TRUE) or Failure (FALSE) + + [Cross-reference] + + <SfxDocumentTemplates::Move(sal_uInt16 nTargetRegion, + sal_uInt16 nTargetIdx, + sal_uInt16 nSourceRegion, + sal_uInt16 nSourceIdx)> +*/ + +{ + if(nSourceIdx == USHRT_MAX) // No directory moved + return sal_False ; + const sal_Bool bOk = pTemplates->Move(nTargetRegion, nTargetIdx, + nSourceRegion, nSourceIdx); + if(bOk) + bModified = 1; + return bOk; +} + +//------------------------------------------------------------------------- + +sal_Bool SfxOrganizeMgr::Delete(SfxOrganizeListBox_Impl *pCaller, + sal_uInt16 nRegion, sal_uInt16 nIdx) + +/* [Description] + + Delete a Document Template + + [Parameter] + + SfxOrganizeListBox *pCaller calling ListBox, since this event + is triggered by the menu or the + keyboard, the ListBox must be updated. + sal_uInt16 nRegion Index for Region + sal_uInt16 nIdx Index of Document template + + [Return value] Success (TRUE) or Failure (FALSE) + + [Cross-reference] + + <SfxDocumentTemplates::Delete(sal_uInt16 nRegion, sal_uInt16 nIdx)> + +*/ + +{ + sal_Bool bOk = sal_False; + + if ( USHRT_MAX == nIdx ) + { + // deleting of a group + + SvLBoxEntry *pGroupToDelete = pCaller->SvLBox::GetEntry(nRegion); + if ( pGroupToDelete ) + { + sal_uInt16 nItemNum = (sal_uInt16)( pCaller->GetModel()->GetChildCount( pGroupToDelete ) ); + sal_uInt16 nToDeleteNum = 0; + SvLBoxEntry **pEntriesToDelete = new SvLBoxEntry*[nItemNum]; + + sal_uInt16 nInd = 0; + for ( nInd = 0; nInd < nItemNum; nInd++ ) + pEntriesToDelete[nInd] = NULL; + + for ( nInd = 0; nInd < nItemNum; nInd++ ) + { + // TODO/LATER: check that nInd is the same index that is used in pTemplates + if ( pTemplates->Delete( nRegion, nInd ) ) + { + bModified = 1; + pEntriesToDelete[nToDeleteNum++] = pCaller->SvLBox::GetEntry( pGroupToDelete, nInd ); + } + } + + for ( nInd = 0; nInd < nToDeleteNum; nInd++ ) + if ( pEntriesToDelete[nInd] ) + pCaller->GetModel()->Remove( pEntriesToDelete[nInd] ); + + if ( !pCaller->GetModel()->GetChildCount( pGroupToDelete ) ) + { + bOk = pTemplates->Delete( nRegion, nIdx ); + if ( bOk ) + pCaller->GetModel()->Remove( pGroupToDelete ); + } + } + } + else + { + // deleting of a template + bOk = pTemplates->Delete(nRegion, nIdx); + if(bOk) + { + bModified = 1; + // Entry to be deleted. + SvLBoxEntry *pEntryToDelete = pCaller->SvLBox::GetEntry(pCaller->SvLBox::GetEntry(nRegion), nIdx); + + pCaller->GetModel()->Remove(pEntryToDelete); + } + } + + return bOk; +} + +//------------------------------------------------------------------------- + +sal_Bool SfxOrganizeMgr::InsertDir +( + SfxOrganizeListBox_Impl* pCaller, /* calling ListBox, since this event + is triggered by the menu or the + keyboard, the ListBox must be updated. */ + const String& rText, // logical Name of Region + sal_uInt16 nRegion // Index of Region +) + +/* [Description] + + Insert Region. + + [Return value] Success (TRUE) or Failure (FALSE) + + [Cross-reference] + + <SfxDocumentTemplates::InsertDir(const String &, sal_uInt16 nRegion)> +*/ + +{ + const sal_Bool bOk = pTemplates->InsertDir(rText, nRegion); + if(bOk) + { + bModified = 1; + SvLBoxEntry *pEntry = pCaller->InsertEntry(rText, + pCaller->GetOpenedBmp(0), + pCaller->GetClosedBmp(0), + 0, sal_True, nRegion); + pCaller->Update(); + pCaller->EditEntry(pEntry); + } + return bOk; +} + +//------------------------------------------------------------------------- + +sal_Bool SfxOrganizeMgr::SetName(const String &rName, + sal_uInt16 nRegion, sal_uInt16 nIdx) + +/* [Description] + + Set (logical) Name + + [Parameter] + + const String &rName The new Name + sal_uInt16 nRegion Index of Region + sal_uInt16 nIdx Index of Document template + + [Return value] Success (TRUE) or Failure (FALSE) + + [Cross-reference] + + <SfxDocumentTemplates::SetName(const String &, sal_uInt16 nRegion, sal_uInt16 nIdx)> +*/ + +{ + const sal_Bool bOk = pTemplates->SetName(rName, nRegion, nIdx); + if(bOk) + bModified = 1; + return bOk; +} + +//------------------------------------------------------------------------- + +sal_Bool SfxOrganizeMgr::CopyTo(sal_uInt16 nRegion, sal_uInt16 nIdx, const String &rName) const + +/* [Description] + + Export of a Template + + [Parameter] + + sal_uInt16 nRegion Index of Region + sal_uInt16 nIdx Index of Document Template + const String &rName File name + + [Return value] Success (TRUE) or Failure (FALSE) + + [Cross-reference] + + <SfxDocumentTemplates::CopyTo( sal_uInt16 nRegion, sal_uInt16 nIdx, const String &)> +*/ + +{ + return pTemplates->CopyTo(nRegion, nIdx, rName); +} + +//------------------------------------------------------------------------- + +sal_Bool SfxOrganizeMgr::CopyFrom(SfxOrganizeListBox_Impl *pCaller, + sal_uInt16 nRegion, sal_uInt16 nIdx, String &rName) + +/* [Description] + + Import of Document Template + + [Parameter] + + SfxOrganizeListBox *pCaller calling ListBox, since this event + is triggered by the menu or the + keyboard, the ListBox must be updated. + + sal_uInt16 nRegion Index of Region + sal_uInt16 nIdx Index of Document Template + String &rName File name + + [Return value] Success (TRUE) or Failure (FALSE) + + [Cross-reference] + + <SfxDocumentTemplates::CopyFrom( sal_uInt16 nRegion, sal_uInt16 nIdx, const String &)> +*/ + +{ + SvLBoxEntry *pParent = pCaller->FirstSelected(); + if( nIdx!=USHRT_MAX ) + pParent = pCaller->GetParent(pParent); + if( pTemplates->CopyFrom( nRegion, nIdx, rName ) ) + { + // Update pCaller + if( nIdx == USHRT_MAX ) + nIdx = 0; + else nIdx++; + + pCaller->InsertEntry( rName, + pCaller->GetOpenedBmp(1), + pCaller->GetClosedBmp(1), + pParent, + sal_True, + nIdx); + pCaller->Update(); + pCaller->Expand( pParent ); + bModified = sal_True; + return sal_True; + } + return sal_False; +} + +//------------------------------------------------------------------------- + +sal_Bool SfxOrganizeMgr::InsertFile( SfxOrganizeListBox_Impl* pCaller, const String& rFileName ) + +/* [Description] + + Insert a file in the file view. + + [Parameter] + + SfxOrganizeListBox *pCaller calling ListBox, since this event + is triggered by the menu or the + keyboard, the ListBox must be updated. + + const String &rFileName Name of inserted File. + + [Return value] Success (TRUE) or Failure (FALSE) +*/ + +{ + const CollatorWrapper* pCollator = pImpl->pIntlWrapper->getCaseCollator(); + _FileListEntry* pEntry = new _FileListEntry( rFileName, pCollator ); + if ( pImpl->pDocList->C40_PTR_INSERT( _FileListEntry, pEntry ) ) + { + sal_uInt16 nPos = 0; + pImpl->pDocList->Seek_Entry( pEntry, &nPos ); + pCaller->InsertEntry( pEntry->aBaseName, pCaller->GetOpenedBmp(1), + pCaller->GetClosedBmp(1), 0, sal_True, nPos ); + return sal_True; + } + return sal_False; +} + +//------------------------------------------------------------------------- + +sal_Bool SfxOrganizeMgr::Rescan() + +/* [Description] + + Updating the database. + + [Return value] + + TRUE Changes were made + FALSE No changes + + [Cross-reference] + + <SfxDocumentTemplates::Rescan()> +*/ + +{ + if(pTemplates->Rescan()) + { + bModified = sal_True; + return sal_True; + } + return sal_False; +} + +//------------------------------------------------------------------------- + +void SfxOrganizeMgr::SaveAll(Window *pParent) + +/* [Description] + + Save all Documents that have been modified + + [Parameter] + + Window *pParent Parent of the Error message Box +*/ + +{ + sal_uInt16 nRangeCount = pTemplates->GetRegionCount(); + sal_uInt16 i; + for(i = 0; i < nRangeCount; ++i) + { + if( pTemplates->IsRegionLoaded( i )) + { + const sal_uInt16 nCount = pTemplates->GetCount(i); + for(sal_uInt16 j = 0; j < nCount; ++j) + { + if(!pTemplates->DeleteObjectShell(i, j)) + { + String aText = String(SfxResId(STR_ERROR_SAVE_TEMPLATE)); + aText += pTemplates->GetName(i, j); + ErrorBox aBox(pParent, + WinBits(WB_OK_CANCEL | WB_DEF_CANCEL), + aText); + if(RET_CANCEL == aBox.Execute()) + break; + } + } + } + } + nRangeCount = pImpl->pDocList->Count(); + for(i = 0; i < nRangeCount; ++i) + { + _FileListEntry *pEntry = (*pImpl->pDocList)[i]; + if(!pEntry->DeleteObjectShell()) + { + String aText(SfxResId(STR_ERROR_SAVE_TEMPLATE)); + aText += pEntry->aBaseName; + ErrorBox aBox(pParent, WinBits(WB_OK_CANCEL | WB_DEF_CANCEL), aText); + if(RET_CANCEL == aBox.Execute()) + break; + } + } +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/printer.cxx b/sfx2/source/view/printer.cxx new file mode 100644 index 000000000000..5f044c94dc0b --- /dev/null +++ b/sfx2/source/view/printer.cxx @@ -0,0 +1,311 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" +#include <vcl/virdev.hxx> +#include <vcl/metric.hxx> +#include <vcl/msgbox.hxx> +#include <unotools/printwarningoptions.hxx> +#include <svtools/printoptions.hxx> +#include <vector> + +#include <sfx2/printer.hxx> +#include <sfx2/printopt.hxx> +#include "sfxtypes.hxx" +#include <sfx2/prnmon.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/tabdlg.hxx> +#include "sfx2/sfxresid.hxx" +#include "view.hrc" + +// struct SfxPrinter_Impl ------------------------------------------------ + +struct SfxPrinter_Impl +{ + sal_Bool mbAll; + sal_Bool mbSelection; + sal_Bool mbFromTo; + sal_Bool mbRange; + + SfxPrinter_Impl() : + mbAll ( sal_True ), + mbSelection ( sal_True ), + mbFromTo ( sal_True ), + mbRange ( sal_True ) {} + ~SfxPrinter_Impl() {} +}; + +struct SfxPrintOptDlg_Impl +{ + sal_Bool mbHelpDisabled; + + SfxPrintOptDlg_Impl() : + mbHelpDisabled ( sal_False ) {} +}; + +// class SfxPrinter ------------------------------------------------------ + +SfxPrinter* SfxPrinter::Create( SvStream& rStream, SfxItemSet* pOptions ) + +/* [Description] + + Creates a <SfxPrinter> from the stream. Loading is really only a jobsetup. + If such a printer is not available on the system, then the original is + marked as the original Job-setup and a comparable printer is selected from + existing ones. + + The 'pOptions' are taken over in the generated SfxPrinter, the return + value belongs to the caller. +*/ + +{ + // Load JobSetup + JobSetup aFileJobSetup; + rStream >> aFileJobSetup; + + // Get printers + SfxPrinter *pPrinter = new SfxPrinter( pOptions, aFileJobSetup ); + return pPrinter; +} + +//-------------------------------------------------------------------- + +SvStream& SfxPrinter::Store( SvStream& rStream ) const + +/* [Description] + + Saves the used JobSetup of <SfxPrinter>s. +*/ + +{ + return ( rStream << GetJobSetup() ); +} + +//-------------------------------------------------------------------- + +SfxPrinter::SfxPrinter( SfxItemSet* pTheOptions ) : + +/* [Description] + + This constructor creates a default printer. +*/ + + pOptions( pTheOptions ), + bKnown(sal_True) + +{ + pImpl = new SfxPrinter_Impl; +} + +//-------------------------------------------------------------------- + +SfxPrinter::SfxPrinter( SfxItemSet* pTheOptions, + const JobSetup& rTheOrigJobSetup ) : + + Printer ( rTheOrigJobSetup.GetPrinterName() ), + pOptions ( pTheOptions ) + +{ + pImpl = new SfxPrinter_Impl; + bKnown = GetName() == rTheOrigJobSetup.GetPrinterName(); + + if ( bKnown ) + SetJobSetup( rTheOrigJobSetup ); +} + +//-------------------------------------------------------------------- + +SfxPrinter::SfxPrinter( SfxItemSet* pTheOptions, + const String& rPrinterName ) : + + Printer ( rPrinterName ), + pOptions ( pTheOptions ), + bKnown ( GetName() == rPrinterName ) + +{ + pImpl = new SfxPrinter_Impl; +} + +//-------------------------------------------------------------------- + +SfxPrinter::SfxPrinter( const SfxPrinter& rPrinter ) : + + Printer ( rPrinter.GetName() ), + pOptions( rPrinter.GetOptions().Clone() ), + bKnown ( rPrinter.IsKnown() ) +{ + SetJobSetup( rPrinter.GetJobSetup() ); + SetPrinterProps( &rPrinter ); + SetMapMode( rPrinter.GetMapMode() ); + + pImpl = new SfxPrinter_Impl; + pImpl->mbAll = rPrinter.pImpl->mbAll; + pImpl->mbSelection = rPrinter.pImpl->mbSelection; + pImpl->mbFromTo = rPrinter.pImpl->mbFromTo; + pImpl->mbRange = rPrinter.pImpl->mbRange; +} + +//-------------------------------------------------------------------- + +SfxPrinter* SfxPrinter::Clone() const +{ + if ( IsDefPrinter() ) + { + SfxPrinter *pNewPrinter; + pNewPrinter = new SfxPrinter( GetOptions().Clone() ); + pNewPrinter->SetJobSetup( GetJobSetup() ); + pNewPrinter->SetPrinterProps( this ); + pNewPrinter->SetMapMode( GetMapMode() ); + pNewPrinter->pImpl->mbAll = pImpl->mbAll; + pNewPrinter->pImpl->mbSelection =pImpl->mbSelection; + pNewPrinter->pImpl->mbFromTo = pImpl->mbFromTo; + pNewPrinter->pImpl->mbRange =pImpl->mbRange; + return pNewPrinter; + } + else + return new SfxPrinter( *this ); +} + +//-------------------------------------------------------------------- + +SfxPrinter::~SfxPrinter() +{ + delete pOptions; + delete pImpl; +} + +//-------------------------------------------------------------------- + +void SfxPrinter::SetOptions( const SfxItemSet &rNewOptions ) +{ + pOptions->Set(rNewOptions); +} + +//-------------------------------------------------------------------- + +SfxPrintOptionsDialog::SfxPrintOptionsDialog( Window *pParent, + SfxViewShell *pViewShell, + const SfxItemSet *pSet ) : + + ModalDialog( pParent, WinBits( WB_STDMODAL | WB_3DLOOK ) ), + + aOkBtn ( this ), + aCancelBtn ( this ), + aHelpBtn ( this ), + pDlgImpl ( new SfxPrintOptDlg_Impl ), + pViewSh ( pViewShell ), + pOptions ( pSet->Clone() ), + pPage ( NULL ) + +{ + SetText( SfxResId( STR_PRINT_OPTIONS_TITLE ) ); + + // Insert TabPage + pPage = pViewSh->CreatePrintOptionsPage( this, *pOptions ); + DBG_ASSERT( pPage, "CreatePrintOptions != SFX_VIEW_HAS_PRINTOPTIONS" ); + if( pPage ) + { + pPage->Reset( *pOptions ); + SetHelpId( pPage->GetHelpId() ); + pPage->Show(); + } + + // Set dialog size + Size a6Sz = LogicToPixel( Size( 6, 6 ), MAP_APPFONT ); + Size aBtnSz = LogicToPixel( Size( 50, 14 ), MAP_APPFONT ); + Size aOutSz( pPage ? pPage->GetSizePixel() : Size() ); + aOutSz.Height() += 6; + long nWidth = aBtnSz.Width(); + nWidth += a6Sz.Width(); + aOutSz.Width() += nWidth; + if ( aOutSz.Height() < 90 ) + // at least the height of the 3 buttons + aOutSz.Height() = 90; + SetOutputSizePixel( aOutSz ); + + // set position and size of the buttons + Point aBtnPos( aOutSz.Width() - aBtnSz.Width() - a6Sz.Width(), a6Sz.Height() ); + aOkBtn.SetPosSizePixel( aBtnPos, aBtnSz ); + aBtnPos.Y() += aBtnSz.Height() + ( a6Sz.Height() / 2 ); + aCancelBtn.SetPosSizePixel( aBtnPos, aBtnSz ); + aBtnPos.Y() += aBtnSz.Height() + a6Sz.Height(); + aHelpBtn.SetPosSizePixel( aBtnPos, aBtnSz ); + + aCancelBtn.Show(); + aOkBtn.Show(); + aHelpBtn.Show(); +} + +//-------------------------------------------------------------------- + +SfxPrintOptionsDialog::~SfxPrintOptionsDialog() +{ + delete pDlgImpl; + delete pPage; + delete pOptions; +} + +//-------------------------------------------------------------------- + +short SfxPrintOptionsDialog::Execute() +{ + if( ! pPage ) + return RET_CANCEL; + + short nRet = ModalDialog::Execute(); + if ( nRet == RET_OK ) + pPage->FillItemSet( *pOptions ); + else + pPage->Reset( *pOptions ); + return nRet; +} + +//-------------------------------------------------------------------- + +long SfxPrintOptionsDialog::Notify( NotifyEvent& rNEvt ) +{ + if ( rNEvt.GetType() == EVENT_KEYINPUT ) + { + if ( rNEvt.GetKeyEvent()->GetKeyCode().GetCode() == KEY_F1 && pDlgImpl->mbHelpDisabled ) + return 1; // help disabled -> <F1> does nothing + } + + return ModalDialog::Notify( rNEvt ); +} + +//-------------------------------------------------------------------- + +void SfxPrintOptionsDialog::DisableHelp() +{ + pDlgImpl->mbHelpDisabled = sal_True; + + aHelpBtn.Disable(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/sfxbasecontroller.cxx b/sfx2/source/view/sfxbasecontroller.cxx new file mode 100644 index 000000000000..58f1cfa64676 --- /dev/null +++ b/sfx2/source/view/sfxbasecontroller.cxx @@ -0,0 +1,1544 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +//________________________________________________________________________________________________________ +// my own includes +//________________________________________________________________________________________________________ + +#include <time.h> +#include <sfx2/sfxbasecontroller.hxx> + +//________________________________________________________________________________________________________ +// include of other projects +//________________________________________________________________________________________________________ +#include <com/sun/star/awt/KeyEvent.hpp> +#include <com/sun/star/awt/KeyModifier.hpp> +#include <com/sun/star/awt/MouseEvent.hpp> +#include <com/sun/star/awt/MouseButton.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/util/XCloseBroadcaster.hpp> +#include <com/sun/star/util/XCloseListener.hpp> +#include <com/sun/star/util/CloseVetoException.hpp> +#include <com/sun/star/document/XViewDataSupplier.hpp> +#include <cppuhelper/implbase1.hxx> +#include <cppuhelper/implbase2.hxx> +#include <com/sun/star/frame/FrameActionEvent.hpp> +#include <com/sun/star/frame/FrameAction.hpp> +#include <com/sun/star/frame/CommandGroup.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XBorderResizeListener.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/EventObject.hpp> +#include <com/sun/star/lang/XEventListener.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <cppuhelper/interfacecontainer.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <cppuhelper/implbase1.hxx> +#include <basic/sbstar.hxx> +#include <uno/mapping.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/docfac.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/app.hxx> +#include <sfx2/msgpool.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/userinputinterception.hxx> + +#include <viewimp.hxx> +#include <sfx2/unoctitm.hxx> +#include <sfx2/childwin.hxx> +#include <sfx2/sfxsids.hrc> +#include <workwin.hxx> +#include <sfx2/objface.hxx> + +#include <osl/mutex.hxx> +#include <osl/mutex.hxx> +#include <tools/diagnose_ex.h> +#include <comphelper/sequence.hxx> +#include <rtl/ustrbuf.hxx> +#include <toolkit/helper/convert.hxx> +#include <framework/titlehelper.hxx> +#include <comphelper/processfactory.hxx> +#include <tools/diagnose_ex.h> + +#include <boost/unordered_map.hpp> + +#include <sfx2/event.hxx> +#include "sfx2/viewfac.hxx" + +#define OMULTITYPEINTERFACECONTAINERHELPER ::cppu::OMultiTypeInterfaceContainerHelper +#define OINTERFACECONTAINERHELPER ::cppu::OInterfaceContainerHelper +#define XFRAMEACTIONLISTENER ::com::sun::star::frame::XFrameActionListener +#define XCLOSELISTENER ::com::sun::star::util::XCloseListener +#define FRAMEACTIONEVENT ::com::sun::star::frame::FrameActionEvent +#define EVENTOBJECT ::com::sun::star::lang::EventObject +#define OTYPECOLLECTION ::cppu::OTypeCollection +#define OIMPLEMENTATIONID ::cppu::OImplementationId +#define MUTEXGUARD ::osl::MutexGuard +#define UNOQUERY ::com::sun::star::uno::UNO_QUERY +#define MAPPING ::com::sun::star::uno::Mapping +#define XSTATUSINDICATORSUPPLIER ::com::sun::star::task::XStatusIndicatorSupplier +#define XCOMPONENT ::com::sun::star::lang::XComponent +#define XINTERFACE ::com::sun::star::uno::XInterface +#define XKEYHANDLER ::com::sun::star::awt::XKeyHandler +#define XMOUSECLICKHANDLER ::com::sun::star::awt::XMouseClickHandler + +#define TIMEOUT_START_RESCHEDULE 10L /* 10th s */ + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::uno::UNO_SET_THROW; +using ::com::sun::star::lang::DisposedException; +using ::com::sun::star::awt::XWindow; +using ::com::sun::star::frame::XController; +using ::com::sun::star::frame::XDispatchProvider; +using ::com::sun::star::document::XViewDataSupplier; +using ::com::sun::star::container::XIndexAccess; +using ::com::sun::star::beans::PropertyValue; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::frame::XFrame; +using ::com::sun::star::frame::XFrameActionListener; +using ::com::sun::star::util::XCloseListener; +using ::com::sun::star::task::XStatusIndicator; +using ::com::sun::star::frame::XTitle; +namespace css = ::com::sun::star; + +struct GroupIDToCommandGroup +{ + sal_Int16 nGroupID; + sal_Int16 nCommandGroup; +}; + +// Please update when a new command group is added +const sal_Int16 MAX_COMMANDGROUP = com::sun::star::frame::CommandGroup::CONTROLS; + +static sal_Bool bGroupIDMapInitialized = sal_False; +static GroupIDToCommandGroup GroupIDCommandGroupMap[] = +{ + { GID_INTERN , com::sun::star::frame::CommandGroup::INTERNAL }, + { GID_APPLICATION , com::sun::star::frame::CommandGroup::APPLICATION }, + { GID_DOCUMENT , com::sun::star::frame::CommandGroup::DOCUMENT }, + { GID_VIEW , com::sun::star::frame::CommandGroup::VIEW }, + { GID_EDIT , com::sun::star::frame::CommandGroup::EDIT }, + { GID_MACRO , com::sun::star::frame::CommandGroup::MACRO }, + { GID_OPTIONS , com::sun::star::frame::CommandGroup::OPTIONS }, + { GID_MATH , com::sun::star::frame::CommandGroup::MATH }, + { GID_NAVIGATOR , com::sun::star::frame::CommandGroup::NAVIGATOR }, + { GID_INSERT , com::sun::star::frame::CommandGroup::INSERT }, + { GID_FORMAT , com::sun::star::frame::CommandGroup::FORMAT }, + { GID_TEMPLATE , com::sun::star::frame::CommandGroup::TEMPLATE }, + { GID_TEXT , com::sun::star::frame::CommandGroup::TEXT }, + { GID_FRAME , com::sun::star::frame::CommandGroup::FRAME }, + { GID_GRAPHIC , com::sun::star::frame::CommandGroup::GRAPHIC }, + { GID_TABLE , com::sun::star::frame::CommandGroup::TABLE }, + { GID_ENUMERATION , com::sun::star::frame::CommandGroup::ENUMERATION }, + { GID_DATA , com::sun::star::frame::CommandGroup::DATA }, + { GID_SPECIAL , com::sun::star::frame::CommandGroup::SPECIAL }, + { GID_IMAGE , com::sun::star::frame::CommandGroup::IMAGE }, + { GID_CHART , com::sun::star::frame::CommandGroup::CHART }, + { GID_EXPLORER , com::sun::star::frame::CommandGroup::EXPLORER }, + { GID_CONNECTOR , com::sun::star::frame::CommandGroup::CONNECTOR }, + { GID_MODIFY , com::sun::star::frame::CommandGroup::MODIFY }, + { GID_DRAWING , com::sun::star::frame::CommandGroup::DRAWING }, + { GID_CONTROLS , com::sun::star::frame::CommandGroup::CONTROLS }, + { 0 , 0 } +}; + +typedef boost::unordered_map< sal_Int16, sal_Int16 > GroupHashMap; + + +sal_Int16 MapGroupIDToCommandGroup( sal_Int16 nGroupID ) +{ + static GroupHashMap mHashMap; + + if ( !bGroupIDMapInitialized ) + { + sal_Int32 i = 0; + while ( GroupIDCommandGroupMap[i].nGroupID != 0 ) + { + mHashMap.insert( GroupHashMap::value_type( + GroupIDCommandGroupMap[i].nGroupID, + GroupIDCommandGroupMap[i].nCommandGroup )); + ++i; + } + } + + GroupHashMap::const_iterator pIter = mHashMap.find( nGroupID ); + if ( pIter != mHashMap.end() ) + return pIter->second; + else + return com::sun::star::frame::CommandGroup::INTERNAL; +} + +sal_Int16 MapCommandGroupToGroupID( sal_Int16 nCommandGroup ) +{ + sal_Int32 i = 0; + while ( GroupIDCommandGroupMap[i].nGroupID != 0 ) + { + if ( GroupIDCommandGroupMap[i].nCommandGroup == nCommandGroup ) + return GroupIDCommandGroupMap[i].nGroupID; + ++i; + } + + return -1; +} + +sal_Bool SupportsCommandGroup( sal_Int16 nCommandGroup ) +{ + if (( nCommandGroup >= 0 ) && ( nCommandGroup <= MAX_COMMANDGROUP )) + return sal_True; + else + return sal_False; +} + +sal_uInt32 Get10ThSec() +{ + sal_uInt32 n10Ticks = 10 * (sal_uInt32)clock(); + return n10Ticks / CLOCKS_PER_SEC; +} + +sal_Int32 m_nInReschedule = 0; /// static counter for rescheduling + +void reschedule() +{ + if ( m_nInReschedule == 0 ) + { + ++m_nInReschedule; + Application::Reschedule(); + --m_nInReschedule; + } +} + +class SfxStatusIndicator : public ::cppu::WeakImplHelper2< ::com::sun::star::task::XStatusIndicator, ::com::sun::star::lang::XEventListener > +{ +friend class SfxBaseController; + ::com::sun::star::uno::Reference < XController > xOwner; + ::com::sun::star::uno::Reference < ::com::sun::star::task::XStatusIndicator > xProgress; + SfxWorkWindow* pWorkWindow; + sal_Int32 _nRange; + sal_Int32 _nValue; + long _nStartTime; +public: + SfxStatusIndicator(SfxBaseController* pController, SfxWorkWindow* pWork) + : xOwner( pController ) + , pWorkWindow( pWork ) + { + ++m_refCount; + ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > xComponent( + SAL_STATIC_CAST(::cppu::OWeakObject*, pController ), ::com::sun::star::uno::UNO_QUERY ); + if (xComponent.is()) + xComponent->addEventListener(this); + --m_refCount; + } + + virtual void SAL_CALL start(const ::rtl::OUString& aText, sal_Int32 nRange) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL end(void) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setText(const ::rtl::OUString& aText) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setValue(sal_Int32 nValue) throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL reset() throw(::com::sun::star::uno::RuntimeException); + + virtual void SAL_CALL disposing( const com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException); +}; + +void SAL_CALL SfxStatusIndicator::start(const ::rtl::OUString& aText, sal_Int32 nRange) throw(::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if ( xOwner.is() ) + { + _nRange = nRange; + _nValue = 0; + + if ( !xProgress.is() ) + xProgress = pWorkWindow->GetStatusIndicator(); + + if ( xProgress.is() ) + xProgress->start( aText, nRange ); + + _nStartTime = Get10ThSec(); + reschedule(); + } +} + +void SAL_CALL SfxStatusIndicator::end(void) throw(::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if ( xOwner.is() ) + { + if ( !xProgress.is() ) + xProgress = pWorkWindow->GetStatusIndicator(); + + if ( xProgress.is() ) + xProgress->end(); + + reschedule(); + } +} + +void SAL_CALL SfxStatusIndicator::setText(const ::rtl::OUString& aText) throw(::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if ( xOwner.is() ) + { + if ( !xProgress.is() ) + xProgress = pWorkWindow->GetStatusIndicator(); + + if ( xProgress.is() ) + xProgress->setText( aText ); + + reschedule(); + } +} + +void SAL_CALL SfxStatusIndicator::setValue( sal_Int32 nValue ) throw(::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if ( xOwner.is() ) + { + _nValue = nValue; + + if ( !xProgress.is() ) + xProgress = pWorkWindow->GetStatusIndicator(); + + if ( xProgress.is() ) + xProgress->setValue( nValue ); + + sal_Bool bReschedule = (( Get10ThSec() - _nStartTime ) > TIMEOUT_START_RESCHEDULE ); + if ( bReschedule ) + reschedule(); + } +} + +void SAL_CALL SfxStatusIndicator::reset() throw(::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if ( xOwner.is() ) + { + if ( !xProgress.is() ) + xProgress = pWorkWindow->GetStatusIndicator(); + + if ( xProgress.is() ) + xProgress->reset(); + + reschedule(); + } +} + +void SAL_CALL SfxStatusIndicator::disposing( const com::sun::star::lang::EventObject& /*Source*/ ) throw(::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard aGuard; + xOwner = 0; + xProgress.clear(); +} + +//________________________________________________________________________________________________________ +// declaration IMPL_SfxBaseController_ListenerHelper +//________________________________________________________________________________________________________ + +class IMPL_SfxBaseController_ListenerHelper : public ::cppu::WeakImplHelper1< ::com::sun::star::frame::XFrameActionListener > +{ +public: + IMPL_SfxBaseController_ListenerHelper( MUTEX& aMutex , + SfxBaseController* pController ) ; + virtual ~IMPL_SfxBaseController_ListenerHelper() ; + virtual void SAL_CALL frameAction( const FRAMEACTIONEVENT& aEvent ) throw (RUNTIMEEXCEPTION) ; + virtual void SAL_CALL disposing( const EVENTOBJECT& aEvent ) throw (RUNTIMEEXCEPTION) ; + +private: + + MUTEX& m_aMutex ; + SfxBaseController* m_pController ; + +} ; // class IMPL_SfxBaseController_ListenerContainer + +class IMPL_SfxBaseController_CloseListenerHelper : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XCloseListener > +{ +public: + IMPL_SfxBaseController_CloseListenerHelper( MUTEX& aMutex , + SfxBaseController* pController ) ; + virtual ~IMPL_SfxBaseController_CloseListenerHelper() ; + virtual void SAL_CALL queryClosing( const EVENTOBJECT& aEvent, sal_Bool bDeliverOwnership ) + throw (RUNTIMEEXCEPTION, com::sun::star::util::CloseVetoException) ; + virtual void SAL_CALL notifyClosing( const EVENTOBJECT& aEvent ) throw (RUNTIMEEXCEPTION) ; + virtual void SAL_CALL disposing( const EVENTOBJECT& aEvent ) throw (RUNTIMEEXCEPTION) ; + +private: + + MUTEX& m_aMutex; + SfxBaseController* m_pController; + +} ; // class IMPL_SfxBaseController_ListenerContainer + +IMPL_SfxBaseController_CloseListenerHelper::IMPL_SfxBaseController_CloseListenerHelper( MUTEX& aMutex , + SfxBaseController* pController ) + : m_aMutex ( aMutex ) + , m_pController ( pController ) +{ +} + +IMPL_SfxBaseController_CloseListenerHelper::~IMPL_SfxBaseController_CloseListenerHelper() +{ +} + +void SAL_CALL IMPL_SfxBaseController_CloseListenerHelper::disposing( const EVENTOBJECT& /*aEvent*/ ) throw( ::com::sun::star::uno::RuntimeException ) +{ +} + +void SAL_CALL IMPL_SfxBaseController_CloseListenerHelper::queryClosing( const EVENTOBJECT& aEvent, sal_Bool bDeliverOwnership ) + throw (RUNTIMEEXCEPTION, com::sun::star::util::CloseVetoException) +{ + SolarMutexGuard aGuard; + SfxViewShell* pShell = m_pController->GetViewShell_Impl(); + if ( m_pController != NULL && pShell ) + { + sal_Bool bCanClose = (sal_Bool) pShell->PrepareClose( sal_False ); + if ( !bCanClose ) + { + if ( bDeliverOwnership && ( !pShell->GetWindow() || !pShell->GetWindow()->IsReallyVisible() ) ) + { + // ignore OwnerShip in case of visible frame (will be closed by user) + uno::Reference < frame::XModel > xModel( aEvent.Source, uno::UNO_QUERY ); + if ( xModel.is() ) + pShell->TakeOwnerShip_Impl(); + else + pShell->TakeFrameOwnerShip_Impl(); + } + + throw com::sun::star::util::CloseVetoException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Controller disagree ...")),static_cast< ::cppu::OWeakObject*>(this)); + } + } +} + +void SAL_CALL IMPL_SfxBaseController_CloseListenerHelper::notifyClosing( const EVENTOBJECT& /*aEvent*/ ) throw (RUNTIMEEXCEPTION) +{ +} + +//________________________________________________________________________________________________________ +// declaration IMPL_SfxBaseController_DataContainer +//________________________________________________________________________________________________________ + +struct IMPL_SfxBaseController_DataContainer +{ + Reference< XFrame > m_xFrame ; + Reference< XFrameActionListener > m_xListener ; + Reference< XCloseListener > m_xCloseListener ; + ::sfx2::UserInputInterception m_aUserInputInterception; + OMULTITYPEINTERFACECONTAINERHELPER m_aListenerContainer ; + OINTERFACECONTAINERHELPER m_aInterceptorContainer ; + Reference< XStatusIndicator > m_xIndicator ; + SfxViewShell* m_pViewShell ; + SfxBaseController* m_pController ; + sal_Bool m_bDisposing ; + sal_Bool m_bSuspendState ; + Reference< XTitle > m_xTitleHelper ; + Sequence< PropertyValue > m_aCreationArgs ; + + IMPL_SfxBaseController_DataContainer( MUTEX& aMutex , + SfxViewShell* pViewShell , + SfxBaseController* pController ) + : m_xListener ( new IMPL_SfxBaseController_ListenerHelper( aMutex, pController ) ) + , m_xCloseListener ( new IMPL_SfxBaseController_CloseListenerHelper( aMutex, pController ) ) + , m_aUserInputInterception ( *pController, aMutex ) + , m_aListenerContainer ( aMutex ) + , m_aInterceptorContainer ( aMutex ) + , m_pViewShell ( pViewShell ) + , m_pController ( pController ) + , m_bDisposing ( sal_False ) + , m_bSuspendState ( sal_False ) + { + } + +} ; // struct IMPL_SfxBaseController_DataContainer + +//________________________________________________________________________________________________________ +// IMPL_SfxBaseController_ListenerHelper constructor +//________________________________________________________________________________________________________ + +IMPL_SfxBaseController_ListenerHelper::IMPL_SfxBaseController_ListenerHelper( MUTEX& aMutex , + SfxBaseController* pController ) + : m_aMutex ( aMutex ) + , m_pController ( pController ) +{ +} + +//________________________________________________________________________________________________________ +// IMPL_SfxBaseController_ListenerHelper destructor +//________________________________________________________________________________________________________ + +IMPL_SfxBaseController_ListenerHelper::~IMPL_SfxBaseController_ListenerHelper() +{ +} + +void SAL_CALL IMPL_SfxBaseController_ListenerHelper::frameAction( const FRAMEACTIONEVENT& aEvent ) throw( RUNTIMEEXCEPTION ) +{ + SolarMutexGuard aGuard; + if ( + ( m_pController != NULL ) && + ( aEvent.Frame == m_pController->getFrame() ) && + ( m_pController->GetViewShell_Impl() && m_pController->GetViewShell_Impl()->GetWindow() != NULL ) + ) + { + if ( aEvent.Action == ::com::sun::star::frame::FrameAction_FRAME_UI_ACTIVATED ) + { + if ( !m_pController->GetViewShell_Impl()->GetUIActiveIPClient_Impl() ) + m_pController->GetViewShell_Impl()->GetViewFrame()->MakeActive_Impl( sal_False ); + } + else if ( aEvent.Action == ::com::sun::star::frame::FrameAction_CONTEXT_CHANGED ) + { + m_pController->GetViewShell_Impl()->GetViewFrame()->GetBindings().ContextChanged_Impl(); + } + } +} + +//________________________________________________________________________________________________________ +// IMPL_SfxBaseController_ListenerHelper -> XEventListener +//________________________________________________________________________________________________________ + +void SAL_CALL IMPL_SfxBaseController_ListenerHelper::disposing( const EVENTOBJECT& /*aEvent*/ ) throw( ::com::sun::star::uno::RuntimeException ) +{ + SolarMutexGuard aGuard; + if ( m_pController && m_pController->getFrame().is() ) + m_pController->getFrame()->removeFrameActionListener( this ) ; +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> constructor +//________________________________________________________________________________________________________ +DBG_NAME(sfx2_SfxBaseController) +SfxBaseController::SfxBaseController( SfxViewShell* pViewShell ) + : m_pData ( new IMPL_SfxBaseController_DataContainer( m_aMutex, pViewShell, this )) +{ + DBG_CTOR(sfx2_SfxBaseController,NULL); + m_pData->m_pViewShell->SetController( this ); +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> destructor +//________________________________________________________________________________________________________ + +SfxBaseController::~SfxBaseController() +{ + DBG_DTOR(sfx2_SfxBaseController,NULL); + delete m_pData; +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XController2 +//________________________________________________________________________________________________________ + +Reference< XWindow > SAL_CALL SfxBaseController::getComponentWindow() throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if ( !m_pData->m_pViewShell ) + throw DisposedException(); + + return Reference< XWindow >( GetViewFrame_Impl().GetFrame().GetWindow().GetComponentInterface(), UNO_QUERY_THROW ); +} + +::rtl::OUString SAL_CALL SfxBaseController::getViewControllerName() throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if ( !m_pData->m_pViewShell || !m_pData->m_pViewShell->GetObjectShell() ) + throw DisposedException(); + + const SfxObjectFactory& rDocFac( m_pData->m_pViewShell->GetObjectShell()->GetFactory() ); + sal_uInt16 nViewNo = rDocFac.GetViewNo_Impl( GetViewFrame_Impl().GetCurViewId(), rDocFac.GetViewFactoryCount() ); + OSL_ENSURE( nViewNo < rDocFac.GetViewFactoryCount(), "SfxBaseController::getViewControllerName: view ID not found in view factories!" ); + + ::rtl::OUString sViewName; + if ( nViewNo < rDocFac.GetViewFactoryCount() ) + sViewName = rDocFac.GetViewFactory( nViewNo ).GetAPIViewName(); + + return sViewName; +} + +Sequence< PropertyValue > SAL_CALL SfxBaseController::getCreationArguments() throw (RuntimeException) +{ + SolarMutexGuard aGuard; + if ( !m_pData->m_pViewShell || !m_pData->m_pViewShell->GetObjectShell() ) + throw DisposedException(); + + return m_pData->m_aCreationArgs; +} + +void SfxBaseController::SetCreationArguments_Impl( const Sequence< PropertyValue >& i_rCreationArgs ) +{ + OSL_ENSURE( m_pData->m_aCreationArgs.getLength() == 0, "SfxBaseController::SetCreationArguments_Impl: not intended to be called twice!" ); + m_pData->m_aCreationArgs = i_rCreationArgs; +} + +SfxViewFrame& SfxBaseController::GetViewFrame_Impl() const +{ + ENSURE_OR_THROW( m_pData->m_pViewShell, "not to be called without a view shell" ); + SfxViewFrame* pActFrame = m_pData->m_pViewShell->GetFrame(); + ENSURE_OR_THROW( pActFrame, "a view shell without a view frame is pretty pathological" ); + return *pActFrame; +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XController2 -> XController +//________________________________________________________________________________________________________ + +void SAL_CALL SfxBaseController::attachFrame( const REFERENCE< XFRAME >& xFrame ) throw( ::com::sun::star::uno::RuntimeException ) +{ + REFERENCE< XFRAME > xTemp( getFrame() ) ; + + SolarMutexGuard aGuard; + if ( xTemp.is() ) + { + xTemp->removeFrameActionListener( m_pData->m_xListener ) ; + REFERENCE < ::com::sun::star::util::XCloseBroadcaster > xCloseable( xTemp, com::sun::star::uno::UNO_QUERY ); + if ( xCloseable.is() ) + xCloseable->removeCloseListener( m_pData->m_xCloseListener ); + } + + m_pData->m_xFrame = xFrame; + + if ( xFrame.is() ) + { + xFrame->addFrameActionListener( m_pData->m_xListener ) ; + REFERENCE < ::com::sun::star::util::XCloseBroadcaster > xCloseable( xFrame, com::sun::star::uno::UNO_QUERY ); + if ( xCloseable.is() ) + xCloseable->addCloseListener( m_pData->m_xCloseListener ); + + if ( m_pData->m_pViewShell ) + { + ConnectSfxFrame_Impl( E_CONNECT ); + + // attaching the frame to the controller is the last step in the creation of a new view, so notify this + SfxViewEventHint aHint( SFX_EVENT_VIEWCREATED, GlobalEventConfig::GetEventName( STR_EVENT_VIEWCREATED ), m_pData->m_pViewShell->GetObjectShell(), uno::Reference< frame::XController2 >( this ) ); + SFX_APP()->NotifyEvent( aHint ); + } + } +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XController +//________________________________________________________________________________________________________ + +sal_Bool SAL_CALL SfxBaseController::attachModel( const REFERENCE< XMODEL >& xModel ) throw( ::com::sun::star::uno::RuntimeException ) +{ + if ( m_pData->m_pViewShell && xModel.is() && xModel != m_pData->m_pViewShell->GetObjectShell()->GetModel() ) + { + // don't allow to reattach a model! + OSL_FAIL("Can't reattach model!"); + return sal_False; + } + + REFERENCE < ::com::sun::star::util::XCloseBroadcaster > xCloseable( xModel, com::sun::star::uno::UNO_QUERY ); + if ( xCloseable.is() ) + xCloseable->addCloseListener( m_pData->m_xCloseListener ); + return sal_True; +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XController +//________________________________________________________________________________________________________ + +sal_Bool SAL_CALL SfxBaseController::suspend( sal_Bool bSuspend ) throw( ::com::sun::star::uno::RuntimeException ) +{ + SolarMutexGuard aGuard; + + // ignore dublicate calls, which doesnt change anything real + if (bSuspend == m_pData->m_bSuspendState) + return sal_True; + + if ( bSuspend == sal_True ) + { + if ( !m_pData->m_pViewShell ) + { + m_pData->m_bSuspendState = sal_True; + return sal_True; + } + + if ( !m_pData->m_pViewShell->PrepareClose() ) + return sal_False; + + if ( getFrame().is() ) + getFrame()->removeFrameActionListener( m_pData->m_xListener ) ; + SfxViewFrame* pActFrame = m_pData->m_pViewShell->GetFrame() ; + + // More Views on the same document? + SfxObjectShell* pDocShell = m_pData->m_pViewShell->GetObjectShell() ; + sal_Bool bOther = sal_False ; + + for ( const SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocShell ); !bOther && pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, pDocShell ) ) + bOther = (pFrame != pActFrame); + + sal_Bool bRet = bOther || pDocShell->PrepareClose(); + if ( bRet ) + { + ConnectSfxFrame_Impl( E_DISCONNECT ); + m_pData->m_bSuspendState = sal_True; + } + + return bRet; + } + else + { + if ( getFrame().is() ) + getFrame()->addFrameActionListener( m_pData->m_xListener ) ; + + if ( m_pData->m_pViewShell ) + { + ConnectSfxFrame_Impl( E_RECONNECT ); + } + + m_pData->m_bSuspendState = sal_False; + return sal_True ; + } +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XController +//________________________________________________________________________________________________________ + +ANY SfxBaseController::getViewData() throw( ::com::sun::star::uno::RuntimeException ) +{ + ANY aAny; + String sData1; + SolarMutexGuard aGuard; + if ( m_pData->m_pViewShell ) + { + m_pData->m_pViewShell->WriteUserData( sData1 ) ; + ::rtl::OUString sData( sData1 ); + aAny <<= sData ; + } + + return aAny ; +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XController +//________________________________________________________________________________________________________ + +void SAL_CALL SfxBaseController::restoreViewData( const ANY& aValue ) throw( ::com::sun::star::uno::RuntimeException ) +{ + SolarMutexGuard aGuard; + if ( m_pData->m_pViewShell ) + { + ::rtl::OUString sData; + aValue >>= sData ; + m_pData->m_pViewShell->ReadUserData( sData ) ; + } +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XController +//________________________________________________________________________________________________________ + +REFERENCE< XFRAME > SAL_CALL SfxBaseController::getFrame() throw( ::com::sun::star::uno::RuntimeException ) +{ + SolarMutexGuard aGuard; + return m_pData->m_xFrame; +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XController +//________________________________________________________________________________________________________ + +REFERENCE< XMODEL > SAL_CALL SfxBaseController::getModel() throw( ::com::sun::star::uno::RuntimeException ) +{ + SolarMutexGuard aGuard; + return m_pData->m_pViewShell ? m_pData->m_pViewShell->GetObjectShell()->GetModel() : REFERENCE < XMODEL > () ; +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XDispatchProvider +//________________________________________________________________________________________________________ + +REFERENCE< XDISPATCH > SAL_CALL SfxBaseController::queryDispatch( const UNOURL& aURL , + const ::rtl::OUString& sTargetFrameName, + sal_Int32 eSearchFlags ) throw( RUNTIMEEXCEPTION ) +{ + SolarMutexGuard aGuard; + REFERENCE< XDISPATCH > xDisp; + if ( m_pData->m_pViewShell ) + { + SfxViewFrame* pAct = m_pData->m_pViewShell->GetViewFrame() ; + if ( !m_pData->m_bDisposing ) + { + if ( sTargetFrameName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("_beamer")) ) + { + SfxViewFrame *pFrame = m_pData->m_pViewShell->GetViewFrame(); + if ( eSearchFlags & ( ::com::sun::star::frame::FrameSearchFlag::CREATE )) + pFrame->SetChildWindow( SID_BROWSER, sal_True ); + SfxChildWindow* pChildWin = pFrame->GetChildWindow( SID_BROWSER ); + REFERENCE < XFRAME > xFrame; + if ( pChildWin ) + xFrame = ( pChildWin->GetFrame() ); + if ( xFrame.is() ) + xFrame->setName( sTargetFrameName ); + + Reference< XDispatchProvider > xProv( xFrame, ::com::sun::star::uno::UNO_QUERY ); + if ( xProv.is() ) + return xProv->queryDispatch( aURL, sTargetFrameName, ::com::sun::star::frame::FrameSearchFlag::SELF ); + } + + if ( aURL.Protocol.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(".uno:")) ) + { + rtl::OUString aMasterCommand = SfxOfficeDispatch::GetMasterUnoCommand( aURL ); + sal_Bool bMasterCommand( aMasterCommand.getLength() > 0 ); + + pAct = m_pData->m_pViewShell->GetViewFrame() ; + SfxSlotPool& rSlotPool = SfxSlotPool::GetSlotPool( pAct ); + + const SfxSlot* pSlot( 0 ); + if ( bMasterCommand ) + pSlot = rSlotPool.GetUnoSlot( aMasterCommand ); + else + pSlot = rSlotPool.GetUnoSlot( aURL.Path ); + if ( pSlot && ( !pAct->GetFrame().IsInPlace() || !pSlot->IsMode( SFX_SLOT_CONTAINER ) ) ) + return pAct->GetBindings().GetDispatch( pSlot, aURL, bMasterCommand ); + else + { + // try to find parent SfxViewFrame + uno::Reference< frame::XFrame > xParentFrame; + uno::Reference< frame::XFrame > xOwnFrame = pAct->GetFrame().GetFrameInterface(); + if ( xOwnFrame.is() ) + xParentFrame = uno::Reference< frame::XFrame >( xOwnFrame->getCreator(), uno::UNO_QUERY ); + + if ( xParentFrame.is() ) + { + // TODO/LATER: in future probably SfxViewFrame hirarchy should be the same as XFrame hirarchy + // SfxViewFrame* pParentFrame = pAct->GetParentViewFrame(); + + // search the related SfxViewFrame + SfxViewFrame* pParentFrame = NULL; + for ( SfxViewFrame* pFrame = SfxViewFrame::GetFirst(); + pFrame; + pFrame = SfxViewFrame::GetNext( *pFrame ) ) + { + if ( pFrame->GetFrame().GetFrameInterface() == xParentFrame ) + { + pParentFrame = pFrame; + break; + } + } + + if ( pParentFrame ) + { + SfxSlotPool& rFrameSlotPool = SfxSlotPool::GetSlotPool( pParentFrame ); + const SfxSlot* pSlot2( 0 ); + if ( bMasterCommand ) + pSlot2 = rFrameSlotPool.GetUnoSlot( aMasterCommand ); + else + pSlot2 = rFrameSlotPool.GetUnoSlot( aURL.Path ); + + if ( pSlot2 ) + return pParentFrame->GetBindings().GetDispatch( pSlot2, aURL, bMasterCommand ); + } + } + } + } + else if ( aURL.Protocol.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("slot:")) ) + { + sal_uInt16 nId = (sal_uInt16) aURL.Path.toInt32(); + + pAct = m_pData->m_pViewShell->GetViewFrame() ; + if (nId >= SID_VERB_START && nId <= SID_VERB_END) + { + const SfxSlot* pSlot = m_pData->m_pViewShell->GetVerbSlot_Impl(nId); + if ( pSlot ) + return pAct->GetBindings().GetDispatch( pSlot, aURL, sal_False ); + } + + SfxSlotPool& rSlotPool = SfxSlotPool::GetSlotPool( pAct ); + const SfxSlot* pSlot = rSlotPool.GetSlot( nId ); + if ( pSlot && ( !pAct->GetFrame().IsInPlace() || !pSlot->IsMode( SFX_SLOT_CONTAINER ) ) ) + return pAct->GetBindings().GetDispatch( pSlot, aURL, sal_False ); + else + { + // try to find parent SfxViewFrame + uno::Reference< frame::XFrame > xParentFrame; + uno::Reference< frame::XFrame > xOwnFrame = pAct->GetFrame().GetFrameInterface(); + if ( xOwnFrame.is() ) + xParentFrame = uno::Reference< frame::XFrame >( xOwnFrame->getCreator(), uno::UNO_QUERY ); + + if ( xParentFrame.is() ) + { + // TODO/LATER: in future probably SfxViewFrame hirarchy should be the same as XFrame hirarchy + // SfxViewFrame* pParentFrame = pAct->GetParentViewFrame(); + + // search the related SfxViewFrame + SfxViewFrame* pParentFrame = NULL; + for ( SfxViewFrame* pFrame = SfxViewFrame::GetFirst(); + pFrame; + pFrame = SfxViewFrame::GetNext( *pFrame ) ) + { + if ( pFrame->GetFrame().GetFrameInterface() == xParentFrame ) + { + pParentFrame = pFrame; + break; + } + } + + if ( pParentFrame ) + { + SfxSlotPool& rSlotPool2 = SfxSlotPool::GetSlotPool( pParentFrame ); + const SfxSlot* pSlot2 = rSlotPool2.GetUnoSlot( aURL.Path ); + if ( pSlot2 ) + return pParentFrame->GetBindings().GetDispatch( pSlot2, aURL, sal_False ); + } + } + } + } + else if( sTargetFrameName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("_self")) || sTargetFrameName.getLength()==0 ) + { + // check for already loaded URL ... but with additional jumpmark! + REFERENCE< XMODEL > xModel = getModel(); + if( xModel.is() && aURL.Mark.getLength() ) + { + SfxSlotPool& rSlotPool = SfxSlotPool::GetSlotPool( pAct ); + const SfxSlot* pSlot = rSlotPool.GetSlot( SID_JUMPTOMARK ); + if( aURL.Main.getLength() && aURL.Main == xModel->getURL() && pSlot ) + return REFERENCE< XDISPATCH >( new SfxOfficeDispatch( pAct->GetBindings(), pAct->GetDispatcher(), pSlot, aURL) ); + } + } + } + } + + return xDisp; +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XDispatchProvider +//________________________________________________________________________________________________________ + +uno::Sequence< REFERENCE< XDISPATCH > > SAL_CALL SfxBaseController::queryDispatches( const uno::Sequence< DISPATCHDESCRIPTOR >& seqDescripts ) throw( ::com::sun::star::uno::RuntimeException ) +{ + // Create return list - which must have same size then the given descriptor + // It's not allowed to pack it! + sal_Int32 nCount = seqDescripts.getLength(); + uno::Sequence< REFERENCE< XDISPATCH > > lDispatcher( nCount ); + + for( sal_Int32 i=0; i<nCount; ++i ) + { + lDispatcher[i] = queryDispatch( seqDescripts[i].FeatureURL , + seqDescripts[i].FrameName , + seqDescripts[i].SearchFlags ); + } + + return lDispatcher; +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XControllerBorder +//________________________________________________________________________________________________________ + +frame::BorderWidths SAL_CALL SfxBaseController::getBorder() + throw ( uno::RuntimeException ) +{ + frame::BorderWidths aResult; + + SolarMutexGuard aGuard; + if ( m_pData->m_pViewShell ) + { + SvBorder aBorder = m_pData->m_pViewShell->GetBorderPixel(); + aResult.Left = aBorder.Left(); + aResult.Top = aBorder.Top(); + aResult.Right = aBorder.Right(); + aResult.Bottom = aBorder.Bottom(); + } + + return aResult; +} + +void SAL_CALL SfxBaseController::addBorderResizeListener( const uno::Reference< frame::XBorderResizeListener >& xListener ) + throw ( uno::RuntimeException ) +{ + m_pData->m_aListenerContainer.addInterface( ::getCppuType((const uno::Reference< frame::XBorderResizeListener >*)0), + xListener ); +} + +void SAL_CALL SfxBaseController::removeBorderResizeListener( const uno::Reference< frame::XBorderResizeListener >& xListener ) + throw ( uno::RuntimeException ) +{ + m_pData->m_aListenerContainer.removeInterface( ::getCppuType((const uno::Reference< frame::XBorderResizeListener >*)0), + xListener ); +} + +awt::Rectangle SAL_CALL SfxBaseController::queryBorderedArea( const awt::Rectangle& aPreliminaryRectangle ) + throw ( uno::RuntimeException ) +{ + SolarMutexGuard aGuard; + if ( m_pData->m_pViewShell ) + { + Rectangle aTmpRect = VCLRectangle( aPreliminaryRectangle ); + m_pData->m_pViewShell->QueryObjAreaPixel( aTmpRect ); + return AWTRectangle( aTmpRect ); + } + + return aPreliminaryRectangle; +} + +void SfxBaseController::BorderWidthsChanged_Impl() +{ + ::cppu::OInterfaceContainerHelper* pContainer = m_pData->m_aListenerContainer.getContainer( + ::getCppuType( ( const uno::Reference< frame::XBorderResizeListener >*) NULL ) ); + if ( pContainer ) + { + frame::BorderWidths aBWidths = getBorder(); + uno::Reference< uno::XInterface > xThis( static_cast< ::cppu::OWeakObject* >(this), uno::UNO_QUERY ); + + ::cppu::OInterfaceIteratorHelper pIterator(*pContainer); + while (pIterator.hasMoreElements()) + { + try + { + ((frame::XBorderResizeListener*)pIterator.next())->borderWidthsChanged( xThis, aBWidths ); + } + catch( uno::RuntimeException& ) + { + pIterator.remove(); + } + } + } +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XComponent +//________________________________________________________________________________________________________ + +void SAL_CALL SfxBaseController::dispose() throw( ::com::sun::star::uno::RuntimeException ) +{ + SolarMutexGuard aGuard; + Reference< XController > xTmp( this ); + m_pData->m_bDisposing = sal_True ; + + EVENTOBJECT aEventObject; + aEventObject.Source = *this ; + m_pData->m_aListenerContainer.disposeAndClear( aEventObject ) ; + + if ( m_pData->m_pController && m_pData->m_pController->getFrame().is() ) + m_pData->m_pController->getFrame()->removeFrameActionListener( m_pData->m_xListener ) ; + + if ( m_pData->m_pViewShell ) + { + SfxViewFrame* pFrame = m_pData->m_pViewShell->GetViewFrame() ; + if ( pFrame && pFrame->GetViewShell() == m_pData->m_pViewShell ) + pFrame->GetFrame().SetIsClosing_Impl(); + m_pData->m_pViewShell->DiscardClients_Impl(); + m_pData->m_pViewShell->pImp->m_bControllerSet = false; + + if ( pFrame ) + { + EVENTOBJECT aObject; + aObject.Source = *this ; + + SfxObjectShell* pDoc = pFrame->GetObjectShell() ; + SfxViewFrame *pView = SfxViewFrame::GetFirst(pDoc); + while( pView ) + { + // if there is another ViewFrame or currently the ViewShell in my ViewFrame is switched (PagePreview) + if ( pView != pFrame || pView->GetViewShell() != m_pData->m_pViewShell ) + break; + pView = SfxViewFrame::GetNext( *pView, pDoc ); + } + + SFX_APP()->NotifyEvent( SfxViewEventHint(SFX_EVENT_CLOSEVIEW, GlobalEventConfig::GetEventName( STR_EVENT_CLOSEVIEW ), pDoc, uno::Reference< frame::XController2 >( this ) ) ); + if ( !pView ) + SFX_APP()->NotifyEvent( SfxEventHint(SFX_EVENT_CLOSEDOC, GlobalEventConfig::GetEventName( STR_EVENT_CLOSEDOC ), pDoc) ); + + REFERENCE< XMODEL > xModel = pDoc->GetModel(); + REFERENCE < ::com::sun::star::util::XCloseable > xCloseable( xModel, com::sun::star::uno::UNO_QUERY ); + if ( xModel.is() ) + { + xModel->disconnectController( this ); + if ( xCloseable.is() ) + xCloseable->removeCloseListener( m_pData->m_xCloseListener ); + } + + REFERENCE < XFRAME > aXFrame; + attachFrame( aXFrame ); + + m_pData->m_xListener->disposing( aObject ); + SfxViewShell *pShell = m_pData->m_pViewShell; + m_pData->m_pViewShell = NULL; + if ( pFrame->GetViewShell() == pShell ) + { + // Enter registrations only allowed if we are the owner! + if ( pFrame->GetFrame().OwnsBindings_Impl() ) + pFrame->GetBindings().ENTERREGISTRATIONS(); + pFrame->GetFrame().SetFrameInterface_Impl( aXFrame ); + pFrame->GetFrame().DoClose_Impl(); + } + } + } +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XComponent +//________________________________________________________________________________________________________ + +void SAL_CALL SfxBaseController::addEventListener( const REFERENCE< XEVENTLISTENER >& aListener ) throw( ::com::sun::star::uno::RuntimeException ) +{ + m_pData->m_aListenerContainer.addInterface( ::getCppuType((const REFERENCE< XEVENTLISTENER >*)0), aListener ); +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XComponent +//________________________________________________________________________________________________________ + +void SAL_CALL SfxBaseController::removeEventListener( const REFERENCE< XEVENTLISTENER >& aListener ) throw( ::com::sun::star::uno::RuntimeException ) +{ + m_pData->m_aListenerContainer.removeInterface( ::getCppuType((const REFERENCE< XEVENTLISTENER >*)0), aListener ); +} + +void SfxBaseController::ReleaseShell_Impl() +{ + SolarMutexGuard aGuard; + if ( m_pData->m_pViewShell ) + { + SfxObjectShell* pDoc = m_pData->m_pViewShell->GetObjectShell() ; + REFERENCE< XMODEL > xModel = pDoc->GetModel(); + REFERENCE < ::com::sun::star::util::XCloseable > xCloseable( xModel, com::sun::star::uno::UNO_QUERY ); + if ( xModel.is() ) + { + xModel->disconnectController( this ); + if ( xCloseable.is() ) + xCloseable->removeCloseListener( m_pData->m_xCloseListener ); + } + m_pData->m_pViewShell = 0; + + REFERENCE < XFRAME > aXFrame; + attachFrame( aXFrame ); + } +} + +SfxViewShell* SfxBaseController::GetViewShell_Impl() const +{ + return m_pData->m_pViewShell; +} + +::com::sun::star::uno::Reference< ::com::sun::star::task::XStatusIndicator > SAL_CALL SfxBaseController::getStatusIndicator( ) throw (::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if ( m_pData->m_pViewShell && !m_pData->m_xIndicator.is() ) + m_pData->m_xIndicator = new SfxStatusIndicator( this, m_pData->m_pViewShell->GetViewFrame()->GetFrame().GetWorkWindow_Impl() ); + return m_pData->m_xIndicator; +} + +void SAL_CALL SfxBaseController::registerContextMenuInterceptor( const REFERENCE< XCONTEXTMENUINTERCEPTOR >& xInterceptor ) throw( RUNTIMEEXCEPTION ) + +{ + m_pData->m_aInterceptorContainer.addInterface( xInterceptor ); + + SolarMutexGuard aGuard; + if ( m_pData->m_pViewShell ) + m_pData->m_pViewShell->AddContextMenuInterceptor_Impl( xInterceptor ); +} + +void SAL_CALL SfxBaseController::releaseContextMenuInterceptor( const REFERENCE< XCONTEXTMENUINTERCEPTOR >& xInterceptor ) throw( RUNTIMEEXCEPTION ) + +{ + m_pData->m_aInterceptorContainer.removeInterface( xInterceptor ); + + SolarMutexGuard aGuard; + if ( m_pData->m_pViewShell ) + m_pData->m_pViewShell->RemoveContextMenuInterceptor_Impl( xInterceptor ); +} + +void SAL_CALL SfxBaseController::addKeyHandler( const ::com::sun::star::uno::Reference< XKEYHANDLER >& xHandler ) throw (::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard aGuard; + m_pData->m_aUserInputInterception.addKeyHandler( xHandler ); +} + +void SAL_CALL SfxBaseController::removeKeyHandler( const ::com::sun::star::uno::Reference< XKEYHANDLER >& xHandler ) throw (::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard aGuard; + m_pData->m_aUserInputInterception.removeKeyHandler( xHandler ); +} + +void SAL_CALL SfxBaseController::addMouseClickHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XMouseClickHandler >& xHandler ) throw (::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard aGuard; + m_pData->m_aUserInputInterception.addMouseClickHandler( xHandler ); +} + +void SAL_CALL SfxBaseController::removeMouseClickHandler( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XMouseClickHandler >& xHandler ) throw (::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard aGuard; + m_pData->m_aUserInputInterception.removeMouseClickHandler( xHandler ); +} + +::com::sun::star::uno::Sequence< sal_Int16 > SAL_CALL SfxBaseController::getSupportedCommandGroups() +throw (::com::sun::star::uno::RuntimeException) +{ + SolarMutexGuard aGuard; + + std::list< sal_Int16 > aGroupList; + SfxViewFrame* pViewFrame( m_pData->m_pViewShell->GetFrame() ); + SfxSlotPool* pPool = &SfxSlotPool::GetSlotPool( pViewFrame ); + + SfxSlotPool* pSlotPool = pPool ? pPool : &SFX_SLOTPOOL(); + const sal_uIntPtr nMode( SFX_SLOT_TOOLBOXCONFIG|SFX_SLOT_ACCELCONFIG|SFX_SLOT_MENUCONFIG ); + + // Select Group ( Group 0 is internal ) + for ( sal_uInt16 i=0; i<pSlotPool->GetGroupCount(); i++ ) + { + String aName = pSlotPool->SeekGroup( i ); + const SfxSlot* pSfxSlot = pSlotPool->FirstSlot(); + while ( pSfxSlot ) + { + if ( pSfxSlot->GetMode() & nMode ) + { + sal_Int16 nCommandGroup = MapGroupIDToCommandGroup( pSfxSlot->GetGroupId() ); + aGroupList.push_back( nCommandGroup ); + break; + } + pSfxSlot = pSlotPool->NextSlot(); + } + } + + ::com::sun::star::uno::Sequence< sal_Int16 > aSeq = + comphelper::containerToSequence< sal_Int16 >( aGroupList ); + return aSeq; +} + +::com::sun::star::uno::Sequence< ::com::sun::star::frame::DispatchInformation > SAL_CALL SfxBaseController::getConfigurableDispatchInformation( sal_Int16 nCmdGroup ) +throw (::com::sun::star::uno::RuntimeException) +{ + std::list< ::com::sun::star::frame::DispatchInformation > aCmdList; + + SolarMutexGuard aGuard; + if ( m_pData->m_pViewShell ) + { + const sal_uIntPtr nMode( SFX_SLOT_TOOLBOXCONFIG|SFX_SLOT_ACCELCONFIG|SFX_SLOT_MENUCONFIG ); + + SfxViewFrame* pViewFrame( m_pData->m_pViewShell->GetFrame() ); + SfxSlotPool* pPool( &SfxSlotPool::GetSlotPool( pViewFrame )); + rtl::OUString aCmdPrefix( RTL_CONSTASCII_USTRINGPARAM( ".uno:" )); + + SfxSlotPool* pSlotPool = pPool ? pPool : &SFX_SLOTPOOL(); + for ( sal_uInt16 i=0; i<pSlotPool->GetGroupCount(); i++ ) + { + String aName = pSlotPool->SeekGroup( i ); + const SfxSlot* pSfxSlot = pSlotPool->FirstSlot(); + if ( pSfxSlot ) + { + sal_Int16 nCommandGroup = MapGroupIDToCommandGroup( pSfxSlot->GetGroupId() ); + if ( nCommandGroup == nCmdGroup ) + { + while ( pSfxSlot ) + { + if ( pSfxSlot->GetMode() & nMode ) + { + ::com::sun::star::frame::DispatchInformation aCmdInfo; + ::rtl::OUStringBuffer aBuf( aCmdPrefix ); + aBuf.appendAscii( pSfxSlot->GetUnoName() ); + aCmdInfo.Command = aBuf.makeStringAndClear(); + aCmdInfo.GroupId = nCommandGroup; + aCmdList.push_back( aCmdInfo ); + } + pSfxSlot = pSlotPool->NextSlot(); + } + } + } + } + } + + ::com::sun::star::uno::Sequence< ::com::sun::star::frame::DispatchInformation > aSeq = + comphelper::containerToSequence< ::com::sun::star::frame::DispatchInformation, std::list< ::com::sun::star::frame::DispatchInformation > >( aCmdList ); + + return aSeq; +} + +sal_Bool SfxBaseController::HandleEvent_Impl( NotifyEvent& rEvent ) +{ + return m_pData->m_aUserInputInterception.handleNotifyEvent( rEvent ); +} + +sal_Bool SfxBaseController::HasKeyListeners_Impl() +{ + return m_pData->m_aUserInputInterception.hasKeyHandlers(); +} + +sal_Bool SfxBaseController::HasMouseClickListeners_Impl() +{ + return m_pData->m_aUserInputInterception.hasMouseClickListeners(); +} + +void SfxBaseController::ConnectSfxFrame_Impl( const ConnectSfxFrame i_eConnect ) +{ + ENSURE_OR_THROW( m_pData->m_pViewShell, "not to be called without a view shell" ); + SfxViewFrame* pViewFrame = m_pData->m_pViewShell->GetFrame(); + ENSURE_OR_THROW( pViewFrame, "a view shell without a view frame is pretty pathological" ); + + const bool bConnect = ( i_eConnect != E_DISCONNECT ); + + // disable window and dispatcher + pViewFrame->Enable( bConnect ); + pViewFrame->GetDispatcher()->Lock( !bConnect ); + + if ( bConnect ) + { + if ( i_eConnect == E_CONNECT ) + { + if ( ( m_pData->m_pViewShell->GetObjectShell() != NULL ) + && ( m_pData->m_pViewShell->GetObjectShell()->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED ) + ) + { + SfxViewFrame* pViewFrm = m_pData->m_pViewShell->GetViewFrame(); + if ( !pViewFrm->GetFrame().IsInPlace() ) + { + // for outplace embedded objects, we want the layout manager to keep the content window + // size constant, if possible + try + { + uno::Reference< beans::XPropertySet > xFrameProps( m_pData->m_xFrame, uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySet > xLayouterProps( + xFrameProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ) ) ), uno::UNO_QUERY_THROW ); + xLayouterProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PreserveContentSize" ) ), uno::makeAny( sal_True ) ); + } + catch( const uno::Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + } + } + + // upon DISCONNECT, we did *not* pop the shells from the stack (this is done elsewhere), so upon + // RECONNECT, we're not allowed to push them + if ( i_eConnect != E_RECONNECT ) + { + pViewFrame->GetDispatcher()->Push( *m_pData->m_pViewShell ); + if ( m_pData->m_pViewShell->GetSubShell() ) + pViewFrame->GetDispatcher()->Push( *m_pData->m_pViewShell->GetSubShell() ); + m_pData->m_pViewShell->PushSubShells_Impl(); + pViewFrame->GetDispatcher()->Flush(); + } + + Window* pEditWin = m_pData->m_pViewShell->GetWindow(); + if ( pEditWin && m_pData->m_pViewShell->IsShowView_Impl() ) + pEditWin->Show(); + + if ( SfxViewFrame::Current() == pViewFrame ) + pViewFrame->GetDispatcher()->Update_Impl( sal_True ); + + Window* pFrameWin = &pViewFrame->GetWindow(); + if ( pFrameWin != &pViewFrame->GetFrame().GetWindow() ) + pFrameWin->Show(); + + if ( i_eConnect == E_CONNECT ) + { + ::comphelper::NamedValueCollection aDocumentArgs( getModel()->getArgs() ); + + const sal_Int16 nPluginMode = aDocumentArgs.getOrDefault( "PluginMode", sal_Int16( 0 ) ); + const bool bHasPluginMode = ( nPluginMode != 0 ); + + SfxFrame& rFrame = pViewFrame->GetFrame(); + SfxObjectShell& rDoc = *m_pData->m_pViewShell->GetObjectShell(); + if ( !rFrame.IsMarkedHidden_Impl() ) + { + if ( rDoc.IsHelpDocument() || ( nPluginMode == 2 ) ) + pViewFrame->GetDispatcher()->HideUI( sal_True ); + else + pViewFrame->GetDispatcher()->HideUI( sal_False ); + + if ( rFrame.IsInPlace() ) + pViewFrame->LockAdjustPosSizePixel(); + + if ( nPluginMode == 3 ) + rFrame.GetWorkWindow_Impl()->SetInternalDockingAllowed( sal_False ); + + if ( !rFrame.IsInPlace() ) + pViewFrame->GetDispatcher()->Update_Impl(); + pViewFrame->Show(); + rFrame.GetWindow().Show(); + if ( !rFrame.IsInPlace() || ( nPluginMode == 3 ) ) + pViewFrame->MakeActive_Impl( rFrame.GetFrameInterface()->isActive() ); + + if ( rFrame.IsInPlace() ) + { + pViewFrame->UnlockAdjustPosSizePixel(); + // force resize for OLE server to fix layout problems of writer and math + // see i53651 + if ( nPluginMode == 3 ) + pViewFrame->Resize( sal_True ); + } + } + else + { + DBG_ASSERT( !rFrame.IsInPlace() && !bHasPluginMode, "Special modes not compatible with hidden mode!" ); + rFrame.GetWindow().Show(); + } + + // UpdateTitle now, hidden TopFrames have otherwise no Name! + pViewFrame->UpdateTitle(); + + if ( !rFrame.IsInPlace() ) + pViewFrame->Resize( sal_True ); + + // if there's a JumpMark given, then, well, jump to it + ::comphelper::NamedValueCollection aViewArgs( getCreationArguments() ); + const ::rtl::OUString sJumpMark = aViewArgs.getOrDefault( "JumpMark", ::rtl::OUString() ); + const bool bHasJumpMark = ( sJumpMark.getLength() > 0 ); + OSL_ENSURE( ( !m_pData->m_pViewShell->GetObjectShell()->IsLoading() ) + || ( !sJumpMark.getLength() ), + "SfxBaseController::ConnectSfxFrame_Impl: so this code wasn't dead?" ); + // Before CWS autorecovery, there was code which postponed jumping to the Mark to a later time + // (SfxObjectShell::PositionView_Impl), but it seems this branch was never used, since this method + // here is never called before the load process finished. At least not with a non-empty jump mark + if ( sJumpMark.getLength() ) + m_pData->m_pViewShell->JumpToMark( sJumpMark ); + + // if no plugin mode and no jump mark was supplied, check whether the document itself can provide view data, and + // if so, forward it to the view/shell. + if ( !bHasPluginMode && !bHasJumpMark ) + { + // Note that this might not be the ideal place here. Restoring view data should, IMO, be the + // responsibility of the loader, not an implementation detail burried here deep within the controller's + // implementation. + // What I think should be done to replace the below code: + // - change SfxBaseController::restoreViewData to also accept a PropertyValue[] (it currently accepts + // a string only), and forward it to its ViewShell's ReadUserDataSequence + // - change the frame loader so that when a new document is loaded (as opposed to an existing + // document being loaded into a new frame), the model's view data is examine the very same + // way as below, and the proper view data is set via XController::restoreViewData + // - extend SfxViewFrame::SwitchToViewShell_Impl. Currently, it cares for the case where a non-PrintPreview + // view is exchanged, and sets the old view's data at the model. It should also care for the other + // way, were the PrintPreview view is left: in this case, the new view should also be initialized + // with the model's view data + try + { + Reference< XViewDataSupplier > xViewDataSupplier( getModel(), UNO_QUERY_THROW ); + Reference< XIndexAccess > xViewData( xViewDataSupplier->getViewData() ); + + // find the view data item whose ViewId matches the ID of the view we're just connecting to + const SfxObjectFactory& rDocFactory( rDoc.GetFactory() ); + const sal_Int32 nCount = xViewData.is() ? xViewData->getCount() : 0; + sal_Int32 nViewDataIndex = 0; + for ( sal_Int32 i=0; i<nCount; ++i ) + { + const ::comphelper::NamedValueCollection aViewData( xViewData->getByIndex(i) ); + ::rtl::OUString sViewId( aViewData.getOrDefault( "ViewId", ::rtl::OUString() ) ); + if ( sViewId.getLength() == 0 ) + continue; + + const SfxViewFactory* pViewFactory = rDocFactory.GetViewFactoryByViewName( sViewId ); + if ( pViewFactory == NULL ) + continue; + + if ( pViewFactory->GetOrdinal() == pViewFrame->GetCurViewId() ) + { + nViewDataIndex = i; + break; + } + } + if ( nViewDataIndex < nCount ) + { + Sequence< PropertyValue > aViewData; + OSL_VERIFY( xViewData->getByIndex( nViewDataIndex ) >>= aViewData ); + if ( aViewData.getLength() > 0 ) + m_pData->m_pViewShell->ReadUserDataSequence( aViewData, sal_True ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + } + } + + // invalidate slot corresponding to the view shell + const sal_uInt16 nViewNo = m_pData->m_pViewShell->GetObjectShell()->GetFactory().GetViewNo_Impl( pViewFrame->GetCurViewId(), USHRT_MAX ); + DBG_ASSERT( nViewNo != USHRT_MAX, "view shell id not found" ); + if ( nViewNo != USHRT_MAX ) + pViewFrame->GetBindings().Invalidate( nViewNo + SID_VIEWSHELL0 ); +} + +//============================================================================= +css::uno::Reference< css::frame::XTitle > SfxBaseController::impl_getTitleHelper () +{ + SolarMutexGuard aGuard; + + if ( ! m_pData->m_xTitleHelper.is ()) + { + css::uno::Reference< css::frame::XModel > xModel = getModel (); + css::uno::Reference< css::frame::XUntitledNumbers > xUntitledProvider(xModel , css::uno::UNO_QUERY ); + css::uno::Reference< css::frame::XController > xThis (static_cast< css::frame::XController* >(this), css::uno::UNO_QUERY_THROW); + + ::framework::TitleHelper* pHelper = new ::framework::TitleHelper(::comphelper::getProcessServiceFactory()); + m_pData->m_xTitleHelper = css::uno::Reference< css::frame::XTitle >(static_cast< ::cppu::OWeakObject* >(pHelper), css::uno::UNO_QUERY_THROW); + + pHelper->setOwner (xThis ); + pHelper->connectWithUntitledNumbers (xUntitledProvider); + } + + return m_pData->m_xTitleHelper; +} + +//============================================================================= +// css::frame::XTitle +::rtl::OUString SAL_CALL SfxBaseController::getTitle() + throw (css::uno::RuntimeException) +{ + return impl_getTitleHelper()->getTitle (); +} + +//============================================================================= +// css::frame::XTitle +void SAL_CALL SfxBaseController::setTitle(const ::rtl::OUString& sTitle) + throw (css::uno::RuntimeException) +{ + impl_getTitleHelper()->setTitle (sTitle); +} + +//============================================================================= +// css::frame::XTitleChangeBroadcaster +void SAL_CALL SfxBaseController::addTitleChangeListener(const css::uno::Reference< css::frame::XTitleChangeListener >& xListener) + throw (css::uno::RuntimeException) +{ + css::uno::Reference< css::frame::XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper(), css::uno::UNO_QUERY); + if (xBroadcaster.is ()) + xBroadcaster->addTitleChangeListener (xListener); +} + +//============================================================================= +// css::frame::XTitleChangeBroadcaster +void SAL_CALL SfxBaseController::removeTitleChangeListener(const css::uno::Reference< css::frame::XTitleChangeListener >& xListener) + throw (css::uno::RuntimeException) +{ + css::uno::Reference< css::frame::XTitleChangeBroadcaster > xBroadcaster(impl_getTitleHelper(), css::uno::UNO_QUERY); + if (xBroadcaster.is ()) + xBroadcaster->removeTitleChangeListener (xListener); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/userinputinterception.cxx b/sfx2/source/view/userinputinterception.cxx new file mode 100644 index 000000000000..19c6ff50e5c9 --- /dev/null +++ b/sfx2/source/view/userinputinterception.cxx @@ -0,0 +1,281 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ***********************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#include "sfx2/userinputinterception.hxx" + +/** === begin UNO includes === **/ +#include <com/sun/star/awt/MouseButton.hpp> +#include <com/sun/star/awt/KeyModifier.hpp> +/** === end UNO includes === **/ + +#include <cppuhelper/interfacecontainer.hxx> +#include <cppuhelper/weak.hxx> +#include <vcl/event.hxx> +#include <vcl/window.hxx> + +//........................................................................ +namespace sfx2 +{ +//........................................................................ + + /** === begin UNO using === **/ + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + using ::com::sun::star::uno::UNO_QUERY; + using ::com::sun::star::uno::UNO_QUERY_THROW; + using ::com::sun::star::uno::UNO_SET_THROW; + using ::com::sun::star::uno::Exception; + using ::com::sun::star::uno::RuntimeException; + using ::com::sun::star::uno::Any; + using ::com::sun::star::uno::makeAny; + using ::com::sun::star::awt::MouseEvent; + using ::com::sun::star::awt::KeyEvent; + using ::com::sun::star::awt::InputEvent; + using ::com::sun::star::awt::XKeyHandler; + using ::com::sun::star::awt::XMouseClickHandler; + using ::com::sun::star::lang::DisposedException; + /** === end UNO using === **/ + namespace MouseButton = ::com::sun::star::awt::MouseButton; + namespace KeyModifier = ::com::sun::star::awt::KeyModifier; + + struct UserInputInterception_Data + { + public: + ::cppu::OWeakObject& m_rControllerImpl; + ::cppu::OInterfaceContainerHelper m_aKeyHandlers; + ::cppu::OInterfaceContainerHelper m_aMouseClickHandlers; + + public: + UserInputInterception_Data( ::cppu::OWeakObject& _rControllerImpl, ::osl::Mutex& _rMutex ) + :m_rControllerImpl( _rControllerImpl ) + ,m_aKeyHandlers( _rMutex ) + ,m_aMouseClickHandlers( _rMutex ) + { + } + }; + + namespace + { + template< class VLCEVENT > + void lcl_initModifiers( InputEvent& _rEvent, const VLCEVENT& _rVclEvent ) + { + _rEvent.Modifiers = 0; + + if ( _rVclEvent.IsShift() ) + _rEvent.Modifiers |= KeyModifier::SHIFT; + if ( _rVclEvent.IsMod1() ) + _rEvent.Modifiers |= KeyModifier::MOD1; + if ( _rVclEvent.IsMod2() ) + _rEvent.Modifiers |= KeyModifier::MOD2; + if ( _rVclEvent.IsMod3() ) + _rEvent.Modifiers |= KeyModifier::MOD3; + } + + void lcl_initKeyEvent( KeyEvent& rEvent, const ::KeyEvent& rEvt ) + { + lcl_initModifiers( rEvent, rEvt.GetKeyCode() ); + + rEvent.KeyCode = rEvt.GetKeyCode().GetCode(); + rEvent.KeyChar = rEvt.GetCharCode(); + rEvent.KeyFunc = sal::static_int_cast< sal_Int16 >( rEvt.GetKeyCode().GetFunction()); + } + + void lcl_initMouseEvent( MouseEvent& rEvent, const ::MouseEvent& rEvt ) + { + lcl_initModifiers( rEvent, rEvt ); + + rEvent.Buttons = 0; + if ( rEvt.IsLeft() ) + rEvent.Buttons |= MouseButton::LEFT; + if ( rEvt.IsRight() ) + rEvent.Buttons |= MouseButton::RIGHT; + if ( rEvt.IsMiddle() ) + rEvent.Buttons |= MouseButton::MIDDLE; + + rEvent.X = rEvt.GetPosPixel().X(); + rEvent.Y = rEvt.GetPosPixel().Y(); + rEvent.ClickCount = rEvt.GetClicks(); + rEvent.PopupTrigger = sal_False; + } + + } + + //==================================================================== + //= UserInputInterception + //==================================================================== + //-------------------------------------------------------------------- + UserInputInterception::UserInputInterception( ::cppu::OWeakObject& _rControllerImpl, ::osl::Mutex& _rMutex ) + :m_pData( new UserInputInterception_Data( _rControllerImpl, _rMutex ) ) + { + } + + //-------------------------------------------------------------------- + UserInputInterception::~UserInputInterception() + { + } + + //-------------------------------------------------------------------- + void UserInputInterception::addKeyHandler( const Reference< XKeyHandler >& _rxHandler ) throw (RuntimeException) + { + if ( _rxHandler.is() ) + m_pData->m_aKeyHandlers.addInterface( _rxHandler ); + } + + //-------------------------------------------------------------------- + void UserInputInterception::removeKeyHandler( const Reference< XKeyHandler >& _rxHandler ) throw (RuntimeException) + { + m_pData->m_aKeyHandlers.removeInterface( _rxHandler ); + } + + //-------------------------------------------------------------------- + void UserInputInterception::addMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler ) throw (RuntimeException) + { + if ( _rxHandler.is() ) + m_pData->m_aMouseClickHandlers.addInterface( _rxHandler ); + } + + //-------------------------------------------------------------------- + void UserInputInterception::removeMouseClickHandler( const Reference< XMouseClickHandler >& _rxHandler ) throw (RuntimeException) + { + m_pData->m_aMouseClickHandlers.removeInterface( _rxHandler ); + } + + //-------------------------------------------------------------------- + bool UserInputInterception::hasKeyHandlers() const + { + return m_pData->m_aKeyHandlers.getLength() > 0; + } + + //-------------------------------------------------------------------- + bool UserInputInterception::hasMouseClickListeners() const + { + return m_pData->m_aMouseClickHandlers.getLength() > 0; + } + + //-------------------------------------------------------------------- + bool UserInputInterception::handleNotifyEvent( const NotifyEvent& _rEvent ) + { + Reference < XInterface > xHoldAlive( m_pData->m_rControllerImpl ); + + sal_uInt16 nType = _rEvent.GetType(); + bool bHandled = false; + + switch ( nType ) + { + case EVENT_KEYINPUT: + case EVENT_KEYUP: + { + KeyEvent aEvent; + lcl_initKeyEvent( aEvent, *_rEvent.GetKeyEvent() ); + if ( _rEvent.GetWindow() ) + aEvent.Source = _rEvent.GetWindow()->GetComponentInterface(); + + ::cppu::OInterfaceIteratorHelper aIterator( m_pData->m_aKeyHandlers ); + while ( aIterator.hasMoreElements() ) + { + Reference< XKeyHandler > xHandler( static_cast< XKeyHandler* >( aIterator.next() ) ); + if ( !xHandler.is() ) + continue; + + try + { + if ( nType == EVENT_KEYINPUT ) + bHandled = xHandler->keyPressed( aEvent ); + else + bHandled = xHandler->keyReleased( aEvent ); + } + catch( const DisposedException& e ) + { + if ( e.Context == xHandler ) + aIterator.remove(); + } + catch( const RuntimeException& ) + { + throw; + } + catch( const Exception& ) + { + } + } + } + break; + + case EVENT_MOUSEBUTTONDOWN: + case EVENT_MOUSEBUTTONUP: + { + MouseEvent aEvent; + lcl_initMouseEvent( aEvent, *_rEvent.GetMouseEvent() ); + if ( _rEvent.GetWindow() ) + aEvent.Source = _rEvent.GetWindow()->GetComponentInterface(); + + ::cppu::OInterfaceIteratorHelper aIterator( m_pData->m_aMouseClickHandlers ); + while ( aIterator.hasMoreElements() ) + { + Reference< XMouseClickHandler > xHandler( static_cast< XMouseClickHandler* >( aIterator.next() ) ); + if ( !xHandler.is() ) + continue; + + try + { + if ( nType == EVENT_MOUSEBUTTONDOWN ) + bHandled = xHandler->mousePressed( aEvent ); + else + bHandled = xHandler->mouseReleased( aEvent ); + } + catch( const DisposedException& e ) + { + if ( e.Context == xHandler ) + aIterator.remove(); + } + catch( const RuntimeException& ) + { + throw; + } + catch( const Exception& ) + { + } + } + } + break; + + default: + OSL_FAIL( "UserInputInterception::handleNotifyEvent: illegal event type!" ); + break; + } + + return bHandled; + } + +//........................................................................ +} // namespace sfx2 +//........................................................................ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/view.hrc b/sfx2/source/view/view.hrc new file mode 100755 index 000000000000..3dce1ec795bb --- /dev/null +++ b/sfx2/source/view/view.hrc @@ -0,0 +1,120 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifndef _SFX_VIEW_HRC +#define _SFX_VIEW_HRC + +#include <sfx2/sfx.hrc> + +// #defines ***************************************************************** + +#define STR_NODEFPRINTER (RID_SFX_VIEW_START+ 0) +#define STR_PRINTER_NOTAVAIL (RID_SFX_VIEW_START+ 1) + + +#define STR_PRINT_OPTIONS (RID_SFX_VIEW_START+ 6) +#define STR_PRINT_OPTIONS_TITLE (RID_SFX_VIEW_START+ 7) +#define STR_ERROR_PRINTER_BUSY (RID_SFX_VIEW_START+ 8) +#define STR_NOSTARTPRINTER (RID_SFX_VIEW_START+ 9) +#define STR_PRINTING (RID_SFX_VIEW_START+10) + +#define DLG_PRINTMONITOR (RID_SFX_VIEW_START) +#define FT_DOCNAME 1 +#define FT_PRINTING 2 +#define FT_PRINTER 3 +#define FT_PRINTINFO 4 +#define PB_CANCELPRNMON 5 +#define STR_FT_PREPARATION 6 +#define STR_PAGE (RID_SFX_VIEW_START+20) +#define STR_ERROR_PRINT (RID_SFX_VIEW_START+21) +#define STR_PRINT_NEWORI (RID_SFX_VIEW_START+22) +#define STR_PRINT_NEWSIZE (RID_SFX_VIEW_START+23) +#define STR_PRINT_NEWORISIZE (RID_SFX_VIEW_START+24) + +#define STR_PREVIEW_DOCINFO (RID_SFX_VIEW_START+25) +#define STR_PREVIEW_NODOCINFO (RID_SFX_VIEW_START+26) + +#define MSG_ERROR_SEND_MAIL (RID_SFX_VIEW_START+31) + +#define STR_ERROR_SAVE_TEMPLATE (RID_SFX_VIEW_START+33) + +#define MSG_QUERY_OPENASTEMPLATE (RID_SFX_VIEW_START+41) +#define MSG_CANT_CLOSE (RID_SFX_VIEW_START+42) +#define MSG_ERROR_NO_WEBBROWSER_FOUND (RID_SFX_VIEW_START+43) +#define TP_FRAMEPROPERTIES (RID_SFX_VIEW_START+44) + +#define FT_FRAMENAME 3 +#define ED_FRAMENAME 4 +#define FT_URL 5 +#define ED_URL 6 +#define BT_FILEOPEN 7 +#define NM_MARGINHEIGHT 8 +#define FT_MARGINHEIGHT 9 +#define NM_MARGINWIDTH 10 +#define FT_MARGINWIDTH 11 +#define GB_MARGIN 12 +#define RB_SCROLLINGON 13 +#define RB_SCROLLINGOFF 14 +#define RB_SCROLLINGAUTO 15 +#define GB_SCROLLING 16 +#define GB_BORDER 17 +#define RB_FRMBORDER_ON 18 +#define RB_FRMBORDER_INHERIT 19 +#define RB_FRMBORDER_OFF 20 +#define CB_MARGINWIDTHDEFAULT 21 +#define CB_MARGINHEIGHTDEFAULT 22 + +#define GB_WIDTH 23 +#define GB_HEIGHT 24 +#define RB_PIXELWIDTH 25 +#define RB_PERCENTWIDTH 26 +#define RB_RELATIVEWIDTH 27 +#define RB_PIXELHEIGHT 28 +#define RB_PERCENTHEIGHT 29 +#define RB_RELATIVEHEIGHT 30 +#define FT_WIDTHCOMMENT 31 +#define FT_HEIGHTCOMMENT 32 +#define FT_WIDTH 33 +#define NM_WIDTH 34 +#define CB_WIDTHFIXED 35 +#define CB_HEIGHTFIXED 36 +#define FT_HEIGHT 37 +#define NM_HEIGHT 38 + +#define FT_FRAMESPACING 39 +#define NM_FRAMESPACING 40 +#define CB_FRAMESPACING_INHERIT 41 +#define FT_FRAMESPACINGCOLOR 42 +#define ED_FRAMESPACINGCOLOR 43 +#define CB_FRAMESPACINGCOLOR_INHERIT 44 +#define GB_FRAMESET 45 +#define FL_SEP_LEFT 46 +#define FL_SEP_RIGHT 47 + +#define STR_FRAME_FILEDLG (RID_SFX_VIEW_START+46) + +#endif + diff --git a/sfx2/source/view/view.src b/sfx2/source/view/view.src new file mode 100644 index 000000000000..b4c09a0677ed --- /dev/null +++ b/sfx2/source/view/view.src @@ -0,0 +1,190 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + // include --------------------------------------------------------------- +#include "view.hrc" +#include <sfx2/sfx.hrc> +#include "helpid.hrc" +#include "sfxlocal.hrc" + + // Strings --------------------------------------------------------------- +String STR_NODEFPRINTER +{ + Text [ en-US ] = "No default printer found.\nPlease choose a printer and try again." ; +}; +String STR_NOSTARTPRINTER +{ + Text [ en-US ] = "Could not start printer.\nPlease check your printer configuration." ; +}; +String STR_PRINTER_NOTAVAIL +{ + Text [ en-US ] = "This document has been formatted for the printer $1. The specified printer is not available. \nDo you want to use the standard printer $2 ?" ; +}; +String STR_PRINT_OPTIONS +{ + Text [ en-US ] = "Options..." ; +}; +String STR_PRINT_OPTIONS_TITLE +{ + Text [ en-US ] = "Printer Options" ; +}; +String STR_ERROR_PRINTER_BUSY +{ + Text [ en-US ] = "Printer busy" ; +}; +String STR_ERROR_PRINT +{ + Text [ en-US ] = "Error while printing" ; +}; +String STR_PRINTING +{ + Text [ en-US ] = "Printing" ; +}; +String STR_PAGE +{ + Text [ en-US ] = "Page " ; +}; +String STR_ERROR_SAVE_TEMPLATE +{ + Text [ en-US ] = "Error saving template " ; +}; +String STR_READONLY +{ + Text [ en-US ] = " (read-only)" ; +}; +String STR_PRINT_NEWORI +{ + Text [ en-US ] = "The page size and orientation have been modified.\nWould you like to save the new settings in the\nactive document?" ; +}; +String STR_PRINT_NEWSIZE +{ + Text [ en-US ] = "The page size has been modified.\nShould the new settings be saved\nin the active document?" ; +}; +String STR_PRINT_NEWORISIZE +{ + Text [ en-US ] = "The page size and orientation have been modified.\nWould you like to save the new settings in the\nactive document?" ; +}; +String STR_PREVIEW_DOCINFO +{ + Text [ en-US ] = "<html><body BGCOLOR=\"#c0c0c0\"><font FACE=\"Arial\"><dl><dt><b>Title:</b><dd>$(TITEL)<dt><b>Subject:</b><dd>$(THEME)<dt><b>Keywords:</b><dd>$(KEYWORDS)<dt><b>Description:</b><dd>$(TEXT)</dl></font></body></html>" ; +}; +String STR_PREVIEW_NODOCINFO +{ + Text [ en-US ] = "<HTML><BODY BGCOLOR=\"#c0c0c0\"><BR><BR><P><FONT FACE=\"Arial\"><B>No document properties found.</B></FONT></P></BODY></HTML>" ; +}; + // ----------------------------------------------------------------------- +InfoBox MSG_CANT_CLOSE +{ + Message [ en-US ] = "The document cannot be closed because a\n print job is being carried out." ; +}; + // DLG_PRINTMONITOR ------------------------------------------------------ + +#define DLG_PRINTMONITOR_TEXT \ + Text [ en-US ] = "Print Monitor" ; \ + +ModelessDialog DLG_PRINTMONITOR +{ + HelpID = HID_PRINTMONITOR ; + OutputSize = TRUE ; + SVLook = TRUE ; + Hide = TRUE ; + Moveable = TRUE; + Size = MAP_APPFONT ( 112 , 81 ) ; + DLG_PRINTMONITOR_TEXT + FixedText FT_DOCNAME + { + Pos = MAP_APPFONT ( 6 , 6 ) ; + Size = MAP_APPFONT ( 100 , 10 ) ; + Center = TRUE ; + }; + FixedText FT_PRINTING + { + Pos = MAP_APPFONT ( 6 , 19 ) ; + Size = MAP_APPFONT ( 100 , 10 ) ; + Center = TRUE ; + Text [ en-US ] = "is being printed on" ; + }; + FixedText FT_PRINTER + { + Pos = MAP_APPFONT ( 6 , 32 ) ; + Size = MAP_APPFONT ( 100 , 10 ) ; + Center = TRUE ; + }; + FixedText FT_PRINTINFO + { + Pos = MAP_APPFONT ( 6 , 45 ) ; + Size = MAP_APPFONT ( 100 , 10 ) ; + Center = TRUE ; + }; + CancelButton PB_CANCELPRNMON + { + Pos = MAP_APPFONT ( 31 , 61 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + }; + String STR_FT_PREPARATION + { + Text [ en-US ] = "is being prepared for printing"; + }; +}; + + // MSG_ERROR_SEND_MAIL --------------------------------------------------- + +InfoBox MSG_ERROR_SEND_MAIL +{ + BUTTONS = WB_OK ; + DEFBUTTON = WB_DEF_OK ; + Message [ en-US ] = "An error occurred in sending the message. Possible errors could be a missing user account or a defective setup.\nPlease check the %PRODUCTNAME settings or your e-mail program settings." ; +}; + + // QueryBoxen ------------------------------------------------------------ +QueryBox MSG_QUERY_OPENASTEMPLATE +{ + Buttons = WB_YES_NO ; + DefButton = WB_DEF_NO ; + Message [ en-US ] = "This document cannot be edited, possibly due to missing access rights. Do you want to edit a copy of the document?" ; +}; +String STR_REPAIREDDOCUMENT +{ + Text [ en-US ] = " (repaired document)" ; +}; + +ErrorBox MSG_ERROR_NO_WEBBROWSER_FOUND +{ + BUTTONS = WB_OK ; + DEFBUTTON = WB_DEF_OK ; + Message[ en-US ] = "%PRODUCTNAME could not find a web browser on your system. Please check your Desktop Preferences or install a web browser (for example, Mozilla) in the default location requested during the browser installation." ; +}; + + + + + + + + + + + diff --git a/sfx2/source/view/viewfac.cxx b/sfx2/source/view/viewfac.cxx new file mode 100644 index 000000000000..16fd68505ad9 --- /dev/null +++ b/sfx2/source/view/viewfac.cxx @@ -0,0 +1,90 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" +// INCLUDE --------------------------------------------------------------- + +#include <sfx2/app.hxx> +#include "sfx2/viewfac.hxx" +#include <rtl/ustrbuf.hxx> + +// STATIC DATA ----------------------------------------------------------- + +DBG_NAME(SfxViewFactory) + +SfxViewShell *SfxViewFactory::CreateInstance(SfxViewFrame *pFrame, SfxViewShell *pOldSh ) +{ + DBG_CHKTHIS(SfxViewFactory, 0); + return (*fnCreate)(pFrame, pOldSh); +} + +void SfxViewFactory::InitFactory() +{ + DBG_CHKTHIS(SfxViewFactory, 0); + (*fnInit)(); +} + +String SfxViewFactory::GetLegacyViewName() const +{ + ::rtl::OUStringBuffer aViewName; + aViewName.appendAscii( "view" ); + aViewName.append( sal_Int32( GetOrdinal() ) ); + return aViewName.makeStringAndClear(); +} + +String SfxViewFactory::GetAPIViewName() const +{ + if ( m_sViewName.Len() > 0 ) + return m_sViewName; + + if ( GetOrdinal() == 0 ) + return String::CreateFromAscii( "Default" ); + + return GetLegacyViewName(); +} + +// CTOR / DTOR ----------------------------------------------------------- + +SfxViewFactory::SfxViewFactory( SfxViewCtor fnC, SfxViewInit fnI, + sal_uInt16 nOrdinal, const sal_Char* asciiViewName ): + fnCreate(fnC), + fnInit(fnI), + nOrd(nOrdinal), + m_sViewName( String::CreateFromAscii( asciiViewName ) ) +{ + DBG_CTOR(SfxViewFactory, 0); +} + +SfxViewFactory::~SfxViewFactory() +{ + DBG_DTOR(SfxViewFactory, 0); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx new file mode 100644 index 000000000000..6895190d0c32 --- /dev/null +++ b/sfx2/source/view/viewfrm.cxx @@ -0,0 +1,3467 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#include <stdio.h> + +#include <sfx2/viewfrm.hxx> +#include <com/sun/star/document/MacroExecMode.hpp> +#include <com/sun/star/frame/XLoadable.hpp> +#include <com/sun/star/frame/XLayoutManager.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> + +#include <toolkit/unohlp.hxx> +#include <vcl/splitwin.hxx> +#include <unotools/moduleoptions.hxx> +#include <svl/intitem.hxx> +#include <svl/visitem.hxx> +#include <svl/stritem.hxx> +#include <svl/eitem.hxx> +#include <svl/slstitm.hxx> +#include <svl/whiter.hxx> +#include <svl/undo.hxx> +#include <vcl/msgbox.hxx> +#include <svtools/sfxecode.hxx> +#include <svtools/miscopt.hxx> +#include <svtools/ehdl.hxx> +#include <tools/diagnose_ex.h> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/frame/XFramesSupplier.hpp> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XFrames.hpp> +#include <com/sun/star/frame/XFramesSupplier.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/frame/XModel2.hpp> +#include <com/sun/star/util/XURLTransformer.hpp> +#include <com/sun/star/util/XCloseable.hpp> +#include <com/sun/star/frame/XDispatchRecorderSupplier.hpp> +#include <com/sun/star/document/MacroExecMode.hpp> +#include <com/sun/star/document/UpdateDocMode.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/uri/XUriReferenceFactory.hpp> +#include <com/sun/star/uri/XVndSunStarScriptUrl.hpp> +#include <com/sun/star/embed/XStorage.hpp> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/document/XViewDataSupplier.hpp> +#include <com/sun/star/container/XIndexContainer.hpp> +#include <rtl/ustrbuf.hxx> + +#include <unotools/localfilehelper.hxx> +#include <unotools/ucbhelper.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/componentcontext.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/configurationhelper.hxx> +#include <comphelper/docpasswordrequest.hxx> +#include <comphelper/docpasswordhelper.hxx> + +#include <com/sun/star/uno/Reference.h> +#include <com/sun/star/ucb/XContent.hpp> + +#include <basic/basmgr.hxx> +#include <basic/sbmod.hxx> +#include <basic/sbmeth.hxx> +#include <basic/sbx.hxx> +#include <comphelper/storagehelper.hxx> +#include <svtools/asynclink.hxx> +#include <svl/sharecontrolfile.hxx> +#include <svtools/svtools.hrc> +#include <svtools/svtdata.hxx> +#include <framework/framelistanalyzer.hxx> + +#include <boost/optional.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::ucb; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using ::com::sun::star::awt::XWindow; +using ::com::sun::star::beans::PropertyValue; +using ::com::sun::star::document::XViewDataSupplier; +using ::com::sun::star::container::XIndexContainer; +namespace css = ::com::sun::star; + +// Due to ViewFrame::Current +#include "appdata.hxx" +#include <sfx2/taskpane.hxx> +#include <sfx2/app.hxx> +#include <sfx2/objface.hxx> +#include "openflag.hxx" +#include "objshimp.hxx" +#include <sfx2/viewsh.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include "arrdecl.hxx" +#include "sfxtypes.hxx" +#include <sfx2/request.hxx> +#include <sfx2/docfac.hxx> +#include <sfx2/ipclient.hxx> +#include "sfx2/sfxresid.hxx" +#include "appbas.hxx" +#include <sfx2/objitem.hxx> +#include "sfx2/viewfac.hxx" +#include <sfx2/event.hxx> +#include "fltfnc.hxx" +#include <sfx2/docfile.hxx> +#include <sfx2/module.hxx> +#include <sfx2/msgpool.hxx> +#include <sfx2/viewfrm.hxx> +#include "viewimp.hxx" +#include <sfx2/sfxbasecontroller.hxx> +#include <sfx2/sfx.hrc> +#include "view.hrc" +#include <sfx2/frmdescr.hxx> +#include <sfx2/sfxuno.hxx> +#include <sfx2/progress.hxx> +#include "workwin.hxx" +#include "helper.hxx" +#include "macro.hxx" +#include "sfx2/minfitem.hxx" +#include "../appl/app.hrc" +#include "impviewframe.hxx" + +//------------------------------------------------------------------------- +DBG_NAME(SfxViewFrame) + +#define SfxViewFrame +#include "sfxslots.hxx" +#undef SfxViewFrame + +//------------------------------------------------------------------------- + +SFX_IMPL_INTERFACE(SfxViewFrame,SfxShell,SfxResId(0)) +{ + SFX_CHILDWINDOW_REGISTRATION( SID_BROWSER ); + SFX_CHILDWINDOW_REGISTRATION( SID_RECORDING_FLOATWINDOW ); + + SFX_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_FULLSCREEN | SFX_VISIBILITY_FULLSCREEN, SfxResId(RID_FULLSCREENTOOLBOX) ); + SFX_OBJECTBAR_REGISTRATION( SFX_OBJECTBAR_APPLICATION | SFX_VISIBILITY_STANDARD, SfxResId(RID_ENVTOOLBOX) ); +} + +TYPEINIT2(SfxViewFrame,SfxShell,SfxListener); +TYPEINIT1(SfxViewFrameItem, SfxPoolItem); + +//------------------------------------------------------------------------- +namespace +{ + bool moduleHasToolPanels( SfxViewFrame_Impl& i_rViewFrameImpl ) + { + if ( !i_rViewFrameImpl.aHasToolPanels ) + { + i_rViewFrameImpl.aHasToolPanels.reset( ::sfx2::ModuleTaskPane::ModuleHasToolPanels( + i_rViewFrameImpl.rFrame.GetFrameInterface() ) ); + } + return *i_rViewFrameImpl.aHasToolPanels; + } +} + +//------------------------------------------------------------------------- +static sal_Bool AskPasswordToModify_Impl( const uno::Reference< task::XInteractionHandler >& xHandler, const ::rtl::OUString& aPath, const SfxFilter* pFilter, sal_uInt32 nPasswordHash, const uno::Sequence< beans::PropertyValue > aInfo ) +{ + // TODO/LATER: In future the info should replace the direct hash completely + sal_Bool bResult = ( !nPasswordHash && !aInfo.getLength() ); + + OSL_ENSURE( pFilter && ( pFilter->GetFilterFlags() & SFX_FILTER_PASSWORDTOMODIFY ), "PasswordToModify feature is active for a filter that does not support it!" ); + + if ( pFilter && xHandler.is() ) + { + sal_Bool bCancel = sal_False; + sal_Bool bFirstTime = sal_True; + + while ( !bResult && !bCancel ) + { + sal_Bool bMSType = !pFilter->IsOwnFormat(); + + ::rtl::Reference< ::comphelper::DocPasswordRequest > pPasswordRequest( + new ::comphelper::DocPasswordRequest( + bMSType ? ::comphelper::DocPasswordRequestType_MS : ::comphelper::DocPasswordRequestType_STANDARD, + bFirstTime ? ::com::sun::star::task::PasswordRequestMode_PASSWORD_ENTER : ::com::sun::star::task::PasswordRequestMode_PASSWORD_REENTER, + aPath, + sal_True ) ); + + uno::Reference< com::sun::star::task::XInteractionRequest > rRequest( pPasswordRequest.get() ); + xHandler->handle( rRequest ); + + if ( pPasswordRequest->isPassword() ) + { + if ( aInfo.getLength() ) + { + bResult = ::comphelper::DocPasswordHelper::IsModifyPasswordCorrect( pPasswordRequest->getPasswordToModify(), aInfo ); + } + else + { + // the binary format + bResult = ( SfxMedium::CreatePasswordToModifyHash( pPasswordRequest->getPasswordToModify(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.text.TextDocument" ) ).equals( pFilter->GetServiceName() ) ) == nPasswordHash ); + } + } + else + bCancel = sal_True; + + bFirstTime = sal_False; + } + } + + return bResult; +} + +//------------------------------------------------------------------------- +void SfxViewFrame::SetDowning_Impl() +{ + pImp->bIsDowning = sal_True; +} + +//------------------------------------------------------------------------- +sal_Bool SfxViewFrame::IsDowning_Impl() const +{ + return pImp->bIsDowning; +} + + +//-------------------------------------------------------------------- +class SfxViewNotificatedFrameList_Impl : + public SfxListener, public SfxViewFrameArr_Impl +{ +public: + + void InsertViewFrame( SfxViewFrame* pFrame ) + { + StartListening( *pFrame ); + C40_INSERT( SfxViewFrame, pFrame, Count() ); + } + void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); +}; + +//------------------------------------------------------------------------- +void SfxViewNotificatedFrameList_Impl::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + if ( rHint.IsA(TYPE(SfxSimpleHint)) ) + { + switch( ( (SfxSimpleHint&) rHint ).GetId() ) + { + case SFX_HINT_DYING: + SfxViewFrame* pFrame = (SfxViewFrame*) &rBC; + if( pFrame ) + { + sal_uInt16 nPos = C40_GETPOS( SfxViewFrame, pFrame ); + if( nPos != USHRT_MAX ) + Remove( nPos ); + } + break; + } + } +} + +//------------------------------------------------------------------------- + +long ReloadDecouple_Impl( void* pObj, void* pArg ) +{ + ((SfxViewFrame*) pObj)->ExecReload_Impl( *(SfxRequest*)pArg ); + return 0; +} + +void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq, sal_Bool bAsync ) +{ + if( bAsync ) + { + if( !pImp->pReloader ) + pImp->pReloader = new svtools::AsynchronLink( + Link( this, ReloadDecouple_Impl ) ); + pImp->pReloader->Call( new SfxRequest( rReq ) ); + } + else ExecReload_Impl( rReq ); +} + +void SfxViewFrame::ExecReload_Impl( SfxRequest& rReq ) +{ + SfxFrame *pParent = GetFrame().GetParentFrame(); + if ( rReq.GetSlot() == SID_RELOAD ) + { + // When CTRL-Reload, reload the active Frame + SfxViewFrame* pActFrame = this; + while ( pActFrame ) + pActFrame = pActFrame->GetActiveChildFrame_Impl(); + + if ( pActFrame ) + { + sal_uInt16 nModifier = rReq.GetModifier(); + if ( nModifier & KEY_MOD1 ) + { + pActFrame->ExecReload_Impl( rReq ); + return; + } + } + + // If only a reload of the graphics for one or more child frames + // should be made + SfxFrame& rFrame = GetFrame(); + if ( pParent == &rFrame && rFrame.GetChildFrameCount() ) + { + sal_Bool bReloadAvailable = sal_False; + SfxFrameIterator aIter( rFrame, sal_False ); + SfxFrame *pChild = aIter.FirstFrame(); + while ( pChild ) + { + SfxFrame *pNext = aIter.NextFrame( *pChild ); + SfxObjectShell *pShell = pChild->GetCurrentDocument(); + if( pShell && pShell->Get_Impl()->bReloadAvailable ) + { + bReloadAvailable = sal_True; + pChild->GetCurrentViewFrame()->ExecuteSlot( rReq ); + } + pChild = pNext; + } + + // The top level frame itself has no graphics! + if ( bReloadAvailable ) + return; + } + } + else + { + // When CTRL-Edit, edit the TopFrame. + sal_uInt16 nModifier = rReq.GetModifier(); + + if ( ( nModifier & KEY_MOD1 ) && pParent ) + { + SfxViewFrame *pTop = GetTopViewFrame(); + pTop->ExecReload_Impl( rReq ); + return; + } + } + + SfxObjectShell* pSh = GetObjectShell(); + switch ( rReq.GetSlot() ) + { + case SID_EDITDOC: + { + if ( GetFrame().HasComponent() ) + break; + + // Due to Double occupancy in toolboxes (with or without Ctrl), + // it is also possible that the slot is enabled, but Ctrl-click + // despite this is not! + if( !pSh || !pSh->HasName() || !(pSh->Get_Impl()->nLoadedFlags & SFX_LOADED_MAINDOCUMENT )) + break; + + SfxMedium* pMed = pSh->GetMedium(); + + SFX_ITEMSET_ARG( pSh->GetMedium()->GetItemSet(), pItem, SfxBoolItem, SID_VIEWONLY, sal_False ); + if ( pItem && pItem->GetValue() ) + { + SfxApplication* pApp = SFX_APP(); + SfxAllItemSet aSet( pApp->GetPool() ); + aSet.Put( SfxStringItem( SID_FILE_NAME, pMed->GetURLObject().GetMainURL(INetURLObject::NO_DECODE) ) ); + aSet.Put( SfxBoolItem( SID_TEMPLATE, sal_True ) ); + aSet.Put( SfxStringItem( SID_TARGETNAME, String::CreateFromAscii("_blank") ) ); + SFX_ITEMSET_ARG( pMed->GetItemSet(), pReferer, SfxStringItem, SID_REFERER, sal_False ); + if ( pReferer ) + aSet.Put( *pReferer ); + SFX_ITEMSET_ARG( pSh->GetMedium()->GetItemSet(), pVersionItem, SfxInt16Item, SID_VERSION, sal_False ); + if ( pVersionItem ) + aSet.Put( *pVersionItem ); + + if( pMed->GetFilter() ) + { + aSet.Put( SfxStringItem( SID_FILTER_NAME, pMed->GetFilter()->GetFilterName() ) ); + SFX_ITEMSET_ARG( pMed->GetItemSet(), pOptions, SfxStringItem, SID_FILE_FILTEROPTIONS, sal_False ); + if ( pOptions ) + aSet.Put( *pOptions ); + } + + GetDispatcher()->Execute( SID_OPENDOC, SFX_CALLMODE_ASYNCHRON, aSet ); + return; + } + + sal_uInt16 nOpenMode; + sal_Bool bNeedsReload = sal_False; + if ( !pSh->IsReadOnly() ) + { + // Save and reload Readonly + if( pSh->IsModified() ) + { + if ( pSh->PrepareClose() ) + { + // the storing could let the medium be changed + pMed = pSh->GetMedium(); + bNeedsReload = sal_True; + } + else + { + rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), sal_False ) ); + return; + } + } + nOpenMode = SFX_STREAM_READONLY; + } + else + { + if ( pSh->IsReadOnlyMedium() + && ( pSh->GetModifyPasswordHash() || pSh->GetModifyPasswordInfo().getLength() ) + && !pSh->IsModifyPasswordEntered() ) + { + ::rtl::OUString aDocumentName = INetURLObject( pMed->GetOrigURL() ).GetMainURL( INetURLObject::DECODE_WITH_CHARSET ); + if( !AskPasswordToModify_Impl( pMed->GetInteractionHandler(), aDocumentName, pMed->GetOrigFilter(), pSh->GetModifyPasswordHash(), pSh->GetModifyPasswordInfo() ) ) + { + // this is a read-only document, if it has "Password to modify" + // the user should enter password before he can edit the document + rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), sal_False ) ); + return; + } + + pSh->SetModifyPasswordEntered(); + } + + nOpenMode = SFX_STREAM_READWRITE; + pSh->SetReadOnlyUI( sal_False ); + + // if only the view was in the readonly mode then there is no need to do the reload + if ( !pSh->IsReadOnly() ) + return; + } + + if ( rReq.IsAPI() ) + { + // Control through API if r/w or r/o + SFX_REQUEST_ARG(rReq, pEditItem, SfxBoolItem, SID_EDITDOC, sal_False); + if ( pEditItem ) + nOpenMode = pEditItem->GetValue() ? SFX_STREAM_READWRITE : SFX_STREAM_READONLY; + } + + // doing + + String aTemp; + utl::LocalFileHelper::ConvertPhysicalNameToURL( pMed->GetPhysicalName(), aTemp ); + INetURLObject aPhysObj( aTemp ); + SFX_ITEMSET_ARG( pSh->GetMedium()->GetItemSet(), + pVersionItem, SfxInt16Item, SID_VERSION, sal_False ); + + INetURLObject aMedObj( pMed->GetName() ); + + // the logic below is following, if the document seems not to need to be reloaded and the physical name is different + // to the logical one, then on file system it can be checked that the copy is still newer than the original and no document reload is required + if ( ( !bNeedsReload && ( (aMedObj.GetProtocol() == INET_PROT_FILE && + aMedObj.getFSysPath(INetURLObject::FSYS_DETECT) != aPhysObj.getFSysPath(INetURLObject::FSYS_DETECT) && + !::utl::UCBContentHelper::IsYounger( aMedObj.GetMainURL( INetURLObject::NO_DECODE ), aPhysObj.GetMainURL( INetURLObject::NO_DECODE ) )) + || pMed->IsRemote() ) ) + || pVersionItem ) + { + sal_Bool bOK = sal_False; + if ( !pVersionItem ) + { + sal_Bool bHasStorage = pMed->HasStorage_Impl(); + // switching edit mode could be possible without reload + if ( bHasStorage && pMed->GetStorage() == pSh->GetStorage() ) + { + // TODO/LATER: faster creation of copy + if ( !pSh->ConnectTmpStorage_Impl( pMed->GetStorage(), pMed ) ) + return; + } + + pMed->CloseAndRelease(); + pMed->GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, !( nOpenMode & STREAM_WRITE ) ) ); + pMed->SetOpenMode( nOpenMode, pMed->IsDirect() ); + + pMed->CompleteReOpen(); + if ( nOpenMode & STREAM_WRITE ) + pMed->LockOrigFileOnDemand( sal_False, sal_True ); + + // LockOrigFileOnDemand might set the readonly flag itself, it should be set back + pMed->GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, !( nOpenMode & STREAM_WRITE ) ) ); + + if ( !pMed->GetErrorCode() ) + bOK = sal_True; + } + + if( !bOK ) + { + ErrCode nErr = pMed->GetErrorCode(); + if ( pVersionItem ) + nErr = ERRCODE_IO_ACCESSDENIED; + else + { + pMed->ResetError(); + pMed->SetOpenMode( SFX_STREAM_READONLY, pMed->IsDirect() ); + pMed->ReOpen(); + pSh->DoSaveCompleted( pMed ); + } + + // Readonly document can not be switched to edit mode? + rReq.Done( sal_False ); + + if ( nOpenMode == SFX_STREAM_READWRITE && !rReq.IsAPI() ) + { + // ::com::sun::star::sdbcx::User offering to open it as a template + QueryBox aBox( &GetWindow(), SfxResId(MSG_QUERY_OPENASTEMPLATE) ); + if ( RET_YES == aBox.Execute() ) + { + SfxApplication* pApp = SFX_APP(); + SfxAllItemSet aSet( pApp->GetPool() ); + aSet.Put( SfxStringItem( SID_FILE_NAME, pMed->GetName() ) ); + SFX_ITEMSET_ARG( pMed->GetItemSet(), pReferer, SfxStringItem, SID_REFERER, sal_False ); + if ( pReferer ) + aSet.Put( *pReferer ); + aSet.Put( SfxBoolItem( SID_TEMPLATE, sal_True ) ); + if ( pVersionItem ) + aSet.Put( *pVersionItem ); + + if( pMed->GetFilter() ) + { + aSet.Put( SfxStringItem( SID_FILTER_NAME, pMed->GetFilter()->GetFilterName() ) ); + SFX_ITEMSET_ARG( pMed->GetItemSet(), pOptions, + SfxStringItem, SID_FILE_FILTEROPTIONS, sal_False ); + if ( pOptions ) + aSet.Put( *pOptions ); + } + + GetDispatcher()->Execute( SID_OPENDOC, SFX_CALLMODE_ASYNCHRON, aSet ); + return; + } + else + nErr = 0; + } + + ErrorHandler::HandleError( nErr ); + rReq.SetReturnValue( + SfxBoolItem( rReq.GetSlot(), sal_False ) ); + return; + } + else + { + pSh->DoSaveCompleted( pMed ); + pSh->Broadcast( SfxSimpleHint(SFX_HINT_MODECHANGED) ); + rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), sal_True ) ); + rReq.Done( sal_True ); + return; + } + } + + rReq.AppendItem( SfxBoolItem( SID_FORCERELOAD, sal_True) ); + rReq.AppendItem( SfxBoolItem( SID_SILENT, sal_True )); + } + + case SID_RELOAD: + { + // Due to Double occupancy in toolboxes (with or without Ctrl), + // it is also possible that the slot is enabled, but Ctrl-click + // despite this is not! + if ( !pSh || !pSh->CanReload_Impl() ) + break; + SfxApplication* pApp = SFX_APP(); + SFX_REQUEST_ARG(rReq, pForceReloadItem, SfxBoolItem, + SID_FORCERELOAD, sal_False); + if( pForceReloadItem && !pForceReloadItem->GetValue() && + !pSh->GetMedium()->IsExpired() ) + return; + if( pImp->bReloading || pSh->IsInModalMode() ) + return; + + // AutoLoad is prohibited if possible + SFX_REQUEST_ARG(rReq, pAutoLoadItem, SfxBoolItem, SID_AUTOLOAD, sal_False); + if ( pAutoLoadItem && pAutoLoadItem->GetValue() && + GetFrame().IsAutoLoadLocked_Impl() ) + return; + + SfxObjectShellLock xOldObj( pSh ); + pImp->bReloading = sal_True; + SFX_REQUEST_ARG(rReq, pURLItem, SfxStringItem, + SID_FILE_NAME, sal_False); + // Open as editable? + sal_Bool bForEdit = !pSh->IsReadOnly(); + if ( rReq.GetSlot() == SID_EDITDOC ) + bForEdit = !bForEdit; + + // If possible ask the User + sal_Bool bDo = ( GetViewShell()->PrepareClose() != sal_False ); + SFX_REQUEST_ARG(rReq, pSilentItem, SfxBoolItem, SID_SILENT, sal_False); + if ( bDo && GetFrame().DocIsModified_Impl() && + !rReq.IsAPI() && ( !pSilentItem || !pSilentItem->GetValue() ) ) + { + QueryBox aBox( &GetWindow(), SfxResId(MSG_QUERY_LASTVERSION) ); + bDo = ( RET_YES == aBox.Execute() ); + } + + if ( bDo ) + { + SfxMedium *pMedium = xOldObj->GetMedium(); + + // Remove Frameset before the FramesetView may disappear + String aURL = pURLItem ? pURLItem->GetValue() : + pMedium->GetName(); + + sal_Bool bHandsOff = + ( pMedium->GetURLObject().GetProtocol() == INET_PROT_FILE && !xOldObj->IsDocShared() ); + + // Emty existing SfxMDIFrames for this Document + // in native format or R/O, open it now for editing? + SfxObjectShellLock xNewObj; + + // collect the views of the document + // TODO: when UNO ViewFactories are available for SFX-based documents, the below code should + // be UNOized, too + typedef ::std::pair< Reference< XFrame >, sal_uInt16 > ViewDescriptor; + ::std::list< ViewDescriptor > aViewFrames; + SfxViewFrame *pView = GetFirst( xOldObj ); + while ( pView ) + { + Reference< XFrame > xFrame( pView->GetFrame().GetFrameInterface() ); + OSL_ENSURE( xFrame.is(), "SfxViewFrame::ExecReload_Impl: no XFrame?!" ); + aViewFrames.push_back( ViewDescriptor( xFrame, pView->GetCurViewId() ) ); + + pView = GetNext( *pView, xOldObj ); + } + + DELETEZ( xOldObj->Get_Impl()->pReloadTimer ); + + SfxItemSet* pNewSet = 0; + const SfxFilter *pFilter = pMedium->GetFilter(); + if( pURLItem ) + { + pNewSet = new SfxAllItemSet( pApp->GetPool() ); + pNewSet->Put( *pURLItem ); + + // Filter Detection + SfxMedium aMedium( pURLItem->GetValue(), SFX_STREAM_READWRITE ); + SfxFilterMatcher().GuessFilter( aMedium, &pFilter ); + if ( pFilter ) + pNewSet->Put( SfxStringItem( SID_FILTER_NAME, pFilter->GetName() ) ); + pNewSet->Put( *aMedium.GetItemSet() ); + } + else + { + pNewSet = new SfxAllItemSet( *pMedium->GetItemSet() ); + pNewSet->ClearItem( SID_VIEW_ID ); + pNewSet->ClearItem( SID_STREAM ); + pNewSet->ClearItem( SID_INPUTSTREAM ); + pNewSet->Put( SfxStringItem( SID_FILTER_NAME, pMedium->GetFilter()->GetName() ) ); + + // let the current security settings be checked again + pNewSet->Put( SfxUInt16Item( SID_MACROEXECMODE, document::MacroExecMode::USE_CONFIG ) ); + + if ( rReq.GetSlot() == SID_EDITDOC || !bForEdit ) + // edit mode is switched or reload of readonly document + pNewSet->Put( SfxBoolItem( SID_DOC_READONLY, !bForEdit ) ); + else + // Reload of file opened for writing + pNewSet->ClearItem( SID_DOC_READONLY ); + } + + // If a salvaged file is present, do not enclose the OrigURL + // again, since the Tempdate is invalid after reload. + SFX_ITEMSET_ARG( pNewSet, pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, sal_False); + if( pSalvageItem ) + { + aURL = pSalvageItem->GetValue(); + pNewSet->ClearItem( SID_DOC_SALVAGE ); + } + + // TODO/LATER: Temporary solution, the SfxMedium must know the original URL as aLogicName + // SfxMedium::Transfer_Impl() will be forbidden then. + if ( xOldObj->IsDocShared() ) + pNewSet->Put( SfxStringItem( SID_FILE_NAME, xOldObj->GetSharedFileURL() ) ); + + if ( pURLItem ) + pNewSet->Put( SfxStringItem( SID_REFERER, pMedium->GetName() ) ); + else + pNewSet->Put( SfxStringItem( SID_REFERER, String() ) ); + + xOldObj->CancelTransfers(); + + + if ( pSilentItem && pSilentItem->GetValue() ) + pNewSet->Put( SfxBoolItem( SID_SILENT, sal_True ) ); + + SFX_ITEMSET_ARG(pNewSet, pInteractionItem, SfxUnoAnyItem, SID_INTERACTIONHANDLER, sal_False); + SFX_ITEMSET_ARG(pNewSet, pMacroExecItem , SfxUInt16Item, SID_MACROEXECMODE , sal_False); + SFX_ITEMSET_ARG(pNewSet, pDocTemplateItem, SfxUInt16Item, SID_UPDATEDOCMODE , sal_False); + + if (!pInteractionItem) + { + Reference < ::com::sun::star::task::XInteractionHandler > xHdl( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.uui.UUIInteractionHandler"))), UNO_QUERY ); + if (xHdl.is()) + pNewSet->Put( SfxUnoAnyItem(SID_INTERACTIONHANDLER,::com::sun::star::uno::makeAny(xHdl)) ); + } + + if (!pMacroExecItem) + pNewSet->Put( SfxUInt16Item(SID_MACROEXECMODE,::com::sun::star::document::MacroExecMode::USE_CONFIG) ); + if (!pDocTemplateItem) + pNewSet->Put( SfxUInt16Item(SID_UPDATEDOCMODE,::com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG) ); + + xOldObj->SetModified( sal_False ); + // Do not chache the old Document! Is invalid when loading + // another document. + + SFX_ITEMSET_ARG( pMedium->GetItemSet(), pSavedOptions, SfxStringItem, SID_FILE_FILTEROPTIONS, sal_False); + SFX_ITEMSET_ARG( pMedium->GetItemSet(), pSavedReferer, SfxStringItem, SID_REFERER, sal_False); + + sal_Bool bHasStorage = pMedium->HasStorage_Impl(); + if( bHandsOff ) + { + if ( bHasStorage && pMedium->GetStorage() == xOldObj->GetStorage() ) + { + // TODO/LATER: faster creation of copy + if ( !xOldObj->ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) ) + return; + } + + pMedium->CloseAndRelease(); + } + + xNewObj = SfxObjectShell::CreateObject( pFilter->GetServiceName(), SFX_CREATE_MODE_STANDARD ); + + if ( xOldObj->IsModifyPasswordEntered() ) + xNewObj->SetModifyPasswordEntered(); + + uno::Sequence < beans::PropertyValue > aLoadArgs; + TransformItems( SID_OPENDOC, *pNewSet, aLoadArgs ); + try + { + uno::Reference < frame::XLoadable > xLoad( xNewObj->GetModel(), uno::UNO_QUERY ); + xLoad->load( aLoadArgs ); + } + catch ( uno::Exception& ) + { + xNewObj->DoClose(); + xNewObj = 0; + } + + DELETEZ( pNewSet ); + + if( !xNewObj.Is() ) + { + if( bHandsOff ) + { + // back to old medium + pMedium->ReOpen(); + pMedium->LockOrigFileOnDemand( sal_False, sal_True ); + + xOldObj->DoSaveCompleted( pMedium ); + } + + // r/o-Doc couldn't be switched to writing mode + if ( bForEdit && SID_EDITDOC == rReq.GetSlot() ) + { + // ask user for opening as template + QueryBox aBox( &GetWindow(), SfxResId(MSG_QUERY_OPENASTEMPLATE) ); + if ( RET_YES == aBox.Execute() ) + { + SfxAllItemSet aSet( pApp->GetPool() ); + aSet.Put( SfxStringItem( SID_FILE_NAME, pMedium->GetName() ) ); + aSet.Put( SfxStringItem( SID_TARGETNAME, String::CreateFromAscii("_blank") ) ); + if ( pSavedOptions ) + aSet.Put( *pSavedOptions ); + if ( pSavedReferer ) + aSet.Put( *pSavedReferer ); + aSet.Put( SfxBoolItem( SID_TEMPLATE, sal_True ) ); + if( pFilter ) + aSet.Put( SfxStringItem( SID_FILTER_NAME, pFilter->GetFilterName() ) ); + GetDispatcher()->Execute( SID_OPENDOC, SFX_CALLMODE_ASYNCHRON, aSet ); + } + } + } + else + { + if ( xNewObj->GetModifyPasswordHash() && xNewObj->GetModifyPasswordHash() != xOldObj->GetModifyPasswordHash() ) + { + xNewObj->SetModifyPasswordEntered( sal_False ); + xNewObj->SetReadOnly(); + } + else if ( rReq.GetSlot() == SID_EDITDOC && bForEdit && !xNewObj->IsReadOnlyMedium() ) + { + // the filter might request setting of the document to readonly state + // but in case of SID_EDITDOC it should not happen if the document + // can be opened for editing + xNewObj->SetReadOnlyUI( sal_False ); + } + + if ( xNewObj->IsDocShared() ) + { + // the file is shared but the closing can change the sharing control file + xOldObj->DoNotCleanShareControlFile(); + } + + // the Reload and Silent items were only temporary, remove them + xNewObj->GetMedium()->GetItemSet()->ClearItem( SID_RELOAD ); + xNewObj->GetMedium()->GetItemSet()->ClearItem( SID_SILENT ); + TransformItems( SID_OPENDOC, *xNewObj->GetMedium()->GetItemSet(), aLoadArgs ); + + UpdateDocument_Impl(); + + try + { + while ( !aViewFrames.empty() ) + { + LoadViewIntoFrame_Impl( *xNewObj, aViewFrames.front().first, aLoadArgs, aViewFrames.front().second, false ); + aViewFrames.pop_front(); + } + } + catch( const Exception& ) + { + // close the remaining frames + // Don't catch exceptions herein, if this fails, then we're left in an indetermined state, and + // crashing is better than trying to proceed + while ( !aViewFrames.empty() ) + { + Reference< util::XCloseable > xClose( aViewFrames.front().first, UNO_QUERY_THROW ); + xClose->close( sal_True ); + aViewFrames.pop_front(); + } + } + + // Propagate document closure. + SFX_APP()->NotifyEvent( SfxEventHint( SFX_EVENT_CLOSEDOC, GlobalEventConfig::GetEventName( STR_EVENT_CLOSEDOC ), xOldObj ) ); + } + + // Record as done + rReq.Done( sal_True ); + rReq.SetReturnValue(SfxBoolItem(rReq.GetSlot(), sal_True)); + return; + } + else + { + // Record as not done + rReq.Done(); + rReq.SetReturnValue(SfxBoolItem(rReq.GetSlot(), sal_False)); + pImp->bReloading = sal_False; + return; + } + } + } +} + +//------------------------------------------------------------------------- +void SfxViewFrame::StateReload_Impl( SfxItemSet& rSet ) +{ + SfxObjectShell* pSh = GetObjectShell(); + if ( !pSh ) + // I'm just on reload and am yielding myself ... + return; + + GetFrame().GetParentFrame(); + SfxWhichIter aIter( rSet ); + for ( sal_uInt16 nWhich = aIter.FirstWhich(); nWhich; nWhich = aIter.NextWhich() ) + { + if ( GetFrame().HasComponent() ) + { + // If the component is not self-dispatched, then + // it makes no sense! + rSet.DisableItem( nWhich ); + continue; + } + + switch ( nWhich ) + { + case SID_EDITDOC: + { + if ( !pSh || !pSh->HasName() || !( pSh->Get_Impl()->nLoadedFlags & SFX_LOADED_MAINDOCUMENT ) + || pSh->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED ) + rSet.DisableItem( SID_EDITDOC ); + else + { + SFX_ITEMSET_ARG( pSh->GetMedium()->GetItemSet(), pItem, SfxBoolItem, SID_EDITDOC, sal_False ); + if ( pItem && !pItem->GetValue() ) + rSet.DisableItem( SID_EDITDOC ); + else + rSet.Put( SfxBoolItem( nWhich, !pSh->IsReadOnly() ) ); + } + break; + } + + case SID_RELOAD: + { + SfxFrame* pFrame = &GetTopFrame(); + + if ( !pSh || !pSh->CanReload_Impl() || pSh->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED ) + rSet.DisableItem(nWhich); + else + { + // If any ChildFrame is reloadable, the slot is enabled, + // so you can perfom CTRL-Reload + sal_Bool bReloadAvailable = sal_False; + SfxFrameIterator aFrameIter( *pFrame, sal_True ); + for( SfxFrame* pNextFrame = aFrameIter.FirstFrame(); + pFrame; + pNextFrame = pNextFrame ? + aFrameIter.NextFrame( *pNextFrame ) : 0 ) + { + SfxObjectShell *pShell = pFrame->GetCurrentDocument(); + if( pShell && pShell->Get_Impl()->bReloadAvailable ) + { + bReloadAvailable = sal_True; + break; + } + pFrame = pNextFrame; + } + + rSet.Put( SfxBoolItem( nWhich, bReloadAvailable)); + } + + break; + } + } + } +} + + +//-------------------------------------------------------------------- +void SfxViewFrame::ExecHistory_Impl( SfxRequest &rReq ) +{ + // Is there an Undo-Manager on the top Shell? + SfxShell *pSh = GetDispatcher()->GetShell(0); + ::svl::IUndoManager* pShUndoMgr = pSh->GetUndoManager(); + sal_Bool bOK = sal_False; + if ( pShUndoMgr ) + { + switch ( rReq.GetSlot() ) + { + case SID_CLEARHISTORY: + pShUndoMgr->Clear(); + bOK = sal_True; + break; + + case SID_UNDO: + pShUndoMgr->Undo(); + GetBindings().InvalidateAll(sal_False); + bOK = sal_True; + break; + + case SID_REDO: + pShUndoMgr->Redo(); + GetBindings().InvalidateAll(sal_False); + bOK = sal_True; + break; + + case SID_REPEAT: + if ( pSh->GetRepeatTarget() ) + pShUndoMgr->Repeat( *pSh->GetRepeatTarget() ); + bOK = sal_True; + break; + } + } + else if ( GetViewShell() ) + { + // The SW has its own undo in the View + const SfxPoolItem *pRet = GetViewShell()->ExecuteSlot( rReq ); + if ( pRet ) + bOK = ((SfxBoolItem*)pRet)->GetValue(); + } + + rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bOK ) ); + rReq.Done(); +} + +//-------------------------------------------------------------------- +void SfxViewFrame::StateHistory_Impl( SfxItemSet &rSet ) +{ + // Search for Undo-Manager + SfxShell *pSh = GetDispatcher()->GetShell(0); + if ( !pSh ) + // I'm just on reload and am yielding myself ... + return; + + ::svl::IUndoManager *pShUndoMgr = pSh->GetUndoManager(); + if ( !pShUndoMgr ) + { + // The SW has its own undo in the View + SfxWhichIter aIter( rSet ); + SfxViewShell *pViewSh = GetViewShell(); + if( !pViewSh ) return; + for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() ) + pViewSh->GetSlotState( nSID, 0, &rSet ); + return; + } + + if ( pShUndoMgr->GetUndoActionCount() == 0 && + pShUndoMgr->GetRedoActionCount() == 0 && + pShUndoMgr->GetRepeatActionCount() == 0 ) + rSet.DisableItem( SID_CLEARHISTORY ); + + if ( pShUndoMgr && pShUndoMgr->GetUndoActionCount() ) + { + String aTmp( SvtResId( STR_UNDO ) ); + aTmp+= pShUndoMgr->GetUndoActionComment(0); + rSet.Put( SfxStringItem( SID_UNDO, aTmp ) ); + } + else + rSet.DisableItem( SID_UNDO ); + + if ( pShUndoMgr && pShUndoMgr->GetRedoActionCount() ) + { + String aTmp( SvtResId(STR_REDO) ); + aTmp += pShUndoMgr->GetRedoActionComment(0); + rSet.Put( SfxStringItem( SID_REDO, aTmp ) ); + } + else + rSet.DisableItem( SID_REDO ); + SfxRepeatTarget *pTarget = pSh->GetRepeatTarget(); + if ( pShUndoMgr && pTarget && pShUndoMgr->GetRepeatActionCount() && + pShUndoMgr->CanRepeat(*pTarget) ) + { + String aTmp( SvtResId(STR_REPEAT) ); + aTmp += pShUndoMgr->GetRepeatActionComment(*pTarget); + rSet.Put( SfxStringItem( SID_REPEAT, aTmp ) ); + } + else + rSet.DisableItem( SID_REPEAT ); +} + +//-------------------------------------------------------------------- +void SfxViewFrame::PopShellAndSubShells_Impl( SfxViewShell& i_rViewShell ) +{ + i_rViewShell.PopSubShells_Impl(); + sal_uInt16 nLevel = pDispatcher->GetShellLevel( i_rViewShell ); + if ( nLevel != USHRT_MAX ) + { + if ( nLevel ) + { + // more sub shells on the stack, which were not affected by PopSubShells_Impl + SfxShell *pSubShell = pDispatcher->GetShell( nLevel-1 ); + if ( pSubShell == i_rViewShell.GetSubShell() ) + // "real" sub shells will be deleted elsewhere + pDispatcher->Pop( *pSubShell, SFX_SHELL_POP_UNTIL ); + else + pDispatcher->Pop( *pSubShell, SFX_SHELL_POP_UNTIL | SFX_SHELL_POP_DELETE ); + } + pDispatcher->Pop( i_rViewShell ); + pDispatcher->Flush(); + } + +} + +//-------------------------------------------------------------------- +void SfxViewFrame::ReleaseObjectShell_Impl() + +/* [Description] + + This method empties the SfxViewFrame, i.e. takes the <SfxObjectShell> + from the dispatcher and ends its <SfxListener> Relationship to this + SfxObjectShell (by which they may even destroy themselves). + + Thus, by invoking ReleaseObjectShell() and SetObjectShell() the + SfxObjectShell can be replaced. + + Between RealeaseObjectShell() and SetObjectShell() can the control not + be handed over to the system. + + [Cross-reference] + + <SfxViewFrame::SetObjectShell(SfxObjectShell&)> +*/ +{ + DBG_CHKTHIS(SfxViewFrame, 0); + DBG_ASSERT( xObjSh.Is(), "no SfxObjectShell to release!" ); + + GetFrame().ReleasingComponent_Impl( sal_True ); + if ( GetWindow().HasChildPathFocus( sal_True ) ) + { + DBG_ASSERT( !GetActiveChildFrame_Impl(), "Wrong active child frame!" ); + GetWindow().GrabFocus(); + } + + SfxViewShell *pDyingViewSh = GetViewShell(); + if ( pDyingViewSh ) + { + PopShellAndSubShells_Impl( *pDyingViewSh ); + pDyingViewSh->DisconnectAllClients(); + SetViewShell_Impl(0); + delete pDyingViewSh; + } +#ifdef DBG_UTIL + else + OSL_FAIL("No Shell"); +#endif + + if ( xObjSh.Is() ) + { + pImp->aLastType = xObjSh->Type(); + pDispatcher->Pop( *xObjSh ); + SfxModule* pModule = xObjSh->GetModule(); + if( pModule ) + pDispatcher->RemoveShell_Impl( *pModule ); + pDispatcher->Flush(); + EndListening( *xObjSh ); + + Notify( *xObjSh, SfxSimpleHint(SFX_HINT_TITLECHANGED) ); + Notify( *xObjSh, SfxSimpleHint(SFX_HINT_DOCCHANGED) ); + + if ( 1 == xObjSh->GetOwnerLockCount() && pImp->bObjLocked && xObjSh->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED ) + xObjSh->DoClose(); + SfxObjectShellRef xDyingObjSh = xObjSh; + xObjSh.Clear(); + if( ( GetFrameType() & SFXFRAME_HASTITLE ) && pImp->nDocViewNo ) + xDyingObjSh->GetNoSet_Impl().ReleaseIndex(pImp->nDocViewNo-1); + if ( pImp->bObjLocked ) + { + xDyingObjSh->OwnerLock( sal_False ); + pImp->bObjLocked = sal_False; + } + } + + GetDispatcher()->SetDisableFlags( 0 ); +} + +//-------------------------------------------------------------------- +sal_Bool SfxViewFrame::Close() +{ + DBG_CHKTHIS(SfxViewFrame, 0); + + DBG_ASSERT( GetFrame().IsClosing_Impl() || !GetFrame().GetFrameInterface().is(), "ViewFrame closed too early!" ); + + // If no saving have been made up until now, then embedded Objects should + // not be saved automatically anymore. + if ( GetViewShell() ) + GetViewShell()->DiscardClients_Impl(); + Broadcast( SfxSimpleHint( SFX_HINT_DYING ) ); + + if (SfxViewFrame::Current() == this) + SfxViewFrame::SetViewFrame( NULL ); + + // Since the Dispatcher is emptied, it can not be used in any reasnable + // manner, thus it is better to let the dispatcher be. + GetDispatcher()->Lock(sal_True); + delete this; + + return sal_True; +} + +//-------------------------------------------------------------------- + +void SfxViewFrame::DoActivate( sal_Bool bUI, SfxViewFrame* pOldFrame ) +{ + DBG_CHKTHIS(SfxViewFrame, 0); + SFX_APP(); + + pDispatcher->DoActivate_Impl( bUI, pOldFrame ); + + // If this ViewFrame has got a parent and this is not a parent of the + // old ViewFrames, it gets a ParentActivate. + if ( bUI ) + { + SfxViewFrame *pFrame = GetParentViewFrame(); + while ( pFrame ) + { + if ( !pOldFrame || !pOldFrame->GetFrame().IsParent( &pFrame->GetFrame() ) ) + pFrame->pDispatcher->DoParentActivate_Impl(); + pFrame = pFrame->GetParentViewFrame(); + } + } +} + +//-------------------------------------------------------------------- +void SfxViewFrame::DoDeactivate(sal_Bool bUI, SfxViewFrame* pNewFrame ) +{ + DBG_CHKTHIS(SfxViewFrame, 0); + SFX_APP(); + pDispatcher->DoDeactivate_Impl( bUI, pNewFrame ); + + // If this ViewFrame has got a parent and this is not a parent of the + // new ViewFrames, it gets a ParentDeactivate. + if ( bUI ) + { + SfxViewFrame *pFrame = GetParentViewFrame(); + while ( pFrame ) + { + if ( !pNewFrame || !pNewFrame->GetFrame().IsParent( &pFrame->GetFrame() ) ) + pFrame->pDispatcher->DoParentDeactivate_Impl(); + pFrame = pFrame->GetParentViewFrame(); + } + } +} + +//------------------------------------------------------------------------ +void SfxViewFrame::InvalidateBorderImpl( const SfxViewShell* pSh ) +{ + if( pSh && !nAdjustPosPixelLock ) + { + if ( GetViewShell() && GetWindow().IsVisible() ) + { + if ( GetFrame().IsInPlace() ) + { + return; + } + + DoAdjustPosSizePixel( (SfxViewShell *) GetViewShell(), Point(), + GetWindow().GetOutputSizePixel() ); + } + } +} + +//------------------------------------------------------------------------ +sal_Bool SfxViewFrame::SetBorderPixelImpl +( + const SfxViewShell* pVSh, + const SvBorder& rBorder +) + +{ + pImp->aBorder = rBorder; + + if ( IsResizeInToOut_Impl() && !GetFrame().IsInPlace() ) + { + Size aSize = pVSh->GetWindow()->GetOutputSizePixel(); + if ( aSize.Width() && aSize.Height() ) + { + aSize.Width() += rBorder.Left() + rBorder.Right(); + aSize.Height() += rBorder.Top() + rBorder.Bottom(); + + Size aOldSize = GetWindow().GetOutputSizePixel(); + GetWindow().SetOutputSizePixel( aSize ); + Window* pParent = &GetWindow(); + while ( pParent->GetParent() ) + pParent = pParent->GetParent(); + Size aOuterSize = pParent->GetOutputSizePixel(); + aOuterSize.Width() += ( aSize.Width() - aOldSize.Width() ); + aOuterSize.Height() += ( aSize.Height() - aOldSize.Height() ); + pParent->SetOutputSizePixel( aOuterSize ); + } + } + else + { + Point aPoint; + Rectangle aEditArea( aPoint, GetWindow().GetOutputSizePixel() ); + aEditArea.Left() += rBorder.Left(); + aEditArea.Right() -= rBorder.Right(); + aEditArea.Top() += rBorder.Top(); + aEditArea.Bottom() -= rBorder.Bottom(); + pVSh->GetWindow()->SetPosSizePixel( aEditArea.TopLeft(), aEditArea.GetSize() ); + } + + return sal_True; +} + +//------------------------------------------------------------------------ +const SvBorder& SfxViewFrame::GetBorderPixelImpl +( + const SfxViewShell* /*pSh*/ +) const + +{ + return pImp->aBorder; +} + +//-------------------------------------------------------------------- +void SfxViewFrame::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint ) +{ + {DBG_CHKTHIS(SfxViewFrame, 0);} + + if( IsDowning_Impl()) + return; + + // we know only SimpleHints + if ( rHint.IsA(TYPE(SfxSimpleHint)) ) + { + switch( ( (SfxSimpleHint&) rHint ).GetId() ) + { + case SFX_HINT_MODECHANGED: + { + UpdateTitle(); + + if ( !xObjSh.Is() ) + break; + + // Switch r/o? + SfxBindings& rBind = GetBindings(); + rBind.Invalidate( SID_RELOAD ); + SfxDispatcher *pDispat = GetDispatcher(); + sal_Bool bWasReadOnly = pDispat->GetReadOnly_Impl(); + sal_Bool bIsReadOnly = xObjSh->IsReadOnly(); + if ( !bWasReadOnly != !bIsReadOnly ) + { + // Then also TITLE_CHANGED + UpdateTitle(); + rBind.Invalidate( SID_FILE_NAME ); + rBind.Invalidate( SID_DOCINFO_TITLE ); + rBind.Invalidate( SID_EDITDOC ); + + pDispat->GetBindings()->InvalidateAll(sal_True); + pDispat->SetReadOnly_Impl( bIsReadOnly ); + + // Only force and Dispatcher-Update, if it is done next + // anyway, otherwise flickering or GPF is possibel since + // the Writer for example prefers in Resize preform some + // actions which has a SetReadOnlyUI in Dispatcher as a + // result! + + if ( pDispat->IsUpdated_Impl() ) + pDispat->Update_Impl(sal_True); + } + + Enable( !xObjSh->IsInModalMode() ); + break; + } + + case SFX_HINT_TITLECHANGED: + { + UpdateTitle(); + SfxBindings& rBind = GetBindings(); + rBind.Invalidate( SID_FILE_NAME ); + rBind.Invalidate( SID_DOCINFO_TITLE ); + rBind.Invalidate( SID_EDITDOC ); + rBind.Invalidate( SID_RELOAD ); + break; + } + + case SFX_HINT_DEINITIALIZING: + GetFrame().DoClose(); + break; + case SFX_HINT_DYING: + // when the Object is being deleted, destroy the view too + if ( xObjSh.Is() ) + ReleaseObjectShell_Impl(); + else + GetFrame().DoClose(); + break; + + } + } + else if ( rHint.IsA(TYPE(SfxEventHint)) ) + { + // When the Document is loaded asynchronously, was the Dispatcher + // set as ReadOnly, to what must be returned when the document itself + // is not read only, and the loading is finished. + switch ( ((SfxEventHint&)rHint).GetEventId() ) + { + case SFX_EVENT_MODIFYCHANGED: + { + SfxBindings& rBind = GetBindings(); + rBind.Invalidate( SID_DOC_MODIFIED ); + rBind.Invalidate( SID_SAVEDOC ); + rBind.Invalidate( SID_RELOAD ); + rBind.Invalidate( SID_EDITDOC ); + break; + } + + case SFX_EVENT_OPENDOC: + case SFX_EVENT_CREATEDOC: + { + if ( !xObjSh.Is() ) + break; + + SfxBindings& rBind = GetBindings(); + rBind.Invalidate( SID_RELOAD ); + rBind.Invalidate( SID_EDITDOC ); + if ( !xObjSh->IsReadOnly() ) + { + // In contrast to above (TITLE_CHANGED) does the UI not + // have to be updated because it was not obstructed + + // #i21560# InvalidateAll() causes the assertion + // 'SfxBindings::Invalidate while in update" when + // the sfx slot SID_BASICIDE_APPEAR is executed + // via API from another thread (Java). + // According to MBA this call is not necessary anymore, + // because each document has its own SfxBindings. + //GetDispatcher()->GetBindings()->InvalidateAll(sal_True); + } + + break; + } + + case SFX_EVENT_TOGGLEFULLSCREENMODE: + { + if ( GetFrame().OwnsBindings_Impl() ) + GetBindings().GetDispatcher_Impl()->Update_Impl( sal_True ); + break; + } + } + } +} + +//------------------------------------------------------------------------ +void SfxViewFrame::Construct_Impl( SfxObjectShell *pObjSh ) +{ + pImp->bResizeInToOut = sal_True; + pImp->bDontOverwriteResizeInToOut = sal_False; + pImp->bObjLocked = sal_False; + pImp->pFocusWin = 0; + pImp->pActiveChild = NULL; + pImp->nCurViewId = 0; + pImp->bReloading = sal_False; + pImp->bIsDowning = sal_False; + pImp->bModal = sal_False; + pImp->bEnabled = sal_True; + pImp->nDocViewNo = 0; + pImp->aMargin = Size( -1, -1 ); + pImp->pWindow = 0; + + SetPool( &SFX_APP()->GetPool() ); + pDispatcher = new SfxDispatcher(this); + if ( !GetBindings().GetDispatcher() ) + GetBindings().SetDispatcher( pDispatcher ); + + xObjSh = pObjSh; + if ( xObjSh.Is() && xObjSh->IsPreview() ) + SetQuietMode_Impl( sal_True ); + + if ( pObjSh ) + { + pDispatcher->Push( *SFX_APP() ); + SfxModule* pModule = xObjSh->GetModule(); + if( pModule ) + pDispatcher->Push( *pModule ); + pDispatcher->Push( *this ); + pDispatcher->Push( *pObjSh ); + pDispatcher->Flush(); + StartListening( *pObjSh ); + pObjSh->ViewAssigned(); + Notify( *pObjSh, SfxSimpleHint(SFX_HINT_TITLECHANGED) ); + Notify( *pObjSh, SfxSimpleHint(SFX_HINT_DOCCHANGED) ); + pDispatcher->SetReadOnly_Impl( pObjSh->IsReadOnly() ); + } + else + { + pDispatcher->Push( *SFX_APP() ); + pDispatcher->Push( *this ); + pDispatcher->Flush(); + } + + SfxViewFrame *pThis = this; // this due to the sick Array syntax + SfxViewFrameArr_Impl &rViewArr = SFX_APP()->GetViewFrames_Impl(); + rViewArr.C40_INSERT(SfxViewFrame, pThis, rViewArr.Count() ); +} + +SfxViewFrame::SfxViewFrame +( + SfxFrame& rFrame, + SfxObjectShell* pObjShell +) + +/* [Description] + + Constructor of SfxViewFrame for a <SfxObjectShell> from the Resource. + The 'nViewId' to the created <SfxViewShell> can be returned. + (default is the SfxViewShell-Subclass that was registered first). +*/ + + : pImp( new SfxViewFrame_Impl( rFrame ) ) + , pDispatcher(0) + , pBindings( new SfxBindings ) + , nAdjustPosPixelLock( 0 ) +{ + DBG_CTOR( SfxViewFrame, NULL ); + + rFrame.SetCurrentViewFrame_Impl( this ); + rFrame.SetFrameType_Impl( GetFrameType() | SFXFRAME_HASTITLE ); + Construct_Impl( pObjShell ); + + pImp->pWindow = new SfxFrameViewWindow_Impl( this, rFrame.GetWindow() ); + pImp->pWindow->SetSizePixel( rFrame.GetWindow().GetOutputSizePixel() ); + rFrame.SetOwnsBindings_Impl( sal_True ); + rFrame.CreateWorkWindow_Impl(); +} + +//------------------------------------------------------------------------ +SfxViewFrame::~SfxViewFrame() +{ + DBG_DTOR(SfxViewFrame, 0); + + SetDowning_Impl(); + + if ( SfxViewFrame::Current() == this ) + SfxViewFrame::SetViewFrame( NULL ); + + ReleaseObjectShell_Impl(); + + if ( GetFrame().OwnsBindings_Impl() ) + // The Bindings delete the Frame! + KillDispatcher_Impl(); + + delete pImp->pWindow; + + if ( GetFrame().GetCurrentViewFrame() == this ) + GetFrame().SetCurrentViewFrame_Impl( NULL ); + + // Unregister from the Frame List. + SfxApplication *pSfxApp = SFX_APP(); + SfxViewFrameArr_Impl &rFrames = pSfxApp->GetViewFrames_Impl(); + const SfxViewFrame *pThis = this; + rFrames.Remove( rFrames.GetPos(pThis) ); + + // Delete Member + KillDispatcher_Impl(); + + delete pImp; +} + +//------------------------------------------------------------------------ +void SfxViewFrame::KillDispatcher_Impl() + +// Remove and delete the Dispatcher. + +{ + DBG_CHKTHIS(SfxViewFrame, 0); + + SfxModule* pModule = xObjSh.Is() ? xObjSh->GetModule() : 0; + if ( xObjSh.Is() ) + ReleaseObjectShell_Impl(); + if ( pDispatcher ) + { + if( pModule ) + pDispatcher->Pop( *pModule, SFX_SHELL_POP_UNTIL ); + else + pDispatcher->Pop( *this ); + DELETEZ(pDispatcher); + } +} + +//------------------------------------------------------------------------ +SfxViewFrame* SfxViewFrame::Current() +{ + return SfxApplication::Get() ? SFX_APP()->Get_Impl()->pViewFrame : NULL; +} + +//-------------------------------------------------------------------- +sal_uInt16 SfxViewFrame::Count() + +/* [Description] + + Returns the number of visable <SfxViewFrame> instances. +*/ + +{ + SfxApplication *pSfxApp = SFX_APP(); + SfxViewFrameArr_Impl& rFrames = pSfxApp->GetViewFrames_Impl(); + const sal_uInt16 nCount = rFrames.Count(); + sal_uInt16 nFound = 0; + for ( sal_uInt16 i = 0; i < nCount; ++i ) + { + SfxViewFrame *pFrame = rFrames[i]; + if ( pFrame->IsVisible() ) + ++nFound; + } + return nFound; +} + +//-------------------------------------------------------------------- +// returns the first window of spec. type viewing the specified doc. +SfxViewFrame* SfxViewFrame::GetFirst +( + const SfxObjectShell* pDoc, + sal_Bool bOnlyIfVisible +) +{ + SfxApplication *pSfxApp = SFX_APP(); + SfxViewFrameArr_Impl &rFrames = pSfxApp->GetViewFrames_Impl(); + + // search for a SfxDocument of the specified type + for ( sal_uInt16 nPos = 0; nPos < rFrames.Count(); ++nPos ) + { + SfxViewFrame *pFrame = rFrames.GetObject(nPos); + if ( ( !pDoc || pDoc == pFrame->GetObjectShell() ) + && ( !bOnlyIfVisible || pFrame->IsVisible() ) + ) + return pFrame; + } + + return 0; +} +//-------------------------------------------------------------------- + +// returns thenext window of spec. type viewing the specified doc. +SfxViewFrame* SfxViewFrame::GetNext +( + const SfxViewFrame& rPrev, + const SfxObjectShell* pDoc, + sal_Bool bOnlyIfVisible +) +{ + SfxApplication *pSfxApp = SFX_APP(); + SfxViewFrameArr_Impl &rFrames = pSfxApp->GetViewFrames_Impl(); + + // refind the specified predecessor + sal_uInt16 nPos; + for ( nPos = 0; nPos < rFrames.Count(); ++nPos ) + if ( rFrames.GetObject(nPos) == &rPrev ) + break; + + // search for a Frame of the specified type + for ( ++nPos; nPos < rFrames.Count(); ++nPos ) + { + SfxViewFrame *pFrame = rFrames.GetObject(nPos); + if ( ( !pDoc || pDoc == pFrame->GetObjectShell() ) + && ( !bOnlyIfVisible || pFrame->IsVisible() ) + ) + return pFrame; + } + return 0; +} + +void SfxViewFrame::CloseHiddenFrames_Impl() +{ + SfxApplication *pSfxApp = SFX_APP(); + SfxViewFrameArr_Impl &rFrames = pSfxApp->GetViewFrames_Impl(); + for ( sal_uInt16 nPos=0; nPos<rFrames.Count(); ) + { + SfxViewFrame *pFrame = rFrames.GetObject(nPos); + if ( !pFrame->IsVisible() ) + pFrame->DoClose(); + else + nPos++; + } +} + +//-------------------------------------------------------------------- +SfxProgress* SfxViewFrame::GetProgress() const +{ + SfxObjectShell *pObjSh = GetObjectShell(); + return pObjSh ? pObjSh->GetProgress() : 0; +} + +//-------------------------------------------------------------------- +void SfxViewFrame::ShowStatusText( const String& /*rText*/) +{ +} + +//-------------------------------------------------------------------- +void SfxViewFrame::HideStatusText() +{ +} + +//-------------------------------------------------------------------- +#ifdef ENABLE_INIMANAGER//MUSTINI +SfxIniManager* SfxViewFrame::GetIniManager() const +{ + return SFX_APP()->GetAppIniManager(); +} +#endif + +//-------------------------------------------------------------------- +void SfxViewFrame::DoAdjustPosSizePixel //! divide on Inner.../Outer... +( + SfxViewShell* pSh, + const Point& rPos, + const Size& rSize +) +{ + DBG_CHKTHIS(SfxViewFrame, 0); + + // Components do not use this Method! + if( pSh && pSh->GetWindow() && !nAdjustPosPixelLock ) + { + nAdjustPosPixelLock++; + if ( pImp->bResizeInToOut ) + pSh->InnerResizePixel( rPos, rSize ); + else + pSh->OuterResizePixel( rPos, rSize ); + nAdjustPosPixelLock--; + } +} + +//======================================================================== + +int SfxViewFrameItem::operator==( const SfxPoolItem &rItem ) const +{ + return PTR_CAST(SfxViewFrameItem, &rItem)->pFrame== pFrame; +} + +//-------------------------------------------------------------------- +String SfxViewFrameItem::GetValueText() const +{ + return String(); +} + +//-------------------------------------------------------------------- +SfxPoolItem* SfxViewFrameItem::Clone( SfxItemPool *) const +{ + return new SfxViewFrameItem( pFrame); +} + +//-------------------------------------------------------------------- +void SfxViewFrame::SetViewShell_Impl( SfxViewShell *pVSh ) + +/* [Description] + + Internal Method to set the current <SfxViewShell> Instance, + that is active int this SfxViewFrame at the moment. +*/ + +{ + SfxShell::SetViewShell_Impl( pVSh ); + + // Hack: InPlaceMode + if ( pVSh ) + pImp->bResizeInToOut = sal_False; +} + +//-------------------------------------------------------------------- +/* [Description] + + The ParentViewFrame of the Containers ViewFrame in the internal InPlace +*/ + +//TODO/LATER: is it still necessary? is there a replacement for GetParentViewFrame_Impl? +SfxViewFrame* SfxViewFrame::GetParentViewFrame_Impl() const +{ + return NULL; +} + +//-------------------------------------------------------------------- +void SfxViewFrame::ForceOuterResize_Impl(sal_Bool bOn) +{ + if ( !pImp->bDontOverwriteResizeInToOut ) + pImp->bResizeInToOut = !bOn; +} + +void SfxViewFrame::ForceInnerResize_Impl(sal_Bool bOn) +{ + pImp->bDontOverwriteResizeInToOut = bOn; +} + +//-------------------------------------------------------------------- +sal_Bool SfxViewFrame::IsResizeInToOut_Impl() const +{ + return pImp->bResizeInToOut; +} +//-------------------------------------------------------------------- +void SfxViewFrame::DoAdjustPosSize( SfxViewShell *pSh, + const Point rPos, const Size &rSize ) +{ + DBG_CHKTHIS(SfxViewFrame, 0); + if( pSh && !nAdjustPosPixelLock ) + { + Window *pWindow = pSh->GetWindow(); + Point aPos = pWindow->LogicToPixel(rPos); + Size aSize = pWindow->LogicToPixel(rSize); + DoAdjustPosSizePixel(pSh, aPos, aSize); + } +} + +//-------------------------------------------------------------------- +void SfxViewFrame::GetDocNumber_Impl() +{ + DBG_ASSERT( GetObjectShell(), "No Document!" ); + GetObjectShell()->SetNamedVisibility_Impl(); + pImp->nDocViewNo = GetObjectShell()->GetNoSet_Impl().GetFreeIndex()+1; +} + +//-------------------------------------------------------------------- + +void SfxViewFrame::Enable( sal_Bool bEnable ) +{ + if ( bEnable != pImp->bEnabled ) + { + pImp->bEnabled = bEnable; + + // e.g. InPlace-Frames have a parent... + SfxViewFrame *pParent = GetParentViewFrame_Impl(); + if ( pParent ) + { + pParent->Enable( bEnable ); + } + else + { + Window *pWindow = &GetFrame().GetTopFrame().GetWindow(); + if ( !bEnable ) + pImp->bWindowWasEnabled = pWindow->IsInputEnabled(); + if ( !bEnable || pImp->bWindowWasEnabled ) + pWindow->EnableInput( bEnable, sal_True ); + } + + // cursor and focus + SfxViewShell* pViewSh = GetViewShell(); + if ( bEnable ) + { + // show cursor + if ( pViewSh ) + pViewSh->ShowCursor(); + } + else + { + // hide cursor + if ( pViewSh ) + pViewSh->ShowCursor(sal_False); + } + } +} + +//-------------------------------------------------------------------- +void SfxViewFrame::Show() + +/* [Description] + + This method makes the Frame-Window visible and before transmitts the + window name. In addition, the document is held. In general one can never + show the window directly! +*/ + +{ + // First lock the objectShell so that UpdateTitle() is valid: + // IsVisible() == sal_True (:#) + if ( xObjSh.Is() ) + { + xObjSh->GetMedium()->GetItemSet()->ClearItem( SID_HIDDEN ); + if ( !pImp->bObjLocked ) + LockObjectShell_Impl( sal_True ); + + // Adjust Doc-Shell titel nummer, get unique view-no + if ( 0 == pImp->nDocViewNo ) + { + GetDocNumber_Impl(); + UpdateTitle(); + } + } + else + UpdateTitle(); + + // Display Frame-window, but only if the ViewFrame has no window of its + // own or if it does not contain a Component + if ( &GetWindow() == &GetFrame().GetWindow() || !GetFrame().HasComponent() ) + GetWindow().Show(); + GetFrame().GetWindow().Show(); + + if ( xObjSh.Is() && xObjSh->Get_Impl()->bHiddenLockedByAPI ) + { + xObjSh->Get_Impl()->bHiddenLockedByAPI = sal_False; + xObjSh->OwnerLock(sal_False); + } +} + +//-------------------------------------------------------------------- +sal_Bool SfxViewFrame::IsVisible() const +{ + return pImp->bObjLocked; +} + +//-------------------------------------------------------------------- +void SfxViewFrame::Hide() +{ + GetWindow().Hide(); + if ( pImp->bObjLocked ) + LockObjectShell_Impl( sal_False ); +} + +//-------------------------------------------------------------------- +void SfxViewFrame::LockObjectShell_Impl( sal_Bool bLock ) +{ + DBG_ASSERT( pImp->bObjLocked != bLock, "Wrong Locked status!" ); + + DBG_ASSERT( GetObjectShell(), "No Document!" ); + GetObjectShell()->OwnerLock(bLock); + pImp->bObjLocked = bLock; +} + +//-------------------------------------------------------------------- +void SfxViewFrame::MakeActive_Impl( sal_Bool bGrabFocus ) +{ + if ( GetViewShell() && !GetFrame().IsClosing_Impl() ) + { + if ( IsVisible() ) + { + if ( GetViewShell() ) + { + sal_Bool bPreview = sal_False; + if ( GetObjectShell()->IsPreview() ) + { + bPreview = sal_True; + } + else + { + SfxViewFrame* pParent = GetParentViewFrame(); + if ( pParent ) + pParent->SetActiveChildFrame_Impl( this ); + } + + SfxViewFrame* pCurrent = SfxViewFrame::Current(); + css::uno::Reference< css::frame::XFrame > xFrame = GetFrame().GetFrameInterface(); + if ( !bPreview ) + { + SetViewFrame( this ); + GetBindings().SetActiveFrame( css::uno::Reference< css::frame::XFrame >() ); + uno::Reference< frame::XFramesSupplier > xSupp( xFrame, uno::UNO_QUERY ); + if ( xSupp.is() ) + xSupp->setActiveFrame( uno::Reference < frame::XFrame >() ); + + css::uno::Reference< css::awt::XWindow > xContainerWindow = xFrame->getContainerWindow(); + Window* pWindow = VCLUnoHelper::GetWindow(xContainerWindow); + if (pWindow && pWindow->HasChildPathFocus() && bGrabFocus) + { + SfxInPlaceClient *pCli = GetViewShell()->GetUIActiveClient(); + if ( ( !pCli || !pCli->IsObjectUIActive() ) && + ( !pCurrent || pCurrent->GetParentViewFrame_Impl() != this ) ) + GetFrame().GrabFocusOnComponent_Impl(); + } + } + else + { + GetBindings().SetDispatcher( GetDispatcher() ); + GetBindings().SetActiveFrame( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame > () ); + GetDispatcher()->Update_Impl( sal_False ); + } + } + } + } +} + +//------------------------------------------------------------------------- + +void SfxViewFrame::SetQuietMode_Impl( sal_Bool bOn ) +{ + GetDispatcher()->SetQuietMode_Impl( bOn ); +} + +//------------------------------------------------------------------------- + +SfxObjectShell* SfxViewFrame::GetObjectShell() +{ + return xObjSh; +} + +const Size& SfxViewFrame::GetMargin_Impl() const +{ + return pImp->aMargin; +} + +void SfxViewFrame::SetActiveChildFrame_Impl( SfxViewFrame *pViewFrame ) +{ + if ( pViewFrame != pImp->pActiveChild ) + { + if ( !pImp->pActiveChild ) + GetDispatcher()->LockUI_Impl( sal_False ); + + pImp->pActiveChild = pViewFrame; + + Reference< XFramesSupplier > xFrame( GetFrame().GetFrameInterface(), UNO_QUERY ); + Reference< XFrame > xActive; + if ( pViewFrame ) + xActive = pViewFrame->GetFrame().GetFrameInterface(); + + if ( xFrame.is() ) // xFrame can be NULL + xFrame->setActiveFrame( xActive ); + } +} + +SfxViewFrame* SfxViewFrame::GetActiveChildFrame_Impl() const +{ + SfxViewFrame *pViewFrame = pImp->pActiveChild; + return pViewFrame; +} + +//-------------------------------------------------------------------- +SfxViewFrame* SfxViewFrame::LoadViewIntoFrame_Impl_NoThrow( const SfxObjectShell& i_rDoc, const Reference< XFrame >& i_rFrame, + const sal_uInt16 i_nViewId, const bool i_bHidden ) +{ + Reference< XFrame > xFrame( i_rFrame ); + bool bOwnFrame = false; + SfxViewShell* pSuccessView = NULL; + try + { + if ( !xFrame.is() ) + { + ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); + Reference < XFrame > xDesktop( aContext.createComponent( "com.sun.star.frame.Desktop" ), UNO_QUERY_THROW ); + + if ( !i_bHidden ) + { + try + { + // if there is a backing component, use it + Reference< XFramesSupplier > xTaskSupplier( xDesktop , css::uno::UNO_QUERY_THROW ); + ::framework::FrameListAnalyzer aAnalyzer( xTaskSupplier, Reference< XFrame >(), ::framework::FrameListAnalyzer::E_BACKINGCOMPONENT ); + + if ( aAnalyzer.m_xBackingComponent.is() ) + xFrame = aAnalyzer.m_xBackingComponent; + } + catch( uno::Exception& ) + {} + } + + if ( !xFrame.is() ) + xFrame.set( xDesktop->findFrame( DEFINE_CONST_UNICODE("_blank"), 0 ), UNO_SET_THROW ); + + bOwnFrame = true; + } + + pSuccessView = LoadViewIntoFrame_Impl( + i_rDoc, + xFrame, + Sequence< PropertyValue >(), // means "reuse existing model's args" + i_nViewId, + i_bHidden + ); + + if ( bOwnFrame && !i_bHidden ) + { + // ensure the frame/window is visible + Reference< XWindow > xContainerWindow( xFrame->getContainerWindow(), UNO_SET_THROW ); + xContainerWindow->setVisible( sal_True ); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + + if ( pSuccessView ) + return pSuccessView->GetViewFrame(); + + if ( bOwnFrame ) + { + try + { + xFrame->dispose(); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } + } + + return NULL; +} + +//-------------------------------------------------------------------- +SfxViewShell* SfxViewFrame::LoadViewIntoFrame_Impl( const SfxObjectShell& i_rDoc, const Reference< XFrame >& i_rFrame, + const Sequence< PropertyValue >& i_rLoadArgs, const sal_uInt16 i_nViewId, + const bool i_bHidden ) +{ + Reference< XModel > xDocument( i_rDoc.GetModel(), UNO_SET_THROW ); + + ::comphelper::NamedValueCollection aTransformLoadArgs( i_rLoadArgs.getLength() ? i_rLoadArgs : xDocument->getArgs() ); + aTransformLoadArgs.put( "Model", xDocument ); + if ( i_nViewId ) + aTransformLoadArgs.put( "ViewId", sal_Int16( i_nViewId ) ); + if ( i_bHidden ) + aTransformLoadArgs.put( "Hidden", i_bHidden ); + else + aTransformLoadArgs.remove( "Hidden" ); + + ::rtl::OUString sURL( RTL_CONSTASCII_USTRINGPARAM( "private:object" ) ); + if ( !sURL.getLength() ) + sURL = i_rDoc.GetFactory().GetFactoryURL(); + + Reference< XComponentLoader > xLoader( i_rFrame, UNO_QUERY_THROW ); + xLoader->loadComponentFromURL( sURL, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_self")), 0, + aTransformLoadArgs.getPropertyValues() ); + + SfxViewShell* pViewShell = SfxViewShell::Get( i_rFrame->getController() ); + ENSURE_OR_THROW( pViewShell, + "SfxViewFrame::LoadViewIntoFrame_Impl: loading an SFX doc into a frame resulted in a non-SFX view - quite impossible" ); + return pViewShell; +} + +//-------------------------------------------------------------------- + +SfxViewFrame* SfxViewFrame::LoadHiddenDocument( SfxObjectShell& i_rDoc, const sal_uInt16 i_nViewId ) +{ + return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, Reference< XFrame >(), i_nViewId, true ); +} + +//-------------------------------------------------------------------- + +SfxViewFrame* SfxViewFrame::LoadDocument( SfxObjectShell& i_rDoc, const sal_uInt16 i_nViewId ) +{ + return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, Reference< XFrame >(), i_nViewId, false ); +} + +//-------------------------------------------------------------------- + +SfxViewFrame* SfxViewFrame::LoadDocumentIntoFrame( SfxObjectShell& i_rDoc, const Reference< XFrame >& i_rTargetFrame, const sal_uInt16 i_nViewId ) +{ + return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, i_rTargetFrame, i_nViewId, false ); +} + +//-------------------------------------------------------------------- + +SfxViewFrame* SfxViewFrame::LoadDocumentIntoFrame( SfxObjectShell& i_rDoc, const SfxFrameItem* i_pFrameItem, const sal_uInt16 i_nViewId ) +{ + return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, i_pFrameItem && i_pFrameItem->GetFrame() ? i_pFrameItem->GetFrame()->GetFrameInterface() : NULL, i_nViewId, false ); +} + +//-------------------------------------------------------------------- +SfxViewFrame* SfxViewFrame::DisplayNewDocument( SfxObjectShell& i_rDoc, const SfxRequest& i_rCreateDocRequest, const sal_uInt16 i_nViewId ) +{ + SFX_REQUEST_ARG( i_rCreateDocRequest, pFrameItem, SfxUnoFrameItem, SID_FILLFRAME, sal_False ); + SFX_REQUEST_ARG( i_rCreateDocRequest, pHiddenItem, SfxBoolItem, SID_HIDDEN, sal_False ); + + return LoadViewIntoFrame_Impl_NoThrow( + i_rDoc, + pFrameItem ? pFrameItem->GetFrame() : NULL, + i_nViewId, + pHiddenItem ? pHiddenItem->GetValue() : false + ); +} + +//-------------------------------------------------------------------- + +SfxViewFrame* SfxViewFrame::Get( const Reference< XController>& i_rController, const SfxObjectShell* i_pDoc ) +{ + if ( !i_rController.is() ) + return NULL; + + const SfxObjectShell* pDoc = i_pDoc; + if ( !pDoc ) + { + Reference< XModel > xDocument( i_rController->getModel() ); + for ( pDoc = SfxObjectShell::GetFirst( 0, false ); + pDoc; + pDoc = SfxObjectShell::GetNext( *pDoc, 0, false ) + ) + { + if ( pDoc->GetModel() == xDocument ) + break; + } + } + + SfxViewFrame* pViewFrame = NULL; + for ( pViewFrame = SfxViewFrame::GetFirst( pDoc, sal_False ); + pViewFrame; + pViewFrame = SfxViewFrame::GetNext( *pViewFrame, pDoc, sal_False ) + ) + { + if ( pViewFrame->GetViewShell()->GetController() == i_rController ) + break; + } + + return pViewFrame; +} + +//-------------------------------------------------------------------- + +void SfxViewFrame::SaveCurrentViewData_Impl( const sal_uInt16 i_nNewViewId ) +{ + SfxViewShell* pCurrentShell = GetViewShell(); + ENSURE_OR_RETURN_VOID( pCurrentShell != NULL, "SfxViewFrame::SaveCurrentViewData_Impl: no current view shell -> no current view data!" ); + + // determine the logical (API) view name + const SfxObjectFactory& rDocFactory( pCurrentShell->GetObjectShell()->GetFactory() ); + const sal_uInt16 nCurViewNo = rDocFactory.GetViewNo_Impl( GetCurViewId(), 0 ); + const String sCurrentViewName = rDocFactory.GetViewFactory( nCurViewNo ).GetAPIViewName(); + const sal_uInt16 nNewViewNo = rDocFactory.GetViewNo_Impl( i_nNewViewId, 0 ); + const String sNewViewName = rDocFactory.GetViewFactory( nNewViewNo ).GetAPIViewName(); + if ( ( sCurrentViewName.Len() == 0 ) || ( sNewViewName.Len() == 0 ) ) + { + // can't say anything about the view, the respective application did not yet migrate its code to + // named view factories => bail out + OSL_FAIL( "SfxViewFrame::SaveCurrentViewData_Impl: views without API names? Shouldn't happen anymore?" ); + return; + } + OSL_ENSURE( !sNewViewName.Equals( sCurrentViewName ), "SfxViewFrame::SaveCurrentViewData_Impl: suspicious: new and old view name are identical!" ); + + // save the view data only when we're moving from a non-print-preview to the print-preview view + if ( !sNewViewName.EqualsAscii( "PrintPreview" ) ) + return; + + // retrieve the view data from the view + Sequence< PropertyValue > aViewData; + pCurrentShell->WriteUserDataSequence( aViewData ); + + try + { + // retrieve view data (for *all* views) from the model + const Reference< XController > xController( pCurrentShell->GetController(), UNO_SET_THROW ); + const Reference< XViewDataSupplier > xViewDataSupplier( xController->getModel(), UNO_QUERY_THROW ); + const Reference< XIndexContainer > xViewData( xViewDataSupplier->getViewData(), UNO_QUERY_THROW ); + + // look up the one view data item which corresponds to our current view, and remove it + const sal_Int32 nCount = xViewData->getCount(); + for ( sal_Int32 i=0; i<nCount; ++i ) + { + const ::comphelper::NamedValueCollection aCurViewData( xViewData->getByIndex(i) ); + ::rtl::OUString sViewId( aCurViewData.getOrDefault( "ViewId", ::rtl::OUString() ) ); + if ( sViewId.getLength() == 0 ) + continue; + + const SfxViewFactory* pViewFactory = rDocFactory.GetViewFactoryByViewName( sViewId ); + if ( pViewFactory == NULL ) + continue; + + if ( pViewFactory->GetOrdinal() == GetCurViewId() ) + { + xViewData->removeByIndex(i); + break; + } + } + + // then replace it with the most recent view data we just obtained + xViewData->insertByIndex( 0, makeAny( aViewData ) ); + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//-------------------------------------------------------------------- + +sal_Bool SfxViewFrame::SwitchToViewShell_Impl +( + sal_uInt16 nViewIdOrNo, /* > 0 + Registration-Id of the View, to which the + the method should switch, for example the one + that will be created. + + == 0 + First use the Default view. */ + + sal_Bool bIsIndex /* sal_True + 'nViewIdOrNo' is no Registration-Id instead + an Index of <SfxViewFrame> in <SfxObjectShell>. + */ +) + +/* [Description] + + Internal Method for switching to another <SfxViewShell> subclass, + which should be created in this SfxMDIFrame. If no SfxViewShell exist + in this SfxMDIFrame, then one will first be created. + + + [Return Value] + + sal_Bool sal_True + requested SfxViewShell was created and a + possibly existing one deleted + + sal_False + SfxViewShell requested could not be created, + the existing SfxViewShell thus continue to exist +*/ + +{ + try + { + ENSURE_OR_THROW( GetObjectShell() != NULL, "not possible without a document" ); + + // if we already have a view shell, remove it + SfxViewShell* pOldSh = GetViewShell(); + OSL_PRECOND( pOldSh, "SfxViewFrame::SwitchToViewShell_Impl: that's called *switch* (not for *initial-load*) for a reason" ); + if ( pOldSh ) + { + // ask wether it can be closed + if ( !pOldSh->PrepareClose( sal_True ) ) + return sal_False; + + // remove sub shells from Dispatcher before switching to new ViewShell + PopShellAndSubShells_Impl( *pOldSh ); + } + + GetBindings().ENTERREGISTRATIONS(); + LockAdjustPosSizePixel(); + + // ID of the new view + SfxObjectFactory& rDocFact = GetObjectShell()->GetFactory(); + const sal_uInt16 nViewId = ( bIsIndex || !nViewIdOrNo ) ? rDocFact.GetViewFactory( nViewIdOrNo ).GetOrdinal() : nViewIdOrNo; + + // save the view data of the old view, so it can be restored later on (when needed) + SaveCurrentViewData_Impl( nViewId ); + + // create and load new ViewShell + SfxViewShell* pNewSh = LoadViewIntoFrame_Impl( + *GetObjectShell(), + GetFrame().GetFrameInterface(), + Sequence< PropertyValue >(), // means "reuse existing model's args" + nViewId, + false + ); + + // allow resize events to be processed + UnlockAdjustPosSizePixel(); + + if ( GetWindow().IsReallyVisible() ) + DoAdjustPosSizePixel( pNewSh, Point(), GetWindow().GetOutputSizePixel() ); + + GetBindings().LEAVEREGISTRATIONS(); + delete pOldSh; + } + catch ( const com::sun::star::uno::Exception& ) + { + // the SfxCode is not able to cope with exceptions thrown while creating views + // the code will crash in the stack unwinding procedure, so we shouldn't let exceptions go through here + DBG_UNHANDLED_EXCEPTION(); + return sal_False; + } + + DBG_ASSERT( SFX_APP()->GetViewFrames_Impl().Count() == SFX_APP()->GetViewShells_Impl().Count(), "Inconsistent view arrays!" ); + return sal_True; +} + +//------------------------------------------------------------------------- +void SfxViewFrame::SetCurViewId_Impl( const sal_uInt16 i_nID ) +{ + pImp->nCurViewId = i_nID; +} + +//------------------------------------------------------------------------- +sal_uInt16 SfxViewFrame::GetCurViewId() const +{ + return pImp->nCurViewId; +} + +//------------------------------------------------------------------------- +void SfxViewFrame::ExecView_Impl +( + SfxRequest& rReq // The executable <SfxRequest> +) + +/* [Description] + + Internal method to run the slot for the <SfxShell> Subclass in the + SfxViewFrame <SVIDL> described slots. +*/ + +{ + DBG_CHKTHIS(SfxViewFrame, 0); + + // If the Shells are just being replaced... + if ( !GetObjectShell() || !GetViewShell() ) + return; + + switch ( rReq.GetSlot() ) + { + case SID_TERMINATE_INPLACEACTIVATION : + { + SfxInPlaceClient* pClient = GetViewShell()->GetUIActiveClient(); + if ( pClient ) + pClient->DeactivateObject(); + break; + } + + case SID_VIEWSHELL: + { + const SfxPoolItem *pItem = 0; + if ( rReq.GetArgs() + && SFX_ITEM_SET == rReq.GetArgs()->GetItemState( SID_VIEWSHELL, sal_False, &pItem ) + ) + { + const sal_uInt16 nViewId = static_cast< const SfxUInt16Item* >( pItem )->GetValue(); + sal_Bool bSuccess = SwitchToViewShell_Impl( nViewId ); + rReq.SetReturnValue( SfxBoolItem( 0, bSuccess ) ); + } + break; + } + + case SID_VIEWSHELL0: + case SID_VIEWSHELL1: + case SID_VIEWSHELL2: + case SID_VIEWSHELL3: + case SID_VIEWSHELL4: + { + const sal_uInt16 nViewNo = rReq.GetSlot() - SID_VIEWSHELL0; + sal_Bool bSuccess = SwitchToViewShell_Impl( nViewNo, sal_True ); + rReq.SetReturnValue( SfxBoolItem( 0, bSuccess ) ); + break; + } + + case SID_NEWWINDOW: + { + // Hack. at the moment a virtual Function + if ( !GetViewShell()->NewWindowAllowed() ) + { + OSL_FAIL( "You should have disabled the 'Window/New Window' slot!" ); + return; + } + + // Get ViewData of FrameSets recursivly. + GetFrame().GetViewData_Impl(); + SfxMedium* pMed = GetObjectShell()->GetMedium(); + + // do not open the new window hidden + pMed->GetItemSet()->ClearItem( SID_HIDDEN ); + + // the view ID (optional arg. TODO: this is currently not supported in the slot definition ...) + SFX_REQUEST_ARG( rReq, pViewIdItem, SfxUInt16Item, SID_VIEW_ID, sal_False ); + const sal_uInt16 nViewId = pViewIdItem ? pViewIdItem->GetValue() : GetCurViewId(); + + Reference < XFrame > xFrame; + // the frame (optional arg. TODO: this is currently not supported in the slot definition ...) + SFX_REQUEST_ARG( rReq, pFrameItem, SfxUnoFrameItem, SID_FILLFRAME, sal_False ); + if ( pFrameItem ) + xFrame = pFrameItem->GetFrame(); + + LoadViewIntoFrame_Impl_NoThrow( *GetObjectShell(), xFrame, nViewId, false ); + + rReq.Done(); + break; + } + + case SID_OBJECT: + { + SFX_REQUEST_ARG( rReq, pItem, SfxUInt16Item, SID_OBJECT, sal_False ); + + SfxViewShell *pViewShell = GetViewShell(); + if ( pViewShell && pItem ) + { + pViewShell->DoVerb( pItem->GetValue() ); + rReq.Done(); + break;; + } + } + } +} + +//------------------------------------------------------------------------- +/* TODO as96863: + This method try to collect informations about the count of currently open documents. + But the algorithm is implemented very simple ... + E.g. hidden documents should be ignored here ... but they are counted. + TODO: export special helper "framework::FrameListAnalyzer" within the framework module + and use it here. +*/ +sal_Bool impl_maxOpenDocCountReached() +{ + static ::rtl::OUString SERVICE_DESKTOP(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop")); + + try + { + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = ::comphelper::getProcessServiceFactory(); + css::uno::Any aVal = ::comphelper::ConfigurationHelper::readDirectKey( + xSMGR, + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.Common/")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Misc")), + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MaxOpenDocuments")), + ::comphelper::ConfigurationHelper::E_READONLY); + + // NIL means: count of allowed documents = infinite ! + if ( ! aVal.hasValue()) + return sal_False; + + sal_Int32 nOpenDocs = 0; + sal_Int32 nMaxDocs = 0; + aVal >>= nMaxDocs; + + css::uno::Reference< css::frame::XFramesSupplier > xDesktop(xSMGR->createInstance(SERVICE_DESKTOP), css::uno::UNO_QUERY_THROW); + css::uno::Reference< css::container::XIndexAccess > xCont (xDesktop->getFrames() , css::uno::UNO_QUERY_THROW); + + sal_Int32 c = xCont->getCount(); + sal_Int32 i = 0; + + for (i=0; i<c; ++i) + { + try + { + css::uno::Reference< css::frame::XFrame > xFrame; + xCont->getByIndex(i) >>= xFrame; + if ( ! xFrame.is()) + continue; + + // a) do not count the help window + if (xFrame->getName().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("OFFICE_HELP_TASK"))) + continue; + + // b) count all other frames + ++nOpenDocs; + } + catch(const css::uno::Exception&) + // A IndexOutOfBoundException can happen in multithreaded + // environments, where any other thread can change this + // container ! + { continue; } + } + + return (nOpenDocs >= nMaxDocs); + } + catch(const css::uno::Exception&) + {} + + // Any internal error is no reason to stop opening documents ! + // Limitation of opening documents is a special "nice to have" feature. + // Otherwhise it can happen, that NO document will be opened ... + return sal_False; +} + +//------------------------------------------------------------------------- +void SfxViewFrame::StateView_Impl +( + SfxItemSet& rSet /* empty <SfxItemSet> with <Which-Ranges>, + which describes the Slot Ids */ +) + +/* [Description] + + This internal methode returns in 'rSet' the Status for the <SfxShell> + Subclass SfxViewFrame in the <SVIDL> described <Slots>. + + Thus exactly those Slots-IDs that are recognized as beeing invalid by Sfx + are included as Which-ranges in 'rSet'. If there exists a mapping for + single slot-IDs of the <SfxItemPool> set in the shell, then the respective + Which-IDs are used so that items can be replaced directly with a working + Core::sun::com::star::script::Engine of the Which-IDs if possible. . +*/ + +{ + DBG_CHKTHIS(SfxViewFrame, 0); + + SfxObjectShell *pDocSh = GetObjectShell(); + + if ( !pDocSh ) + // I'm just on reload and am yielding myself ... + return; + + const sal_uInt16 *pRanges = rSet.GetRanges(); + DBG_ASSERT(pRanges, "Set with no Range"); + while ( *pRanges ) + { + for ( sal_uInt16 nWhich = *pRanges++; nWhich <= *pRanges; ++nWhich ) + { + switch(nWhich) + { + case SID_VIEWSHELL: + { + rSet.Put( SfxUInt16Item( nWhich, pImp->nCurViewId ) ); + break; + } + + case SID_VIEWSHELL0: + case SID_VIEWSHELL1: + case SID_VIEWSHELL2: + case SID_VIEWSHELL3: + case SID_VIEWSHELL4: + { + sal_uInt16 nViewNo = nWhich - SID_VIEWSHELL0; + if ( GetObjectShell()->GetFactory().GetViewFactoryCount() > + nViewNo && !GetObjectShell()->IsInPlaceActive() ) + { + SfxViewFactory &rViewFactory = + GetObjectShell()->GetFactory().GetViewFactory(nViewNo); + rSet.Put( SfxBoolItem( + nWhich, pImp->nCurViewId == rViewFactory.GetOrdinal() ) ); + } + else + rSet.DisableItem( nWhich ); + break; + } + case SID_FRAMETITLE: + { + if( GetFrameType() & SFXFRAME_HASTITLE ) + rSet.Put( SfxStringItem( + SID_FRAMETITLE, pImp->aFrameTitle) ); + else + rSet.DisableItem( nWhich ); + break; + } + + case SID_NEWWINDOW: + { + if ( !GetViewShell()->NewWindowAllowed() + || impl_maxOpenDocCountReached() + ) + rSet.DisableItem( nWhich ); + break; + } + } + } + } +} + +//------------------------------------------------------------------------- +void SfxViewFrame::ToTop() +{ + GetFrame().Appear(); +} + +//------------------------------------------------------------------------- +SfxViewFrame* SfxViewFrame::GetParentViewFrame() const +/* [Description] + + The ParentViewFrame is the ViewFrame of the ParentFrames. +*/ +{ + SfxFrame *pFrame = GetFrame().GetParentFrame(); + return pFrame ? pFrame->GetCurrentViewFrame() : NULL; +} + +//------------------------------------------------------------------------- +SfxFrame& SfxViewFrame::GetFrame() const +/* [Description] + + GetFrame returns the Frame, in which the ViewFrame is located. +*/ +{ + return pImp->rFrame; +} + +//------------------------------------------------------------------------- +SfxViewFrame* SfxViewFrame::GetTopViewFrame() const +{ + return GetFrame().GetTopFrame().GetCurrentViewFrame(); +} + +Window& SfxViewFrame::GetWindow() const +{ + return pImp->pWindow ? *pImp->pWindow : GetFrame().GetWindow(); +} + +sal_Bool SfxViewFrame::DoClose() +{ + return GetFrame().DoClose(); +} + +String SfxViewFrame::GetActualPresentationURL_Impl() const +{ + if ( xObjSh.Is() ) + return xObjSh->GetMedium()->GetName(); + return String(); +} + +void SfxViewFrame::SetModalMode( sal_Bool bModal ) +{ + pImp->bModal = bModal; + if ( xObjSh.Is() ) + { + for ( SfxViewFrame* pFrame = SfxViewFrame::GetFirst( xObjSh ); + !bModal && pFrame; pFrame = SfxViewFrame::GetNext( *pFrame, xObjSh ) ) + bModal = pFrame->pImp->bModal; + xObjSh->SetModalMode_Impl( bModal ); + } +} + +sal_Bool SfxViewFrame::IsInModalMode() const +{ + return pImp->bModal || GetFrame().GetWindow().IsInModalMode(); +} + +void SfxViewFrame::Resize( sal_Bool bForce ) +{ + Size aSize = GetWindow().GetOutputSizePixel(); + if ( bForce || aSize != pImp->aSize ) + { + pImp->aSize = aSize; + SfxViewShell *pShell = GetViewShell(); + if ( pShell ) + { + if ( GetFrame().IsInPlace() ) + { + Point aPoint = GetWindow().GetPosPixel(); + DoAdjustPosSizePixel( pShell, aPoint, aSize ); + } + else + { + DoAdjustPosSizePixel( pShell, Point(), aSize ); + } + } + } +} + +#define LINE_SEP 0x0A + +void CutLines( ::rtl::OUString& rStr, sal_Int32 nStartLine, sal_Int32 nLines, sal_Bool bEraseTrailingEmptyLines ) +{ + sal_Int32 nStartPos = 0; + sal_Int32 nLine = 0; + while ( nLine < nStartLine ) + { + nStartPos = rStr.indexOf( LINE_SEP, nStartPos ); + if( nStartPos == -1 ) + break; + nStartPos++; // not the \n. + nLine++; + } + + DBG_ASSERTWARNING( nStartPos != STRING_NOTFOUND, "CutLines: Start row not found!" ); + + if ( nStartPos != -1 ) + { + sal_Int32 nEndPos = nStartPos; + for ( sal_Int32 i = 0; i < nLines; i++ ) + nEndPos = rStr.indexOf( LINE_SEP, nEndPos+1 ); + + if ( nEndPos == -1 ) // Can happen at the last row. + nEndPos = rStr.getLength(); + else + nEndPos++; + + ::rtl::OUString aEndStr = rStr.copy( nEndPos ); + rStr = rStr.copy( 0, nStartPos ); + rStr += aEndStr; + } + if ( bEraseTrailingEmptyLines ) + { + sal_Int32 n = nStartPos; + sal_Int32 nLen = rStr.getLength(); + while ( ( n < nLen ) && ( rStr.getStr()[ n ] == LINE_SEP ) ) + n++; + + if ( n > nStartPos ) + { + ::rtl::OUString aEndStr = rStr.copy( n ); + rStr = rStr.copy( 0, nStartPos ); + rStr += aEndStr; + } + } +} + +/* + add new recorded dispatch macro script into the application global basic + lib container. It generates a new unique id for it and insert the macro + by using this number as name for the modul + */ +void SfxViewFrame::AddDispatchMacroToBasic_Impl( const ::rtl::OUString& sMacro ) +{ + if ( !sMacro.getLength() ) + return; + + SfxApplication* pSfxApp = SFX_APP(); + SfxRequest aReq( SID_BASICCHOOSER, SFX_CALLMODE_SYNCHRON, pSfxApp->GetPool() ); + aReq.AppendItem( SfxBoolItem(SID_RECORDMACRO,sal_True) ); + const SfxPoolItem* pRet = SFX_APP()->ExecuteSlot( aReq ); + String aScriptURL; + if ( pRet ) + aScriptURL = ((SfxStringItem*)pRet)->GetValue(); + if ( aScriptURL.Len() ) + { + // parse scriptURL + String aLibName; + String aModuleName; + String aMacroName; + String aLocation; + Reference< XMultiServiceFactory > xSMgr = ::comphelper::getProcessServiceFactory(); + Reference< com::sun::star::uri::XUriReferenceFactory > xFactory( xSMgr->createInstance( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uri.UriReferenceFactory")) ), UNO_QUERY ); + if ( xFactory.is() ) + { + Reference< com::sun::star::uri::XVndSunStarScriptUrl > xUrl( xFactory->parse( aScriptURL ), UNO_QUERY ); + if ( xUrl.is() ) + { + // get name + ::rtl::OUString aName = xUrl->getName(); + sal_Unicode cTok = '.'; + sal_Int32 nIndex = 0; + aLibName = aName.getToken( 0, cTok, nIndex ); + if ( nIndex != -1 ) + aModuleName = aName.getToken( 0, cTok, nIndex ); + if ( nIndex != -1 ) + aMacroName = aName.getToken( 0, cTok, nIndex ); + + // get location + ::rtl::OUString aLocKey(RTL_CONSTASCII_USTRINGPARAM("location")); + if ( xUrl->hasParameter( aLocKey ) ) + aLocation = xUrl->getParameter( aLocKey ); + } + } + + BasicManager* pBasMgr = 0; + if ( aLocation.EqualsIgnoreCaseAscii( "application" ) ) + { + // application basic + pBasMgr = pSfxApp->GetBasicManager(); + } + else if ( aLocation.EqualsIgnoreCaseAscii( "document" ) ) + { + pBasMgr = GetObjectShell()->GetBasicManager(); + } + + ::rtl::OUString aOUSource; + if ( pBasMgr) + { + StarBASIC* pBasic = pBasMgr->GetLib( aLibName ); + if ( pBasic ) + { + SbModule* pModule = pBasic->FindModule( aModuleName ); + if ( pModule ) + { + SbMethod* pMethod = (SbMethod*)pModule->GetMethods()->Find( aMacroName, SbxCLASS_METHOD ); + aOUSource = pModule->GetSource32(); + sal_uInt16 nStart, nEnd; + pMethod->GetLineRange( nStart, nEnd ); + sal_uIntPtr nlStart = nStart; + sal_uIntPtr nlEnd = nEnd; + CutLines( aOUSource, nlStart-1, nlEnd-nlStart+1, sal_True ); + } + } + } + + // open lib container and break operation if it couldn't be opened + com::sun::star::uno::Reference< com::sun::star::script::XLibraryContainer > xLibCont; + if ( aLocation.EqualsIgnoreCaseAscii( "application" ) ) + { + xLibCont = SFX_APP()->GetBasicContainer(); + } + else if ( aLocation.EqualsIgnoreCaseAscii( "document" ) ) + { + xLibCont = GetObjectShell()->GetBasicContainer(); + } + + if(!xLibCont.is()) + { + DBG_ERRORFILE("couldn't get access to the basic lib container. Adding of macro isn't possible."); + return; + } + + // get LibraryContainer + com::sun::star::uno::Any aTemp; + com::sun::star::uno::Reference< com::sun::star::container::XNameAccess > xRoot( + xLibCont, + com::sun::star::uno::UNO_QUERY); + + ::rtl::OUString sLib( aLibName ); + com::sun::star::uno::Reference< com::sun::star::container::XNameAccess > xLib; + if(xRoot->hasByName(sLib)) + { + // library must be loaded + aTemp = xRoot->getByName(sLib); + xLibCont->loadLibrary(sLib); + aTemp >>= xLib; + } + else + { + xLib = com::sun::star::uno::Reference< com::sun::star::container::XNameAccess >( + xLibCont->createLibrary(sLib), + com::sun::star::uno::UNO_QUERY); + } + + // pack the macro as direct usable "sub" routine + ::rtl::OUString sCode; + ::rtl::OUStringBuffer sRoutine(10000); + ::rtl::OUString sMacroName( aMacroName ); + sal_Bool bReplace = sal_False; + + // get module + ::rtl::OUString sModule( aModuleName ); + if(xLib->hasByName(sModule)) + { + if ( aOUSource.getLength() ) + { + sRoutine.append( aOUSource ); + } + else + { + aTemp = xLib->getByName(sModule); + aTemp >>= sCode; + sRoutine.append( sCode ); + } + + bReplace = sal_True; + } + + // append new method + sRoutine.appendAscii("\nsub " ); + sRoutine.append (sMacroName ); + sRoutine.appendAscii("\n" ); + sRoutine.append (sMacro ); + sRoutine.appendAscii("\nend sub\n"); + + // create the modul inside the library and insert the macro routine + aTemp <<= sRoutine.makeStringAndClear(); + if ( bReplace ) + { + com::sun::star::uno::Reference< com::sun::star::container::XNameContainer > xModulCont( + xLib, + com::sun::star::uno::UNO_QUERY); + xModulCont->replaceByName(sModule,aTemp); + } + else + { + com::sun::star::uno::Reference< com::sun::star::container::XNameContainer > xModulCont( + xLib, + com::sun::star::uno::UNO_QUERY); + xModulCont->insertByName(sModule,aTemp); + } + + // #i17355# update the Basic IDE + for ( SfxViewShell* pViewShell = SfxViewShell::GetFirst(); pViewShell; pViewShell = SfxViewShell::GetNext( *pViewShell ) ) + { + if ( pViewShell->GetName().EqualsAscii( "BasicIDE" ) ) + { + SfxViewFrame* pViewFrame = pViewShell->GetViewFrame(); + SfxDispatcher* pDispat = pViewFrame ? pViewFrame->GetDispatcher() : NULL; + if ( pDispat ) + { + SfxMacroInfoItem aInfoItem( SID_BASICIDE_ARG_MACROINFO, pBasMgr, aLibName, aModuleName, String(), String() ); + pDispat->Execute( SID_BASICIDE_UPDATEMODULESOURCE, SFX_CALLMODE_SYNCHRON, &aInfoItem, 0L ); + } + } + } + } + else + { + // add code for "session only" macro + } +} + +void SfxViewFrame::MiscExec_Impl( SfxRequest& rReq ) +{ + DBG_MEMTEST(); + switch ( rReq.GetSlot() ) + { + case SID_STOP_RECORDING : + case SID_RECORDMACRO : + { + // try to find any active recorder on this frame + ::rtl::OUString sProperty(RTL_CONSTASCII_USTRINGPARAM("DispatchRecorderSupplier")); + com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xFrame( + GetFrame().GetFrameInterface(), + com::sun::star::uno::UNO_QUERY); + + com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xSet(xFrame,com::sun::star::uno::UNO_QUERY); + com::sun::star::uno::Any aProp = xSet->getPropertyValue(sProperty); + com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorderSupplier > xSupplier; + aProp >>= xSupplier; + com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder > xRecorder; + if (xSupplier.is()) + xRecorder = xSupplier->getDispatchRecorder(); + + sal_Bool bIsRecording = xRecorder.is(); + SFX_REQUEST_ARG( rReq, pItem, SfxBoolItem, SID_RECORDMACRO, sal_False); + if ( pItem && pItem->GetValue() == bIsRecording ) + return; + + if ( xRecorder.is() ) + { + // disable active recording + aProp <<= com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorderSupplier >(); + xSet->setPropertyValue(sProperty,aProp); + + SFX_REQUEST_ARG( rReq, pRecordItem, SfxBoolItem, FN_PARAM_1, sal_False); + if ( !pRecordItem || !pRecordItem->GetValue() ) + // insert script into basic library container of application + AddDispatchMacroToBasic_Impl(xRecorder->getRecordedMacro()); + + xRecorder->endRecording(); + xRecorder = NULL; + GetBindings().SetRecorder_Impl( xRecorder ); + + SetChildWindow( SID_RECORDING_FLOATWINDOW, sal_False ); + if ( rReq.GetSlot() != SID_RECORDMACRO ) + GetBindings().Invalidate( SID_RECORDMACRO ); + } + else if ( rReq.GetSlot() == SID_RECORDMACRO ) + { + // enable recording + com::sun::star::uno::Reference< com::sun::star::lang::XMultiServiceFactory > xFactory( + ::comphelper::getProcessServiceFactory(), + com::sun::star::uno::UNO_QUERY); + + xRecorder = com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorder >( + xFactory->createInstance(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.DispatchRecorder"))), + com::sun::star::uno::UNO_QUERY); + + xSupplier = com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorderSupplier >( + xFactory->createInstance(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.DispatchRecorderSupplier"))), + com::sun::star::uno::UNO_QUERY); + + xSupplier->setDispatchRecorder(xRecorder); + xRecorder->startRecording(xFrame); + aProp <<= xSupplier; + xSet->setPropertyValue(sProperty,aProp); + GetBindings().SetRecorder_Impl( xRecorder ); + SetChildWindow( SID_RECORDING_FLOATWINDOW, sal_True ); + } + + rReq.Done(); + break; + } + + case SID_TOGGLESTATUSBAR: + { + com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xFrame( + GetFrame().GetFrameInterface(), + com::sun::star::uno::UNO_QUERY); + + Reference< com::sun::star::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY ); + Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager; + if ( xPropSet.is() ) + { + try + { + Any aValue = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ))); + aValue >>= xLayoutManager; + } + catch ( Exception& ) + { + } + } + + if ( xLayoutManager.is() ) + { + rtl::OUString aStatusbarResString( RTL_CONSTASCII_USTRINGPARAM( "private:resource/statusbar/statusbar" )); + // Evaluate parameter. + SFX_REQUEST_ARG(rReq, pShowItem, SfxBoolItem, rReq.GetSlot(), sal_False); + sal_Bool bShow( sal_True ); + if ( !pShowItem ) + bShow = xLayoutManager->isElementVisible( aStatusbarResString ); + else + bShow = pShowItem->GetValue(); + + if ( bShow ) + { + xLayoutManager->createElement( aStatusbarResString ); + xLayoutManager->showElement( aStatusbarResString ); + } + else + xLayoutManager->hideElement( aStatusbarResString ); + + if ( !pShowItem ) + rReq.AppendItem( SfxBoolItem( SID_TOGGLESTATUSBAR, bShow ) ); + } + rReq.Done(); + break; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + case SID_WIN_FULLSCREEN: + { + SFX_REQUEST_ARG(rReq, pItem, SfxBoolItem, rReq.GetSlot(), sal_False); + SfxViewFrame *pTop = GetTopViewFrame(); + if ( pTop ) + { + WorkWindow* pWork = (WorkWindow*) pTop->GetFrame().GetTopWindow_Impl(); + if ( pWork ) + { + com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xFrame( + GetFrame().GetFrameInterface(), + com::sun::star::uno::UNO_QUERY); + + Reference< ::com::sun::star::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY ); + Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager; + if ( xPropSet.is() ) + { + try + { + Any aValue = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ))); + aValue >>= xLayoutManager; + } + catch ( Exception& ) + { + } + } + + sal_Bool bNewFullScreenMode = pItem ? pItem->GetValue() : !pWork->IsFullScreenMode(); + if ( bNewFullScreenMode != pWork->IsFullScreenMode() ) + { + Reference< ::com::sun::star::beans::XPropertySet > xLMPropSet( xLayoutManager, UNO_QUERY ); + if ( xLMPropSet.is() ) + { + try + { + xLMPropSet->setPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "HideCurrentUI" )), + makeAny( bNewFullScreenMode )); + } + catch ( ::com::sun::star::beans::UnknownPropertyException& ) + { + } + } + pWork->ShowFullScreenMode( bNewFullScreenMode ); + pWork->SetMenuBarMode( bNewFullScreenMode ? MENUBAR_MODE_HIDE : MENUBAR_MODE_NORMAL ); + GetFrame().GetWorkWindow_Impl()->SetFullScreen_Impl( bNewFullScreenMode ); + if ( !pItem ) + rReq.AppendItem( SfxBoolItem( SID_WIN_FULLSCREEN, bNewFullScreenMode ) ); + rReq.Done(); + } + else + rReq.Ignore(); + } + } + else + rReq.Ignore(); + + GetDispatcher()->Update_Impl( sal_True ); + break; + } + } +} + +void SfxViewFrame::MiscState_Impl(SfxItemSet &rSet) +{ + DBG_MEMTEST(); + + const sal_uInt16 *pRanges = rSet.GetRanges(); + DBG_ASSERT(pRanges && *pRanges, "Set without range"); + while ( *pRanges ) + { + for(sal_uInt16 nWhich = *pRanges++; nWhich <= *pRanges; ++nWhich) + { + switch(nWhich) + { + case SID_CURRENT_URL: + { + // Get the ContainerFrame, when internal InPlace. + SfxViewFrame *pFrame = this; + if ( pFrame->GetParentViewFrame_Impl() ) + pFrame = pFrame->GetParentViewFrame_Impl(); + rSet.Put( SfxStringItem( nWhich, pFrame->GetActualPresentationURL_Impl() ) ); + break; + } + + case SID_RECORDMACRO : + { + SvtMiscOptions aMiscOptions; + const char* pName = GetObjectShell()->GetFactory().GetShortName(); + if ( !aMiscOptions.IsExperimentalMode() || + ( strcmp(pName,"swriter") && strcmp(pName,"scalc") ) ) + { + rSet.DisableItem( nWhich ); + rSet.Put(SfxVisibilityItem(nWhich, sal_False)); + break; + } + + ::rtl::OUString sProperty(RTL_CONSTASCII_USTRINGPARAM("DispatchRecorderSupplier")); + com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xSet( + GetFrame().GetFrameInterface(), + com::sun::star::uno::UNO_QUERY); + + com::sun::star::uno::Any aProp = xSet->getPropertyValue(sProperty); + com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorderSupplier > xSupplier; + if ( aProp >>= xSupplier ) + rSet.Put( SfxBoolItem( nWhich, xSupplier.is() ) ); + else + rSet.DisableItem( nWhich ); + break; + } + + case SID_STOP_RECORDING : + { + SvtMiscOptions aMiscOptions; + const char* pName = GetObjectShell()->GetFactory().GetShortName(); + if ( !aMiscOptions.IsExperimentalMode() || + ( strcmp(pName,"swriter") && strcmp(pName,"scalc") ) ) + { + rSet.DisableItem( nWhich ); + break; + } + + ::rtl::OUString sProperty(RTL_CONSTASCII_USTRINGPARAM("DispatchRecorderSupplier")); + com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xSet( + GetFrame().GetFrameInterface(), + com::sun::star::uno::UNO_QUERY); + + com::sun::star::uno::Any aProp = xSet->getPropertyValue(sProperty); + com::sun::star::uno::Reference< com::sun::star::frame::XDispatchRecorderSupplier > xSupplier; + if ( !(aProp >>= xSupplier) || !xSupplier.is() ) + rSet.DisableItem( nWhich ); + break; + } + + case SID_TOGGLESTATUSBAR: + { + com::sun::star::uno::Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager; + com::sun::star::uno::Reference< com::sun::star::beans::XPropertySet > xSet( + GetFrame().GetFrameInterface(), + com::sun::star::uno::UNO_QUERY); + com::sun::star::uno::Any aProp = xSet->getPropertyValue( + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" )) ); + + if ( !( aProp >>= xLayoutManager )) + rSet.Put( SfxBoolItem( nWhich, sal_False )); + else + { + rtl::OUString aStatusbarResString( RTL_CONSTASCII_USTRINGPARAM( "private:resource/statusbar/statusbar" )); + sal_Bool bShow = xLayoutManager->isElementVisible( aStatusbarResString ); + rSet.Put( SfxBoolItem( nWhich, bShow )); + } + break; + } + + case SID_WIN_FULLSCREEN: + { + SfxViewFrame* pTop = GetTopViewFrame(); + if ( pTop ) + { + WorkWindow* pWork = (WorkWindow*) pTop->GetFrame().GetTopWindow_Impl(); + if ( pWork ) + { + rSet.Put( SfxBoolItem( nWhich, pWork->IsFullScreenMode() ) ); + break; + } + } + + rSet.DisableItem( nWhich ); + break; + } + + case SID_FORMATMENUSTATE : + { + OSL_FAIL("Outdated slot!"); + rSet.DisableItem( nWhich ); + break; + } + + default: + break; + } + } + + ++pRanges; + } +} + +void SfxViewFrame::ChildWindowExecute( SfxRequest &rReq ) + +/* [Description] + + This method can be included in the Execute method for the on- and off- + switching of ChildWindows, to implement this and API-bindings. + + Simply include as 'ExecuteMethod' in the IDL. +*/ + +{ + // Evaluate Parameter + sal_uInt16 nSID = rReq.GetSlot(); + + SFX_REQUEST_ARG(rReq, pShowItem, SfxBoolItem, nSID, sal_False); + if ( nSID == SID_VIEW_DATA_SOURCE_BROWSER ) + { + if (!SvtModuleOptions().IsModuleInstalled(SvtModuleOptions::E_SDATABASE)) + return; + Reference < XFrame > xFrame = GetFrame().GetTopFrame().GetFrameInterface(); + Reference < XFrame > xBeamer( xFrame->findFrame( DEFINE_CONST_UNICODE("_beamer"), FrameSearchFlag::CHILDREN ) ); + sal_Bool bShow = sal_False; + sal_Bool bHasChild = xBeamer.is(); + bShow = pShowItem ? pShowItem->GetValue() : !bHasChild; + if ( pShowItem ) + { + if( bShow == bHasChild ) + return; + } + else + rReq.AppendItem( SfxBoolItem( nSID, bShow ) ); + + if ( !bShow ) + { + SetChildWindow( SID_BROWSER, sal_False ); + } + else + { + ::com::sun::star::util::URL aTargetURL; + aTargetURL.Complete = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".component:DB/DataSourceBrowser")); + Reference < ::com::sun::star::util::XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.util.URLTransformer"))), UNO_QUERY ); + xTrans->parseStrict( aTargetURL ); + + Reference < XDispatchProvider > xProv( xFrame, UNO_QUERY ); + Reference < ::com::sun::star::frame::XDispatch > xDisp; + if ( xProv.is() ) + xDisp = xProv->queryDispatch( aTargetURL, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_beamer")), 31 ); + if ( xDisp.is() ) + { + Sequence < ::com::sun::star::beans::PropertyValue > aArgs(1); + ::com::sun::star::beans::PropertyValue* pArg = aArgs.getArray(); + pArg[0].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Referer")); + pArg[0].Value <<= ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:user")); + xDisp->dispatch( aTargetURL, aArgs ); + } + } + + rReq.Done(); + return; + } + + sal_Bool bShow = sal_False; + sal_Bool bHasChild = HasChildWindow(nSID); + bShow = pShowItem ? pShowItem->GetValue() : !bHasChild; + + // Perform action. + if ( !pShowItem || bShow != bHasChild ) + ToggleChildWindow( nSID ); + + GetBindings().Invalidate( nSID ); + GetDispatcher()->Update_Impl( sal_True ); + + // Record if possible. + if ( nSID == SID_HYPERLINK_DIALOG || nSID == SID_SEARCH_DLG ) + { + rReq.Ignore(); + } + else + { + rReq.AppendItem( SfxBoolItem( nSID, bShow ) ); + rReq.Done(); + } +} + +//-------------------------------------------------------------------- + +void SfxViewFrame::ChildWindowState( SfxItemSet& rState ) + +/* [Description] + + This method can be used in the state method for the on and off-state + of child-windows, in order to implement this. + + Just register the IDL as 'StateMethod'. +*/ + +{ + SfxWhichIter aIter( rState ); + for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() ) + { + if ( nSID == SID_VIEW_DATA_SOURCE_BROWSER ) + { + rState.Put( SfxBoolItem( nSID, HasChildWindow( SID_BROWSER ) ) ); + } + else if ( nSID == SID_HYPERLINK_DIALOG ) + { + const SfxPoolItem* pDummy = NULL; + SfxItemState eState = GetDispatcher()->QueryState( SID_HYPERLINK_SETLINK, pDummy ); + if ( SFX_ITEM_DISABLED == eState ) + rState.DisableItem(nSID); + else + { + if ( KnowsChildWindow(nSID) ) + rState.Put( SfxBoolItem( nSID, HasChildWindow(nSID)) ); + else + rState.DisableItem(nSID); + } + } + else if ( nSID == SID_BROWSER ) + { + Reference < XFrame > xFrame = GetFrame().GetTopFrame().GetFrameInterface()-> + findFrame( DEFINE_CONST_UNICODE("_beamer"), FrameSearchFlag::CHILDREN ); + if ( !xFrame.is() ) + rState.DisableItem( nSID ); + else if ( KnowsChildWindow(nSID) ) + rState.Put( SfxBoolItem( nSID, HasChildWindow(nSID) ) ); + } + else if ( nSID == SID_TASKPANE ) + { + if ( !KnowsChildWindow( nSID ) ) + { + OSL_FAIL( "SID_TASKPANE state requested, but no task pane child window exists for this ID!" ); + rState.DisableItem( nSID ); + } + else if ( !moduleHasToolPanels( *pImp ) ) + { + rState.Put( SfxVisibilityItem( nSID, sal_False ) ); + } + else + { + rState.Put( SfxBoolItem( nSID, HasChildWindow( nSID ) ) ); + } + } + else if ( KnowsChildWindow(nSID) ) + rState.Put( SfxBoolItem( nSID, HasChildWindow(nSID) ) ); + else + rState.DisableItem(nSID); + } +} + +//-------------------------------------------------------------------- +SfxWorkWindow* SfxViewFrame::GetWorkWindow_Impl( sal_uInt16 /*nId*/ ) +{ + SfxWorkWindow* pWork = 0; + pWork = GetFrame().GetWorkWindow_Impl(); + return pWork; +} + +void SfxViewFrame::SetChildWindow(sal_uInt16 nId, sal_Bool bOn, sal_Bool bSetFocus ) +{ + SfxWorkWindow* pWork = GetWorkWindow_Impl( nId ); + if ( pWork ) + pWork->SetChildWindow_Impl( nId, bOn, bSetFocus ); +} + +//-------------------------------------------------------------------- + +void SfxViewFrame::ToggleChildWindow(sal_uInt16 nId) +{ + SfxWorkWindow* pWork = GetWorkWindow_Impl( nId ); + if ( pWork ) + pWork->ToggleChildWindow_Impl( nId, sal_True ); +} + +//-------------------------------------------------------------------- + +sal_Bool SfxViewFrame::HasChildWindow( sal_uInt16 nId ) +{ + SfxWorkWindow* pWork = GetWorkWindow_Impl( nId ); + return pWork ? pWork->HasChildWindow_Impl(nId) : sal_False; +} + +//-------------------------------------------------------------------- + +sal_Bool SfxViewFrame::KnowsChildWindow( sal_uInt16 nId ) +{ + SfxWorkWindow* pWork = GetWorkWindow_Impl( nId ); + return pWork ? pWork->KnowsChildWindow_Impl(nId) : sal_False; +} + +//-------------------------------------------------------------------- + +void SfxViewFrame::ShowChildWindow( sal_uInt16 nId, sal_Bool bVisible ) +{ + SfxWorkWindow* pWork = GetWorkWindow_Impl( nId ); + if ( pWork ) + { + GetDispatcher()->Update_Impl(sal_True); + pWork->ShowChildWindow_Impl(nId, bVisible, sal_True ); + } +} + +//-------------------------------------------------------------------- + +SfxChildWindow* SfxViewFrame::GetChildWindow(sal_uInt16 nId) +{ + SfxWorkWindow* pWork = GetWorkWindow_Impl( nId ); + return pWork ? pWork->GetChildWindow_Impl(nId) : NULL; +} + +void SfxViewFrame::UpdateDocument_Impl() +{ + SfxObjectShell* pDoc = GetObjectShell(); + if ( pDoc->IsLoadingFinished() ) + pDoc->CheckSecurityOnLoading_Impl(); + + // check if document depends on a template + pDoc->UpdateFromTemplate_Impl(); +} + +void SfxViewFrame::SetViewFrame( SfxViewFrame* pFrame ) +{ + SFX_APP()->SetViewFrame_Impl( pFrame ); +} + +// --------------------------------------------------------------------------------------------------------------------- +void SfxViewFrame::ActivateToolPanel( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& i_rFrame, const ::rtl::OUString& i_rPanelURL ) +{ + SolarMutexGuard aGuard; + + // look up the SfxFrame for the given XFrame + SfxFrame* pFrame = NULL; + for ( pFrame = SfxFrame::GetFirst(); pFrame; pFrame = SfxFrame::GetNext( *pFrame ) ) + { + if ( pFrame->GetFrameInterface() == i_rFrame ) + break; + } + SfxViewFrame* pViewFrame = pFrame ? pFrame->GetCurrentViewFrame() : NULL; + ENSURE_OR_RETURN_VOID( pViewFrame != NULL, "SfxViewFrame::ActivateToolPanel: did not find an SfxFrame for the given XFrame!" ); + + pViewFrame->ActivateToolPanel_Impl( i_rPanelURL ); +} + +// --------------------------------------------------------------------------------------------------------------------- +void SfxViewFrame::ActivateToolPanel_Impl( const ::rtl::OUString& i_rPanelURL ) +{ + // ensure the task pane is visible + ENSURE_OR_RETURN_VOID( KnowsChildWindow( SID_TASKPANE ), "SfxViewFrame::ActivateToolPanel: this frame/module does not allow for a task pane!" ); + if ( !HasChildWindow( SID_TASKPANE ) ) + ToggleChildWindow( SID_TASKPANE ); + + SfxChildWindow* pTaskPaneChildWindow = GetChildWindow( SID_TASKPANE ); + ENSURE_OR_RETURN_VOID( pTaskPaneChildWindow, "SfxViewFrame::ActivateToolPanel_Impl: just switched it on, but it is not there!" ); + + ::sfx2::ITaskPaneToolPanelAccess* pPanelAccess = dynamic_cast< ::sfx2::ITaskPaneToolPanelAccess* >( pTaskPaneChildWindow ); + ENSURE_OR_RETURN_VOID( pPanelAccess, "SfxViewFrame::ActivateToolPanel_Impl: task pane child window does not implement a required interface!" ); + pPanelAccess->ActivateToolPanel( i_rPanelURL ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/viewfrm2.cxx b/sfx2/source/view/viewfrm2.cxx new file mode 100644 index 000000000000..57c64187a839 --- /dev/null +++ b/sfx2/source/view/viewfrm2.cxx @@ -0,0 +1,516 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#include "impviewframe.hxx" +#include "statcach.hxx" +#include "sfx2/viewfac.hxx" +#include "workwin.hxx" + +#include "sfx2/app.hxx" +#include "sfx2/bindings.hxx" +#include "sfx2/ctrlitem.hxx" +#include "sfx2/dispatch.hxx" +#include "sfx2/docfac.hxx" +#include "sfx2/docfile.hxx" +#include "sfx2/objitem.hxx" +#include "sfx2/objsh.hxx" +#include "sfx2/request.hxx" +#include "sfx2/viewfrm.hxx" +#include "sfx2/viewsh.hxx" + +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/beans/XMaterialHolder.hpp> +#include <com/sun/star/util/XCloseable.hpp> + +#include <comphelper/componentcontext.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/processfactory.hxx> +#include <svtools/asynclink.hxx> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <svl/rectitem.hxx> +#include <svl/stritem.hxx> +#include <tools/diagnose_ex.h> +#include <tools/urlobj.hxx> +#include <unotools/bootstrap.hxx> +#include <unotools/configmgr.hxx> +#include <vcl/window.hxx> + +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; + +//------------------------------------------------------------------------ + +static ::rtl::OUString GetModuleName_Impl( const ::rtl::OUString& sDocService ) +{ + uno::Reference< container::XNameAccess > xMM( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.ModuleManager"))), uno::UNO_QUERY ); + ::rtl::OUString sVar; + if ( !xMM.is() ) + return sVar; + + try + { + ::comphelper::NamedValueCollection aAnalyzer( xMM->getByName( sDocService ) ); + sVar = aAnalyzer.getOrDefault( "ooSetupFactoryUIName", ::rtl::OUString() ); + } + catch( uno::Exception& ) + { + sVar = ::rtl::OUString(); + } + + return sVar; +} + +//-------------------------------------------------------------------- +void SfxFrameViewWindow_Impl::StateChanged( StateChangedType nStateChange ) +{ + if ( nStateChange == STATE_CHANGE_INITSHOW ) + { + SfxObjectShell* pDoc = pFrame->GetObjectShell(); + if ( pDoc && !pFrame->IsVisible() ) + pFrame->Show(); + + pFrame->Resize(); + } + else + Window::StateChanged( nStateChange ); +} + +void SfxFrameViewWindow_Impl::Resize() +{ + if ( IsReallyVisible() || IsReallyShown() || GetOutputSizePixel().Width() ) + pFrame->Resize(); +} + +static String _getTabString() +{ + String result; + + Reference < XMaterialHolder > xHolder( + ::comphelper::getProcessServiceFactory()->createInstance( + DEFINE_CONST_UNICODE("com.sun.star.tab.tabreg") ), UNO_QUERY ); + if (xHolder.is()) + { + rtl::OUString aTabString; + Sequence< NamedValue > sMaterial; + if (xHolder->getMaterial() >>= sMaterial) { + for (int i=0; i < sMaterial.getLength(); i++) { + if ((sMaterial[i].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("title"))) && + (sMaterial[i].Value >>= aTabString)) + { + result += ' '; + result += String(aTabString); + } + } + } + } + return result; +} + +//======================================================================== + +//-------------------------------------------------------------------- +String SfxViewFrame::UpdateTitle() + +/* [Description] + + With this method, can the SfxViewFrame be forced to immediately provide + the new title from the <SfxObjectShell>. + + [Note] + + This is for example necessary if one listens to the SfxObjectShell as + SfxListener and then react on the <SfxSimpleHint> SFX_HINT_TITLECHANGED, + then query the title of his views. However these views (SfxTopViewFrames) + are also SfxListener and because the order of notifications might not be + fixed, the title update will be enforced in advance. + + [Example] + + void SwDocShell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) + { + if ( rHint.IsA(TYPE(SfxSimpleHint)) ) + { + switch( ( (SfxSimpleHint&) rHint ).GetId() ) + { + case SFX_HINT_TITLECHANGED: + for ( SfxViewFrame *pTop = SfxViewFrame::GetFirst( this ); + pTop; + pTop = SfxViewFrame::GetNext( this ); + { + pTop->UpdateTitle(); + ... pTop->GetName() ... + } + break; + ... + } + } + } +*/ + +{ + DBG_CHKTHIS(SfxViewFrame, 0); + + const SfxObjectFactory &rFact = GetObjectShell()->GetFactory(); + pImp->aFactoryName = String::CreateFromAscii( rFact.GetShortName() ); + + SfxObjectShell *pObjSh = GetObjectShell(); + if ( !pObjSh ) + return String(); + + + const SfxMedium *pMedium = pObjSh->GetMedium(); + String aURL; + GetFrame(); // -Wall required?? + if ( pObjSh->HasName() ) + { + INetURLObject aTmp( pMedium->GetName() ); + aURL = aTmp.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET ); + } + + if ( aURL != pImp->aActualURL ) + // URL has changed + pImp->aActualURL = aURL; + + // Is there another view? + sal_uInt16 nViews=0; + for ( SfxViewFrame *pView= GetFirst(pObjSh); + pView && nViews<2; + pView = GetNext(*pView,pObjSh) ) + if ( ( pView->GetFrameType() & SFXFRAME_HASTITLE ) && + !IsDowning_Impl()) + nViews++; + + // Window Title + String aTitle; + if ( nViews == 2 || pImp->nDocViewNo > 1 ) + // Then attach the number + aTitle = pObjSh->UpdateTitle( NULL, pImp->nDocViewNo ); + else + aTitle = pObjSh->UpdateTitle(); + + // SbxObjects name + String aSbxName = pObjSh->SfxShell::GetName(); + if ( IsVisible() ) + { + aSbxName += ':'; + aSbxName += String::CreateFromInt32(pImp->nDocViewNo); + } + + SetName( aSbxName ); + pImp->aFrameTitle = aTitle; + GetBindings().Invalidate( SID_FRAMETITLE ); + GetBindings().Invalidate( SID_CURRENT_URL ); + + ::rtl::OUString aProductName; + ::utl::ConfigManager::GetDirectConfigProperty(::utl::ConfigManager::PRODUCTNAME) >>= aProductName; + + aTitle += String::CreateFromAscii( " - " ); + aTitle += String(aProductName); + aTitle += ' '; + ::rtl::OUString aDocServiceName( GetObjectShell()->GetFactory().GetDocumentServiceName() ); + aTitle += String( GetModuleName_Impl( aDocServiceName ) ); +#ifdef DBG_UTIL + ::rtl::OUString aDefault; + aTitle += DEFINE_CONST_UNICODE(" ["); + String aVerId( utl::Bootstrap::getBuildIdData( aDefault )); + aTitle += aVerId; + aTitle += ']'; +#endif + + // append TAB string if available + aTitle += _getTabString(); + + GetBindings().Invalidate( SID_NEWDOCDIRECT ); + + return aTitle; +} + +void SfxViewFrame::Exec_Impl(SfxRequest &rReq ) +{ + // If presently the shells are replaced... + if ( !GetObjectShell() || !GetViewShell() ) + return; + + switch ( rReq.GetSlot() ) + { + case SID_SHOWPOPUPS : + { + SFX_REQUEST_ARG(rReq, pShowItem, SfxBoolItem, SID_SHOWPOPUPS, sal_False); + sal_Bool bShow = pShowItem ? pShowItem->GetValue() : sal_True; + SFX_REQUEST_ARG(rReq, pIdItem, SfxUInt16Item, SID_CONFIGITEMID, sal_False); + sal_uInt16 nId = pIdItem ? pIdItem->GetValue() : 0; + + SfxWorkWindow *pWorkWin = GetFrame().GetWorkWindow_Impl(); + if ( bShow ) + { + // First, make the floats viewable + pWorkWin->MakeChildsVisible_Impl( bShow ); + GetDispatcher()->Update_Impl( sal_True ); + + // Then view it + GetBindings().HidePopups( !bShow ); + } + else + { + // Hide all + SfxBindings *pBind = &GetBindings(); + while ( pBind ) + { + pBind->HidePopupCtrls_Impl( !bShow ); + pBind = pBind->GetSubBindings_Impl(); + } + + pWorkWin->HidePopups_Impl( !bShow, sal_True, nId ); + pWorkWin->MakeChildsVisible_Impl( bShow ); + } + + Invalidate( rReq.GetSlot() ); + rReq.Done(); + break; + } + + case SID_ACTIVATE: + { + MakeActive_Impl( sal_True ); + rReq.SetReturnValue( SfxObjectItem( 0, this ) ); + break; + } + + case SID_NEWDOCDIRECT : + { + SFX_REQUEST_ARG( rReq, pFactoryItem, SfxStringItem, SID_NEWDOCDIRECT, sal_False); + String aFactName; + if ( pFactoryItem ) + aFactName = pFactoryItem->GetValue(); + else if ( pImp->aFactoryName.Len() ) + aFactName = pImp->aFactoryName; + else + { + OSL_FAIL("Missing argument!"); + break; + } + + SfxRequest aReq( SID_OPENDOC, SFX_CALLMODE_SYNCHRON, GetPool() ); + String aFact = String::CreateFromAscii("private:factory/"); + aFact += aFactName; + aReq.AppendItem( SfxStringItem( SID_FILE_NAME, aFact ) ); + aReq.AppendItem( SfxFrameItem( SID_DOCFRAME, &GetFrame() ) ); + aReq.AppendItem( SfxStringItem( SID_TARGETNAME, String::CreateFromAscii( "_blank" ) ) ); + SFX_APP()->ExecuteSlot( aReq ); + const SfxViewFrameItem* pItem = PTR_CAST( SfxViewFrameItem, aReq.GetReturnValue() ); + if ( pItem ) + rReq.SetReturnValue( SfxFrameItem( 0, pItem->GetFrame() ) ); + break; + } + + case SID_CLOSEWIN: + { + // disable CloseWin, if frame is not a task + Reference < XCloseable > xTask( GetFrame().GetFrameInterface(), UNO_QUERY ); + if ( !xTask.is() ) + break; + + if ( GetViewShell()->PrepareClose() ) + { + // More Views on the same Document? + SfxObjectShell *pDocSh = GetObjectShell(); + int bOther = sal_False; + for ( const SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocSh ); + !bOther && pFrame; + pFrame = SfxViewFrame::GetNext( *pFrame, pDocSh ) ) + bOther = (pFrame != this); + + // Document only needs to be queried, if no other View present. + sal_Bool bClosed = sal_False; + sal_Bool bUI = sal_True; + if ( ( bOther || pDocSh->PrepareClose( bUI ) ) ) + { + if ( !bOther ) + pDocSh->SetModified( sal_False ); + rReq.Done(); // Must call this before Close()! + bClosed = sal_False; + try + { + xTask->close(sal_True); + bClosed = sal_True; + } + catch( CloseVetoException& ) + { + bClosed = sal_False; + } + } + + rReq.SetReturnValue( SfxBoolItem( rReq.GetSlot(), bClosed )); + } + return; + } + } + + rReq.Done(); +} + +void SfxViewFrame::GetState_Impl( SfxItemSet &rSet ) +{ + SfxObjectShell *pDocSh = GetObjectShell(); + + if ( !pDocSh ) + return; + + const sal_uInt16 *pRanges = rSet.GetRanges(); + DBG_ASSERT(pRanges, "Set without Range"); + while ( *pRanges ) + { + for ( sal_uInt16 nWhich = *pRanges++; nWhich <= *pRanges; ++nWhich ) + { + switch(nWhich) + { + case SID_NEWDOCDIRECT : + { + if ( pImp->aFactoryName.Len() ) + { + String aFact = String::CreateFromAscii("private:factory/"); + aFact += pImp->aFactoryName; + rSet.Put( SfxStringItem( nWhich, aFact ) ); + } + break; + } + + case SID_NEWWINDOW: + rSet.DisableItem(nWhich); + break; + + case SID_CLOSEWIN: + { + // disable CloseWin, if frame is not a task + Reference < XCloseable > xTask( GetFrame().GetFrameInterface(), UNO_QUERY ); + if ( !xTask.is() ) + rSet.DisableItem(nWhich); + break; + } + + case SID_SHOWPOPUPS : + break; + + case SID_OBJECT: + if ( GetViewShell() && GetViewShell()->GetVerbs().getLength() && !GetObjectShell()->IsInPlaceActive() ) + { + uno::Any aAny; + aAny <<= GetViewShell()->GetVerbs(); + rSet.Put( SfxUnoAnyItem( sal_uInt16( SID_OBJECT ), aAny ) ); + } + else + rSet.DisableItem( SID_OBJECT ); + break; + + default: + OSL_FAIL( "invalid message-id" ); + } + } + ++pRanges; + } +} + +void SfxViewFrame::INetExecute_Impl( SfxRequest &rRequest ) +{ + sal_uInt16 nSlotId = rRequest.GetSlot(); + switch( nSlotId ) + { + case SID_BROWSE_FORWARD: + case SID_BROWSE_BACKWARD: + OSL_FAIL( "SfxViewFrame::INetExecute_Impl: SID_BROWSE_FORWARD/BACKWARD are dead!" ); + break; + case SID_CREATELINK: + { +/*! (pb) we need new implementation to create a link +*/ + break; + } + case SID_FOCUSURLBOX: + { + SfxStateCache *pCache = GetBindings().GetAnyStateCache_Impl( SID_OPENURL ); + if( pCache ) + { + SfxControllerItem* pCtrl = pCache->GetItemLink(); + while( pCtrl ) + { + pCtrl->StateChanged( SID_FOCUSURLBOX, SFX_ITEM_UNKNOWN, 0 ); + pCtrl = pCtrl->GetItemLink(); + } + } + } + } + + // Recording + rRequest.Done(); +} + +void SfxViewFrame::INetState_Impl( SfxItemSet &rItemSet ) +{ + rItemSet.DisableItem( SID_BROWSE_FORWARD ); + rItemSet.DisableItem( SID_BROWSE_BACKWARD ); + + // Add/SaveToBookmark at BASIC-IDE, QUERY-EDITOR etc. disable + SfxObjectShell *pDocSh = GetObjectShell(); + sal_Bool bPseudo = pDocSh && !( pDocSh->GetFactory().GetFlags() & SFXOBJECTSHELL_HASOPENDOC ); + sal_Bool bEmbedded = pDocSh && pDocSh->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED; + if ( !pDocSh || bPseudo || bEmbedded || !pDocSh->HasName() ) + rItemSet.DisableItem( SID_CREATELINK ); +} + +void SfxViewFrame::SetZoomFactor( const Fraction &rZoomX, const Fraction &rZoomY ) +{ + GetViewShell()->SetZoomFactor( rZoomX, rZoomY ); +} + +void SfxViewFrame::Activate( sal_Bool bMDI ) +{ + DBG_ASSERT(GetViewShell(), "No Shell"); + if ( bMDI ) + pImp->bActive = sal_True; +//(mba): here maybe as in Beanframe NotifyEvent ?! +} + +void SfxViewFrame::Deactivate( sal_Bool bMDI ) +{ + DBG_ASSERT(GetViewShell(), "No Shell"); + if ( bMDI ) + pImp->bActive = sal_False; +//(mba): here maybe as in Beanframe NotifyEvent ?! +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/viewimp.hxx b/sfx2/source/view/viewimp.hxx new file mode 100644 index 000000000000..edd5495a33ef --- /dev/null +++ b/sfx2/source/view/viewimp.hxx @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SFX_VIEWIMP_HXX +#define SFX_VIEWIMP_HXX + +// include --------------------------------------------------------------- + +#include <basic/sbxobj.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/viewfrm.hxx> // SvBorder +#include <osl/mutex.hxx> +#include <cppuhelper/interfacecontainer.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <svtools/acceleratorexecute.hxx> +#include <rtl/ref.hxx> +#include <vcl/print.hxx> +#include <queue> + +// forward --------------------------------------------------------------- + +class SfxOfficeDispatch; +class SfxBaseController; + +typedef SfxShell* SfxShellPtr_Impl; +SV_DECL_PTRARR( SfxShellArr_Impl, SfxShellPtr_Impl, 4, 4 ) + +class SfxClipboardChangeListener; + +struct SfxViewShell_Impl +{ + ::osl::Mutex aMutex; + ::cppu::OInterfaceContainerHelper aInterceptorContainer; + bool m_bControllerSet; + SfxShellArr_Impl aArr; + SvBorder aBorder; + Size aOptimalSize; + Size aMargin; + sal_uInt16 m_nPrinterLocks; + bool m_bCanPrint; + bool m_bHasPrintOptions; + bool m_bPlugInsActive; + bool m_bIsShowView; + // FIXME UNUSED ??? + //bool m_bOwnsMenu; + bool m_bGotOwnership; + bool m_bGotFrameOwnership; + SfxScrollingMode m_eScroll; + sal_uInt16 m_nFamily; + ::rtl::Reference<SfxBaseController> m_pController; + ::std::auto_ptr< ::svt::AcceleratorExecute > m_pAccExec; + com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > aPrintOpts; + ::rtl::Reference< SfxClipboardChangeListener > xClipboardListener; + ::boost::shared_ptr< vcl::PrinterController > m_pPrinterController; + + SfxViewShell_Impl(sal_uInt16 const nFlags); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/viewprn.cxx b/sfx2/source/view/viewprn.cxx new file mode 100644 index 000000000000..877005eb908c --- /dev/null +++ b/sfx2/source/view/viewprn.cxx @@ -0,0 +1,938 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +#include <com/sun/star/document/XDocumentProperties.hpp> +#include <com/sun/star/view/PrintableState.hpp> +#include "com/sun/star/view/XRenderable.hpp" + +#include <svl/itempool.hxx> +#include <vcl/msgbox.hxx> +#include <svtools/prnsetup.hxx> +#include <svl/flagitem.hxx> +#include <svl/stritem.hxx> +#include <svl/intitem.hxx> +#include <svl/eitem.hxx> +#include <sfx2/app.hxx> +#include <unotools/useroptions.hxx> +#include <unotools/printwarningoptions.hxx> +#include <tools/datetime.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/objface.hxx> +#include <sfx2/viewsh.hxx> +#include "viewimp.hxx" +#include <sfx2/viewfrm.hxx> +#include <sfx2/prnmon.hxx> +#include "sfx2/sfxresid.hxx" +#include <sfx2/request.hxx> +#include <sfx2/objsh.hxx> +#include "sfxtypes.hxx" +#include <sfx2/event.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/docfilt.hxx> + +#include "toolkit/awt/vclxdevice.hxx" + +#include "view.hrc" +#include "helpid.hrc" + +using namespace com::sun::star; +using namespace com::sun::star::uno; + +TYPEINIT1(SfxPrintingHint, SfxHint); + +// ----------------------------------------------------------------------- +class SfxPrinterController : public vcl::PrinterController, public SfxListener +{ + Any maCompleteSelection; + Any maSelection; + Reference< view::XRenderable > mxRenderable; + mutable Printer* mpLastPrinter; + mutable Reference<awt::XDevice> mxDevice; + SfxViewShell* mpViewShell; + SfxObjectShell* mpObjectShell; + sal_Bool m_bOrigStatus; + sal_Bool m_bNeedsChange; + sal_Bool m_bApi; + sal_Bool m_bTempPrinter; + util::DateTime m_aLastPrinted; + ::rtl::OUString m_aLastPrintedBy; + + Sequence< beans::PropertyValue > getMergedOptions() const; + const Any& getSelectionObject() const; +public: + SfxPrinterController( const boost::shared_ptr<Printer>& i_rPrinter, + const Any& i_rComplete, + const Any& i_rSelection, + const Any& i_rViewProp, + const Reference< view::XRenderable >& i_xRender, + sal_Bool i_bApi, sal_Bool i_bDirect, + SfxViewShell* pView, + const uno::Sequence< beans::PropertyValue >& rProps + ); + + virtual ~SfxPrinterController(); + virtual void Notify( SfxBroadcaster&, const SfxHint& ); + + virtual int getPageCount() const; + virtual Sequence< beans::PropertyValue > getPageParameters( int i_nPage ) const; + virtual void printPage( int i_nPage ) const; + virtual void jobStarted(); + virtual void jobFinished( com::sun::star::view::PrintableState ); +}; + +SfxPrinterController::SfxPrinterController( const boost::shared_ptr<Printer>& i_rPrinter, + const Any& i_rComplete, + const Any& i_rSelection, + const Any& i_rViewProp, + const Reference< view::XRenderable >& i_xRender, + sal_Bool i_bApi, sal_Bool i_bDirect, + SfxViewShell* pView, + const uno::Sequence< beans::PropertyValue >& rProps + ) + : PrinterController( i_rPrinter) + , maCompleteSelection( i_rComplete ) + , maSelection( i_rSelection ) + , mxRenderable( i_xRender ) + , mpLastPrinter( NULL ) + , mpViewShell( pView ) + , mpObjectShell(0) + , m_bOrigStatus( sal_False ) + , m_bNeedsChange( sal_False ) + , m_bApi(i_bApi) + , m_bTempPrinter( i_rPrinter.get() != NULL ) +{ + if ( mpViewShell ) + { + StartListening( *mpViewShell ); + mpObjectShell = mpViewShell->GetObjectShell(); + StartListening( *mpObjectShell ); + } + + // initialize extra ui options + if( mxRenderable.is() ) + { + for (sal_Int32 nProp=0; nProp<rProps.getLength(); nProp++) + setValue( rProps[nProp].Name, rProps[nProp].Value ); + + Sequence< beans::PropertyValue > aRenderOptions( 3 ); + aRenderOptions[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ExtraPrintUIOptions" ) ); + aRenderOptions[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "View" ) ); + aRenderOptions[1].Value = i_rViewProp; + aRenderOptions[2].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsPrinter" ) ); + aRenderOptions[2].Value <<= sal_True; + try + { + Sequence< beans::PropertyValue > aRenderParms( mxRenderable->getRenderer( 0 , getSelectionObject(), aRenderOptions ) ); + int nProps = aRenderParms.getLength(); + for( int i = 0; i < nProps; i++ ) + { + if( aRenderParms[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ExtraPrintUIOptions" ) ) ) + { + Sequence< beans::PropertyValue > aUIProps; + aRenderParms[i].Value >>= aUIProps; + setUIOptions( aUIProps ); + break; + } + } + } + catch( lang::IllegalArgumentException& ) + { + // the first renderer should always be available for the UI options, + // but catch the exception to be safe + } + } + + // set some job parameters + setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsApi" ) ), makeAny( i_bApi ) ); + setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDirect" ) ), makeAny( i_bDirect ) ); + setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsPrinter" ) ), makeAny( sal_True ) ); + setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "View" ) ), i_rViewProp ); +} + +void SfxPrinterController::Notify( SfxBroadcaster& , const SfxHint& rHint ) +{ + if ( rHint.IsA(TYPE(SfxSimpleHint)) ) + { + if ( ((SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + EndListening(*mpViewShell); + EndListening(*mpObjectShell); + mpViewShell = 0; + mpObjectShell = 0; + } + } +} + +SfxPrinterController::~SfxPrinterController() +{ +} + +const Any& SfxPrinterController::getSelectionObject() const +{ + const beans::PropertyValue* pVal = getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintSelectionOnly" ) ) ); + if( pVal ) + { + sal_Bool bSel = sal_False; + pVal->Value >>= bSel; + return bSel ? maSelection : maCompleteSelection; + } + + sal_Int32 nChoice = 0; + pVal = getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintContent" ) ) ); + if( pVal ) + pVal->Value >>= nChoice; + return (nChoice > 1) ? maSelection : maCompleteSelection; +} + +Sequence< beans::PropertyValue > SfxPrinterController::getMergedOptions() const +{ + boost::shared_ptr<Printer> pPrinter( getPrinter() ); + if( pPrinter.get() != mpLastPrinter ) + { + mpLastPrinter = pPrinter.get(); + VCLXDevice* pXDevice = new VCLXDevice(); + pXDevice->SetOutputDevice( mpLastPrinter ); + mxDevice = Reference< awt::XDevice >( pXDevice ); + } + + Sequence< beans::PropertyValue > aRenderOptions( 1 ); + aRenderOptions[ 0 ].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RenderDevice" ) ); + aRenderOptions[ 0 ].Value <<= mxDevice; + + aRenderOptions = getJobProperties( aRenderOptions ); + return aRenderOptions; +} + +int SfxPrinterController::getPageCount() const +{ + int nPages = 0; + boost::shared_ptr<Printer> pPrinter( getPrinter() ); + if( mxRenderable.is() && pPrinter ) + { + Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() ); + nPages = mxRenderable->getRendererCount( getSelectionObject(), aJobOptions ); + } + return nPages; +} + +Sequence< beans::PropertyValue > SfxPrinterController::getPageParameters( int i_nPage ) const +{ + boost::shared_ptr<Printer> pPrinter( getPrinter() ); + Sequence< beans::PropertyValue > aResult; + + if( mxRenderable.is() && pPrinter ) + { + Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() ); + try + { + aResult = mxRenderable->getRenderer( i_nPage, getSelectionObject(), aJobOptions ); + } + catch( lang::IllegalArgumentException& ) + { + } + } + return aResult; +} + +void SfxPrinterController::printPage( int i_nPage ) const +{ + boost::shared_ptr<Printer> pPrinter( getPrinter() ); + if( mxRenderable.is() && pPrinter ) + { + Sequence< beans::PropertyValue > aJobOptions( getMergedOptions() ); + try + { + mxRenderable->render( i_nPage, getSelectionObject(), aJobOptions ); + } + catch( lang::IllegalArgumentException& ) + { + // don't care enough about nonexistant page here + // to provoke a crash + } + } +} + +void SfxPrinterController::jobStarted() +{ + if ( mpObjectShell ) + { + m_bOrigStatus = mpObjectShell->IsEnableSetModified(); + + // check configuration: shall update of printing information in DocInfo set the document to "modified"? + if ( m_bOrigStatus && !SvtPrintWarningOptions().IsModifyDocumentOnPrintingAllowed() ) + { + mpObjectShell->EnableSetModified( sal_False ); + m_bNeedsChange = sal_True; + } + + // refresh document info + uno::Reference<document::XDocumentProperties> xDocProps(mpObjectShell->getDocProperties()); + m_aLastPrintedBy = xDocProps->getPrintedBy(); + m_aLastPrinted = xDocProps->getPrintDate(); + + xDocProps->setPrintedBy( mpObjectShell->IsUseUserData() + ? ::rtl::OUString( SvtUserOptions().GetFullName() ) + : ::rtl::OUString() ); + ::DateTime now; + + xDocProps->setPrintDate( util::DateTime( + now.Get100Sec(), now.GetSec(), now.GetMin(), now.GetHour(), + now.GetDay(), now.GetMonth(), now.GetYear() ) ); + + // FIXME: how to get all print options incl. AdditionalOptions easily? + uno::Sequence < beans::PropertyValue > aOpts; + mpObjectShell->Broadcast( SfxPrintingHint( view::PrintableState_JOB_STARTED, aOpts ) ); + } +} + +void SfxPrinterController::jobFinished( com::sun::star::view::PrintableState nState ) +{ + if ( mpObjectShell ) + { + bool bCopyJobSetup = false; + mpObjectShell->Broadcast( SfxPrintingHint( nState ) ); + switch ( nState ) + { + case view::PrintableState_JOB_FAILED : + { + // "real" problem (not simply printing cancelled by user) + String aMsg( SfxResId( STR_NOSTARTPRINTER ) ); + if ( !m_bApi ) + ErrorBox( mpViewShell->GetWindow(), WB_OK | WB_DEF_OK, aMsg ).Execute(); + // intentionally no break + } + case view::PrintableState_JOB_ABORTED : + { + // printing not succesful, reset DocInfo + uno::Reference<document::XDocumentProperties> xDocProps(mpObjectShell->getDocProperties()); + xDocProps->setPrintedBy(m_aLastPrintedBy); + xDocProps->setPrintDate(m_aLastPrinted); + break; + } + + case view::PrintableState_JOB_SPOOLED : + case view::PrintableState_JOB_COMPLETED : + { + SfxBindings& rBind = mpViewShell->GetViewFrame()->GetBindings(); + rBind.Invalidate( SID_PRINTDOC ); + rBind.Invalidate( SID_PRINTDOCDIRECT ); + rBind.Invalidate( SID_SETUPPRINTER ); + bCopyJobSetup = ! m_bTempPrinter; + break; + } + + default: + break; + } + + if( bCopyJobSetup && mpViewShell ) + { + // #i114306# + // Note: this possibly creates a printer that gets immediately replaced + // by a new one. The reason for this is that otherwise we would not get + // the printer's SfxItemSet here to copy. Awkward, but at the moment there is no + // other way here to get the item set. + SfxPrinter* pDocPrt = mpViewShell->GetPrinter(sal_True); + if( pDocPrt ) + { + if( pDocPrt->GetName() == getPrinter()->GetName() ) + pDocPrt->SetJobSetup( getPrinter()->GetJobSetup() ); + else + { + SfxPrinter* pNewPrt = new SfxPrinter( pDocPrt->GetOptions().Clone(), getPrinter()->GetName() ); + pNewPrt->SetJobSetup( getPrinter()->GetJobSetup() ); + mpViewShell->SetPrinter( pNewPrt, SFX_PRINTER_PRINTER | SFX_PRINTER_JOBSETUP ); + } + } + } + + if ( m_bNeedsChange ) + mpObjectShell->EnableSetModified( m_bOrigStatus ); + + if ( mpViewShell ) + { + mpViewShell->pImp->m_pPrinterController.reset(); + } + } +} + +//==================================================================== + +class SfxDialogExecutor_Impl + +/* [Description] + + An instance of this class is created for the life span of the + printer dialogue, to create in its click handler for the additions by the + virtual method of the derived SfxViewShell generated print options dialogue + and to cache the options set there as SfxItemSet. +*/ + +{ +private: + SfxViewShell* _pViewSh; + PrinterSetupDialog* _pSetupParent; + SfxItemSet* _pOptions; + sal_Bool _bModified; + sal_Bool _bHelpDisabled; + + DECL_LINK( Execute, void * ); + +public: + SfxDialogExecutor_Impl( SfxViewShell* pViewSh, PrinterSetupDialog* pParent ); + ~SfxDialogExecutor_Impl() { delete _pOptions; } + + Link GetLink() const { return LINK( this, SfxDialogExecutor_Impl, Execute); } + const SfxItemSet* GetOptions() const { return _pOptions; } + void DisableHelp() { _bHelpDisabled = sal_True; } +}; + +//-------------------------------------------------------------------- + +SfxDialogExecutor_Impl::SfxDialogExecutor_Impl( SfxViewShell* pViewSh, PrinterSetupDialog* pParent ) : + + _pViewSh ( pViewSh ), + _pSetupParent ( pParent ), + _pOptions ( NULL ), + _bModified ( sal_False ), + _bHelpDisabled ( sal_False ) + +{ +} + +//-------------------------------------------------------------------- + +IMPL_LINK( SfxDialogExecutor_Impl, Execute, void *, EMPTYARG ) +{ + // Options noted locally + if ( !_pOptions ) + { + DBG_ASSERT( _pSetupParent, "no dialog parent" ); + if( _pSetupParent ) + _pOptions = ( (SfxPrinter*)_pSetupParent->GetPrinter() )->GetOptions().Clone(); + } + + // Create Dialog + SfxPrintOptionsDialog* pDlg = new SfxPrintOptionsDialog( static_cast<Window*>(_pSetupParent), + _pViewSh, _pOptions ); + if ( _bHelpDisabled ) + pDlg->DisableHelp(); + if ( pDlg->Execute() == RET_OK ) + { + delete _pOptions; + _pOptions = pDlg->GetOptions().Clone(); + + } + delete pDlg; + + return 0; +} + +//------------------------------------------------------------------------- + +SfxPrinter* SfxViewShell::SetPrinter_Impl( SfxPrinter *pNewPrinter ) + + +/* Internal method for setting the differences between 'pNewPrinter' to the + current printer. pNewPrinter is either taken over or deleted. +*/ + +{ + // get current Printer + SfxPrinter *pDocPrinter = GetPrinter(); + + // Evaluate Printer Options + bool bOriToDoc = false; + bool bSizeToDoc = false; + if ( &pDocPrinter->GetOptions() ) + { + sal_uInt16 nWhich = GetPool().GetWhich(SID_PRINTER_CHANGESTODOC); + const SfxFlagItem *pFlagItem = 0; + pDocPrinter->GetOptions().GetItemState( nWhich, sal_False, (const SfxPoolItem**) &pFlagItem ); + bOriToDoc = pFlagItem ? (pFlagItem->GetValue() & SFX_PRINTER_CHG_ORIENTATION) : sal_False; + bSizeToDoc = pFlagItem ? (pFlagItem->GetValue() & SFX_PRINTER_CHG_SIZE) : sal_False; + } + + // Determine the previous format and size + Orientation eOldOri = pDocPrinter->GetOrientation(); + Size aOldPgSz = pDocPrinter->GetPaperSizePixel(); + + // Determine the new format and size + Orientation eNewOri = pNewPrinter->GetOrientation(); + Size aNewPgSz = pNewPrinter->GetPaperSizePixel(); + + // Determine the changes in page format + sal_Bool bOriChg = (eOldOri != eNewOri) && bOriToDoc; + sal_Bool bPgSzChg = ( aOldPgSz.Height() != + ( bOriChg ? aNewPgSz.Width() : aNewPgSz.Height() ) || + aOldPgSz.Width() != + ( bOriChg ? aNewPgSz.Height() : aNewPgSz.Width() ) ) && + bSizeToDoc; + + // Message and Flags for page format, summaries changes + String aMsg; + sal_uInt16 nNewOpt=0; + if( bOriChg && bPgSzChg ) + { + aMsg = String(SfxResId(STR_PRINT_NEWORISIZE)); + nNewOpt = SFX_PRINTER_CHG_ORIENTATION | SFX_PRINTER_CHG_SIZE; + } + else if (bOriChg ) + { + aMsg = String(SfxResId(STR_PRINT_NEWORI)); + nNewOpt = SFX_PRINTER_CHG_ORIENTATION; + } + else if (bPgSzChg) + { + aMsg = String(SfxResId(STR_PRINT_NEWSIZE)); + nNewOpt = SFX_PRINTER_CHG_SIZE; + } + + // Summaries in this variable what has been changed. + sal_uInt16 nChangedFlags = 0; + + // Ask if possible, if page format should be taken over from printer. + if ( ( bOriChg || bPgSzChg ) && + RET_YES == QueryBox(0, WB_YES_NO | WB_DEF_OK, aMsg).Execute() ) + // Flags wich changes for <SetPrinter(SfxPrinter*)> are maintained + nChangedFlags |= nNewOpt; + + // For the MAC to have its "temporary of class String" in next if() + String aTempPrtName = pNewPrinter->GetName(); + String aDocPrtName = pDocPrinter->GetName(); + + // Was the printer selection changed from Default to Specific + // or the other way around? + if ( (aTempPrtName != aDocPrtName) || (pDocPrinter->IsDefPrinter() != pNewPrinter->IsDefPrinter()) ) + { + nChangedFlags |= SFX_PRINTER_PRINTER|SFX_PRINTER_JOBSETUP; + pDocPrinter = pNewPrinter; + } + else + { + // Compare extra options + if ( ! (pNewPrinter->GetOptions() == pDocPrinter->GetOptions()) ) + { + // Option have changed + pDocPrinter->SetOptions( pNewPrinter->GetOptions() ); + nChangedFlags |= SFX_PRINTER_OPTIONS; + } + + // Compare JobSetups + JobSetup aNewJobSetup = pNewPrinter->GetJobSetup(); + JobSetup aOldJobSetup = pDocPrinter->GetJobSetup(); + if ( aNewJobSetup != aOldJobSetup ) + { + nChangedFlags |= SFX_PRINTER_JOBSETUP; + } + + // Keep old changed Printer. + pDocPrinter->SetPrinterProps( pNewPrinter ); + delete pNewPrinter; + } + + if ( 0 != nChangedFlags ) + // SetPrinter will delete the old printer if it changes + SetPrinter( pDocPrinter, nChangedFlags ); + return pDocPrinter; +} + +//------------------------------------------------------------------------- +// Sadly enough the problem arises with WIN32 that nothing is printed when +// SID_PRINTDOCDIRECT auflaueft. At the moment the only known solution in this +// case is to turn off the optimazation. +#ifdef _MSC_VER +#pragma optimize ( "", off ) +#endif + +void SfxViewShell::ExecPrint( const uno::Sequence < beans::PropertyValue >& rProps, sal_Bool bIsAPI, sal_Bool bIsDirect ) +{ + // get the current selection; our controller should know it + Reference< frame::XController > xController( GetController() ); + Reference< view::XSelectionSupplier > xSupplier( xController, UNO_QUERY ); + + Any aSelection; + if( xSupplier.is() ) + aSelection = xSupplier->getSelection(); + else + aSelection <<= GetObjectShell()->GetModel(); + Any aComplete( makeAny( GetObjectShell()->GetModel() ) ); + Any aViewProp( makeAny( xController ) ); + boost::shared_ptr<Printer> aPrt; + + const beans::PropertyValue* pVal = rProps.getConstArray(); + for( sal_Int32 i = 0; i < rProps.getLength(); i++ ) + { + if( pVal[i].Name.equalsAscii( "PrinterName" ) ) + { + rtl::OUString aPrinterName; + pVal[i].Value >>= aPrinterName; + aPrt.reset( new Printer( aPrinterName ) ); + break; + } + } + + boost::shared_ptr<vcl::PrinterController> pController( new SfxPrinterController( + aPrt, + aComplete, + aSelection, + aViewProp, + GetRenderable(), + bIsAPI, + bIsDirect, + this, + rProps + ) ); + pImp->m_pPrinterController = pController; + + SfxObjectShell *pObjShell = GetObjectShell(); + pController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "JobName" ) ), + makeAny( rtl::OUString( pObjShell->GetTitle(0) ) ) ); + + // FIXME: job setup + SfxPrinter* pDocPrt = GetPrinter(sal_False); + JobSetup aJobSetup = pDocPrt ? pDocPrt->GetJobSetup() : GetJobSetup(); + if( bIsDirect ) + aJobSetup.SetValue( String( RTL_CONSTASCII_USTRINGPARAM( "IsQuickJob" ) ), + String( RTL_CONSTASCII_USTRINGPARAM( "true" ) ) ); + + Printer::PrintJob( pController, aJobSetup ); +} + +Printer* SfxViewShell::GetActivePrinter() const +{ + return (pImp->m_pPrinterController) + ? pImp->m_pPrinterController->getPrinter().get() : 0; +} + +void SfxViewShell::ExecPrint_Impl( SfxRequest &rReq ) +{ + sal_uInt16 nDialogRet = RET_CANCEL; + SfxPrinter* pPrinter = 0; + SfxDialogExecutor_Impl* pExecutor = 0; + bool bSilent = false; + sal_Bool bIsAPI = rReq.GetArgs() && rReq.GetArgs()->Count(); + if ( bIsAPI ) + { + SFX_REQUEST_ARG(rReq, pSilentItem, SfxBoolItem, SID_SILENT, sal_False); + bSilent = pSilentItem && pSilentItem->GetValue(); + } + + //FIXME: how to transport "bPrintOnHelp"? + + // no help button in dialogs if called from the help window + // (pressing help button would exchange the current page inside the help + // document that is going to be printed!) + String aHelpFilterName( DEFINE_CONST_UNICODE("writer_web_HTML_help") ); + SfxMedium* pMedium = GetViewFrame()->GetObjectShell()->GetMedium(); + const SfxFilter* pFilter = pMedium ? pMedium->GetFilter() : NULL; + sal_Bool bPrintOnHelp = ( pFilter && pFilter->GetFilterName() == aHelpFilterName ); + + const sal_uInt16 nId = rReq.GetSlot(); + switch( nId ) + { + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + case SID_PRINTDOC: + case SID_PRINTDOCDIRECT: + { + SfxObjectShell* pDoc = GetObjectShell(); + + // derived class may decide to abort this + if( !pDoc->QuerySlotExecutable( nId ) ) + { + rReq.SetReturnValue( SfxBoolItem( 0, sal_False ) ); + return; + } + + bool bDetectHidden = ( !bSilent && pDoc ); + if ( bDetectHidden && pDoc->QueryHiddenInformation( WhenPrinting, NULL ) != RET_YES ) + break; + + SFX_REQUEST_ARG(rReq, pSelectItem, SfxBoolItem, SID_SELECTION, sal_False); + sal_Bool bSelection = pSelectItem && pSelectItem->GetValue(); + if( pSelectItem && rReq.GetArgs()->Count() == 1 ) + bIsAPI = sal_False; + + uno::Sequence < beans::PropertyValue > aProps; + if ( bIsAPI ) + { + // supported properties: + // String PrinterName + // String FileName + // Int16 From + // Int16 To + // In16 Copies + // String RangeText + // bool Selection + // bool Asynchron + // bool Collate + // bool Silent + TransformItems( nId, *rReq.GetArgs(), aProps, GetInterface()->GetSlot(nId) ); + for ( sal_Int32 nProp=0; nProp<aProps.getLength(); nProp++ ) + { + if ( aProps[nProp].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Copies")) ) + aProps[nProp]. Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CopyCount")); + else if ( aProps[nProp].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("RangeText")) ) + aProps[nProp]. Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Pages")); + if ( aProps[nProp].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Asynchron")) ) + { + aProps[nProp]. Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Wait")); + sal_Bool bAsynchron = sal_False; + aProps[nProp].Value >>= bAsynchron; + aProps[nProp].Value <<= (sal_Bool) (!bAsynchron); + } + if ( aProps[nProp].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Silent")) ) + { + aProps[nProp]. Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MonitorVisible")); + sal_Bool bPrintSilent = sal_False; + aProps[nProp].Value >>= bPrintSilent; + aProps[nProp].Value <<= (sal_Bool) (!bPrintSilent); + } + } + } + // HACK: writer sets the SID_SELECTION item when printing directly and expects + // to get only the selection document in that case (see getSelectionObject) + // however it also reacts to the PrintContent property. We need this distinction here, too, + // else one of the combinations print / print direct and selection / all will not work. + // it would be better if writer handled this internally + if( nId == SID_PRINTDOCDIRECT ) + { + sal_Int32 nLen = aProps.getLength(); + aProps.realloc( nLen + 1 ); + aProps[nLen].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintSelectionOnly" ) ); + aProps[nLen].Value = makeAny( bSelection ); + } + + ExecPrint( aProps, bIsAPI, (nId == SID_PRINTDOCDIRECT) ); + + // FIXME: Recording + rReq.Done(); + break; + } + + case SID_SETUPPRINTER : + case SID_PRINTER_NAME : // only for recorded macros + { + // get printer and printer settings from the document + SfxPrinter *pDocPrinter = GetPrinter(sal_True); + + // look for printer in parameters + SFX_REQUEST_ARG( rReq, pPrinterItem, SfxStringItem, SID_PRINTER_NAME, sal_False ); + if ( pPrinterItem ) + { + // use PrinterName parameter to create a printer + pPrinter = new SfxPrinter( pDocPrinter->GetOptions().Clone(), ((const SfxStringItem*) pPrinterItem)->GetValue() ); + + // if printer is unknown, it can't be used - now printer from document will be used + if ( !pPrinter->IsOriginal() ) + DELETEZ(pPrinter); + } + + if ( SID_PRINTER_NAME == nId ) + { + // just set a recorded printer name + if ( pPrinter ) + SetPrinter( pPrinter, SFX_PRINTER_PRINTER ); + break; + } + + // no PrinterName parameter in ItemSet or the PrinterName points to an unknown printer + if ( !pPrinter ) + // use default printer from document + pPrinter = pDocPrinter; + + if( !pPrinter || !pPrinter->IsValid() ) + { + // no valid printer either in ItemSet or at the document + if ( bSilent ) + { + rReq.SetReturnValue(SfxBoolItem(0,sal_False)); + break; + } + else + ErrorBox( NULL, WB_OK | WB_DEF_OK, String( SfxResId( STR_NODEFPRINTER ) ) ).Execute(); + } + + // FIXME: printer isn't used for printing anymore! + if( pPrinter->IsPrinting() ) + { + // if printer is busy, abort printing + if ( !bSilent ) + InfoBox( NULL, String( SfxResId( STR_ERROR_PRINTER_BUSY ) ) ).Execute(); + rReq.SetReturnValue(SfxBoolItem(0,sal_False)); + break; + } + + // if no arguments are given, retrieve them from a dialog + if ( !bIsAPI ) + { + // PrinterDialog needs a temporary printer + SfxPrinter* pDlgPrinter = pPrinter->Clone(); + nDialogRet = 0; + + // execute PrinterSetupDialog + PrinterSetupDialog* pPrintSetupDlg = new PrinterSetupDialog( GetWindow() ); + + if (pImp->m_bHasPrintOptions) + { + // additional controls for dialog + pExecutor = new SfxDialogExecutor_Impl( this, pPrintSetupDlg ); + if ( bPrintOnHelp ) + pExecutor->DisableHelp(); + pPrintSetupDlg->SetOptionsHdl( pExecutor->GetLink() ); + } + + pPrintSetupDlg->SetPrinter( pDlgPrinter ); + nDialogRet = pPrintSetupDlg->Execute(); + + if ( pExecutor && pExecutor->GetOptions() ) + { + if ( nDialogRet == RET_OK ) + // remark: have to be recorded if possible! + pDlgPrinter->SetOptions( *pExecutor->GetOptions() ); + else + { + pPrinter->SetOptions( *pExecutor->GetOptions() ); + SetPrinter( pPrinter, SFX_PRINTER_OPTIONS ); + } + } + + DELETEZ( pPrintSetupDlg ); + + // no recording of PrinterSetup except printer name (is printer dependent) + rReq.Ignore(); + + if ( nDialogRet == RET_OK ) + { + if ( pPrinter->GetName() != pDlgPrinter->GetName() ) + { + // user has changed the printer -> macro recording + SfxRequest aReq( GetViewFrame(), SID_PRINTER_NAME ); + aReq.AppendItem( SfxStringItem( SID_PRINTER_NAME, pDlgPrinter->GetName() ) ); + aReq.Done(); + } + if ( nId == SID_SETUPPRINTER ) + { + rReq.AppendItem( SfxBoolItem( SID_DIALOG_RETURN, sal_True ) ); + } + + // take the changes made in the dialog + pPrinter = SetPrinter_Impl( pDlgPrinter ); + + // forget new printer, it was taken over (as pPrinter) or deleted + pDlgPrinter = NULL; + + } + else + { + // PrinterDialog is used to transfer information on printing, + // so it will only be deleted here if dialog was cancelled + DELETEZ( pDlgPrinter ); + rReq.Ignore(); + if ( SID_PRINTDOC == nId ) + rReq.SetReturnValue(SfxBoolItem(0,sal_False)); + if ( nId == SID_SETUPPRINTER ) + { + rReq.AppendItem( SfxBoolItem( SID_DIALOG_RETURN, sal_False ) ); + } + } + } + } + + break; + } +} + +// Turn on optimazation again. +#ifdef _MSC_VER +#pragma optimize ( "", on ) +#endif + +//-------------------------------------------------------------------- + +sal_Bool SfxViewShell::IsPrinterLocked() const +{ + return pImp->m_nPrinterLocks > 0; +} + +//-------------------------------------------------------------------- + +void SfxViewShell::LockPrinter( sal_Bool bLock) +{ + sal_Bool bChanged = sal_False; + if ( bLock ) + { + bChanged = 1 == ++pImp->m_nPrinterLocks; + } + else + { + bChanged = 0 == --pImp->m_nPrinterLocks; + } + + if ( bChanged ) + { + Invalidate( SID_PRINTDOC ); + Invalidate( SID_PRINTDOCDIRECT ); + Invalidate( SID_SETUPPRINTER ); + } +} + +//-------------------------------------------------------------------- + +SfxPrinter* SfxViewShell::GetPrinter( sal_Bool /*bCreate*/ ) +{ + return 0; +} + +//-------------------------------------------------------------------- + +sal_uInt16 SfxViewShell::SetPrinter( SfxPrinter* /*pNewPrinter*/, sal_uInt16 /*nDiffFlags*/, bool ) +{ + return 0; +} + +//-------------------------------------------------------------------- + +SfxTabPage* SfxViewShell::CreatePrintOptionsPage +( + Window* /*pParent*/, + const SfxItemSet& /*rOptions*/ +) +{ + return 0; +} + +JobSetup SfxViewShell::GetJobSetup() const +{ + return JobSetup(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx new file mode 100644 index 000000000000..eb5f98905cbb --- /dev/null +++ b/sfx2/source/view/viewsh.cxx @@ -0,0 +1,2299 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" +#include <svl/stritem.hxx> +#include <svl/eitem.hxx> +#include <svl/whiter.hxx> +#include <vcl/msgbox.hxx> +#include <vcl/toolbox.hxx> +#include <svl/intitem.hxx> +#include <svtools/sfxecode.hxx> +#include <svtools/ehdl.hxx> +#include <com/sun/star/frame/XLayoutManager.hpp> +#include <com/sun/star/frame/XModuleManager.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/embed/EmbedStates.hpp> +#include <com/sun/star/embed/EmbedMisc.hpp> +#include <com/sun/star/system/XSystemShellExecute.hpp> +#include <com/sun/star/system/SystemShellExecuteFlags.hpp> +#include <com/sun/star/container/XContainerQuery.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp> +#include <cppuhelper/implbase1.hxx> + +#include <osl/file.hxx> +#include <osl/mutex.hxx> +#include <tools/urlobj.hxx> +#include <unotools/tempfile.hxx> +#include <unotools/pathoptions.hxx> +#include <svtools/miscopt.hxx> +#include <svtools/soerr.hxx> +#include <unotools/internaloptions.hxx> + +#include <unotools/javaoptions.hxx> +#include <basic/basmgr.hxx> +#include <basic/sbuno.hxx> +#include <framework/actiontriggerhelper.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <toolkit/unohlp.hxx> + + +#include <sfx2/app.hxx> +#include "view.hrc" +#include <sfx2/viewsh.hxx> +#include "viewimp.hxx" +#include "sfx2/sfxresid.hxx" +#include <sfx2/request.hxx> +#include <sfx2/templdlg.hxx> +#include <sfx2/printer.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/dispatch.hxx> +#include "arrdecl.hxx" +#include <sfx2/docfac.hxx> +#include "view.hrc" +#include "sfxlocal.hrc" +#include <sfx2/sfxbasecontroller.hxx> +#include "sfx2/mailmodelapi.hxx" +#include <sfx2/viewfrm.hxx> +#include <sfx2/event.hxx> +#include <sfx2/fcontnr.hxx> +#include <sfx2/ipclient.hxx> +#include "workwin.hxx" +#include <sfx2/objface.hxx> +#include <sfx2/docfilt.hxx> + +#include <comphelper/processfactory.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::system; +using namespace ::cppu; +namespace css = ::com::sun::star; + +//========================================================================= +DBG_NAME(SfxViewShell) + +#define SfxViewShell +#include "sfxslots.hxx" + +//========================================================================= + +class SfxClipboardChangeListener : public ::cppu::WeakImplHelper1< + datatransfer::clipboard::XClipboardListener > +{ +public: + SfxClipboardChangeListener( SfxViewShell* pView, const uno::Reference< datatransfer::clipboard::XClipboardNotifier >& xClpbrdNtfr ); + virtual ~SfxClipboardChangeListener(); + + // XEventListener + virtual void SAL_CALL disposing( const lang::EventObject& rEventObject ) + throw ( uno::RuntimeException ); + + // XClipboardListener + virtual void SAL_CALL changedContents( const datatransfer::clipboard::ClipboardEvent& rEventObject ) + throw ( uno::RuntimeException ); + + void DisconnectViewShell() { m_pViewShell = NULL; } + void ChangedContents(); + + enum AsyncExecuteCmd + { + ASYNCEXECUTE_CMD_DISPOSING, + ASYNCEXECUTE_CMD_CHANGEDCONTENTS + }; + + struct AsyncExecuteInfo + { + AsyncExecuteInfo( AsyncExecuteCmd eCmd, uno::Reference< datatransfer::clipboard::XClipboardListener > xThis, SfxClipboardChangeListener* pListener ) : + m_eCmd( eCmd ), m_xThis( xThis ), m_pListener( pListener ) {} + + AsyncExecuteCmd m_eCmd; + uno::Reference< datatransfer::clipboard::XClipboardListener > m_xThis; + SfxClipboardChangeListener* m_pListener; + }; + +private: + SfxViewShell* m_pViewShell; + uno::Reference< datatransfer::clipboard::XClipboardNotifier > m_xClpbrdNtfr; + uno::Reference< lang::XComponent > m_xCtrl; + + DECL_STATIC_LINK( SfxClipboardChangeListener, AsyncExecuteHdl_Impl, AsyncExecuteInfo* ); +}; + +SfxClipboardChangeListener::SfxClipboardChangeListener( SfxViewShell* pView, const uno::Reference< datatransfer::clipboard::XClipboardNotifier >& xClpbrdNtfr ) + : m_pViewShell( 0 ), m_xClpbrdNtfr( xClpbrdNtfr ) +{ + m_xCtrl = uno::Reference < lang::XComponent >( pView->GetController(), uno::UNO_QUERY ); + if ( m_xCtrl.is() ) + { + m_xCtrl->addEventListener( uno::Reference < lang::XEventListener > ( static_cast < lang::XEventListener* >( this ) ) ); + m_pViewShell = pView; + } + if ( m_xClpbrdNtfr.is() ) + { + m_xClpbrdNtfr->addClipboardListener( uno::Reference< datatransfer::clipboard::XClipboardListener >( + static_cast< datatransfer::clipboard::XClipboardListener* >( this ))); + } +} + +SfxClipboardChangeListener::~SfxClipboardChangeListener() +{ +} + +void SfxClipboardChangeListener::ChangedContents() +{ + const SolarMutexGuard aGuard; + if( m_pViewShell ) + { + SfxBindings& rBind = m_pViewShell->GetViewFrame()->GetBindings(); + rBind.Invalidate( SID_PASTE ); + rBind.Invalidate( SID_PASTE_SPECIAL ); + rBind.Invalidate( SID_CLIPBOARD_FORMAT_ITEMS ); + } +} + +IMPL_STATIC_LINK_NOINSTANCE( SfxClipboardChangeListener, AsyncExecuteHdl_Impl, AsyncExecuteInfo*, pAsyncExecuteInfo ) +{ + if ( pAsyncExecuteInfo ) + { + uno::Reference< datatransfer::clipboard::XClipboardListener > xThis( pAsyncExecuteInfo->m_xThis ); + if ( pAsyncExecuteInfo->m_pListener ) + { + if ( pAsyncExecuteInfo->m_eCmd == ASYNCEXECUTE_CMD_DISPOSING ) + pAsyncExecuteInfo->m_pListener->DisconnectViewShell(); + else if ( pAsyncExecuteInfo->m_eCmd == ASYNCEXECUTE_CMD_CHANGEDCONTENTS ) + pAsyncExecuteInfo->m_pListener->ChangedContents(); + } + } + delete pAsyncExecuteInfo; + + return 0; +} + +void SAL_CALL SfxClipboardChangeListener::disposing( const lang::EventObject& /*rEventObject*/ ) +throw ( uno::RuntimeException ) +{ + // Either clipboard or ViewShell is going to be destroyed -> no interest in listening anymore + uno::Reference< lang::XComponent > xCtrl( m_xCtrl ); + uno::Reference< datatransfer::clipboard::XClipboardNotifier > xNotify( m_xClpbrdNtfr ); + + uno::Reference< datatransfer::clipboard::XClipboardListener > xThis( static_cast< datatransfer::clipboard::XClipboardListener* >( this )); + if ( xCtrl.is() ) + xCtrl->removeEventListener( uno::Reference < lang::XEventListener > ( static_cast < lang::XEventListener* >( this ))); + if ( xNotify.is() ) + xNotify->removeClipboardListener( xThis ); + + // Make asynchronous call to avoid locking SolarMutex which is the + // root for many deadlocks, especially in conjuction with the "Windows" + // based single thread apartment clipboard code! + AsyncExecuteInfo* pInfo = new AsyncExecuteInfo( ASYNCEXECUTE_CMD_DISPOSING, xThis, this ); + Application::PostUserEvent( STATIC_LINK( 0, SfxClipboardChangeListener, AsyncExecuteHdl_Impl ), pInfo ); +} + +void SAL_CALL SfxClipboardChangeListener::changedContents( const datatransfer::clipboard::ClipboardEvent& ) + throw ( RuntimeException ) +{ + // Make asynchronous call to avoid locking SolarMutex which is the + // root for many deadlocks, especially in conjuction with the "Windows" + // based single thread apartment clipboard code! + uno::Reference< datatransfer::clipboard::XClipboardListener > xThis( static_cast< datatransfer::clipboard::XClipboardListener* >( this )); + AsyncExecuteInfo* pInfo = new AsyncExecuteInfo( ASYNCEXECUTE_CMD_CHANGEDCONTENTS, xThis, this ); + Application::PostUserEvent( STATIC_LINK( 0, SfxClipboardChangeListener, AsyncExecuteHdl_Impl ), pInfo ); +} + +//========================================================================= + +static ::rtl::OUString RetrieveLabelFromCommand( + const ::rtl::OUString& rCommandURL, + const css::uno::Reference< css::frame::XFrame >& rFrame ) +{ + static css::uno::WeakReference< frame::XModuleManager > s_xModuleManager; + static css::uno::WeakReference< container::XNameAccess > s_xNameAccess; + + ::rtl::OUString aLabel; + css::uno::Reference< css::frame::XModuleManager > xModuleManager( s_xModuleManager ); + css::uno::Reference< css::container::XNameAccess > xNameAccess( s_xNameAccess ); + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR( + ::comphelper::getProcessServiceFactory(), css::uno::UNO_QUERY_THROW); + + try + { + if ( !xModuleManager.is() ) + { + xModuleManager = css::uno::Reference< css::frame::XModuleManager >( + xSMGR->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.ModuleManager" ))), + css::uno::UNO_QUERY_THROW ); + s_xModuleManager = xModuleManager; + } + + ::rtl::OUString aModuleIdentifier = xModuleManager->identify( rFrame ); + + if ( !xNameAccess.is() ) + { + xNameAccess = css::uno::Reference< css::container::XNameAccess >( + xSMGR->createInstance( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.UICommandDescription" ))), + css::uno::UNO_QUERY_THROW ); + s_xNameAccess = xNameAccess; + } + + css::uno::Any a = xNameAccess->getByName( aModuleIdentifier ); + css::uno::Reference< css::container::XNameAccess > xUICommands; + a >>= xUICommands; + + rtl::OUString aStr; + css::uno::Sequence< css::beans::PropertyValue > aPropSeq; + + a = xUICommands->getByName( rCommandURL ); + if ( a >>= aPropSeq ) + { + for ( sal_Int32 i = 0; i < aPropSeq.getLength(); i++ ) + { + if ( aPropSeq[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Label" ) )) + { + aPropSeq[i].Value >>= aStr; + break; + } + } + aLabel = aStr; + } + } + catch ( css::uno::Exception& ) + { + } + + return aLabel; +} + +//========================================================================= +SfxViewShell_Impl::SfxViewShell_Impl(sal_uInt16 const nFlags) +: aInterceptorContainer( aMutex ) +, m_bControllerSet(false) +, m_nPrinterLocks(0) +, m_bCanPrint(SFX_VIEW_CAN_PRINT == (nFlags & SFX_VIEW_CAN_PRINT)) +, m_bHasPrintOptions( + SFX_VIEW_HAS_PRINTOPTIONS == (nFlags & SFX_VIEW_HAS_PRINTOPTIONS)) +, m_bPlugInsActive(true) +, m_bIsShowView(SFX_VIEW_NO_SHOW != (nFlags & SFX_VIEW_NO_SHOW)) +, m_bGotOwnership(false) +, m_bGotFrameOwnership(false) +, m_eScroll(SCROLLING_DEFAULT) +, m_nFamily(0xFFFF) // undefined, default set by TemplateDialog +, m_pController(0) +, m_pAccExec(0) +{} + +//========================================================================= +SFX_IMPL_INTERFACE(SfxViewShell,SfxShell,SfxResId(0)) +{ + SFX_CHILDWINDOW_REGISTRATION( SID_MAIL_CHILDWIN ); +} + +TYPEINIT2(SfxViewShell,SfxShell,SfxListener); + +//-------------------------------------------------------------------- +/** search for a filter name dependent on type and module + */ + +static ::rtl::OUString impl_retrieveFilterNameFromTypeAndModule( + const css::uno::Reference< css::container::XContainerQuery >& rContainerQuery, + const ::rtl::OUString& rType, + const ::rtl::OUString& rModuleIdentifier, + const sal_Int32 nFlags ) +{ + // Retrieve filter from type + css::uno::Sequence< css::beans::NamedValue > aQuery( 2 ); + aQuery[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Type" )); + aQuery[0].Value = css::uno::makeAny( rType ); + aQuery[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DocumentService" )); + aQuery[1].Value = css::uno::makeAny( rModuleIdentifier ); + + css::uno::Reference< css::container::XEnumeration > xEnumeration = + rContainerQuery->createSubSetEnumerationByProperties( aQuery ); + + ::rtl::OUString aFoundFilterName; + while ( xEnumeration->hasMoreElements() ) + { + ::comphelper::SequenceAsHashMap aFilterPropsHM( xEnumeration->nextElement() ); + ::rtl::OUString aFilterName = aFilterPropsHM.getUnpackedValueOrDefault( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name")), + ::rtl::OUString() ); + + sal_Int32 nFilterFlags = aFilterPropsHM.getUnpackedValueOrDefault( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Flags")), + sal_Int32( 0 ) ); + + if ( nFilterFlags & nFlags ) + { + aFoundFilterName = aFilterName; + break; + } + } + + return aFoundFilterName; +} + +//-------------------------------------------------------------------- +/** search for an internal typename, which map to the current app module + and map also to a "family" of file formats as e.g. PDF/MS Doc/OOo Doc. + */ +enum ETypeFamily +{ + E_MS_DOC, + E_OOO_DOC +}; + +::rtl::OUString impl_searchFormatTypeForApp(const css::uno::Reference< css::frame::XFrame >& xFrame , + ETypeFamily eTypeFamily) +{ + static ::rtl::OUString SERVICENAME_MODULEMANAGER(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.ModuleManager")); + + try + { + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR (::comphelper::getProcessServiceFactory() , css::uno::UNO_QUERY_THROW); + css::uno::Reference< css::frame::XModuleManager > xModuleManager(xSMGR->createInstance(SERVICENAME_MODULEMANAGER), css::uno::UNO_QUERY_THROW); + + ::rtl::OUString sModule = xModuleManager->identify(xFrame); + ::rtl::OUString sType ; + + switch(eTypeFamily) + { + case E_MS_DOC: + { + if (sModule.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.text.TextDocument" ) )) + sType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "writer_MS_Word_97" )); + else + if (sModule.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.sheet.SpreadsheetDocument" ) )) + sType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "calc_MS_Excel_97" )); + else + if (sModule.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.DrawingDocument" ) )) + sType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "impress_MS_PowerPoint_97" )); + else + if (sModule.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.presentation.PresentationDocument" ) )) + sType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "impress_MS_PowerPoint_97" )); + } + break; + + case E_OOO_DOC: + { + if (sModule.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.text.TextDocument" ) )) + sType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "writer8" )); + else + if (sModule.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.sheet.SpreadsheetDocument" ) )) + sType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "calc8" )); + else + if (sModule.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.drawing.DrawingDocument" ) )) + sType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "draw8" )); + else + if (sModule.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.presentation.PresentationDocument" ) )) + sType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "impress8" )); + } + break; + } + + return sType; + } + catch(const css::uno::RuntimeException& exRun) + { throw exRun; } + catch(const css::uno::Exception&) + {} + + return ::rtl::OUString(); +} + +//-------------------------------------------------------------------- + +SAL_DLLPRIVATE void SfxViewShell::IPClientGone_Impl( SfxInPlaceClient *pIPClient ) +{ + SfxInPlaceClientList* pClientList = GetIPClientList_Impl(sal_True); + + for( SfxInPlaceClientList::iterator it = pClientList->begin(); it < pClientList->end(); ++it ) + { + if ( *it == pIPClient ) + { + pClientList->erase( it ); + break; + } + } +} + + + +//-------------------------------------------------------------------- + +void SfxViewShell::ExecMisc_Impl( SfxRequest &rReq ) +{ + const sal_uInt16 nId = rReq.GetSlot(); + switch( nId ) + { + case SID_STYLE_FAMILY : + { + SFX_REQUEST_ARG(rReq, pItem, SfxUInt16Item, nId, sal_False); + if (pItem) + { + pImp->m_nFamily = pItem->GetValue(); + } + break; + } + + case SID_STYLE_CATALOG: + { + SfxTemplateCatalog aCatalog( + SFX_APP()->GetTopWindow(), &GetViewFrame()->GetBindings()); + aCatalog.Execute(); + rReq.Ignore(); + break; + } + case SID_ACTIVATE_STYLE_APPLY: + { + com::sun::star::uno::Reference< com::sun::star::frame::XFrame > xFrame( + GetViewFrame()->GetFrame().GetFrameInterface(), + com::sun::star::uno::UNO_QUERY); + + Reference< com::sun::star::beans::XPropertySet > xPropSet( xFrame, UNO_QUERY ); + Reference< ::com::sun::star::frame::XLayoutManager > xLayoutManager; + if ( xPropSet.is() ) + { + try + { + Any aValue = xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LayoutManager" ))); + aValue >>= xLayoutManager; + if ( xLayoutManager.is() ) + { + rtl::OUString aTextResString( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/textobjectbar" )); + uno::Reference< ui::XUIElement > xElement = xLayoutManager->getElement( aTextResString ); + if(!xElement.is()) + { + rtl::OUString aFrameResString( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/frameobjectbar" )); + xElement = xLayoutManager->getElement( aFrameResString ); + } + if(!xElement.is()) + { + rtl::OUString aOleResString( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/oleobjectbar" )); + xElement = xLayoutManager->getElement( aOleResString ); + } + if(xElement.is()) + { + uno::Reference< awt::XWindow > xWin( xElement->getRealInterface(), uno::UNO_QUERY_THROW ); + Window* pWin = VCLUnoHelper::GetWindow( xWin ); + ToolBox* pTextToolbox = dynamic_cast< ToolBox* >( pWin ); + if( pTextToolbox ) + { + sal_uInt16 nItemCount = pTextToolbox->GetItemCount(); + for( sal_uInt16 nItem = 0; nItem < nItemCount; ++nItem ) + { + sal_uInt16 nItemId = pTextToolbox->GetItemId( nItem ); + const XubString& rCommand = pTextToolbox->GetItemCommand( nItemId ); + if( rCommand.EqualsAscii( ".uno:StyleApply" ) ) + { + Window* pItemWin = pTextToolbox->GetItemWindow( nItemId ); + if( pItemWin ) + pItemWin->GrabFocus(); + break; + } + } + } + } + } + } + catch ( Exception& ) + { + } + } + rReq.Done(); + } + break; + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + case SID_MAIL_SENDDOCASMS: + case SID_MAIL_SENDDOCASOOO: + case SID_MAIL_SENDDOCASPDF: + case SID_MAIL_SENDDOC: + case SID_MAIL_SENDDOCASFORMAT: + { + SfxObjectShell* pDoc = GetObjectShell(); + if ( pDoc && pDoc->QueryHiddenInformation( + WhenSaving, &GetViewFrame()->GetWindow() ) != RET_YES ) + break; + + if ( SvtInternalOptions().MailUIEnabled() ) + { + GetViewFrame()->SetChildWindow( SID_MAIL_CHILDWIN, sal_True ); + } + else + { + SfxMailModel aModel; + rtl::OUString aDocType; + + SFX_REQUEST_ARG(rReq, pMailSubject, SfxStringItem, SID_MAIL_SUBJECT, sal_False ); + if ( pMailSubject ) + aModel.SetSubject( pMailSubject->GetValue() ); + + SFX_REQUEST_ARG(rReq, pMailRecipient, SfxStringItem, SID_MAIL_RECIPIENT, sal_False ); + if ( pMailRecipient ) + { + String aRecipient( pMailRecipient->GetValue() ); + String aMailToStr( String::CreateFromAscii( "mailto:" )); + + if ( aRecipient.Search( aMailToStr ) == 0 ) + aRecipient = aRecipient.Erase( 0, aMailToStr.Len() ); + aModel.AddAddress( aRecipient, SfxMailModel::ROLE_TO ); + } + SFX_REQUEST_ARG(rReq, pMailDocType, SfxStringItem, SID_TYPE_NAME, sal_False ); + if ( pMailDocType ) + aDocType = pMailDocType->GetValue(); + + uno::Reference < frame::XFrame > xFrame( pFrame->GetFrame().GetFrameInterface() ); + SfxMailModel::SendMailResult eResult = SfxMailModel::SEND_MAIL_ERROR; + + if ( nId == SID_MAIL_SENDDOC ) + eResult = aModel.SaveAndSend( xFrame, rtl::OUString() ); + else + if ( nId == SID_MAIL_SENDDOCASPDF ) + eResult = aModel.SaveAndSend( xFrame, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "pdf_Portable_Document_Format" ))); + else + if ( nId == SID_MAIL_SENDDOCASMS ) + { + aDocType = impl_searchFormatTypeForApp(xFrame, E_MS_DOC); + if (aDocType.getLength() > 0) + eResult = aModel.SaveAndSend( xFrame, aDocType ); + } + else + if ( nId == SID_MAIL_SENDDOCASOOO ) + { + aDocType = impl_searchFormatTypeForApp(xFrame, E_OOO_DOC); + if (aDocType.getLength() > 0) + eResult = aModel.SaveAndSend( xFrame, aDocType ); + } + + if ( eResult == SfxMailModel::SEND_MAIL_ERROR ) + { + InfoBox aBox( SFX_APP()->GetTopWindow(), SfxResId( MSG_ERROR_SEND_MAIL )); + aBox.Execute(); + rReq.Ignore(); + } + else + rReq.Done(); + } + + break; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + case SID_WEBHTML: + { + static const char HTML_DOCUMENT_TYPE[] = "writer_web_HTML"; + static const char HTML_GRAPHIC_TYPE[] = "graphic_HTML"; + const sal_Int32 FILTERFLAG_EXPORT = 0x00000002; + + css::uno::Reference< lang::XMultiServiceFactory > xSMGR(::comphelper::getProcessServiceFactory(), css::uno::UNO_QUERY_THROW); + css::uno::Reference < css::frame::XFrame > xFrame( pFrame->GetFrame().GetFrameInterface() ); + css::uno::Reference< css::frame::XModel > xModel; + + const rtl::OUString aModuleManager( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.frame.ModuleManager" )); + css::uno::Reference< css::frame::XModuleManager > xModuleManager( xSMGR->createInstance( aModuleManager ), css::uno::UNO_QUERY_THROW ); + if ( !xModuleManager.is() ) + { + rReq.Done(sal_False); + return; + } + + rtl::OUString aModule; + try + { + aModule = xModuleManager->identify( xFrame ); + } + catch ( css::uno::RuntimeException& ) + { + throw; + } + catch ( css::uno::Exception& ) + { + } + + if ( xFrame.is() ) + { + css::uno::Reference< css::frame::XController > xController = xFrame->getController(); + if ( xController.is() ) + xModel = xController->getModel(); + } + + // We need at least a valid module name and model reference + css::uno::Reference< css::frame::XStorable > xStorable( xModel, css::uno::UNO_QUERY ); + if ( xModel.is() && xStorable.is() ) + { + rtl::OUString aFilterName; + rtl::OUString aTypeName( RTL_CONSTASCII_USTRINGPARAM( HTML_DOCUMENT_TYPE )); + rtl::OUString aFileName; + rtl::OUString aExtension( RTL_CONSTASCII_USTRINGPARAM( "htm" )); + + rtl::OUString aLocation = xStorable->getLocation(); + INetURLObject aFileObj( aLocation ); + + bool bPrivateProtocol = ( aFileObj.GetProtocol() == INET_PROT_PRIV_SOFFICE ); + bool bHasLocation = ( aLocation.getLength() > 0 ) && !bPrivateProtocol; + + css::uno::Reference< css::container::XContainerQuery > xContainerQuery( + xSMGR->createInstance( rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.FilterFactory" ))), + css::uno::UNO_QUERY_THROW ); + + // Retrieve filter from type + sal_Int32 nFilterFlags = FILTERFLAG_EXPORT; + aFilterName = impl_retrieveFilterNameFromTypeAndModule( xContainerQuery, aTypeName, aModule, nFilterFlags ); + if ( aFilterName.getLength() == 0 ) + { + // Draw/Impress uses a different type. 2nd chance try to use alternative type name + aFilterName = impl_retrieveFilterNameFromTypeAndModule( + xContainerQuery, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( HTML_GRAPHIC_TYPE )), aModule, nFilterFlags ); + } + + // No filter found => error + // No type and no location => error + if (( aFilterName.getLength() == 0 ) || ( aTypeName.getLength() == 0 )) + { + rReq.Done(sal_False); + return; + } + + // Use provided save file name. If empty determine file name + if ( !bHasLocation ) + { + // Create a default file name with the correct extension + const rtl::OUString aPreviewFileName( RTL_CONSTASCII_USTRINGPARAM( "webpreview" )); + aFileName = aPreviewFileName; + } + else + { + // Determine file name from model + INetURLObject aFObj( xStorable->getLocation() ); + aFileName = aFObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::NO_DECODE ); + } + + OSL_ASSERT( aFilterName.getLength() > 0 ); + OSL_ASSERT( aFileName.getLength() > 0 ); + + // Creates a temporary directory to store our predefined file into it. + ::utl::TempFile aTempDir( NULL, sal_True ); + + INetURLObject aFilePathObj( aTempDir.GetURL() ); + aFilePathObj.insertName( aFileName ); + aFilePathObj.setExtension( aExtension ); + + rtl::OUString aFileURL = aFilePathObj.GetMainURL( INetURLObject::NO_DECODE ); + + css::uno::Sequence< css::beans::PropertyValue > aArgs( 1 ); + aArgs[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" )); + aArgs[0].Value = css::uno::makeAny( aFilterName ); + + // Store document in the html format + try + { + xStorable->storeToURL( aFileURL, aArgs ); + } + catch ( com::sun::star::io::IOException& ) + { + rReq.Done(sal_False); + return; + } + + ::com::sun::star::uno::Reference< XSystemShellExecute > xSystemShellExecute( xSMGR->createInstance( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.system.SystemShellExecute"))), + css::uno::UNO_QUERY ); + + sal_Bool bRet( sal_True ); + if ( xSystemShellExecute.is() ) + { + try + { + xSystemShellExecute->execute( + aFileURL, ::rtl::OUString(), SystemShellExecuteFlags::DEFAULTS ); + } + catch ( uno::Exception& ) + { + SolarMutexGuard aGuard; + Window *pParent = SFX_APP()->GetTopWindow(); + ErrorBox( pParent, SfxResId( MSG_ERROR_NO_WEBBROWSER_FOUND )).Execute(); + bRet = sal_False; + } + } + + rReq.Done(bRet); + break; + } + else + { + rReq.Done(sal_False); + return; + } + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + case SID_PLUGINS_ACTIVE: + { + SFX_REQUEST_ARG(rReq, pShowItem, SfxBoolItem, nId, sal_False); + bool const bActive = (pShowItem) + ? pShowItem->GetValue() + : !pImp->m_bPlugInsActive; + // ggf. recorden + if ( !rReq.IsAPI() ) + rReq.AppendItem( SfxBoolItem( nId, bActive ) ); + + // Jetzt schon DONE aufrufen, da die Argumente evtl. einen Pool + // benutzen, der demn"achst weg ist + rReq.Done(sal_True); + + // ausfuehren + if (!pShowItem || (bActive != pImp->m_bPlugInsActive)) + { + SfxFrame* pTopFrame = &GetFrame()->GetTopFrame(); + if ( pTopFrame != &GetFrame()->GetFrame() ) + { + // FramesetDocument + SfxViewShell *pShell = pTopFrame->GetCurrentViewFrame()->GetViewShell(); + if ( pShell->GetInterface()->GetSlot( nId ) ) + pShell->ExecuteSlot( rReq ); + break; + } + + SfxFrameIterator aIter( *pTopFrame ); + while ( pTopFrame ) + { + if ( pTopFrame->GetCurrentViewFrame() ) + { + SfxViewShell *pView = pTopFrame->GetCurrentViewFrame()->GetViewShell(); + if ( pView ) + { + pView->pImp->m_bPlugInsActive = bActive; + Rectangle aVisArea = GetObjectShell()->GetVisArea(); + VisAreaChanged(aVisArea); + + // the plugins might need change in their state + SfxInPlaceClientList *pClients = pView->GetIPClientList_Impl(sal_False); + if ( pClients ) + { + for ( size_t n = 0; n < pClients->size(); n++) + { + SfxInPlaceClient* pIPClient = pClients->at( n ); + if ( pIPClient ) + pView->CheckIPClient_Impl( pIPClient, aVisArea ); + } + } + } + } + + if ( !pTopFrame->GetParentFrame() ) + pTopFrame = aIter.FirstFrame(); + else + pTopFrame = aIter.NextFrame( *pTopFrame ); + } + } + + break; + } + } +} + +//-------------------------------------------------------------------- + +void SfxViewShell::GetState_Impl( SfxItemSet &rSet ) +{ + DBG_CHKTHIS(SfxViewShell, 0); + + SfxWhichIter aIter( rSet ); + for ( sal_uInt16 nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() ) + { + switch ( nSID ) + { + case SID_STYLE_CATALOG: + { + if ( !GetViewFrame()->KnowsChildWindow( SID_STYLE_DESIGNER ) ) + rSet.DisableItem( nSID ); + break; + } + + // Printer functions + case SID_PRINTDOC: + case SID_PRINTDOCDIRECT: + case SID_SETUPPRINTER: + case SID_PRINTER_NAME: + { + bool bEnabled = pImp->m_bCanPrint && !pImp->m_nPrinterLocks; + bEnabled = bEnabled && !Application::GetSettings().GetMiscSettings().GetDisablePrinting(); + if ( bEnabled ) + { + SfxPrinter *pPrinter = GetPrinter(sal_False); + + if ( SID_PRINTDOCDIRECT == nSID ) + { + rtl::OUString aPrinterName; + if ( pPrinter != NULL ) + aPrinterName = pPrinter->GetName(); + else + aPrinterName = Printer::GetDefaultPrinterName(); + if ( aPrinterName.getLength() > 0 ) + { + uno::Reference < frame::XFrame > xFrame( pFrame->GetFrame().GetFrameInterface() ); + + ::rtl::OUStringBuffer aBuffer( 60 ); + aBuffer.append( RetrieveLabelFromCommand( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:PrintDefault" )), + xFrame )); + aBuffer.appendAscii( " (" ); + aBuffer.append( aPrinterName ); + aBuffer.appendAscii( ")" ); + + rSet.Put( SfxStringItem( SID_PRINTDOCDIRECT, aBuffer.makeStringAndClear() ) ); + } + } + bEnabled = !pPrinter || !pPrinter->IsPrinting(); + } + break; + } + + // Mail functions + case SID_MAIL_SENDDOCASPDF: + case SID_MAIL_SENDDOC: + case SID_MAIL_SENDDOCASFORMAT: + { + sal_Bool bEnable = !GetViewFrame()->HasChildWindow( SID_MAIL_CHILDWIN ); + if ( !bEnable ) + rSet.DisableItem( nSID ); + break; + } + + // PlugIns running + case SID_PLUGINS_ACTIVE: + { + rSet.Put( SfxBoolItem( SID_PLUGINS_ACTIVE, + !pImp->m_bPlugInsActive) ); + break; + } + case SID_STYLE_FAMILY : + { + rSet.Put( SfxUInt16Item( SID_STYLE_FAMILY, pImp->m_nFamily ) ); + break; + } + } + } +} + +//-------------------------------------------------------------------- + +void SfxViewShell::SetZoomFactor( const Fraction &rZoomX, + const Fraction &rZoomY ) +{ + DBG_ASSERT( GetWindow(), "no window" ); + MapMode aMap( GetWindow()->GetMapMode() ); + aMap.SetScaleX( rZoomX ); + aMap.SetScaleY( rZoomY ); + GetWindow()->SetMapMode( aMap ); +} + +//-------------------------------------------------------------------- +ErrCode SfxViewShell::DoVerb(long /*nVerb*/) + +/* [Description] + + Virtual Method used to perform a Verb on a selected Object. + Since this Object is just known by the derived classes, DoVerb + must be overloaded. +*/ + +{ + return ERRCODE_SO_NOVERBS; +} + +//-------------------------------------------------------------------- + +void SfxViewShell::OutplaceActivated( sal_Bool bActive, SfxInPlaceClient* /*pClient*/ ) +{ + if ( !bActive ) + GetFrame()->GetFrame().Appear(); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::InplaceActivating( SfxInPlaceClient* /*pClient*/ ) +{ + // TODO/LATER: painting of the bitmap can be stopped, it is required if CLIPCHILDREN problem #i25788# is not solved, + // but may be the bug will not affect the real office vcl windows, then it is not required +} + +//-------------------------------------------------------------------- + +void SfxViewShell::InplaceDeactivated( SfxInPlaceClient* /*pClient*/ ) +{ + // TODO/LATER: paint the replacement image in normal way if the painting was stopped +} + +//-------------------------------------------------------------------- + +void SfxViewShell::UIActivating( SfxInPlaceClient* /*pClient*/ ) +{ + uno::Reference < frame::XFrame > xOwnFrame( pFrame->GetFrame().GetFrameInterface() ); + uno::Reference < frame::XFramesSupplier > xParentFrame( xOwnFrame->getCreator(), uno::UNO_QUERY ); + if ( xParentFrame.is() ) + xParentFrame->setActiveFrame( xOwnFrame ); + + pFrame->GetBindings().HidePopups(sal_True); + pFrame->GetDispatcher()->Update_Impl( sal_True ); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::UIDeactivated( SfxInPlaceClient* /*pClient*/ ) +{ + if ( !pFrame->GetFrame().IsClosing_Impl() || + SfxViewFrame::Current() != pFrame ) + pFrame->GetDispatcher()->Update_Impl( sal_True ); + pFrame->GetBindings().HidePopups(sal_False); + +} + +//-------------------------------------------------------------------- + +SfxInPlaceClient* SfxViewShell::FindIPClient +( + const uno::Reference < embed::XEmbeddedObject >& xObj, + Window* pObjParentWin +) const +{ + SfxInPlaceClientList *pClients = GetIPClientList_Impl(sal_False); + if ( !pClients ) + return 0; + + if( !pObjParentWin ) + pObjParentWin = GetWindow(); + for ( size_t n = 0; n < pClients->size(); n++) + { + SfxInPlaceClient *pIPClient = (SfxInPlaceClient*) pClients->at( n ); + if ( pIPClient->GetObject() == xObj && pIPClient->GetEditWin() == pObjParentWin ) + return pIPClient; + } + + return 0; +} + +//-------------------------------------------------------------------- + +SfxInPlaceClient* SfxViewShell::GetIPClient() const +{ + return GetUIActiveClient(); +} + +//-------------------------------------------------------------------- + +SfxInPlaceClient* SfxViewShell::GetUIActiveIPClient_Impl() const +{ + // this method is needed as long as SFX still manages the border space for ChildWindows (see SfxFrame::Resize) + SfxInPlaceClientList *pClients = GetIPClientList_Impl(sal_False); + if ( !pClients ) + return 0; + + for ( size_t n = 0; n < pClients->size(); n++) + { + SfxInPlaceClient* pIPClient = pClients->at( n ); + if ( pIPClient->IsUIActive() ) + return pIPClient; + } + + return NULL; +} + +SfxInPlaceClient* SfxViewShell::GetUIActiveClient() const +{ + SfxInPlaceClientList *pClients = GetIPClientList_Impl(sal_False); + if ( !pClients ) + return 0; + + for ( size_t n = 0; n < pClients->size(); n++) + { + SfxInPlaceClient* pIPClient = pClients->at( n ); + if ( pIPClient->IsObjectUIActive() ) + return pIPClient; + } + + return NULL; +} + +//-------------------------------------------------------------------- + +void SfxViewShell::Activate( sal_Bool bMDI ) +{ + DBG_CHKTHIS(SfxViewShell, 0); + if ( bMDI ) + { + SfxObjectShell *pSh = GetViewFrame()->GetObjectShell(); + if ( pSh->GetModel().is() ) + pSh->GetModel()->setCurrentController( GetViewFrame()->GetFrame().GetController() ); + + SetCurrentDocument(); + } +} + +//-------------------------------------------------------------------- + +void SfxViewShell::Deactivate(sal_Bool /*bMDI*/) +{ + DBG_CHKTHIS(SfxViewShell, 0); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::AdjustPosSizePixel +( + const Point& /*rToolOffset*/,// Upper left corner Tools in Frame-Window + const Size& /*rSize*/ // All available sizes. +) + +{ + DBG_CHKTHIS(SfxViewShell, 0); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::Move() + +/* [Description] + + This virtual Method is called when the window displayed in the + SfxViewShell gets a StarView-Move() notification. + + This base implementation does not have to be called. . + + [Note] + + This Method can be used to cancel a selection, in order to catch the + mouse movement which is due to moving a window. + + For now the notification does not work In-Place. +*/ + +{ +} + +//-------------------------------------------------------------------- + +void SfxViewShell::OuterResizePixel +( + const Point& /*rToolOffset*/,// Upper left corner Tools in Frame-Window + const Size& /*rSize*/ // All available sizes. +) + +/* [Description] + + This Method has to be overloaded to be able to react to the size-change of + the View. Thus the View is defined as the Edit window and also the + attached Tools are defined (for example the ruler). + + The Edit window must not be changed either in size or position. + + The Vis-Area of SfxObjectShell, its scale and position can be changed + here. The mainuse is to change the size of the Vis-Area. + + If the Border is changed due to the new calculation then this has to be set + by <SfxViewShell::SetBorderPixel(const SvBorder&)>. The Postioning of Tools + is only allowed after the calling of 'SetBorderPixel'. + + [Example] + + void AppViewSh::OuterViewResizePixel( const Point &rOfs, const Size &rSz ) + +{ + // Calculate Tool position and size externally, do not set! + // (due to the following Border calculation) + Point aHLinPos...; Size aHLinSz...; + ... + + // Calculate and Set a Border of Tools which matches rSize. + SvBorder aBorder... + SetBorderPixel( aBorder ); // Allow Positioning from here on. + + // Arrange Tools + pHLin->SetPosSizePixel( aHLinPos, aHLinSz ); + ... + } + + [Cross-reference] + + <SfxViewShell::InnerResizePixel(const Point&,const Size& rSize)> +*/ + +{ + DBG_CHKTHIS(SfxViewShell, 0); + SetBorderPixel( SvBorder() ); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::InnerResizePixel +( + const Point& /*rToolOffset*/,// Upper left corner Tools in Frame-Window + const Size& /*rSize*/ // All available sizes. +) + +/* [Description] + + This Method has to be overloaded to be able to react to the size-change of + the Edit window. + + The Edit window must not be changed either in size or position. + Neither the Vis-Area of SfxObjectShell nor its scale or position are + allowed to be changed + + If the Border is changed due to the new calculation then is has to be set + by <SfxViewShell::SetBorderPixel(const SvBorder&)>. + The Postioning of Tools is only allowed after the calling of + 'SetBorderPixel'. + + + [Note] + + void AppViewSh::InnerViewResizePixel( const Point &rOfs, const Size &rSz ) + { + // Calculate Tool position and size internally, do not set! + // (due to the following Border calculation) + Point aHLinPos...; Size aHLinSz...; + ... + + // Calculate and Set a Border of Tools which matches rSize. + SvBorder aBorder... + SetBorderPixel( aBorder ); // Allow Positioning from here on. + + // Arrange Tools + pHLin->SetPosSizePixel( aHLinPos, aHLinSz ); + ... + } + + [Cross-reference] + + <SfxViewShell::OuterResizePixel(const Point&,const Size& rSize)> +*/ + +{ + DBG_CHKTHIS(SfxViewShell, 0); + SetBorderPixel( SvBorder() ); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::InvalidateBorder() +{ + DBG_CHKTHIS(SfxViewShell, 0); + DBG_ASSERT( GetViewFrame(), "SfxViewShell without SfxViewFrame" ); + + GetViewFrame()->InvalidateBorderImpl( this ); + if (pImp->m_pController.is()) + { + pImp->m_pController->BorderWidthsChanged_Impl(); + } +} + +//-------------------------------------------------------------------- + +void SfxViewShell::SetBorderPixel( const SvBorder &rBorder ) +{ + DBG_CHKTHIS(SfxViewShell, 0); + DBG_ASSERT( GetViewFrame(), "SfxViewShell without SfxViewFrame" ); + + { + GetViewFrame()->SetBorderPixelImpl( this, rBorder ); + + // notify related controller that border size is changed + if (pImp->m_pController.is()) + { + pImp->m_pController->BorderWidthsChanged_Impl(); + } + } +} + +//-------------------------------------------------------------------- + +const SvBorder& SfxViewShell::GetBorderPixel() const +{ + DBG_CHKTHIS(SfxViewShell, 0); + DBG_ASSERT( GetViewFrame(), "SfxViewShell without SfxViewFrame" ); + + return GetViewFrame()->GetBorderPixelImpl( this ); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::SetWindow +( + Window* pViewPort // For example Null pointer in the Destructor. +) + +/* [Description] + + With this method the SfxViewShell is set in the data window. This is + needed for the in-place container and for restoring the proper focus. + + Even in-place-active the conversion of the ViewPort Windows is forbidden. +*/ + +{ + if( pWindow == pViewPort ) + return; + + // Disconnect existing IP-Clients if possible + DisconnectAllClients(); + + //TODO: should we have a "ReconnectAllClients" method? + DiscardClients_Impl(); + + // Switch View-Port + sal_Bool bHadFocus = pWindow ? pWindow->HasChildPathFocus( sal_True ) : sal_False; + pWindow = pViewPort; + + if( pWindow ) + { + // Disable automatic GUI mirroring (right-to-left) for document windows + pWindow->EnableRTL( sal_False ); + } + + if ( bHadFocus && pWindow ) + pWindow->GrabFocus(); + //TODO/CLEANUP + //Do we still need this Method?! + //SFX_APP()->GrabFocus( pWindow ); +} + +//-------------------------------------------------------------------- + +Size SfxViewShell::GetOptimalSizePixel() const +{ + OSL_FAIL( "Useless call!" ); + return Size(); +} + +//------------------------------------------------------------------------ + +SfxViewShell::SfxViewShell +( + SfxViewFrame* pViewFrame, /* <SfxViewFrame>, which will be + displayed in this View */ + sal_uInt16 nFlags /* See <SfxViewShell-Flags> */ +) + +: SfxShell(this) +, pImp( new SfxViewShell_Impl(nFlags) ) + ,pIPClientList( 0 ) + ,pFrame(pViewFrame) + ,pSubShell(0) + ,pWindow(0) + ,bNoNewWindow( 0 != (nFlags & SFX_VIEW_NO_NEWWINDOW) ) +{ + DBG_CTOR(SfxViewShell, 0); + + if ( pViewFrame->GetParentViewFrame() ) + { + pImp->m_bPlugInsActive = pViewFrame->GetParentViewFrame() + ->GetViewShell()->pImp->m_bPlugInsActive; + } + SetMargin( pViewFrame->GetMargin_Impl() ); + + SetPool( &pViewFrame->GetObjectShell()->GetPool() ); + StartListening(*pViewFrame->GetObjectShell()); + + // Insert into list + const SfxViewShell *pThis = this; // due to the sick Array syntax + SfxViewShellArr_Impl &rViewArr = SFX_APP()->GetViewShells_Impl(); + rViewArr.Insert(pThis, rViewArr.Count() ); +} + +//-------------------------------------------------------------------- + +SfxViewShell::~SfxViewShell() +{ + DBG_DTOR(SfxViewShell, 0); + + // Remove from list + const SfxViewShell *pThis = this; + SfxViewShellArr_Impl &rViewArr = SFX_APP()->GetViewShells_Impl(); + rViewArr.Remove( rViewArr.GetPos(pThis) ); + + if ( pImp->xClipboardListener.is() ) + { + pImp->xClipboardListener->DisconnectViewShell(); + pImp->xClipboardListener = NULL; + } + + if (pImp->m_pController.is()) + { + pImp->m_pController->ReleaseShell_Impl(); + pImp->m_pController.clear(); + } + + DELETEZ( pImp ); + DELETEZ( pIPClientList ); +} + +//-------------------------------------------------------------------- + +sal_uInt16 SfxViewShell::PrepareClose +( + sal_Bool bUI, // TRUE: Allow Dialog and so on, FALSE: silent-mode + sal_Bool /*bForBrowsing*/ +) +{ + SfxPrinter *pPrinter = GetPrinter(); + if ( pPrinter && pPrinter->IsPrinting() ) + { + if ( bUI ) + { + InfoBox aInfoBox( &GetViewFrame()->GetWindow(), SfxResId( MSG_CANT_CLOSE ) ); + aInfoBox.Execute(); + } + + return sal_False; + } + + if( GetViewFrame()->IsInModalMode() ) + return sal_False; + + if( bUI && GetViewFrame()->GetDispatcher()->IsLocked() ) + return sal_False; + + return sal_True; +} + +//-------------------------------------------------------------------- + +SfxViewShell* SfxViewShell::Current() +{ + SfxViewFrame *pCurrent = SfxViewFrame::Current(); + return pCurrent ? pCurrent->GetViewShell() : NULL; +} + +//-------------------------------------------------------------------- + +SfxViewShell* SfxViewShell::Get( const Reference< XController>& i_rController ) +{ + if ( !i_rController.is() ) + return NULL; + + for ( SfxViewShell* pViewShell = SfxViewShell::GetFirst( NULL, sal_False ); + pViewShell; + pViewShell = SfxViewShell::GetNext( *pViewShell, NULL, sal_False ) + ) + { + if ( pViewShell->GetController() == i_rController ) + return pViewShell; + } + return NULL; +} + +//-------------------------------------------------------------------- + +SdrView* SfxViewShell::GetDrawView() const + +/* [Description] + + This virtual Method has to be overloded by the sub classes, to be able + make the Property-Editor available. + + The default implementation does always return zero. +*/ + +{ + return 0; +} + +//-------------------------------------------------------------------- + +String SfxViewShell::GetSelectionText +( + sal_Bool /*bCompleteWords*/ /* FALSE (default) + Only the actual selected text is returned. + + TRUE + The selected text is expanded so that only + whole words are returned. As word separators + these are used: white spaces and punctuation + ".,;" and single and double quotes. + */ +) + +/* [Description] + + This Method can be overloaded by the programmers to return a text that + is included in the current selection. This is for example used when + sending emails. + + When called with "CompleteWords == TRUE", it is for example sufficent + with having the Cursor positioned somewhere within an URL in-order + to have the entire URL returned. +*/ + +{ + return String(); +} + +//-------------------------------------------------------------------- + +sal_Bool SfxViewShell::HasSelection( sal_Bool ) const + +/* [Description] + + With this virtual Method can a for example a Dialog be queried, to + check if something is selected in the current view. If the Parameter + is <BOOL> TRUE then it is checked wether some text is selected. +*/ + +{ + return sal_False; +} + +//-------------------------------------------------------------------- + +void SfxViewShell::SetSubShell( SfxShell *pShell ) + +/* [Description] + + With this method a selection or cursor Shell can be registered, which are + automatically pushed to SfxDispatcher immediately after SfxViewShell, and + and automatically popped immediately before SfxViewShell. + + If the SfxViewShell instance is already pushed, then pShell will be + immediately pushed as well. Is another SfxShell instance registered by + using SetSubShell, which was previously registered, the previously + registered shell is popped automatically if possible. With pShell==0 + the current sub-shell be can thus be unregistered. +*/ + +{ + // Is this ViewShell even active? + SfxDispatcher *pDisp = pFrame->GetDispatcher(); + if ( pDisp->IsActive(*this) ) + { + // Update Dispatcher + if ( pSubShell ) + pDisp->Pop(*pSubShell); + if ( pShell ) + pDisp->Push(*pShell); + pDisp->Flush(); + } + + pSubShell = pShell; +} + +void SfxViewShell::AddSubShell( SfxShell& rShell ) +{ + pImp->aArr.Insert( &rShell, pImp->aArr.Count() ); + SfxDispatcher *pDisp = pFrame->GetDispatcher(); + if ( pDisp->IsActive(*this) ) + { + pDisp->Push(rShell); + pDisp->Flush(); + } +} + +void SfxViewShell::RemoveSubShell( SfxShell* pShell ) +{ + SfxDispatcher *pDisp = pFrame->GetDispatcher(); + if ( !pShell ) + { + sal_uInt16 nCount = pImp->aArr.Count(); + if ( pDisp->IsActive(*this) ) + { + for ( sal_uInt16 n=nCount; n>0; n-- ) + pDisp->Pop( *pImp->aArr[n-1] ); + pDisp->Flush(); + } + + pImp->aArr.Remove(0, nCount); + } + else + { + sal_uInt16 nPos = pImp->aArr.GetPos( pShell ); + if ( nPos != 0xFFFF ) + { + pImp->aArr.Remove( nPos ); + if ( pDisp->IsActive(*this) ) + { + pDisp->RemoveShell_Impl( *pShell ); + pDisp->Flush(); + } + } + } +} + +SfxShell* SfxViewShell::GetSubShell( sal_uInt16 nNo ) +{ + sal_uInt16 nCount = pImp->aArr.Count(); + if ( nNo<nCount ) + return pImp->aArr[nCount-nNo-1]; + return NULL; +} + +void SfxViewShell::PushSubShells_Impl( sal_Bool bPush ) +{ + sal_uInt16 nCount = pImp->aArr.Count(); + SfxDispatcher *pDisp = pFrame->GetDispatcher(); + if ( bPush ) + { + for ( sal_uInt16 n=0; n<nCount; n++ ) + pDisp->Push( *pImp->aArr[n] ); + } + else if ( nCount ) + { + SfxShell& rPopUntil = *pImp->aArr[0]; + if ( pDisp->GetShellLevel( rPopUntil ) != USHRT_MAX ) + pDisp->Pop( rPopUntil, SFX_SHELL_POP_UNTIL ); + } + + pDisp->Flush(); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::WriteUserData( String&, sal_Bool ) +{ +} + +//-------------------------------------------------------------------- + +void SfxViewShell::ReadUserData(const String&, sal_Bool ) +{ +} + +void SfxViewShell::ReadUserDataSequence ( const ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >&, sal_Bool ) +{ +} + +void SfxViewShell::WriteUserDataSequence ( ::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue >&, sal_Bool ) +{ +} + + +//-------------------------------------------------------------------- +// returns the first shell of spec. type viewing the specified doc. + +SfxViewShell* SfxViewShell::GetFirst +( + const TypeId* pType, + sal_Bool bOnlyVisible +) +{ + // search for a SfxViewShell of the specified type + SfxViewShellArr_Impl &rShells = SFX_APP()->GetViewShells_Impl(); + SfxViewFrameArr_Impl &rFrames = SFX_APP()->GetViewFrames_Impl(); + for ( sal_uInt16 nPos = 0; nPos < rShells.Count(); ++nPos ) + { + SfxViewShell *pShell = rShells.GetObject(nPos); + if ( pShell ) + { + // sometimes dangling SfxViewShells exist that point to a dead SfxViewFrame + // these ViewShells shouldn't be accessible anymore + // a destroyed ViewFrame is not in the ViewFrame array anymore, so checking this array helps + for ( sal_uInt16 n=0; n<rFrames.Count(); ++n ) + { + SfxViewFrame *pFrame = rFrames.GetObject(n); + if ( pFrame == pShell->GetViewFrame() ) + { + // only ViewShells with a valid ViewFrame will be returned + if ( ( !bOnlyVisible || pFrame->IsVisible() ) && ( !pType || pShell->IsA(*pType) ) ) + return pShell; + break; + } + } + } + } + + return 0; +} + +//-------------------------------------------------------------------- +// returns the next shell of spec. type viewing the specified doc. + +SfxViewShell* SfxViewShell::GetNext +( + const SfxViewShell& rPrev, + const TypeId* pType, + sal_Bool bOnlyVisible +) +{ + SfxViewShellArr_Impl &rShells = SFX_APP()->GetViewShells_Impl(); + SfxViewFrameArr_Impl &rFrames = SFX_APP()->GetViewFrames_Impl(); + sal_uInt16 nPos; + for ( nPos = 0; nPos < rShells.Count(); ++nPos ) + if ( rShells.GetObject(nPos) == &rPrev ) + break; + + for ( ++nPos; nPos < rShells.Count(); ++nPos ) + { + SfxViewShell *pShell = rShells.GetObject(nPos); + if ( pShell ) + { + // sometimes dangling SfxViewShells exist that point to a dead SfxViewFrame + // these ViewShells shouldn't be accessible anymore + // a destroyed ViewFrame is not in the ViewFrame array anymore, so checking this array helps + for ( sal_uInt16 n=0; n<rFrames.Count(); ++n ) + { + SfxViewFrame *pFrame = rFrames.GetObject(n); + if ( pFrame == pShell->GetViewFrame() ) + { + // only ViewShells with a valid ViewFrame will be returned + if ( ( !bOnlyVisible || pFrame->IsVisible() ) && ( !pType || pShell->IsA(*pType) ) ) + return pShell; + break; + } + } + } + } + + return 0; +} + +//-------------------------------------------------------------------- + +void SfxViewShell::Notify( SfxBroadcaster& rBC, + const SfxHint& rHint ) +{ + if ( rHint.IsA(TYPE(SfxEventHint)) ) + { + switch ( ((SfxEventHint&)rHint).GetEventId() ) + { + case SFX_EVENT_LOADFINISHED: + { + if ( GetController().is() ) + { + // avoid access to dangling ViewShells + SfxViewFrameArr_Impl &rFrames = SFX_APP()->GetViewFrames_Impl(); + for ( sal_uInt16 n=0; n<rFrames.Count(); ++n ) + { + SfxViewFrame *frame = rFrames.GetObject(n); + if ( frame == GetViewFrame() && &rBC == GetObjectShell() ) + { + SfxItemSet* pSet = GetObjectShell()->GetMedium()->GetItemSet(); + SFX_ITEMSET_ARG( pSet, pItem, SfxUnoAnyItem, SID_VIEW_DATA, sal_False ); + if ( pItem ) + { + pImp->m_pController->restoreViewData( + pItem->GetValue() ); + pSet->ClearItem( SID_VIEW_DATA ); + } + + break; + } + } + } + + break; + } + } + } +} + +//-------------------------------------------------------------------- + +sal_Bool SfxViewShell::ExecKey_Impl(const KeyEvent& aKey) +{ + if (!pImp->m_pAccExec.get()) + { + pImp->m_pAccExec.reset( + ::svt::AcceleratorExecute::createAcceleratorHelper() ); + pImp->m_pAccExec->init(::comphelper::getProcessServiceFactory(), + pFrame->GetFrame().GetFrameInterface()); + } + + return pImp->m_pAccExec->execute(aKey.GetKeyCode()); +} + +//-------------------------------------------------------------------- + +bool SfxViewShell::KeyInput( const KeyEvent &rKeyEvent ) + +/* [Description] + + This Method executes the KeyEvent 'rKeyEvent' of the Keys (Accelerator) + configured either direct or indirect (for example by the Application) + in the SfxViewShell. + + [Return value] + + bool TRUE + The Key (Accelerator) is configured and the + the associated Handler was called + + FALSE + The Key (Accelerator) is not configured and + subsequently no Handler was called + + [Cross-reference] + + <SfxApplication::KeyInput(const KeyEvent&)> +*/ +{ + return ExecKey_Impl(rKeyEvent); +} + +bool SfxViewShell::GlobalKeyInput_Impl( const KeyEvent &rKeyEvent ) +{ + return ExecKey_Impl(rKeyEvent); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::ShowCursor( bool /*bOn*/ ) + +/* [Description] + + This Method has to be overloaded by the subclasses so that SFx from + the Cursor can be switched on and off. This happes for example with + with the running <SfxProgress>. +*/ + +{ +} + +//-------------------------------------------------------------------- + +void SfxViewShell::GotFocus() const + +/* [Description] + + This Method has to be called by the programmer, when the + Edit window has received the focus. This gives for example the SFx + the power to turn on the accelerator. + + [Note] + + <StarView> does sadly enough not provide the possibillity to attach + such "side-way" events. +*/ + +{ +} + +//-------------------------------------------------------------------- +void SfxViewShell::ResetAllClients_Impl( SfxInPlaceClient *pIP ) +{ + + SfxInPlaceClientList *pClients = GetIPClientList_Impl(sal_False); + if ( !pClients ) + return; + + for ( size_t n = 0; n < pClients->size(); n++ ) + { + SfxInPlaceClient* pIPClient = pClients->at( n ); + if( pIPClient != pIP ) + pIPClient->ResetObject(); + } +} + +//-------------------------------------------------------------------- + +void SfxViewShell::DisconnectAllClients() +{ + SfxInPlaceClientList *pClients = GetIPClientList_Impl(sal_False); + if ( !pClients ) + return; + + for ( size_t n = 0; n < pClients->size(); ) + // clients will remove themselves from the list + delete pClients->at( n ); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::QueryObjAreaPixel( Rectangle& ) const +{ +} + +//-------------------------------------------------------------------- + +void SfxViewShell::AdjustVisArea(const Rectangle& rRect) +{ + DBG_ASSERT (pFrame, "No Frame?"); + GetObjectShell()->SetVisArea( rRect ); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::VisAreaChanged(const Rectangle& /*rVisArea*/) +{ + SfxInPlaceClientList *pClients = GetIPClientList_Impl(sal_False); + if ( !pClients ) + return; + + for ( size_t n = 0; n < pClients->size(); n++) + { + SfxInPlaceClient* pIPClient = pClients->at( n ); + if ( pIPClient->IsObjectInPlaceActive() ) + // client is active, notify client that the VisArea might have changed + pIPClient->VisAreaChanged(); + } +} + +//-------------------------------------------------------------------- +void SfxViewShell::CheckIPClient_Impl( SfxInPlaceClient *pIPClient, const Rectangle& rVisArea ) +{ + if ( GetObjectShell()->IsInClose() ) + return; + + sal_Bool bAlwaysActive = + ( ( pIPClient->GetObjectMiscStatus() & embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY ) != 0 ); + sal_Bool bActiveWhenVisible = + ( ( pIPClient->GetObjectMiscStatus() & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE ) != 0 ); + + // this method is called when either a client is created or the "Edit/Plugins" checkbox is checked + if ( !pIPClient->IsObjectInPlaceActive() && pImp->m_bPlugInsActive ) + { + // object in client is currently not active + // check if the object wants to be activated always or when it becomes at least partially visible + // TODO/LATER: maybe we should use the scaled area instead of the ObjArea?! + if ( bAlwaysActive || (bActiveWhenVisible && rVisArea.IsOver(pIPClient->GetObjArea())) ) + { + try + { + pIPClient->GetObject()->changeState( embed::EmbedStates::INPLACE_ACTIVE ); + } + catch ( uno::Exception& ) + { + } + } + } + else if (!pImp->m_bPlugInsActive) + { + // object in client is currently active and "Edit/Plugins" checkbox is selected + // check if the object wants to be activated always or when it becomes at least partially visible + // in this case selecting of the "Edit/Plugin" checkbox should let such objects deactivate + if ( bAlwaysActive || bActiveWhenVisible ) + pIPClient->GetObject()->changeState( embed::EmbedStates::RUNNING ); + } +} + +//-------------------------------------------------------------------- + +sal_Bool SfxViewShell::PlugInsActive() const +{ + return pImp->m_bPlugInsActive; +} + +//-------------------------------------------------------------------- +void SfxViewShell::DiscardClients_Impl() + +/* [Description] + + The purpose of this Method is to prevent the saving of Objects when closing + the Document, if the user has chosen to close without saving. +*/ + +{ + SfxInPlaceClientList *pClients = GetIPClientList_Impl(sal_False); + if ( !pClients ) + return; + + for ( size_t n = 0; n < pClients->size(); ) + delete pClients->at( n ); +} + +//-------------------------------------------------------------------- + +SfxScrollingMode SfxViewShell::GetScrollingMode() const +{ + return pImp->m_eScroll; +} + +//-------------------------------------------------------------------- + +void SfxViewShell::SetScrollingMode( SfxScrollingMode eMode ) +{ + pImp->m_eScroll = eMode; +} + +//-------------------------------------------------------------------- + +SfxObjectShell* SfxViewShell::GetObjectShell() +{ + return pFrame ? pFrame->GetObjectShell() : NULL; +} + +//-------------------------------------------------------------------- + +Reference< XModel > SfxViewShell::GetCurrentDocument() const +{ + Reference< XModel > xDocument; + + const SfxObjectShell* pDocShell( const_cast< SfxViewShell* >( this )->GetObjectShell() ); + OSL_ENSURE( pDocShell, "SfxViewFrame::GetCurrentDocument: no DocShell!?" ); + if ( pDocShell ) + xDocument = pDocShell->GetModel(); + return xDocument; +} + +//-------------------------------------------------------------------- + +void SfxViewShell::SetCurrentDocument() const +{ + uno::Reference< frame::XModel > xDocument( GetCurrentDocument() ); + if ( xDocument.is() ) + SfxObjectShell::SetCurrentComponent( xDocument ); +} + +//-------------------------------------------------------------------- + +const Size& SfxViewShell::GetMargin() const +{ + return pImp->aMargin; +} + +//-------------------------------------------------------------------- + +void SfxViewShell::SetMargin( const Size& rSize ) +{ + // the default margin was verified using www.apple.com !! + Size aMargin = rSize; + if ( aMargin.Width() == -1 ) + aMargin.Width() = DEFAULT_MARGIN_WIDTH; + if ( aMargin.Height() == -1 ) + aMargin.Height() = DEFAULT_MARGIN_HEIGHT; + + if ( aMargin != pImp->aMargin ) + { + pImp->aMargin = aMargin; + MarginChanged(); + } +} + +//-------------------------------------------------------------------- + +void SfxViewShell::MarginChanged() +{ +} + +//-------------------------------------------------------------------- + +sal_Bool SfxViewShell::IsShowView_Impl() const +{ + return pImp->m_bIsShowView; +} + +//-------------------------------------------------------------------- + +SfxFrame* SfxViewShell::GetSmartSelf( SfxFrame* pSelf, SfxMedium& /*rMedium*/ ) +{ + return pSelf; +} + +//------------------------------------------------------------------------ + +void SfxViewShell::JumpToMark( const String& rMark ) +{ + SfxStringItem aMarkItem( SID_JUMPTOMARK, rMark ); + GetViewFrame()->GetDispatcher()->Execute( + SID_JUMPTOMARK, + SFX_CALLMODE_SYNCHRON|SFX_CALLMODE_RECORD, + &aMarkItem, 0L ); +} + +//------------------------------------------------------------------------ + +SfxInPlaceClientList* SfxViewShell::GetIPClientList_Impl( sal_Bool bCreate ) const +{ + if ( !pIPClientList && bCreate ) + ( (SfxViewShell*) this )->pIPClientList = new SfxInPlaceClientList; + return pIPClientList; +} + +void SfxViewShell::SetController( SfxBaseController* pController ) +{ + pImp->m_pController = pController; + pImp->m_bControllerSet = true; + + // there should be no old listener, but if there is one, it should be disconnected + if ( pImp->xClipboardListener.is() ) + pImp->xClipboardListener->DisconnectViewShell(); + + pImp->xClipboardListener = new SfxClipboardChangeListener( this, GetClipboardNotifier() ); +} + +Reference < XController > SfxViewShell::GetController() +{ + return pImp->m_pController.get(); +} + +SfxBaseController* SfxViewShell::GetBaseController_Impl() const +{ + return pImp->m_pController.get(); +} + +void SfxViewShell::AddContextMenuInterceptor_Impl( const REFERENCE< XCONTEXTMENUINTERCEPTOR >& xInterceptor ) +{ + pImp->aInterceptorContainer.addInterface( xInterceptor ); +} + +void SfxViewShell::RemoveContextMenuInterceptor_Impl( const REFERENCE< XCONTEXTMENUINTERCEPTOR >& xInterceptor ) +{ + pImp->aInterceptorContainer.removeInterface( xInterceptor ); +} + +::cppu::OInterfaceContainerHelper& SfxViewShell::GetContextMenuInterceptors() const +{ + return pImp->aInterceptorContainer; +} + +void Change( Menu* pMenu, SfxViewShell* pView ) +{ + SfxDispatcher *pDisp = pView->GetViewFrame()->GetDispatcher(); + sal_uInt16 nCount = pMenu->GetItemCount(); + for ( sal_uInt16 nPos=0; nPos<nCount; ++nPos ) + { + sal_uInt16 nId = pMenu->GetItemId(nPos); + String aCmd = pMenu->GetItemCommand(nId); + PopupMenu* pPopup = pMenu->GetPopupMenu(nId); + if ( pPopup ) + { + Change( pPopup, pView ); + } + else if ( nId < 5000 ) + { + if ( aCmd.CompareToAscii(".uno:", 5) == 0 ) + { + for (sal_uInt16 nIdx=0;;) + { + SfxShell *pShell=pDisp->GetShell(nIdx++); + if (pShell == NULL) + break; + const SfxInterface *pIFace = pShell->GetInterface(); + const SfxSlot* pSlot = pIFace->GetSlot( aCmd ); + if ( pSlot ) + { + pMenu->InsertItem( pSlot->GetSlotId(), pMenu->GetItemText( nId ), pMenu->GetItemBits( nId ), nPos ); + pMenu->SetItemCommand( pSlot->GetSlotId(), aCmd ); + pMenu->RemoveItem( nPos+1 ); + break; + } + } + } + } + } +} + + +sal_Bool SfxViewShell::TryContextMenuInterception( Menu& rIn, const ::rtl::OUString& rMenuIdentifier, Menu*& rpOut, ui::ContextMenuExecuteEvent aEvent ) +{ + rpOut = NULL; + sal_Bool bModified = sal_False; + + // create container from menu + aEvent.ActionTriggerContainer = ::framework::ActionTriggerHelper::CreateActionTriggerContainerFromMenu( + ::comphelper::getProcessServiceFactory(), &rIn, &rMenuIdentifier ); + + // get selection from controller + aEvent.Selection = uno::Reference < view::XSelectionSupplier > ( GetController(), uno::UNO_QUERY ); + + // call interceptors + ::cppu::OInterfaceIteratorHelper aIt( pImp->aInterceptorContainer ); + while( aIt.hasMoreElements() ) + { + try + { + ui::ContextMenuInterceptorAction eAction = + ((ui::XContextMenuInterceptor*)aIt.next())->notifyContextMenuExecute( aEvent ); + switch ( eAction ) + { + case ui::ContextMenuInterceptorAction_CANCELLED : + // interceptor does not want execution + return sal_False; + case ui::ContextMenuInterceptorAction_EXECUTE_MODIFIED : + // interceptor wants his modified menu to be executed + bModified = sal_True; + break; + case ui::ContextMenuInterceptorAction_CONTINUE_MODIFIED : + // interceptor has modified menu, but allows for calling other interceptors + bModified = sal_True; + continue; + case ui::ContextMenuInterceptorAction_IGNORED : + // interceptor is indifferent + continue; + default: + OSL_FAIL("Wrong return value of ContextMenuInterceptor!"); + continue; + } + } + catch( uno::RuntimeException& ) + { + aIt.remove(); + } + + break; + } + + if ( bModified ) + { + // container was modified, create a new window out of it + rpOut = new PopupMenu; + ::framework::ActionTriggerHelper::CreateMenuFromActionTriggerContainer( rpOut, aEvent.ActionTriggerContainer ); + + Change( rpOut, this ); + } + + return sal_True; +} + +void SfxViewShell::TakeOwnerShip_Impl() +{ + // currently there is only one reason to take OwnerShip: a hidden frame is printed + // so the ViewShell will check this on EndPrint (->prnmon.cxx) + pImp->m_bGotOwnership = true; +} + +void SfxViewShell::TakeFrameOwnerShip_Impl() +{ + // currently there is only one reason to take OwnerShip: a hidden frame is printed + // so the ViewShell will check this on EndPrint (->prnmon.cxx) + pImp->m_bGotFrameOwnership = true; +} + +void SfxViewShell::CheckOwnerShip_Impl() +{ + sal_Bool bSuccess = sal_False; + if (pImp->m_bGotOwnership) + { + uno::Reference < util::XCloseable > xModel( + GetObjectShell()->GetModel(), uno::UNO_QUERY ); + if ( xModel.is() ) + { + try + { + // this call will destroy this object in case of success! + xModel->close( sal_True ); + bSuccess = sal_True; + } + catch ( util::CloseVetoException& ) + { + } + } + } + + if (!bSuccess && pImp->m_bGotFrameOwnership) + { + // document couldn't be closed or it shouldn't, now try at least to close the frame + uno::Reference < util::XCloseable > xFrame( + GetViewFrame()->GetFrame().GetFrameInterface(), com::sun::star::uno::UNO_QUERY ); + if ( xFrame.is() ) + { + try + { + xFrame->close( sal_True ); + } + catch ( util::CloseVetoException& ) + { + } + } + } +} + +long SfxViewShell::HandleNotifyEvent_Impl( NotifyEvent& rEvent ) +{ + if (pImp->m_pController.is()) + return pImp->m_pController->HandleEvent_Impl( rEvent ); + return 0; +} + +sal_Bool SfxViewShell::HasKeyListeners_Impl() +{ + return (pImp->m_pController.is()) + ? pImp->m_pController->HasKeyListeners_Impl() : sal_False; +} + +sal_Bool SfxViewShell::HasMouseClickListeners_Impl() +{ + return (pImp->m_pController.is()) + ? pImp->m_pController->HasMouseClickListeners_Impl() : sal_False; +} + +void SfxViewShell::SetAdditionalPrintOptions( const com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue >& rOpts ) +{ + pImp->aPrintOpts = rOpts; +} + +sal_Bool SfxViewShell::Escape() +{ + return GetViewFrame()->GetBindings().Execute( SID_TERMINATE_INPLACEACTIVATION ); +} + +Reference< view::XRenderable > SfxViewShell::GetRenderable() +{ + Reference< view::XRenderable >xRender; + SfxObjectShell* pObj = GetObjectShell(); + if( pObj ) + { + Reference< frame::XModel > xModel( pObj->GetModel() ); + if( xModel.is() ) + xRender = Reference< view::XRenderable >( xModel, UNO_QUERY ); + } + return xRender; +} + +uno::Reference< datatransfer::clipboard::XClipboardNotifier > SfxViewShell::GetClipboardNotifier() +{ + uno::Reference< datatransfer::clipboard::XClipboardNotifier > xClipboardNotifier; + if ( GetViewFrame() ) + xClipboardNotifier = uno::Reference< datatransfer::clipboard::XClipboardNotifier >( GetViewFrame()->GetWindow().GetClipboard(), uno::UNO_QUERY ); + + return xClipboardNotifier; +} + +void SfxViewShell::AddRemoveClipboardListener( const uno::Reference < datatransfer::clipboard::XClipboardListener >& rClp, sal_Bool bAdd ) +{ + try + { + if ( GetViewFrame() ) + { + uno::Reference< datatransfer::clipboard::XClipboard > xClipboard( GetViewFrame()->GetWindow().GetClipboard() ); + if( xClipboard.is() ) + { + uno::Reference< datatransfer::clipboard::XClipboardNotifier > xClpbrdNtfr( xClipboard, uno::UNO_QUERY ); + if( xClpbrdNtfr.is() ) + { + if( bAdd ) + xClpbrdNtfr->addClipboardListener( rClp ); + else + xClpbrdNtfr->removeClipboardListener( rClp ); + } + } + } + } + catch( const uno::Exception& ) + { + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |