diff options
Diffstat (limited to 'sfx2/source/view')
-rw-r--r-- | sfx2/source/view/frame.cxx | 994 | ||||
-rw-r--r-- | sfx2/source/view/frame2.cxx | 484 | ||||
-rw-r--r-- | sfx2/source/view/frmload.cxx | 746 | ||||
-rw-r--r-- | sfx2/source/view/impframe.hxx | 100 | ||||
-rw-r--r-- | sfx2/source/view/impviewframe.hxx | 98 | ||||
-rw-r--r-- | sfx2/source/view/ipclient.cxx | 1163 | ||||
-rw-r--r-- | sfx2/source/view/makefile.mk | 65 | ||||
-rw-r--r-- | sfx2/source/view/orgmgr.cxx | 832 | ||||
-rw-r--r-- | sfx2/source/view/printer.cxx | 624 | ||||
-rw-r--r-- | sfx2/source/view/prnmon.cxx | 495 | ||||
-rw-r--r-- | sfx2/source/view/sfxbasecontroller.cxx | 1509 | ||||
-rw-r--r-- | sfx2/source/view/userinputinterception.cxx | 264 | ||||
-rw-r--r-- | sfx2/source/view/view.hrc | 126 | ||||
-rw-r--r-- | sfx2/source/view/view.src | 190 | ||||
-rw-r--r-- | sfx2/source/view/viewfac.cxx | 79 | ||||
-rw-r--r-- | sfx2/source/view/viewfrm.cxx | 3512 | ||||
-rw-r--r-- | sfx2/source/view/viewfrm2.cxx | 523 | ||||
-rw-r--r-- | sfx2/source/view/viewimp.hxx | 84 | ||||
-rw-r--r-- | sfx2/source/view/viewprn.cxx | 1034 | ||||
-rw-r--r-- | sfx2/source/view/viewsh.cxx | 2248 |
20 files changed, 15170 insertions, 0 deletions
diff --git a/sfx2/source/view/frame.cxx b/sfx2/source/view/frame.cxx new file mode 100644 index 000000000000..090e94ecb63f --- /dev/null +++ b/sfx2/source/view/frame.cxx @@ -0,0 +1,994 @@ +/************************************************************************* + * + * 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> + +#ifndef _MENU_HXX //autogen +#include <vcl/menu.hxx> +#endif +#include <svl/intitem.hxx> +#ifndef _SPLITWIN_HXX //autogen +#include <vcl/splitwin.hxx> +#endif +#include <svl/eitem.hxx> +#include <svl/stritem.hxx> +#ifndef _TOOLKIT_UNOHLP_HXX +#include <toolkit/helper/vclunohelper.hxx> +#endif +#include <com/sun/star/awt/PosSize.hpp> +#ifndef _UNOTOOLS_PROCESSFACTORY_HXX +#include <comphelper/processfactory.hxx> +#endif +#include <vcl/msgbox.hxx> + +#ifndef GCC +#endif + +// 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(), "Childs nicht entfernt!" ); + delete pChildArr; + } + + delete pImp; +} + +sal_Bool SfxFrame::DoClose() +{ + // Eigentlich wird noch ein PrepareClose gebraucht !!! + BOOL bRet = 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 = 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 = 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(); + + // Bei internen Tasks m"ussen Controller und Tools abger"aumt werden + 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( SfxEventHint(SFX_EVENT_PREPARECLOSEVIEW, GlobalEventConfig::GetEventName( STR_EVENT_PREPARECLOSEVIEW ), pCur) ); + + 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( USHORT 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(), "Falscher Index!"); + return (*pChildArr)[nPos]; + } + + return 0L; +} + +void SfxFrame::RemoveChildFrame_Impl( SfxFrame* pFrame ) +{ + DBG_ASSERT( pChildArr, "Unbekannter 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 = 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 ) ) ; + // Keine anderer Frame mehr auf Doc -> Cancel + if( !pFrm ) + { + pObj->CancelTransfers(); + GetCurrentDocument()->Broadcast( SfxSimpleHint(SFX_HINT_TITLECHANGED) ); + } + } + + // zuerst Nachladende Frames stoppen + sal_uInt16 nCount = GetChildFrameCount(); + for( sal_uInt16 n = 0; n<nCount; n++ ) + GetChildFrame( n )->CancelTransfers(); + + // ggf. StarOne-Loader canceln + 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() +{ + // Alle zwischen Laden und Entfernen "anderbaren Daten aktualisieren; die + // festen Daten werden nur einmal ( nach PrepareForDoc_Impl in UpdateDescriptor ) + // geholt, um Zeit zu sparen. + 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 ) + { + // Bei Framesets m"ussen auch die Daten der ChildViews geholt werden + 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 ) +{ + // Beim PrepareForDoc_Impl wird der Descriptor des Frames aktualisiert + // und sein ItemSet neu initialisiert. Alle Daten, die f"ur ein sp"ateres + // Restaurieren der View n"otig sind, sind damit festgehalten. + // Soll das Dokument ersetzt werden, wird durch GetViewData_Impl (s.o.) + // die neueste Information hinzugef"ugt. Alles zusammen wird dann in der + // Browse-History gesichert. Beim Aktivieren eines solchen FramePickEntry + // wird das komplette ItemSet und der Descriptor im OpenDoc mitgeschickt. + // Hier werden nur die festen Eigenschaften gesichert; die "anderbaren werden + // durch GetViewData geholt ( spart Zeit ). + 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 ); + + // FileOpen-Parameter merken + 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(); + + // Alle alten Items l"oschen + 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, "Kein Descriptor!" ); + DBG_ASSERT( pD != pImp->pDescr, "Descriptor ist schon gesetzt!" ); + + if ( pImp->pDescr ) + { + // Nur TopLevel-Frames verwalten ihren Descriptor selbst, bei den + // anderen tut es das Frameset + if ( !pParentFrame ) + delete pImp->pDescr; + } + pImp->pDescr = pD; +} + +//------------------------------------------------------------------------- + +SfxFrameDescriptor* SfxFrame::GetDescriptor() const +{ + // On Demand einen FrameDescriptor anlegen; wenn es kein TopLevel-Frame + // ist, f"uhrt es zu Fehlern, da keine g"ulige Verkettung hergestellt wird + + if ( !pImp->pDescr ) + { + DBG_ASSERT( !GetParentFrame(), "Kein TopLevel-Frame, aber kein Descriptor!" ); + pImp->pDescr = new SfxFrameDescriptor; + if ( GetCurrentDocument() ) + pImp->pDescr->SetURL( GetCurrentDocument()->GetMedium()->GetOrigURL() ); + } + return pImp->pDescr; +} + +//------------------------------------------------------------------------- + +void SfxFrame::GetTargetList( TargetList& rList ) const +{ + if ( !GetParentFrame() ) + { + // Einen Leerstring f"ur 'Kein Target' + rList.Insert( new String() ); + rList.Insert( new String( DEFINE_CONST_UNICODE( "_top" ) ) ); + rList.Insert( new String( DEFINE_CONST_UNICODE( "_parent" ) ) ); + rList.Insert( new String( DEFINE_CONST_UNICODE( "_blank" ) ) ); + rList.Insert( 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; +} + +sal_Bool SfxFrameItem::QueryValue( com::sun::star::uno::Any& rVal, BYTE ) const +{ + if ( wFrame ) + { + rVal <<= wFrame->GetFrameInterface(); + return TRUE; + } + + return FALSE; +} + +sal_Bool SfxFrameItem::PutValue( const com::sun::star::uno::Any& rVal, BYTE ) +{ + Reference < XFrame > xFrame; + if ( (rVal >>= xFrame) && xFrame.is() ) + { + SfxFrame* pFr = SfxFrame::GetFirst(); + while ( pFr ) + { + if ( pFr->GetFrameInterface() == xFrame ) + { + wFrame = pFrame = pFr; + return TRUE; + } + + pFr = SfxFrame::GetNext( *pFr ); + } + return TRUE; + } + + return 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 rItem.ISA( SfxUsrAnyItem ) && ((SfxUsrAnyItem&)rItem).aValue == aValue; + return sal_False; +} + +SfxPoolItem* SfxUsrAnyItem::Clone( SfxItemPool *) const +{ + return new SfxUsrAnyItem( Which(), aValue ); +} + +sal_Bool SfxUsrAnyItem::QueryValue( com::sun::star::uno::Any& rVal, BYTE /*nMemberId*/ ) const +{ + rVal = aValue; + return sal_True; +} + +sal_Bool SfxUsrAnyItem::PutValue( const com::sun::star::uno::Any& rVal, BYTE /*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 ); +} + +sal_Bool SfxUnoFrameItem::QueryValue( com::sun::star::uno::Any& rVal, BYTE /*nMemberId*/ ) const +{ + rVal <<= m_xFrame; + return sal_True; +} + +sal_Bool SfxUnoFrameItem::PutValue( const com::sun::star::uno::Any& rVal, BYTE /*nMemberId*/ ) +{ + return ( rVal >>= m_xFrame ); +} + +SfxFrameIterator::SfxFrameIterator( const SfxFrame& rFrame, sal_Bool bRecur ) + : pFrame( &rFrame ) + , bRecursive( bRecur ) +{} + +SfxFrame* SfxFrameIterator::FirstFrame() +{ + // GetFirst beginnt die Iteration beim ersten ChildFrame + return pFrame->GetChildFrame( 0 ); +} + +SfxFrame* SfxFrameIterator::NextFrame( SfxFrame& rPrev ) +{ + // Zuerst auf Kinder testen, wenn Rekursion erw"unscht + SfxFrame *pRet = NULL; + if ( bRecursive ) + pRet = rPrev.GetChildFrame( 0 ); + if ( !pRet ) + { + // Anderenfalls mit den Geschwistern von rPrev weitermachen + 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_ENSURE(0,"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 ) +{ + USHORT 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 ); +} + diff --git a/sfx2/source/view/frame2.cxx b/sfx2/source/view/frame2.cxx new file mode 100644 index 000000000000..d99ad8733e03 --- /dev/null +++ b/sfx2/source/view/frame2.cxx @@ -0,0 +1,484 @@ +/************************************************************************* + * + * 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 "sfxhelp.hxx" +#include "workwin.hxx" + +#include "sfx2/app.hxx" +#include "sfx2/bindings.hxx" +#include "sfx2/dispatch.hxx" +#include "sfx2/docfac.hxx" +#include "sfx2/docfile.hxx" +#include "sfx2/event.hxx" +#include "sfx2/objface.hxx" +#include "sfx2/request.hxx" + +#include <com/sun/star/awt/XWindow2.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XFramesSupplier.hpp> +#include <com/sun/star/frame/XLayoutManager.hpp> + +#include <comphelper/componentcontext.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/processfactory.hxx> +#include <svl/eitem.hxx> +#include <svl/intitem.hxx> +#include <svl/itemset.hxx> +#include <svl/rectitem.hxx> +#include <svl/stritem.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <tools/diagnose_ex.h> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::util; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::beans; +using ::com::sun::star::lang::XMultiServiceFactory; +using ::com::sun::star::lang::XComponent; +using ::com::sun::star::frame::XComponentLoader; + +//------------------------------------------------------------------------ + +class SfxFrameWindow_Impl : public Window +{ +public: + SfxFrame* pFrame; + + SfxFrameWindow_Impl( SfxFrame* pF, Window& i_rContainerWindow ); + ~SfxFrameWindow_Impl( ); + + virtual void DataChanged( const DataChangedEvent& rDCEvt ); + virtual void StateChanged( StateChangedType nStateChange ); + virtual long PreNotify( NotifyEvent& rNEvt ); + virtual long Notify( NotifyEvent& rEvt ); + virtual void Resize(); + virtual void GetFocus(); + void DoResize(); + DECL_LINK( CloserHdl, void* ); +}; + +SfxFrameWindow_Impl::SfxFrameWindow_Impl( SfxFrame* pF, Window& i_rContainerWindow ) + : Window( &i_rContainerWindow, WB_BORDER | WB_CLIPCHILDREN | WB_NODIALOGCONTROL | WB_3DLOOK ) + , pFrame( pF ) +{ +} + +SfxFrameWindow_Impl::~SfxFrameWindow_Impl( ) +{ +} + +void SfxFrameWindow_Impl::DataChanged( const DataChangedEvent& rDCEvt ) +{ + Window::DataChanged( rDCEvt ); + SfxWorkWindow *pWorkWin = pFrame->GetWorkWindow_Impl(); + if ( pWorkWin ) + pWorkWin->DataChanged_Impl( rDCEvt ); +} + +long SfxFrameWindow_Impl::Notify( NotifyEvent& rNEvt ) +{ + if ( pFrame->IsClosing_Impl() || !pFrame->GetFrameInterface().is() ) + return sal_False; + + SfxViewFrame* pView = pFrame->GetCurrentViewFrame(); + if ( !pView || !pView->GetObjectShell() ) + return Window::Notify( rNEvt ); + + if ( rNEvt.GetType() == EVENT_GETFOCUS ) + { + if ( pView->GetViewShell() && !pView->GetViewShell()->GetUIActiveIPClient_Impl() && !pFrame->IsInPlace() ) + { + DBG_TRACE("SfxFrame: GotFocus"); + pView->MakeActive_Impl( FALSE ); + } + + // TODO/LATER: do we still need this code? + Window* pWindow = rNEvt.GetWindow(); + ULONG nHelpId = 0; + while ( !nHelpId && pWindow ) + { + nHelpId = pWindow->GetHelpId(); + pWindow = pWindow->GetParent(); + } + + if ( nHelpId ) + SfxHelp::OpenHelpAgent( pFrame, nHelpId ); + + // 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 TRUE; + } + else if ( rNEvt.GetType() == EVENT_EXECUTEDIALOG /*|| rNEvt.GetType() == EVENT_INPUTDISABLE*/ ) + { + pView->SetModalMode( sal_True ); + return sal_True; + } + else if ( rNEvt.GetType() == EVENT_ENDEXECUTEDIALOG /*|| rNEvt.GetType() == EVENT_INPUTENABLE*/ ) + { + //EnableInput( sal_True, sal_True ); + pView->SetModalMode( sal_False ); + return sal_True; + } + + return Window::Notify( rNEvt ); +} + +long SfxFrameWindow_Impl::PreNotify( NotifyEvent& rNEvt ) +{ + USHORT 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( 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 = 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, USHORT 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( rDoc.GetModel()->getURL() ); + if ( sLoaderURL.getLength() == 0 ) + sLoaderURL = rDoc.GetFactory().GetFactoryURL(); + + 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( 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( 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( BOOL bLock ) +{ + pImp->bLockResize = bLock; +} + +IMPL_LINK( SfxFrameWindow_Impl, CloserHdl, void*, EMPTYARG ) +{ + if ( pFrame && !pFrame->PrepareClose_Impl( TRUE ) ) + return 0L; + + if ( pFrame ) + pFrame->GetCurrentViewFrame()->GetBindings().Execute( SID_CLOSEWIN, 0, 0, SFX_CALLMODE_ASYNCHRON ); + return 0L; +} + +void SfxFrame::SetMenuBarOn_Impl( 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 ); + } +} + +BOOL SfxFrame::IsMenuBarOn_Impl() const +{ + return pImp->bMenuBarOn; +} + +void SfxFrame::PositionWindow_Impl( const Rectangle& rWinArea ) const +{ + Window *pWin = pImp->pExternalContainerWindow; + + // Groesse setzen + const Size aAppWindow( pImp->pExternalContainerWindow->GetDesktopRectPixel().GetSize() ); + Point aPos( rWinArea.TopLeft() ); + Size aSz( rWinArea.GetSize() ); + if ( aSz.Width() && aSz.Height() ) + { + aPos.X() = Min(aPos.X(), + long(aAppWindow.Width() - aSz.Width() + aSz.Width() / 2) ); + aPos.Y() = Min(aPos.Y(), + long( aAppWindow.Height() - aSz.Height() + aSz.Height() / 2) ); + if ( aPos.X() + aSz.Width() < + aAppWindow.Width() + aSz.Width() / 2 && + aPos.Y() + aSz.Height() < + aAppWindow.Height() + aSz.Height() / 2 ) + { + pWin->SetPosPixel( aPos ); + pWin->SetOutputSizePixel( aSz ); + } + } +} + +void SfxFrame::PrepareForDoc_Impl( SfxObjectShell& i_rDoc ) +{ + const ::comphelper::NamedValueCollection aDocumentArgs( i_rDoc.GetModel()->getArgs() ); + + // hidden? + OSL_ENSURE( !pImp->bHidden, "when does this happen?" ); + pImp->bHidden = aDocumentArgs.getOrDefault( "Hidden", pImp->bHidden ); + + // update our descriptor + UpdateDescriptor( &i_rDoc ); + + // plugin mode + sal_Int16 nPluginMode = aDocumentArgs.getOrDefault( "PluginMode", sal_Int16( 0 ) ); + if ( nPluginMode && ( nPluginMode != 2 ) ) + SetInPlace_Impl( TRUE ); +} + +bool SfxFrame::IsMarkedHidden_Impl() const +{ + return pImp->bHidden; +} diff --git a/sfx2/source/view/frmload.cxx b/sfx2/source/view/frmload.cxx new file mode 100644 index 000000000000..ed158ce009e3 --- /dev/null +++ b/sfx2/source/view/frmload.cxx @@ -0,0 +1,746 @@ +/************************************************************************* + * + * 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 "frmload.hxx" +#include "objshimp.hxx" +#include "viewfac.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" + +/** === 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 <vos/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* pRequest = new ::framework::RequestFilterSelect( i_rDocumentURL ); + Reference< XInteractionRequest > xRequest ( pRequest ); + i_rxHandler->handle( xRequest ); + if( !pRequest->isAbort() ) + sFilterName = pRequest->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 USHORT _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, TRUE ) ); + return lcl_getDispatchResult( SFX_APP()->ExecuteSlot( aRequest ) ); +} + +// -------------------------------------------------------------------------------------------------------------------- +void SfxFrameLoader_Impl::impl_lockHiddenDocument( SfxObjectShell& i_rDocument, const ::comphelper::NamedValueCollection& i_rDescriptor ) const +{ + const sal_Bool bHidden = i_rDescriptor.getOrDefault( "Hidden", sal_False ); + if ( !bHidden ) + return; + + const SfxViewFrame* pExistingViewFrame = SfxViewFrame::GetFirst( &i_rDocument ); + if ( pExistingViewFrame ) + return; + + // the document is to be loaded hidden, and it is not yet displayed in any other frame + // To prevent it from being closed when the loader returns, increase its OwnerLock + // (the OwnerLock is normally increased by every frame in which the document is displayed, and by this loader) + i_rDocument.RestoreNoDelete(); + i_rDocument.OwnerLock( TRUE ); + i_rDocument.Get_Impl()->bHiddenLockedByAPI = TRUE; +} + +// -------------------------------------------------------------------------------------------------------------------- +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() ) ); + } +} + +// -------------------------------------------------------------------------------------------------------------------- +SfxObjectShellLock SfxFrameLoader_Impl::impl_findObjectShell( const Reference< XModel2 >& i_rxDocument ) const +{ + for ( SfxObjectShell* pDoc = SfxObjectShell::GetFirst( NULL, FALSE ); pDoc; pDoc = SfxObjectShell::GetNext( *pDoc, NULL, FALSE ) ) + { + if ( i_rxDocument == pDoc->GetModel() ) + { + return pDoc; + } + } + + DBG_ERROR( "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; +} + +// -------------------------------------------------------------------------------------------------------------------- +USHORT 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 USHORT( 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 < sizeof( pKnownViewArgs ) / sizeof( pKnownViewArgs[0] ); ++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" ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + 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 USHORT 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() ); + // TODO: not sure this is correct. The original, pre-refactoring code did it this way. However, I could + // imagine scenarios where it is *not* correct to overrule the *existing* model args (XModel::getArgs) + // with the ones passed to the loader here. For instance, what about the MacroExecutionMode? The document + // might have a mode other than the one passed to the loader, and we always overwrite the former with + // the latter. + } + + // get the SfxObjectShell (still needed at the moment) + const SfxObjectShellLock 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 ).GetViewName() ); + + // if the document is created hidden, prevent it from being deleted until it is shown or disposed + impl_lockHiddenDocument( *xDoc, aDescriptor ); + // TODO; if we wouldn't use a SfxObjectShellLock instance for xDoc, but a simple SfxObjectShellRef, + // then this would not be necessary, /me thinks. That is, the *Lock classes inc/dec a "Lock" counter + // (additional to the ref counter) in their ctor/dtor, and if the lock counter goes to 0, the + // object is closed (DoClose). The impl_lockHiddenDocument is to prevent exactly that premature + // closing. However, a *Ref object wouldn't close, anyway. And in case of unsuccessfull loading, the + // code at the very end of this method cares for closing the XModel, which should also close the + // ObjectShell. + + // 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] = UNOOUSTRING::createFromAscii( "com.sun.star.frame.SynchronousFrameLoader" ); + return seqServiceNames ; +} + +/* Helper for XServiceInfo */ +UNOOUSTRING SfxFrameLoader_Impl::impl_getStaticImplementationName() +{ + return UNOOUSTRING::createFromAscii( "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 ) ); +} + diff --git a/sfx2/source/view/impframe.hxx b/sfx2/source/view/impframe.hxx new file mode 100644 index 000000000000..72f322036efb --- /dev/null +++ b/sfx2/source/view/impframe.hxx @@ -0,0 +1,100 @@ +/************************************************************************* + * + * 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 + diff --git a/sfx2/source/view/impviewframe.hxx b/sfx2/source/view/impviewframe.hxx new file mode 100644 index 000000000000..abe4cb6852d9 --- /dev/null +++ b/sfx2/source/view/impviewframe.hxx @@ -0,0 +1,98 @@ +/************************************************************************* +* 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 +{ + BOOL bActive; + SfxViewFrame* pFrame; + +public: + SfxFrameViewWindow_Impl( SfxViewFrame* p, Window& rParent, WinBits nBits=0 ) : + Window( &rParent, nBits | WB_BORDER | WB_CLIPCHILDREN ), + bActive( FALSE ), + pFrame( p ) + { + p->GetFrame().GetWindow().SetBorderStyle( WINDOW_BORDER_NOBORDER ); + } + + virtual void Resize(); + virtual void StateChanged( StateChangedType nStateChange ); +}; + +#endif // SFX2_IMPVIEWFRAME_HXX + diff --git a/sfx2/source/view/ipclient.cxx b/sfx2/source/view/ipclient.cxx new file mode 100644 index 000000000000..328d88d8b2b9 --- /dev/null +++ b/sfx2/source/view/ipclient.cxx @@ -0,0 +1,1163 @@ +/************************************************************************* + * + * 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 ); + } + else if ( m_pClient && nNewState == embed::EmbedStates::UI_ACTIVE ) + { +/* + uno::Reference < lang::XUnoTunnel > xObj( m_xObject->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 ) + { + // currently needs SFX code + SfxObjectShell* pDoc = reinterpret_cast< SfxObjectShell* >( sal::static_int_cast< sal_IntPtr >( nHandle )); + SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDoc ); + SfxWorkWindow *pWorkWin = pFrame->GetFrame().GetWorkWindow_Impl(); + pWorkWin->UpdateObjectBars_Impl(); + } +*/ + } +} + +void SAL_CALL SfxInPlaceClient_Impl::notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if ( m_pClient && aEvent.EventName.equalsAscii("OnVisAreaChanged") && m_nAspect != embed::Aspects::MSOLE_ICON ) + { + 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 ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + 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 = 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 = 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::createFromAscii("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_ENSURE( sal_False, "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_ENSURE( sal_False, "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_ENSURE( sal_False, "Can not set the client site!\n" ); + } + + m_pImp->m_aTimer.Start(); + } + else + m_pImp->m_aTimer.Stop(); +} + +//-------------------------------------------------------------------- +BOOL SfxInPlaceClient::SetObjArea( const Rectangle& rArea ) +{ + if( rArea != m_pImp->m_aObjArea ) + { + m_pImp->m_aObjArea = rArea; + m_pImp->SizeHasChanged(); + + Invalidate(); + return TRUE; + } + + return 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(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(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::DeactivateObject() +{ + if ( GetObject().is() ) + { + try + { + m_pImp->m_bUIActive = FALSE; + BOOL bHasFocus = 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( TRUE ); + } + } + + if ( m_pViewSh ) + m_pViewSh->GetViewFrame()->GetTopFrame().LockResize_Impl(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(FALSE); + pFrame->GetTopFrame().Resize(); + } + } + catch (com::sun::star::uno::Exception& ) + {} + } +} + +void SfxInPlaceClient::ResetObject() +{ + if ( GetObject().is() ) + { + try + { + m_pImp->m_bUIActive = 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& ) + {} + } +} + +BOOL SfxInPlaceClient::IsUIActive() +{ + return m_pImp->m_bUIActive; +} diff --git a/sfx2/source/view/makefile.mk b/sfx2/source/view/makefile.mk new file mode 100644 index 000000000000..9c257f4c9f75 --- /dev/null +++ b/sfx2/source/view/makefile.mk @@ -0,0 +1,65 @@ +#************************************************************************* +# +# 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. +# +#************************************************************************* + + + +PRJ=..$/.. + +PRJNAME= sfx2 +TARGET= view +ENABLE_EXCEPTIONS= TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SRS1NAME=$(TARGET) +SRC1FILES = \ + view.src + +SLOFILES = \ + $(SLO)$/ipclient.obj \ + $(SLO)$/viewsh.obj \ + $(SLO)$/frmload.obj \ + $(SLO)$/frame.obj \ + $(SLO)$/frame2.obj \ + $(SLO)$/printer.obj \ + $(SLO)$/viewprn.obj \ + $(SLO)$/viewfac.obj \ + $(SLO)$/orgmgr.obj \ + $(SLO)$/viewfrm.obj \ + $(SLO)$/viewfrm2.obj \ + $(SLO)$/sfxbasecontroller.obj \ + $(SLO)$/userinputinterception.obj + +# --- Targets ------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/sfx2/source/view/orgmgr.cxx b/sfx2/source/view/orgmgr.cxx new file mode 100644 index 000000000000..b15392372b19 --- /dev/null +++ b/sfx2/source/view/orgmgr.cxx @@ -0,0 +1,832 @@ +/************************************************************************* + * + * 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> + +#ifndef _MSGBOX_HXX //autogen +#include <vcl/msgbox.hxx> +#endif +#include <tools/urlobj.hxx> +#ifndef GCC +#endif + +#ifndef _UNOTOOLS_PROCESSFACTORY_HXX +#include <comphelper/processfactory.hxx> +#endif +#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 "sfxresid.hxx" +#include "view.hrc" +#include <sfx2/docfilt.hxx> +#include "fltfnc.hxx" + +using namespace ::com::sun::star; + +//========================================================================= + +/* [Beschreibung] + + Implementierungsklasse; einzelner Eintrag in der Dateiansicht + +*/ + +struct _FileListEntry +{ + String aFileName; // Dateiname mit komplettem Pfad + String aBaseName; // Dateiname + const CollatorWrapper* pCollator; + SfxObjectShellLock aDocShell; // ObjectShell als Ref-Klasse + +//REMOVE SvStorageRef aStor; // Referenz auf Storage, wenn wir diesen geoeffnet haben + //uno::Reference< embed::XStorage > xStorage; + + BOOL bFile; // als Datei auf Platte + // (!= unbenannt1, nicht als Dok. geladen; + // diese werden nicht gespeichert!) + BOOL bOwner; // selbst erzeugt + BOOL bNoName; + 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; + 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 ( FALSE ), + bOwner ( FALSE ), + bNoName ( TRUE ), + bOwnFormat ( 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*) + +//========================================================================= + +BOOL _FileListEntry::DeleteObjectShell() + +/* [Beschreibung] + + Freigabe der DokumentShell + + [Returnwert] TRUE: alles Ok + FALSE: es ist ein Fehler aufgetreten (das + Dokument konnte nicht gesichert werden) + +*/ + +{ + BOOL bRet = TRUE; + //Falls wir die Shell angelegt haben und sie veraendert wurde + if(bOwner && aDocShell.Is() && aDocShell->IsModified()) + { + //Mussten wir konvertieren? + if( bOwnFormat ) + { + if(!aDocShell->Save() ) + bRet = 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& ) + { + } + +// aDocShell->SfxObjectShell::DoSaveCompleted(); + } + } + else + { + // Falls konvertiert im eigenen Format speichern + 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(USHORT i) const +{ + return (*this)[i]->aBaseName; +} + +//------------------------------------------------------------------------- + +const String& SfxObjectList::GetFileName( USHORT 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) + +/* [Beschreibung] + + Konstruktor + + Das aktuelle Dokument wird in die Liste der Dokumente + aufgenommen. + +*/ +{ + 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( USHORT nIdx ) + +/* [Beschreibung] + + Zugriff auf die DokumentShell an der Position nIdx + + [Returnwert] Referenz auf die DokumentShell + +*/ + +{ + _FileListEntry* pEntry = (*pImpl->pDocList)[nIdx]; + // andernfalls Doc-Shell anlegen + if ( !pEntry->aDocShell.Is() ) + { +//(mba)/task SfxWaitCursor aWaitCursor; + INetURLObject aFileObj( pEntry->aFileName ); + BOOL bDum = FALSE; + SfxApplication* pSfxApp = SFX_APP(); + String aFilePath = aFileObj.GetMainURL( INetURLObject::NO_DECODE ); + pEntry->aDocShell = pSfxApp->DocAlreadyLoaded( aFilePath, FALSE, bDum ); + if ( !pEntry->aDocShell.Is() ) + { + pEntry->bOwner = TRUE; + SfxMedium* pMed = new SfxMedium( + aFilePath, ( STREAM_READ | STREAM_SHARE_DENYWRITE ), FALSE, 0 ); + const SfxFilter* pFilter = NULL; + pMed->UseInteractionHandler(TRUE); + if ( + pSfxApp->GetFilterMatcher().GuessFilter(*pMed, &pFilter, SFX_FILTER_TEMPLATE, 0) || + (pFilter && !pFilter->IsOwnFormat()) || + (pFilter && !pFilter->UsesStorage()) + ) + { + pSfxApp->LoadTemplate( pEntry->aDocShell, aFilePath ); + pEntry->bOwnFormat = FALSE; + delete pMed; + if ( pEntry->aDocShell.Is() ) + return (SfxObjectShellRef)(SfxObjectShell*)(pEntry->aDocShell); + } + else + { + if ( pFilter ) + { + pEntry->bOwnFormat = 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); +} + +//------------------------------------------------------------------------- + +BOOL SfxOrganizeMgr::DeleteObjectShell(USHORT nIdx) + +/* [Beschreibung] + + Freigabe der DokumentShell an der Position nIdx + + [Returnwert] TRUE: alles Ok + FALSE: es ist ein Fehler aufgetreten (das + Dokument konnte nicht gesichert werden) + +*/ +{ + return (*pImpl->pDocList)[nIdx]->DeleteObjectShell(); +} + +//------------------------------------------------------------------------- + +SfxObjectShellRef SfxOrganizeMgr::CreateObjectShell(USHORT nRegion, + USHORT nIdx) +/* [Beschreibung] + + Zugriff auf die DokumentShell an der Position nIdx im Bereich + nRegion (Dokumentvorlage) + + [Returnwert] Referenz auf die DokumentShell + +*/ +{ +//(mba)/task SfxWaitCursor aWaitCursor; + return pTemplates->CreateObjectShell(nRegion, nIdx); +} + +//------------------------------------------------------------------------- + +BOOL SfxOrganizeMgr::DeleteObjectShell(USHORT nRegion, USHORT nIdx) + +/* [Beschreibung] + + Freigabe der DokumentShell an der Position nIdx im Bereich + nRegion (Dokumentvorlage) + + [Returnwert] TRUE: alles Ok + FALSE: es ist ein Fehler aufgetreten (das + Dokument konnte nicht gesichert werden) + +*/ + +{ + return pTemplates->DeleteObjectShell(nRegion, nIdx); +} + +//------------------------------------------------------------------------- + +BOOL SfxOrganizeMgr::Copy(USHORT nTargetRegion, + USHORT nTargetIdx, + USHORT nSourceRegion, + USHORT nSourceIdx) + +/* [Beschreibung] + + Kopieren einer Dokumentvorlage + + [Parameter] + + USHORT nTargetRegion Index des Zielbereiches + USHORT nTargetIdx Index Zielposition + USHORT nSourceRegion Index des Quellbereiches + USHORT nSourceIdx Index der zu kopierenden / z uverschiebenden + Dokumentvorlage + + [R"uckgabewert] Erfolg (TRUE) oder Mi"serfolg (FALSE) + + + [Querverweise] + + <SfxDocumentTemplates::Copy(USHORT nTargetRegion, + USHORT nTargetIdx, + USHORT nSourceRegion, + USHORT nSourceIdx)> + +*/ + +{ + if(nSourceIdx == USHRT_MAX) // keine Verzeichnisse kopieren + return FALSE ; + const BOOL bOk = pTemplates->Copy(nTargetRegion, nTargetIdx, + nSourceRegion, nSourceIdx); + if(bOk) + bModified = 1; + return bOk; +} + +//------------------------------------------------------------------------- + +BOOL SfxOrganizeMgr::Move(USHORT nTargetRegion, + USHORT nTargetIdx, + USHORT nSourceRegion, + USHORT nSourceIdx) + +/* [Beschreibung] + + Verschieben einer Dokumentvorlage + + [Parameter] + + USHORT nTargetRegion Index des Zielbereiches + USHORT nTargetIdx Index Zielposition + USHORT nSourceRegion Index des Quellbereiches + USHORT nSourceIdx Index der zu kopierenden / z uverschiebenden + Dokumentvorlage + + [R"uckgabewert] Erfolg (TRUE) oder Mi"serfolg (FALSE) + + + [Querverweise] + + <SfxDocumentTemplates::Move(USHORT nTargetRegion, + USHORT nTargetIdx, + USHORT nSourceRegion, + USHORT nSourceIdx)> + +*/ + +{ + if(nSourceIdx == USHRT_MAX) // keine Verzeichnisse verschieben + return FALSE ; + const BOOL bOk = pTemplates->Move(nTargetRegion, nTargetIdx, + nSourceRegion, nSourceIdx); + if(bOk) + bModified = 1; + return bOk; +} + +//------------------------------------------------------------------------- + +BOOL SfxOrganizeMgr::Delete(SfxOrganizeListBox_Impl *pCaller, + USHORT nRegion, USHORT nIdx) + +/* [Beschreibung] + + "oschen einer Dokumentvorlage + + [Parameter] + + SfxOrganizeListBox *pCaller rufende ListBox; da dieses + Event durch das Men"u oder + durch das Keyboard angetriggert wird, + mu"s das Model der ListBox anschlie"send + aktualisiert werden. + USHORT nRegion Index des Bereiches + USHORT nIdx Index der Dokumentvorlage + + [R"uckgabewert] Erfolg (TRUE) oder Mi"serfolg (FALSE) + + + [Querverweise] + + <SfxDocumentTemplates::Delete(USHORT nRegion, USHORT nIdx)> + +*/ + +{ + BOOL bOk = FALSE; + + if ( USHRT_MAX == nIdx ) + { + // deleting of a group + + SvLBoxEntry *pGroupToDelete = pCaller->SvLBox::GetEntry(nRegion); + if ( pGroupToDelete ) + { + USHORT nItemNum = (USHORT)( pCaller->GetModel()->GetChildCount( pGroupToDelete ) ); + USHORT nToDeleteNum = 0; + SvLBoxEntry **pEntriesToDelete = new SvLBoxEntry*[nItemNum]; + + USHORT 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; + // zu loeschender Eintrag + SvLBoxEntry *pEntryToDelete = pCaller->SvLBox::GetEntry(pCaller->SvLBox::GetEntry(nRegion), nIdx); + + pCaller->GetModel()->Remove(pEntryToDelete); + } + } + + return bOk; +} + +//------------------------------------------------------------------------- + +BOOL SfxOrganizeMgr::InsertDir +( + SfxOrganizeListBox_Impl* pCaller,/* rufende ListBox; da dieses Event + durch das Men"u oder durch das + Keyboard angetriggert wird, + mu\s das Model der ListBox + anschlie\send aktualisiert werden */ + const String& rText, // logischer Name des Bereiches + USHORT nRegion // Index des Bereiches +) + +/* [Beschreibung] + + Einf"ugen eines Bereiches + + + [R"uckgabewert] + + Erfolg (TRUE) oder Mi\serfolg (FALSE) + + + [Querverweise] + + <SfxDocumentTemplates::InsertDir(const String &, USHORT nRegion)> +*/ + +{ + const BOOL bOk = pTemplates->InsertDir(rText, nRegion); + if(bOk) + { + bModified = 1; + SvLBoxEntry *pEntry = pCaller->InsertEntry(rText, + pCaller->GetOpenedBmp(0), + pCaller->GetClosedBmp(0), + 0, TRUE, nRegion); + pCaller->Update(); + pCaller->EditEntry(pEntry); + } + return bOk; +} + +//------------------------------------------------------------------------- + +BOOL SfxOrganizeMgr::SetName(const String &rName, + USHORT nRegion, USHORT nIdx) + +/* [Beschreibung] + + "Andern eines (logischen) Namens + + [Parameter] + + const String &rName der neue Name + USHORT nRegion Index des Bereiches + USHORT nIdx Index der Dokumentvorlage + + [R"uckgabewert] Erfolg (TRUE) oder Mi"serfolg (FALSE) + + + [Querverweise] + + <SfxDocumentTemplates::SetName(const String &, USHORT nRegion, USHORT nIdx)> + +*/ + +{ + const BOOL bOk = pTemplates->SetName(rName, nRegion, nIdx); + if(bOk) + bModified = 1; + return bOk; +} + +//------------------------------------------------------------------------- + +BOOL SfxOrganizeMgr::CopyTo(USHORT nRegion, USHORT nIdx, const String &rName) const + +/* [Beschreibung] + + Export einer Vorlage + + [Parameter] + + USHORT nRegion Index des Bereiches + USHORT nIdx Index der Dokumentvorlage + const String &rName Dateiname + + [R"uckgabewert] Erfolg (TRUE) oder Mi"serfolg (FALSE) + + + [Querverweise] + + <SfxDocumentTemplates::CopyTo( USHORT nRegion, USHORT nIdx, const String &)> + +*/ + +{ + return pTemplates->CopyTo(nRegion, nIdx, rName); +} + +//------------------------------------------------------------------------- + +BOOL SfxOrganizeMgr::CopyFrom(SfxOrganizeListBox_Impl *pCaller, + USHORT nRegion, USHORT nIdx, String &rName) + +/* [Beschreibung] + + Import einer Vorlage + + [Parameter] + + SfxOrganizeListBox *pCaller rufende ListBox; da dieses + Event durch das Men"u angetriggert wird, + mu"s das Model der ListBox anschlie"send + aktualisiert werden. + USHORT nRegion Index des Bereiches + USHORT nIdx Index der Dokumentvorlage + String &rName Dateiname + + [R"uckgabewert] Erfolg (TRUE) oder Mi"serfolg (FALSE) + + + [Querverweise] + + <SfxDocumentTemplates::CopyFrom( USHORT nRegion, USHORT nIdx, const String &)> + +*/ + +{ + SvLBoxEntry *pParent = pCaller->FirstSelected(); + if( nIdx!=USHRT_MAX ) + pParent = pCaller->GetParent(pParent); + if( pTemplates->CopyFrom( nRegion, nIdx, rName ) ) + { + // pCaller aktualisieren + if( nIdx == USHRT_MAX ) + nIdx = 0; + else nIdx++; + + pCaller->InsertEntry( rName, + pCaller->GetOpenedBmp(1), + pCaller->GetClosedBmp(1), + pParent, + TRUE, + nIdx); + pCaller->Update(); + // pCaller->EditEntry( pEntry ); + pCaller->Expand( pParent ); + bModified = TRUE; + return TRUE; + } + return FALSE; +} + +//------------------------------------------------------------------------- + +BOOL SfxOrganizeMgr::InsertFile( SfxOrganizeListBox_Impl* pCaller, const String& rFileName ) + +/* [Beschreibung] + + Eine Datei in der Dateiansicht hinzuf"ugen + + [Parameter] + + SfxOrganizeListBox *pCaller rufende ListBox; da dieses + Event durch das Men"u angetriggert wird, + mu"s das Model der ListBox anschlie"send + aktualisiert werden. + const String &rFileName Name der hinzuf"ugenden Datei + + [R"uckgabewert] Erfolg (TRUE) oder Mi"serfolg (FALSE) + +*/ + +{ + const CollatorWrapper* pCollator = pImpl->pIntlWrapper->getCaseCollator(); + _FileListEntry* pEntry = new _FileListEntry( rFileName, pCollator ); + if ( pImpl->pDocList->C40_PTR_INSERT( _FileListEntry, pEntry ) ) + { + USHORT nPos = 0; + pImpl->pDocList->Seek_Entry( pEntry, &nPos ); + pCaller->InsertEntry( pEntry->aBaseName, pCaller->GetOpenedBmp(1), + pCaller->GetClosedBmp(1), 0, TRUE, nPos ); + return TRUE; + } + return FALSE; +} + +//------------------------------------------------------------------------- + +BOOL SfxOrganizeMgr::Rescan() + +/* [Beschreibung] + + Aktualisieren der Datenbasis + + [R"uckgabewert] + + TRUE es bestanden Unterschiede + FALSE keine "Anderung + + [Querverweise] + + <SfxDocumentTemplates::Rescan()> +*/ + +{ + if(pTemplates->Rescan()) + { + bModified = TRUE; + return TRUE; + } + return FALSE; +} + +//------------------------------------------------------------------------- + +void SfxOrganizeMgr::SaveAll(Window *pParent) + +/* [Beschreibung] + + Schreiben aller ge"anderten Dokumente + + [Parameter] + + Window *pParent Parent der Boxen f"ur Fehlermeldungen + +*/ + +{ + USHORT nRangeCount = pTemplates->GetRegionCount(); + USHORT i; + for(i = 0; i < nRangeCount; ++i) + { + if( pTemplates->IsRegionLoaded( i )) + { + const USHORT nCount = pTemplates->GetCount(i); + for(USHORT 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; + } + } +} + + diff --git a/sfx2/source/view/printer.cxx b/sfx2/source/view/printer.cxx new file mode 100644 index 000000000000..46a96bafab9a --- /dev/null +++ b/sfx2/source/view/printer.cxx @@ -0,0 +1,624 @@ +/************************************************************************* + * + * 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 <svtools/printdlg.hxx> +#include <unotools/printwarningoptions.hxx> +#include <svtools/printoptions.hxx> +#include <vector> + +#ifndef GCC +#endif + +#include <sfx2/printer.hxx> +#include <sfx2/printopt.hxx> +#include "sfxtypes.hxx" +#include <sfx2/prnmon.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/tabdlg.hxx> +#include "sfxresid.hxx" +#include "view.hrc" + +#ifdef MSC +// der ist buggy +#define NEW_OBJECTS(Class, nCount) ((Class*) new char[ sizeof(Class) * (nCount) ]) +#else +#define NEW_OBJECTS(Class, nCount) (new Class[nCount]) +#endif + + +USHORT SfxFontSizeInfo::pStaticSizes[] = +{ + 60, + 80, + 100, + 120, + 140, + 180, + 240, + 360, + 480, + 600, + 720 +}; + +//-------------------------------------------------------------------- + +SV_DECL_PTRARR_DEL(SfxFontArr_Impl,SfxFont*,10,5) + +// struct SfxPrinter_Impl ------------------------------------------------ + +struct SfxPrinter_Impl +{ + SfxFontArr_Impl* mpFonts; + BOOL mbAll; + BOOL mbSelection; + BOOL mbFromTo; + BOOL mbRange; + + SfxPrinter_Impl() : + mpFonts ( NULL ), + mbAll ( TRUE ), + mbSelection ( TRUE ), + mbFromTo ( TRUE ), + mbRange ( TRUE ) {} + ~SfxPrinter_Impl() { delete mpFonts; } +}; + +#define FONTS() pImpl->mpFonts + +struct SfxPrintOptDlg_Impl +{ + sal_Bool mbHelpDisabled; + + SfxPrintOptDlg_Impl() : + mbHelpDisabled ( sal_False ) {} +}; + +//-------------------------------------------------------------------- + +SfxFontSizeInfo::SfxFontSizeInfo( const SfxFont &rFont, + const OutputDevice &rDevice ) : + + pSizes(0), + nSizes(0), + bScalable(TRUE) + +{ + if ( 0 == rDevice.GetDevFontCount() ) + bScalable = FALSE; + else + { + OutputDevice &rDev = (OutputDevice&) rDevice; + Font aFont(rFont.GetName(), Size(0,12)); + aFont.SetFamily(rFont.GetFamily()); + aFont.SetPitch(rFont.GetPitch()); + aFont.SetCharSet(rFont.GetCharSet()); + + // verfuegbare Groessen in die Liste eintragen, Groesse in 10tel Punkt + int nSizeCount = rDev.GetDevFontSizeCount(aFont); + pSizes = NEW_OBJECTS(Size, nSizeCount); + const MapMode aOldMapMode = rDev.GetMapMode(); + MapMode aMap(aOldMapMode); + aMap.SetMapUnit(MAP_POINT); + const Fraction aTen(1, 10); + aMap.SetScaleX(aTen); + aMap.SetScaleY(aTen); + rDev.SetMapMode(aMap); + + // Es gibt Fonts mit Bitmaps und skalierbaren Groessen + // In diesem Fall wird der Fonts als skalierbar behandelt. + BOOL bFoundScalable = FALSE; + for ( int i = 0; i < nSizeCount; ++i ) + { + const Size aSize( rDev.GetDevFontSize(aFont, i) ); + if ( aSize.Height() != 0 ) + pSizes[nSizes++] = aSize; + else + bFoundScalable |= TRUE; + } + if( !bFoundScalable ) + bScalable = FALSE; + else + { + // statische Font-Sizes verwenden + delete [] pSizes; + nSizes = 0; + } + rDev.SetMapMode(aOldMapMode); + } + + if ( 0 == nSizes ) + { + nSizes = sizeof(pStaticSizes) / sizeof(USHORT); + pSizes = NEW_OBJECTS(Size, nSizes); + for ( USHORT nPos = 0; nPos <nSizes; ++nPos ) + pSizes[nPos] = Size( 0, pStaticSizes[nPos] ); + } +} + +//-------------------------------------------------------------------- + +SfxFontSizeInfo::~SfxFontSizeInfo() +{ + delete [] pSizes; +} + +//-------------------------------------------------------------------- + +BOOL SfxFontSizeInfo::HasSize(const Size &rSize) const +{ + if ( bScalable ) + return TRUE; + for ( USHORT i = 0; i < nSizes; ++i) + if ( pSizes[i] == rSize ) + return TRUE; + return FALSE; +} + +//-------------------------------------------------------------------- + +SfxFont::SfxFont( const FontFamily eFontFamily, const String& aFontName, + const FontPitch eFontPitch, const CharSet eFontCharSet ): + aName( aFontName ), + eFamily( eFontFamily ), + ePitch( eFontPitch ), + eCharSet( eFontCharSet ) +{ +} + +// class SfxPrinter ------------------------------------------------------ + +SfxPrinter* SfxPrinter::Create( SvStream& rStream, SfxItemSet* pOptions ) + +/* [Beschreibung] + + Erzeugt einen <SfxPrinter> aus dem Stream. Geladen wird genaugenommen + nur ein JobSetup. Falls ein solcher Drucker auf dem System nicht + verf"augbar ist, wird das Original als Orig-JobSetup gemerkt und + ein "anhlicher exisitierender Drucker genommen. + + Die 'pOptions' werden in den erzeugten SfxPrinter "ubernommen, + der Returnwert geh"ort dem Caller. +*/ + +{ + // JobSetup laden + JobSetup aFileJobSetup; + rStream >> aFileJobSetup; + + // Drucker erzeugen + SfxPrinter *pPrinter = new SfxPrinter( pOptions, aFileJobSetup ); + return pPrinter; +} + +//-------------------------------------------------------------------- + +SvStream& SfxPrinter::Store( SvStream& rStream ) const + +/* [Beschreibung] + + Speichert das verwendete JobSetup des <SfxPrinter>s. +*/ + +{ + return ( rStream << GetJobSetup() ); +} + +//-------------------------------------------------------------------- + +SfxPrinter::SfxPrinter( SfxItemSet* pTheOptions ) : + +/* [Beschreibung] + + Dieser Ctor erzeugt einen Standard-Drucker. +*/ + + 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); +} + +//-------------------------------------------------------------------- + +void SfxPrinter::EnableRange( USHORT nRange ) +{ + PrintDialogRange eRange = (PrintDialogRange)nRange; + + if ( eRange == PRINTDIALOG_ALL ) + pImpl->mbAll = TRUE; + else if ( eRange == PRINTDIALOG_SELECTION ) + pImpl->mbSelection = TRUE; + else if ( eRange == PRINTDIALOG_FROMTO ) + pImpl->mbFromTo = TRUE; + else if ( eRange == PRINTDIALOG_RANGE ) + pImpl->mbRange = TRUE; +} + +//-------------------------------------------------------------------- + +void SfxPrinter::DisableRange( USHORT nRange ) +{ + PrintDialogRange eRange = (PrintDialogRange)nRange; + + if ( eRange == PRINTDIALOG_ALL ) + pImpl->mbAll = FALSE; + else if ( eRange == PRINTDIALOG_SELECTION ) + pImpl->mbSelection = FALSE; + else if ( eRange == PRINTDIALOG_FROMTO ) + pImpl->mbFromTo = FALSE; + else if ( eRange == PRINTDIALOG_RANGE ) + pImpl->mbRange = FALSE; +} + +//-------------------------------------------------------------------- + +BOOL SfxPrinter::IsRangeEnabled( USHORT nRange ) const +{ + PrintDialogRange eRange = (PrintDialogRange)nRange; + BOOL bRet = FALSE; + + if ( eRange == PRINTDIALOG_ALL ) + bRet = pImpl->mbAll; + else if ( eRange == PRINTDIALOG_SELECTION ) + bRet = pImpl->mbSelection; + else if ( eRange == PRINTDIALOG_FROMTO ) + bRet = pImpl->mbFromTo; + else if ( eRange == PRINTDIALOG_RANGE ) + bRet = pImpl->mbRange; + + return bRet; +} + +//-------------------------------------------------------------------- + +SV_IMPL_PTRARR(SfxFontArr_Impl,SfxFont*) + +//-------------------------------------------------------------------- + +const SfxFont* SfxFindFont_Impl( const SfxFontArr_Impl& rArr, + const String& rName ) +{ + const USHORT nCount = rArr.Count(); + for ( USHORT i = 0; i < nCount; ++i ) + { + const SfxFont *pFont = rArr[i]; + if ( pFont->GetName() == rName ) + return pFont; + } + return NULL; +} + +//-------------------------------------------------------------------- + +void SfxPrinter::UpdateFonts_Impl() +{ + VirtualDevice *pVirDev = 0; + const OutputDevice *pOut = this; + + // falls kein Drucker gefunden werden konnte, ein + // temp. Device erzeugen fuer das Erfragen der Fonts + if( !IsValid() ) + pOut = pVirDev = new VirtualDevice; + + int nCount = pOut->GetDevFontCount(); + FONTS() = new SfxFontArr_Impl((BYTE)nCount); + + std::vector< Font > aNonRegularFonts; + for(int i = 0;i < nCount;++i) + { + Font aFont(pOut->GetDevFont(i)); + if ( (aFont.GetItalic() != ITALIC_NONE) || + (aFont.GetWeight() != WEIGHT_MEDIUM) ) + { + // First: Don't add non-regular fonts. The font name is not unique so we have + // to filter the device font list. + aNonRegularFonts.push_back( aFont ); + } + else if ( FONTS()->Count() == 0 || + (*FONTS())[FONTS()->Count()-1]->GetName() != aFont.GetName() ) + { + DBG_ASSERT(0 == SfxFindFont_Impl(*FONTS(), aFont.GetName()), "Doppelte Fonts vom SV-Device!"); + SfxFont* pTmp = new SfxFont( aFont.GetFamily(), aFont.GetName(), + aFont.GetPitch(), aFont.GetCharSet() ); + FONTS()->C40_INSERT(SfxFont, pTmp, FONTS()->Count()); + } + } + delete pVirDev; + + // Try to add all non-regular fonts. It could be that there was no regular font + // with the same name added. + std::vector< Font >::const_iterator pIter; + for ( pIter = aNonRegularFonts.begin(); pIter != aNonRegularFonts.end(); pIter++ ) + { + if ( SfxFindFont_Impl( *FONTS(), pIter->GetName() ) == 0 ) + { + SfxFont* pTmp = new SfxFont( pIter->GetFamily(), pIter->GetName(), + pIter->GetPitch(), pIter->GetCharSet() ); + FONTS()->C40_INSERT( SfxFont, pTmp, FONTS()->Count() ); + } + } +} + +//-------------------------------------------------------------------- + +USHORT SfxPrinter::GetFontCount() +{ + if ( !FONTS() ) + UpdateFonts_Impl(); + return FONTS()->Count(); +} + +//-------------------------------------------------------------------- + +const SfxFont* SfxPrinter::GetFont( USHORT nNo ) const +{ + DBG_ASSERT( FONTS(), "bitte erst GetFontCount() abfragen!" ); + return (*FONTS())[ nNo ]; +} + +//-------------------------------------------------------------------- + +const SfxFont* SfxPrinter::GetFontByName( const String &rFontName ) +{ + if ( !FONTS() ) + UpdateFonts_Impl(); + return SfxFindFont_Impl(*FONTS(), rFontName); +} + +//-------------------------------------------------------------------- + +BOOL SfxPrinter::InitJob( Window* pUIParent, BOOL bAskAboutTransparentObjects ) +{ + const SvtPrinterOptions aPrinterOpt; + const SvtPrintFileOptions aPrintFileOpt; + const SvtBasePrintOptions* pPrinterOpt = &aPrinterOpt; + const SvtBasePrintOptions* pPrintFileOpt = &aPrintFileOpt; + PrinterOptions aNewPrinterOptions; + BOOL bRet = TRUE; + + ( ( IsPrintFileEnabled() && GetPrintFile().Len() ) ? pPrintFileOpt : pPrinterOpt )->GetPrinterOptions( aNewPrinterOptions ); + + if( bAskAboutTransparentObjects && !aNewPrinterOptions.IsReduceTransparency() ) + { + if ( !Application::IsHeadlessModeEnabled() ) + { + SvtPrintWarningOptions aWarnOpt; + + if( aWarnOpt.IsTransparency() ) + { + TransparencyPrintWarningBox aWarnBox( pUIParent ); + const USHORT nRet = aWarnBox.Execute(); + + if( nRet == RET_CANCEL ) + bRet = FALSE; + else + { + aNewPrinterOptions.SetReduceTransparency( nRet != RET_NO ); + aWarnOpt.SetTransparency( !aWarnBox.IsNoWarningChecked() ); + } + } + } + } + + if( bRet ) + SetPrinterOptions( aNewPrinterOptions ); + + return bRet; +} + +//-------------------------------------------------------------------- + +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 ) ); + + // TabPage einh"angen + pPage = pViewSh->CreatePrintOptionsPage( this, *pOptions ); + DBG_ASSERT( pPage, "CreatePrintOptions != SFX_VIEW_HAS_PRINTOPTIONS" ); + if( pPage ) + { + pPage->Reset( *pOptions ); + SetHelpId( pPage->GetHelpId() ); + pPage->Show(); + } + + // Dialoggr"o\se bestimmen + 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 ) + // mindestens die H"ohe der 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(); +} + diff --git a/sfx2/source/view/prnmon.cxx b/sfx2/source/view/prnmon.cxx new file mode 100644 index 000000000000..a4e96ab1065e --- /dev/null +++ b/sfx2/source/view/prnmon.cxx @@ -0,0 +1,495 @@ +/************************************************************************* + * + * 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/view/PrintableState.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 <vcl/fixed.hxx> +#include <vcl/msgbox.hxx> +#include <svtools/asynclink.hxx> + +#include <unotools/printwarningoptions.hxx> +#include <svl/eitem.hxx> + +#ifndef GCC +#endif + +#include <sfx2/prnmon.hxx> +#include <sfx2/viewsh.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/docfile.hxx> +#include "sfxtypes.hxx" +#include <sfx2/progress.hxx> +#include <sfx2/bindings.hxx> +#include "sfxresid.hxx" +#include <sfx2/event.hxx> +#include <sfx2/request.hxx> +#include <sfx2/app.hxx> + +#include "view.hrc" + +//------------------------------------------------------------------------ + +#define SFX_TITLE_MAXLEN_PRINTMONITOR 22 + +//------------------------------------------------------------------------ + +struct SfxPrintMonitor_Impl: public ModelessDialog +{ + + SfxPrintMonitor_Impl( Window *pParent, SfxViewShell *rpViewShell ); + virtual BOOL Close(); + + SfxViewShell* pViewShell; + FixedText aDocName; + FixedText aPrinting; + FixedText aPrinter; + FixedText aPrintInfo; + CancelButton aCancel; +}; + +//------------------------------------------------------------------------- + +struct SfxPrintProgress_Impl : public SfxListener +{ + SfxPrintMonitor_Impl* pMonitor; + SfxViewShell* pViewShell; + SfxPrinter* pPrinter; + SfxPrinter* pOldPrinter; + USHORT nLastPage; + BOOL bRunning; + BOOL bCancel; + BOOL bDeleteOnEndPrint; + BOOL bShow; + BOOL bCallbacks; + BOOL bOldEnablePrintFile; + BOOL bOldFlag; + BOOL bRestoreFlag; + BOOL bAborted; + svtools::AsynchronLink aDeleteLink; + Link aCancelHdl; + +private: + DECL_LINK( CancelHdl, Button * ); + DECL_STATIC_LINK( SfxPrintProgress_Impl, DeleteHdl, SfxPrintProgress * ); + +public: + SfxPrintProgress_Impl( SfxViewShell* pTheViewShell, SfxPrinter* pThePrinter ); + ~SfxPrintProgress_Impl(); + + void Delete( SfxPrintProgress* pAntiImpl ) { aDeleteLink.Call( pAntiImpl ); } + SfxViewShell* GetViewShell() const { return pViewShell; } + BOOL SetPage( USHORT nPage, const String &rPage ); + void CreateMonitor(); + virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); +}; + +void SfxPrintProgress_Impl::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint ) +{ + SfxPrintingHint* pPrintHint = PTR_CAST( SfxPrintingHint, &rHint ); + if ( pPrintHint ) + { + if ( pPrintHint->GetWhich() == -2 ) + CancelHdl(0); + } +} + +//------------------------------------------------------------------------ + +SfxPrintMonitor_Impl::SfxPrintMonitor_Impl( Window* pParent, SfxViewShell* rpViewShell ) : + ModelessDialog( pParent, SfxResId( DLG_PRINTMONITOR ) ), + pViewShell ( rpViewShell ), + aDocName ( this, SfxResId( FT_DOCNAME ) ), + aPrinting ( this, SfxResId( FT_PRINTING ) ), + aPrinter ( this, SfxResId( FT_PRINTER ) ), + aPrintInfo ( this, SfxResId( FT_PRINTINFO ) ), + aCancel ( this, SfxResId( PB_CANCELPRNMON ) ) +{ + if( rpViewShell->GetPrinter()->GetCapabilities( PRINTER_CAPABILITIES_EXTERNALDIALOG ) != 0 ) + { + String aPrep( SfxResId( STR_FT_PREPARATION ) ); + aPrinting.SetText( aPrep ); + aPrinter.Show( FALSE ); + } + FreeResource(); +} + +//------------------------------------------------------------------------ + +IMPL_STATIC_LINK_NOINSTANCE( SfxPrintProgress_Impl, DeleteHdl, SfxPrintProgress*, pAntiImpl ) +{ + delete pAntiImpl; + return 0; +} + +void actualizePrintCancelState(CancelButton& rButton, const SfxObjectShell* pShell) +{ + sal_Bool bEnableCancelButton = sal_True; + if (pShell) + bEnableCancelButton = pShell->Stamp_GetPrintCancelState(); + + if (!bEnableCancelButton) + rButton.Disable(); + else + rButton.Enable(); +} + +//------------------------------------------------------------------------ + +SfxPrintProgress_Impl::SfxPrintProgress_Impl( SfxViewShell* pTheViewShell, + SfxPrinter* pThePrinter ) : + + pMonitor ( 0 ), + pViewShell ( pTheViewShell ), + pPrinter ( pThePrinter ), + pOldPrinter ( NULL ), + nLastPage ( 0 ), + bRunning ( TRUE ), + bCancel ( FALSE ), + bDeleteOnEndPrint ( FALSE ), + bShow ( FALSE ), + bCallbacks ( FALSE ), + bOldEnablePrintFile ( FALSE ), + bOldFlag ( TRUE ), + bRestoreFlag ( FALSE ), + bAborted ( FALSE ), + aDeleteLink ( STATIC_LINK( this, SfxPrintProgress_Impl, DeleteHdl ) ) +{ + StartListening( *pViewShell->GetObjectShell() ); +} + +void SfxPrintProgress_Impl::CreateMonitor() +{ + // mark monitor to been shown in first status indication + bShow = TRUE; + + if ( !pMonitor ) + { + Window* pParent = pViewShell->GetWindow(); + pMonitor = new SfxPrintMonitor_Impl( pParent, pViewShell ); + pMonitor->aDocName.SetText( pViewShell->GetObjectShell()->GetTitle( SFX_TITLE_MAXLEN_PRINTMONITOR ) ); + pMonitor->aPrinter.SetText( pViewShell->GetPrinter()->GetName() ); + + // Stampit enable/dsiable cancel button + actualizePrintCancelState( pMonitor->aCancel, pViewShell->GetObjectShell() ); + pMonitor->aCancel.SetClickHdl( LINK( this, SfxPrintProgress_Impl, CancelHdl ) ); + } +} + +//------------------------------------------------------------------------ + +SfxPrintProgress_Impl::~SfxPrintProgress_Impl() +{ +} + +//------------------------------------------------------------------------ + +BOOL SfxPrintProgress_Impl::SetPage( USHORT nPage, const String &rPage ) +{ + // wurde der Druckauftrag abgebrochen? + if ( bCancel || !pMonitor ) + return FALSE; + + // Stampit enable/dsiable cancel button + actualizePrintCancelState(pMonitor->aCancel, pViewShell->GetObjectShell()); + + nLastPage = nPage; + String aStrPrintInfo = String( SfxResId( STR_PAGE ) ); + if ( !rPage.Len() ) + aStrPrintInfo += String::CreateFromInt32( nLastPage ); + else + aStrPrintInfo += rPage; + pMonitor->aPrintInfo.SetText( aStrPrintInfo ); + pMonitor->Update(); + return TRUE; +} + +//------------------------------------------------------------------------ + +IMPL_LINK( SfxPrintProgress_Impl, CancelHdl, Button *, EMPTYARG ) +{ + if ( !pViewShell->GetPrinter()->IsJobActive() && pViewShell->GetPrinter()->IsPrinting() ) + // we are still in StartJob, cancelling now might lead to a crash + return 0; + + if ( pMonitor ) + pMonitor->Hide(); + + pViewShell->GetObjectShell()->Broadcast( SfxPrintingHint( com::sun::star::view::PrintableState_JOB_ABORTED, NULL, NULL ) ); + pViewShell->GetPrinter()->AbortJob(); + bCancel = TRUE; + + if ( aCancelHdl.IsSet() ) + aCancelHdl.Call( this ); + + bAborted = TRUE; + return 0; +} + +BOOL SfxPrintMonitor_Impl::Close() +{ + BOOL bAgree = pViewShell ? pViewShell->GetObjectShell()->Stamp_GetPrintCancelState() : TRUE; + if (!bAgree) + return FALSE; + else + return ModelessDialog::Close(); +} + +//-------------------------------------------------------------------- + +SfxPrintProgress::SfxPrintProgress( SfxViewShell* pViewSh, FASTBOOL bShow ) +: SfxProgress( pViewSh->GetViewFrame()->GetObjectShell(), + String(SfxResId(STR_PRINTING)), 1, FALSE ), + pImp( new SfxPrintProgress_Impl( pViewSh, pViewSh->GetPrinter() ) ) +{ + #if 0 + pImp->pPrinter->SetEndPrintHdl( LINK( this, SfxPrintProgress, EndPrintNotify ) ); + pImp->pPrinter->SetErrorHdl( LINK( this, SfxPrintProgress, PrintErrorNotify ) ); + pImp->pPrinter->SetStartPrintHdl( LINK( this, SfxPrintProgress, StartPrintNotify ) ); + pImp->bCallbacks = TRUE; + #endif + + SfxObjectShell* pDoc = pViewSh->GetObjectShell(); + SFX_ITEMSET_ARG( pDoc->GetMedium()->GetItemSet(), pItem, SfxBoolItem, SID_HIDDEN, FALSE ); + if ( pItem && pItem->GetValue() ) + bShow = FALSE; + + if ( bShow ) + pImp->CreateMonitor(); + + Lock(); + if ( !SvtPrintWarningOptions().IsModifyDocumentOnPrintingAllowed() ) + { + pImp->bRestoreFlag = TRUE; + pImp->bOldFlag = pDoc->IsEnableSetModified(); + if ( pImp->bOldFlag ) + pDoc->EnableSetModified( FALSE ); + } +} + +//-------------------------------------------------------------------- + +SfxPrintProgress::~SfxPrintProgress() +{ + // k"onnte auch schon weg sein (in EndPrintNotify) + DELETEZ(pImp->pMonitor); + + // ggf. Callbacks entfermen + if ( pImp->bCallbacks ) + { + // pImp->pPrinter->SetEndPrintHdl( Link() ); + pImp->pPrinter->SetErrorHdl( Link() ); + pImp->bCallbacks = FALSE; + } + + // ggf. vorherigen Drucker wieder einsetzen + if ( pImp->pOldPrinter ) + pImp->pViewShell->SetPrinter( pImp->pOldPrinter, SFX_PRINTER_PRINTER ); + else + // ggf. vorherigen Print-To-File-Status zuruecksetzen + pImp->pViewShell->GetPrinter()->EnablePrintFile( pImp->bOldEnablePrintFile ); + + // EndPrint-Notification an Frame + //pImp->pViewShell->GetViewFrame()->GetFrame().Lock_Impl(FALSE); + pImp->EndListening( *(pImp->pViewShell->GetObjectShell()) ); + + // the following call might destroy the view or even the document + pImp->pViewShell->CheckOwnerShip_Impl(); + delete pImp; +} + +//-------------------------------------------------------------------- + +BOOL SfxPrintProgress::SetState( ULONG nValue, ULONG nNewRange ) +{ + if ( pImp->bShow ) + { + pImp->bShow = FALSE; + if ( pImp->pMonitor ) + { + pImp->pMonitor->Show(); + pImp->pMonitor->Update(); + } + } + + return pImp->SetPage( (USHORT)nValue, GetStateText_Impl() ) && + SfxProgress::SetState( nValue, nNewRange ); +} + +//-------------------------------------------------------------------- + +void SfxPrintProgress::SetText( const String& rText ) +{ + if ( pImp->pMonitor ) + { + pImp->pMonitor->SetText( rText ); + pImp->pMonitor->Update(); + } + SfxProgress::SetText( rText ); +} + +//------------------------------------------------------------------------ + +IMPL_LINK_INLINE_START( SfxPrintProgress, PrintErrorNotify, void *, EMPTYARG ) +{ + if ( pImp->pMonitor ) + pImp->pMonitor->Hide(); + // AbortJob calls EndPrint hdl, so do not delete pImp just now + BOOL bWasDeleteOnEndPrint = pImp->bDeleteOnEndPrint; + pImp->bDeleteOnEndPrint = FALSE; + pImp->pPrinter->AbortJob(); + InfoBox( pImp->GetViewShell()->GetWindow(), + String( SfxResId(STR_ERROR_PRINT) ) ).Execute(); + if ( pImp->bRestoreFlag && pImp->pViewShell->GetObjectShell()->IsEnableSetModified() != pImp->bOldFlag ) + pImp->pViewShell->GetObjectShell()->EnableSetModified( pImp->bOldFlag ); + pImp->GetViewShell()->GetObjectShell()->Broadcast( SfxPrintingHint( com::sun::star::view::PrintableState_JOB_FAILED, NULL, NULL ) ); + // now we can clean up like normally EndPrint hdl does + if( bWasDeleteOnEndPrint ) + { + DELETEZ(pImp->pMonitor); + delete this; + } + return 0; +} +IMPL_LINK_INLINE_END( SfxPrintProgress, PrintErrorNotify, void *, EMPTYARG ) + +//------------------------------------------------------------------------ + +IMPL_LINK( SfxPrintProgress, StartPrintNotify, void *, EMPTYARG ) +{ + SfxObjectShell *pObjShell = pImp->pViewShell->GetObjectShell(); + SFX_APP()->NotifyEvent(SfxEventHint(SFX_EVENT_PRINTDOC, GlobalEventConfig::GetEventName( STR_EVENT_PRINTDOC ), pObjShell)); + pObjShell->Broadcast( SfxPrintingHint( com::sun::star::view::PrintableState_JOB_STARTED, NULL, NULL ) ); + return 0; +} + +IMPL_LINK( SfxPrintProgress, EndPrintNotify, void *, EMPTYARG ) +{ + if ( pImp->pMonitor ) + pImp->pMonitor->Hide(); + + SfxViewShell* pViewShell = pImp->pViewShell; + + // Slots enablen + pViewShell->Invalidate( SID_PRINTDOC ); + pViewShell->Invalidate( SID_PRINTDOCDIRECT ); + pViewShell->Invalidate( SID_SETUPPRINTER ); + + // . . . falls der Printer im System umgestellt wurde, hier Aenderung + // nachziehen. + //! if( pMDI->IsPrinterChanged() ) pMDI->Changed( 0L ); + + // Callbacks rausnehmen + // pImp->pPrinter->SetEndPrintHdl( Link() ); + pImp->pPrinter->SetErrorHdl( Link() ); + pImp->bCallbacks = FALSE; + + // ggf. alten Printer wieder einsetzen + if ( pImp->pOldPrinter ) + { + // Fix #59613#: niemals den aktuellen Printer synchron abschiessen ! + // Da sowieso immer bDeleteOnEndPrint gesetzt wird, wird der der Drucker im + // dtor vom Printprogress ( dann aber asynchron !! ) zur"uckgesetzt. +/* + pImp->pViewShell->SetPrinter( pImp->pOldPrinter, SFX_PRINTER_PRINTER ); + pImp->pOldPrinter = 0; + pImp->pPrinter = 0; + */ + } + else + // ggf. vorherigen Print-To-File-Status zuruecksetzen + pViewShell->GetPrinter()->EnablePrintFile( pImp->bOldEnablePrintFile ); + + // it is possible that after printing the document or view is deleted (because the VieShell got the ownership) + // so first clean up + if ( pImp->bRestoreFlag && pViewShell->GetObjectShell()->IsEnableSetModified() != pImp->bOldFlag ) + pViewShell->GetObjectShell()->EnableSetModified( TRUE ); + + pViewShell->GetObjectShell()->Broadcast( SfxPrintingHint( com::sun::star::view::PrintableState_JOB_COMPLETED, NULL, NULL ) ); + if ( pImp->bDeleteOnEndPrint ) + { + DELETEZ(pImp->pMonitor); + delete this; + } + else + { + DBG_ASSERT( !pImp->pOldPrinter, "Unable to restore printer!" ); + pImp->bRunning = FALSE; + } + + return 0; +} + +//------------------------------------------------------------------------ + +void SfxPrintProgress::DeleteOnEndPrint() +{ + UnLock(); // jetzt schon, wg. Drucken im Thread +#ifndef WNT + // da das Drucken im 'Thread' unter Windows zu undefiniert ist bleibt der + // Print-Monitor dort stehen, auf den anderen Plattformen kann man dann + // weiterarbeiten, also kommt das Teil weg + DELETEZ( pImp->pMonitor ); +#endif + + pImp->bDeleteOnEndPrint = TRUE; + if ( !pImp->bRunning ) + delete this; +} + +//------------------------------------------------------------------------ + +void SfxPrintProgress::RestoreOnEndPrint( SfxPrinter *pOldPrinter, + BOOL bOldEnablePrintFile ) +{ + pImp->pOldPrinter = pOldPrinter; + pImp->bOldEnablePrintFile = bOldEnablePrintFile; +} + +//------------------------------------------------------------------------ + +void SfxPrintProgress::RestoreOnEndPrint( SfxPrinter *pOldPrinter ) +{ + RestoreOnEndPrint( pOldPrinter, FALSE ); +} + +//------------------------------------------------------------------------ + +void SfxPrintProgress::SetCancelHdl( const Link& aCancelHdl ) +{ + pImp->aCancelHdl = aCancelHdl; +} + +BOOL SfxPrintProgress::IsAborted() const +{ + return pImp->bAborted; +} diff --git a/sfx2/source/view/sfxbasecontroller.cxx b/sfx2/source/view/sfxbasecontroller.cxx new file mode 100644 index 000000000000..f5c24b195af7 --- /dev/null +++ b/sfx2/source/view/sfxbasecontroller.cxx @@ -0,0 +1,1509 @@ +/************************************************************************* + * + * 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 <vos/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 <hash_map> + +#include <sfx2/event.hxx> +#include "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::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 std::hash_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) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + SfxViewShell* pShell = m_pController->GetViewShell_Impl(); + if ( m_pController != NULL && pShell ) + { + BOOL bCanClose = (BOOL) pShell->PrepareClose( 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::createFromAscii("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 ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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( 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 ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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 ).GetViewName(); + + return sViewName; +} + +Sequence< PropertyValue > SAL_CALL SfxBaseController::getCreationArguments() throw (RuntimeException) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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() ) ; + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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 + SfxEventHint aHint( SFX_EVENT_VIEWCREATED, GlobalEventConfig::GetEventName( STR_EVENT_VIEWCREATED ), m_pData->m_pViewShell->GetObjectShell() ); + 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! + DBG_ERROR("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 ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // 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() ; + + // weitere View auf dasselbe Doc? + 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); + + 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; + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + if ( m_pData->m_pViewShell ) + { + m_pData->m_pViewShell->WriteUserData( sData1 ) ; + OUSTRING sData( sData1 ); + aAny <<= sData ; + } + + return aAny ; +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XController +//________________________________________________________________________________________________________ + +void SAL_CALL SfxBaseController::restoreViewData( const ANY& aValue ) throw( ::com::sun::star::uno::RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + if ( m_pData->m_pViewShell ) + { + OUSTRING sData; + aValue >>= sData ; + m_pData->m_pViewShell->ReadUserData( sData ) ; + } +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XController +//________________________________________________________________________________________________________ + +REFERENCE< XFRAME > SAL_CALL SfxBaseController::getFrame() throw( ::com::sun::star::uno::RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + return m_pData->m_xFrame; +} + +//________________________________________________________________________________________________________ +// SfxBaseController -> XController +//________________________________________________________________________________________________________ + +REFERENCE< XMODEL > SAL_CALL SfxBaseController::getModel() throw( ::com::sun::star::uno::RuntimeException ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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 OUSTRING& sTargetFrameName, + sal_Int32 eSearchFlags ) throw( RUNTIMEEXCEPTION ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + REFERENCE< XDISPATCH > xDisp; + if ( m_pData->m_pViewShell ) + { + SfxViewFrame* pAct = m_pData->m_pViewShell->GetViewFrame() ; + if ( !m_pData->m_bDisposing ) + { + if ( sTargetFrameName.compareToAscii( "_beamer" ) == COMPARE_EQUAL ) + { + SfxViewFrame *pFrame = m_pData->m_pViewShell->GetViewFrame(); + if ( eSearchFlags & ( ::com::sun::star::frame::FrameSearchFlag::CREATE )) + pFrame->SetChildWindow( SID_BROWSER, 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.compareToAscii( ".uno:" ) == COMPARE_EQUAL ) + { + 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.compareToAscii( "slot:" ) == COMPARE_EQUAL ) + { + USHORT nId = (USHORT) 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.compareToAscii( "_self" )==COMPARE_EQUAL || 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 +//________________________________________________________________________________________________________ + +SEQUENCE< REFERENCE< XDISPATCH > > SAL_CALL SfxBaseController::queryDispatches( const 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(); + 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; + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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 ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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 ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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->bControllerSet = sal_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( SfxEventHint(SFX_EVENT_CLOSEVIEW, GlobalEventConfig::GetEventName( STR_EVENT_CLOSEVIEW ), pDoc ) ); + 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() +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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 ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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 ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + 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) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + m_pData->m_aUserInputInterception.removeMouseClickHandler( xHandler ); +} + +::com::sun::star::uno::Sequence< sal_Int16 > SAL_CALL SfxBaseController::getSupportedCommandGroups() +throw (::com::sun::star::uno::RuntimeException) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + std::list< sal_Int16 > aGroupList; + SfxViewFrame* pViewFrame( m_pData->m_pViewShell->GetFrame() ); + SfxSlotPool* pPool = &SfxSlotPool::GetSlotPool( pViewFrame ); + + SfxSlotPool* pSlotPool = pPool ? pPool : &SFX_SLOTPOOL(); + const ULONG nMode( SFX_SLOT_TOOLBOXCONFIG|SFX_SLOT_ACCELCONFIG|SFX_SLOT_MENUCONFIG ); + + // Gruppe anw"ahlen ( Gruppe 0 ist intern ) + for ( USHORT 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; + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + if ( m_pData->m_pViewShell ) + { + const ULONG 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 ( USHORT 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; +} + +BOOL SfxBaseController::HandleEvent_Impl( NotifyEvent& rEvent ) +{ + return m_pData->m_aUserInputInterception.handleNotifyEvent( rEvent ); +} + +BOOL SfxBaseController::HasKeyListeners_Impl() +{ + return m_pData->m_aUserInputInterception.hasKeyHandlers(); +} + +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( TRUE ); + else + pViewFrame->GetDispatcher()->HideUI( FALSE ); + + if ( rFrame.IsInPlace() ) + pViewFrame->LockAdjustPosSizePixel(); + + if ( nPluginMode == 3 ) + rFrame.GetWorkWindow_Impl()->SetInternalDockingAllowed( 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( TRUE ); + } + } + else + { + DBG_ASSERT( !rFrame.IsInPlace() && !bHasPluginMode, "Special modes not compatible with hidden mode!" ); + rFrame.GetWindow().Show(); + } + + // Jetzt UpdateTitle, hidden TopFrames haben sonst keinen Namen! + pViewFrame->UpdateTitle(); + + if ( !rFrame.IsInPlace() ) + pViewFrame->Resize( 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 ) + { + try + { + Reference< XViewDataSupplier > xViewDataSupplier( getModel(), UNO_QUERY ); + Reference< XIndexAccess > xViewData; + if ( xViewDataSupplier.is() ) + xViewData = xViewDataSupplier->getViewData(); + if ( xViewData.is() && xViewData->getCount() > 0 ) + { + Sequence< PropertyValue > aViewData; + if ( ( xViewData->getByIndex( 0 ) >>= aViewData ) && ( aViewData.getLength() ) ) + { + m_pData->m_pViewShell->ReadUserDataSequence( aViewData, 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 () +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + 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); +} diff --git a/sfx2/source/view/userinputinterception.cxx b/sfx2/source/view/userinputinterception.cxx new file mode 100644 index 000000000000..e716e604b649 --- /dev/null +++ b/sfx2/source/view/userinputinterception.cxx @@ -0,0 +1,264 @@ +/************************************************************************* + * + * 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 ); + + USHORT 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(); + } + } + } + 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(); + } + } + } + break; + + default: + OSL_ENSURE( false, "UserInputInterception::handleNotifyEvent: illegal event type!" ); + break; + } + + return bHandled; + } + +//........................................................................ +} // namespace sfx2 +//........................................................................ diff --git a/sfx2/source/view/view.hrc b/sfx2/source/view/view.hrc new file mode 100644 index 000000000000..243dcd56e4c8 --- /dev/null +++ b/sfx2/source/view/view.hrc @@ -0,0 +1,126 @@ +/************************************************************************* + * + * 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) + +#ifndef STR_UNDO +#define STR_UNDO (RID_SFX_VIEW_START+11) +#define STR_REDO (RID_SFX_VIEW_START+12) +#define STR_REPEAT (RID_SFX_VIEW_START+13) +#endif + +#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..b58bbc2840da --- /dev/null +++ b/sfx2/source/view/viewfac.cxx @@ -0,0 +1,79 @@ +/************************************************************************* + * + * 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 <rtl/ustrbuf.hxx> +#include "viewfac.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::GetViewName() const +{ + ::rtl::OUStringBuffer aViewName; + aViewName.appendAscii( "view" ); + aViewName.append( sal_Int32( GetOrdinal() ) ); + return aViewName.makeStringAndClear(); +} + +// CTOR / DTOR ----------------------------------------------------------- + +SfxViewFactory::SfxViewFactory( SfxViewCtor fnC, SfxViewInit fnI, + USHORT nOrdinal, const ResId& aDescrResId ): + fnCreate(fnC), + fnInit(fnI), + nOrd(nOrdinal), + aDescription(aDescrResId.GetId(), *aDescrResId.GetResMgr()) +{ + aDescription.SetRT(aDescrResId.GetRT()); + DBG_CTOR(SfxViewFactory, 0); +// SFX_APP()->RegisterViewFactory_Impl(*this); +} + +SfxViewFactory::~SfxViewFactory() +{ + DBG_DTOR(SfxViewFactory, 0); +} + + diff --git a/sfx2/source/view/viewfrm.cxx b/sfx2/source/view/viewfrm.cxx new file mode 100644 index 000000000000..035fd3f794de --- /dev/null +++ b/sfx2/source/view/viewfrm.cxx @@ -0,0 +1,3512 @@ +/************************************************************************* + * + * 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> + +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/unohlp.hxx> +#endif +#ifndef _SPLITWIN_HXX //autogen +#include <vcl/splitwin.hxx> +#endif +#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> +#ifndef _MSGBOX_HXX //autogen +#include <vcl/msgbox.hxx> +#endif +#include <svtools/sfxecode.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 <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 <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; +namespace css = ::com::sun::star; + +#ifndef GCC +#endif + +// wg. 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 "sfxresid.hxx" +#include "appbas.hxx" +#include <sfx2/objitem.hxx> +#include "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 "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 ) + { + // Bei CTRL-Reload den aktiven Frame reloaden + 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; + } + } + + // Wenn nur ein Reload der Graphiken eines oder mehrerer ChildFrames + // gemacht werden soll + 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; + } + + // Der TopLevel-Frame selbst het keine Graphiken! + if ( bReloadAvailable ) + return; + } + } + else + { + // Bei CTRL-Edit den TopFrame bearbeiten + 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; + + // Wg. Doppeltbelegung in Toolboxen (mit/ohne Ctrl) ist es auch + // m"oglich, da\s der Slot zwar enabled ist, aber Ctrl-Click + // trotzdem nicht geht! + 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() ) + { + // Speichern und Readonly Reloaden + 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; + } + + // Parameter auswerten + // sal_Bool bReload = sal_True; + if ( rReq.IsAPI() ) + { + // per API steuern ob r/w oder 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 ); + } + + // r/o-Doc kann nicht in Editmode geschaltet werden? + rReq.Done( sal_False ); + + if ( nOpenMode == SFX_STREAM_READWRITE && !rReq.IsAPI() ) + { + // dem ::com::sun::star::sdbcx::User anbieten, als Vorlage zu oeffnen + 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 ); + // if( nOpenMode == SFX_STREAM_READONLY ) + // pMed->Close(); + return; + } + } + + rReq.AppendItem( SfxBoolItem( SID_FORCERELOAD, sal_True) ); + rReq.AppendItem( SfxBoolItem( SID_SILENT, sal_True )); + } + + case SID_RELOAD: + { + // Wg. Doppeltbelegung in Toolboxen (mit/ohne Ctrl) ist es auch + // m"oglich, da\s der Slot zwar enabled ist, aber Ctrl-Click + // trotzdem nicht geht! + 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 ist ggf. verboten + 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); + // editierbar "offnen? + sal_Bool bForEdit = !pSh->IsReadOnly(); + if ( rReq.GetSlot() == SID_EDITDOC ) + bForEdit = !bForEdit; + + // ggf. beim User nachfragen + sal_Bool bDo = ( GetViewShell()->PrepareClose() != 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(); + + // Frameset abziehen, bevor FramesetView evtl. verschwindet + String aURL = pURLItem ? pURLItem->GetValue() : + pMedium->GetName(); + + sal_Bool bHandsOff = + ( pMedium->GetURLObject().GetProtocol() == INET_PROT_FILE && !xOldObj->IsDocShared() ); + + // bestehende SfxMDIFrames f"ur dieses Doc leeren + // eigenes Format oder R/O jetzt editierbar "offnen? + 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 >, USHORT > 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 ); + } + + // Falls eine salvagede Datei vorliegt, nicht nochmals die + // OrigURL mitschicken, denn die Tempdate ist nach Reload + // ungueltig + 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 vorbidden then. + if ( xOldObj->IsDocShared() ) + pNewSet->Put( SfxStringItem( SID_FILE_NAME, xOldObj->GetSharedFileURL() ) ); + + //pNewMedium = new SfxMedium( aURL, nMode, pMedium->IsDirect(), bUseFilter ? pMedium->GetFilter() : 0, pNewSet ); + //pNewSet = pNewMedium->GetItemSet(); + if ( pURLItem ) + pNewSet->Put( SfxStringItem( SID_REFERER, pMedium->GetName() ) ); + else + pNewSet->Put( SfxStringItem( SID_REFERER, String() ) ); + + xOldObj->CancelTransfers(); + + // eigentliches Reload + //pNewSet->Put( SfxFrameItem ( SID_DOCFRAME, GetFrame() ) ); + + if ( pSilentItem && pSilentItem->GetValue() ) + pNewSet->Put( SfxBoolItem( SID_SILENT, sal_True ) ); + + SFX_ITEMSET_ARG(pNewSet, pInteractionItem, SfxUnoAnyItem, SID_INTERACTIONHANDLER, FALSE); + SFX_ITEMSET_ARG(pNewSet, pMacroExecItem , SfxUInt16Item, SID_MACROEXECMODE , FALSE); + SFX_ITEMSET_ARG(pNewSet, pDocTemplateItem, SfxUInt16Item, SID_UPDATEDOCMODE , FALSE); + + if (!pInteractionItem) + { + Reference < ::com::sun::star::task::XInteractionHandler > xHdl( ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString::createFromAscii("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 ); + // Altes Dok nicht cachen! Gilt nicht, wenn anderes + // Doc geladen wird. + + 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 + { + // an error handling should be done here?! + // if ( !pSilentItem || !pSilentItem->GetValue() ) + // ErrorHandler::HandleError( nLoadError ); + } + } + else + { + if ( xNewObj->GetModifyPasswordHash() && xNewObj->GetModifyPasswordHash() != xOldObj->GetModifyPasswordHash() ) + { + xNewObj->SetModifyPasswordEntered( sal_False ); + xNewObj->SetReadOnly(); + } + + 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 ) ); + } + + // als erledigt recorden + rReq.Done( sal_True ); + rReq.SetReturnValue(SfxBoolItem(rReq.GetSlot(), sal_True)); + return; + } + else + { + // als nicht erledigt recorden + 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 ) + // Ich bin gerade am Reloaden und Yielde so vor mich hin ... + return; + + GetFrame().GetParentFrame(); + SfxWhichIter aIter( rSet ); + for ( sal_uInt16 nWhich = aIter.FirstWhich(); nWhich; nWhich = aIter.NextWhich() ) + { + if ( GetFrame().HasComponent() ) + { + // Wenn die Komponente es nicht selbst dispatched, dann + // macht es auch keinen Sinn! + 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 + { + // Wenn irgendein ChildFrame reloadable ist, wird der Slot + // enabled, damit man CTRL-Reload machen kann + 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 ) +{ + // gibt es an der obersten Shell einen Undo-Manager? + SfxShell *pSh = GetDispatcher()->GetShell(0); + SfxUndoManager* 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(0); + GetBindings().InvalidateAll(sal_False); + bOK = sal_True; + break; + + case SID_REDO: + pShUndoMgr->Redo(0); + GetBindings().InvalidateAll(sal_False); + bOK = sal_True; + break; + + case SID_REPEAT: + if ( pSh->GetRepeatTarget() ) + pShUndoMgr->Repeat( *pSh->GetRepeatTarget(), 0); + bOK = sal_True; + break; + } + } + else if ( GetViewShell() ) + { + // der SW hat eigenes Undo an der 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 ) +{ + // Undo-Manager suchen + SfxShell *pSh = GetDispatcher()->GetShell(0); + if ( !pSh ) + // Ich bin gerade am Reloaden und Yielde so vor mich hin ... + return; + + SfxUndoManager *pShUndoMgr = pSh->GetUndoManager(); + if ( !pShUndoMgr ) + { + // der SW hat eigenes Undo an der 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( SfxResId( STR_UNDO ) ); + aTmp += pShUndoMgr->GetUndoActionComment(0); + rSet.Put( SfxStringItem( SID_UNDO, aTmp ) ); + } + else + rSet.DisableItem( SID_UNDO ); + + if ( pShUndoMgr && pShUndoMgr->GetRedoActionCount() ) + { + String aTmp( SfxResId(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, 0) ) + { + String aTmp( SfxResId(STR_REPEAT) ); + aTmp += pShUndoMgr->GetRepeatActionComment(*pTarget, 0); + 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() + +/* [Beschreibung] + + Diese Methode entleert den SfxViewFrame, d.h. nimmt die <SfxObjectShell> + vom Dispatcher und beendet seine <SfxListener>-Beziehung zu dieser + SfxObjectShell (wodurch sie sich ggf. selbst zerst"ort). + + Somit kann durch Aufruf von ReleaseObjectShell() und SetObjectShell() + die SfxObjectShell ausgetauscht werden. + + Zwischen RealeaseObjectShell() und SetObjectShell() darf die Kontrolle + nicht an das System abgegeben werden. + + + [Querverweise] + + <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 + DBG_ERROR("Keine 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!" ); + + // Wenn bis jetzt noch nicht gespeichert wurde, sollen eingebettete Objekte + // auch nicht mehr automatisch gespeichert werden! + if ( GetViewShell() ) + GetViewShell()->DiscardClients_Impl(); + Broadcast( SfxSimpleHint( SFX_HINT_DYING ) ); + + if (SfxViewFrame::Current() == this) + SfxViewFrame::SetViewFrame( NULL ); + + // Da der Dispatcher leer ger"aumt wird, kann man ihn auch nicht mehr + // vern"unftig verwenden - also besser still legen + GetDispatcher()->Lock(sal_True); + delete this; + + return sal_True; +} + +//-------------------------------------------------------------------- + +void SfxViewFrame::DoActivate( sal_Bool bUI, SfxViewFrame* pOldFrame ) +{ + DBG_CHKTHIS(SfxViewFrame, 0); + SFX_APP(); + +#ifdef WIN + pSfxApp->TestFreeResources_Impl(); +#endif + + pDispatcher->DoActivate_Impl( bUI, pOldFrame ); + + // Wenn ich einen parent habe und dieser ist kein parent des alten + // ViewFrames, erh"alt er ein ParentActivate + if ( bUI ) + { +/* + SfxMedium* pMed = GetObjectShell() ? GetObjectShell()->GetMedium() : NULL; + if( pMed ) + { + SFX_ITEMSET_ARG( + pMed->GetItemSet(), pInterceptorItem, SfxSlotInterceptorItem, + SID_INTERCEPTOR, sal_False ); + if( pInterceptorItem ) + { + SfxSlotInterceptor* pInter = pInterceptorItem->GetValue(); + if( !pInter->GetBindings() ) + pInter->SetBindings( &GetBindings() ); + pInter->Activate( sal_True ); + } + } + */ + 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 ); + + // Wenn ich einen parent habe und dieser ist kein parent des neuen + // ViewFrames, erh"alt er ein ParentDeactivate + if ( bUI ) + { +// if ( GetFrame().GetWorkWindow_Impl() ) +// GetFrame().GetWorkWindow_Impl()->SaveStatus_Impl(); +/* + SfxMedium* pMed = GetObjectShell() ? GetObjectShell()->GetMedium() : NULL; + if( pMed ) + { + SFX_ITEMSET_ARG( + pMed->GetItemSet(), pInterceptorItem, SfxSlotInterceptorItem, + SID_INTERCEPTOR, sal_False ); + if( pInterceptorItem ) + pInterceptorItem->GetValue()->Activate( sal_False ); + } +*/ + SfxViewFrame *pFrame = GetParentViewFrame(); + while ( pFrame ) + { + if ( !pNewFrame || !pNewFrame->GetFrame().IsParent( &pFrame->GetFrame() ) ) + pFrame->pDispatcher->DoParentDeactivate_Impl(); + pFrame = pFrame->GetParentViewFrame(); + } + } +#ifdef WIN + pSfxApp->TestFreeResources_Impl(); +#endif +} + +//------------------------------------------------------------------------ +void SfxViewFrame::InvalidateBorderImpl( const SfxViewShell* pSh ) +{ + if( pSh && !nAdjustPosPixelLock ) + { + if ( GetViewShell() && GetWindow().IsVisible() ) + { + if ( GetFrame().IsInPlace() ) + { + /* + Size aSize( GetViewShell()->GetWindow()->GetSizePixel() ); + + //Size aBorderSz( pEnv->GetBorderWin()->GetHatchBorderPixel() ); + Point aOfs; //( aBorderSz.Width(), aBorderSz.Height() ); + + DoAdjustPosSizePixel( GetViewShell(), aOfs, aSize );*/ + 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; + + // r/o Umschaltung? + SfxBindings& rBind = GetBindings(); + rBind.Invalidate( SID_RELOAD ); + SfxDispatcher *pDispat = GetDispatcher(); + sal_Bool bWasReadOnly = pDispat->GetReadOnly_Impl(); + sal_Bool bIsReadOnly = xObjSh->IsReadOnly(); + if ( !bWasReadOnly != !bIsReadOnly ) + { + // Dann auch 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 ); + + // Dispatcher-Update nur erzwingen, wenn es nicht sowieso + // demn"achst kommt, anderenfalls ist Zappelei oder gar + // GPF m"oglich, da Writer z.B. gerne mal im Resize irgendwelche + // Aktionen t"atigt, die ein SetReadOnlyUI am Dispatcher zur + // Folge haben! + 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)) ) + { + // Wenn das Document asynchron geladen wurde, wurde der Dispatcher + // auf ReadOnly gesetzt, was zur"?ckgenommen werden mu\s, wenn + // das Document selbst nicht ReadOnly ist und das Laden fertig ist. + 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() ) + { + // Im Gegensatz zu oben (TITLE_CHANGED) mu\s das UI nicht + // upgedated werden, da es nicht gehidet war! + + // #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; // wegen der kranken Array-Syntax + SfxViewFrameArr_Impl &rViewArr = SFX_APP()->GetViewFrames_Impl(); + rViewArr.C40_INSERT(SfxViewFrame, pThis, rViewArr.Count() ); +} + +SfxViewFrame::SfxViewFrame +( + SfxFrame& rFrame, + SfxObjectShell* pObjShell +) + +/* [Beschreibung] + + Ctor des SfxViewFrame f"ur eine <SfxObjectShell> aus der Ressource. + Die 'nViewId' der zu erzeugenden <SfxViewShell> kann angegeben werden + (default ist die zuerst registrierte SfxViewShell-Subklasse). +*/ + + : 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() ) + // Die Bindings l"oscht der Frame! + KillDispatcher_Impl(); + + delete pImp->pWindow; + + if ( GetFrame().GetCurrentViewFrame() == this ) + GetFrame().SetCurrentViewFrame_Impl( NULL ); + + // von Frame-Liste abmelden + SfxApplication *pSfxApp = SFX_APP(); + SfxViewFrameArr_Impl &rFrames = pSfxApp->GetViewFrames_Impl(); + const SfxViewFrame *pThis = this; + rFrames.Remove( rFrames.GetPos(pThis) ); + + // Member l"oschen + KillDispatcher_Impl(); + + delete pImp; +} + +//------------------------------------------------------------------------ +void SfxViewFrame::KillDispatcher_Impl() + +// Dispatcher abr"aumen und l"oschen + +{ + 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() + +/* [Beschreibung] + + Liefert die Anzahl der sichtbaren <SfxViewFrame>-Instanzen. +*/ + +{ + 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*/) +{ +/* OBSOLETE: If this is used, framework/uielement/progressbarwrapper.[h|c]xx & + framework/uielement/statusindicatorinterfacewrapper.[h|c]xx must be + extended to support a new interface to support ShowStatusText/HideStatusText + SfxWorkWindow* pWorkWin = GetFrame().GetWorkWindow_Impl(); + SfxStatusBarManager *pMgr = pWorkWin->GetStatusBarManager_Impl(); + if ( pMgr ) + { + pMgr->GetStatusBar()->HideItems(); + pMgr->GetStatusBar()->SetText( rText ); + } +*/ +} + +//-------------------------------------------------------------------- +void SfxViewFrame::HideStatusText() +{ +/* OBSOLETE: If this is used, framework/uielement/progressbarwrapper.[h|c]xx & + framework/uielement/statusindicatorinterfacewrapper.[h|c]xx must be + extended to support a new interface to support ShowStatusText/HideStatusText + SfxWorkWindow* pWorkWin = GetFrame().GetWorkWindow_Impl(); + SfxStatusBarManager *pMgr = pWorkWin->GetStatusBarManager_Impl(); + if ( pMgr ) + pMgr->GetStatusBar()->ShowItems(); +*/ +} + + +//-------------------------------------------------------------------- +#ifdef ENABLE_INIMANAGER//MUSTINI +SfxIniManager* SfxViewFrame::GetIniManager() const +{ +/* SfxIniManager *pIniMgr = GetObjectShell() + ? GetObjectShell()->GetFactory().GetIniManager() + : 0; + if ( !pIniMgr )*/ //! + return SFX_APP()->GetAppIniManager(); +// return pIniMgr; +} +#endif + +//-------------------------------------------------------------------- +void SfxViewFrame::DoAdjustPosSizePixel //! teilen in Inner.../Outer... +( + SfxViewShell* pSh, + const Point& rPos, + const Size& rSize +) +{ + DBG_CHKTHIS(SfxViewFrame, 0); + + // Components benutzen diese Methode nicht! + 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 ) + +/* [Beschreibung] + + Interne Methode zum setzen der jeweils aktuellen <SfxViewShell>-Instanz, + die in diesem SfxViewFrame aktiv ist. +*/ + +{ + SfxShell::SetViewShell_Impl( pVSh ); + + // Hack: InPlaceMode + if ( pVSh ) + pImp->bResizeInToOut = sal_False; +} + +//-------------------------------------------------------------------- +/* + Beschreibung: + Der ParentViewFrame ist der ViewFrame des Containers bei internem 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(), "Kein Dokument!" ); + 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, TRUE ); + } + + // cursor and focus + SfxViewShell* pViewSh = GetViewShell(); + if ( bEnable ) + { + // show cursor + if ( pViewSh ) + pViewSh->ShowCursor(); + } + else + { + // hide cursor + if ( pViewSh ) + pViewSh->ShowCursor(sal_False); + } +/* + if ( !bEnable ) + GetBindings().ENTERREGISTRATIONS(); + GetDispatcher()->Lock( !bEnable ); + if ( bEnable ) + GetBindings().LEAVEREGISTRATIONS(); +*/ + } +} + +//-------------------------------------------------------------------- +void SfxViewFrame::Show() + +/* [Beschreibung] + + Diese Methode macht das Frame-Window sichtbar und ermittelt vorher + den Fenstername. Au\serdem wird das Dokument festgehalten. Man darf + i.d.R. nie das Window direkt showen! +*/ + +{ + // zuerst locken damit in UpdateTitle() gilt: IsVisible() == sal_True (:#) + if ( xObjSh.Is() ) + { + xObjSh->GetMedium()->GetItemSet()->ClearItem( SID_HIDDEN ); + if ( !pImp->bObjLocked ) + LockObjectShell_Impl( sal_True ); + + // Doc-Shell Titel-Nummer anpassen, get unique view-no + if ( 0 == pImp->nDocViewNo ) + { + GetDocNumber_Impl(); + UpdateTitle(); + } + } + else + UpdateTitle(); + + // Frame-Window anzeigen, aber nur wenn der ViewFrame kein eigenes Window + // hat oder wenn er keine Component enth"alt + if ( &GetWindow() == &GetFrame().GetWindow() || !GetFrame().HasComponent() ) + GetWindow().Show(); + GetFrame().GetWindow().Show(); + +/* SfxViewFrame* pCurrent = SfxViewFrame::Current(); + if ( GetFrame().GetFrameInterface()->isActive() && + pCurrent != this && + ( !pCurrent || pCurrent->GetParentViewFrame_Impl() != this ) && + !GetActiveChildFrame_Impl() ) + MakeActive_Impl( FALSE );*/ + if ( xObjSh.Is() && xObjSh->Get_Impl()->bHiddenLockedByAPI ) + { + xObjSh->Get_Impl()->bHiddenLockedByAPI = FALSE; + xObjSh->OwnerLock(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, "Falscher Locked-Status!" ); + + DBG_ASSERT( GetObjectShell(), "Kein Dokument!" ); + GetObjectShell()->OwnerLock(bLock); + pImp->bObjLocked = bLock; +} + +//-------------------------------------------------------------------- +void SfxViewFrame::MakeActive_Impl( BOOL bGrabFocus ) +{ + if ( GetViewShell() && !GetFrame().IsClosing_Impl() ) + { + if ( IsVisible() ) + { + if ( GetViewShell() ) + { + BOOL bPreview = FALSE; + if ( GetObjectShell()->IsPreview() ) + { + bPreview = 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( 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() ) // PB: #74432# xFrame cann be NULL + xFrame->setActiveFrame( xActive ); + } +} + +SfxViewFrame* SfxViewFrame::GetActiveChildFrame_Impl() const +{ + SfxViewFrame *pViewFrame = pImp->pActiveChild; +/* + if ( !pViewFrame ) + { + // Wenn es keinen aktiven ChildFrame gibt, irgendeinen nehmen + for ( sal_uInt16 n=0; n<GetChildFrameCount(); n++ ) + { + pViewFrame = + PTR_CAST( SfxViewFrame, GetChildFrame(n)->GetChildFrame(0) ); + if ( pViewFrame ) + break; + } + } + + pImp->pActiveChild = pViewFrame; +*/ + return pViewFrame; +} + +//-------------------------------------------------------------------- +SfxViewFrame* SfxViewFrame::LoadViewIntoFrame_Impl_NoThrow( const SfxObjectShell& i_rDoc, const Reference< XFrame >& i_rFrame, + const USHORT 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 ); + 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 USHORT 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" ) ); + + Reference< XComponentLoader > xLoader( i_rFrame, UNO_QUERY_THROW ); + xLoader->loadComponentFromURL( sURL, ::rtl::OUString::createFromAscii( "_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 USHORT i_nViewId ) +{ + return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, Reference< XFrame >(), i_nViewId, true ); +} + +//-------------------------------------------------------------------- + +SfxViewFrame* SfxViewFrame::LoadDocument( SfxObjectShell& i_rDoc, const USHORT 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 USHORT i_nViewId ) +{ + return LoadViewIntoFrame_Impl_NoThrow( i_rDoc, i_rTargetFrame, i_nViewId, false ); +} + +//-------------------------------------------------------------------- + +SfxViewFrame* SfxViewFrame::LoadDocumentIntoFrame( SfxObjectShell& i_rDoc, const SfxFrameItem* i_pFrameItem, const USHORT 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 USHORT i_nViewId ) +{ + SFX_REQUEST_ARG( i_rCreateDocRequest, pFrameItem, SfxUnoFrameItem, SID_FILLFRAME, FALSE ); + SFX_REQUEST_ARG( i_rCreateDocRequest, pHiddenItem, SfxBoolItem, SID_HIDDEN, 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, FALSE ); + pViewFrame; + pViewFrame = SfxViewFrame::GetNext( *pViewFrame, pDoc, FALSE ) + ) + { + if ( pViewFrame->GetViewShell()->GetController() == i_rController ) + break; + } + + return pViewFrame; +} + +//-------------------------------------------------------------------- + +sal_Bool SfxViewFrame::SwitchToViewShell_Impl +( + sal_uInt16 nViewIdOrNo, /* > 0 + Registrierungs-Id der View, auf die umge- + schaltet werden soll, bzw. die erstmalig + erzeugt werden soll. + + == 0 + Es soll die Default-View verwendet werden. */ + + sal_Bool bIsIndex /* sal_True + 'nViewIdOrNo' ist keine Registrations-Id sondern + ein Index in die f"ur die in diesem + <SfxViewFrame> dargestellte <SfxObjectShell>. + */ +) + +/* [Beschreibung] + + Interne Methode zum Umschalten auf eine andere <SfxViewShell>-Subklasse, + die in diesem SfxMDIFrame erzeugt werden soll. Existiert noch + keine SfxViewShell in diesem SfxMDIFrame, so wird erstmalig eine + erzeugt. + + + [R"uckgabewert] + + sal_Bool sal_True + die angeforderte SfxViewShell wurde erzeugt + und eine ggf. bestehende gel"oscht + + sal_False + die angeforderte SfxViewShell konnte nicht + erzeugt werden, die bestehende SfxViewShell + existiert daher weiterhin +*/ + +{ + 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( 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 USHORT nViewId = ( bIsIndex || !nViewIdOrNo ) ? rDocFact.GetViewFactory( nViewIdOrNo ).GetOrdinal() : nViewIdOrNo; + + // 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 USHORT i_nID ) +{ + pImp->nCurViewId = i_nID; +} + +//------------------------------------------------------------------------- +sal_uInt16 SfxViewFrame::GetCurViewId() const +{ + return pImp->nCurViewId; +} + +//------------------------------------------------------------------------- +void SfxViewFrame::ExecView_Impl +( + SfxRequest& rReq // der auszuf"uhrende <SfxRequest> +) + +/* [Beschreibung] + + Interne Methode zum Ausf"uhren der f"ur die <SfxShell> Subklasse + SfxViewFrame in der <SVIDL> beschriebenen Slots. +*/ + +{ + DBG_CHKTHIS(SfxViewFrame, 0); + + // Wenn gerade die Shells ausgetauscht werden... + 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(); + 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; + BOOL bSuccess = SwitchToViewShell_Impl( nViewNo, sal_True ); + rReq.SetReturnValue( SfxBoolItem( 0, bSuccess ) ); + break; + } + + case SID_NEWWINDOW: + { + // Hack. demnaechst virtuelle Funktion + if ( !GetViewShell()->NewWindowAllowed() ) + { + OSL_ENSURE( false, "You should have disabled the 'Window/New Window' slot!" ); + return; + } + + // ViewData bei FrameSets rekursiv holen + 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 USHORT 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::OUString::createFromAscii("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::createFromAscii("org.openoffice.Office.Common/"), + ::rtl::OUString::createFromAscii("Misc"), + ::rtl::OUString::createFromAscii("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().equalsAscii("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 /* leeres <SfxItemSet> mit <Which-Ranges>, + welche die Ids der zu erfragenden + Slots beschreiben. */ +) + +/* [Beschreibung] + + Diese interne Methode liefert in 'rSet' die Status der f"ur die + <SfxShell> Subklasse SfxViewFrame in der <SVIDL> beschriebenen <Slots>. + + In 'rSet' sind dabei genau die vom SFx als ung"ultig erkannten + Slot-Ids als Which-ranges enthalten. Falls der an dieser Shell gesetzte + <SfxItemPool> f"ur einzelne Slot-Ids ein Mapping hat, werden die + entsprechenden Which-Ids verwendet, so da\s Items ggf. direkt mit + einer mit Which-Ids arbeitenden Core-::com::sun::star::script::Engine ausgetauscht werden + k"onnen. +*/ + +{ + DBG_CHKTHIS(SfxViewFrame, 0); + + SfxObjectShell *pDocSh = GetObjectShell(); + + if ( !pDocSh ) + // Ich bin gerade am Reloaden und Yielde so vor mich hin ... + return; + + const sal_uInt16 *pRanges = rSet.GetRanges(); + DBG_ASSERT(pRanges, "Set ohne Bereich"); + 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 +/* + Beschreibung: + Der ParentViewFrame ist der ViewFrame des ParentFrames +*/ +{ + SfxFrame *pFrame = GetFrame().GetParentFrame(); + return pFrame ? pFrame->GetCurrentViewFrame() : NULL; +} + +//------------------------------------------------------------------------- +SfxFrame& SfxViewFrame::GetFrame() const +/* + Beschreibung: + GetFrame liefert den Frame, in dem sich der ViewFrame befindet +*/ +{ + 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 ); + } +} + +BOOL SfxViewFrame::IsInModalMode() const +{ + return pImp->bModal || GetFrame().GetWindow().IsInModalMode(); +} + +void SfxViewFrame::Resize( 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, BOOL bEraseTrailingEmptyLines ) +{ + sal_Int32 nStartPos = 0; + sal_Int32 nEndPos = 0; + sal_Int32 nLine = 0; + while ( nLine < nStartLine ) + { + nStartPos = rStr.indexOf( LINE_SEP, nStartPos ); + if( nStartPos == -1 ) + break; + nStartPos++; // nicht das \n. + nLine++; + } + + DBG_ASSERTWARNING( nStartPos != STRING_NOTFOUND, "CutLines: Startzeile nicht gefunden!" ); + + if ( nStartPos != -1 ) + { + nEndPos = nStartPos; + for ( sal_Int32 i = 0; i < nLines; i++ ) + nEndPos = rStr.indexOf( LINE_SEP, nEndPos+1 ); + + if ( nEndPos == -1 ) // kann bei letzter Zeile passieren + 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 ) +{ + /* + // get lib and modul name from dialog + SfxModule *pMod = GetObjectShell()->GetModule(); + SfxRequest aReq( SID_BASICCHOOSER, SFX_CALLMODE_SYNCHRON, pMod->GetPool() ); + const SfxPoolItem* pRet = pMod->ExecuteSlot( aReq ); + if ( pRet ) + ::rtl::OUString = ((SfxStringItem*)pRet)->GetValue(); + */ + if ( !sMacro.getLength() ) + return; + + SfxApplication* pSfxApp = SFX_APP(); + SfxRequest aReq( SID_BASICCHOOSER, SFX_CALLMODE_SYNCHRON, pSfxApp->GetPool() ); + aReq.AppendItem( SfxBoolItem(SID_RECORDMACRO,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::createFromAscii( "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::OUString::createFromAscii( "location" ); + if ( xUrl->hasParameter( aLocKey ) ) + aLocation = xUrl->getParameter( aLocKey ); + } + } + + pSfxApp->EnterBasicCall(); + + 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(); + USHORT nStart, nEnd; + pMethod->GetLineRange( nStart, nEnd ); + ULONG nlStart = nStart; + ULONG nlEnd = nEnd; + CutLines( aOUSource, nlStart-1, nlEnd-nlStart+1, 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 ); + BOOL bReplace = 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 = 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 ); + } + } + } + + pSfxApp->LeaveBasicCall(); + } + else + { + // add code for "session only" macro + } + + /* + FILE* pFile = fopen( "macro.bas", "a" ); + fprintf( pFile, "%s", ::rtl::OUStringToOString(sBuffer.makeStringAndClear(),RTL_TEXTENCODING_UTF8).getStr() ); + fclose ( pFile ); + */ +} + +void SfxViewFrame::MiscExec_Impl( SfxRequest& rReq ) +{ + DBG_MEMTEST(); + FASTBOOL bDone = FALSE; + switch ( rReq.GetSlot() ) + { + case SID_STOP_RECORDING : + case SID_RECORDMACRO : + { + // try to find any active recorder on this frame + ::rtl::OUString sProperty = rtl::OUString::createFromAscii("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(); + + 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, 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::createFromAscii("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::createFromAscii("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, 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" )); + // Parameter auswerten + SFX_REQUEST_ARG(rReq, pShowItem, SfxBoolItem, rReq.GetSlot(), FALSE); + BOOL bShow( 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(), 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& ) + { + } + } + + 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( TRUE ); + break; + } + } + + if ( bDone ) + rReq.Done(); +} + +void SfxViewFrame::MiscState_Impl(SfxItemSet &rSet) +{ + DBG_MEMTEST(); + + const USHORT *pRanges = rSet.GetRanges(); + DBG_ASSERT(pRanges && *pRanges, "Set ohne Bereich"); + while ( *pRanges ) + { + for(USHORT nWhich = *pRanges++; nWhich <= *pRanges; ++nWhich) + { + switch(nWhich) + { + case SID_CURRENT_URL: + { + // Bei internem InPlace den ContainerFrame nehmen + SfxViewFrame *pFrame = this; + if ( pFrame->GetParentViewFrame_Impl() ) + pFrame = pFrame->GetParentViewFrame_Impl(); + rSet.Put( SfxStringItem( nWhich, pFrame->GetActualPresentationURL_Impl() ) ); + break; + } + + case SID_RECORDMACRO : + { + const char* pName = GetObjectShell()->GetFactory().GetShortName(); + if ( strcmp(pName,"swriter") && strcmp(pName,"scalc") ) + { + rSet.DisableItem( nWhich ); + break; + } + + ::rtl::OUString sProperty = rtl::OUString::createFromAscii("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 : + { + const char* pName = GetObjectShell()->GetFactory().GetShortName(); + if ( strcmp(pName,"swriter") && strcmp(pName,"scalc") ) + { + rSet.DisableItem( nWhich ); + break; + } + + ::rtl::OUString sProperty = rtl::OUString::createFromAscii("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, FALSE )); + else + { + rtl::OUString aStatusbarResString( RTL_CONSTASCII_USTRINGPARAM( "private:resource/statusbar/statusbar" )); + 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 : + { + DBG_ERROR("Outdated slot!"); + rSet.DisableItem( nWhich ); + break; + } + + default: + //! DBG_ASSERT(FALSE, "Falscher Server fuer GetState"); + break; + } + } + + ++pRanges; + } +} + +void SfxViewFrame::ChildWindowExecute( SfxRequest &rReq ) + +/* [Beschreibung] + + Diese Methode kann in der Execute-Methode f"ur das ein- und ausschalten + von Child-Windows eingesetzt werden, um dieses inkl. API-Anbindung zu + implementieren. + + Einfach in der IDL als 'ExecuteMethod' eintragen. +*/ + +{ + // Parameter auswerten + USHORT nSID = rReq.GetSlot(); + + SFX_REQUEST_ARG(rReq, pShowItem, SfxBoolItem, nSID, 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 ) ); + BOOL bShow = FALSE; + 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, FALSE ); + } + else + { + ::com::sun::star::util::URL aTargetURL; + aTargetURL.Complete = ::rtl::OUString::createFromAscii(".component:DB/DataSourceBrowser"); + Reference < ::com::sun::star::util::XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii("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::createFromAscii("_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::createFromAscii("Referer"); + pArg[0].Value <<= ::rtl::OUString::createFromAscii("private:user"); + xDisp->dispatch( aTargetURL, aArgs ); + } + } + + rReq.Done(); + return; + } + + BOOL bShow = FALSE; + BOOL bHasChild = HasChildWindow(nSID); + bShow = pShowItem ? pShowItem->GetValue() : !bHasChild; + + // ausf"uhren + if ( !pShowItem || bShow != bHasChild ) + ToggleChildWindow( nSID ); + + GetBindings().Invalidate( nSID ); + GetDispatcher()->Update_Impl( TRUE ); + + // ggf. recorden + if ( nSID == SID_HYPERLINK_DIALOG || nSID == SID_SEARCH_DLG ) + { + rReq.Ignore(); + } + else + { + rReq.AppendItem( SfxBoolItem( nSID, bShow ) ); + rReq.Done(); + } +} + +//-------------------------------------------------------------------- + +void SfxViewFrame::ChildWindowState( SfxItemSet& rState ) + +/* [Beschreibung] + + Diese Methode kann in der Status-Methode f"ur das Ein- und Ausschalt- + Zustand von Child-Windows eingesetzt werden, um dieses zu implementieren. + + Einfach in der IDL als 'StateMethod' eintragen. +*/ + +{ + SfxWhichIter aIter( rState ); + for ( USHORT 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_ENSURE( false, "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( USHORT /*nId*/ ) +{ + SfxWorkWindow* pWork = 0; + pWork = GetFrame().GetWorkWindow_Impl(); + return pWork; +} + +/* +void SfxViewFrame::SetChildWindow(USHORT nId, BOOL bOn) +{ + SetChildWindow( nId, bOn, TRUE ); +}*/ + +void SfxViewFrame::SetChildWindow(USHORT nId, BOOL bOn, BOOL bSetFocus ) +{ + SfxWorkWindow* pWork = GetWorkWindow_Impl( nId ); + if ( pWork ) + pWork->SetChildWindow_Impl( nId, bOn, bSetFocus ); +} + +//-------------------------------------------------------------------- + +void SfxViewFrame::ToggleChildWindow(USHORT nId) +{ + SfxWorkWindow* pWork = GetWorkWindow_Impl( nId ); + if ( pWork ) + pWork->ToggleChildWindow_Impl( nId, TRUE ); +} + +//-------------------------------------------------------------------- + +BOOL SfxViewFrame::HasChildWindow( USHORT nId ) +{ + SfxWorkWindow* pWork = GetWorkWindow_Impl( nId ); + return pWork ? pWork->HasChildWindow_Impl(nId) : FALSE; +} + +//-------------------------------------------------------------------- + +BOOL SfxViewFrame::KnowsChildWindow( USHORT nId ) +{ + SfxWorkWindow* pWork = GetWorkWindow_Impl( nId ); + return pWork ? pWork->KnowsChildWindow_Impl(nId) : FALSE; +} + +//-------------------------------------------------------------------- + +void SfxViewFrame::ShowChildWindow( USHORT nId, BOOL bVisible ) +{ + SfxWorkWindow* pWork = GetWorkWindow_Impl( nId ); + if ( pWork ) + { + GetDispatcher()->Update_Impl(sal_True); + pWork->ShowChildWindow_Impl(nId, bVisible, TRUE ); + } +} + +//-------------------------------------------------------------------- + +SfxChildWindow* SfxViewFrame::GetChildWindow(USHORT 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 ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // 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 ); +} diff --git a/sfx2/source/view/viewfrm2.cxx b/sfx2/source/view/viewfrm2.cxx new file mode 100644 index 000000000000..480b5307df2e --- /dev/null +++ b/sfx2/source/view/viewfrm2.cxx @@ -0,0 +1,523 @@ +/************************************************************************* + * + * 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 "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::createFromAscii("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.equalsAscii("title")) && + (sMaterial[i].Value >>= aTabString)) + { + result += ' '; + result += String(aTabString); + } + } + } + } + return result; +} + +//======================================================================== + +//-------------------------------------------------------------------- +String SfxViewFrame::UpdateTitle() + +/* [Beschreibung] + + Mit dieser Methode kann der SfxViewFrame gezwungen werden, sich sofort + den neuen Titel vom der <SfxObjectShell> zu besorgen. + + [Anmerkung] + + Dies ist z.B. dann notwendig, wenn man der SfxObjectShell als SfxListener + zuh"ort und dort auf den <SfxSimpleHint> SFX_HINT_TITLECHANGED reagieren + m"ochte, um dann die Titel seiner Views abzufragen. Diese Views (SfxTopViewFrames) + jedoch sind ebenfalls SfxListener und da die Reihenfolge der Benachrichtigung + nicht feststeht, mu\s deren Titel-Update vorab erzwungen werden. + + + [Beispiel] + + 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(); + +// if ( pObjSh->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED ) +// // kein UpdateTitle mit Embedded-ObjectShell +// 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 hat sich ge"andert + pImp->aActualURL = aURL; + + // gibt es noch eine weitere 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++; + + // Titel des Fensters + String aTitle; + if ( nViews == 2 || pImp->nDocViewNo > 1 ) + // dann die Nummer dranh"angen + aTitle = pObjSh->UpdateTitle( NULL, pImp->nDocViewNo ); + else + aTitle = pObjSh->UpdateTitle(); + + // Name des SbxObjects + 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 ); + + /* AS_TITLE + Window* pWindow = GetFrame()->GetTopWindow_Impl(); + if ( pWindow && pWindow->GetText() != aTitle ) + pWindow->SetText( aTitle ); + */ + return aTitle; +} + +void SfxViewFrame::Exec_Impl(SfxRequest &rReq ) +{ + // Wenn gerade die Shells ausgetauscht werden... + if ( !GetObjectShell() || !GetViewShell() ) + return; + + switch ( rReq.GetSlot() ) + { + case SID_SHOWPOPUPS : + { + SFX_REQUEST_ARG(rReq, pShowItem, SfxBoolItem, SID_SHOWPOPUPS, FALSE); + BOOL bShow = pShowItem ? pShowItem->GetValue() : TRUE; + SFX_REQUEST_ARG(rReq, pIdItem, SfxUInt16Item, SID_CONFIGITEMID, FALSE); + USHORT nId = pIdItem ? pIdItem->GetValue() : 0; + + // ausfuehren + SfxWorkWindow *pWorkWin = GetFrame().GetWorkWindow_Impl(); + if ( bShow ) + { + // Zuerst die Floats auch anzeigbar machen + pWorkWin->MakeChildsVisible_Impl( bShow ); + GetDispatcher()->Update_Impl( TRUE ); + + // Dann anzeigen + GetBindings().HidePopups( !bShow ); + } + else + { + // Alles hiden + SfxBindings *pBind = &GetBindings(); + while ( pBind ) + { + pBind->HidePopupCtrls_Impl( !bShow ); + pBind = pBind->GetSubBindings_Impl(); + } + + pWorkWin->HidePopups_Impl( !bShow, TRUE, nId ); + pWorkWin->MakeChildsVisible_Impl( bShow ); + } + + Invalidate( rReq.GetSlot() ); + rReq.Done(); + break; + } + + case SID_ACTIVATE: + { + MakeActive_Impl( TRUE ); + rReq.SetReturnValue( SfxObjectItem( 0, this ) ); + break; + } + + case SID_NEWDOCDIRECT : + { + SFX_REQUEST_ARG( rReq, pFactoryItem, SfxStringItem, SID_NEWDOCDIRECT, FALSE); + String aFactName; + if ( pFactoryItem ) + aFactName = pFactoryItem->GetValue(); + else if ( pImp->aFactoryName.Len() ) + aFactName = pImp->aFactoryName; + else + { + DBG_ERROR("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() ) + { + // weitere Views auf dasselbe Doc? + SfxObjectShell *pDocSh = GetObjectShell(); + int bOther = sal_False; + for ( const SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDocSh ); + !bOther && pFrame; + pFrame = SfxViewFrame::GetNext( *pFrame, pDocSh ) ) + bOther = (pFrame != this); + + // Doc braucht nur gefragt zu werden, wenn keine weitere View + sal_Bool bClosed = sal_False; + sal_Bool bUI = TRUE; + if ( ( bOther || pDocSh->PrepareClose( bUI ) ) ) + { + if ( !bOther ) + pDocSh->SetModified( FALSE ); + rReq.Done(); // unbedingt vor Close() rufen! + 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 ohne Bereich"); + 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( USHORT( SID_OBJECT ), aAny ) ); + } + else + rSet.DisableItem( SID_OBJECT ); + break; + + default: + DBG_ERROR( "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_ENSURE( false, "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 bei BASIC-IDE, QUERY-EDITOR etc. disablen + 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(), "Keine Shell"); + if ( bMDI ) + pImp->bActive = sal_True; +//(mba): hier evtl. wie in Beanframe NotifyEvent ?! +} + +void SfxViewFrame::Deactivate( sal_Bool bMDI ) +{ + DBG_ASSERT(GetViewShell(), "Keine Shell"); + if ( bMDI ) + pImp->bActive = sal_False; +//(mba): hier evtl. wie in Beanframe NotifyEvent ?! +} diff --git a/sfx2/source/view/viewimp.hxx b/sfx2/source/view/viewimp.hxx new file mode 100644 index 000000000000..1c9e219cf180 --- /dev/null +++ b/sfx2/source/view/viewimp.hxx @@ -0,0 +1,84 @@ +/************************************************************************* + * + * 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 _VIEWIMP_HXX +#define _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 bControllerSet; + SfxShellArr_Impl aArr; + SvBorder aBorder; + Size aOptimalSize; + Size aMargin; + USHORT nPrinterLocks; + BOOL bCanPrint; + BOOL bHasPrintOptions; + BOOL bPlugInsActive; + BOOL bIsShowView; + BOOL bOwnsMenu; + BOOL bGotOwnerShip; + BOOL bGotFrameOwnerShip; + SfxScrollingMode eScroll; + USHORT nFamily; + SfxBaseController* pController; + ::svt::AcceleratorExecute* pAccExec; + com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue > aPrintOpts; + ::rtl::Reference< SfxClipboardChangeListener > xClipboardListener; + vcl::PrinterController* pPrinterController; + + SfxViewShell_Impl(); +}; + +#endif + diff --git a/sfx2/source/view/viewprn.cxx b/sfx2/source/view/viewprn.cxx new file mode 100644 index 000000000000..f62ae4c1ddc7 --- /dev/null +++ b/sfx2/source/view/viewprn.cxx @@ -0,0 +1,1034 @@ +/************************************************************************* + * + * 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/printdlg.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 "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; + util::DateTime m_aLastPrinted; + ::rtl::OUString m_aLastPrintedBy; + + Sequence< beans::PropertyValue > getMergedOptions() const; + const Any& getSelectionObject() const; +public: + SfxPrinterController( 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 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 + ) + : 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) +{ + 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; + Sequence< beans::PropertyValue > aRenderParms( mxRenderable->getRenderer( 0 , getSelectionObject(), aRenderOptions ) ); + int nProps = aRenderParms.getLength(); + for( int i = 0; i < nProps; i++ ) + { + if( aRenderParms[i].Name.equalsAscii( "ExtraPrintUIOptions" ) ) + { + Sequence< beans::PropertyValue > aUIProps; + aRenderParms[i].Value >>= aUIProps; + setUIOptions( aUIProps ); + break; + } + } + } + + // 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 +{ + sal_Int32 nChoice = 0; + sal_Bool bSel = sal_False; + const beans::PropertyValue* pVal = getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintContent" ) ) ); + if( pVal ) + pVal->Value >>= nChoice; + pVal = getValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintSelectionOnly" ) ) ); + if( pVal ) + pVal->Value >>= bSel; + return (nChoice > 1 || bSel) ? 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() ); + aResult = mxRenderable->getRenderer( i_nPage, getSelectionObject(), aJobOptions ); + } + 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 ) + { + 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 ); + break; + } + + default: + break; + } + + if ( m_bNeedsChange ) + mpObjectShell->EnableSetModified( m_bOrigStatus ); + + if ( mpViewShell ) + mpViewShell->pImp->pPrinterController = 0; + } +} + +// ----------------------------------------------------------------------- + +void DisableRanges( PrintDialog& rDlg, SfxPrinter* pPrinter ) + +/* [Beschreibung] + + Mit dieser Funktion werden die nicht verf"ugbaren Ranges + vom Printer zum PrintDialog geforwarded. +*/ + +{ + if ( !pPrinter ) + return; + + if ( !pPrinter->IsRangeEnabled( PRINTDIALOG_ALL ) ) + rDlg.DisableRange( PRINTDIALOG_ALL ); + if ( !pPrinter->IsRangeEnabled( PRINTDIALOG_SELECTION ) ) + rDlg.DisableRange( PRINTDIALOG_SELECTION ); + if ( !pPrinter->IsRangeEnabled( PRINTDIALOG_FROMTO ) ) + rDlg.DisableRange( PRINTDIALOG_FROMTO ); + if ( !pPrinter->IsRangeEnabled( PRINTDIALOG_RANGE ) ) + rDlg.DisableRange( PRINTDIALOG_RANGE ); +} + +//==================================================================== + +class SfxDialogExecutor_Impl + +/* [Beschreibung] + + Eine Instanz dieser Klasse wird f"ur die Laufzeit des Printer-Dialogs + erzeugt, um im dessen Click-Handler f"ur die Zus"atze den per + virtueller Methode von der abgeleiteten SfxViewShell erzeugten + Print-Options-Dialog zu erzeugen und die dort eingestellten Optionen + als SfxItemSet zu zwischenzuspeichern. +*/ + +{ +private: + SfxViewShell* _pViewSh; + PrintDialog* _pPrintParent; + PrinterSetupDialog* _pSetupParent; + SfxItemSet* _pOptions; + sal_Bool _bModified; + sal_Bool _bHelpDisabled; + + DECL_LINK( Execute, void * ); + +public: + SfxDialogExecutor_Impl( SfxViewShell* pViewSh, PrintDialog* pParent ); + 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, PrintDialog* pParent ) : + + _pViewSh ( pViewSh ), + _pPrintParent ( pParent ), + _pSetupParent ( NULL ), + _pOptions ( NULL ), + _bModified ( sal_False ), + _bHelpDisabled ( sal_False ) + +{ +} + +SfxDialogExecutor_Impl::SfxDialogExecutor_Impl( SfxViewShell* pViewSh, PrinterSetupDialog* pParent ) : + + _pViewSh ( pViewSh ), + _pPrintParent ( NULL ), + _pSetupParent ( pParent ), + _pOptions ( NULL ), + _bModified ( sal_False ), + _bHelpDisabled ( sal_False ) + +{ +} + +//-------------------------------------------------------------------- + +IMPL_LINK( SfxDialogExecutor_Impl, Execute, void *, EMPTYARG ) +{ + // Options lokal merken + if ( !_pOptions ) + { + DBG_ASSERT( _pPrintParent || _pSetupParent, "no dialog parent" ); + if( _pPrintParent ) + _pOptions = ( (SfxPrinter*)_pPrintParent->GetPrinter() )->GetOptions().Clone(); + else if( _pSetupParent ) + _pOptions = ( (SfxPrinter*)_pSetupParent->GetPrinter() )->GetOptions().Clone(); + } + + if ( _pOptions && _pPrintParent && _pPrintParent->IsSheetRangeAvailable() ) + { + SfxItemState eState = _pOptions->GetItemState( SID_PRINT_SELECTEDSHEET ); + if ( eState != SFX_ITEM_UNKNOWN ) + { + PrintSheetRange eRange = _pPrintParent->GetCheckedSheetRange(); + BOOL bValue = ( PRINTSHEETS_ALL != eRange ); + _pOptions->Put( SfxBoolItem( SID_PRINT_SELECTEDSHEET, bValue ) ); + } + } + + // Dialog ausf"uhren + SfxPrintOptionsDialog* pDlg = new SfxPrintOptionsDialog( _pPrintParent ? static_cast<Window*>(_pPrintParent) + : static_cast<Window*>(_pSetupParent), + _pViewSh, _pOptions ); + if ( _bHelpDisabled ) + pDlg->DisableHelp(); + if ( pDlg->Execute() == RET_OK ) + { + delete _pOptions; + _pOptions = pDlg->GetOptions().Clone(); + + if ( _pOptions && _pPrintParent && _pPrintParent->IsSheetRangeAvailable() ) + { + const SfxPoolItem* pItem; + if ( SFX_ITEM_SET == _pOptions->GetItemState( SID_PRINT_SELECTEDSHEET, FALSE , &pItem ) ) + { + _pPrintParent->CheckSheetRange( ( (const SfxBoolItem*)pItem )->GetValue() + ? PRINTSHEETS_SELECTED_SHEETS : PRINTSHEETS_ALL ); + } + } + } + delete pDlg; + + return 0; +} + +//------------------------------------------------------------------------- + +BOOL UseStandardPrinter_Impl( Window* /*pParent*/, SfxPrinter* pDocPrinter ) +{ + // Optionen abfragen, ob gewarnt werden soll (Doc uebersteuert App) + BOOL bWarn = FALSE; + const SfxItemSet *pDocOptions = &pDocPrinter->GetOptions(); + if ( pDocOptions ) + { + USHORT nWhich = pDocOptions->GetPool()->GetWhich(SID_PRINTER_NOTFOUND_WARN); + const SfxBoolItem* pBoolItem = NULL; + pDocPrinter->GetOptions().GetItemState( nWhich, FALSE, (const SfxPoolItem**) &pBoolItem ); + if ( pBoolItem ) + bWarn = pBoolItem->GetValue(); + } +/* + // ggf. den User fragen + if ( bWarn ) + { + // Geht nicht mehr ohne OrigJobSetup! + String aTmp( SfxResId( STR_PRINTER_NOTAVAIL ) ); + QueryBox aBox( pParent, WB_OK_CANCEL | WB_DEF_OK, aTmp ); + return RET_OK == aBox.Execute(); + } +*/ + // nicht gewarnt => einfach so den StandardDrucker nehmen + return TRUE; +} +//------------------------------------------------------------------------- + +SfxPrinter* SfxViewShell::SetPrinter_Impl( SfxPrinter *pNewPrinter ) + +/* Interne Methode zum Setzen der Unterschiede von 'pNewPrinter' zum + aktuellen Printer. pNewPrinter wird entweder "ubernommen oder gel"oscht. +*/ + +{ + // aktuellen Printer holen + SfxPrinter *pDocPrinter = GetPrinter(); + + // Printer-Options auswerten + FASTBOOL bOriToDoc = FALSE; + FASTBOOL bSizeToDoc = FALSE; + if ( &pDocPrinter->GetOptions() ) + { + USHORT nWhich = GetPool().GetWhich(SID_PRINTER_CHANGESTODOC); + const SfxFlagItem *pFlagItem = 0; + pDocPrinter->GetOptions().GetItemState( nWhich, FALSE, (const SfxPoolItem**) &pFlagItem ); + bOriToDoc = pFlagItem ? (pFlagItem->GetValue() & SFX_PRINTER_CHG_ORIENTATION) : FALSE; + bSizeToDoc = pFlagItem ? (pFlagItem->GetValue() & SFX_PRINTER_CHG_SIZE) : FALSE; + } + + // vorheriges Format und Size feststellen + Orientation eOldOri = pDocPrinter->GetOrientation(); + Size aOldPgSz = pDocPrinter->GetPaperSizePixel(); + + // neues Format und Size feststellen + Orientation eNewOri = pNewPrinter->GetOrientation(); + Size aNewPgSz = pNewPrinter->GetPaperSizePixel(); + + // "Anderungen am Seitenformat feststellen + BOOL bOriChg = (eOldOri != eNewOri) && bOriToDoc; + BOOL bPgSzChg = ( aOldPgSz.Height() != + ( bOriChg ? aNewPgSz.Width() : aNewPgSz.Height() ) || + aOldPgSz.Width() != + ( bOriChg ? aNewPgSz.Height() : aNewPgSz.Width() ) ) && + bSizeToDoc; + + // Message und Flags f"ur Seitenformat-"Anderung zusammenstellen + String aMsg; + USHORT 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; + } + + // in dieser Variable sammeln, was sich so ge"aendert hat + USHORT nChangedFlags = 0; + + // ggf. Nachfrage, ob Seitenformat vom Drucker "ubernommen werden soll + if ( ( bOriChg || bPgSzChg ) && + RET_YES == QueryBox(0, WB_YES_NO | WB_DEF_OK, aMsg).Execute() ) + // Flags mit "Anderungen f"ur <SetPrinter(SfxPrinter*)> mitpflegen + nChangedFlags |= nNewOpt; + + // fuer den MAC sein "temporary of class String" im naechsten if() + String aTempPrtName = pNewPrinter->GetName(); + String aDocPrtName = pDocPrinter->GetName(); + + // Wurde der Drucker gewechselt oder von Default auf Specific + // oder umgekehrt geaendert? + if ( (aTempPrtName != aDocPrtName) || (pDocPrinter->IsDefPrinter() != pNewPrinter->IsDefPrinter()) ) + { + // neuen Printer "ubernehmen + // pNewPrinter->SetOrigJobSetup( pNewPrinter->GetJobSetup() ); + nChangedFlags |= SFX_PRINTER_PRINTER|SFX_PRINTER_JOBSETUP; + pDocPrinter = pNewPrinter; + } + else + { + // Extra-Optionen vergleichen + if ( ! (pNewPrinter->GetOptions() == pDocPrinter->GetOptions()) ) + { + // Options haben sich geaendert + pDocPrinter->SetOptions( pNewPrinter->GetOptions() ); + nChangedFlags |= SFX_PRINTER_OPTIONS; + } + + // JobSetups vergleichen + JobSetup aNewJobSetup = pNewPrinter->GetJobSetup(); + JobSetup aOldJobSetup = pDocPrinter->GetJobSetup(); + if ( aNewJobSetup != aOldJobSetup ) + { + // JobSetup hat sich geaendert (=> App mu\s neu formatieren) + // pDocPrinter->SetOrigJobSetup( aNewJobSetup ); + nChangedFlags |= SFX_PRINTER_JOBSETUP; + } + + // alten, ver"anderten Printer behalten + pDocPrinter->SetPrinterProps( pNewPrinter ); + delete pNewPrinter; + } + + if ( 0 != nChangedFlags ) + // SetPrinter will delete the old printer if it changes + SetPrinter( pDocPrinter, nChangedFlags ); + return pDocPrinter; +} + +//------------------------------------------------------------------------- +// Unter WIN32 tritt leider das Problem auf, dass nichts gedruckt +// wird, wenn SID_PRINTDOCDIRECT auflaueft; bisher bekannte, +// einzige Abhilfe ist in diesem Fall das Abschalten der Optimierungen +// (KA 17.12.95) +#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<vcl::PrinterController> pController( new SfxPrinterController( aComplete, + aSelection, + aViewProp, + GetRenderable(), + bIsAPI, + bIsDirect, + this, + rProps + ) ); + pImp->pPrinterController = pController.get(); + + SfxObjectShell *pObjShell = GetObjectShell(); + pController->setValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "JobName" ) ), + makeAny( rtl::OUString( pObjShell->GetTitle(0) ) ) ); + + // FIXME: job setup + SfxPrinter* pDocPrt = GetPrinter(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->pPrinterController ? pImp->pPrinterController->getPrinter().get() : 0; +} + +void SfxViewShell::ExecPrint_Impl( SfxRequest &rReq ) +{ + // USHORT nCopies=1; + USHORT nDialogRet = RET_CANCEL; + // BOOL bCollate=FALSE; + SfxPrinter* pPrinter = 0; + PrintDialog* pPrintDlg = 0; + SfxDialogExecutor_Impl* pExecutor = 0; + bool bSilent = false; + BOOL bIsAPI = rReq.GetArgs() && rReq.GetArgs()->Count(); + if ( bIsAPI ) + { + SFX_REQUEST_ARG(rReq, pSilentItem, SfxBoolItem, SID_SILENT, 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 USHORT nId = rReq.GetSlot(); + switch( nId ) + { + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + case SID_PRINTDOC: + case SID_PRINTDOCDIRECT: + { + SfxObjectShell* pDoc = GetObjectShell(); + bool bDetectHidden = ( !bSilent && pDoc ); + if ( bDetectHidden && pDoc->QueryHiddenInformation( WhenPrinting, NULL ) != RET_YES ) + break; + + SFX_REQUEST_ARG(rReq, pSelectItem, SfxBoolItem, SID_SELECTION, FALSE); + sal_Bool bSelection = pSelectItem && pSelectItem->GetValue(); + if( pSelectItem && rReq.GetArgs()->Count() == 1 ) + bIsAPI = 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.equalsAscii("Copies") ) + aProps[nProp]. Name = rtl::OUString::createFromAscii("CopyCount"); + else if ( aProps[nProp].Name.equalsAscii("RangeText") ) + aProps[nProp]. Name = rtl::OUString::createFromAscii("Pages"); + if ( aProps[nProp].Name.equalsAscii("Asynchron") ) + { + aProps[nProp]. Name = rtl::OUString::createFromAscii("Wait"); + sal_Bool bAsynchron = sal_False; + aProps[nProp].Value >>= bAsynchron; + aProps[nProp].Value <<= (sal_Bool) (!bAsynchron); + } + if ( aProps[nProp].Name.equalsAscii("Silent") ) + { + aProps[nProp]. Name = rtl::OUString::createFromAscii("MonitorVisible"); + sal_Bool bPrintSilent = sal_False; + aProps[nProp].Value >>= bPrintSilent; + aProps[nProp].Value <<= (sal_Bool) (!bPrintSilent); + } + } + } + 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(TRUE); + + // look for printer in parameters + SFX_REQUEST_ARG( rReq, pPrinterItem, SfxStringItem, SID_PRINTER_NAME, 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,FALSE)); + break; + } + else + ErrorBox( NULL, WB_OK | WB_DEF_OK, String( SfxResId( STR_NODEFPRINTER ) ) ).Execute(); + } + + if ( !pPrinter->IsOriginal() && rReq.GetArgs() && !UseStandardPrinter_Impl( NULL, pPrinter ) ) + { + // printer is not available, but standard printer should not be used + rReq.SetReturnValue(SfxBoolItem(0,FALSE)); + break; + } + + // 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,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->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(); + } + + // take the changes made in the dialog + pPrinter = SetPrinter_Impl( pDlgPrinter ); + + // forget new printer, it was taken over (as pPrinter) or deleted + pDlgPrinter = NULL; + + /* Now lets reset the Dialog printer, since its freed */ + if (pPrintDlg) + pPrintDlg->SetPrinter (pPrinter); + } + else + { + // PrinterDialog is used to transfer information on printing, + // so it will only be deleted here if dialog was cancelled + DELETEZ( pDlgPrinter ); + DELETEZ( pPrintDlg ); + rReq.Ignore(); + if ( SID_PRINTDOC == nId ) + rReq.SetReturnValue(SfxBoolItem(0,FALSE)); + } + } + } + + break; + } +} + +// Optimierungen wieder einschalten +#ifdef _MSC_VER +#pragma optimize ( "", on ) +#endif + +//-------------------------------------------------------------------- + +PrintDialog* SfxViewShell::CreatePrintDialog( Window* /*pParent*/ ) + +/* [Beschreibung] + + Diese Methode kann "uberladen werden, um einen speziellen PrintDialog + zu erzeugen. Dies ist z.B. notwendig wenn spezielle <StarView> Features + wie drucken von Seitenbereichen. +*/ + +{ + #if 0 + PrintDialog *pDlg = new PrintDialog( pParent, false ); + pDlg->SetFirstPage( 1 ); + pDlg->SetLastPage( 9999 ); + pDlg->EnableCollate(); + return pDlg; + #else + return NULL; + #endif +} + +//-------------------------------------------------------------------- + +void SfxViewShell::PreparePrint( PrintDialog * ) +{ +} + +//-------------------------------------------------------------------- + + +ErrCode SfxViewShell::DoPrint( SfxPrinter* /*pPrinter*/, + PrintDialog* /*pPrintDlg*/, + BOOL /*bSilent*/, BOOL /*bIsAPI*/ ) +{ + #if 0 + // Printer-Dialogbox waehrend des Ausdrucks mu\s schon vor + // StartJob erzeugt werden, da SV bei einem Quit-Event h"angt + SfxPrintProgress *pProgress = new SfxPrintProgress( this, !bSilent ); + SfxPrinter *pDocPrinter = GetPrinter(TRUE); + if ( !pPrinter ) + pPrinter = pDocPrinter; + else if ( pDocPrinter != pPrinter ) + { + pProgress->RestoreOnEndPrint( pDocPrinter->Clone() ); + SetPrinter( pPrinter, SFX_PRINTER_PRINTER ); + } + pProgress->SetWaitMode(FALSE); + + // Drucker starten + PreparePrint( pPrintDlg ); + SfxObjectShell *pObjShell = GetViewFrame()->GetObjectShell(); + if ( pPrinter->StartJob(pObjShell->GetTitle(0)) ) + { + // Drucken + Print( *pProgress, bIsAPI, pPrintDlg ); + pProgress->Stop(); + pProgress->DeleteOnEndPrint(); + pPrinter->EndJob(); + } + else + { + // Printer konnte nicht gestartet werden + delete pProgress; + } + + return pPrinter->GetError(); + #else + DBG_ERROR( "DoPrint called, dead code !" ); + return ERRCODE_IO_NOTSUPPORTED; + #endif +} + +//-------------------------------------------------------------------- + +BOOL SfxViewShell::IsPrinterLocked() const +{ + return pImp->nPrinterLocks > 0; +} + +//-------------------------------------------------------------------- + +void SfxViewShell::LockPrinter( BOOL bLock) +{ + BOOL bChanged = FALSE; + if ( bLock ) + bChanged = 1 == ++pImp->nPrinterLocks; + else + bChanged = 0 == --pImp->nPrinterLocks; + + if ( bChanged ) + { + Invalidate( SID_PRINTDOC ); + Invalidate( SID_PRINTDOCDIRECT ); + Invalidate( SID_SETUPPRINTER ); + } +} + +//-------------------------------------------------------------------- + +USHORT SfxViewShell::Print( SfxProgress& /*rProgress*/, BOOL /*bIsAPI*/, PrintDialog* /*pDlg*/ ) +{ + return 0; +} + +//-------------------------------------------------------------------- + +SfxPrinter* SfxViewShell::GetPrinter( BOOL /*bCreate*/ ) +{ + return 0; +} + +//-------------------------------------------------------------------- + +USHORT SfxViewShell::SetPrinter( SfxPrinter* /*pNewPrinter*/, USHORT /*nDiffFlags*/, bool ) +{ + return 0; +} + +//-------------------------------------------------------------------- + +SfxTabPage* SfxViewShell::CreatePrintOptionsPage +( + Window* /*pParent*/, + const SfxItemSet& /*rOptions*/ +) +{ + return 0; +} + +JobSetup SfxViewShell::GetJobSetup() const +{ + return JobSetup(); +} + diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx new file mode 100644 index 000000000000..5c65c967434f --- /dev/null +++ b/sfx2/source/view/viewsh.cxx @@ -0,0 +1,2248 @@ +/************************************************************************* + * + * 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/XClipboardNotifier.hpp> +#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp> +#include <cppuhelper/implbase1.hxx> + +#include <osl/file.hxx> +#include <vos/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 "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/viewfrm.hxx> +#include "mailmodelapi.hxx" +#include <sfx2/event.hxx> +#include <sfx2/fcontnr.hxx> +#include <sfx2/ipclient.hxx> +#include "workwin.hxx" +#include <sfx2/objface.hxx> +#include <sfx2/docfilt.hxx> + +// #110897# +#ifndef _UNOTOOLS_PROCESSFACTORY_HXX +#include <comphelper/processfactory.hxx> +#endif + +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 > +{ + SfxViewShell* pViewShell; + + // 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 ); + +public: + SfxClipboardChangeListener( SfxViewShell* pView ); + virtual ~SfxClipboardChangeListener(); + + void DisconnectViewShell() { pViewShell = NULL; } +}; + +SfxClipboardChangeListener::SfxClipboardChangeListener( SfxViewShell* pView ) +: pViewShell( 0 ) +{ + uno::Reference < lang::XComponent > xCtrl( pView->GetController(), uno::UNO_QUERY ); + if ( xCtrl.is() ) + { + xCtrl->addEventListener( uno::Reference < lang::XEventListener > ( static_cast < lang::XEventListener* >( this ) ) ); + pViewShell = pView; + } +} + +SfxClipboardChangeListener::~SfxClipboardChangeListener() +{ +} + +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 + const ::vos::OGuard aGuard( Application::GetSolarMutex() ); + if ( pViewShell ) + { + uno::Reference < lang::XComponent > xCtrl( pViewShell->GetController(), uno::UNO_QUERY ); + if ( xCtrl.is() ) + xCtrl->removeEventListener( uno::Reference < lang::XEventListener > ( static_cast < lang::XEventListener* >( this ) ) ); + pViewShell->AddRemoveClipboardListener( uno::Reference < datatransfer::clipboard::XClipboardListener > (this), FALSE ); + pViewShell = 0; + } +} + +void SAL_CALL SfxClipboardChangeListener::changedContents( const datatransfer::clipboard::ClipboardEvent& ) + throw ( RuntimeException ) +{ + const ::vos::OGuard aGuard( Application::GetSolarMutex() ); + if( pViewShell ) + { + SfxBindings& rBind = pViewShell->GetViewFrame()->GetBindings(); + rBind.Invalidate( SID_PASTE ); + rBind.Invalidate( SID_PASTE_SPECIAL ); + rBind.Invalidate( SID_CLIPBOARD_FORMAT_ITEMS ); + } +} + + +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.equalsAscii( "Label" )) + { + aPropSeq[i].Value >>= aStr; + break; + } + } + aLabel = aStr; + } + } + catch ( css::uno::Exception& ) + { + } + + return aLabel; +} + +//========================================================================= +SfxViewShell_Impl::SfxViewShell_Impl() +: aInterceptorContainer( aMutex ) +, 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::createFromAscii( "Name" ), + ::rtl::OUString() ); + + sal_Int32 nFilterFlags = aFilterPropsHM.getUnpackedValueOrDefault( + ::rtl::OUString::createFromAscii( "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::OUString::createFromAscii("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.equalsAscii( "com.sun.star.text.TextDocument" )) + sType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "writer_MS_Word_97" )); + else + if (sModule.equalsAscii( "com.sun.star.sheet.SpreadsheetDocument" )) + sType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "calc_MS_Excel_97" )); + else + if (sModule.equalsAscii( "com.sun.star.drawing.DrawingDocument" )) + sType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "impress_MS_PowerPoint_97" )); + else + if (sModule.equalsAscii( "com.sun.star.presentation.PresentationDocument" )) + sType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "impress_MS_PowerPoint_97" )); + } + break; + + case E_OOO_DOC: + { + if (sModule.equalsAscii( "com.sun.star.text.TextDocument" )) + sType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "writer8" )); + else + if (sModule.equalsAscii( "com.sun.star.sheet.SpreadsheetDocument" )) + sType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "calc8" )); + else + if (sModule.equalsAscii( "com.sun.star.drawing.DrawingDocument" )) + sType = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "draw8" )); + else + if (sModule.equalsAscii( "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(); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::ExecMisc_Impl( SfxRequest &rReq ) +{ + const USHORT nId = rReq.GetSlot(); + switch( nId ) + { + case SID_STYLE_FAMILY : + { + SFX_REQUEST_ARG(rReq, pItem, SfxUInt16Item, nId, FALSE); + if (pItem) + pImp->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 ) + { + USHORT nItemCount = pTextToolbox->GetItemCount(); + for( USHORT nItem = 0; nItem < nItemCount; ++nItem ) + { + USHORT 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, TRUE ); + } + else + { + SfxMailModel aModel; + rtl::OUString aDocType; + + SFX_REQUEST_ARG(rReq, pMailSubject, SfxStringItem, SID_MAIL_SUBJECT, FALSE ); + if ( pMailSubject ) + aModel.SetSubject( pMailSubject->GetValue() ); + + SFX_REQUEST_ARG(rReq, pMailRecipient, SfxStringItem, SID_MAIL_RECIPIENT, 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, 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(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(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(FALSE); + return; + } + + ::com::sun::star::uno::Reference< XSystemShellExecute > xSystemShellExecute( xSMGR->createInstance( + ::rtl::OUString::createFromAscii( "com.sun.star.system.SystemShellExecute" )), + css::uno::UNO_QUERY ); + + BOOL bRet( TRUE ); + if ( xSystemShellExecute.is() ) + { + try + { + xSystemShellExecute->execute( + aFileURL, ::rtl::OUString(), SystemShellExecuteFlags::DEFAULTS ); + } + catch ( uno::Exception& ) + { + vos::OGuard aGuard( Application::GetSolarMutex() ); + Window *pParent = SFX_APP()->GetTopWindow(); + ErrorBox( pParent, SfxResId( MSG_ERROR_NO_WEBBROWSER_FOUND )).Execute(); + bRet = FALSE; + } + } + + rReq.Done(bRet); + break; + } + else + { + rReq.Done(FALSE); + return; + } + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + case SID_PLUGINS_ACTIVE: + { + SFX_REQUEST_ARG(rReq, pShowItem, SfxBoolItem, nId, FALSE); + BOOL bActive = pShowItem ? pShowItem->GetValue() : !pImp->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(TRUE); + + // ausfuehren + if ( !pShowItem || bActive != pImp->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->bPlugInsActive = bActive; + Rectangle aVisArea = GetObjectShell()->GetVisArea(); + VisAreaChanged(aVisArea); + + // the plugins might need change in their state + SfxInPlaceClientList *pClients = pView->GetIPClientList_Impl(FALSE); + if ( pClients ) + { + for (USHORT n=0; n < pClients->Count(); n++) + { + SfxInPlaceClient* pIPClient = pClients->GetObject(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 ( USHORT nSID = aIter.FirstWhich(); nSID; nSID = aIter.NextWhich() ) + { + switch ( nSID ) + { + case SID_STYLE_CATALOG: + { + if ( !GetViewFrame()->KnowsChildWindow( SID_STYLE_DESIGNER ) ) + rSet.DisableItem( nSID ); + break; + } + + // Printer-Funktionen + case SID_PRINTDOC: + case SID_PRINTDOCDIRECT: + case SID_SETUPPRINTER: + case SID_PRINTER_NAME: + { + BOOL bEnabled = pImp->bCanPrint && !pImp->nPrinterLocks; + bEnabled = bEnabled && !Application::GetSettings().GetMiscSettings().GetDisablePrinting(); + if ( bEnabled ) + { + SfxPrinter *pPrinter = GetPrinter(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(); + } + if ( !bEnabled ) + { + // will now be handled by requeing the request + /* rSet.DisableItem( SID_PRINTDOC ); + rSet.DisableItem( SID_PRINTDOCDIRECT ); + rSet.DisableItem( SID_SETUPPRINTER ); */ + } + break; + } + + // Mail-Funktionen + case SID_MAIL_SENDDOCASPDF: + case SID_MAIL_SENDDOC: + case SID_MAIL_SENDDOCASFORMAT: + { + 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->bPlugInsActive) ); + break; + } +/* + // SelectionText + case SID_SELECTION_TEXT: + { + rSet.Put( SfxStringItem( SID_SELECTION_TEXT, GetSelectionText() ) ); + break; + } + + // SelectionTextExt + case SID_SELECTION_TEXT_EXT: + { + rSet.Put( SfxStringItem( SID_SELECTION_TEXT_EXT, GetSelectionText(TRUE) ) ); + break; + } +*/ + case SID_STYLE_FAMILY : + { + rSet.Put( SfxUInt16Item( SID_STYLE_FAMILY, pImp->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*/) + +/* [Beschreibung] + + Virtuelle Methode, um am selektierten Objekt ein Verb auszuf"uhren. + Da dieses Objekt nur den abgeleiteten Klassen bekannt ist, muss DoVerb + dort "uberschrieben werden. + +*/ + +{ + 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(TRUE); + pFrame->GetDispatcher()->Update_Impl( TRUE ); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::UIDeactivated( SfxInPlaceClient* /*pClient*/ ) +{ + if ( !pFrame->GetFrame().IsClosing_Impl() || + SfxViewFrame::Current() != pFrame ) + pFrame->GetDispatcher()->Update_Impl( TRUE ); + pFrame->GetBindings().HidePopups(FALSE); + + // uno::Reference < frame::XFrame > xOwnFrame( pFrame->GetFrame().GetFrameInterface() ); + // uno::Reference < frame::XFramesSupplier > xParentFrame( xOwnFrame->getCreator(), uno::UNO_QUERY ); + // if ( xParentFrame.is() ) + // xParentFrame->setActiveFrame( uno::Reference < frame::XFrame >() ); +} + +//-------------------------------------------------------------------- + +SfxInPlaceClient* SfxViewShell::FindIPClient +( + const uno::Reference < embed::XEmbeddedObject >& xObj, + Window* pObjParentWin +) const +{ + SfxInPlaceClientList *pClients = GetIPClientList_Impl(FALSE); + if ( !pClients ) + return 0; + + if( !pObjParentWin ) + pObjParentWin = GetWindow(); + for (USHORT n=0; n < pClients->Count(); n++) + { + SfxInPlaceClient *pIPClient = (SfxInPlaceClient*) pClients->GetObject(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(FALSE); + if ( !pClients ) + return 0; + + for (USHORT n=0; n < pClients->Count(); n++) + { + SfxInPlaceClient* pIPClient = pClients->GetObject(n); + if ( pIPClient->IsUIActive() ) + return pIPClient; + } + + return NULL; +} + +SfxInPlaceClient* SfxViewShell::GetUIActiveClient() const +{ + SfxInPlaceClientList *pClients = GetIPClientList_Impl(FALSE); + if ( !pClients ) + return 0; + + for (USHORT n=0; n < pClients->Count(); n++) + { + SfxInPlaceClient* pIPClient = pClients->GetObject(n); + if ( pIPClient->IsObjectUIActive() ) + return pIPClient; + } + + return NULL; +} + +//-------------------------------------------------------------------- + +void SfxViewShell::Activate( 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(BOOL /*bMDI*/) +{ + DBG_CHKTHIS(SfxViewShell, 0); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::AdjustPosSizePixel +( + const Point& /*rToolOffset*/,// linke obere Ecke der Tools im Frame-Window + const Size& /*rSize*/ // gesamte zur Verf"ugung stehende Gr"o\se +) + +{ + DBG_CHKTHIS(SfxViewShell, 0); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::Move() + +/* [Beschreibung] + + Diese virtuelle Methode wird gerufen, wenn das Fenster, in dem die + SfxViewShell dargestellt wird eine StarView-Move() Nachricht erh"alt. + + Die Basisimplementierung braucht nicht gerufen zu werden. + + + [Anmerkung] + + Diese Methode kann dazu verwendet werden, eine Selektion abzubrechen, + um durch das Moven des Fensters erzeugte Maus-Bewegungen anzufangen. + + Zur Zeit funktioniert die Benachrichtigung nicht In-Place. +*/ + +{ +} + +//-------------------------------------------------------------------- + +void SfxViewShell::OuterResizePixel +( + const Point& /*rToolOffset*/,// linke obere Ecke der Tools im Frame-Window + const Size& /*rSize*/ // gesamte zur Verf"ugung stehende Gr"o\se +) + +/* [Beschreibung] + + Diese Methode muss ueberladen werden, um auf "Anderungen der Groesse + der View zu reagieren. Dabei definieren wir die View als das Edit-Window + zuz"uglich der um das Edit-Window angeordnenten Tools (z.B. Lineale). + + Das Edit-Window darf weder in Gr"o\se noch Position ver"andert werden. + + Die Vis-Area der SfxObjectShell, dessen Skalierung und Position + d"urfen hier ver"andert werden. Der Hauptanwendungsfall ist dabei, + das Ver"andern der Gr"o\se der Vis-Area. + + "Andert sich durch die neue Berechnung der Border, so mu\s dieser + mit <SfxViewShell::SetBorderPixel(const SvBorder&)> gesetzt werden. + Erst nach Aufruf von 'SetBorderPixel' ist das Positionieren von + Tools erlaubt. + + + [Beispiel] + + void AppViewSh::OuterViewResizePixel( const Point &rOfs, const Size &rSz ) + { + // Tool-Positionen und Gr"o\sen von au\sen berechnen, NICHT setzen! + // (wegen folgender Border-Berechnung) + Point aHLinPos...; Size aHLinSz...; + ... + + // Border f"ur Tools passend zu rSize berechnen und setzen + SvBorder aBorder... + SetBorderPixel( aBorder ); // ab jetzt sind Positionierungen erlaubt + + // Tools anordnen + pHLin->SetPosSizePixel( aHLinPos, aHLinSz ); + ... + } + + + [Querverweise] + + <SfxViewShell::InnerResizePixel(const Point&,const Size& rSize)> +*/ + +{ + DBG_CHKTHIS(SfxViewShell, 0); + SetBorderPixel( SvBorder() ); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::InnerResizePixel +( + const Point& /*rToolOffset*/,// linke obere Ecke der Tools im Frame-Window + const Size& /*rSize*/ // dem Edit-Win zur Verf"ugung stehende Gr"o\se +) + +/* [Beschreibung] + + Diese Methode muss ueberladen werden, um auf "Anderungen der Groesse + des Edit-Windows zu reagieren. + + Das Edit-Window darf weder in Gr"o\se noch Position ver"andert werden. + Weder die Vis-Area der SfxObjectShell noch dessen Skalierung oder + Position d"urfen ver"andert werden. + + "Andert sich durch die neue Berechnung der Border, so mu\s dieser + mit <SfxViewShell::SetBorderPixel(const SvBorder&)> gesetzt werden. + Erst nach Aufruf von 'SetBorderPixel' ist das Positionieren von + Tools erlaubt. + + + [Beispiel] + + void AppViewSh::InnerViewResizePixel( const Point &rOfs, const Size &rSz ) + { + // Tool-Positionen und Gr"o\sen von innen berechnen, NICHT setzen! + // (wegen folgender Border-Berechnung) + Point aHLinPos...; Size aHLinSz...; + ... + + // Border f"ur Tools passend zu rSz berechnen und setzen + SvBorder aBorder... + SetBorderPixel( aBorder ); // ab jetzt sind Positionierungen erlaubt + + // Tools anordnen + pHLin->SetPosSizePixel( aHLinPos, aHLinSz ); + ... + } + + + [Querverweise] + + <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->pController ) + pImp->pController->BorderWidthsChanged_Impl(); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::SetBorderPixel( const SvBorder &rBorder ) +{ + DBG_CHKTHIS(SfxViewShell, 0); + DBG_ASSERT( GetViewFrame(), "SfxViewShell without SfxViewFrame" ); + + //if ( rBorder != GetBorderPixel()) + { + GetViewFrame()->SetBorderPixelImpl( this, rBorder ); + + // notify related controller that border size is changed + if ( pImp->pController ) + pImp->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 // Pointer auf das Datenfenster bzw. 0 im Destruktor +) + +/* [Beschreibung] + + Mit dieser Methode wird der SfxViewShell das Datenfenster mitgeteilt. + Dieses wird f"ur den In-Place-Container und f"ur das korrekte + Wiederherstellen des Focus ben"otigt. + + Selbst In-Place-aktiv ist das Umsetzen des ViewPort-Windows verboten. +*/ + +{ + if( pWindow == pViewPort ) + return; + + // ggf. vorhandene IP-Clients disconnecten + DisconnectAllClients(); + + //TODO: should we have a "ReconnectAllClients" method? + DiscardClients_Impl(); + + // View-Port austauschen + BOOL bHadFocus = pWindow ? pWindow->HasChildPathFocus( TRUE ) : FALSE; + pWindow = pViewPort; + + if( pWindow ) + { + // Disable automatic GUI mirroring (right-to-left) for document windows + pWindow->EnableRTL( FALSE ); + } + + if ( bHadFocus && pWindow ) + pWindow->GrabFocus(); + //TODO/CLEANUP + //brauchen wir die Methode doch noch?! + //SFX_APP()->GrabFocus( pWindow ); +} + +//-------------------------------------------------------------------- + +Size SfxViewShell::GetOptimalSizePixel() const +{ + DBG_ERROR( "Useless call!" ); + return Size(); +} + +//------------------------------------------------------------------------ + +SfxViewShell::SfxViewShell +( + SfxViewFrame* pViewFrame, /* <SfxViewFrame>, in dem diese View + dargestellt wird */ + USHORT nFlags /* siehe <SfxViewShell-Flags> */ +) + +: SfxShell(this) + ,pImp( new SfxViewShell_Impl ) + ,pIPClientList( 0 ) + ,pFrame(pViewFrame) + ,pSubShell(0) + ,pWindow(0) + ,bNoNewWindow( 0 != (nFlags & SFX_VIEW_NO_NEWWINDOW) ) +{ + DBG_CTOR(SfxViewShell, 0); + + //pImp->pPrinterCommandQueue = new SfxAsyncPrintExec_Impl( this ); + pImp->pController = 0; + pImp->bIsShowView = + !(SFX_VIEW_NO_SHOW == (nFlags & SFX_VIEW_NO_SHOW)); + + pImp->bCanPrint = SFX_VIEW_CAN_PRINT == (nFlags & SFX_VIEW_CAN_PRINT); + pImp->bHasPrintOptions = + SFX_VIEW_HAS_PRINTOPTIONS == (nFlags & SFX_VIEW_HAS_PRINTOPTIONS); + pImp->bPlugInsActive = TRUE; + pImp->bGotOwnerShip = FALSE; + pImp->bGotFrameOwnerShip = FALSE; + if ( pViewFrame->GetParentViewFrame() ) + pImp->bPlugInsActive = pViewFrame->GetParentViewFrame()->GetViewShell()->pImp->bPlugInsActive; + pImp->eScroll = SCROLLING_DEFAULT; + pImp->nPrinterLocks = 0; + pImp->bControllerSet = FALSE; + pImp->nFamily = 0xFFFF; // undefined, default set by TemplateDialog + SetMargin( pViewFrame->GetMargin_Impl() ); + + SetPool( &pViewFrame->GetObjectShell()->GetPool() ); + StartListening(*pViewFrame->GetObjectShell()); + + // in Liste eintragen + const SfxViewShell *pThis = this; // wegen der kranken Array-Syntax + SfxViewShellArr_Impl &rViewArr = SFX_APP()->GetViewShells_Impl(); + rViewArr.Insert(pThis, rViewArr.Count() ); +} + +//-------------------------------------------------------------------- + +SfxViewShell::~SfxViewShell() +{ + DBG_DTOR(SfxViewShell, 0); + + // aus Liste austragen + 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->pController ) + { + pImp->pController->ReleaseShell_Impl(); + pImp->pController->release(); + pImp->pController = NULL; + } + + if (pImp->pAccExec) + { + DELETEZ( pImp->pAccExec ); + } + + //DELETEZ( pImp->pPrinterCommandQueue ); + DELETEZ( pImp ); + DELETEZ( pIPClientList ); +} + +//-------------------------------------------------------------------- + +USHORT SfxViewShell::PrepareClose +( + BOOL bUI, // TRUE: Dialoge etc. erlaubt, FALSE: silent-mode + BOOL /*bForBrowsing*/ +) +{ + SfxPrinter *pPrinter = GetPrinter(); + if ( pPrinter && pPrinter->IsPrinting() ) + { + if ( bUI ) + { + InfoBox aInfoBox( &GetViewFrame()->GetWindow(), SfxResId( MSG_CANT_CLOSE ) ); + aInfoBox.Execute(); + } + + return FALSE; + } + + if( GetViewFrame()->IsInModalMode() ) + return FALSE; + + if( bUI && GetViewFrame()->GetDispatcher()->IsLocked() ) + return FALSE; + + return 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, FALSE ); + pViewShell; + pViewShell = SfxViewShell::GetNext( *pViewShell, NULL, FALSE ) + ) + { + if ( pViewShell->GetController() == i_rController ) + return pViewShell; + } + return NULL; +} + +//-------------------------------------------------------------------- + +SdrView* SfxViewShell::GetDrawView() const + +/* [Beschreibung] + + Diese virtuelle Methode mu\s von den Subklassen "uberladen werden, wenn + der Property-Editor zur Verf"ugung stehen soll. + + Die Default-Implementierung liefert immer 0. +*/ + +{ + return 0; +} + +//-------------------------------------------------------------------- + +String SfxViewShell::GetSelectionText +( + BOOL /*bCompleteWords*/ /* FALSE (default) + Nur der tats"achlich selektierte Text wird + zur"uckgegeben. + + TRUE + Der selektierte Text wird soweit erweitert, + da\s nur ganze W"orter zur"uckgegeben werden. + Als Worttrenner gelten White-Spaces und die + Satzzeichen ".,;" sowie einfache und doppelte + Anf"uhrungszeichen. + */ +) + +/* [Beschreibung] + + Diese Methode kann von Anwendungsprogrammierer "uberladen werden, + um einen Text zur"uckzuliefern, der in der aktuellen Selektion + steht. Dieser wird z.B. beim Versenden (email) verwendet. + + Mit "CompleteWords == TRUE" ger"ufen, reicht z.B. auch der Cursor, + der in einer URL steht, um die gesamte URL zu liefern. +*/ + +{ + return String(); +} + +//-------------------------------------------------------------------- + +BOOL SfxViewShell::HasSelection( BOOL ) const + +/* [Beschreibung] + + Mit dieser virtuellen Methode kann z.B. ein Dialog abfragen, ob in der + aktuellen View etwas selektiert ist. Wenn der Parameter <BOOL> TRUE ist, + wird abgefragt, ob Text selektiert ist. +*/ + +{ + return FALSE; +} + +//-------------------------------------------------------------------- + +void SfxViewShell::SetSubShell( SfxShell *pShell ) + +/* [Beschreibung] + + Mit dieser Methode kann eine Selektions- oder Cursor-Shell angemeldet + werden, die automatisch unmittelbar nach der SfxViewShell auf den + SfxDispatcher gepusht wird, und automatisch umittelbar vor ihr + gepoppt wird. + + Ist die SfxViewShell-Instanz bereits gepusht, dann wird pShell + sofort ebenfalls gepusht. Wird mit SetSubShell eine andere SfxShell + Instanz angemeldet, als vorher angemeldet war, wird die zuvor angemeldete + ggf. automatisch gepoppt. Mit pShell==0 kann daher die aktuelle + Sub-Shell abgemeldet werden. +*/ + +{ + // ist diese ViewShell "uberhaupt aktiv? + SfxDispatcher *pDisp = pFrame->GetDispatcher(); + if ( pDisp->IsActive(*this) ) + { + // Dispatcher updaten + 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 ) + { + USHORT nCount = pImp->aArr.Count(); + if ( pDisp->IsActive(*this) ) + { + for ( USHORT n=nCount; n>0; n-- ) + pDisp->Pop( *pImp->aArr[n-1] ); + pDisp->Flush(); + } + + pImp->aArr.Remove(0, nCount); + } + else + { + USHORT 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( USHORT nNo ) +{ + USHORT nCount = pImp->aArr.Count(); + if ( nNo<nCount ) + return pImp->aArr[nCount-nNo-1]; + return NULL; +} + +void SfxViewShell::PushSubShells_Impl( BOOL bPush ) +{ + USHORT nCount = pImp->aArr.Count(); + SfxDispatcher *pDisp = pFrame->GetDispatcher(); + if ( bPush ) + { + for ( USHORT 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&, BOOL ) +{ +} + +//-------------------------------------------------------------------- + +void SfxViewShell::ReadUserData(const String&, 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, + 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 ( USHORT 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, + BOOL bOnlyVisible +) +{ + SfxViewShellArr_Impl &rShells = SFX_APP()->GetViewShells_Impl(); + SfxViewFrameArr_Impl &rFrames = SFX_APP()->GetViewFrames_Impl(); + USHORT 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->pController->restoreViewData( pItem->GetValue() ); + pSet->ClearItem( SID_VIEW_DATA ); + } + + break; + } + } + } + + break; + } + } + } +} + +//-------------------------------------------------------------------- + +BOOL SfxViewShell::ExecKey_Impl(const KeyEvent& aKey) +{ + if (!pImp->pAccExec) + { + pImp->pAccExec = ::svt::AcceleratorExecute::createAcceleratorHelper(); + pImp->pAccExec->init(::comphelper::getProcessServiceFactory(), pFrame->GetFrame().GetFrameInterface()); + } + + return pImp->pAccExec->execute(aKey.GetKeyCode()); +} + +//-------------------------------------------------------------------- + +FASTBOOL SfxViewShell::KeyInput( const KeyEvent &rKeyEvent ) + +/* [Beschreibung] + + Diese Methode f"uhrt das KeyEvent 'rKeyEvent' "uber die an dieser + SfxViewShell direkt oder indirekt (z.B. via Applikation) konfigurierten + Tasten (Accelerator) aus. + + + [R"uckgabewert] + + FASTBOOL TRUE + die Taste ist konfiguriert, der betreffende + Handler wurde gerufen + + FALSE + die Taste ist nicht konfiguriert, es konnte + also kein Handler gerufen werden + + + [Querverweise] + <SfxApplication::KeyInput(const KeyEvent&)> +*/ +{ + return ExecKey_Impl(rKeyEvent); +} + +FASTBOOL SfxViewShell::GlobalKeyInput_Impl( const KeyEvent &rKeyEvent ) +{ + return ExecKey_Impl(rKeyEvent); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::ShowCursor( FASTBOOL /*bOn*/ ) + +/* [Beschreibung] + + Diese Methode mu\s von Subklassen "uberladen werden, damit vom SFx + aus der Cursor ein- und ausgeschaltet werden kann. Dies geschieht + z.B. bei laufendem <SfxProgress>. +*/ + +{ +} + +//-------------------------------------------------------------------- + +void SfxViewShell::GotFocus() const + +/* [Beschreibung] + + Diese Methode mu\s vom Applikationsentwickler gerufen werden, wenn + das Edit-Window den Focus erhalten hat. Der SFx hat so z.B. die + M"oglichkeit, den Accelerator einzuschalten. + + + [Anmerkung] + + <StarView> liefert leider keine M"oglichkeit, solche Events + 'von der Seite' einzuh"angen. +*/ + +{ +} + +//-------------------------------------------------------------------- +void SfxViewShell::ResetAllClients_Impl( SfxInPlaceClient *pIP ) +{ + + SfxInPlaceClientList *pClients = GetIPClientList_Impl(FALSE); + if ( !pClients ) + return; + + for ( USHORT n=0; n < pClients->Count(); n++ ) + { + SfxInPlaceClient* pIPClient = pClients->GetObject(n); + if( pIPClient != pIP ) + pIPClient->ResetObject(); + } +} + +//-------------------------------------------------------------------- + +void SfxViewShell::DisconnectAllClients() +{ + SfxInPlaceClientList *pClients = GetIPClientList_Impl(FALSE); + if ( !pClients ) + return; + + for ( USHORT n=0; n<pClients->Count(); ) + // clients will remove themselves from the list + delete pClients->GetObject(n); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::QueryObjAreaPixel( Rectangle& ) const +{ +} + +//-------------------------------------------------------------------- + +void SfxViewShell::AdjustVisArea(const Rectangle& rRect) +{ + DBG_ASSERT (pFrame, "Kein Frame?"); + GetObjectShell()->SetVisArea( rRect ); +} + +//-------------------------------------------------------------------- + +void SfxViewShell::VisAreaChanged(const Rectangle& /*rVisArea*/) +{ + SfxInPlaceClientList *pClients = GetIPClientList_Impl(FALSE); + if ( !pClients ) + return; + + for (USHORT n=0; n < pClients->Count(); n++) + { + SfxInPlaceClient* pIPClient = pClients->GetObject(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->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->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 ); + } +} + +//-------------------------------------------------------------------- + +BOOL SfxViewShell::PlugInsActive() const +{ + return pImp->bPlugInsActive; +} + +//-------------------------------------------------------------------- +void SfxViewShell::DiscardClients_Impl() + +/* [Beschreibung] + + Diese Methode dient dazu, vor dem Schlie\sen eines Dokuments das + Speichern der Objekte zu verhindern, wenn der Benutzer Schlie\en ohne + Speichern gew"ahlt hatte. +*/ + +{ + SfxInPlaceClientList *pClients = GetIPClientList_Impl(FALSE); + if ( !pClients ) + return; + + for (USHORT n=0; n < pClients->Count(); ) + delete pClients->GetObject(n); +} + +//-------------------------------------------------------------------- + +SfxScrollingMode SfxViewShell::GetScrollingMode() const +{ + return pImp->eScroll; +} + +//-------------------------------------------------------------------- + +void SfxViewShell::SetScrollingMode( SfxScrollingMode eMode ) +{ + pImp->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 ) +{ + // Der default-Margin wurde "geeicht" mit 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() +{ +} + +//-------------------------------------------------------------------- + +BOOL SfxViewShell::IsShowView_Impl() const +{ + return pImp->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( BOOL bCreate ) const +{ + if ( !pIPClientList && bCreate ) + ( (SfxViewShell*) this )->pIPClientList = new SfxInPlaceClientList; + return pIPClientList; +} + +void SfxViewShell::SetController( SfxBaseController* pController ) +{ + pImp->pController = pController; + pImp->pController->acquire(); + pImp->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 ); + AddRemoveClipboardListener( pImp->xClipboardListener.get(), TRUE ); +} + +Reference < XController > SfxViewShell::GetController() +{ + return pImp->pController; +} + +SfxBaseController* SfxViewShell::GetBaseController_Impl() const +{ + return pImp->pController; +} + +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(); + USHORT nCount = pMenu->GetItemCount(); + for ( USHORT nPos=0; nPos<nCount; ++nPos ) + { + USHORT 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 (USHORT 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->RemoveItem( nPos+1 ); + break; + } + } + } + } + } +} + + +BOOL SfxViewShell::TryContextMenuInterception( Menu& rIn, const ::rtl::OUString& rMenuIdentifier, Menu*& rpOut, ::com::sun::star::ui::ContextMenuExecuteEvent aEvent ) +{ + rpOut = NULL; + BOOL bModified = FALSE; + + // create container from menu + // #110897# + // aEvent.ActionTriggerContainer = ::framework::ActionTriggerHelper::CreateActionTriggerContainerFromMenu( &rIn ); + aEvent.ActionTriggerContainer = ::framework::ActionTriggerHelper::CreateActionTriggerContainerFromMenu( + ::comphelper::getProcessServiceFactory(), &rIn, &rMenuIdentifier ); + + // get selection from controller + aEvent.Selection = ::com::sun::star::uno::Reference < ::com::sun::star::view::XSelectionSupplier > ( GetController(), ::com::sun::star::uno::UNO_QUERY ); + + // call interceptors + ::cppu::OInterfaceIteratorHelper aIt( pImp->aInterceptorContainer ); + while( aIt.hasMoreElements() ) + { + try + { + ::com::sun::star::ui::ContextMenuInterceptorAction eAction = + ((::com::sun::star::ui::XContextMenuInterceptor*)aIt.next())->notifyContextMenuExecute( aEvent ); + switch ( eAction ) + { + case ::com::sun::star::ui::ContextMenuInterceptorAction_CANCELLED : + // interceptor does not want execution + return FALSE; + case ::com::sun::star::ui::ContextMenuInterceptorAction_EXECUTE_MODIFIED : + // interceptor wants his modified menu to be executed + bModified = TRUE; + break; + case ::com::sun::star::ui::ContextMenuInterceptorAction_CONTINUE_MODIFIED : + // interceptor has modified menu, but allows for calling other interceptors + bModified = TRUE; + continue; + case ::com::sun::star::ui::ContextMenuInterceptorAction_IGNORED : + // interceptor is indifferent + continue; + default: + DBG_ERROR("Wrong return value of ContextMenuInterceptor!"); + continue; + } + } + catch( ::com::sun::star::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 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->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->bGotFrameOwnerShip = TRUE; +} + +void SfxViewShell::CheckOwnerShip_Impl() +{ + BOOL bSuccess = FALSE; + if( pImp->bGotOwnerShip ) + { + com::sun::star::uno::Reference < com::sun::star::util::XCloseable > xModel( + GetObjectShell()->GetModel(), com::sun::star::uno::UNO_QUERY ); + if ( xModel.is() ) + { + try + { + // this call will destroy this object in case of success! + xModel->close( sal_True ); + bSuccess = TRUE; + } + catch ( com::sun::star::util::CloseVetoException& ) + { + } + } + } + + if( !bSuccess && pImp->bGotFrameOwnerShip ) + { + // document couldn't be closed or it shouldn't, now try at least to close the frame + com::sun::star::uno::Reference < com::sun::star::util::XCloseable > xFrame( + GetViewFrame()->GetFrame().GetFrameInterface(), com::sun::star::uno::UNO_QUERY ); + if ( xFrame.is() ) + { + try + { + xFrame->close( sal_True ); + } + catch ( com::sun::star::util::CloseVetoException& ) + { + } + } + } +} + +long SfxViewShell::HandleNotifyEvent_Impl( NotifyEvent& rEvent ) +{ + if ( pImp->pController ) + return pImp->pController->HandleEvent_Impl( rEvent ); + return 0; +} + +BOOL SfxViewShell::HasKeyListeners_Impl() +{ + return pImp->pController ? pImp->pController->HasKeyListeners_Impl() : FALSE; +} + +BOOL SfxViewShell::HasMouseClickListeners_Impl() +{ + return pImp->pController ? pImp->pController->HasMouseClickListeners_Impl() : FALSE; +} + +void SfxViewShell::SetAdditionalPrintOptions( const com::sun::star::uno::Sequence < com::sun::star::beans::PropertyValue >& rOpts ) +{ + pImp->aPrintOpts = rOpts; +// GetObjectShell()->Broadcast( SfxPrintingHint( -3, NULL, NULL, rOpts ) ); +} + +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; +} + +void SfxViewShell::AddRemoveClipboardListener( const uno::Reference < datatransfer::clipboard::XClipboardListener >& rClp, 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& ) + { + } +} + |