1747 lines
54 KiB
C++
1747 lines
54 KiB
C++
/*************************************************************************
|
|
*
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright 2000, 2010 Oracle and/or its affiliates.
|
|
*
|
|
* OpenOffice.org - a multi-platform office productivity suite
|
|
*
|
|
* This file is part of OpenOffice.org.
|
|
*
|
|
* OpenOffice.org is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License version 3
|
|
* only, as published by the Free Software Foundation.
|
|
*
|
|
* OpenOffice.org is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Lesser General Public License version 3 for more details
|
|
* (a copy is included in the LICENSE file that accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public License
|
|
* version 3 along with OpenOffice.org. If not, see
|
|
* <http://www.openoffice.org/license.html>
|
|
* for a copy of the LGPLv3 License.
|
|
*
|
|
************************************************************************/
|
|
|
|
// MARKER(update_precomp.py): autogen include statement, do not remove
|
|
#include "precompiled_svtools.hxx"
|
|
|
|
#define _SVTREEBX_CXX
|
|
#include <tools/debug.hxx>
|
|
#include <com/sun/star/lang/XServiceInfo.hpp>
|
|
#include <com/sun/star/lang/DisposedException.hpp>
|
|
#include <com/sun/star/view/SelectionType.hpp>
|
|
#include <toolkit/helper/property.hxx>
|
|
#include <toolkit/helper/vclunohelper.hxx>
|
|
|
|
#include <com/sun/star/awt/tree/XMutableTreeNode.hpp>
|
|
#include <treecontrolpeer.hxx>
|
|
#include <comphelper/processfactory.hxx>
|
|
|
|
#include <rtl/ref.hxx>
|
|
#include <vcl/graph.hxx>
|
|
#include <svtools/svtreebx.hxx>
|
|
|
|
#include <map>
|
|
|
|
using ::rtl::OUString;
|
|
using namespace ::com::sun::star;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::lang;
|
|
using namespace ::com::sun::star::awt::tree;
|
|
using namespace ::com::sun::star::beans;
|
|
using namespace ::com::sun::star::view;
|
|
using namespace ::com::sun::star::container;
|
|
using namespace ::com::sun::star::util;
|
|
using namespace ::com::sun::star::graphic;
|
|
|
|
#define O(x) OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
|
|
|
|
struct LockGuard
|
|
{
|
|
public:
|
|
LockGuard( sal_Int32& rLock )
|
|
: mrLock( rLock )
|
|
{
|
|
rLock++;
|
|
}
|
|
|
|
~LockGuard()
|
|
{
|
|
mrLock--;
|
|
}
|
|
|
|
sal_Int32& mrLock;
|
|
};
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
class ImplGraphicItem : public SvLBoxBmp
|
|
{
|
|
public:
|
|
ImplGraphicItem( SvLBoxEntry* pEntry, USHORT nFlags, Image& aImage ) : SvLBoxBmp( pEntry, nFlags, aImage ) {}
|
|
|
|
OUString msGraphicURL;
|
|
};
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
class ImplContextGraphicItem : public SvLBoxContextBmp
|
|
{
|
|
public:
|
|
ImplContextGraphicItem( SvLBoxEntry* pEntry,USHORT nFlags,Image& rI1,Image& rI2, USHORT nEntryFlagsBmp1)
|
|
: SvLBoxContextBmp( pEntry, nFlags, rI1, rI2, nEntryFlagsBmp1 ) {}
|
|
|
|
OUString msExpandedGraphicURL;
|
|
OUString msCollapsedGraphicURL;
|
|
};
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
class UnoTreeListBoxImpl : public SvTreeListBox
|
|
{
|
|
public:
|
|
UnoTreeListBoxImpl( TreeControlPeer* pPeer, Window* pParent, WinBits nWinStyle );
|
|
~UnoTreeListBoxImpl();
|
|
|
|
sal_uInt32 insert( SvLBoxEntry* pEntry,SvLBoxEntry* pParent,ULONG nPos=LIST_APPEND );
|
|
|
|
virtual void RequestingChilds( SvLBoxEntry* pParent );
|
|
|
|
virtual BOOL EditingEntry( SvLBoxEntry* pEntry, Selection& );
|
|
virtual BOOL EditedEntry( SvLBoxEntry* pEntry, const XubString& rNewText );
|
|
|
|
DECL_LINK( OnSelectionChangeHdl, UnoTreeListBoxImpl* );
|
|
DECL_LINK( OnExpandingHdl, UnoTreeListBoxImpl* );
|
|
DECL_LINK( OnExpandedHdl, UnoTreeListBoxImpl* );
|
|
|
|
private:
|
|
rtl::Reference< TreeControlPeer > mxPeer;
|
|
};
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
class SVT_DLLPUBLIC UnoTreeListItem : public SvLBoxItem
|
|
{
|
|
public:
|
|
UnoTreeListItem( SvLBoxEntry* );
|
|
UnoTreeListItem();
|
|
virtual ~UnoTreeListItem();
|
|
virtual USHORT IsA();
|
|
void InitViewData( SvLBox*,SvLBoxEntry*,SvViewDataItem* );
|
|
OUString GetText() const;
|
|
void SetText( const OUString& rText );
|
|
Image GetImage() const;
|
|
void SetImage( const Image& rImage );
|
|
OUString GetGraphicURL() const;
|
|
void SetGraphicURL( const OUString& rGraphicURL );
|
|
void Paint( const Point&, SvLBox& rDev, USHORT nFlags,SvLBoxEntry* );
|
|
SvLBoxItem* Create() const;
|
|
void Clone( SvLBoxItem* pSource );
|
|
|
|
private:
|
|
OUString maText;
|
|
OUString maGraphicURL;
|
|
Image maImage;
|
|
};
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
class UnoTreeListEntry : public SvLBoxEntry
|
|
{
|
|
public:
|
|
UnoTreeListEntry( const Reference< XTreeNode >& xNode, TreeControlPeer* pPeer );
|
|
virtual ~UnoTreeListEntry();
|
|
|
|
Reference< XTreeNode > mxNode;
|
|
TreeControlPeer* mpPeer;
|
|
};
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
class TreeNodeMap : public std::map< Reference< XTreeNode >, UnoTreeListEntry* >
|
|
{
|
|
};
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
TreeControlPeer::TreeControlPeer()
|
|
: maSelectionListeners( *this )
|
|
, maTreeExpansionListeners( *this )
|
|
, maTreeEditListeners( *this )
|
|
, mpTreeImpl( 0 )
|
|
, mnEditLock( 0 )
|
|
, mpTreeNodeMap( 0 )
|
|
{
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
TreeControlPeer::~TreeControlPeer()
|
|
{
|
|
if( mpTreeImpl )
|
|
mpTreeImpl->Clear();
|
|
delete mpTreeNodeMap;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void TreeControlPeer::addEntry( UnoTreeListEntry* pEntry )
|
|
{
|
|
if( pEntry && pEntry->mxNode.is() )
|
|
{
|
|
if( !mpTreeNodeMap )
|
|
{
|
|
mpTreeNodeMap = new TreeNodeMap();
|
|
}
|
|
|
|
(*mpTreeNodeMap)[ pEntry->mxNode ] = pEntry;
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void TreeControlPeer::removeEntry( UnoTreeListEntry* pEntry )
|
|
{
|
|
if( mpTreeNodeMap && pEntry && pEntry->mxNode.is() )
|
|
{
|
|
TreeNodeMap::iterator aIter( mpTreeNodeMap->find( pEntry->mxNode ) );
|
|
if( aIter != mpTreeNodeMap->end() )
|
|
{
|
|
mpTreeNodeMap->erase( aIter );
|
|
}
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
UnoTreeListEntry* TreeControlPeer::getEntry( const Reference< XTreeNode >& xNode, bool bThrow /* = true */ ) throw( IllegalArgumentException )
|
|
{
|
|
if( mpTreeNodeMap )
|
|
{
|
|
TreeNodeMap::iterator aIter( mpTreeNodeMap->find( xNode ) );
|
|
if( aIter != mpTreeNodeMap->end() )
|
|
return (*aIter).second;
|
|
}
|
|
|
|
if( bThrow )
|
|
throw IllegalArgumentException();
|
|
|
|
return 0;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
Window* TreeControlPeer::createVclControl( Window* pParent, sal_Int64 nWinStyle )
|
|
{
|
|
mpTreeImpl = new UnoTreeListBoxImpl( this, pParent, nWinStyle );
|
|
return mpTreeImpl;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
/** called from the UnoTreeListBoxImpl when it gets deleted */
|
|
void TreeControlPeer::disposeControl()
|
|
{
|
|
delete mpTreeNodeMap;
|
|
mpTreeNodeMap = 0;
|
|
mpTreeImpl = 0;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void TreeControlPeer::SetWindow( Window* pWindow )
|
|
{
|
|
VCLXWindow::SetWindow( pWindow );
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
UnoTreeListEntry* TreeControlPeer::createEntry( const Reference< XTreeNode >& xNode, UnoTreeListEntry* pParent, ULONG nPos /* = LIST_APPEND */ )
|
|
{
|
|
UnoTreeListEntry* pEntry = 0;
|
|
if( mpTreeImpl )
|
|
{
|
|
Image aImage;
|
|
pEntry = new UnoTreeListEntry( xNode, this );
|
|
ImplContextGraphicItem* pContextBmp= new ImplContextGraphicItem( pEntry,0, aImage, aImage, SVLISTENTRYFLAG_EXPANDED );
|
|
|
|
pEntry->AddItem( pContextBmp );
|
|
|
|
UnoTreeListItem * pUnoItem = new UnoTreeListItem( pEntry );
|
|
|
|
if( xNode->getNodeGraphicURL().getLength() )
|
|
{
|
|
pUnoItem->SetGraphicURL( xNode->getNodeGraphicURL() );
|
|
Image aNodeImage;
|
|
loadImage( xNode->getNodeGraphicURL(), aNodeImage );
|
|
pUnoItem->SetImage( aNodeImage );
|
|
mpTreeImpl->AdjustEntryHeight( aNodeImage );
|
|
}
|
|
|
|
pEntry->AddItem( pUnoItem );
|
|
|
|
mpTreeImpl->insert( pEntry, pParent, nPos );
|
|
|
|
if( msDefaultExpandedGraphicURL.getLength() )
|
|
mpTreeImpl->SetExpandedEntryBmp( pEntry, maDefaultExpandedImage );
|
|
|
|
if( msDefaultCollapsedGraphicURL.getLength() )
|
|
mpTreeImpl->SetCollapsedEntryBmp( pEntry, maDefaultCollapsedImage );
|
|
|
|
updateEntry( pEntry );
|
|
}
|
|
return pEntry;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
bool TreeControlPeer::updateEntry( UnoTreeListEntry* pEntry )
|
|
{
|
|
bool bChanged = false;
|
|
if( pEntry && pEntry->mxNode.is() && mpTreeImpl )
|
|
{
|
|
const OUString aValue( getEntryString( pEntry->mxNode->getDisplayValue() ) );
|
|
UnoTreeListItem* pUnoItem = dynamic_cast< UnoTreeListItem* >( pEntry->GetItem( 1 ) );
|
|
if( pUnoItem )
|
|
{
|
|
if( aValue != pUnoItem->GetText() )
|
|
{
|
|
pUnoItem->SetText( aValue );
|
|
bChanged = true;
|
|
}
|
|
|
|
if( pUnoItem->GetGraphicURL() != pEntry->mxNode->getNodeGraphicURL() )
|
|
{
|
|
Image aImage;
|
|
if( loadImage( pEntry->mxNode->getNodeGraphicURL(), aImage ) )
|
|
{
|
|
pUnoItem->SetGraphicURL( pEntry->mxNode->getNodeGraphicURL() );
|
|
pUnoItem->SetImage( aImage );
|
|
mpTreeImpl->AdjustEntryHeight( aImage );
|
|
bChanged = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( (pEntry->mxNode->hasChildrenOnDemand() == sal_True) != (pEntry->HasChildsOnDemand() == TRUE) )
|
|
{
|
|
pEntry->EnableChildsOnDemand( pEntry->mxNode->hasChildrenOnDemand() ? TRUE : FALSE );
|
|
bChanged = true;
|
|
}
|
|
|
|
ImplContextGraphicItem* pContextGraphicItem = dynamic_cast< ImplContextGraphicItem* >( pEntry->GetItem( 0 ) );
|
|
if( pContextGraphicItem )
|
|
{
|
|
if( pContextGraphicItem->msExpandedGraphicURL != pEntry->mxNode->getExpandedGraphicURL() )
|
|
{
|
|
Image aImage;
|
|
if( loadImage( pEntry->mxNode->getExpandedGraphicURL(), aImage ) )
|
|
{
|
|
pContextGraphicItem->msExpandedGraphicURL = pEntry->mxNode->getExpandedGraphicURL();
|
|
mpTreeImpl->SetExpandedEntryBmp( pEntry, aImage );
|
|
bChanged = true;
|
|
}
|
|
}
|
|
if( pContextGraphicItem->msCollapsedGraphicURL != pEntry->mxNode->getCollapsedGraphicURL() )
|
|
{
|
|
Image aImage;
|
|
if( loadImage( pEntry->mxNode->getCollapsedGraphicURL(), aImage ) )
|
|
{
|
|
pContextGraphicItem->msCollapsedGraphicURL = pEntry->mxNode->getCollapsedGraphicURL();
|
|
mpTreeImpl->SetCollapsedEntryBmp( pEntry, aImage );
|
|
bChanged = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bChanged )
|
|
mpTreeImpl->GetModel()->InvalidateEntry( pEntry );
|
|
}
|
|
|
|
return bChanged;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void TreeControlPeer::onSelectionChanged()
|
|
{
|
|
Reference< XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
|
|
EventObject aEvent( xSource );
|
|
maSelectionListeners.selectionChanged( aEvent );
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void TreeControlPeer::onRequestChildNodes( const Reference< XTreeNode >& xNode )
|
|
{
|
|
try
|
|
{
|
|
Reference< XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
|
|
TreeExpansionEvent aEvent( xSource, xNode );
|
|
maTreeExpansionListeners.requestChildNodes( aEvent );
|
|
}
|
|
catch( Exception& )
|
|
{
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
bool TreeControlPeer::onExpanding( const Reference< XTreeNode >& xNode, bool bExpanding )
|
|
{
|
|
try
|
|
{
|
|
Reference< XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
|
|
TreeExpansionEvent aEvent( xSource, xNode );
|
|
if( bExpanding )
|
|
{
|
|
maTreeExpansionListeners.treeExpanding( aEvent );
|
|
}
|
|
else
|
|
{
|
|
maTreeExpansionListeners.treeCollapsing( aEvent );
|
|
}
|
|
}
|
|
catch( Exception& )
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void TreeControlPeer::onExpanded( const Reference< XTreeNode >& xNode, bool bExpanding )
|
|
{
|
|
try
|
|
{
|
|
Reference< XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
|
|
TreeExpansionEvent aEvent( xSource, xNode );
|
|
|
|
if( bExpanding )
|
|
{
|
|
maTreeExpansionListeners.treeExpanded( aEvent );
|
|
}
|
|
else
|
|
{
|
|
maTreeExpansionListeners.treeCollapsed( aEvent );
|
|
}
|
|
}
|
|
catch( Exception& )
|
|
{
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void TreeControlPeer::fillTree( UnoTreeListBoxImpl& rTree, const Reference< XTreeDataModel >& xDataModel )
|
|
{
|
|
rTree.Clear();
|
|
|
|
if( xDataModel.is() )
|
|
{
|
|
Reference< XTreeNode > xRootNode( xDataModel->getRoot() );
|
|
if( xRootNode.is() )
|
|
{
|
|
if( mbIsRootDisplayed )
|
|
{
|
|
addNode( rTree, xRootNode, 0 );
|
|
}
|
|
else
|
|
{
|
|
const sal_Int32 nChildCount = xRootNode->getChildCount();
|
|
for( sal_Int32 nChild = 0; nChild < nChildCount; nChild++ )
|
|
addNode( rTree, xRootNode->getChildAt( nChild ), 0 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void TreeControlPeer::addNode( UnoTreeListBoxImpl& rTree, const Reference< XTreeNode >& xNode, UnoTreeListEntry* pParentEntry )
|
|
{
|
|
if( xNode.is() )
|
|
{
|
|
UnoTreeListEntry* pEntry = createEntry( xNode, pParentEntry, LIST_APPEND );
|
|
const sal_Int32 nChildCount = xNode->getChildCount();
|
|
for( sal_Int32 nChild = 0; nChild < nChildCount; nChild++ )
|
|
addNode( rTree, xNode->getChildAt( nChild ), pEntry );
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
UnoTreeListBoxImpl& TreeControlPeer::getTreeListBoxOrThrow() const throw (RuntimeException )
|
|
{
|
|
if( !mpTreeImpl )
|
|
throw DisposedException();
|
|
return *mpTreeImpl;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void TreeControlPeer::ChangeNodesSelection( const Any& rSelection, bool bSelect, bool bSetSelection ) throw( RuntimeException, IllegalArgumentException )
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
|
|
Reference< XTreeNode > xTempNode;
|
|
Sequence< XTreeNode > aTempSeq;
|
|
|
|
const Reference< XTreeNode > *pNodes = 0;
|
|
sal_Int32 nCount = 0;
|
|
|
|
if( rSelection.hasValue() )
|
|
{
|
|
switch( rSelection.getValueTypeClass() )
|
|
{
|
|
case TypeClass_INTERFACE:
|
|
{
|
|
rSelection >>= xTempNode;
|
|
if( xTempNode.is() )
|
|
{
|
|
nCount = 1;
|
|
pNodes = &xTempNode;
|
|
}
|
|
break;
|
|
}
|
|
case TypeClass_SEQUENCE:
|
|
{
|
|
if( rSelection.getValueType() == ::getCppuType( (const Sequence< Reference< XTreeNode > > *) 0 ) )
|
|
{
|
|
const Sequence< Reference< XTreeNode > >& rSeq( *(const Sequence< Reference< XTreeNode > > *)rSelection.getValue() );
|
|
nCount = rSeq.getLength();
|
|
if( nCount )
|
|
pNodes = rSeq.getConstArray();
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if( nCount == 0 )
|
|
throw IllegalArgumentException();
|
|
}
|
|
|
|
if( bSetSelection )
|
|
rTree.SelectAll( FALSE );
|
|
|
|
if( pNodes && nCount )
|
|
{
|
|
while( nCount-- )
|
|
{
|
|
UnoTreeListEntry* pEntry = getEntry( *pNodes++ );
|
|
rTree.Select( pEntry, bSelect ? TRUE : FALSE );
|
|
}
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
// ::com::sun::star::view::XSelectionSupplier
|
|
// -------------------------------------------------------------------
|
|
|
|
sal_Bool SAL_CALL TreeControlPeer::select( const Any& rSelection ) throw (IllegalArgumentException, RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
ChangeNodesSelection( rSelection, true, true );
|
|
return sal_True;
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
Any SAL_CALL TreeControlPeer::getSelection() throw (RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
|
|
Any aRet;
|
|
|
|
ULONG nSelectionCount = rTree.GetSelectionCount();
|
|
if( nSelectionCount == 1 )
|
|
{
|
|
UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.FirstSelected() );
|
|
if( pEntry && pEntry->mxNode.is() )
|
|
aRet <<= pEntry->mxNode;
|
|
}
|
|
else if( nSelectionCount > 1 )
|
|
{
|
|
Sequence< Reference< XTreeNode > > aSelection( nSelectionCount );
|
|
Reference< XTreeNode >* pNodes = aSelection.getArray();
|
|
UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.FirstSelected() );
|
|
while( pEntry && nSelectionCount )
|
|
{
|
|
*pNodes++ = pEntry->mxNode;
|
|
pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.NextSelected( pEntry ) );
|
|
--nSelectionCount;
|
|
}
|
|
|
|
OSL_ASSERT( (pEntry == 0) && (nSelectionCount == 0) );
|
|
aRet <<= aSelection;
|
|
}
|
|
|
|
return aRet;
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
void SAL_CALL TreeControlPeer::addSelectionChangeListener( const Reference< XSelectionChangeListener >& xListener ) throw (RuntimeException)
|
|
{
|
|
maSelectionListeners.addInterface( xListener );
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
void SAL_CALL TreeControlPeer::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& xListener ) throw (RuntimeException)
|
|
{
|
|
maSelectionListeners.addInterface( xListener );
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
// ::com::sun::star::view::XMultiSelectionSupplier
|
|
// -------------------------------------------------------------------
|
|
|
|
sal_Bool SAL_CALL TreeControlPeer::addSelection( const Any& rSelection ) throw (IllegalArgumentException, RuntimeException)
|
|
{
|
|
ChangeNodesSelection( rSelection, true, false );
|
|
return sal_True;
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
void SAL_CALL TreeControlPeer::removeSelection( const Any& rSelection ) throw (IllegalArgumentException, RuntimeException)
|
|
{
|
|
ChangeNodesSelection( rSelection, false, false );
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
void SAL_CALL TreeControlPeer::clearSelection() throw (RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
getTreeListBoxOrThrow().SelectAll( FALSE );
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
sal_Int32 SAL_CALL TreeControlPeer::getSelectionCount() throw (RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
return getTreeListBoxOrThrow().GetSelectionCount();
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
class TreeSelectionEnumeration : public ::cppu::WeakImplHelper1< XEnumeration >
|
|
{
|
|
public:
|
|
TreeSelectionEnumeration( std::list< Any >& rSelection );
|
|
virtual ::sal_Bool SAL_CALL hasMoreElements() throw (RuntimeException);
|
|
virtual Any SAL_CALL nextElement() throw (NoSuchElementException, WrappedTargetException, RuntimeException);
|
|
|
|
std::list< Any > maSelection;
|
|
std::list< Any >::iterator maIter;
|
|
};
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
TreeSelectionEnumeration::TreeSelectionEnumeration( std::list< Any >& rSelection )
|
|
{
|
|
maSelection.swap( rSelection );
|
|
maIter = maSelection.begin();
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
::sal_Bool SAL_CALL TreeSelectionEnumeration::hasMoreElements() throw (RuntimeException)
|
|
{
|
|
return maIter != maSelection.end();
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
Any SAL_CALL TreeSelectionEnumeration::nextElement() throw (NoSuchElementException, WrappedTargetException, RuntimeException)
|
|
{
|
|
if( maIter == maSelection.end() )
|
|
throw NoSuchElementException();
|
|
|
|
return (*maIter++);
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
Reference< XEnumeration > SAL_CALL TreeControlPeer::createSelectionEnumeration() throw (RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
|
|
sal_uInt32 nSelectionCount = rTree.GetSelectionCount();
|
|
std::list< Any > aSelection( nSelectionCount );
|
|
|
|
UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.FirstSelected() );
|
|
while( pEntry && nSelectionCount )
|
|
{
|
|
aSelection.push_back( Any( pEntry->mxNode ) );
|
|
pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.NextSelected( pEntry ) );
|
|
--nSelectionCount;
|
|
}
|
|
|
|
OSL_ASSERT( (pEntry == 0) && (nSelectionCount == 0) );
|
|
|
|
return Reference< XEnumeration >( new TreeSelectionEnumeration( aSelection ) );
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
Reference< XEnumeration > SAL_CALL TreeControlPeer::createReverseSelectionEnumeration() throw (RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
|
|
sal_uInt32 nSelectionCount = rTree.GetSelectionCount();
|
|
std::list< Any > aSelection;
|
|
|
|
UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.FirstSelected() );
|
|
while( pEntry && nSelectionCount )
|
|
{
|
|
aSelection.push_front( Any( pEntry->mxNode ) );
|
|
pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.NextSelected( pEntry ) );
|
|
--nSelectionCount;
|
|
}
|
|
|
|
OSL_ASSERT( (pEntry == 0) && (nSelectionCount == 0) );
|
|
|
|
return Reference< XEnumeration >( new TreeSelectionEnumeration( aSelection ) );
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// ::com::sun::star::awt::XTreeControl
|
|
// --------------------------------------------------------------------
|
|
|
|
OUString SAL_CALL TreeControlPeer::getDefaultExpandedGraphicURL() throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
return msDefaultExpandedGraphicURL;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void SAL_CALL TreeControlPeer::setDefaultExpandedGraphicURL( const ::rtl::OUString& sDefaultExpandedGraphicURL ) throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
if( msDefaultExpandedGraphicURL != sDefaultExpandedGraphicURL )
|
|
{
|
|
if( sDefaultExpandedGraphicURL.getLength() )
|
|
loadImage( sDefaultExpandedGraphicURL, maDefaultExpandedImage );
|
|
else
|
|
maDefaultExpandedImage = Image();
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
|
|
SvLBoxEntry* pEntry = rTree.First();
|
|
while( pEntry )
|
|
{
|
|
ImplContextGraphicItem* pContextGraphicItem = dynamic_cast< ImplContextGraphicItem* >( pEntry->GetItem( 0 ) );
|
|
if( pContextGraphicItem )
|
|
{
|
|
if( pContextGraphicItem->msExpandedGraphicURL.getLength() == 0 )
|
|
rTree.SetExpandedEntryBmp( pEntry, maDefaultExpandedImage );
|
|
}
|
|
pEntry = rTree.Next( pEntry );
|
|
}
|
|
|
|
msDefaultExpandedGraphicURL = sDefaultExpandedGraphicURL;
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
OUString SAL_CALL TreeControlPeer::getDefaultCollapsedGraphicURL() throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
return msDefaultCollapsedGraphicURL;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void SAL_CALL TreeControlPeer::setDefaultCollapsedGraphicURL( const ::rtl::OUString& sDefaultCollapsedGraphicURL ) throw (::com::sun::star::uno::RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
if( msDefaultCollapsedGraphicURL != sDefaultCollapsedGraphicURL )
|
|
{
|
|
if( sDefaultCollapsedGraphicURL.getLength() )
|
|
loadImage( sDefaultCollapsedGraphicURL, maDefaultCollapsedImage );
|
|
else
|
|
maDefaultCollapsedImage = Image();
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
|
|
SvLBoxEntry* pEntry = rTree.First();
|
|
while( pEntry )
|
|
{
|
|
ImplContextGraphicItem* pContextGraphicItem = dynamic_cast< ImplContextGraphicItem* >( pEntry->GetItem( 0 ) );
|
|
if( pContextGraphicItem )
|
|
{
|
|
if( pContextGraphicItem->msCollapsedGraphicURL.getLength() == 0 )
|
|
rTree.SetCollapsedEntryBmp( pEntry, maDefaultCollapsedImage );
|
|
}
|
|
pEntry = rTree.Next( pEntry );
|
|
}
|
|
|
|
msDefaultCollapsedGraphicURL = sDefaultCollapsedGraphicURL;
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
sal_Bool SAL_CALL TreeControlPeer::isNodeExpanded( const Reference< XTreeNode >& xNode ) throw (RuntimeException, IllegalArgumentException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
UnoTreeListEntry* pEntry = getEntry( xNode );
|
|
return ( pEntry && rTree.IsExpanded( pEntry ) ) ? sal_True : sal_False;
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
sal_Bool SAL_CALL TreeControlPeer::isNodeCollapsed( const Reference< XTreeNode >& xNode ) throw (RuntimeException, IllegalArgumentException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
return !isNodeExpanded( xNode );
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
void SAL_CALL TreeControlPeer::makeNodeVisible( const Reference< XTreeNode >& xNode ) throw (RuntimeException, ExpandVetoException, IllegalArgumentException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
UnoTreeListEntry* pEntry = getEntry( xNode );
|
|
if( pEntry )
|
|
rTree.MakeVisible( pEntry );
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
sal_Bool SAL_CALL TreeControlPeer::isNodeVisible( const Reference< XTreeNode >& xNode ) throw (RuntimeException, IllegalArgumentException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
UnoTreeListEntry* pEntry = getEntry( xNode );
|
|
return ( pEntry && rTree.IsEntryVisible( pEntry ) ) ? sal_True : sal_False;
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
void SAL_CALL TreeControlPeer::expandNode( const Reference< XTreeNode >& xNode ) throw (RuntimeException, ExpandVetoException, IllegalArgumentException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
UnoTreeListEntry* pEntry = getEntry( xNode );
|
|
if( pEntry )
|
|
rTree.Expand( pEntry );
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
void SAL_CALL TreeControlPeer::collapseNode( const Reference< XTreeNode >& xNode ) throw (RuntimeException, ExpandVetoException, IllegalArgumentException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
UnoTreeListEntry* pEntry = getEntry( xNode );
|
|
if( pEntry )
|
|
rTree.Collapse( pEntry );
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
void SAL_CALL TreeControlPeer::addTreeExpansionListener( const Reference< XTreeExpansionListener >& xListener ) throw (RuntimeException)
|
|
{
|
|
maTreeExpansionListeners.addInterface( xListener );
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
void SAL_CALL TreeControlPeer::removeTreeExpansionListener( const Reference< XTreeExpansionListener >& xListener ) throw (RuntimeException)
|
|
{
|
|
maTreeExpansionListeners.removeInterface( xListener );
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
Reference< XTreeNode > SAL_CALL TreeControlPeer::getNodeForLocation( sal_Int32 x, sal_Int32 y ) throw (RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
|
|
Reference< XTreeNode > xNode;
|
|
|
|
const Point aPos( x, y );
|
|
UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.GetEntry( aPos, TRUE ) );
|
|
if( pEntry )
|
|
xNode = pEntry->mxNode;
|
|
|
|
return xNode;
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
Reference< XTreeNode > SAL_CALL TreeControlPeer::getClosestNodeForLocation( sal_Int32 x, sal_Int32 y ) throw (RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
|
|
Reference< XTreeNode > xNode;
|
|
|
|
const Point aPos( x, y );
|
|
UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.GetEntry( aPos, TRUE ) );
|
|
if( pEntry )
|
|
xNode = pEntry->mxNode;
|
|
|
|
return xNode;
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
awt::Rectangle SAL_CALL TreeControlPeer::getNodeRect( const Reference< XTreeNode >& i_Node ) throw (IllegalArgumentException, RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
UnoTreeListEntry* pEntry = getEntry( i_Node, true );
|
|
|
|
::Rectangle aEntryRect( rTree.GetFocusRect( pEntry, rTree.GetEntryPosition( pEntry ).Y() ) );
|
|
return VCLUnoHelper::ConvertToAWTRect( aEntryRect );
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
sal_Bool SAL_CALL TreeControlPeer::isEditing( ) throw (RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
return rTree.IsEditingActive() ? sal_True : sal_False;
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
sal_Bool SAL_CALL TreeControlPeer::stopEditing() throw (RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
if( rTree.IsEditingActive() )
|
|
{
|
|
rTree.EndEditing(FALSE);
|
|
return sal_True;
|
|
}
|
|
else
|
|
{
|
|
return sal_False;
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
void SAL_CALL TreeControlPeer::cancelEditing( ) throw (RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
rTree.EndEditing(FALSE);
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
|
|
void SAL_CALL TreeControlPeer::startEditingAtNode( const Reference< XTreeNode >& xNode ) throw (IllegalArgumentException, RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
UnoTreeListEntry* pEntry = getEntry( xNode );
|
|
rTree.EditEntry( pEntry );
|
|
}
|
|
|
|
void SAL_CALL TreeControlPeer::addTreeEditListener( const Reference< XTreeEditListener >& xListener ) throw (RuntimeException)
|
|
{
|
|
maTreeEditListeners.addInterface( xListener );
|
|
}
|
|
|
|
void SAL_CALL TreeControlPeer::removeTreeEditListener( const Reference< XTreeEditListener >& xListener ) throw (RuntimeException)
|
|
{
|
|
maTreeEditListeners.removeInterface( xListener );
|
|
}
|
|
|
|
bool TreeControlPeer::onEditingEntry( UnoTreeListEntry* pEntry )
|
|
{
|
|
if( mpTreeImpl && pEntry && pEntry->mxNode.is() && (maTreeEditListeners.getLength() > 0) )
|
|
{
|
|
try
|
|
{
|
|
maTreeEditListeners.nodeEditing( pEntry->mxNode );
|
|
}
|
|
catch( VetoException& )
|
|
{
|
|
return false;
|
|
}
|
|
catch( Exception& )
|
|
{
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool TreeControlPeer::onEditedEntry( UnoTreeListEntry* pEntry, const XubString& rNewText )
|
|
{
|
|
if( mpTreeImpl && pEntry && pEntry->mxNode.is() ) try
|
|
{
|
|
LockGuard aLockGuard( mnEditLock );
|
|
const OUString aNewText( rNewText );
|
|
if( maTreeEditListeners.getLength() > 0 )
|
|
{
|
|
maTreeEditListeners.nodeEdited( pEntry->mxNode, aNewText );
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
Reference< XMutableTreeNode > xMutableNode( pEntry->mxNode, UNO_QUERY );
|
|
if( xMutableNode.is() )
|
|
xMutableNode->setDisplayValue( Any( aNewText ) );
|
|
else
|
|
return false;
|
|
}
|
|
|
|
}
|
|
catch( Exception& )
|
|
{
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// ::com::sun::star::awt::tree::TreeDataModelListener
|
|
// --------------------------------------------------------------------
|
|
|
|
void SAL_CALL TreeControlPeer::treeNodesChanged( const ::com::sun::star::awt::tree::TreeDataModelEvent& rEvent ) throw (RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
if( mnEditLock != 0 )
|
|
return;
|
|
|
|
updateTree( rEvent, true );
|
|
}
|
|
|
|
void SAL_CALL TreeControlPeer::treeNodesInserted( const ::com::sun::star::awt::tree::TreeDataModelEvent& rEvent ) throw (RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
if( mnEditLock != 0 )
|
|
return;
|
|
|
|
updateTree( rEvent, true );
|
|
}
|
|
|
|
void SAL_CALL TreeControlPeer::treeNodesRemoved( const ::com::sun::star::awt::tree::TreeDataModelEvent& rEvent ) throw (RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
if( mnEditLock != 0 )
|
|
return;
|
|
|
|
updateTree( rEvent, true );
|
|
}
|
|
|
|
void SAL_CALL TreeControlPeer::treeStructureChanged( const ::com::sun::star::awt::tree::TreeDataModelEvent& rEvent ) throw (RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
if( mnEditLock != 0 )
|
|
return;
|
|
|
|
updateTree( rEvent, true );
|
|
}
|
|
|
|
void TreeControlPeer::updateTree( const ::com::sun::star::awt::tree::TreeDataModelEvent& rEvent, bool bRecursive )
|
|
{
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
|
|
Sequence< Reference< XTreeNode > > Nodes;
|
|
Reference< XTreeNode > xNode( rEvent.ParentNode );
|
|
if( !xNode.is() && Nodes.getLength() )
|
|
{
|
|
xNode = Nodes[0];
|
|
}
|
|
|
|
if( xNode.is() )
|
|
updateNode( rTree, xNode, bRecursive );
|
|
}
|
|
|
|
void TreeControlPeer::updateNode( UnoTreeListBoxImpl& rTree, const Reference< XTreeNode >& xNode, bool bRecursive )
|
|
{
|
|
if( xNode.is() )
|
|
{
|
|
UnoTreeListEntry* pNodeEntry = getEntry( xNode, false );
|
|
|
|
if( !pNodeEntry )
|
|
{
|
|
Reference< XTreeNode > xParentNode( xNode->getParent() );
|
|
UnoTreeListEntry* pParentEntry = 0;
|
|
ULONG nChild = LIST_APPEND;
|
|
|
|
if( xParentNode.is() )
|
|
{
|
|
pParentEntry = getEntry( xParentNode );
|
|
nChild = xParentNode->getIndex( xNode );
|
|
}
|
|
|
|
pNodeEntry = createEntry( xNode, pParentEntry, nChild );
|
|
}
|
|
|
|
if( bRecursive )
|
|
updateChildNodes( rTree, xNode, pNodeEntry );
|
|
}
|
|
}
|
|
|
|
void TreeControlPeer::updateChildNodes( UnoTreeListBoxImpl& rTree, const Reference< XTreeNode >& xParentNode, UnoTreeListEntry* pParentEntry )
|
|
{
|
|
if( xParentNode.is() && pParentEntry )
|
|
{
|
|
UnoTreeListEntry* pCurrentChild = dynamic_cast< UnoTreeListEntry* >( rTree.FirstChild( pParentEntry ) );
|
|
|
|
const sal_Int32 nChildCount = xParentNode->getChildCount();
|
|
for( sal_Int32 nChild = 0; nChild < nChildCount; nChild++ )
|
|
{
|
|
Reference< XTreeNode > xNode( xParentNode->getChildAt( nChild ) );
|
|
if( !pCurrentChild || ( pCurrentChild->mxNode != xNode ) )
|
|
{
|
|
UnoTreeListEntry* pNodeEntry = getEntry( xNode, false );
|
|
if( pNodeEntry == 0 )
|
|
{
|
|
// child node is not yet part of the tree, add it
|
|
pCurrentChild = createEntry( xNode, pParentEntry, nChild );
|
|
}
|
|
else if( pNodeEntry != pCurrentChild )
|
|
{
|
|
// node is already part of the tree, but not on the correct position
|
|
rTree.GetModel()->Move( pNodeEntry, pParentEntry, nChild );
|
|
pCurrentChild = pNodeEntry;
|
|
updateEntry( pCurrentChild );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// child node has entry and entry is equal to current entry,
|
|
// so no structural changes happened
|
|
updateEntry( pCurrentChild );
|
|
}
|
|
|
|
pCurrentChild = dynamic_cast< UnoTreeListEntry* >( rTree.NextSibling( pCurrentChild ) );
|
|
}
|
|
|
|
// check if we have entries without nodes left, we need to remove them
|
|
while( pCurrentChild )
|
|
{
|
|
UnoTreeListEntry* pNextChild = dynamic_cast< UnoTreeListEntry* >( rTree.NextSibling( pCurrentChild ) );
|
|
rTree.GetModel()->Remove( pCurrentChild );
|
|
pCurrentChild = pNextChild;
|
|
}
|
|
}
|
|
}
|
|
|
|
OUString TreeControlPeer::getEntryString( const Any& rValue )
|
|
{
|
|
OUString sValue;
|
|
if( rValue.hasValue() )
|
|
{
|
|
switch( rValue.getValueTypeClass() )
|
|
{
|
|
case TypeClass_SHORT:
|
|
case TypeClass_LONG:
|
|
{
|
|
sal_Int32 nValue = 0;
|
|
if( rValue >>= nValue )
|
|
sValue = OUString::valueOf( nValue );
|
|
break;
|
|
}
|
|
case TypeClass_BYTE:
|
|
case TypeClass_UNSIGNED_SHORT:
|
|
case TypeClass_UNSIGNED_LONG:
|
|
{
|
|
sal_uInt32 nValue = 0;
|
|
if( rValue >>= nValue )
|
|
sValue = OUString::valueOf( (sal_Int64)nValue );
|
|
break;
|
|
}
|
|
case TypeClass_HYPER:
|
|
{
|
|
sal_Int64 nValue = 0;
|
|
if( rValue >>= nValue )
|
|
sValue = OUString::valueOf( nValue );
|
|
break;
|
|
}
|
|
case TypeClass_UNSIGNED_HYPER:
|
|
{
|
|
sal_uInt64 nValue = 0;
|
|
if( rValue >>= nValue )
|
|
sValue = OUString::valueOf( (sal_Int64)nValue );
|
|
break;
|
|
}
|
|
case TypeClass_FLOAT:
|
|
case TypeClass_DOUBLE:
|
|
{
|
|
double fValue = 0.0;
|
|
if( rValue >>= fValue )
|
|
sValue = OUString::valueOf( fValue );
|
|
break;
|
|
}
|
|
case TypeClass_STRING:
|
|
rValue >>= sValue;
|
|
break;
|
|
/*
|
|
case TypeClass_INTERFACE:
|
|
// @todo
|
|
break;
|
|
case TypeClass_SEQUENCE:
|
|
{
|
|
Sequence< Any > aValues;
|
|
if( aValue >>= aValues )
|
|
{
|
|
updateEntry( SvLBoxEntry& rEntry, aValues );
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
*/
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return sValue;
|
|
}
|
|
|
|
// XEventListener
|
|
void SAL_CALL TreeControlPeer::disposing( const ::com::sun::star::lang::EventObject& ) throw(::com::sun::star::uno::RuntimeException)
|
|
{
|
|
// model is disposed, so we clear our tree
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
rTree.Clear();
|
|
mxDataModel.clear();
|
|
}
|
|
|
|
void TreeControlPeer::onChangeDataModel( UnoTreeListBoxImpl& rTree, const Reference< XTreeDataModel >& xDataModel )
|
|
{
|
|
if( xDataModel.is() && (mxDataModel == xDataModel) )
|
|
return; // do nothing
|
|
|
|
Reference< XTreeDataModelListener > xListener( this );
|
|
|
|
if( mxDataModel.is() )
|
|
mxDataModel->removeTreeDataModelListener( xListener );
|
|
|
|
if( !xDataModel.is() )
|
|
{
|
|
static const OUString aSN( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.tree.DefaultTreeDataModel" ) );
|
|
Reference< XMultiServiceFactory > xORB( ::comphelper::getProcessServiceFactory() );
|
|
if( xORB.is() )
|
|
{
|
|
mxDataModel.query( xORB->createInstance( aSN ) );
|
|
}
|
|
}
|
|
|
|
mxDataModel = xDataModel;
|
|
|
|
fillTree( rTree, mxDataModel );
|
|
|
|
if( mxDataModel.is() )
|
|
mxDataModel->addTreeDataModelListener( xListener );
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// ::com::sun::star::awt::XLayoutConstrains
|
|
// --------------------------------------------------------------------
|
|
|
|
::com::sun::star::awt::Size TreeControlPeer::getMinimumSize() throw(RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
::com::sun::star::awt::Size aSz;
|
|
/* todo
|
|
MultiLineEdit* pEdit = (MultiLineEdit*) GetWindow();
|
|
if ( pEdit )
|
|
aSz = AWTSize(pEdit->CalcMinimumSize());
|
|
*/
|
|
return aSz;
|
|
}
|
|
|
|
::com::sun::star::awt::Size TreeControlPeer::getPreferredSize() throw(RuntimeException)
|
|
{
|
|
return getMinimumSize();
|
|
}
|
|
|
|
::com::sun::star::awt::Size TreeControlPeer::calcAdjustedSize( const ::com::sun::star::awt::Size& rNewSize ) throw(RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
::com::sun::star::awt::Size aSz = rNewSize;
|
|
/* todo
|
|
MultiLineEdit* pEdit = (MultiLineEdit*) GetWindow();
|
|
if ( pEdit )
|
|
aSz = AWTSize(pEdit->CalcAdjustedSize( VCLSize(rNewSize )));
|
|
*/
|
|
return aSz;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// ::com::sun::star::awt::XVclWindowPeer
|
|
// --------------------------------------------------------------------
|
|
|
|
void TreeControlPeer::setProperty( const ::rtl::OUString& PropertyName, const Any& aValue) throw(RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
|
|
switch( GetPropertyId( PropertyName ) )
|
|
{
|
|
case BASEPROPERTY_TREE_SELECTIONTYPE:
|
|
{
|
|
SelectionType eSelectionType;
|
|
if( aValue >>= eSelectionType )
|
|
{
|
|
SelectionMode eSelMode;
|
|
switch( eSelectionType )
|
|
{
|
|
case SelectionType_SINGLE: eSelMode = SINGLE_SELECTION; break;
|
|
case SelectionType_RANGE: eSelMode = RANGE_SELECTION; break;
|
|
case SelectionType_MULTI: eSelMode = MULTIPLE_SELECTION; break;
|
|
// case SelectionType_NONE:
|
|
default: eSelMode = NO_SELECTION; break;
|
|
}
|
|
if( rTree.GetSelectionMode() != eSelMode )
|
|
rTree.SetSelectionMode( eSelMode );
|
|
}
|
|
break;
|
|
}
|
|
|
|
case BASEPROPERTY_TREE_DATAMODEL:
|
|
onChangeDataModel( rTree, Reference< XTreeDataModel >( aValue, UNO_QUERY ) );
|
|
break;
|
|
case BASEPROPERTY_TREE_ROWHEIGHT:
|
|
{
|
|
sal_Int32 nHeight = 0;
|
|
if( aValue >>= nHeight )
|
|
rTree.SetEntryHeight( (short)nHeight );
|
|
break;
|
|
}
|
|
case BASEPROPERTY_TREE_EDITABLE:
|
|
{
|
|
sal_Bool bEnabled = false;
|
|
if( aValue >>= bEnabled )
|
|
rTree.EnableInplaceEditing( bEnabled ? TRUE : FALSE );
|
|
break;
|
|
}
|
|
case BASEPROPERTY_TREE_INVOKESSTOPNODEEDITING:
|
|
break; // @todo
|
|
case BASEPROPERTY_TREE_ROOTDISPLAYED:
|
|
{
|
|
sal_Bool bDisplayed = false;
|
|
if( (aValue >>= bDisplayed) && ( bDisplayed != mbIsRootDisplayed) )
|
|
{
|
|
onChangeRootDisplayed(bDisplayed);
|
|
}
|
|
break;
|
|
}
|
|
case BASEPROPERTY_TREE_SHOWSHANDLES:
|
|
{
|
|
sal_Bool bEnabled = false;
|
|
if( aValue >>= bEnabled )
|
|
{
|
|
WinBits nBits = rTree.GetWindowBits() & (~WB_HASLINES);
|
|
if( bEnabled )
|
|
nBits |= WB_HASLINES;
|
|
if( nBits != rTree.GetWindowBits() )
|
|
rTree.SetWindowBits( nBits );
|
|
}
|
|
break;
|
|
}
|
|
case BASEPROPERTY_TREE_SHOWSROOTHANDLES:
|
|
{
|
|
sal_Bool bEnabled = false;
|
|
if( aValue >>= bEnabled )
|
|
{
|
|
WinBits nBits = rTree.GetWindowBits() & (~WB_HASLINESATROOT);
|
|
if( bEnabled )
|
|
nBits |= WB_HASLINESATROOT;
|
|
if( nBits != rTree.GetWindowBits() )
|
|
rTree.SetWindowBits( nBits );
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
VCLXWindow::setProperty( PropertyName, aValue );
|
|
break;
|
|
}
|
|
}
|
|
|
|
Any TreeControlPeer::getProperty( const ::rtl::OUString& PropertyName ) throw(RuntimeException)
|
|
{
|
|
::vos::OGuard aGuard( GetMutex() );
|
|
|
|
const sal_uInt16 nPropId = GetPropertyId( PropertyName );
|
|
if( (nPropId >= BASEPROPERTY_TREE_START) && (nPropId <= BASEPROPERTY_TREE_END) )
|
|
{
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
switch(nPropId)
|
|
{
|
|
case BASEPROPERTY_TREE_SELECTIONTYPE:
|
|
{
|
|
SelectionType eSelectionType;
|
|
|
|
SelectionMode eSelMode = rTree.GetSelectionMode();
|
|
switch( eSelMode )
|
|
{
|
|
case SINGLE_SELECTION: eSelectionType = SelectionType_SINGLE; break;
|
|
case RANGE_SELECTION: eSelectionType = SelectionType_RANGE; break;
|
|
case MULTIPLE_SELECTION:eSelectionType = SelectionType_MULTI; break;
|
|
// case NO_SELECTION:
|
|
default: eSelectionType = SelectionType_NONE; break;
|
|
}
|
|
return Any( eSelectionType );
|
|
}
|
|
case BASEPROPERTY_TREE_ROWHEIGHT:
|
|
return Any( (sal_Int32)rTree.GetEntryHeight() );
|
|
case BASEPROPERTY_TREE_DATAMODEL:
|
|
return Any( mxDataModel );
|
|
case BASEPROPERTY_TREE_EDITABLE:
|
|
return Any( rTree.IsInplaceEditingEnabled() ? sal_True : sal_False );
|
|
case BASEPROPERTY_TREE_INVOKESSTOPNODEEDITING:
|
|
return Any( sal_True ); // @todo
|
|
case BASEPROPERTY_TREE_ROOTDISPLAYED:
|
|
return Any( mbIsRootDisplayed );
|
|
case BASEPROPERTY_TREE_SHOWSHANDLES:
|
|
return Any( (rTree.GetWindowBits() & WB_HASLINES) != 0 ? sal_True : sal_False );
|
|
case BASEPROPERTY_TREE_SHOWSROOTHANDLES:
|
|
return Any( (rTree.GetWindowBits() & WB_HASLINESATROOT) != 0 ? sal_True : sal_False );
|
|
}
|
|
}
|
|
return VCLXWindow::getProperty( PropertyName );
|
|
}
|
|
|
|
void TreeControlPeer::onChangeRootDisplayed( sal_Bool bIsRootDisplayed )
|
|
{
|
|
if( mbIsRootDisplayed == bIsRootDisplayed )
|
|
return;
|
|
|
|
mbIsRootDisplayed = bIsRootDisplayed;
|
|
|
|
UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
|
|
|
|
if( rTree.GetEntryCount() == 0 )
|
|
return;
|
|
|
|
// todo
|
|
fillTree( rTree, mxDataModel );
|
|
if( mbIsRootDisplayed )
|
|
{
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
|
|
bool TreeControlPeer::loadImage( const ::rtl::OUString& rURL, Image& rImage )
|
|
{
|
|
if( !mxGraphicProvider.is() )
|
|
{
|
|
static const OUString aSN( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.graphic.GraphicProvider" ) );
|
|
Reference< XMultiServiceFactory > xORB( ::comphelper::getProcessServiceFactory() );
|
|
if( xORB.is() )
|
|
{
|
|
Reference< XInterface > x( xORB->createInstance( aSN ) );
|
|
mxGraphicProvider.query( x );
|
|
mxGraphicProvider = Reference< XGraphicProvider >( x, UNO_QUERY );
|
|
}
|
|
}
|
|
|
|
if( mxGraphicProvider.is() ) try
|
|
{
|
|
::com::sun::star::beans::PropertyValues aProps( 1 );
|
|
aProps[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
|
|
aProps[0].Value <<= rURL;
|
|
|
|
Reference< XGraphic > xGraphic( mxGraphicProvider->queryGraphic( aProps ) );
|
|
|
|
Graphic aGraphic( xGraphic );
|
|
rImage = aGraphic.GetBitmapEx();
|
|
return true;
|
|
}
|
|
catch( Exception& )
|
|
{
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// ====================================================================
|
|
// class UnoTreeListBoxImpl
|
|
// ====================================================================
|
|
|
|
UnoTreeListBoxImpl::UnoTreeListBoxImpl( TreeControlPeer* pPeer, Window* pParent, WinBits nWinStyle )
|
|
: SvTreeListBox( pParent, nWinStyle )
|
|
, mxPeer( pPeer )
|
|
{
|
|
SetWindowBits( WB_BORDER | WB_HASLINES |WB_HASBUTTONS | WB_HASLINESATROOT | WB_HASBUTTONSATROOT | WB_HSCROLL );
|
|
SetNodeDefaultImages();
|
|
SetSelectHdl( LINK(this, UnoTreeListBoxImpl, OnSelectionChangeHdl) );
|
|
SetDeselectHdl( LINK(this, UnoTreeListBoxImpl, OnSelectionChangeHdl) );
|
|
|
|
SetExpandingHdl( LINK(this, UnoTreeListBoxImpl, OnExpandingHdl) );
|
|
SetExpandedHdl( LINK(this, UnoTreeListBoxImpl, OnExpandedHdl) );
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
UnoTreeListBoxImpl::~UnoTreeListBoxImpl()
|
|
{
|
|
if( mxPeer.is() )
|
|
mxPeer->disposeControl();
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
IMPL_LINK( UnoTreeListBoxImpl, OnSelectionChangeHdl, UnoTreeListBoxImpl*, EMPTYARG )
|
|
{
|
|
if( mxPeer.is() )
|
|
mxPeer->onSelectionChanged();
|
|
return 0;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
IMPL_LINK(UnoTreeListBoxImpl, OnExpandingHdl, UnoTreeListBoxImpl*, EMPTYARG )
|
|
{
|
|
UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( GetHdlEntry() );
|
|
|
|
if( pEntry && mxPeer.is() )
|
|
{
|
|
return mxPeer->onExpanding( pEntry->mxNode, !IsExpanded( pEntry ) ) ? 1 : 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
IMPL_LINK(UnoTreeListBoxImpl, OnExpandedHdl, UnoTreeListBoxImpl*, EMPTYARG )
|
|
{
|
|
UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( GetHdlEntry() );
|
|
if( pEntry && mxPeer.is() )
|
|
{
|
|
mxPeer->onExpanded( pEntry->mxNode, IsExpanded( pEntry ) );
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
sal_uInt32 UnoTreeListBoxImpl::insert( SvLBoxEntry* pEntry,SvLBoxEntry* pParent,ULONG nPos )
|
|
{
|
|
if( pParent )
|
|
return SvTreeListBox::Insert( pEntry, pParent, nPos );
|
|
else
|
|
return SvTreeListBox::Insert( pEntry, nPos );
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void UnoTreeListBoxImpl::RequestingChilds( SvLBoxEntry* pParent )
|
|
{
|
|
UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( pParent );
|
|
if( pEntry && pEntry->mxNode.is() && mxPeer.is() )
|
|
mxPeer->onRequestChildNodes( pEntry->mxNode );
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
BOOL UnoTreeListBoxImpl::EditingEntry( SvLBoxEntry* pEntry, Selection& )
|
|
{
|
|
return mxPeer.is() ? mxPeer->onEditingEntry( dynamic_cast< UnoTreeListEntry* >( pEntry ) ) : false;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
BOOL UnoTreeListBoxImpl::EditedEntry( SvLBoxEntry* pEntry, const XubString& rNewText )
|
|
{
|
|
return mxPeer.is() ? mxPeer->onEditedEntry( dynamic_cast< UnoTreeListEntry* >( pEntry ), rNewText ) : false;
|
|
}
|
|
|
|
// ====================================================================
|
|
// class UnoTreeListItem
|
|
// ====================================================================
|
|
|
|
UnoTreeListItem::UnoTreeListItem( SvLBoxEntry* pEntry )
|
|
: SvLBoxItem( pEntry, 0 )
|
|
{
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
UnoTreeListItem::UnoTreeListItem()
|
|
: SvLBoxItem()
|
|
{
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
UnoTreeListItem::~UnoTreeListItem()
|
|
{
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
USHORT UnoTreeListItem::IsA()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void UnoTreeListItem::Paint( const Point& rPos, SvLBox& rDev, USHORT /* nFlags */, SvLBoxEntry* _pEntry)
|
|
{
|
|
Point aPos( rPos );
|
|
if( _pEntry )
|
|
{
|
|
Size aSize( GetSize(&rDev,_pEntry) );
|
|
if( !!maImage )
|
|
{
|
|
rDev.DrawImage( aPos, maImage, rDev.IsEnabled() ? 0 : IMAGE_DRAW_DISABLE );
|
|
int nWidth = maImage.GetSizePixel().Width() + 6;
|
|
aPos.X() += nWidth;
|
|
aSize.Width() -= nWidth;
|
|
}
|
|
rDev.DrawText( Rectangle(aPos,aSize),maText, rDev.IsEnabled() ? 0 : TEXT_DRAW_DISABLE );
|
|
}
|
|
else
|
|
{
|
|
if( !!maImage )
|
|
{
|
|
rDev.DrawImage( aPos, maImage, rDev.IsEnabled() ? 0 : IMAGE_DRAW_DISABLE);
|
|
aPos.X() += maImage.GetSizePixel().Width() + 6;
|
|
}
|
|
rDev.DrawText( aPos, maText);
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
SvLBoxItem* UnoTreeListItem::Create() const
|
|
{
|
|
return new UnoTreeListItem;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void UnoTreeListItem::Clone( SvLBoxItem* pSource )
|
|
{
|
|
UnoTreeListItem* pSourceItem = dynamic_cast< UnoTreeListItem* >( pSource );
|
|
if( pSourceItem )
|
|
{
|
|
maText = pSourceItem->maText;
|
|
maImage = pSourceItem->maImage;
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
OUString UnoTreeListItem::GetText() const
|
|
{
|
|
return maText;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void UnoTreeListItem::SetText( const OUString& rText )
|
|
{
|
|
maText = rText;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void UnoTreeListItem::SetImage( const Image& rImage )
|
|
{
|
|
maImage = rImage;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
OUString UnoTreeListItem::GetGraphicURL() const
|
|
{
|
|
return maGraphicURL;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void UnoTreeListItem::SetGraphicURL( const OUString& rGraphicURL )
|
|
{
|
|
maGraphicURL = rGraphicURL;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
void UnoTreeListItem::InitViewData( SvLBox* pView,SvLBoxEntry* pEntry, SvViewDataItem* pViewData)
|
|
{
|
|
if( !pViewData )
|
|
pViewData = pView->GetViewDataItem( pEntry, this );
|
|
|
|
pViewData->aSize = maImage.GetSizePixel();
|
|
|
|
const Size aTextSize(pView->GetTextWidth( maText ), pView->GetTextHeight());
|
|
if( pViewData->aSize.Width() )
|
|
{
|
|
pViewData->aSize.Width() += 6 + aTextSize.Width();
|
|
if( pViewData->aSize.Height() < aTextSize.Height() )
|
|
pViewData->aSize.Height() = aTextSize.Height();
|
|
}
|
|
else
|
|
{
|
|
pViewData->aSize = aTextSize;
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
UnoTreeListEntry::UnoTreeListEntry( const Reference< XTreeNode >& xNode, TreeControlPeer* pPeer )
|
|
: SvLBoxEntry()
|
|
, mxNode( xNode )
|
|
, mpPeer( pPeer )
|
|
{
|
|
if( mpPeer )
|
|
mpPeer->addEntry( this );
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
|
|
UnoTreeListEntry::~UnoTreeListEntry()
|
|
{
|
|
if( mpPeer )
|
|
mpPeer->removeEntry( this );
|
|
}
|