/************************************************************************* * * $RCSfile: fmexpl.cxx,v $ * * $Revision: 1.13 $ * * last change: $Author: oj $ $Date: 2001-07-05 10:15:13 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses * * - GNU Lesser General Public License Version 2.1 * - Sun Industry Standards Source License Version 1.1 * * Sun Microsystems Inc., October, 2000 * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2000 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library 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 for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * * Sun Industry Standards Source License Version 1.1 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.1 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://www.openoffice.org/license.html. * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2000 by Sun Microsystems, Inc. * * All Rights Reserved. * * Contributor(s): _______________________________________ * * ************************************************************************/ #ifndef _SVX_FMUNOVW_HXX #include "fmvwimp.hxx" #endif #ifndef _SVX_FMRESIDS_HRC #include "fmresids.hrc" #endif #ifndef _SVX_FMEXPL_HRC #include "fmexpl.hrc" #endif #ifndef _SVX_FMEXPL_HXX #include "fmexpl.hxx" #endif #ifndef _SVDPAGV_HXX //autogen #include "svdpagv.hxx" #endif #ifndef _SVX_FMHELP_HRC #include "fmhelp.hrc" #endif #ifndef _SVX_FMGLOB_HXX #include "fmglob.hxx" #endif #ifndef _SVX_FMITEMS_HXX #include "fmitems.hxx" #endif #ifndef _SVDOGRP_HXX #include "svdogrp.hxx" #endif #ifndef _SVX_FMSERVS_HXX #include "fmservs.hxx" #endif #ifndef _SVX_TABORDER_HXX #include "taborder.hxx" #endif #ifndef _SVX_DBERRBOX_HXX #include "dbmsgbox.hxx" #endif #ifndef _SVX_FMMODEL_HXX #include "fmmodel.hxx" #endif #ifndef _SVX_FMEXCH_HXX #include "fmexch.hxx" #endif #ifndef _SVX_FMUNDO_HXX #include "fmundo.hxx" #endif #ifndef _SVX_FMUNOPGE_HXX #include "fmpgeimp.hxx" #endif #ifndef _SVX_SVXIDS_HRC #include "svxids.hrc" #endif #ifndef _SVX_FMPROP_HRC #include "fmprop.hrc" #endif #ifndef _SVX_DIALMGR_HXX //autogen #include "dialmgr.hxx" #endif #ifndef _SVDITER_HXX //autogen #include "svditer.hxx" #endif #ifndef _SVDOUNO_HXX #include #endif #ifndef _SVX_FMUNDO_HXX #include #endif #ifndef _SVDOBJ_HXX #include #endif #ifndef _SV_MSGBOX_HXX //autogen #include #endif #ifndef _SFXDISPATCH_HXX //autogen #include #endif #ifndef _SFX_OBJSH_HXX //autogen #include #endif #ifndef _SFXVIEWSH_HXX #include #endif #ifndef _SFXVIEWFRM_HXX #include #endif #ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_ #include #endif #ifndef _COM_SUN_STAR_FORM_FORMCOMPONENTTYPE_HPP_ #include #endif #ifndef _COM_SUN_STAR_AWT_XTABCONTROLLERMODEL_HPP_ #include #endif #ifndef _SV_MENU_HXX //autogen #include #endif #ifndef _SFX_OBJITEM_HXX //autogen #include #endif #ifndef _SFXREQUEST_HXX #include #endif #ifndef _SHL_HXX #include #endif #ifndef _WRKWIN_HXX //autogen #include #endif #ifndef _SV_EXCHANGE_HXX //autogen #include #endif #ifndef _SV_SOUND_HXX //autogen #include #endif #ifndef _MULTIPRO_HXX #include "multipro.hxx" #endif #ifndef _SVX_FMSHELL_HXX #include "fmshell.hxx" #endif #ifndef _SVX_FMSHIMP_HXX #include "fmshimp.hxx" #endif #ifndef _SVX_FMPAGE_HXX #include "fmpage.hxx" #endif #ifndef _COM_SUN_STAR_IO_XPERSISTOBJECT_HPP_ #include #endif #ifndef _COM_SUN_STAR_SCRIPT_XEVENTATTACHERMANAGER_HPP_ #include #endif #ifndef _COM_SUN_STAR_CONTAINER_XCONTAINER_HPP_ #include #endif #ifndef _COM_SUN_STAR_SDB_COMMANDTYPE_HPP_ #include #endif #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_ #include #endif #ifndef _SVX_FMPROP_HXX #include "fmprop.hxx" #endif #ifndef _COMPHELPER_PROPERTY_HXX_ #include #endif #ifndef _COMPHELPER_PROCESSFACTORY_HXX_ #include #endif #ifndef _OSL_DIAGNOSE_H_ #include #endif using namespace ::svxform; using namespace ::com::sun::star::uno; //======================================================================== #define DROP_ACTION_TIMER_INITIAL_TICKS 10 // solange dauert es, bis das Scrollen anspringt #define DROP_ACTION_TIMER_SCROLL_TICKS 3 // in diesen Intervallen wird jeweils eine Zeile gescrollt #define DROP_ACTION_TIMER_TICK_BASE 10 // das ist die Basis, mit der beide Angaben multipliziert werden (in ms) #define EXPLORER_SYNC_DELAY 200 // dieser Betrag an Millisekunden wird gewartet, ehe der Explorer nach einem Select oder Deselect die ::com::sun::star::sdbcx::View synchronisiert SV_IMPL_PTRARR_SORT( FmEntryDataArray, FmEntryDataPtr ) SV_IMPL_PTRARR_SORT( SvLBoxEntrySortedArray, SvLBoxEntryPtr ) //======================================================================== // class FmExplInsertedHint //======================================================================== TYPEINIT1( FmExplInsertedHint, SfxHint ); DBG_NAME(FmExplInsertedHint); //------------------------------------------------------------------------ FmExplInsertedHint::FmExplInsertedHint( FmEntryData* pInsertedEntryData, sal_uInt32 nRelPos ) :pEntryData( pInsertedEntryData ) ,nPos( nRelPos ) { DBG_CTOR(FmExplInsertedHint,NULL); } //------------------------------------------------------------------------ FmExplInsertedHint::~FmExplInsertedHint() { DBG_DTOR(FmExplInsertedHint,NULL); } //======================================================================== // class FmExplInsertedHint //======================================================================== TYPEINIT1( FmExplModelReplacedHint, SfxHint ); DBG_NAME(FmExplModelReplacedHint); //------------------------------------------------------------------------ FmExplModelReplacedHint::FmExplModelReplacedHint( FmEntryData* pAffectedEntryData ) :pEntryData( pAffectedEntryData ) { DBG_CTOR(FmExplModelReplacedHint,NULL); } //------------------------------------------------------------------------ FmExplModelReplacedHint::~FmExplModelReplacedHint() { DBG_DTOR(FmExplModelReplacedHint,NULL); } //======================================================================== // class FmExplRemovedHint //======================================================================== TYPEINIT1( FmExplRemovedHint, SfxHint ); DBG_NAME(FmExplRemovedHint); //------------------------------------------------------------------------ FmExplRemovedHint::FmExplRemovedHint( FmEntryData* pRemovedEntryData ) :pEntryData( pRemovedEntryData ) { DBG_CTOR(FmExplRemovedHint,NULL); } //------------------------------------------------------------------------ FmExplRemovedHint::~FmExplRemovedHint() { DBG_DTOR(FmExplRemovedHint,NULL); } //======================================================================== // class FmExplNameChangedHint //======================================================================== TYPEINIT1( FmExplNameChangedHint, SfxHint ); DBG_NAME(FmExplNameChangedHint); //------------------------------------------------------------------------ FmExplNameChangedHint::FmExplNameChangedHint( FmEntryData* pData, const ::rtl::OUString& rNewName ) :pEntryData( pData ) ,aNewName( rNewName ) { DBG_CTOR(FmExplNameChangedHint,NULL); } //------------------------------------------------------------------------ FmExplNameChangedHint::~FmExplNameChangedHint() { DBG_DTOR(FmExplNameChangedHint,NULL); } //======================================================================== // class FmExplClearedHint //======================================================================== TYPEINIT1( FmExplClearedHint, SfxHint ); DBG_NAME(FmExplClearedHint); //------------------------------------------------------------------------ FmExplClearedHint::FmExplClearedHint() { DBG_CTOR(FmExplClearedHint,NULL); } //------------------------------------------------------------------------ FmExplClearedHint::~FmExplClearedHint() { DBG_DTOR(FmExplClearedHint,NULL); } //======================================================================== // class FmExplRequestSelectHint //======================================================================== TYPEINIT1(FmExplRequestSelectHint, SfxHint); //======================================================================== // class FmExplViewMarksChanged //======================================================================== TYPEINIT1(FmExplViewMarksChanged, SfxHint); //======================================================================== // class FmEntryDataList //======================================================================== DBG_NAME(FmEntryDataList); //------------------------------------------------------------------------ FmEntryDataList::FmEntryDataList() { DBG_CTOR(FmEntryDataList,NULL); } //------------------------------------------------------------------------ FmEntryDataList::~FmEntryDataList() { DBG_DTOR(FmEntryDataList,NULL); } //======================================================================== // class FmEntryData //======================================================================== TYPEINIT0( FmEntryData ); DBG_NAME(FmEntryData); //------------------------------------------------------------------------ FmEntryData::FmEntryData( FmEntryData* pParentData ) :pParent( pParentData ) { DBG_CTOR(FmEntryData,NULL); pChildList = new FmEntryDataList(); } //------------------------------------------------------------------------ FmEntryData::~FmEntryData() { Clear(); delete pChildList; DBG_DTOR(FmEntryData,NULL); } //------------------------------------------------------------------------ FmEntryData::FmEntryData( const FmEntryData& rEntryData ) { pChildList = new FmEntryDataList(); aText = rEntryData.GetText(); aCollapsedImage = rEntryData.GetCollapsedImage(); aExpandedImage = rEntryData.GetExpandedImage(); pParent = rEntryData.GetParent(); FmEntryData* pChildData; sal_uInt32 nEntryCount = rEntryData.GetChildList()->Count(); for( sal_uInt32 i=0; iGetObject(i); FmEntryData* pNewChildData = pChildData->Clone(); pChildList->Insert( pNewChildData, LIST_APPEND ); } } //------------------------------------------------------------------------ void FmEntryData::Clear() { FmEntryData* pEntryData; while( pEntryData = GetChildList()->Remove(sal_uInt32(0)) ) delete pEntryData; } //------------------------------------------------------------------------ sal_Bool FmEntryData::IsEqualWithoutChilds( FmEntryData* pEntryData ) { if(this == pEntryData) return sal_True; if( !pEntryData ) return sal_False; if( !aText.equals(pEntryData->GetText())) return sal_False; if( !pEntryData->GetParent() && pParent ) return sal_False; if( pEntryData->GetParent() && !pParent ) return sal_False; if( !pEntryData->GetParent() && !pParent ) return sal_True; if( !pParent->IsEqualWithoutChilds(pEntryData->GetParent()) ) return sal_False; return sal_True; } //======================================================================== // class FmFormData //======================================================================== TYPEINIT1( FmFormData, FmEntryData ); DBG_NAME(FmFormData); //------------------------------------------------------------------------ FmFormData::FmFormData( ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xForm, const ImageList& ilNavigatorImages, FmFormData* pParent ) :FmEntryData( pParent ) ,m_xForm( xForm ) { DBG_CTOR(FmEntryData,NULL); ////////////////////////////////////////////////////////////////////// // Images setzen aCollapsedImage = ilNavigatorImages.GetImage( RID_SVXIMG_FORM ); aExpandedImage = ilNavigatorImages.GetImage( RID_SVXIMG_FORM ); ////////////////////////////////////////////////////////////////////// // Titel setzen if (m_xForm.is()) { ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xSet(m_xForm, ::com::sun::star::uno::UNO_QUERY); if (xSet.is()) { ::rtl::OUString aEntryName(::comphelper::getString(xSet->getPropertyValue( FM_PROP_NAME ))); SetText(aEntryName); } } else SetText( ::rtl::OUString() ); } //------------------------------------------------------------------------ FmFormData::~FmFormData() { DBG_DTOR(FmEntryData,NULL); } //------------------------------------------------------------------------ FmFormData::FmFormData( const FmFormData& rFormData ) :FmEntryData( rFormData ) { DBG_CTOR(FmEntryData,NULL); m_xForm = rFormData.GetFormIface(); } //------------------------------------------------------------------------ FmEntryData* FmFormData::Clone() { return new FmFormData( *this ); } //------------------------------------------------------------------------ sal_Bool FmFormData::IsEqualWithoutChilds( FmEntryData* pEntryData ) { if(this == pEntryData) return sal_True; if( !pEntryData->ISA(FmFormData) ) return sal_False; FmFormData* pFormData = (FmFormData*)pEntryData; if( (::com::sun::star::form::XForm*)m_xForm.get() != (::com::sun::star::form::XForm*)pFormData->GetFormIface().get() ) return sal_False; return FmEntryData::IsEqualWithoutChilds( pFormData ); } //======================================================================== // class FmControlData //======================================================================== TYPEINIT1( FmControlData, FmEntryData ); DBG_NAME(FmControlData); //------------------------------------------------------------------------ FmControlData::FmControlData( ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xFormComponent, const ImageList& ilNavigatorImages, FmFormData* pParent ) :FmEntryData( pParent ) ,m_xFormComponent( xFormComponent ) { DBG_CTOR(FmControlData,NULL); ////////////////////////////////////////////////////////////////////// // Images setzen aCollapsedImage = GetImage(ilNavigatorImages); aExpandedImage = GetImage(ilNavigatorImages); ////////////////////////////////////////////////////////////////////// // Titel setzen ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xSet(m_xFormComponent, ::com::sun::star::uno::UNO_QUERY); if( xSet.is() ) { #if DBG_UTIL ::rtl::OUString aEntryName = ::comphelper::getString(xSet->getPropertyValue( FM_PROP_NAME )); #endif SetText( ::comphelper::getString(xSet->getPropertyValue( FM_PROP_NAME ))); } } //------------------------------------------------------------------------ FmControlData::~FmControlData() { DBG_DTOR(FmControlData,NULL); } //------------------------------------------------------------------------ FmControlData::FmControlData( const FmControlData& rControlData ) :FmEntryData( rControlData ) { DBG_CTOR(FmControlData,NULL); m_xFormComponent = rControlData.GetFormComponent(); } //------------------------------------------------------------------------ FmEntryData* FmControlData::Clone() { return new FmControlData( *this ); } //------------------------------------------------------------------------ Image FmControlData::GetImage(const ImageList& ilNavigatorImages) const { ////////////////////////////////////////////////////////////////////// // Default-Image Image aImage = ilNavigatorImages.GetImage( RID_SVXIMG_CONTROL ); if (!m_xFormComponent.is()) return aImage; ::com::sun::star::uno::Reference< ::com::sun::star::lang::XServiceInfo > xInfo(m_xFormComponent, ::com::sun::star::uno::UNO_QUERY); if (!xInfo.is()) return aImage; ////////////////////////////////////////////////////////////////////// // Spezielle Control-Images sal_Int16 nObjectType = getControlTypeByObject(xInfo); switch (nObjectType) { case OBJ_FM_BUTTON: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_BUTTON ); break; case OBJ_FM_FIXEDTEXT: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_FIXEDTEXT ); break; case OBJ_FM_EDIT: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_EDIT ); break; case OBJ_FM_RADIOBUTTON: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_RADIOBUTTON ); break; case OBJ_FM_CHECKBOX: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_CHECKBOX ); break; case OBJ_FM_LISTBOX: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_LISTBOX ); break; case OBJ_FM_COMBOBOX: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_COMBOBOX ); break; case OBJ_FM_GROUPBOX: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_GROUPBOX ); break; case OBJ_FM_IMAGEBUTTON: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_IMAGEBUTTON ); break; case OBJ_FM_FILECONTROL: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_FILECONTROL ); break; case OBJ_FM_HIDDEN: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_HIDDEN ); break; case OBJ_FM_DATEFIELD: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_DATEFIELD ); break; case OBJ_FM_TIMEFIELD: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_TIMEFIELD ); break; case OBJ_FM_NUMERICFIELD: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_NUMERICFIELD ); break; case OBJ_FM_CURRENCYFIELD: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_CURRENCYFIELD ); break; case OBJ_FM_PATTERNFIELD: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_PATTERNFIELD ); break; case OBJ_FM_IMAGECONTROL: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_IMAGECONTROL ); break; case OBJ_FM_FORMATTEDFIELD: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_FORMATTEDFIELD ); break; case OBJ_FM_GRID: aImage = ilNavigatorImages.GetImage( RID_SVXIMG_GRID ); break; } return aImage; } //------------------------------------------------------------------------ sal_Bool FmControlData::IsEqualWithoutChilds( FmEntryData* pEntryData ) { if(this == pEntryData) return sal_True; if( !pEntryData->ISA(FmControlData) ) return sal_False; FmControlData* pControlData = (FmControlData*)pEntryData; if( (::com::sun::star::form::XFormComponent*)m_xFormComponent.get() != (::com::sun::star::form::XFormComponent*)pControlData->GetFormComponent().get() ) return sal_False; return FmEntryData::IsEqualWithoutChilds( pControlData ); } //------------------------------------------------------------------------ void FmControlData::ModelReplaced(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > & xNew, const ImageList& ilNavigatorImages) { m_xFormComponent = xNew; // Images neu setzen aCollapsedImage = aExpandedImage = GetImage(ilNavigatorImages); } //======================================================================== // class FmXExplPropertyChangeList //======================================================================== //------------------------------------------------------------------------ FmXExplPropertyChangeList::FmXExplPropertyChangeList(FmExplorerModel* _pModel) :m_pExplModel(_pModel) ,m_bCanUndo(sal_True) ,m_nLocks(0) { } // ::com::sun::star::beans::XPropertyChangeListener //------------------------------------------------------------------------ void SAL_CALL FmXExplPropertyChangeList::disposing(const ::com::sun::star::lang::EventObject& Source) throw( ::com::sun::star::uno::RuntimeException ) { } //------------------------------------------------------------------------ void SAL_CALL FmXExplPropertyChangeList::propertyChange(const ::com::sun::star::beans::PropertyChangeEvent& evt) { if( !m_pExplModel ) return; if( evt.PropertyName != FM_PROP_NAME ) return; ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xFormComponent(evt.Source, ::com::sun::star::uno::UNO_QUERY); ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xForm(evt.Source, ::com::sun::star::uno::UNO_QUERY); FmEntryData* pEntryData; if( xForm.is() ) pEntryData = m_pExplModel->FindData( xForm, m_pExplModel->GetRootList() ); else if( xFormComponent.is() ) pEntryData = m_pExplModel->FindData( xFormComponent, m_pExplModel->GetRootList() ); if( pEntryData ) { ::rtl::OUString aNewName = ::comphelper::getString(evt.NewValue); pEntryData->SetText( aNewName ); FmExplNameChangedHint aNameChangedHint( pEntryData, aNewName ); m_pExplModel->Broadcast( aNameChangedHint ); } } // ::com::sun::star::container::XContainerListener //------------------------------------------------------------------------------ void SAL_CALL FmXExplPropertyChangeList::elementInserted(const ::com::sun::star::container::ContainerEvent& evt) { if (IsLocked() || !m_pExplModel) return; // keine Undoaction einfuegen m_bCanUndo = sal_False; ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xTemp; evt.Element >>= xTemp; Insert(xTemp, ::comphelper::getINT32(evt.Accessor)); m_bCanUndo = sal_True; } //------------------------------------------------------------------------------ void FmXExplPropertyChangeList::Insert(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > & xIface, sal_Int32 nIndex) { ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xForm(xIface, ::com::sun::star::uno::UNO_QUERY); if (xForm.is()) { m_pExplModel->InsertForm(xForm, sal_uInt32(nIndex)); ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > xContainer(xForm, ::com::sun::star::uno::UNO_QUERY); ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xTemp; for (sal_Int32 i = 0; i < xContainer->getCount(); i++) { xContainer->getByIndex(i) >>= xTemp; Insert(xTemp, i); } } else { ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xFormComp(xIface, ::com::sun::star::uno::UNO_QUERY); if (xFormComp.is()) m_pExplModel->InsertFormComponent(xFormComp, sal_uInt32(nIndex)); } } //------------------------------------------------------------------------------ void SAL_CALL FmXExplPropertyChangeList::elementReplaced(const ::com::sun::star::container::ContainerEvent& evt) { if (IsLocked() || !m_pExplModel) return; m_bCanUndo = sal_False; // EntryData loeschen ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xReplaced; evt.ReplacedElement >>= xReplaced; FmEntryData* pEntryData = m_pExplModel->FindData(xReplaced, m_pExplModel->GetRootList(), sal_True); if (pEntryData) { if (pEntryData->ISA(FmControlData)) { ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xComp; evt.Element >>= xComp; DBG_ASSERT(xComp.is(), "FmXExplPropertyChangeList::elementReplaced : invalid argument !"); // an einer FmControlData sollte eine ::com::sun::star::form::XFormComponent haengen m_pExplModel->ReplaceFormComponent(xReplaced, xComp); } else if (pEntryData->ISA(FmFormData)) { DBG_ERROR("replacing forms not implemented yet !"); } } m_bCanUndo = sal_True; } //------------------------------------------------------------------------------ void SAL_CALL FmXExplPropertyChangeList::elementRemoved(const ::com::sun::star::container::ContainerEvent& evt) { if (IsLocked() || !m_pExplModel) return; m_bCanUndo = sal_False; ////////////////////////////////////////////////////////// // EntryData loeschen ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xTemp; evt.Element >>= xTemp; FmEntryData* pEntryData = m_pExplModel->FindData(xTemp, m_pExplModel->GetRootList(), sal_True); if (pEntryData) m_pExplModel->Remove(pEntryData); m_bCanUndo = sal_True; } //======================================================================== // class FmExplorerModel //======================================================================== //------------------------------------------------------------------------ FmExplorerModel::FmExplorerModel(const ImageList& ilNavigatorImages) :m_pFormShell(NULL) ,m_pFormPage(NULL) ,m_pFormModel(NULL) ,m_ilNavigatorImages(ilNavigatorImages) { m_pPropChangeList = new FmXExplPropertyChangeList(this); m_pPropChangeList->acquire(); m_pRootList = new FmEntryDataList(); } //------------------------------------------------------------------------ FmExplorerModel::~FmExplorerModel() { ////////////////////////////////////////////////////////////////////// // Als Listener abmelden if( m_pFormShell) { FmFormModel* pFormModel = m_pFormShell->GetFormModel(); if( pFormModel && IsListening(*pFormModel)) EndListening( *pFormModel ); if (IsListening(*m_pFormShell)) EndListening(*m_pFormShell); } Clear(); delete m_pRootList; m_pPropChangeList->ReleaseModel(); m_pPropChangeList->release(); } //------------------------------------------------------------------------ void FmExplorerModel::SetModified( sal_Bool bMod ) { if( !m_pFormShell ) return; SfxObjectShell* pObjShell = m_pFormShell->GetFormModel()->GetObjectShell(); if( !pObjShell ) return; pObjShell->SetModified( bMod ); } //------------------------------------------------------------------------ void FmExplorerModel::Clear() { ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > xForms( GetForms()); ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainer > xContainer(xForms, ::com::sun::star::uno::UNO_QUERY); if (xContainer.is()) xContainer->removeContainerListener((::com::sun::star::container::XContainerListener*)m_pPropChangeList); ////////////////////////////////////////////////////////////////////// // RootList loeschen FmEntryData* pChildData; FmEntryDataList* pRootList = GetRootList(); for( sal_uInt32 i=pRootList->Count(); i>0; i-- ) { pChildData = pRootList->GetObject(i-1); pRootList->Remove( pChildData ); delete pChildData; } ////////////////////////////////////////////////////////////////////// // UI benachrichtigen FmExplClearedHint aClearedHint; Broadcast( aClearedHint ); } //------------------------------------------------------------------------ ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > FmExplorerModel::GetForms() const { if( !m_pFormShell || !m_pFormShell->GetCurPage()) return NULL; else return m_pFormShell->GetCurPage()->GetForms(); } //------------------------------------------------------------------------ void FmExplorerModel::Insert(FmEntryData* pEntry, sal_uInt32 nRelPos, sal_Bool bAlterModel) { if (IsListening(*m_pFormModel)) EndListening(*m_pFormModel); m_pPropChangeList->Lock(); FmFormData* pFolder = (FmFormData*) pEntry->GetParent(); ::com::sun::star::uno::Reference< ::com::sun::star::container::XChild > xElement (pEntry->GetElement(), ::com::sun::star::uno::UNO_QUERY); if (bAlterModel) { XubString aStr; if (pEntry->ISA(FmFormData)) aStr = SVX_RES(RID_STR_FORM); else aStr = SVX_RES(RID_STR_CONTROL); ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > xContainer; if (pFolder) xContainer = ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > (pFolder->GetFormIface(), ::com::sun::star::uno::UNO_QUERY); else xContainer = ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > (GetForms(), ::com::sun::star::uno::UNO_QUERY); XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_INSERT)); aUndoStr.SearchAndReplace('#', aStr); m_pFormModel->BegUndo(aUndoStr); if (nRelPos >= (sal_uInt32)xContainer->getCount()) nRelPos = (sal_uInt32)xContainer->getCount(); // UndoAction if (m_pPropChangeList->CanUndo()) m_pFormModel->AddUndo(new FmUndoContainerAction(*m_pFormModel, FmUndoContainerAction::Inserted, xContainer, xElement, nRelPos)); // das Element muss den Typ haben, den der ::com::sun::star::sdbcx::Container erwartet if (xContainer->getElementType() == ::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm>*)0)) { ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xElementAsForm(xElement, ::com::sun::star::uno::UNO_QUERY); xContainer->insertByIndex(nRelPos, ::com::sun::star::uno::makeAny(xElementAsForm)); } else if (xContainer->getElementType() == ::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent>*)0)) { ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xElementAsComponent(xElement, ::com::sun::star::uno::UNO_QUERY); xContainer->insertByIndex(nRelPos, ::com::sun::star::uno::makeAny(xElementAsComponent)); } else { DBG_ERROR("FmExplorerModel::Insert : the parent container needs an elementtype I don't know !"); } m_pFormModel->EndUndo(); } ////////////////////////////////////////////////////////////////////// // Als PropertyChangeListener anmelden ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xSet(xElement, ::com::sun::star::uno::UNO_QUERY); if( xSet.is() ) xSet->addPropertyChangeListener( FM_PROP_NAME, m_pPropChangeList ); ////////////////////////////////////////////////////////////////////// // Daten aus Model entfernen if (pEntry->ISA(FmFormData)) { ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainer > xContainer(xElement, ::com::sun::star::uno::UNO_QUERY); if (xContainer.is()) xContainer->addContainerListener((::com::sun::star::container::XContainerListener*)m_pPropChangeList); } if (pFolder) pFolder->GetChildList()->Insert( pEntry, nRelPos ); else GetRootList()->Insert( pEntry, nRelPos ); ////////////////////////////////////////////////////////////////////// // UI benachrichtigen FmExplInsertedHint aInsertedHint( pEntry, nRelPos ); Broadcast( aInsertedHint ); m_pPropChangeList->UnLock(); if (IsListening(*m_pFormModel)) StartListening(*m_pFormModel); } //------------------------------------------------------------------------ void FmExplorerModel::Remove(FmEntryData* pEntry, sal_Bool bAlterModel) { ////////////////////////////////////////////////////////////////////// // ::com::sun::star::form::Form und Parent holen if (!pEntry || !m_pFormModel) return; if (IsListening(*m_pFormModel)) EndListening(*m_pFormModel); m_pPropChangeList->Lock(); FmFormData* pFolder = (FmFormData*) pEntry->GetParent(); ::com::sun::star::uno::Reference< ::com::sun::star::container::XChild > xElement (pEntry->GetElement(), ::com::sun::star::uno::UNO_QUERY); if (bAlterModel) { XubString aStr; if (pEntry->ISA(FmFormData)) aStr = SVX_RES(RID_STR_FORM); else aStr = SVX_RES(RID_STR_CONTROL); XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_REMOVE)); aUndoStr.SearchAndReplace('#', aStr); m_pFormModel->BegUndo(aUndoStr); } // jetzt die eigentliche Entfernung der Daten aus dem Model if (pEntry->ISA(FmFormData)) RemoveForm((FmFormData*)pEntry); else RemoveFormComponent((FmControlData*)pEntry); if (bAlterModel) { ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > xContainer(xElement->getParent(), ::com::sun::star::uno::UNO_QUERY); // aus dem ::com::sun::star::sdbcx::Container entfernen sal_Int32 nContainerIndex = getElementPos(::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > (xContainer, ::com::sun::star::uno::UNO_QUERY), xElement); // UndoAction if (nContainerIndex >= 0) { if (m_pPropChangeList->CanUndo()) m_pFormModel->AddUndo(new FmUndoContainerAction(*m_pFormModel, FmUndoContainerAction::Removed, xContainer, xElement, nContainerIndex )); xContainer->removeByIndex(nContainerIndex ); } m_pFormModel->EndUndo(); } // beim Vater austragen if (pFolder) pFolder->GetChildList()->Remove(pEntry); else { GetRootList()->Remove(pEntry); ////////////////////////////////////////////////////////////////////// // Wenn keine ::com::sun::star::form::Form mehr in der Root, an der Shell CurForm zuruecksetzen if (!GetRootList()->Count()) m_pFormShell->GetImpl()->setCurForm( ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > () ); } ////////////////////////////////////////////////////////////////////// // UI benachrichtigen FmExplRemovedHint aRemovedHint( pEntry ); Broadcast( aRemovedHint ); // Eintrag loeschen delete pEntry; m_pPropChangeList->UnLock(); StartListening(*m_pFormModel); } //------------------------------------------------------------------------ void FmExplorerModel::RemoveForm(FmFormData* pFormData) { ////////////////////////////////////////////////////////////////////// // ::com::sun::star::form::Form und Parent holen if (!pFormData || !m_pFormModel) return; FmEntryDataList* pChildList = pFormData->GetChildList(); sal_uInt32 nCount = pChildList->Count(); for (sal_uInt32 i = nCount; i > 0; i--) { FmEntryData* pEntryData = pChildList->GetObject(i - 1); ////////////////////////////////////////////////////////////////////// // Child ist ::com::sun::star::form::Form -> rekursiver Aufruf if( pEntryData->ISA(FmFormData) ) RemoveForm( (FmFormData*)pEntryData); else if( pEntryData->ISA(FmControlData) ) RemoveFormComponent((FmControlData*) pEntryData); } ////////////////////////////////////////////////////////////////////// // Als PropertyChangeListener abmelden ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xSet(pFormData->GetFormIface(), ::com::sun::star::uno::UNO_QUERY); if( xSet.is() ) xSet->removePropertyChangeListener( FM_PROP_NAME, m_pPropChangeList ); ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainer > xContainer(xSet, ::com::sun::star::uno::UNO_QUERY); if (xContainer.is()) xContainer->removeContainerListener((::com::sun::star::container::XContainerListener*)m_pPropChangeList); } //------------------------------------------------------------------------ void FmExplorerModel::RemoveFormComponent(FmControlData* pControlData) { ////////////////////////////////////////////////////////////////////// // Control und Parent holen if (!pControlData) return; ////////////////////////////////////////////////////////////////////// // Als PropertyChangeListener abmelden ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xSet(pControlData->GetElement(), ::com::sun::star::uno::UNO_QUERY); if (xSet.is()) xSet->removePropertyChangeListener( FM_PROP_NAME, m_pPropChangeList); } //------------------------------------------------------------------------ void FmExplorerModel::ClearBranch( FmFormData* pParentData ) { ////////////////////////////////////////////////////////////////////// // Alle Eintraege dieses Zweiges loeschen FmEntryDataList* pChildList = pParentData->GetChildList(); FmEntryData* pChildData; for( sal_uInt32 i=pChildList->Count(); i>0; i-- ) { pChildData = pChildList->GetObject(i-1); if( pChildData->ISA(FmFormData) ) ClearBranch( (FmFormData*)pChildData ); pChildList->Remove( pChildData ); } } //------------------------------------------------------------------------ void FmExplorerModel::FillBranch( FmFormData* pFormData ) { ////////////////////////////////////////////////////////////// // ::com::sun::star::form::Forms aus der Root einfuegen if( pFormData == NULL ) { ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > xForms(GetForms(), ::com::sun::star::uno::UNO_QUERY); if (!xForms.is()) return; ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xSubForm; FmFormData* pSubFormData; for (sal_Int32 i=0; igetCount(); ++i) { DBG_ASSERT(xForms->getByIndex(i).getValueType() == ::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm>*)0), "FmExplorerModel::FillBranch : the root container should supply only elements of type XForm"); xForms->getByIndex(i) >>= xSubForm; pSubFormData = new FmFormData( xSubForm, m_ilNavigatorImages, pFormData ); Insert( pSubFormData, LIST_APPEND ); ////////////////////////////////////////////////////////////// // Neuer Branch, wenn SubForm wiederum Subforms enthaelt FillBranch( pSubFormData ); } } ////////////////////////////////////////////////////////////// // Componenten einfuegen else { ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > xComponents( GetFormComponents(pFormData)); if( !xComponents.is() ) return; ::rtl::OUString aControlName; ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xInterface; ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xSet; FmControlData* pNewControlData; FmFormData* pSubFormData; ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xCurrentComponent; for (sal_Int32 j=0; jgetCount(); ++j) { xComponents->getByIndex(j) >>= xCurrentComponent; ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xSubForm(xCurrentComponent, ::com::sun::star::uno::UNO_QUERY); if (xSubForm.is()) { // die aktuelle Component ist eine ::com::sun::star::form::Form pSubFormData = new FmFormData(xSubForm, m_ilNavigatorImages, pFormData); Insert(pSubFormData, LIST_APPEND); ////////////////////////////////////////////////////////////// // Neuer Branch, wenn SubForm wiederum Subforms enthaelt FillBranch(pSubFormData); } else { pNewControlData = new FmControlData(xCurrentComponent, m_ilNavigatorImages, pFormData); Insert(pNewControlData, LIST_APPEND); } } } } //------------------------------------------------------------------------ void FmExplorerModel::InsertForm(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > & xForm, sal_uInt32 nRelPos) { FmFormData* pFormData = (FmFormData*)FindData( xForm, GetRootList() ); if (pFormData) return; ////////////////////////////////////////////////////////// // ParentData setzen ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xIFace( xForm->getParent()); ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xParentForm(xIFace, ::com::sun::star::uno::UNO_QUERY); FmFormData* pParentData = NULL; if (xParentForm.is()) pParentData = (FmFormData*)FindData( xParentForm, GetRootList() ); pFormData = new FmFormData( xForm, m_ilNavigatorImages, pParentData ); Insert( pFormData, nRelPos ); } //------------------------------------------------------------------------ void FmExplorerModel::InsertFormComponent(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > & xComp, sal_uInt32 nRelPos) { ////////////////////////////////////////////////////////// // ParentData setzen ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xIFace( xComp->getParent()); ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xForm(xIFace, ::com::sun::star::uno::UNO_QUERY); if (!xForm.is()) return; FmFormData* pParentData = (FmFormData*)FindData( xForm, GetRootList() ); if( !pParentData ) { pParentData = new FmFormData( xForm, m_ilNavigatorImages, NULL ); Insert( pParentData, LIST_APPEND ); } if (!FindData(xComp, pParentData->GetChildList(),sal_False)) { ////////////////////////////////////////////////////////// // Neue EntryData setzen FmEntryData* pNewEntryData = new FmControlData( xComp, m_ilNavigatorImages, pParentData ); ////////////////////////////////////////////////////////// // Neue EntryData einfuegen Insert( pNewEntryData, nRelPos ); } } //------------------------------------------------------------------------ void FmExplorerModel::ReplaceFormComponent(const ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > & xOld, const ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > & xNew) { FmEntryData* pData = FindData(xOld, GetRootList(), sal_True); DBG_ASSERT(pData && pData->ISA(FmControlData), "FmExplorerModel::ReplaceFormComponent : invalid argument !"); ((FmControlData*)pData)->ModelReplaced(xNew, m_ilNavigatorImages); FmExplModelReplacedHint aReplacedHint( pData ); Broadcast( aReplacedHint ); } //------------------------------------------------------------------------ FmEntryData* FmExplorerModel::FindData(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > & xElement, FmEntryDataList* pDataList, sal_Bool bRecurs) { for (sal_uInt16 i=0; i < pDataList->Count(); i++) { FmEntryData* pEntryData = pDataList->GetObject(i); if (pEntryData->GetElement() == xElement) // zu beachten : das == fuer ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > macht einen 'tiefen' Vergleich, liefert also sal_True, wenn die beiden Refs das // selbe Objekt bezeichnen, egal ob die auf die selben Interfaces zeigen return pEntryData; else if (bRecurs) { pEntryData = FindData( xElement, pEntryData->GetChildList() ); if (pEntryData) return pEntryData; } } return NULL; } //------------------------------------------------------------------------ FmEntryData* FmExplorerModel::FindData( const ::rtl::OUString& rText, FmFormData* pParentData, sal_Bool bRecurs ) { FmEntryDataList* pDataList; if( !pParentData ) pDataList = GetRootList(); else pDataList = pParentData->GetChildList(); ::rtl::OUString aEntryText; FmEntryData* pEntryData; FmEntryData* pChildData; for( sal_uInt16 i=0; iCount(); i++ ) { pEntryData = pDataList->GetObject(i); aEntryText = pEntryData->GetText(); if (rText == aEntryText) return pEntryData; if( bRecurs && pEntryData->ISA(FmFormData) ) { pChildData = FindData( rText, (FmFormData*)pEntryData ); if( pChildData ) return pChildData; } } return NULL; } //------------------------------------------------------------------------ void FmExplorerModel::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) { if( rHint.ISA(SdrHint) ) { SdrHint* pSdrHint = (SdrHint*)&rHint; switch( pSdrHint->GetKind() ) { case HINT_OBJINSERTED: InsertSdrObj(pSdrHint->GetObject()); break; case HINT_OBJREMOVED: RemoveSdrObj(pSdrHint->GetObject()); break; } } // hat sich die shell verabschiedet? else if ( rHint.ISA(SfxSimpleHint) && ((SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING) Update((FmFormShell*)NULL); // hat sich die Markierung der Controls veraendert ? else if (rHint.ISA(FmExplViewMarksChanged)) { FmExplViewMarksChanged* pvmcHint = (FmExplViewMarksChanged*)&rHint; BroadcastMarkedObjects( pvmcHint->GetAffectedView()->GetMarkList() ); } } //------------------------------------------------------------------------ void FmExplorerModel::InsertSdrObj(const SdrObject* pObj) { if (pObj->GetObjInventor() == FmFormInventor) { ////////////////////////////////////////////////////////////////////// // Ist dieses Objekt ein ::com::sun::star::form::XFormComponent? ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xFormComponent(((SdrUnoObj*)pObj)->GetUnoControlModel(), ::com::sun::star::uno::UNO_QUERY); if (xFormComponent.is()) { ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > xContainer(xFormComponent->getParent(), ::com::sun::star::uno::UNO_QUERY); if (xContainer.is()) { sal_Int32 nPos = getElementPos(::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > (xContainer, ::com::sun::star::uno::UNO_QUERY), xFormComponent); InsertFormComponent(xFormComponent, nPos); } } } else if (pObj->IsGroupObject()) { SdrObjListIter aIter(*pObj->GetSubList()); while (aIter.IsMore()) InsertSdrObj(aIter.Next()); } } //------------------------------------------------------------------------ void FmExplorerModel::RemoveSdrObj(const SdrObject* pObj) { if (pObj->GetObjInventor() == FmFormInventor) { ////////////////////////////////////////////////////////////////////// // Ist dieses Objekt ein ::com::sun::star::form::XFormComponent? ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xFormComponent(((SdrUnoObj*)pObj)->GetUnoControlModel(), ::com::sun::star::uno::UNO_QUERY); if (xFormComponent.is()) { FmEntryData* pEntryData = FindData(xFormComponent, GetRootList(), sal_True); if (pEntryData) Remove(pEntryData); } } else if (pObj->IsGroupObject()) { SdrObjListIter aIter(*pObj->GetSubList()); while (aIter.IsMore()) RemoveSdrObj(aIter.Next()); } } sal_Bool FmExplorerModel::InsertFormComponent(FmExplRequestSelectHint& rHint, SdrObject* pObject) { if ( pObject->ISA(SdrObjGroup) ) { // rekursiv absteigen const SdrObjList *pChilds = ((SdrObjGroup*)pObject)->GetSubList(); for ( sal_uInt16 i=0; iGetObjCount(); ++i ) { SdrObject* pCurrent = pChilds->GetObj(i); if (!InsertFormComponent(rHint, pCurrent)) return sal_False; } } else if (pObject->IsUnoObj()) { ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xControlModel( ((SdrUnoObj*)pObject)->GetUnoControlModel()); // Ist dieses Objekt ein ::com::sun::star::form::XFormComponent? ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xFormViewControl(xControlModel, ::com::sun::star::uno::UNO_QUERY); if (xFormViewControl.is()) { // es ist ein ::com::sun::star::form::Form-Control -> selektieren lassen FmEntryData* pControlData = FindData( xFormViewControl, GetRootList() ); if (pControlData) rHint.AddItem( pControlData ); } else { // es ist kein ::com::sun::star::form::Form-Control -> im Baum ueberhaupt nix selektieren lassen return sal_False; } } else return sal_False; return sal_True; } void FmExplorerModel::BroadcastMarkedObjects(const SdrMarkList& mlMarked) { // gehen wir durch alle markierten Objekte und suchen wir die raus, mit denen ich was anfangen kann FmExplRequestSelectHint rshRequestSelection; sal_Bool bIsMixedSelection = sal_False; for (ULONG i=0; (iGetObj(); bIsMixedSelection |= !InsertFormComponent(rshRequestSelection, pobjCurrent); // bei einem Nicht-::com::sun::star::form::Form-Control liefert InsertFormComponent sal_False ! } rshRequestSelection.SetMixedSelection(bIsMixedSelection); if (bIsMixedSelection) rshRequestSelection.ClearItems(); Broadcast(rshRequestSelection); // eine leere Liste interpretiert der FmExplorer so, dass er seine Selektion komplett rausnimmt } //------------------------------------------------------------------------ void FmExplorerModel::Update( const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > & xForms ) { ////////////////////////////////////////////////////////////////////// // Model von der Root aufwaerts neu fuellen Clear(); if (xForms.is()) { ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainer > xFormContainer(xForms, ::com::sun::star::uno::UNO_QUERY); if (xFormContainer.is()) xFormContainer->addContainerListener((::com::sun::star::container::XContainerListener*)m_pPropChangeList); FillBranch(NULL); // jetzt in meinem Tree genau die das in meiner ::com::sun::star::sdbcx::View markierte Control selektieren // (bzw alle solchen), falls es eines gibt ... if(!m_pFormShell) return; // keine Shell -> wech FmFormView* pFormView = m_pFormShell->GetFormView(); DBG_ASSERT(pFormView != NULL, "FmExplorerModel::Update : keine FormView"); BroadcastMarkedObjects(pFormView->GetMarkList()); } } //------------------------------------------------------------------------ void FmExplorerModel::Update( FmFormShell* pShell ) { ////////////////////////////////////////////////////////////////////// // Wenn Shell sich nicht veraendert hat, nichts machen FmFormPage* pNewPage = pShell ? pShell->GetCurPage() : NULL; if ((pShell == m_pFormShell) && (m_pFormPage == pNewPage)) return; ////////////////////////////////////////////////////////////////////// // Als Listener abmelden if( m_pFormShell ) { if (m_pFormModel) EndListening( *m_pFormModel ); m_pFormModel = NULL; EndListening( *m_pFormShell ); Clear(); } ////////////////////////////////////////////////////////////////////// // Vollupdate m_pFormShell = pShell; if (m_pFormShell) { m_pFormPage = pNewPage; Update(m_pFormPage->GetForms()); } else m_pFormPage = NULL; ////////////////////////////////////////////////////////////////////// // Als Listener neu anmelden if( m_pFormShell ) { StartListening( *m_pFormShell ); m_pFormModel = m_pFormShell->GetFormModel(); if( m_pFormModel ) StartListening( *m_pFormModel ); } } //------------------------------------------------------------------------ ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > FmExplorerModel::GetFormComponents( FmFormData* pFormData ) { ////////////////////////////////////////////////////////////////////// // Von der ::com::sun::star::form::Form ::com::sun::star::frame::Components holen if (pFormData) return ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > (pFormData->GetFormIface(), ::com::sun::star::uno::UNO_QUERY); return ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > (); } //------------------------------------------------------------------------ sal_Bool FmExplorerModel::CheckEntry( FmEntryData* pEntryData ) { ////////////////////////////////////////////////////////////////////// // Nur ::com::sun::star::form::Forms duerfen auf Doppeldeutigkeit untersucht werden if( !pEntryData->ISA(FmFormData) ) return sal_True; ////////////////////////////////////////////////////////////////////// // ChildListe des Parents holen FmFormData* pParentData = (FmFormData*)pEntryData->GetParent(); FmEntryDataList* pChildList; if( !pParentData ) pChildList = GetRootList(); else pChildList = pParentData->GetChildList(); ////////////////////////////////////////////////////////////////////// // In ChildListe nach doppelten Namen suchen ::rtl::OUString aChildText; FmEntryData* pChildData; for( sal_uInt16 i=0; iCount(); i++ ) { pChildData = pChildList->GetObject(i); aChildText = pChildData->GetText(); ////////////////////////////////////////////////////////////////////// // Gleichen Eintrag gefunden if ( (aChildText == pEntryData->GetText()) && (pEntryData!=pChildData) ) { SvxDBMsgBox aErrorBox( GetpApp()->GetAppWindow(), SVX_RES(RID_ERR_CONTEXT_ADDFORM), SVX_RES(RID_ERR_DUPLICATE_NAME), WB_OK | WB_DEF_OK, SvxDBMsgBox::Error ); aErrorBox.Execute(); return sal_False; } } return sal_True; } //------------------------------------------------------------------------ sal_Bool FmExplorerModel::Rename( FmEntryData* pEntryData, const ::rtl::OUString& rNewText ) { ////////////////////////////////////////////////////////////////////// // Wenn Name schon vorhanden, Fehlermeldung pEntryData->SetText( rNewText ); ////////////////////////////////////////////////////////////////////// // PropertySet besorgen ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xFormComponent; if( pEntryData->ISA(FmFormData) ) { FmFormData* pFormData = (FmFormData*)pEntryData; ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xForm( pFormData->GetFormIface()); xFormComponent = ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > (xForm, ::com::sun::star::uno::UNO_QUERY); } if( pEntryData->ISA(FmControlData) ) { FmControlData* pControlData = (FmControlData*)pEntryData; xFormComponent = pControlData->GetFormComponent(); } if( !xFormComponent.is() ) return sal_False; ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xSet(xFormComponent, ::com::sun::star::uno::UNO_QUERY); if( !xSet.is() ) return sal_False; ////////////////////////////////////////////////////////////////////// // Namen setzen xSet->setPropertyValue( FM_PROP_NAME, ::com::sun::star::uno::makeAny(rNewText) ); return sal_True; } //------------------------------------------------------------------------ sal_Bool FmExplorerModel::IsNameAlreadyDefined( const ::rtl::OUString& rName, FmFormData* pParentData ) { ////////////////////////////////////////////////////////////////////// // ::com::sun::star::form::Form in der Root if( !pParentData ) { if (GetForms()->hasByName(rName)) return sal_True; } ////////////////////////////////////////////////////////////////////// // Restliche ::com::sun::star::frame::Components else { ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > xFormComponents(GetFormComponents(pParentData), ::com::sun::star::uno::UNO_QUERY); if (xFormComponents.is() && xFormComponents->hasByName(rName)) return sal_True; } return sal_False; } //------------------------------------------------------------------------ SdrObject* FmExplorerModel::GetSdrObj( FmControlData* pControlData ) { if (!pControlData || !m_pFormShell) return NULL; ////////////////////////////////////////////////////////////////////// // In der Page das entsprechende SdrObj finden und selektieren ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xFormComponent( pControlData->GetFormComponent()); if (!xFormComponent.is()) return NULL; FmFormView* pFormView = m_pFormShell->GetFormView(); SdrPageView* pPageView = pFormView->GetPageViewPvNum(0); SdrPage* pPage = pPageView->GetPage(); SdrObjListIter aIter( *pPage ); return Search(aIter, xFormComponent); } //------------------------------------------------------------------ SdrObject* FmExplorerModel::Search(SdrObjListIter& rIter, const ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > & xComp) { while (rIter.IsMore()) { SdrObject* pObj = rIter.Next(); ////////////////////////////////////////////////////////////////////// // Es interessieren nur Uno-Objekte if (pObj->GetObjInventor() == FmFormInventor) { ////////////////////////////////////////////////////////////////////// // Ist dieses Objekt ein ::com::sun::star::form::XFormComponent? ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xFormViewControl(((SdrUnoObj*)pObj)->GetUnoControlModel(), ::com::sun::star::uno::UNO_QUERY); if (xFormViewControl == xComp) return pObj; } else if (pObj->IsGroupObject()) { SdrObjListIter aIter(*pObj->GetSubList()); pObj = Search(aIter, xComp); if (pObj) return pObj; } } return NULL; } //======================================================================== // class FmExplorer //======================================================================== //------------------------------------------------------------------------ FmExplorer::FmExplorer( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xORB, Window* pParent ) :SvTreeListBox( pParent, WB_HASBUTTONS|WB_HASLINES|WB_BORDER ) ,m_aControlExchange(this) ,nEditEvent(0) ,m_pEditEntry(NULL) ,m_nSelectLock(0) ,m_aTimerTriggered(-1,-1) ,m_ilNavigatorImages( SVX_RES(RID_SVXIMGLIST_FMEXPL) ) ,m_bRootSelected(sal_False) ,m_nFormsSelected(0) ,m_nControlsSelected(0) ,m_nHiddenControls(0) ,m_bPrevSelectionMixed(sal_False) ,m_bInitialUpdate(sal_True) ,m_bMarkingObjects(sal_False) ,m_sdiState(SDI_DIRTY) ,m_bShellOrPageChanged(sal_False) ,m_bDragDataDirty(sal_False) ,m_pRootEntry(NULL) ,m_xORB(_xORB) { SetHelpId( HID_FORM_NAVIGATOR ); m_aRootImg = m_ilNavigatorImages.GetImage( RID_SVXIMG_FORMS ); Image m_aCollapsedNodeImg = m_ilNavigatorImages.GetImage( RID_SVXIMG_COLLAPSEDNODE ); Image m_aExpandedNodeImg = m_ilNavigatorImages.GetImage( RID_SVXIMG_EXPANDEDNODE ); SetNodeBitmaps( m_aCollapsedNodeImg, m_aExpandedNodeImg ); #ifndef TF_SVDATA EnableDrop(); #endif //TF_SVDATA SetDragDropMode(0xFFFF); EnableInplaceEditing( sal_True ); SetSelectionMode(MULTIPLE_SELECTION); m_pExplModel = new FmExplorerModel(m_ilNavigatorImages); Clear(); StartListening( *m_pExplModel ); m_aDropActionTimer.SetTimeoutHdl(LINK(this, FmExplorer, OnDropActionTimer)); m_aSynchronizeTimer.SetTimeoutHdl(LINK(this, FmExplorer, OnSynchronizeTimer)); SetSelectHdl(LINK(this, FmExplorer, OnEntrySelDesel)); SetDeselectHdl(LINK(this, FmExplorer, OnEntrySelDesel)); } //------------------------------------------------------------------------ FmExplorer::~FmExplorer() { if( nEditEvent ) Application::RemoveUserEvent( nEditEvent ); if (m_aSynchronizeTimer.IsActive()) m_aSynchronizeTimer.Stop(); DBG_ASSERT(GetExplModel() != NULL, "FmExplorer::~FmExplorer : unerwartet : kein ExplorerModel"); EndListening( *m_pExplModel ); Clear(); delete m_pExplModel; } //------------------------------------------------------------------------ void FmExplorer::Clear() { m_pExplModel->Clear(); } //------------------------------------------------------------------------ void FmExplorer::Update( FmFormShell* pFormShell ) { if (m_bInitialUpdate) { GrabFocus(); m_bInitialUpdate = sal_False; } FmFormShell* pOldShell = GetExplModel()->GetFormShell(); FmFormPage* pOldPage = GetExplModel()->GetFormPage(); FmFormPage* pNewPage = pFormShell ? pFormShell->GetCurPage() : NULL; if ((pOldShell != pFormShell) || (pOldPage != pNewPage)) { // neue Shell, waehrend ich gerade editiere ? if (IsEditingActive()) CancelTextEditing(); m_bShellOrPageChanged = sal_True; m_bDragDataDirty = sal_True; // sicherheitshalber, auch wenn ich gar nicht dragge } GetExplModel()->Update( pFormShell ); // wenn es eine ::com::sun::star::form::Form gibt, die Root expandieren if (m_pRootEntry && !IsExpanded(m_pRootEntry)) Expand(m_pRootEntry); // wenn es GENAU eine ::com::sun::star::form::Form gibt, auch diese expandieren if (m_pRootEntry) { SvLBoxEntry* pFirst = FirstChild(m_pRootEntry); if (pFirst && !NextSibling(pFirst)) Expand(pFirst); } } //------------------------------------------------------------------------------ void FmExplorer::StartDrag( sal_Int8 nAction, const Point& rPosPixel ) { EndSelection(); SvLBoxEntry* pCurEntry = GetCurEntry(); if (!pCurEntry) return; m_aControlExchange.prepareDrag(); m_aControlExchange->setFocusEntry( pCurEntry ); // die Informationen fuer das AcceptDrop und ExecuteDrop CollectSelectionData(SDI_ALL); if (!m_arrCurrentSelection.Count()) // nothing to do return; for (sal_Int32 i=0; iaddSelectedEntry(m_arrCurrentSelection[i]); m_aControlExchange->setShellAndPage( GetExplModel()->GetFormShell(), GetExplModel()->GetFormPage() ); m_aControlExchange->buildPathFormat(this, m_pRootEntry); // testen, ob es sich vielleicht ausschliesslich um hidden controls handelt (dann koennte ich pCtrlExch noch ein // zusaetzliches Format geben) sal_Bool bHasNonHidden = sal_False; for (i=0; iGetUserData()); if (IsHiddenControl(pCurrent)) continue; bHasNonHidden = sal_True; break; } if (!bHasNonHidden) { // eine entsprechende Sequenz aufbauen ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > > seqIFaces(m_arrCurrentSelection.Count()); ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > * pArray = seqIFaces.getArray(); for (i=0; iGetUserData()))->GetElement(); // und das neue Format m_aControlExchange->addHiddenControlsFormat(seqIFaces); } // jetzt haben wir alle in der aktuelle Situation moeglichen Formate eingesammelt, es kann also losgehen ... m_bShellOrPageChanged = m_bDragDataDirty = sal_False; m_aControlExchange.startDrag( DND_ACTION_COPYMOVE ); } //------------------------------------------------------------------------------ void FmExplorer::Command( const CommandEvent& rEvt ) { sal_Bool bHandled = sal_False; switch( rEvt.GetCommand() ) { case COMMAND_CONTEXTMENU: { // die Stelle, an der geklickt wurde Point ptWhere; if (rEvt.IsMouseEvent()) { ptWhere = rEvt.GetMousePosPixel(); SvLBoxEntry* ptClickedOn = GetEntry(ptWhere); if (ptClickedOn == NULL) break; if ( !IsSelected(ptClickedOn) ) { SelectAll(sal_False); Select(ptClickedOn, sal_True); SetCurEntry(ptClickedOn); } } else { if (m_arrCurrentSelection.Count() == 0) // kann nur bei Kontextmenue ueber Tastatur passieren break; SvLBoxEntry* pCurrent = GetCurEntry(); if (!pCurrent) break; ptWhere = GetEntryPos(pCurrent); } // meine Selektionsdaten auf den aktuellen Stand CollectSelectionData(SDI_ALL); // wenn mindestens ein Nicht-Root-Eintrag selektiert ist und die Root auch, dann nehme ich letztere aus der Selektion // fix wieder raus if ( (m_arrCurrentSelection.Count() > 1) && m_bRootSelected ) { Select( m_pRootEntry, sal_False ); SetCursor( m_arrCurrentSelection.GetObject(0), sal_True); } sal_Bool bSingleSelection = (m_arrCurrentSelection.Count() == 1); DBG_ASSERT( (m_arrCurrentSelection.Count() > 0) | m_bRootSelected, "keine Eintraege selektiert" ); // solte nicht passieren, da ich oben bei der IsSelected-Abfrage auf jeden Fall einen selektiert haette, // wenn das vorher nicht der Fall gewesen waere // das Menue zusammenbasteln FmFormShell* pFormShell = GetExplModel()->GetFormShell(); FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : NULL; if( pFormShell && pFormModel ) { PopupMenu aContextMenu(SVX_RES(RID_FMEXPLORER_POPUPMENU)); PopupMenu* pSubMenuNew = aContextMenu.GetPopupMenu( SID_FM_NEW ); // das 'Neu'-Untermenue gibt es nur, wenn genau die Root oder genau ein Formular selektiert sind aContextMenu.EnableItem( SID_FM_NEW, bSingleSelection && (m_nFormsSelected || m_bRootSelected) ); // 'Neu'\'Formular' unter genau den selben Bedingungen pSubMenuNew->EnableItem( SID_FM_NEW_FORM, bSingleSelection && (m_nFormsSelected || m_bRootSelected) ); pSubMenuNew->SetItemImage(SID_FM_NEW_FORM, m_ilNavigatorImages.GetImage(RID_SVXIMG_FORM)); pSubMenuNew->SetItemImage(SID_FM_NEW_HIDDEN, m_ilNavigatorImages.GetImage(RID_SVXIMG_HIDDEN)); // 'Neu'\'verstecktes...', wenn genau ein Formular selektiert ist pSubMenuNew->EnableItem( SID_FM_NEW_HIDDEN, bSingleSelection && m_nFormsSelected ); // 'Loeschen' : alles, was nicht Root ist, darf geloescht werden aContextMenu.EnableItem( SID_FM_DELETE, !m_bRootSelected ); // der TabDialog, wenn es genau ein Formular ist ... aContextMenu.EnableItem( SID_FM_TAB_DIALOG, bSingleSelection && m_nFormsSelected ); // Properties, wenn es nur Controls oder genau ein Formular ist // (und der ProBrowser nicht sowieso schon offen ist) if( pFormShell->GetImpl()->IsPropBrwOpen() ) aContextMenu.RemoveItem( aContextMenu.GetItemPos(SID_FM_SHOW_PROPERTY_BROWSER) ); else aContextMenu.EnableItem( SID_FM_SHOW_PROPERTY_BROWSER, (m_nControlsSelected && !m_nFormsSelected) || (!m_nControlsSelected && m_nFormsSelected) ); // Umbenennen gdw wenn ein Element und nicht die Root aContextMenu.EnableItem( SID_FM_RENAME_OBJECT, bSingleSelection && !m_bRootSelected ); // der Reandonly-Eintrag ist nur auf der Root erlaubt aContextMenu.EnableItem( SID_FM_OPEN_READONLY, m_bRootSelected ); // the same for automatic control focus aContextMenu.EnableItem( SID_FM_AUTOCONTROLFOCUS, m_bRootSelected ); // die ConvertTo-Slots sind enabled, wenn genau ein Control selektiert ist, der // dem Control entsprechende Slot ist disabled if (!m_bRootSelected && !m_nFormsSelected && (m_nControlsSelected == 1)) { aContextMenu.SetPopupMenu( SID_FM_CHANGECONTROLTYPE, FmXFormShell::GetConversionMenu() ); FmControlData* pCurrent = (FmControlData*)(m_arrCurrentSelection[0]->GetUserData()); ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xCurrentProps(pCurrent->GetFormComponent(), ::com::sun::star::uno::UNO_QUERY); pFormShell->GetImpl()->CheckControlConversionSlots(xCurrentProps, *aContextMenu.GetPopupMenu(SID_FM_CHANGECONTROLTYPE)); // die Shell filtert nach weiteren Bedingungen, zum Beispiel kein 'hidden control' } else aContextMenu.EnableItem( SID_FM_CHANGECONTROLTYPE, sal_False ); // jetzt alles, was disabled wurde, wech aContextMenu.RemoveDisabledEntries(sal_True, sal_True); ////////////////////////////////////////////////////////// // OpenReadOnly setzen aContextMenu.CheckItem( SID_FM_OPEN_READONLY, pFormModel->GetOpenInDesignMode() ); aContextMenu.CheckItem( SID_FM_AUTOCONTROLFOCUS, pFormModel->GetAutoControlFocus() ); sal_uInt16 nSlotId = aContextMenu.Execute( this, ptWhere ); switch( nSlotId ) { case SID_FM_NEW_FORM: { XubString aStr(SVX_RES(RID_STR_FORM)); XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_INSERT)); aUndoStr.SearchAndReplace('#', aStr); pFormModel->BegUndo(aUndoStr); // der Slot war nur verfuegbar, wenn es genau einen selektierten Eintrag gibt und dieser die Root // oder ein Formular ist NewForm( m_arrCurrentSelection.GetObject(0) ); pFormModel->EndUndo(); } break; case SID_FM_NEW_HIDDEN: { XubString aStr(SVX_RES(RID_STR_CONTROL)); XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_INSERT)); aUndoStr.SearchAndReplace('#', aStr); pFormModel->BegUndo(aUndoStr); // dieser Slot war guletig bei (genau) einem selektierten Formular rtl::OUString fControlName = FM_COMPONENT_HIDDEN; NewControl( fControlName, m_arrCurrentSelection.GetObject(0) ); pFormModel->EndUndo(); } break; case SID_FM_DELETE: { DeleteSelection(); } break; case SID_FM_TAB_DIALOG: { // dieser Slot galt bei genau einem selektierten Formular SvLBoxEntry* pSelectedForm = m_arrCurrentSelection.GetObject(0); DBG_ASSERT( IsFormEntry(pSelectedForm), "FmExplorer::Command: Dieser Eintrag muss ein FormEntry sein." ); FmFormData* pFormData = (FmFormData*)pSelectedForm->GetUserData(); ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xForm( pFormData->GetFormIface()); ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTabControllerModel > xTabController(xForm, ::com::sun::star::uno::UNO_QUERY); if( !xTabController.is() ) break; FmTabOrderDlg aTabDlg(m_xORB, GetpApp()->GetAppWindow(), GetExplModel()->GetFormShell() ); aTabDlg.Execute(); } break; case SID_FM_SHOW_PROPERTY_BROWSER: { ShowSelectionProperties(sal_True); } break; case SID_FM_RENAME_OBJECT: { // das war bei genau einem Nicht-Root-Eintrag erlaubt EditEntry( m_arrCurrentSelection.GetObject(0) ); } break; case SID_FM_OPEN_READONLY: { pFormModel->SetOpenInDesignMode( !pFormModel->GetOpenInDesignMode() ); pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_OPEN_READONLY); } break; case SID_FM_AUTOCONTROLFOCUS: { pFormModel->SetAutoControlFocus( !pFormModel->GetAutoControlFocus() ); pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_AUTOCONTROLFOCUS); } break; default: if (pFormShell->GetImpl()->IsControlConversionSlot(nSlotId)) { FmControlData* pCurrent = (FmControlData*)(m_arrCurrentSelection[0]->GetUserData()); if (pFormShell->GetImpl()->ExecuteControlConversionSlot(pCurrent->GetFormComponent(), nSlotId)) ShowSelectionProperties(); } } } bHandled = sal_True; } break; } if (!bHandled) SvTreeListBox::Command( rEvt ); } //------------------------------------------------------------------------ sal_Bool FmExplorer::IsDeleteAllowed() { ////////////////////////////////////////////////////////////////////// // Haben wir eine ::com::sun::star::form::Form... SvLBoxEntry* pCurEntry = GetCurEntry(); sal_uInt32 nCurEntryPos = GetModel()->GetAbsPos( pCurEntry ); if( nCurEntryPos==0 ) // Root kann nicht geloescht werden return sal_False; else return IsFormEntry(pCurEntry) || IsFormComponentEntry(pCurEntry); } //------------------------------------------------------------------------ SvLBoxEntry* FmExplorer::FindEntry( FmEntryData* pEntryData ) { if( !pEntryData ) return NULL; SvLBoxEntry* pCurEntry = First(); FmEntryData* pCurEntryData; while( pCurEntry ) { pCurEntryData = (FmEntryData*)pCurEntry->GetUserData(); if( pCurEntryData && pCurEntryData->IsEqualWithoutChilds(pEntryData) ) return pCurEntry; pCurEntry = Next( pCurEntry ); } return NULL; } //------------------------------------------------------------------------ void FmExplorer::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) { if( rHint.ISA(FmExplRemovedHint) ) { FmExplRemovedHint* pRemovedHint = (FmExplRemovedHint*)&rHint; FmEntryData* pEntryData = pRemovedHint->GetEntryData(); Remove( pEntryData ); } else if( rHint.ISA(FmExplInsertedHint) ) { FmExplInsertedHint* pInsertedHint = (FmExplInsertedHint*)&rHint; FmEntryData* pEntryData = pInsertedHint->GetEntryData(); sal_uInt32 nRelPos = pInsertedHint->GetRelPos(); Insert( pEntryData, nRelPos ); } else if( rHint.ISA(FmExplModelReplacedHint) ) { FmEntryData* pData = ((FmExplModelReplacedHint*)&rHint)->GetEntryData(); SvLBoxEntry* pEntry = FindEntry( pData ); if (pEntry) { // das Image neu setzen SetCollapsedEntryBmp(pEntry, pData->GetCollapsedImage()); SetExpandedEntryBmp(pEntry, pData->GetExpandedImage()); } } else if( rHint.ISA(FmExplNameChangedHint) ) { FmExplNameChangedHint* pNameChangedHint = (FmExplNameChangedHint*)&rHint; SvLBoxEntry* pEntry = FindEntry( pNameChangedHint->GetEntryData() ); SetEntryText( pEntry, pNameChangedHint->GetNewName() ); } else if( rHint.ISA(FmExplClearedHint) ) { SvTreeListBox::Clear(); ////////////////////////////////////////////////////////////////////// // Default-Eintrag "Formulare" m_pRootEntry = InsertEntry( SVX_RES(RID_STR_FORMS), m_aRootImg, m_aRootImg, NULL, sal_False, 0, NULL ); } else if (!m_bMarkingObjects && rHint.ISA(FmExplRequestSelectHint)) { // wenn m_bMarkingObjects sal_True ist, markiere ich gerade selber Objekte, und da der ganze Mechanismus dahinter synchron ist, // ist das genau der Hint, der durch mein Markieren ausgeloest wird, also kann ich ihn ignorieren FmExplRequestSelectHint* pershHint = (FmExplRequestSelectHint*)&rHint; FmEntryDataArray& arredToSelect = pershHint->GetItems(); SynchronizeSelection(arredToSelect); if (pershHint->IsMixedSelection()) // in diesem Fall habe ich alles deselektiert, obwohl die ::com::sun::star::sdbcx::View u.U. eine gemischte Markierung hatte // ich muss also im naechsten Select den Navigator an die ::com::sun::star::sdbcx::View anpassen m_bPrevSelectionMixed = sal_True; } } //------------------------------------------------------------------------ SvLBoxEntry* FmExplorer::Insert( FmEntryData* pEntryData, sal_uInt32 nRelPos ) { ////////////////////////////////////////////////////////////////////// // Aktuellen Eintrag einfuegen SvLBoxEntry* pParentEntry = FindEntry( pEntryData->GetParent() ); SvLBoxEntry* pNewEntry; if( !pParentEntry ) pNewEntry = InsertEntry( pEntryData->GetText(), pEntryData->GetExpandedImage(), pEntryData->GetCollapsedImage(), m_pRootEntry, sal_False, nRelPos, pEntryData ); else pNewEntry = InsertEntry( pEntryData->GetText(), pEntryData->GetExpandedImage(), pEntryData->GetCollapsedImage(), pParentEntry, sal_False, nRelPos, pEntryData ); ////////////////////////////////////////////////////////////////////// // Wenn Root-Eintrag Root expandieren if( !pParentEntry ) Expand( m_pRootEntry ); ////////////////////////////////////////////////////////////////////// // Childs einfuegen FmEntryDataList* pChildList = pEntryData->GetChildList(); sal_uInt32 nChildCount = pChildList->Count(); FmEntryData* pChildData; for( sal_uInt32 i=0; iGetObject(i); Insert( pChildData, LIST_APPEND ); } return pNewEntry; } //------------------------------------------------------------------------ void FmExplorer::Remove( FmEntryData* pEntryData ) { if( !pEntryData ) return; // der Entry zu den Daten SvLBoxEntry* pEntry = FindEntry( pEntryData ); if (!pEntry) return; // Eintrag aus TreeListBox entfernen // ich darf das Select, das ich ausloese, nicht behandeln : // Select aendert die MarkList der ::com::sun::star::sdbcx::View, wenn das gerade auch jemand anders macht und dabei ein Remove // triggert, haben wir mit ziemlicher Sicherheit ein Problem - Paradebeispiel war das Gruppieren von Controls mit // offenem Navigator ...) LockSelectionHandling(); // ein kleines Problem : ich merke mir meine selektierten Daten, wenn mir jetzt jemand einen selektierten Eintrag // unter dem Hintern wegschiesst, werde ich inkonsistent ... was schlecht waere Select(pEntry, sal_False); // beim eigentlichen Entfernen kann die ::com::sun::star::awt::Selection geaendert werden, da ich aber das SelectionHandling abgeschaltet // habe, muss ich mich hinterher darum kuemmern ULONG nExpectedSelectionCount = GetSelectionCount(); if( pEntry ) GetModel()->Remove( pEntry ); if (nExpectedSelectionCount != GetSelectionCount()) SynchronizeSelection(); // und standardmaessig behandle ich das Select natuerlich UnlockSelectionHandling(); } //------------------------------------------------------------------------ sal_Bool FmExplorer::IsFormEntry( SvLBoxEntry* pEntry ) { FmEntryData* pEntryData = (FmEntryData*)pEntry->GetUserData(); return !pEntryData || pEntryData->ISA(FmFormData); } //------------------------------------------------------------------------ sal_Bool FmExplorer::IsFormComponentEntry( SvLBoxEntry* pEntry ) { FmEntryData* pEntryData = (FmEntryData*)pEntry->GetUserData(); return pEntryData && pEntryData->ISA(FmControlData); } //------------------------------------------------------------------------ sal_Int8 FmExplorer::AcceptDrop( const AcceptDropEvent& rEvt ) { Point aDropPos = rEvt.maPosPixel; // kuemmern wir uns erst mal um moeglich DropActions (Scrollen und Aufklappen) if (rEvt.mbLeaving) { if (m_aDropActionTimer.IsActive()) m_aDropActionTimer.Stop(); } else { sal_Bool bNeedTrigger = sal_False; // auf dem ersten Eintrag ? if ((aDropPos.Y() >= 0) && (aDropPos.Y() < GetEntryHeight())) { m_aDropActionType = DA_SCROLLUP; bNeedTrigger = sal_True; } else // auf dem letzten (bzw. in dem Bereich, den ein Eintrag einnehmen wuerde, wenn er unten genau buendig // abschliessen wuerde) ? if ((aDropPos.Y() < GetSizePixel().Height()) && (aDropPos.Y() >= GetSizePixel().Height() - GetEntryHeight())) { m_aDropActionType = DA_SCROLLDOWN; bNeedTrigger = sal_True; } else { // auf einem Entry mit Childs, der nicht aufgeklappt ist ? SvLBoxEntry* pDropppedOn = GetEntry(aDropPos); if (pDropppedOn && (GetChildCount(pDropppedOn) > 0) && !IsExpanded(pDropppedOn)) { // -> aufklappen m_aDropActionType = DA_EXPANDNODE; bNeedTrigger = sal_True; } } if (bNeedTrigger && (m_aTimerTriggered != aDropPos)) { // neu anfangen zu zaehlen m_aTimerCounter = DROP_ACTION_TIMER_INITIAL_TICKS; // die Pos merken, da ich auch AcceptDrops bekomme, wenn sich die Maus gar nicht bewegt hat m_aTimerTriggered = aDropPos; // und den Timer los if (!m_aDropActionTimer.IsActive()) // gibt es den Timer schon ? { m_aDropActionTimer.SetTimeout(DROP_ACTION_TIMER_TICK_BASE); m_aDropActionTimer.Start(); } } else if (!bNeedTrigger) m_aDropActionTimer.Stop(); } ////////////////////////////////////////////////////////////////////// // Hat das Object das richtige Format? if (!m_aControlExchange.isDragSource()) return DND_ACTION_NONE; sal_Bool bHasDefControlFormat = m_aControlExchange->hasFieldExchangeFormat(GetDataFlavorExVector()); sal_Bool bHasControlPathFormat = m_aControlExchange->hasControlPathFormat(GetDataFlavorExVector()); sal_Bool bHasHiddenControlsFormat = m_aControlExchange->hasHiddenControlModelsFormat(GetDataFlavorExVector()); if (!bHasDefControlFormat && !bHasControlPathFormat && !bHasHiddenControlsFormat) return DND_ACTION_NONE; sal_Bool bForeignShellOrPage = m_aControlExchange->getShell() != GetExplModel()->GetFormShell() || m_aControlExchange->getPage() != GetExplModel()->GetFormPage(); if (bForeignShellOrPage || (bHasHiddenControlsFormat && (DND_ACTION_COPY == rEvt.mnAction))) { // crossing shell/page boundaries, we can exchange hidden controls only if (!bHasHiddenControlsFormat) return DND_ACTION_NONE; SvLBoxEntry* pDropTarget = GetEntry(aDropPos); if (!pDropTarget || (pDropTarget == m_pRootEntry) || !IsFormEntry(pDropTarget)) return DND_ACTION_NONE; return DND_ACTION_COPY; } if (DND_ACTION_MOVE != rEvt.mnAction) // 'normal' controls within a shell are moved only (never copied) return DND_ACTION_NONE; if (m_bDragDataDirty) { if (!bHasControlPathFormat) // ich befinde mich zwar in der Shell/Page, aus der die Controls stammen, habe aber kein Format, das den stattgefundenen // Shell-Wechsel ueberlebt hat (SVX_FM_CONTROLS_AS_PATH) return DND_ACTION_NONE; // da die Shell waehrend des Draggens umgeschaltet wude, muss ich die Liste des ExchangeObjektes wieder neu aufbauen // (dort stehen SvLBoxEntries drin, und die sind bei der Umschaltung floeten gegangen) m_aControlExchange->buildListFromPath(this, m_pRootEntry); m_bDragDataDirty = sal_False; } // die Liste der gedroppten Eintraege aus dem DragServer ListBoxEntryArray aDropped = m_aControlExchange->selected(); DBG_ASSERT(aDropped.size() >= 1, "FmExplorer::AcceptDrop : keine Eintraege !"); // das Ziel des Droppens (plus einige Daten, die ich nicht in jeder Schleife ermitteln will) SvLBoxEntry* pDropTarget = GetEntry( aDropPos ); if (!pDropTarget) return DND_ACTION_NONE; sal_Bool bDropTargetIsComponent = IsFormComponentEntry( pDropTarget ); SvLBoxEntry* pDropTargetParent = GetParent( pDropTarget ); // conditions to disallow the drop // 0) the root entry is part of the list (can't DnD the root!) // 1) one of the draged entries is to be dropped onto it's own parent // 2) - " - is to be dropped onto itself // 3) - " - is a Form and to be dropped onto one of it's descendants // 4) one of the entries is a controls and to be dropped onto the root // 5) a control or form will be dropped onto a control which is _not_ a sibling (dropping onto a sibling // means moving the control) // collect the ancestors of the drop targte (speeds up 3) SvLBoxEntrySortedArray arrDropAnchestors; SvLBoxEntry* pLoop = pDropTarget; while (pLoop) { arrDropAnchestors.Insert(pLoop); pLoop = GetParent(pLoop); } for (size_t i=0; ihasHiddenControlModelsFormat(GetDataFlavorExVector()); #ifdef DBG_UTIL sal_Bool bForeignShellOrPage = m_aControlExchange->getShell() != GetExplModel()->GetFormShell() || m_aControlExchange->getPage() != GetExplModel()->GetFormPage(); DBG_ASSERT(!bForeignShellOrPage || bHasHiddenControlsFormat, "FmExplorer::ExecuteDrop : invalid format (AcceptDrop shouldn't have let this pass) !"); DBG_ASSERT(bForeignShellOrPage || !m_bDragDataDirty, "FmExplorer::ExecuteDrop : invalid state (shell changed since last exchange resync) !"); // das sollte in AcceptDrop erledigt worden sein : dort wird in m_aControlExchange die Liste der Controls aufgebaut und m_bDragDataDirty // zurueckgesetzt #endif // das Ziel des ExecuteDrop sowie einige Daten darueber Point aDropPos = rEvt.maPosPixel; SvLBoxEntry* pDropTarget = GetEntry( aDropPos ); if (!pDropTarget) return DND_ACTION_NONE; sal_Bool bDropTargetIsForm = IsFormEntry(pDropTarget); FmFormData* pTargetData = bDropTargetIsForm ? (FmFormData*)pDropTarget->GetUserData() : NULL; if (DND_ACTION_COPY == rEvt.mnAction) { DBG_ASSERT(bHasHiddenControlsFormat, "FmExplorer::ExecuteDrop : only copying of hidden controls is supported !"); // das sollte das AcceptDrop abgefangen haben // da ich gleich die Zielobjekte alle selektieren will (und nur die) SelectAll(sal_False); Sequence< Reference< XInterface > > aControls = m_aControlExchange->hiddenControls(); sal_Int32 nCount = aControls.getLength(); const Reference< XInterface >* pControls = aControls.getConstArray(); FmFormShell* pFormShell = GetExplModel()->GetFormShell(); FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : NULL; // innerhalb eines Undo ... if (pFormModel) { XubString aStr(SVX_RES(RID_STR_CONTROL)); XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_INSERT)); aUndoStr.SearchAndReplace('#', aStr); pFormModel->BegUndo(aUndoStr); } // die Conrtols kopieren for (sal_Int32 i=0; i xNewPropSet(pNewControlData->GetElement(), ::com::sun::star::uno::UNO_QUERY); // und die Properties des alten in das neue kopieren ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xCurrent(pControls[i], ::com::sun::star::uno::UNO_QUERY); #if DEBUG || DBG_UTIL // nur mal eben sehen, ob das Ding tatsaechlich ein hidden control ist sal_Int16 nClassId = ::comphelper::getINT16(xCurrent->getPropertyValue(FM_PROP_CLASSID)); DBG_ASSERT(nClassId == ::com::sun::star::form::FormComponentType::HIDDENCONTROL, "FmExplorer::ExecuteDrop : invalid control in drop list !"); // wenn das SVX_FM_HIDDEN_CONTROLS-Format vorhanden ist, dann sollten wirklich nur hidden controls in der Sequenz // stecken #endif // DEBUG || DBG_UTIL ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > xPropInfo( xCurrent->getPropertySetInfo()); ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property> seqAllCurrentProps = xPropInfo->getProperties(); ::com::sun::star::beans::Property* pAllCurrentProps = seqAllCurrentProps.getArray(); for (sal_Int32 j=0; jsetPropertyValue(ustrCurrentProp, xCurrent->getPropertyValue(ustrCurrentProp)); } } SvLBoxEntry* pToSelect = FindEntry(pNewControlData); Select(pToSelect, sal_True); if (i == 0) SetCurEntry(pToSelect); } if (pFormModel) pFormModel->EndUndo(); return DND_ACTION_COPY; } // die Liste der gedraggten Eintraege const ListBoxEntryArray& aDropped = m_aControlExchange->selected(); DBG_ASSERT(aDropped.size() >= 1, "FmExplorer::ExecuteDrop : keine Eintraege !"); // die Shell und das Model FmFormShell* pFormShell = GetExplModel()->GetFormShell(); FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : NULL; if (!pFormModel) return DND_ACTION_NONE; // fuer's Undo XubString strUndoDescription(SVX_RES(RID_STR_UNDO_CONTAINER_REPLACE)); // TODO : den ::rtl::OUString aussagekraeftiger machen pFormModel->BegUndo(strUndoDescription); // ich nehme vor dem Einfuegen eines Eintrages seine ::com::sun::star::awt::Selection raus, damit die Markierung dabei nicht flackert // -> das Handeln des Select locken LockSelectionHandling(); // jetzt durch alle gedroppten Eintraege ... for (size_t i=0; iGetUserData(); ::com::sun::star::uno::Reference< ::com::sun::star::container::XChild > xCurrentChild(pCurrentUserData->GetElement(), ::com::sun::star::uno::UNO_QUERY); ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > xContainer(xCurrentChild->getParent(), ::com::sun::star::uno::UNO_QUERY); FmFormData* pCurrentParentUserData = (FmFormData*)pCurrentUserData->GetParent(); DBG_ASSERT(pCurrentParentUserData == NULL || pCurrentParentUserData->ISA(FmFormData), "FmExplorer::ExecuteDrop : ungueltiges Parent"); // beim Vater austragen if (pCurrentParentUserData) pCurrentParentUserData->GetChildList()->Remove(pCurrentUserData); else GetExplModel()->GetRootList()->Remove(pCurrentUserData); // aus dem ::com::sun::star::sdbcx::Container entfernen sal_Int32 nIndex = getElementPos(::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess > (xContainer, ::com::sun::star::uno::UNO_QUERY), xCurrentChild); GetExplModel()->m_pPropChangeList->Lock(); // die Undo-::com::sun::star::chaos::Action fuer das Rausnehmen if (GetExplModel()->m_pPropChangeList->CanUndo()) pFormModel->AddUndo(new FmUndoContainerAction(*pFormModel, FmUndoContainerAction::Removed, xContainer, xCurrentChild, nIndex)); // Events mitkopieren ::com::sun::star::uno::Reference< ::com::sun::star::script::XEventAttacherManager > xManager(xContainer, ::com::sun::star::uno::UNO_QUERY); ::com::sun::star::uno::Sequence< ::com::sun::star::script::ScriptEventDescriptor > aEvts; if (xManager.is() && nIndex >= 0) aEvts = xManager->getScriptEvents(nIndex); xContainer->removeByIndex(nIndex); // die ::com::sun::star::awt::Selection raus Select(pCurrent, sal_False); // und weg Remove(pCurrentUserData); // die Stelle innerhalb des DropParents, an der ich die gedroppten Eintraege einfuegen muss if (pTargetData) xContainer = ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > (pTargetData->GetElement(), ::com::sun::star::uno::UNO_QUERY); else xContainer = ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > (GetExplModel()->GetForms(), ::com::sun::star::uno::UNO_QUERY); // immer ganz hinten einfuegen nIndex = xContainer->getCount(); // UndoAction fuer das Einfuegen if (GetExplModel()->m_pPropChangeList->CanUndo()) pFormModel->AddUndo(new FmUndoContainerAction(*pFormModel, FmUndoContainerAction::Inserted, xContainer, xCurrentChild, nIndex)); // einfuegen im neuen ::com::sun::star::sdbcx::Container if (pTargetData) { // es wird in eine ::com::sun::star::form::Form eingefuegt, dann brauche ich eine ::com::sun::star::form::FormComponent xContainer->insertByIndex(nIndex, ::com::sun::star::uno::makeAny(::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent>(xCurrentChild, ::com::sun::star::uno::UNO_QUERY))); } else { xContainer->insertByIndex(nIndex, ::com::sun::star::uno::makeAny(::com::sun::star::uno::Reference< ::com::sun::star::form::XForm>(xCurrentChild, ::com::sun::star::uno::UNO_QUERY))); } if (aEvts.getLength()) { xManager = ::com::sun::star::uno::Reference< ::com::sun::star::script::XEventAttacherManager > (xContainer, ::com::sun::star::uno::UNO_QUERY); if (xManager.is()) xManager->registerScriptEvents(nIndex, aEvts); } GetExplModel()->m_pPropChangeList->UnLock(); // zuerst dem Eintrag das neue Parent pCurrentUserData->SetParent(pTargetData); // dann dem Parent das neue Child if (pTargetData) pTargetData->GetChildList()->Insert(pCurrentUserData, nIndex); else GetExplModel()->GetRootList()->Insert(pCurrentUserData, nIndex); // dann bei mir selber bekanntgeben und neu selektieren SvLBoxEntry* pNew = Insert( pCurrentUserData, nIndex ); } UnlockSelectionHandling(); pFormModel->EndUndo(); // waehrend des Verschiebens der Eintraege hat sich die Markierung der unterliegenden ::com::sun::star::sdbcx::View nicht geaendert (da sie mit der // logischen Seite nichts zu tun hat), wohl aber meine Selektion, die ich also wieder an der Markierung ausrichten muss SynchronizeSelection(); return rEvt.mnAction; } //------------------------------------------------------------------------ void FmExplorer::MouseButtonUp( const MouseEvent& rMEvt ) { SvTreeListBox::MouseButtonUp( rMEvt ); } //------------------------------------------------------------------------ void FmExplorer::KeyInput(const KeyEvent& rKEvt) { // loeschen ? if (rKEvt.GetKeyCode().GetCode() == KEY_DELETE && !rKEvt.GetKeyCode().GetModifier()) { DeleteSelection(); return; } SvTreeListBox::KeyInput(rKEvt); } //------------------------------------------------------------------------ sal_Bool FmExplorer::EditingEntry( SvLBoxEntry* pEntry, Selection& rSelection ) { if (!SvTreeListBox::EditingEntry( pEntry, rSelection )) return sal_False; return (pEntry && (pEntry->GetUserData() != NULL)); // die Wurzel, die ich nicht umbenennen darf, hat als UserData NULL } //------------------------------------------------------------------------ void FmExplorer::NewForm( SvLBoxEntry* pParentEntry ) { ////////////////////////////////////////////////////////////////////// // ParentFormData holen if( !IsFormEntry(pParentEntry) ) return; FmFormData* pParentFormData = (FmFormData*)pParentEntry->GetUserData(); ////////////////////////////////////////////////////////////////////// // Neue ::com::sun::star::form::Form erzeugen ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xNewForm(m_xORB->createInstance(FM_SUN_COMPONENT_FORM), ::com::sun::star::uno::UNO_QUERY); if (!xNewForm.is()) return; FmFormData* pNewFormData = new FmFormData( xNewForm, m_ilNavigatorImages, pParentFormData ); ////////////////////////////////////////////////////////////////////// // Namen setzen ::rtl::OUString aName = GenerateName(pNewFormData); pNewFormData->SetText(aName); ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xPropertySet(xNewForm, ::com::sun::star::uno::UNO_QUERY); if (!xPropertySet.is()) return; try { xPropertySet->setPropertyValue( FM_PROP_NAME, ::com::sun::star::uno::makeAny(aName) ); // a form should always have the command type table as default xPropertySet->setPropertyValue( FM_PROP_COMMANDTYPE, ::com::sun::star::uno::makeAny(sal_Int32(::com::sun::star::sdb::CommandType::TABLE))); } catch(...) { DBG_ERROR("FmExplorer::NewForm : could not set esssential properties !"); } ////////////////////////////////////////////////////////////////////// // ::com::sun::star::form::Form einfuegen GetExplModel()->Insert( pNewFormData, LIST_APPEND, sal_True ); ////////////////////////////////////////////////////////////////////// // Neue ::com::sun::star::form::Form als aktive ::com::sun::star::form::Form setzen FmFormShell* pFormShell = GetExplModel()->GetFormShell(); if( pFormShell ) { pFormShell->GetImpl()->setCurForm( xNewForm ); pFormShell->GetCurPage()->GetImpl()->setCurForm( xNewForm ); pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_PROPERTIES,sal_True,sal_True); } GetExplModel()->SetModified(); ////////////////////////////////////////////////////////////////////// // In EditMode schalten SvLBoxEntry* pNewEntry = FindEntry( pNewFormData ); EditEntry( pNewEntry ); } //------------------------------------------------------------------------ FmControlData* FmExplorer::NewControl( const ::rtl::OUString& rServiceName, SvLBoxEntry* pParentEntry, sal_Bool bEditName ) { ////////////////////////////////////////////////////////////////////// // ParentForm holen if (!GetExplModel()->GetFormShell()) return NULL; if (!IsFormEntry(pParentEntry)) return NULL; FmFormData* pParentFormData = (FmFormData*)pParentEntry->GetUserData();; ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xParentForm( pParentFormData->GetFormIface()); ////////////////////////////////////////////////////////////////////// // Neue Component erzeugen ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xNewComponent(::comphelper::getProcessServiceFactory()->createInstance(rServiceName), ::com::sun::star::uno::UNO_QUERY); if (!xNewComponent.is()) return NULL; FmControlData* pNewFormControlData = new FmControlData( xNewComponent, m_ilNavigatorImages, pParentFormData ); ////////////////////////////////////////////////////////////////////// // Namen setzen FmFormView* pFormView = GetExplModel()->GetFormShell()->GetFormView(); SdrPageView* pPageView = pFormView->GetPageViewPvNum(0); FmFormPage* pPage = (FmFormPage*)pPageView->GetPage(); ::rtl::OUString sName = pPage->GetImpl()->setUniqueName( xNewComponent, xParentForm ); pNewFormControlData->SetText( sName ); ////////////////////////////////////////////////////////////////////// // ::com::sun::star::form::FormComponent einfuegen GetExplModel()->Insert( pNewFormControlData, LIST_APPEND, sal_True ); GetExplModel()->SetModified(); if (bEditName) { ////////////////////////////////////////////////////////////////////// // In EditMode schalten SvLBoxEntry* pNewEntry = FindEntry( pNewFormControlData ); Select( pNewEntry, sal_True ); EditEntry( pNewEntry ); } return pNewFormControlData; } //------------------------------------------------------------------------ ::rtl::OUString FmExplorer::GenerateName( FmEntryData* pEntryData ) { const sal_uInt16 nMaxCount = 99; ::rtl::OUString aNewName; ////////////////////////////////////////////////////////////////////// // BasisNamen erzeugen UniString aBaseName; if( pEntryData->ISA(FmFormData) ) aBaseName = SVX_RES( RID_STR_STDFORMNAME ); else if( pEntryData->ISA(FmControlData) ) aBaseName = SVX_RES( RID_STR_CONTROL_CLASSNAME ); ////////////////////////////////////////////////////////////////////// // Neuen Namen erstellen FmFormData* pFormParentData = (FmFormData*)pEntryData->GetParent(); for( sal_Int32 i=0; i0 ) { aNewName += ::rtl::OUString::createFromAscii(" "); aNewName += ::rtl::OUString::valueOf(i).getStr(); } if( GetExplModel()->FindData(aNewName, pFormParentData,sal_False) == NULL ) break; } return aNewName; } //------------------------------------------------------------------------ sal_Bool FmExplorer::EditedEntry( SvLBoxEntry* pEntry, const XubString& rNewText ) { if (EditingCanceled()) return sal_True; GrabFocus(); FmEntryData* pEntryData = (FmEntryData*)pEntry->GetUserData(); sal_Bool bRes = GetExplModel()->Rename( pEntryData, rNewText); if( !bRes ) { m_pEditEntry = pEntry; nEditEvent = Application::PostUserEvent( LINK(this, FmExplorer, OnEdit) ); } else SetCursor(pEntry, sal_True); return bRes; } //------------------------------------------------------------------------ IMPL_LINK( FmExplorer, OnEdit, void*, EMPTYARG ) { nEditEvent = 0; EditEntry( m_pEditEntry ); m_pEditEntry = NULL; return 0L; } //------------------------------------------------------------------------ IMPL_LINK( FmExplorer, OnDropActionTimer, void*, EMPTYARG ) { if (--m_aTimerCounter > 0) return 0L; if (m_aDropActionType == DA_EXPANDNODE) { SvLBoxEntry* pToExpand = GetEntry(m_aTimerTriggered); if (pToExpand && (GetChildCount(pToExpand) > 0) && !IsExpanded(pToExpand)) // tja, eigentlich muesste ich noch testen, ob die Node nicht schon expandiert ist, aber ich // habe dazu weder in den Basisklassen noch im Model eine Methode gefunden ... // aber ich denke, die BK sollte es auch so vertragen Expand(pToExpand); // nach dem Expand habe ich im Gegensatz zum Scrollen natuerlich nix mehr zu tun m_aDropActionTimer.Stop(); } else { switch (m_aDropActionType) { case DA_SCROLLUP : { ScrollOutputArea(1); break; } case DA_SCROLLDOWN : ScrollOutputArea(-1); break; } m_aTimerCounter = DROP_ACTION_TIMER_SCROLL_TICKS; } return 0L; } //------------------------------------------------------------------------ IMPL_LINK(FmExplorer, OnEntrySelDesel, FmExplorer*, pThis) { m_sdiState = SDI_DIRTY; if (IsSelectionHandlingLocked()) return 0L; if (m_aSynchronizeTimer.IsActive()) m_aSynchronizeTimer.Stop(); m_aSynchronizeTimer.SetTimeout(EXPLORER_SYNC_DELAY); m_aSynchronizeTimer.Start(); return 0L; } //------------------------------------------------------------------------ IMPL_LINK(FmExplorer, OnSynchronizeTimer, void*, EMPTYARG) { SynchronizeMarkList(); return 0L; } //------------------------------------------------------------------------ void FmExplorer::ShowSelectionProperties(sal_Bool bForce) { // zuerst brauche ich die FormShell FmFormShell* pFormShell = GetExplModel()->GetFormShell(); if (!pFormShell) // keine Shell -> ich koennte kein curObject setzen -> raus return; CollectSelectionData(SDI_ALL); DBG_ASSERT( (m_nFormsSelected >= 0) && (m_nControlsSelected >= 0) && (m_nHiddenControls >= 0), "FmExplorer::ShowSelectionProperties : selection counter(s) invalid !"); DBG_ASSERT( m_nFormsSelected + m_nControlsSelected + (m_bRootSelected ? 1 : 0) == m_arrCurrentSelection.Count(), "FmExplorer::ShowSelectionProperties : selection meta data invalid !"); ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xInterfaceSelected; ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xFormSelected; sal_Bool bPropertiesAvailable = sal_True; sal_Bool bNeedSetCurControl = sal_True; if (m_bRootSelected) bPropertiesAvailable = sal_False; // fuer die Root habe ich keine - weder einzeln noch in einer Gruppe - Properties else if (m_nFormsSelected + m_nControlsSelected == 0) // keines der beiden sollte kleiner 0 sein ! bPropertiesAvailable = sal_False; // keine Selektion -> keine Properties else if (m_nFormsSelected * m_nControlsSelected != 0) bPropertiesAvailable = sal_False; // gemischte Selektion -> keine Properties else { // so, hier bin ich, wenn entweder nur ::com::sun::star::form::Forms oder nur Controls selektiert sind if (m_arrCurrentSelection.Count() == 1) { if (m_nFormsSelected > 0) { // es ist genau eine ::com::sun::star::form::Form selektiert FmFormData* pFormData = (FmFormData*)m_arrCurrentSelection.GetObject(0)->GetUserData(); xFormSelected = pFormData->GetFormIface(); xInterfaceSelected = xFormSelected; } else { // es ist genau ein Control selektiert (egal ob hidden oder normal) FmEntryData* pEntryData = (FmEntryData*)m_arrCurrentSelection.GetObject(0)->GetUserData(); xInterfaceSelected = pEntryData->GetElement(); pFormShell->GetImpl()->setCurControl(xInterfaceSelected); bNeedSetCurControl = sal_False; if (pEntryData->GetParent()) xFormSelected = ((FmFormData*)pEntryData->GetParent())->GetFormIface(); } } else { // wir haben eine MultiSelection, also muessen wir ein MultiSet dafuer aufbauen if (m_nFormsSelected > 0) { // ... nur ::com::sun::star::form::Forms // erstmal die PropertySet-Interfaces der ::com::sun::star::form::Forms einsammeln ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > > seqForms(m_nFormsSelected); ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > * pPropSets = seqForms.getArray(); for (int i=0; iGetUserData(); pPropSets[i] = ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > (pFormData->GetElement(), ::com::sun::star::uno::UNO_QUERY); } // dann diese in ein MultiSet packen FmXMultiSet* pSelectionSet = new FmXMultiSet( seqForms ); xInterfaceSelected = ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > ( (::com::sun::star::beans::XPropertySet*)pSelectionSet ); } else { // ... nur Controls if (m_nHiddenControls == m_nControlsSelected) { // ein MultiSet fuer die Properties der hidden controls ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > > seqHiddenControls(m_nHiddenControls); ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > * pPropSets = seqHiddenControls.getArray(); FmEntryData* pParentData = ((FmEntryData*)m_arrCurrentSelection.GetObject(0)->GetUserData())->GetParent(); for (int i=0; iGetUserData(); pPropSets[i] = ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > (pEntryData->GetElement(), ::com::sun::star::uno::UNO_QUERY); if (pParentData && pParentData != pEntryData->GetParent()) pParentData = NULL; } // dann diese in ein MultiSet packen FmXMultiSet* pSelectionSet = new FmXMultiSet( seqHiddenControls ); xInterfaceSelected = ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > ( (::com::sun::star::beans::XPropertySet*)pSelectionSet ); // und der Shell als aktuelles Objekt anzeigen pFormShell->GetImpl()->setCurControl( xInterfaceSelected ); bNeedSetCurControl = sal_False; if (pParentData) // alle hidden controls gehoeren zu einer ::com::sun::star::form::Form xFormSelected = ((FmFormData*)pParentData)->GetFormIface(); } else if (m_nHiddenControls == 0) { // nur normale Controls // ein MultiSet aus der MarkList der ::com::sun::star::sdbcx::View aufbauen ... const SdrMarkList& mlMarked = pFormShell->GetFormView()->GetMarkList(); FmXMultiSet* pSelectionSet = FmXMultiSet::Create( mlMarked ); xInterfaceSelected = ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > ( (::com::sun::star::beans::XPropertySet*)pSelectionSet ); pFormShell->GetImpl()->setCurControl( xInterfaceSelected ); bNeedSetCurControl = sal_False; // jetzt das Formular setzen sal_Bool bMixedWithFormControls; xFormSelected = pFormShell->GetImpl()->DetermineCurForm(mlMarked,bMixedWithFormControls); } else // gemischte Selektion aus hidden und normalen Controls -> keine Properties bPropertiesAvailable = sal_False; } } } // um das Setzen des current Controls kann sich die Shell kuemmern (da gibt es einige Feinheiten, die ich hier nicht // neu implementieren moechte) if (bNeedSetCurControl) pFormShell->GetImpl()->DetermineSelection(pFormShell->GetFormView()->GetMarkList()); // und dann meine ::com::sun::star::form::Form und mein SelObject pFormShell->GetImpl()->setSelObject(xInterfaceSelected); pFormShell->GetImpl()->setCurForm(xFormSelected); if (pFormShell->GetImpl()->IsPropBrwOpen() || bForce) { // und jetzt kann ich das Ganze dem PropertyBrowser uebergeben FmInterfaceItem aInterfaceItem( SID_FM_SHOW_PROPERTY_BROWSER, xInterfaceSelected ); pFormShell->GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( SID_FM_SHOW_PROPERTY_BROWSER, SFX_CALLMODE_ASYNCHRON, &aInterfaceItem, 0L ); } } //------------------------------------------------------------------------ void FmExplorer::DeleteSelection() { // die Root darf ich natuerlich nicht mitloeschen sal_Bool bRootSelected = IsSelected(m_pRootEntry); int nSelectionCount = GetSelectionCount(); if (bRootSelected && (nSelectionCount > 1)) // die Root plus andere Elemente ? Select(m_pRootEntry, sal_False); // ja -> die Root raus if ((nSelectionCount == 0) || bRootSelected) // immer noch die Root ? return; // -> sie ist das einzige selektierte -> raus DBG_ASSERT(!m_bPrevSelectionMixed, "FmExplorer::DeleteSelection() : loeschen nicht erlaubt wenn Markierung und Selektion nciht konsistent"); // ich brauche unten das FormModel ... FmFormShell* pFormShell = GetExplModel()->GetFormShell(); if (!pFormShell) return; FmFormModel* pFormModel = pFormShell ? pFormShell->GetFormModel() : NULL; if (!pFormModel) return; // die Undo-Beschreibung UniString aUndoStr = SVX_RES(RID_STR_UNDO_DELETE_LOGICAL); /* falls irgendwann mal Ordnung in das Undo kommt (so dass wir wirklich die aeusserste Klammer sind und beim Loeschen nur // eine, nicht zwei UndoActions erzeugen), koennen wir folgenden Code ja wieder benutzen ... if (m_arrCurrentSelection.Count() == 1) { aUndoStr = SVX_RES(RID_STR_UNDO_CONTAINER_REMOVE); if (m_nFormsSelected) aUndoStr.SearchAndReplace("#", SVX_RES(RID_STR_FORM)); else // bei selektierter Root war loeschen nicht erlaubt, also ist es ein Control aUndoStr.SearchAndReplace("#", SVX_RES(RID_STR_CONTROL)); } else { aUndoStr = SVX_RES(RID_STR_UNDO_CONTAINER_REMOVE_MULTIPLE); aUndoStr.SearchAndReplace("#", UniString(::rtl::OUString(m_arrCurrentSelection.Count()))); // der Umweg ueber den ::rtl::OUString ist notwendig, da nur der den Constructor hat, der gleich eine Zahl formatiert } */ // jetzt muss ich noch die DeleteList etwas absichern : wenn man ein Formular und ein abhaengiges // Element loescht - und zwar in dieser Reihenfolge - dann ist der SvLBoxEntryPtr des abhaengigen Elementes // natuerlich schon ungueltig, wenn es geloescht werden soll ... diesen GPF, den es dann mit Sicherheit gibt, // gilt es zu verhindern, also die 'normalisierte' Liste CollectSelectionData(SDI_NORMALIZED); // folgendes Problem : ich muss das ExplorerModel::Remove verwenden, da nur dieses sich um das korrekte Loeschen von ::com::sun::star::form::Form- // Objekten kuemmert. Andererseits muss ich die Controls selber ueber DeleteMarked loeschen (irgendwo im Writer gibt // es sonst Probleme). Wenn ich erst die Struktur, dann die Controls loesche, klappt das Undo nicht (da dann erst die Controls // eingefuegt werden, dann die Struktur, sprich ihr Parent-Formular). Andersrum sind die EntryDatas ungueltig, wenn ich die // Controls geloescht habe und zur Struktur gehe. Also muss ich die Formulare NACH den normalen Controls loeschen, damit sie // beim Undo VOR denen wiederhergestellt werden. pFormShell->GetImpl()->EnableTrackProperties(sal_False); int i; for (i = m_arrCurrentSelection.Count()-1; i>=0; --i) { FmEntryData* pCurrent = (FmEntryData*)(m_arrCurrentSelection.GetObject(i)->GetUserData()); // eine ::com::sun::star::form::Form ? sal_Bool bIsForm = pCurrent->ISA(FmFormData); // da ich das Loeschen im folgenden der ::com::sun::star::sdbcx::View ueberlasse und dabei auf deren MarkList aufbaue, im Normalfall aber bei // einem makierten Formular nur die direkt, nicht die indirekt abhaengigen Controls markiert werden, muss ich das hier // noch nachholen if (bIsForm) MarkViewObj((FmFormData*)pCurrent, sal_True, sal_True); // das zweite sal_True heisst "deep" // ein hidden control ? sal_Bool bIsHidden = IsHiddenControl(pCurrent); // ::com::sun::star::form::Forms und hidden Controls muss ich behalten, alles andere nicht if (!bIsForm && !bIsHidden) m_arrCurrentSelection.Remove((sal_uInt16)i, 1); } pFormShell->GetImpl()->EnableTrackProperties(sal_True); // und jetzt das eigentliche Loeschen // die Controls wech pFormShell->GetFormView()->DeleteMarked(); // das UNDO beginne ich erst jetzt : Das DeleteMarked erzeugt eine eigene Undo-::com::sun::star::chaos::Action, in die ich mich eigentlich einklinken // muesste, was leider nicht geht (das laeuft irgendwo im SwDoc), also erzeuge ich eine zweite, mit der man das Loeschen der // logischen Struktur zuruecknehmen kann (das ist nicht schoen, dass eine eigentlich atomare Aktion zwei UndoActions erzeugt, // aber das einzige, was wir gefunden haben) pFormModel->BegUndo(aUndoStr); // die Struktur wech for (i=0; iGetUserData()); // noch ein kleines Problem, bevor ich das ganz loesche : wenn es eine ::com::sun::star::form::Form ist und die Shell diese als CurrentObject // kennt, dann muss ich ihr das natuerlich ausreden if (pCurrent->ISA(FmFormData)) { ::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > xCurrentForm(pCurrent->GetElement(), ::com::sun::star::uno::UNO_QUERY); if (pFormShell->GetImpl()->getCurForm() == xCurrentForm) // die Shell kennt die zu loeschende ::com::sun::star::form::Form ? pFormShell->GetImpl()->setCurForm(::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > ()); // -> wegnehmen ... } GetExplModel()->Remove(pCurrent, sal_True); } pFormModel->EndUndo(); } //------------------------------------------------------------------------ void FmExplorer::CollectSelectionData(SELDATA_ITEMS sdiHow) { DBG_ASSERT(sdiHow != SDI_DIRTY, "FmExplorer::CollectSelectionData : ever thought about your parameter ? DIRTY ?"); if (sdiHow == m_sdiState) return; m_arrCurrentSelection.Remove((sal_uInt16)0, m_arrCurrentSelection.Count()); m_nFormsSelected = m_nControlsSelected = m_nHiddenControls = 0; m_bRootSelected = sal_False; SvLBoxEntry* pSelectionLoop = FirstSelected(); while (pSelectionLoop) { // erst mal die Zaehlung der verschiedenen Elemente if (pSelectionLoop == m_pRootEntry) m_bRootSelected = sal_True; else { if (IsFormEntry(pSelectionLoop)) ++m_nFormsSelected; else { ++m_nControlsSelected; if (IsHiddenControl((FmEntryData*)(pSelectionLoop->GetUserData()))) ++m_nHiddenControls; } } if (sdiHow == SDI_NORMALIZED) { // alles, was schon einen selektierten Vorfahr hat, nicht mitnehmen if (pSelectionLoop == m_pRootEntry) m_arrCurrentSelection.Insert(pSelectionLoop); else { SvLBoxEntry* pParentLoop = GetParent(pSelectionLoop); while (pParentLoop) { // eigentlich muesste ich testen, ob das Parent in der m_arrCurrentSelection steht ... // Aber wenn es selektiert ist, dann steht es in m_arrCurrentSelection, oder wenigstens einer seiner Vorfahren, // wenn der auch schon selektiert war. In beiden Faellen reicht also die Abfrage IsSelected if (IsSelected(pParentLoop)) break; else { if (m_pRootEntry == pParentLoop) { // bis (exclusive) zur Root gab es kein selektiertes Parent -> der Eintrag gehoert in die normalisierte Liste m_arrCurrentSelection.Insert(pSelectionLoop); break; } else pParentLoop = GetParent(pParentLoop); } } } } else if (sdiHow == SDI_NORMALIZED_FORMARK) { SvLBoxEntry* pParent = GetParent(pSelectionLoop); if (!pParent || !IsSelected(pParent) || IsFormEntry(pSelectionLoop)) m_arrCurrentSelection.Insert(pSelectionLoop); } else m_arrCurrentSelection.Insert(pSelectionLoop); pSelectionLoop = NextSelected(pSelectionLoop); } m_sdiState = sdiHow; } //------------------------------------------------------------------------ void FmExplorer::SynchronizeSelection(FmEntryDataArray& arredToSelect) { LockSelectionHandling(); if (arredToSelect.Count() == 0) { SelectAll(sal_False); } else { // erst mal gleiche ich meine aktuelle Selektion mit der geforderten SelectList ab SvLBoxEntry* pSelection = FirstSelected(); while (pSelection) { FmEntryData* pCurrent = (FmEntryData*)pSelection->GetUserData(); if (pCurrent != NULL) { sal_uInt16 nPosition; if ( arredToSelect.Seek_Entry(pCurrent, &nPosition) ) { // der Entry ist schon selektiert, steht aber auch in der SelectList -> er kann aus letzterer // raus arredToSelect.Remove(nPosition, 1); } else { // der Entry ist selektiert, aber steht nicht in der SelectList -> Selektion rausnehmen Select(pSelection, sal_False); // und sichtbar machen (kann ja sein, dass das die einzige Modifikation ist, die ich hier in dem // ganzen Handler mache, dann sollte das zu sehen sein) MakeVisible(pSelection); } } else Select(pSelection, sal_False); pSelection = NextSelected(pSelection); } // jetzt habe ich in der SelectList genau die Eintraege, die noch selektiert werden muessen // zwei Moeglichkeiten : 1) ich gehe durch die SelectList, besorge mir zu jedem Eintrag meinen SvLBoxEntry // und selektiere diesen (waere irgendwie intuitiver ;)) 2) ich gehe durch alle meine SvLBoxEntries und selektiere // genau die, die ich in der SelectList finde // 1) braucht O(k*n) (k=Laenge der SelectList, n=Anzahl meiner Entries), plus den Fakt, dass FindEntry nicht den // Pointer auf die UserDaten vergleicht, sondern ein aufwendigeres IsEqualWithoutChilds durchfuehrt // 2) braucht O(n*log k), dupliziert aber etwas Code (naemlich den aus FindEntry) // da das hier eine relativ oft aufgerufenen Stelle sein koennte (bei jeder Aenderung in der Markierung in der ::com::sun::star::sdbcx::View !), // nehme ich doch lieber letzteres SvLBoxEntry* pLoop = First(); while( pLoop ) { FmEntryData* pCurEntryData = (FmEntryData*)pLoop->GetUserData(); sal_uInt16 nPosition; if ( arredToSelect.Seek_Entry(pCurEntryData, &nPosition) ) { Select(pLoop, sal_True); MakeVisible(pLoop); SetCursor(pLoop, sal_True); } pLoop = Next( pLoop ); } } UnlockSelectionHandling(); } //------------------------------------------------------------------------ void FmExplorer::SynchronizeSelection() { // Shell und ::com::sun::star::sdbcx::View FmFormShell* pFormShell = GetExplModel()->GetFormShell(); if(!pFormShell) return; FmFormView* pFormView = pFormShell->GetFormView(); if (!pFormView) return; GetExplModel()->BroadcastMarkedObjects(pFormView->GetMarkList()); } //------------------------------------------------------------------------ void FmExplorer::SynchronizeMarkList() { // die Shell werde ich brauchen ... FmFormShell* pFormShell = GetExplModel()->GetFormShell(); if (!pFormShell) return; CollectSelectionData(SDI_NORMALIZED_FORMARK); // Die ::com::sun::star::sdbcx::View soll jetzt kein Notify bei einer Aenderung der MarkList rauslassen pFormShell->GetImpl()->EnableTrackProperties(sal_False); UnmarkAllViewObj(); for (sal_uInt32 i=0; iGetUserData(), sal_True, sal_False); // Bei Controlselektion Control-SdrObjects markieren else if (IsFormComponentEntry(pSelectionLoop)) { FmControlData* pControlData = (FmControlData*)pSelectionLoop->GetUserData(); if (pControlData) { ///////////////////////////////////////////////////////////////// // Beim ::com::sun::star::form::HiddenControl kann kein Object selektiert werden ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xFormComponent( pControlData->GetFormComponent()); if (!xFormComponent.is()) continue; ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xSet(xFormComponent, ::com::sun::star::uno::UNO_QUERY); if (!xSet.is()) continue; sal_uInt16 nClassId = ::comphelper::getINT16(xSet->getPropertyValue(FM_PROP_CLASSID)); if (nClassId != ::com::sun::star::form::FormComponentType::HIDDENCONTROL) MarkViewObj(pControlData, sal_True, sal_True); } } } // wenn der PropertyBrowser offen ist, muss ich den entsprechend meiner Selektion anpassen // (NICHT entsprechend der MarkList der ::com::sun::star::sdbcx::View : wenn ich ein Formular selektiert habe, sind in der // ::com::sun::star::sdbcx::View alle zugehoerigen Controls markiert, trotzdem moechte ich natuerlich die Formular-Eigenschaften // sehen) ShowSelectionProperties(sal_False); // Flag an ::com::sun::star::sdbcx::View wieder zuruecksetzen pFormShell->GetImpl()->EnableTrackProperties(sal_True); // wenn jetzt genau eine ::com::sun::star::form::Form selektiert ist, sollte die Shell das als CurrentForm mitbekommen // (wenn SelectionHandling nicht locked ist, kuemmert sich die ::com::sun::star::sdbcx::View eigentlich in MarkListHasChanged drum, // aber der Mechanismus greift zum Beispiel nicht, wenn die ::com::sun::star::form::Form leer ist) if ((m_arrCurrentSelection.Count() == 1) && (m_nFormsSelected == 1)) { FmEntryData* pSingleSelectionData = (FmEntryData*)(FirstSelected()->GetUserData()); pFormShell->GetImpl()->setCurForm(::com::sun::star::uno::Reference< ::com::sun::star::form::XForm > (pSingleSelectionData->GetElement(), ::com::sun::star::uno::UNO_QUERY)); } } //------------------------------------------------------------------------ sal_Bool FmExplorer::IsHiddenControl(FmEntryData* pEntryData) { if (pEntryData == NULL) return sal_False; ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > xProperties(pEntryData->GetElement(), ::com::sun::star::uno::UNO_QUERY); if (::comphelper::hasProperty(FM_PROP_CLASSID, xProperties)) { ::com::sun::star::uno::Any aClassID = xProperties->getPropertyValue( FM_PROP_CLASSID ); return (::comphelper::getINT16(aClassID) == ::com::sun::star::form::FormComponentType::HIDDENCONTROL); } return sal_False; } //------------------------------------------------------------------------ sal_Bool FmExplorer::Select( SvLBoxEntry* pEntry, sal_Bool bSelect ) { if (bSelect == IsSelected(pEntry)) // das passiert manchmal, ich glaube, die Basisklasse geht zu sehr auf Nummer sicher ;) return sal_True; return SvTreeListBox::Select(pEntry, bSelect ); } //------------------------------------------------------------------------ void FmExplorer::UnmarkAllViewObj() { FmFormShell* pFormShell = GetExplModel()->GetFormShell(); if( !pFormShell ) return; FmFormView* pFormView = pFormShell->GetFormView(); pFormView->UnMarkAll(); } //------------------------------------------------------------------------ void FmExplorer::MarkViewObj( FmFormData* pFormData, sal_Bool bMark, sal_Bool bDeep ) { ////////////////////////////////////////////////////////////////////// // Alle Controls der ::com::sun::star::form::Form markieren FmEntryDataList* pChildList = pFormData->GetChildList(); FmEntryData* pEntryData; FmControlData* pControlData; for( sal_uInt32 i=0; iCount(); i++ ) { pEntryData = pChildList->GetObject(i); if( pEntryData->ISA(FmControlData) ) { pControlData = (FmControlData*)pEntryData; MarkViewObj( pControlData, (i==pChildList->Count()-1), bMark ); } else if (bDeep && (pEntryData->ISA(FmFormData))) MarkViewObj((FmFormData*)pEntryData, bMark, bDeep); } } //------------------------------------------------------------------------ void FmExplorer::MarkViewObj( FmControlData* pControlData, sal_Bool bMarkHandles, sal_Bool bMark) { if( !pControlData ) return; FmFormShell* pFormShell = GetExplModel()->GetFormShell(); if( !pFormShell ) return; ////////////////////////////////////////////////////////////////////// // In der Page das entsprechende SdrObj finden und selektieren ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xFormComponent( pControlData->GetFormComponent()); FmFormView* pFormView = pFormShell->GetFormView(); SdrPageView* pPageView = pFormView->GetPageViewPvNum(0); SdrPage* pPage = pPageView->GetPage(); SdrObjListIter aIter( *pPage ); while( aIter.IsMore() ) { SdrObject* pObj = aIter.Next(); ////////////////////////////////////////////////////////////////////// // Es interessieren nur Uno-Objekte if( pObj->IsUnoObj() ) { ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xControlModel(((SdrUnoObj*)pObj)->GetUnoControlModel()); ////////////////////////////////////////////////////////////////////// // Ist dieses Objekt ein ::com::sun::star::form::XFormComponent? ::com::sun::star::uno::Reference< ::com::sun::star::form::XFormComponent > xFormViewControl(xControlModel, ::com::sun::star::uno::UNO_QUERY); if( !xFormViewControl.is() ) return; if (xFormViewControl == xFormComponent ) { // Objekt markieren if (bMark != pFormView->IsObjMarked(pObj)) // der Writer mag das leider nicht, wenn schon markierte Objekte noch mal markiert werden ... pFormView->MarkObj( pObj, pPageView, !bMark, sal_False ); // Markierung in allen Fenstern in den sichtbaren Bereich verschieben if( bMarkHandles && bMark) { Rectangle aMarkRect( pFormView->GetAllMarkedRect()); for( sal_uInt16 i=0; iGetWinCount(); i++ ) pFormView->MakeVisible( aMarkRect, *(Window*)pFormView->GetWin(i) ); } } } } } //======================================================================== // class FmExplorerWin //======================================================================== DBG_NAME(FmExplorerWin); //------------------------------------------------------------------------ FmExplorerWin::FmExplorerWin( SfxBindings *pBindings, SfxChildWindow *pMgr, Window* pParent ) :SfxDockingWindow( pBindings, pMgr, pParent, WinBits(WB_STDMODELESS|WB_SIZEABLE|WB_ROLLABLE|WB_3DLOOK|WB_DOCKABLE) ) ,SfxControllerItem( SID_FM_FMEXPLORER_CONTROL, *pBindings ) { DBG_CTOR(FmExplorerWin,NULL); SetHelpId( HID_FORM_NAVIGATOR_WIN ); m_pFmExplorer = new FmExplorer(comphelper::getProcessServiceFactory(), this ); m_pFmExplorer->Show(); SetText( SVX_RES(RID_STR_FMEXPLORER) ); SetSizePixel( Size(200,200) ); } //------------------------------------------------------------------------ FmExplorerWin::~FmExplorerWin() { delete m_pFmExplorer; DBG_DTOR(FmExplorerWin,NULL); } //----------------------------------------------------------------------- void FmExplorerWin::Update( FmFormShell* pFormShell ) { m_pFmExplorer->Update( pFormShell ); } //----------------------------------------------------------------------- void FmExplorerWin::StateChanged( sal_uInt16 nSID, SfxItemState eState, const SfxPoolItem* pState ) { if( !pState || SID_FM_FMEXPLORER_CONTROL != nSID ) return; if( eState >= SFX_ITEM_AVAILABLE ) { FmFormShell* pShell = PTR_CAST( FmFormShell,((SfxObjectItem*)pState)->GetShell() ); Update( pShell ); } else Update( NULL ); } //----------------------------------------------------------------------- sal_Bool FmExplorerWin::Close() { Update( NULL ); return SfxDockingWindow::Close(); } //----------------------------------------------------------------------- void FmExplorerWin::FillInfo( SfxChildWinInfo& rInfo ) const { SfxDockingWindow::FillInfo( rInfo ); rInfo.bVisible = sal_False; } //----------------------------------------------------------------------- Size FmExplorerWin::CalcDockingSize( SfxChildAlignment eAlign ) { Size aSize = SfxDockingWindow::CalcDockingSize( eAlign ); switch( eAlign ) { case SFX_ALIGN_TOP: case SFX_ALIGN_BOTTOM: return Size(); case SFX_ALIGN_LEFT: case SFX_ALIGN_RIGHT: break; } return aSize; } //----------------------------------------------------------------------- SfxChildAlignment FmExplorerWin::CheckAlignment( SfxChildAlignment eActAlign, SfxChildAlignment eAlign ) { switch (eAlign) { case SFX_ALIGN_LEFT: case SFX_ALIGN_RIGHT: case SFX_ALIGN_NOALIGNMENT: return (eAlign); } return (eActAlign); } //------------------------------------------------------------------------ void FmExplorerWin::Resize() { SfxDockingWindow::Resize(); Size aLogOutputSize = PixelToLogic( GetOutputSizePixel(), MAP_APPFONT ); Size aLogExplSize = aLogOutputSize; aLogExplSize.Width() -= 6; aLogExplSize.Height() -= 6; Point aExplPos = LogicToPixel( Point(3,3), MAP_APPFONT ); Size aExplSize = LogicToPixel( aLogExplSize, MAP_APPFONT ); m_pFmExplorer->SetPosSizePixel( aExplPos, aExplSize ); } //======================================================================== // class FmExplorerWinMgr //======================================================================== //----------------------------------------------------------------------- SFX_IMPL_DOCKINGWINDOW( FmExplorerWinMgr, SID_FM_SHOW_FMEXPLORER ) //----------------------------------------------------------------------- FmExplorerWinMgr::FmExplorerWinMgr( Window *pParent, sal_uInt16 nId, SfxBindings *pBindings, SfxChildWinInfo* pInfo ) :SfxChildWindow( pParent, nId ) { pWindow = new FmExplorerWin( pBindings, this, pParent ); eChildAlignment = SFX_ALIGN_NOALIGNMENT; ((SfxDockingWindow*)pWindow)->Initialize( pInfo ); }