xref: /AOO41X/main/svtools/source/uno/treecontrolpeer.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svtools.hxx"
30 
31 #define _SVTREEBX_CXX
32 #include <tools/debug.hxx>
33 #include <com/sun/star/lang/XServiceInfo.hpp>
34 #include <com/sun/star/lang/DisposedException.hpp>
35 #include <com/sun/star/view/SelectionType.hpp>
36 #include <toolkit/helper/property.hxx>
37 #include <toolkit/helper/vclunohelper.hxx>
38 
39 #include <com/sun/star/awt/tree/XMutableTreeNode.hpp>
40 #include <treecontrolpeer.hxx>
41 #include <comphelper/processfactory.hxx>
42 
43 #include <rtl/ref.hxx>
44 #include <vcl/graph.hxx>
45 #include <svtools/svtreebx.hxx>
46 
47 #include <map>
48 
49 using ::rtl::OUString;
50 using namespace ::com::sun::star;
51 using namespace ::com::sun::star::uno;
52 using namespace ::com::sun::star::lang;
53 using namespace ::com::sun::star::awt::tree;
54 using namespace ::com::sun::star::beans;
55 using namespace ::com::sun::star::view;
56 using namespace ::com::sun::star::container;
57 using namespace ::com::sun::star::util;
58 using namespace ::com::sun::star::graphic;
59 
60 #define O(x) OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
61 
62 struct LockGuard
63 {
64 public:
65 	LockGuard( sal_Int32& rLock )
66 	: mrLock( rLock )
67 	{
68 		rLock++;
69 	}
70 
71 	~LockGuard()
72 	{
73 		mrLock--;
74 	}
75 
76 	sal_Int32& mrLock;
77 };
78 
79 // --------------------------------------------------------------------
80 
81 class ImplGraphicItem : public SvLBoxBmp
82 {
83 public:
84 	ImplGraphicItem( SvLBoxEntry* pEntry, sal_uInt16 nFlags, Image& aImage ) : SvLBoxBmp( pEntry, nFlags, aImage ) {}
85 
86 	OUString msGraphicURL;
87 };
88 
89 // --------------------------------------------------------------------
90 
91 class ImplContextGraphicItem : public SvLBoxContextBmp
92 {
93 public:
94 	ImplContextGraphicItem( SvLBoxEntry* pEntry,sal_uInt16 nFlags,Image& rI1,Image& rI2, sal_uInt16 nEntryFlagsBmp1)
95 		: SvLBoxContextBmp( pEntry, nFlags, rI1, rI2, nEntryFlagsBmp1 ) {}
96 
97 	OUString msExpandedGraphicURL;
98 	OUString msCollapsedGraphicURL;
99 };
100 
101 // --------------------------------------------------------------------
102 
103 class UnoTreeListBoxImpl : public SvTreeListBox
104 {
105 public:
106 	UnoTreeListBoxImpl( TreeControlPeer* pPeer, Window* pParent, WinBits nWinStyle );
107 	~UnoTreeListBoxImpl();
108 
109 	sal_uInt32 insert( SvLBoxEntry* pEntry,SvLBoxEntry* pParent,sal_uLong nPos=LIST_APPEND );
110 
111 	virtual void	RequestingChilds( SvLBoxEntry* pParent );
112 
113 	virtual sal_Bool	EditingEntry( SvLBoxEntry* pEntry, Selection& );
114 	virtual sal_Bool	EditedEntry( SvLBoxEntry* pEntry, const XubString& rNewText );
115 
116 	DECL_LINK( OnSelectionChangeHdl, UnoTreeListBoxImpl* );
117 	DECL_LINK( OnExpandingHdl, UnoTreeListBoxImpl* );
118 	DECL_LINK( OnExpandedHdl, UnoTreeListBoxImpl* );
119 
120 private:
121 	rtl::Reference< TreeControlPeer > mxPeer;
122 };
123 
124 // --------------------------------------------------------------------
125 
126 class SVT_DLLPUBLIC UnoTreeListItem : public SvLBoxItem
127 {
128 public:
129 					UnoTreeListItem( SvLBoxEntry* );
130 					UnoTreeListItem();
131 	virtual			~UnoTreeListItem();
132 	virtual sal_uInt16	IsA();
133 	void			InitViewData( SvLBox*,SvLBoxEntry*,SvViewDataItem* );
134 	OUString		GetText() const;
135 	void 			SetText( const OUString& rText );
136 	Image			GetImage() const;
137 	void			SetImage( const Image& rImage );
138 	OUString		GetGraphicURL() const;
139 	void			SetGraphicURL( const OUString& rGraphicURL );
140 	void			Paint( const Point&, SvLBox& rDev, sal_uInt16 nFlags,SvLBoxEntry* );
141 	SvLBoxItem* 	Create() const;
142 	void 			Clone( SvLBoxItem* pSource );
143 
144 private:
145 	OUString		maText;
146 	OUString		maGraphicURL;
147 	Image			maImage;
148 };
149 
150 // --------------------------------------------------------------------
151 
152 class UnoTreeListEntry : public SvLBoxEntry
153 {
154 public:
155 	UnoTreeListEntry( const Reference< XTreeNode >& xNode, TreeControlPeer* pPeer );
156 	virtual ~UnoTreeListEntry();
157 
158 	Reference< XTreeNode > mxNode;
159 	TreeControlPeer* mpPeer;
160 };
161 
162 // --------------------------------------------------------------------
163 
164 class TreeNodeMap : public std::map< Reference< XTreeNode >, UnoTreeListEntry* >
165 {
166 };
167 
168 // --------------------------------------------------------------------
169 
170 TreeControlPeer::TreeControlPeer()
171 : maSelectionListeners( *this )
172 , maTreeExpansionListeners( *this )
173 , maTreeEditListeners( *this )
174 , mpTreeImpl( 0 )
175 , mnEditLock( 0 )
176 , mpTreeNodeMap( 0 )
177 {
178 }
179 
180 // --------------------------------------------------------------------
181 
182 TreeControlPeer::~TreeControlPeer()
183 {
184 	if( mpTreeImpl )
185 		mpTreeImpl->Clear();
186 	delete mpTreeNodeMap;
187 }
188 
189 // --------------------------------------------------------------------
190 
191 void TreeControlPeer::addEntry( UnoTreeListEntry* pEntry )
192 {
193 	if( pEntry && pEntry->mxNode.is() )
194 	{
195 		if( !mpTreeNodeMap )
196 		{
197 			mpTreeNodeMap = new TreeNodeMap();
198 		}
199 
200 		(*mpTreeNodeMap)[ pEntry->mxNode ] = pEntry;
201 	}
202 }
203 
204 // --------------------------------------------------------------------
205 
206 void TreeControlPeer::removeEntry( UnoTreeListEntry* pEntry )
207 {
208 	if( mpTreeNodeMap && pEntry && pEntry->mxNode.is() )
209 	{
210 		TreeNodeMap::iterator aIter( mpTreeNodeMap->find( pEntry->mxNode ) );
211 		if( aIter != mpTreeNodeMap->end() )
212         {
213 			mpTreeNodeMap->erase( aIter );
214         }
215 	}
216 }
217 
218 // --------------------------------------------------------------------
219 
220 UnoTreeListEntry* TreeControlPeer::getEntry( const Reference< XTreeNode >& xNode, bool bThrow /* = true */ ) throw( IllegalArgumentException )
221 {
222 	if( mpTreeNodeMap )
223 	{
224 		TreeNodeMap::iterator aIter( mpTreeNodeMap->find( xNode ) );
225 		if( aIter != mpTreeNodeMap->end() )
226 			return (*aIter).second;
227 	}
228 
229 	if( bThrow )
230 		throw IllegalArgumentException();
231 
232 	return 0;
233 }
234 
235 // --------------------------------------------------------------------
236 
237 Window* TreeControlPeer::createVclControl( Window* pParent, sal_Int64 nWinStyle )
238 {
239 	mpTreeImpl = new UnoTreeListBoxImpl( this, pParent, nWinStyle );
240 	return mpTreeImpl;
241 }
242 
243 // --------------------------------------------------------------------
244 
245 /** called from the UnoTreeListBoxImpl when it gets deleted */
246 void TreeControlPeer::disposeControl()
247 {
248 	delete mpTreeNodeMap;
249 	mpTreeNodeMap = 0;
250 	mpTreeImpl = 0;
251 }
252 
253 // --------------------------------------------------------------------
254 
255 void TreeControlPeer::SetWindow( Window* pWindow )
256 {
257 	VCLXWindow::SetWindow( pWindow );
258 }
259 
260 // --------------------------------------------------------------------
261 
262 UnoTreeListEntry* TreeControlPeer::createEntry( const Reference< XTreeNode >& xNode, UnoTreeListEntry* pParent, sal_uLong nPos /* = LIST_APPEND */ )
263 {
264 	UnoTreeListEntry* pEntry = 0;
265 	if( mpTreeImpl )
266 	{
267 		Image aImage;
268 		pEntry = new UnoTreeListEntry( xNode, this );
269 		ImplContextGraphicItem* pContextBmp= new ImplContextGraphicItem( pEntry,0, aImage, aImage, SVLISTENTRYFLAG_EXPANDED );
270 
271 		pEntry->AddItem( pContextBmp );
272 
273 		UnoTreeListItem * pUnoItem = new UnoTreeListItem( pEntry );
274 
275 		if( xNode->getNodeGraphicURL().getLength() )
276 		{
277 			pUnoItem->SetGraphicURL( xNode->getNodeGraphicURL() );
278 			Image aNodeImage;
279 			loadImage( xNode->getNodeGraphicURL(), aNodeImage );
280 			pUnoItem->SetImage( aNodeImage );
281 			mpTreeImpl->AdjustEntryHeight( aNodeImage );
282 		}
283 
284 		pEntry->AddItem( pUnoItem );
285 
286 		mpTreeImpl->insert( pEntry, pParent, nPos );
287 
288         if( msDefaultExpandedGraphicURL.getLength() )
289 			mpTreeImpl->SetExpandedEntryBmp( pEntry, maDefaultExpandedImage );
290 
291 		if( msDefaultCollapsedGraphicURL.getLength() )
292 			mpTreeImpl->SetCollapsedEntryBmp( pEntry, maDefaultCollapsedImage );
293 
294 		updateEntry( pEntry );
295 	}
296 	return pEntry;
297 }
298 
299 // --------------------------------------------------------------------
300 
301 bool TreeControlPeer::updateEntry( UnoTreeListEntry* pEntry )
302 {
303 	bool bChanged = false;
304 	if( pEntry && pEntry->mxNode.is() && mpTreeImpl )
305 	{
306 		const OUString aValue( getEntryString( pEntry->mxNode->getDisplayValue() ) );
307 		UnoTreeListItem* pUnoItem = dynamic_cast< UnoTreeListItem* >( pEntry->GetItem( 1 ) );
308 		if( pUnoItem )
309 		{
310 			if( aValue != pUnoItem->GetText() )
311 			{
312 				pUnoItem->SetText( aValue );
313 				bChanged = true;
314 			}
315 
316 			if( pUnoItem->GetGraphicURL() != pEntry->mxNode->getNodeGraphicURL() )
317 			{
318 				Image aImage;
319 				if( loadImage( pEntry->mxNode->getNodeGraphicURL(), aImage ) )
320 				{
321 					pUnoItem->SetGraphicURL( pEntry->mxNode->getNodeGraphicURL() );
322 					pUnoItem->SetImage( aImage );
323 					mpTreeImpl->AdjustEntryHeight( aImage );
324 					bChanged = true;
325 				}
326 			}
327 		}
328 
329 		if( (pEntry->mxNode->hasChildrenOnDemand() == sal_True) != (pEntry->HasChildsOnDemand() == sal_True) )
330 		{
331 			pEntry->EnableChildsOnDemand( pEntry->mxNode->hasChildrenOnDemand() ? sal_True : sal_False );
332 			bChanged = true;
333 		}
334 
335 		ImplContextGraphicItem* pContextGraphicItem = dynamic_cast< ImplContextGraphicItem* >( pEntry->GetItem( 0 ) );
336 		if( pContextGraphicItem )
337 		{
338 			if( pContextGraphicItem->msExpandedGraphicURL != pEntry->mxNode->getExpandedGraphicURL() )
339 			{
340 				Image aImage;
341 				if(	loadImage( pEntry->mxNode->getExpandedGraphicURL(), aImage ) )
342 				{
343 					pContextGraphicItem->msExpandedGraphicURL = pEntry->mxNode->getExpandedGraphicURL();
344 					mpTreeImpl->SetExpandedEntryBmp( pEntry, aImage );
345 					bChanged = true;
346 				}
347 			}
348 			if( pContextGraphicItem->msCollapsedGraphicURL != pEntry->mxNode->getCollapsedGraphicURL() )
349 			{
350 				Image aImage;
351 				if(	loadImage( pEntry->mxNode->getCollapsedGraphicURL(), aImage ) )
352 				{
353 					pContextGraphicItem->msCollapsedGraphicURL = pEntry->mxNode->getCollapsedGraphicURL();
354 					mpTreeImpl->SetCollapsedEntryBmp( pEntry, aImage );
355 					bChanged = true;
356 				}
357 			}
358 		}
359 
360 		if( bChanged )
361 			mpTreeImpl->GetModel()->InvalidateEntry( pEntry );
362 	}
363 
364 	return bChanged;
365 }
366 
367 // --------------------------------------------------------------------
368 
369 void TreeControlPeer::onSelectionChanged()
370 {
371 	Reference< XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
372 	EventObject aEvent( xSource );
373 	maSelectionListeners.selectionChanged( aEvent );
374 }
375 
376 // --------------------------------------------------------------------
377 
378 void TreeControlPeer::onRequestChildNodes( const Reference< XTreeNode >& xNode )
379 {
380 	try
381 	{
382 		Reference< XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
383 		TreeExpansionEvent aEvent( xSource, xNode );
384 		maTreeExpansionListeners.requestChildNodes( aEvent );
385 	}
386 	catch( Exception& )
387 	{
388 	}
389 }
390 
391 // --------------------------------------------------------------------
392 
393 bool TreeControlPeer::onExpanding( const Reference< XTreeNode >& xNode, bool bExpanding )
394 {
395 	try
396 	{
397 		Reference< XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
398 		TreeExpansionEvent aEvent( xSource, xNode );
399 		if( bExpanding )
400 		{
401 			maTreeExpansionListeners.treeExpanding( aEvent );
402 		}
403 		else
404 		{
405 			maTreeExpansionListeners.treeCollapsing( aEvent );
406 		}
407 	}
408 	catch( Exception& )
409 	{
410 		return false;
411 	}
412 	return true;
413 }
414 
415 // --------------------------------------------------------------------
416 
417 void TreeControlPeer::onExpanded( const Reference< XTreeNode >& xNode, bool bExpanding )
418 {
419 	try
420 	{
421 		Reference< XInterface > xSource( static_cast< ::cppu::OWeakObject* >( this ) );
422 		TreeExpansionEvent aEvent( xSource, xNode );
423 
424 		if( bExpanding )
425 		{
426 			maTreeExpansionListeners.treeExpanded( aEvent );
427 		}
428 		else
429 		{
430 			maTreeExpansionListeners.treeCollapsed( aEvent );
431 		}
432 	}
433 	catch( Exception& )
434 	{
435 	}
436 }
437 
438 // --------------------------------------------------------------------
439 
440 void TreeControlPeer::fillTree( UnoTreeListBoxImpl& rTree, const Reference< XTreeDataModel >& xDataModel )
441 {
442 	rTree.Clear();
443 
444 	if( xDataModel.is() )
445 	{
446 		Reference< XTreeNode > xRootNode( xDataModel->getRoot() );
447 		if( xRootNode.is() )
448 		{
449 			if( mbIsRootDisplayed )
450 			{
451 				addNode( rTree, xRootNode, 0 );
452 			}
453 			else
454 			{
455 				const sal_Int32 nChildCount = xRootNode->getChildCount();
456 				for( sal_Int32 nChild = 0; nChild < nChildCount; nChild++ )
457 					addNode( rTree, xRootNode->getChildAt( nChild ), 0 );
458 			}
459 		}
460 	}
461 }
462 
463 // --------------------------------------------------------------------
464 
465 void TreeControlPeer::addNode( UnoTreeListBoxImpl& rTree, const Reference< XTreeNode >& xNode, UnoTreeListEntry* pParentEntry )
466 {
467 	if( xNode.is() )
468 	{
469 		UnoTreeListEntry* pEntry = createEntry( xNode, pParentEntry, LIST_APPEND );
470 		const sal_Int32 nChildCount = xNode->getChildCount();
471 		for( sal_Int32 nChild = 0; nChild < nChildCount; nChild++ )
472 			addNode( rTree, xNode->getChildAt( nChild ), pEntry );
473 	}
474 }
475 
476 // --------------------------------------------------------------------
477 
478 UnoTreeListBoxImpl& TreeControlPeer::getTreeListBoxOrThrow() const throw (RuntimeException )
479 {
480 	if( !mpTreeImpl )
481 		throw DisposedException();
482 	return *mpTreeImpl;
483 }
484 
485 // --------------------------------------------------------------------
486 
487 void TreeControlPeer::ChangeNodesSelection( const Any& rSelection, bool bSelect, bool bSetSelection ) throw( RuntimeException, IllegalArgumentException )
488 {
489 	::vos::OGuard aGuard( GetMutex() );
490 
491 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
492 
493 	Reference< XTreeNode > xTempNode;
494 	Sequence< XTreeNode > aTempSeq;
495 
496 	const Reference< XTreeNode > *pNodes = 0;
497 	sal_Int32 nCount = 0;
498 
499 	if( rSelection.hasValue() )
500 	{
501 		switch( rSelection.getValueTypeClass() )
502 		{
503 		case TypeClass_INTERFACE:
504 			{
505 				rSelection >>= xTempNode;
506 				if( xTempNode.is() )
507 				{
508 					nCount = 1;
509 					pNodes = &xTempNode;
510 				}
511 				break;
512 			}
513 		case TypeClass_SEQUENCE:
514 			{
515 				if( rSelection.getValueType() == ::getCppuType( (const Sequence< Reference< XTreeNode > > *) 0 ) )
516 				{
517 					const Sequence< Reference< XTreeNode > >& rSeq( *(const Sequence< Reference< XTreeNode > > *)rSelection.getValue() );
518 					nCount = rSeq.getLength();
519 					if( nCount )
520 						pNodes = rSeq.getConstArray();
521 				}
522 				break;
523 			}
524 		default:
525 			break;
526 		}
527 
528 		if( nCount == 0 )
529 			throw IllegalArgumentException();
530 	}
531 
532 	if( bSetSelection )
533 		rTree.SelectAll( sal_False );
534 
535 	if( pNodes && nCount )
536 	{
537 		while( nCount-- )
538 		{
539 			UnoTreeListEntry* pEntry = getEntry( *pNodes++ );
540 			rTree.Select( pEntry, bSelect ? sal_True : sal_False );
541 		}
542 	}
543 }
544 
545 // -------------------------------------------------------------------
546 // ::com::sun::star::view::XSelectionSupplier
547 // -------------------------------------------------------------------
548 
549 sal_Bool SAL_CALL TreeControlPeer::select( const Any& rSelection ) throw (IllegalArgumentException, RuntimeException)
550 {
551 	::vos::OGuard aGuard( GetMutex() );
552 	ChangeNodesSelection( rSelection, true, true );
553 	return sal_True;
554 }
555 
556 // -------------------------------------------------------------------
557 
558 Any SAL_CALL TreeControlPeer::getSelection() throw (RuntimeException)
559 {
560 	::vos::OGuard aGuard( GetMutex() );
561 
562 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
563 
564 	Any aRet;
565 
566 	sal_uLong nSelectionCount = rTree.GetSelectionCount();
567 	if( nSelectionCount == 1 )
568 	{
569 		UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.FirstSelected() );
570 		if( pEntry && pEntry->mxNode.is() )
571 			aRet <<= pEntry->mxNode;
572 	}
573 	else if( nSelectionCount > 1 )
574 	{
575 		Sequence< Reference< XTreeNode > > aSelection( nSelectionCount );
576 		Reference< XTreeNode >* pNodes = aSelection.getArray();
577 		UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.FirstSelected() );
578 		while( pEntry && nSelectionCount )
579 		{
580 			*pNodes++ = pEntry->mxNode;
581 			pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.NextSelected( pEntry ) );
582 			--nSelectionCount;
583 		}
584 
585 		OSL_ASSERT( (pEntry == 0) && (nSelectionCount == 0) );
586 		aRet <<= aSelection;
587 	}
588 
589 	return aRet;
590 }
591 
592 // -------------------------------------------------------------------
593 
594 void SAL_CALL TreeControlPeer::addSelectionChangeListener( const Reference< XSelectionChangeListener >& xListener ) throw (RuntimeException)
595 {
596 	maSelectionListeners.addInterface( xListener );
597 }
598 
599 // -------------------------------------------------------------------
600 
601 void SAL_CALL TreeControlPeer::removeSelectionChangeListener( const Reference< XSelectionChangeListener >& xListener ) throw (RuntimeException)
602 {
603 	maSelectionListeners.addInterface( xListener );
604 }
605 
606 // -------------------------------------------------------------------
607 // ::com::sun::star::view::XMultiSelectionSupplier
608 // -------------------------------------------------------------------
609 
610 sal_Bool SAL_CALL TreeControlPeer::addSelection( const Any& rSelection ) throw (IllegalArgumentException, RuntimeException)
611 {
612 	ChangeNodesSelection( rSelection, true, false );
613 	return sal_True;
614 }
615 
616 // -------------------------------------------------------------------
617 
618 void SAL_CALL TreeControlPeer::removeSelection( const Any& rSelection ) throw (IllegalArgumentException, RuntimeException)
619 {
620 	ChangeNodesSelection( rSelection, false, false );
621 }
622 
623 // -------------------------------------------------------------------
624 
625 void SAL_CALL TreeControlPeer::clearSelection() throw (RuntimeException)
626 {
627 	::vos::OGuard aGuard( GetMutex() );
628 	getTreeListBoxOrThrow().SelectAll( sal_False );
629 }
630 
631 // -------------------------------------------------------------------
632 
633 sal_Int32 SAL_CALL TreeControlPeer::getSelectionCount() throw (RuntimeException)
634 {
635 	::vos::OGuard aGuard( GetMutex() );
636 	return getTreeListBoxOrThrow().GetSelectionCount();
637 }
638 
639 // -------------------------------------------------------------------
640 
641 class TreeSelectionEnumeration : public ::cppu::WeakImplHelper1< XEnumeration >
642 {
643 public:
644 	TreeSelectionEnumeration( std::list< Any >& rSelection );
645     virtual ::sal_Bool SAL_CALL hasMoreElements() throw (RuntimeException);
646     virtual Any SAL_CALL nextElement() throw (NoSuchElementException, WrappedTargetException, RuntimeException);
647 
648 	std::list< Any > maSelection;
649 	std::list< Any >::iterator maIter;
650 };
651 
652 // -------------------------------------------------------------------
653 
654 TreeSelectionEnumeration::TreeSelectionEnumeration( std::list< Any >& rSelection )
655 {
656 	maSelection.swap( rSelection );
657 	maIter = maSelection.begin();
658 }
659 
660 // -------------------------------------------------------------------
661 
662 ::sal_Bool SAL_CALL TreeSelectionEnumeration::hasMoreElements() throw (RuntimeException)
663 {
664 	return maIter != maSelection.end();
665 }
666 
667 // -------------------------------------------------------------------
668 
669 Any SAL_CALL TreeSelectionEnumeration::nextElement() throw (NoSuchElementException, WrappedTargetException, RuntimeException)
670 {
671 	if( maIter == maSelection.end() )
672 		throw NoSuchElementException();
673 
674 	return (*maIter++);
675 }
676 
677 // -------------------------------------------------------------------
678 
679 Reference< XEnumeration > SAL_CALL TreeControlPeer::createSelectionEnumeration() throw (RuntimeException)
680 {
681 	::vos::OGuard aGuard( GetMutex() );
682 
683 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
684 
685 	sal_uInt32 nSelectionCount = rTree.GetSelectionCount();
686 	std::list< Any > aSelection( nSelectionCount );
687 
688 	UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.FirstSelected() );
689 	while( pEntry && nSelectionCount )
690 	{
691 		aSelection.push_back( Any( pEntry->mxNode ) );
692 		pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.NextSelected( pEntry ) );
693 		--nSelectionCount;
694 	}
695 
696 	OSL_ASSERT( (pEntry == 0) && (nSelectionCount == 0) );
697 
698 	return Reference< XEnumeration >( new TreeSelectionEnumeration( aSelection ) );
699 }
700 
701 // -------------------------------------------------------------------
702 
703 Reference< XEnumeration > SAL_CALL TreeControlPeer::createReverseSelectionEnumeration() throw (RuntimeException)
704 {
705 	::vos::OGuard aGuard( GetMutex() );
706 
707 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
708 
709 	sal_uInt32 nSelectionCount = rTree.GetSelectionCount();
710 	std::list< Any > aSelection;
711 
712 	UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.FirstSelected() );
713 	while( pEntry && nSelectionCount )
714 	{
715 		aSelection.push_front( Any( pEntry->mxNode ) );
716 		pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.NextSelected( pEntry ) );
717 		--nSelectionCount;
718 	}
719 
720 	OSL_ASSERT( (pEntry == 0) && (nSelectionCount == 0) );
721 
722 	return Reference< XEnumeration >( new TreeSelectionEnumeration( aSelection ) );
723 }
724 
725 // --------------------------------------------------------------------
726 // ::com::sun::star::awt::XTreeControl
727 // --------------------------------------------------------------------
728 
729 OUString SAL_CALL TreeControlPeer::getDefaultExpandedGraphicURL() throw (::com::sun::star::uno::RuntimeException)
730 {
731 	::vos::OGuard aGuard( GetMutex() );
732 	return msDefaultExpandedGraphicURL;
733 }
734 
735 // --------------------------------------------------------------------
736 
737 void SAL_CALL TreeControlPeer::setDefaultExpandedGraphicURL( const ::rtl::OUString& sDefaultExpandedGraphicURL ) throw (::com::sun::star::uno::RuntimeException)
738 {
739 	::vos::OGuard aGuard( GetMutex() );
740 	if( msDefaultExpandedGraphicURL != sDefaultExpandedGraphicURL )
741 	{
742 		if( sDefaultExpandedGraphicURL.getLength() )
743 			loadImage( sDefaultExpandedGraphicURL, maDefaultExpandedImage );
744 		else
745 			maDefaultExpandedImage = Image();
746 
747 		UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
748 
749 		SvLBoxEntry* pEntry = rTree.First();
750 		while( pEntry )
751 		{
752 			ImplContextGraphicItem* pContextGraphicItem = dynamic_cast< ImplContextGraphicItem* >( pEntry->GetItem( 0 ) );
753 			if( pContextGraphicItem )
754 			{
755 				if( pContextGraphicItem->msExpandedGraphicURL.getLength() == 0 )
756 					rTree.SetExpandedEntryBmp( pEntry, maDefaultExpandedImage );
757 			}
758 			pEntry = rTree.Next( pEntry );
759 		}
760 
761 		msDefaultExpandedGraphicURL = sDefaultExpandedGraphicURL;
762 	}
763 }
764 
765 // --------------------------------------------------------------------
766 
767 OUString SAL_CALL TreeControlPeer::getDefaultCollapsedGraphicURL() throw (::com::sun::star::uno::RuntimeException)
768 {
769 	::vos::OGuard aGuard( GetMutex() );
770 	return msDefaultCollapsedGraphicURL;
771 }
772 
773 // --------------------------------------------------------------------
774 
775 void SAL_CALL TreeControlPeer::setDefaultCollapsedGraphicURL( const ::rtl::OUString& sDefaultCollapsedGraphicURL ) throw (::com::sun::star::uno::RuntimeException)
776 {
777 	::vos::OGuard aGuard( GetMutex() );
778 	if( msDefaultCollapsedGraphicURL != sDefaultCollapsedGraphicURL )
779 	{
780 		if( sDefaultCollapsedGraphicURL.getLength() )
781 			loadImage( sDefaultCollapsedGraphicURL, maDefaultCollapsedImage );
782 		else
783 			maDefaultCollapsedImage = Image();
784 
785 		UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
786 
787 		SvLBoxEntry* pEntry = rTree.First();
788 		while( pEntry )
789 		{
790 			ImplContextGraphicItem* pContextGraphicItem = dynamic_cast< ImplContextGraphicItem* >( pEntry->GetItem( 0 ) );
791 			if( pContextGraphicItem )
792 			{
793 				if( pContextGraphicItem->msCollapsedGraphicURL.getLength() == 0 )
794 					rTree.SetCollapsedEntryBmp( pEntry, maDefaultCollapsedImage );
795 			}
796 			pEntry = rTree.Next( pEntry );
797 		}
798 
799 		msDefaultCollapsedGraphicURL = sDefaultCollapsedGraphicURL;
800 	}
801 }
802 
803 // --------------------------------------------------------------------
804 
805 sal_Bool SAL_CALL TreeControlPeer::isNodeExpanded( const Reference< XTreeNode >& xNode ) throw (RuntimeException, IllegalArgumentException)
806 {
807 	::vos::OGuard aGuard( GetMutex() );
808 
809 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
810 	UnoTreeListEntry* pEntry = getEntry( xNode );
811 	return ( pEntry && rTree.IsExpanded( pEntry ) ) ? sal_True : sal_False;
812 }
813 
814 // -------------------------------------------------------------------
815 
816 sal_Bool SAL_CALL TreeControlPeer::isNodeCollapsed( const Reference< XTreeNode >& xNode ) throw (RuntimeException, IllegalArgumentException)
817 {
818 	::vos::OGuard aGuard( GetMutex() );
819 	return !isNodeExpanded( xNode );
820 }
821 
822 // -------------------------------------------------------------------
823 
824 void SAL_CALL TreeControlPeer::makeNodeVisible( const Reference< XTreeNode >& xNode ) throw (RuntimeException, ExpandVetoException, IllegalArgumentException)
825 {
826 	::vos::OGuard aGuard( GetMutex() );
827 
828 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
829 	UnoTreeListEntry* pEntry = getEntry( xNode );
830 	if( pEntry )
831 		rTree.MakeVisible( pEntry );
832 }
833 
834 // -------------------------------------------------------------------
835 
836 sal_Bool SAL_CALL TreeControlPeer::isNodeVisible( const Reference< XTreeNode >& xNode ) throw (RuntimeException, IllegalArgumentException)
837 {
838 	::vos::OGuard aGuard( GetMutex() );
839 
840 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
841 	UnoTreeListEntry* pEntry = getEntry( xNode );
842 	return ( pEntry && rTree.IsEntryVisible( pEntry ) ) ? sal_True : sal_False;
843 }
844 
845 // -------------------------------------------------------------------
846 
847 void SAL_CALL TreeControlPeer::expandNode( const Reference< XTreeNode >& xNode ) throw (RuntimeException, ExpandVetoException, IllegalArgumentException)
848 {
849 	::vos::OGuard aGuard( GetMutex() );
850 
851 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
852 	UnoTreeListEntry* pEntry = getEntry( xNode );
853 	if( pEntry )
854 		rTree.Expand( pEntry );
855 }
856 
857 // -------------------------------------------------------------------
858 
859 void SAL_CALL TreeControlPeer::collapseNode( const Reference< XTreeNode >& xNode ) throw (RuntimeException, ExpandVetoException, IllegalArgumentException)
860 {
861 	::vos::OGuard aGuard( GetMutex() );
862 
863 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
864 	UnoTreeListEntry* pEntry = getEntry( xNode );
865 	if( pEntry )
866 		rTree.Collapse( pEntry );
867 }
868 
869 // -------------------------------------------------------------------
870 
871 void SAL_CALL TreeControlPeer::addTreeExpansionListener( const Reference< XTreeExpansionListener >& xListener ) throw (RuntimeException)
872 {
873 	maTreeExpansionListeners.addInterface( xListener );
874 }
875 
876 // -------------------------------------------------------------------
877 
878 void SAL_CALL TreeControlPeer::removeTreeExpansionListener( const Reference< XTreeExpansionListener >& xListener ) throw (RuntimeException)
879 {
880 	maTreeExpansionListeners.removeInterface( xListener );
881 }
882 
883 // -------------------------------------------------------------------
884 
885 Reference< XTreeNode > SAL_CALL TreeControlPeer::getNodeForLocation( sal_Int32 x, sal_Int32 y ) throw (RuntimeException)
886 {
887 	::vos::OGuard aGuard( GetMutex() );
888 
889 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
890 
891 	Reference< XTreeNode > xNode;
892 
893 	const Point aPos( x, y );
894 	UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.GetEntry( aPos, sal_True ) );
895 	if( pEntry )
896 		xNode = pEntry->mxNode;
897 
898 	return xNode;
899 }
900 
901 // -------------------------------------------------------------------
902 
903 Reference< XTreeNode > SAL_CALL TreeControlPeer::getClosestNodeForLocation( sal_Int32 x, sal_Int32 y ) throw (RuntimeException)
904 {
905 	::vos::OGuard aGuard( GetMutex() );
906 
907 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
908 
909 	Reference< XTreeNode > xNode;
910 
911 	const Point aPos( x, y );
912 	UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( rTree.GetEntry( aPos, sal_True ) );
913 	if( pEntry )
914 		xNode = pEntry->mxNode;
915 
916 	return xNode;
917 }
918 
919 // -------------------------------------------------------------------
920 
921 awt::Rectangle SAL_CALL TreeControlPeer::getNodeRect( const Reference< XTreeNode >& i_Node ) throw (IllegalArgumentException, RuntimeException)
922 {
923 	::vos::OGuard aGuard( GetMutex() );
924 
925 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
926 	UnoTreeListEntry* pEntry = getEntry( i_Node, true );
927 
928     ::Rectangle aEntryRect( rTree.GetFocusRect( pEntry, rTree.GetEntryPosition( pEntry ).Y() ) );
929     return VCLUnoHelper::ConvertToAWTRect( aEntryRect );
930 }
931 
932 // -------------------------------------------------------------------
933 
934 sal_Bool SAL_CALL TreeControlPeer::isEditing(  ) throw (RuntimeException)
935 {
936 	::vos::OGuard aGuard( GetMutex() );
937 
938 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
939 	return rTree.IsEditingActive() ? sal_True : sal_False;
940 }
941 
942 // -------------------------------------------------------------------
943 
944 sal_Bool SAL_CALL TreeControlPeer::stopEditing() throw (RuntimeException)
945 {
946 	::vos::OGuard aGuard( GetMutex() );
947 
948 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
949 	if( rTree.IsEditingActive() )
950 	{
951 		rTree.EndEditing(sal_False);
952 		return sal_True;
953 	}
954 	else
955 	{
956 		return sal_False;
957 	}
958 }
959 
960 // -------------------------------------------------------------------
961 
962 void SAL_CALL TreeControlPeer::cancelEditing(  ) throw (RuntimeException)
963 {
964 	::vos::OGuard aGuard( GetMutex() );
965 
966 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
967 	rTree.EndEditing(sal_False);
968 }
969 
970 // -------------------------------------------------------------------
971 
972 void SAL_CALL TreeControlPeer::startEditingAtNode( const Reference< XTreeNode >& xNode ) throw (IllegalArgumentException, RuntimeException)
973 {
974 	::vos::OGuard aGuard( GetMutex() );
975 
976 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
977 	UnoTreeListEntry* pEntry = getEntry( xNode );
978 	rTree.EditEntry( pEntry );
979 }
980 
981 void SAL_CALL TreeControlPeer::addTreeEditListener( const Reference< XTreeEditListener >& xListener ) throw (RuntimeException)
982 {
983 	maTreeEditListeners.addInterface( xListener );
984 }
985 
986 void SAL_CALL TreeControlPeer::removeTreeEditListener( const Reference< XTreeEditListener >& xListener ) throw (RuntimeException)
987 {
988 	maTreeEditListeners.removeInterface( xListener );
989 }
990 
991 bool TreeControlPeer::onEditingEntry( UnoTreeListEntry* pEntry )
992 {
993 	if( mpTreeImpl && pEntry && pEntry->mxNode.is() && (maTreeEditListeners.getLength() > 0)  )
994 	{
995 		try
996 		{
997 			maTreeEditListeners.nodeEditing( pEntry->mxNode );
998 		}
999 		catch( VetoException& )
1000 		{
1001 			return false;
1002 		}
1003 		catch( Exception& )
1004 		{
1005 		}
1006 	}
1007 	return true;
1008 }
1009 
1010 bool TreeControlPeer::onEditedEntry( UnoTreeListEntry* pEntry, const XubString& rNewText )
1011 {
1012 	if( mpTreeImpl && pEntry && pEntry->mxNode.is() ) try
1013 	{
1014 		LockGuard aLockGuard( mnEditLock );
1015 		const OUString aNewText( rNewText );
1016 		if( maTreeEditListeners.getLength() > 0 )
1017 		{
1018 			maTreeEditListeners.nodeEdited( pEntry->mxNode, aNewText );
1019 			return false;
1020 		}
1021 		else
1022 		{
1023 			Reference< XMutableTreeNode > xMutableNode( pEntry->mxNode, UNO_QUERY );
1024 			if( xMutableNode.is() )
1025 				xMutableNode->setDisplayValue( Any( aNewText ) );
1026 			else
1027 				return false;
1028 		}
1029 
1030 	}
1031 	catch( Exception& )
1032 	{
1033 	}
1034 
1035 	return true;
1036 }
1037 
1038 // --------------------------------------------------------------------
1039 // ::com::sun::star::awt::tree::TreeDataModelListener
1040 // --------------------------------------------------------------------
1041 
1042 void SAL_CALL TreeControlPeer::treeNodesChanged( const ::com::sun::star::awt::tree::TreeDataModelEvent& rEvent ) throw (RuntimeException)
1043 {
1044 	::vos::OGuard aGuard( GetMutex() );
1045 
1046 	if( mnEditLock != 0 )
1047 		return;
1048 
1049 	updateTree( rEvent, true );
1050 }
1051 
1052 void SAL_CALL TreeControlPeer::treeNodesInserted( const ::com::sun::star::awt::tree::TreeDataModelEvent& rEvent ) throw (RuntimeException)
1053 {
1054 	::vos::OGuard aGuard( GetMutex() );
1055 
1056 	if( mnEditLock != 0 )
1057 		return;
1058 
1059 	updateTree( rEvent, true );
1060 }
1061 
1062 void SAL_CALL TreeControlPeer::treeNodesRemoved( const ::com::sun::star::awt::tree::TreeDataModelEvent& rEvent ) throw (RuntimeException)
1063 {
1064 	::vos::OGuard aGuard( GetMutex() );
1065 
1066 	if( mnEditLock != 0 )
1067 		return;
1068 
1069 	updateTree( rEvent, true );
1070 }
1071 
1072 void SAL_CALL TreeControlPeer::treeStructureChanged( const ::com::sun::star::awt::tree::TreeDataModelEvent& rEvent ) throw (RuntimeException)
1073 {
1074 	::vos::OGuard aGuard( GetMutex() );
1075 
1076 	if( mnEditLock != 0 )
1077 		return;
1078 
1079 	updateTree( rEvent, true );
1080 }
1081 
1082 void TreeControlPeer::updateTree( const ::com::sun::star::awt::tree::TreeDataModelEvent& rEvent, bool bRecursive )
1083 {
1084 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
1085 
1086 	Sequence< Reference< XTreeNode > > Nodes;
1087 	Reference< XTreeNode > xNode( rEvent.ParentNode );
1088 	if( !xNode.is() && Nodes.getLength() )
1089 	{
1090 		xNode = Nodes[0];
1091 	}
1092 
1093 	if( xNode.is() )
1094 		updateNode( rTree, xNode, bRecursive );
1095 }
1096 
1097 void TreeControlPeer::updateNode( UnoTreeListBoxImpl& rTree, const Reference< XTreeNode >& xNode, bool bRecursive )
1098 {
1099 	if( xNode.is() )
1100 	{
1101 		UnoTreeListEntry* pNodeEntry = getEntry( xNode, false );
1102 
1103 		if( !pNodeEntry )
1104 		{
1105 			Reference< XTreeNode > xParentNode( xNode->getParent() );
1106 			UnoTreeListEntry* pParentEntry = 0;
1107 			sal_uLong nChild = LIST_APPEND;
1108 
1109 			if( xParentNode.is() )
1110 			{
1111 				pParentEntry = getEntry( xParentNode  );
1112 				nChild = xParentNode->getIndex( xNode );
1113 			}
1114 
1115 			pNodeEntry = createEntry( xNode, pParentEntry, nChild );
1116 		}
1117 
1118 		if( bRecursive )
1119 			updateChildNodes( rTree, xNode, pNodeEntry );
1120 	}
1121 }
1122 
1123 void TreeControlPeer::updateChildNodes( UnoTreeListBoxImpl& rTree, const Reference< XTreeNode >& xParentNode, UnoTreeListEntry* pParentEntry )
1124 {
1125 	if( xParentNode.is() && pParentEntry )
1126 	{
1127 		UnoTreeListEntry* pCurrentChild = dynamic_cast< UnoTreeListEntry* >( rTree.FirstChild( pParentEntry ) );
1128 
1129 		const sal_Int32 nChildCount = xParentNode->getChildCount();
1130 		for( sal_Int32 nChild = 0; nChild < nChildCount; nChild++ )
1131 		{
1132 			Reference< XTreeNode > xNode( xParentNode->getChildAt( nChild ) );
1133 			if( !pCurrentChild || ( pCurrentChild->mxNode != xNode ) )
1134 			{
1135 				UnoTreeListEntry* pNodeEntry = getEntry( xNode, false );
1136 				if( pNodeEntry == 0 )
1137 				{
1138 					// child node is not yet part of the tree, add it
1139 					pCurrentChild = createEntry( xNode, pParentEntry, nChild );
1140 				}
1141 				else if( pNodeEntry != pCurrentChild )
1142 				{
1143 					// node is already part of the tree, but not on the correct position
1144 					rTree.GetModel()->Move( pNodeEntry, pParentEntry, nChild );
1145 					pCurrentChild = pNodeEntry;
1146 					updateEntry( pCurrentChild );
1147 				}
1148 			}
1149 			else
1150 			{
1151 				// child node has entry and entry is equal to current entry,
1152 				// so no structural changes happened
1153 				updateEntry( pCurrentChild );
1154 			}
1155 
1156 			pCurrentChild = dynamic_cast< UnoTreeListEntry* >( rTree.NextSibling( pCurrentChild ) );
1157 		}
1158 
1159 		// check if we have entries without nodes left, we need to remove them
1160 		while( pCurrentChild )
1161 		{
1162 			UnoTreeListEntry* pNextChild = dynamic_cast< UnoTreeListEntry* >( rTree.NextSibling( pCurrentChild ) );
1163 			rTree.GetModel()->Remove( pCurrentChild );
1164 			pCurrentChild = pNextChild;
1165 		}
1166 	}
1167 }
1168 
1169 OUString TreeControlPeer::getEntryString( const Any& rValue )
1170 {
1171 	OUString sValue;
1172 	if( rValue.hasValue() )
1173 	{
1174 		switch( rValue.getValueTypeClass() )
1175 		{
1176 		case TypeClass_SHORT:
1177 		case TypeClass_LONG:
1178 			{
1179 				sal_Int32 nValue = 0;
1180 				if( rValue >>= nValue )
1181 					sValue = OUString::valueOf( nValue );
1182 				break;
1183 			}
1184 		case TypeClass_BYTE:
1185 		case TypeClass_UNSIGNED_SHORT:
1186 		case TypeClass_UNSIGNED_LONG:
1187 			{
1188 				sal_uInt32 nValue = 0;
1189 				if( rValue >>= nValue )
1190 					sValue = OUString::valueOf( (sal_Int64)nValue );
1191 				break;
1192 			}
1193 		case TypeClass_HYPER:
1194 			{
1195 				sal_Int64 nValue = 0;
1196 				if( rValue >>= nValue )
1197 					sValue = OUString::valueOf( nValue );
1198 				break;
1199 			}
1200 		case TypeClass_UNSIGNED_HYPER:
1201 			{
1202 				sal_uInt64 nValue = 0;
1203 				if( rValue >>= nValue )
1204 					sValue = OUString::valueOf( (sal_Int64)nValue );
1205 				break;
1206 			}
1207 		case TypeClass_FLOAT:
1208 		case TypeClass_DOUBLE:
1209 			{
1210 				double fValue = 0.0;
1211 				if( rValue >>= fValue )
1212 					sValue = OUString::valueOf( fValue );
1213 				break;
1214 			}
1215 		case TypeClass_STRING:
1216 			rValue >>= sValue;
1217 			break;
1218 	/*
1219 		case TypeClass_INTERFACE:
1220 			// @todo
1221 			break;
1222 		case TypeClass_SEQUENCE:
1223 			{
1224 				Sequence< Any > aValues;
1225 				if( aValue >>= aValues )
1226 				{
1227 					updateEntry( SvLBoxEntry& rEntry, aValues );
1228 					return;
1229 				}
1230 			}
1231 			break;
1232 	*/
1233 		default:
1234 			break;
1235 		}
1236 	}
1237 	return sValue;
1238 }
1239 
1240 // XEventListener
1241 void SAL_CALL TreeControlPeer::disposing( const ::com::sun::star::lang::EventObject& ) throw(::com::sun::star::uno::RuntimeException)
1242 {
1243 	// model is disposed, so we clear our tree
1244 	::vos::OGuard aGuard( GetMutex() );
1245 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
1246 	rTree.Clear();
1247 	mxDataModel.clear();
1248 }
1249 
1250 void TreeControlPeer::onChangeDataModel( UnoTreeListBoxImpl& rTree, const Reference< XTreeDataModel >& xDataModel )
1251 {
1252 	if( xDataModel.is() && (mxDataModel == xDataModel) )
1253 		return; // do nothing
1254 
1255 	Reference< XTreeDataModelListener > xListener( this );
1256 
1257 	if( mxDataModel.is() )
1258 		mxDataModel->removeTreeDataModelListener( xListener );
1259 
1260 	if( !xDataModel.is() )
1261 	{
1262 		static const OUString aSN( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.awt.tree.DefaultTreeDataModel" ) );
1263 		Reference< XMultiServiceFactory > xORB( ::comphelper::getProcessServiceFactory() );
1264 		if( xORB.is() )
1265 		{
1266 			mxDataModel.query( xORB->createInstance( aSN ) );
1267 		}
1268 	}
1269 
1270 	mxDataModel = xDataModel;
1271 
1272 	fillTree( rTree, mxDataModel );
1273 
1274 	if( mxDataModel.is() )
1275 		mxDataModel->addTreeDataModelListener( xListener );
1276 }
1277 
1278 // --------------------------------------------------------------------
1279 // ::com::sun::star::awt::XLayoutConstrains
1280 // --------------------------------------------------------------------
1281 
1282 ::com::sun::star::awt::Size TreeControlPeer::getMinimumSize() throw(RuntimeException)
1283 {
1284 	::vos::OGuard aGuard( GetMutex() );
1285 
1286 	::com::sun::star::awt::Size aSz;
1287 /* todo
1288 	MultiLineEdit* pEdit = (MultiLineEdit*) GetWindow();
1289 	if ( pEdit )
1290 		aSz = AWTSize(pEdit->CalcMinimumSize());
1291 */
1292 	return aSz;
1293 }
1294 
1295 ::com::sun::star::awt::Size TreeControlPeer::getPreferredSize() throw(RuntimeException)
1296 {
1297 	return getMinimumSize();
1298 }
1299 
1300 ::com::sun::star::awt::Size TreeControlPeer::calcAdjustedSize( const ::com::sun::star::awt::Size& rNewSize ) throw(RuntimeException)
1301 {
1302 	::vos::OGuard aGuard( GetMutex() );
1303 
1304 	::com::sun::star::awt::Size aSz = rNewSize;
1305 /* todo
1306 	MultiLineEdit* pEdit = (MultiLineEdit*) GetWindow();
1307 	if ( pEdit )
1308 		aSz = AWTSize(pEdit->CalcAdjustedSize( VCLSize(rNewSize )));
1309 */
1310 	return aSz;
1311 }
1312 
1313 // --------------------------------------------------------------------
1314 // ::com::sun::star::awt::XVclWindowPeer
1315 // --------------------------------------------------------------------
1316 
1317 void TreeControlPeer::setProperty( const ::rtl::OUString& PropertyName, const Any& aValue) throw(RuntimeException)
1318 {
1319 	::vos::OGuard aGuard( GetMutex() );
1320 
1321 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
1322 
1323 	switch( GetPropertyId( PropertyName ) )
1324 	{
1325         case BASEPROPERTY_HIDEINACTIVESELECTION:
1326         {
1327             sal_Bool bEnabled = sal_False;
1328             if ( aValue >>= bEnabled )
1329             {
1330                 WinBits nStyle = rTree.GetStyle();
1331                 if ( bEnabled )
1332                     nStyle |= WB_HIDESELECTION;
1333                 else
1334                     nStyle &= ~WB_HIDESELECTION;
1335                 rTree.SetStyle( nStyle );
1336             }
1337         }
1338         break;
1339 
1340 		case BASEPROPERTY_TREE_SELECTIONTYPE:
1341 		{
1342 			SelectionType eSelectionType;
1343 			if( aValue >>= eSelectionType )
1344 			{
1345 				SelectionMode eSelMode;
1346 				switch( eSelectionType )
1347 				{
1348 				case SelectionType_SINGLE:	eSelMode = SINGLE_SELECTION; break;
1349 				case SelectionType_RANGE:	eSelMode = RANGE_SELECTION; break;
1350 				case SelectionType_MULTI:	eSelMode = MULTIPLE_SELECTION; break;
1351 	//			case SelectionType_NONE:
1352 				default:					eSelMode = NO_SELECTION; break;
1353 				}
1354 				if( rTree.GetSelectionMode() != eSelMode )
1355 					rTree.SetSelectionMode( eSelMode );
1356 			}
1357 			break;
1358 		}
1359 
1360 		case BASEPROPERTY_TREE_DATAMODEL:
1361 			onChangeDataModel( rTree, Reference< XTreeDataModel >( aValue, UNO_QUERY ) );
1362 			break;
1363 		case BASEPROPERTY_ROW_HEIGHT:
1364 		{
1365 			sal_Int32 nHeight = 0;
1366 			if( aValue >>= nHeight )
1367 				rTree.SetEntryHeight( (short)nHeight );
1368 			break;
1369 		}
1370 		case BASEPROPERTY_TREE_EDITABLE:
1371 		{
1372 			sal_Bool bEnabled = false;
1373 			if( aValue >>= bEnabled )
1374 				rTree.EnableInplaceEditing( bEnabled ? sal_True : sal_False );
1375 			break;
1376 		}
1377 		case BASEPROPERTY_TREE_INVOKESSTOPNODEEDITING:
1378 			break; // @todo
1379 		case BASEPROPERTY_TREE_ROOTDISPLAYED:
1380         {
1381 			sal_Bool bDisplayed = false;
1382 			if( (aValue >>= bDisplayed) && ( bDisplayed != mbIsRootDisplayed) )
1383 			{
1384 				onChangeRootDisplayed(bDisplayed);
1385 			}
1386 			break;
1387         }
1388 		case BASEPROPERTY_TREE_SHOWSHANDLES:
1389 		{
1390 			sal_Bool bEnabled = false;
1391 			if( aValue >>= bEnabled )
1392 			{
1393 				WinBits nBits = rTree.GetStyle() & (~WB_HASLINES);
1394 				if( bEnabled )
1395 					nBits |= WB_HASLINES;
1396 				if( nBits != rTree.GetStyle() )
1397 					rTree.SetStyle( nBits );
1398 			}
1399 			break;
1400 		}
1401 		case BASEPROPERTY_TREE_SHOWSROOTHANDLES:
1402 		{
1403 			sal_Bool bEnabled = false;
1404 			if( aValue >>= bEnabled )
1405 			{
1406 				WinBits nBits = rTree.GetStyle() & (~WB_HASLINESATROOT);
1407 				if( bEnabled )
1408 					nBits |= WB_HASLINESATROOT;
1409 				if( nBits != rTree.GetStyle() )
1410 					rTree.SetStyle( nBits );
1411 			}
1412 			break;
1413 		}
1414 		default:
1415 		VCLXWindow::setProperty( PropertyName, aValue );
1416 		break;
1417 	}
1418 }
1419 
1420 Any TreeControlPeer::getProperty( const ::rtl::OUString& PropertyName ) throw(RuntimeException)
1421 {
1422 	::vos::OGuard aGuard( GetMutex() );
1423 
1424 	const sal_uInt16 nPropId = GetPropertyId( PropertyName );
1425 	if( (nPropId >= BASEPROPERTY_TREE_START) && (nPropId <= BASEPROPERTY_TREE_END) )
1426 	{
1427 		UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
1428 		switch(nPropId)
1429 		{
1430         case BASEPROPERTY_HIDEINACTIVESELECTION:
1431 			return Any( ( rTree.GetStyle() & WB_HIDESELECTION ) != 0 ? sal_True : sal_False );
1432 
1433 		case BASEPROPERTY_TREE_SELECTIONTYPE:
1434 		{
1435 			SelectionType eSelectionType;
1436 
1437 			SelectionMode eSelMode = rTree.GetSelectionMode();
1438 			switch( eSelMode )
1439 			{
1440 			case SINGLE_SELECTION:	eSelectionType = SelectionType_SINGLE; break;
1441 			case RANGE_SELECTION:	eSelectionType = SelectionType_RANGE; break;
1442 			case MULTIPLE_SELECTION:eSelectionType = SelectionType_MULTI; break;
1443 //			case NO_SELECTION:
1444 			default:				eSelectionType = SelectionType_NONE; break;
1445 			}
1446 			return Any( eSelectionType );
1447 		}
1448 		case BASEPROPERTY_ROW_HEIGHT:
1449 			return Any( (sal_Int32)rTree.GetEntryHeight() );
1450 		case BASEPROPERTY_TREE_DATAMODEL:
1451 			return Any( mxDataModel );
1452 		case BASEPROPERTY_TREE_EDITABLE:
1453 			return Any( rTree.IsInplaceEditingEnabled() ? sal_True : sal_False );
1454 		case BASEPROPERTY_TREE_INVOKESSTOPNODEEDITING:
1455 			return Any( sal_True ); // @todo
1456 		case BASEPROPERTY_TREE_ROOTDISPLAYED:
1457 			return Any( mbIsRootDisplayed );
1458 		case BASEPROPERTY_TREE_SHOWSHANDLES:
1459 			return Any( (rTree.GetStyle() & WB_HASLINES) != 0 ? sal_True : sal_False );
1460 		case BASEPROPERTY_TREE_SHOWSROOTHANDLES:
1461 			return Any( (rTree.GetStyle() & WB_HASLINESATROOT) != 0 ? sal_True : sal_False );
1462 		}
1463 	}
1464 	return VCLXWindow::getProperty( PropertyName );
1465 }
1466 
1467 void TreeControlPeer::onChangeRootDisplayed( sal_Bool bIsRootDisplayed )
1468 {
1469 	if( mbIsRootDisplayed == bIsRootDisplayed )
1470 		return;
1471 
1472 	mbIsRootDisplayed = bIsRootDisplayed;
1473 
1474 	UnoTreeListBoxImpl& rTree = getTreeListBoxOrThrow();
1475 
1476 	if( rTree.GetEntryCount() == 0 )
1477 		return;
1478 
1479 	// todo
1480 	fillTree( rTree, mxDataModel );
1481 	if( mbIsRootDisplayed )
1482 	{
1483 	}
1484 	else
1485 	{
1486 	}
1487 }
1488 
1489 bool TreeControlPeer::loadImage( const ::rtl::OUString& rURL, Image& rImage )
1490 {
1491 	if( !mxGraphicProvider.is() )
1492 	{
1493 		static const OUString aSN( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.graphic.GraphicProvider" ) );
1494 		Reference< XMultiServiceFactory > xORB( ::comphelper::getProcessServiceFactory() );
1495 		if( xORB.is() )
1496 		{
1497 			Reference< XInterface > x( xORB->createInstance( aSN ) );
1498 			mxGraphicProvider.query( x );
1499 			mxGraphicProvider = Reference< XGraphicProvider >( x, UNO_QUERY );
1500 		}
1501 	}
1502 
1503 	if( mxGraphicProvider.is() ) try
1504 	{
1505 		::com::sun::star::beans::PropertyValues aProps( 1 );
1506 		aProps[0].Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
1507 		aProps[0].Value <<= rURL;
1508 
1509 		Reference< XGraphic > xGraphic( mxGraphicProvider->queryGraphic( aProps ) );
1510 
1511 		Graphic aGraphic( xGraphic );
1512 		rImage = aGraphic.GetBitmapEx();
1513 		return true;
1514 	}
1515 	catch( Exception& )
1516 	{
1517 	}
1518 
1519 	return false;
1520 }
1521 
1522 // ====================================================================
1523 // class UnoTreeListBoxImpl
1524 // ====================================================================
1525 
1526 UnoTreeListBoxImpl::UnoTreeListBoxImpl( TreeControlPeer* pPeer, Window* pParent, WinBits nWinStyle )
1527 : SvTreeListBox( pParent, nWinStyle )
1528 , mxPeer( pPeer )
1529 {
1530 	SetStyle( WB_BORDER | WB_HASLINES |WB_HASBUTTONS | WB_HASLINESATROOT | WB_HASBUTTONSATROOT | WB_HSCROLL );
1531 	SetNodeDefaultImages();
1532 	SetSelectHdl( LINK(this, UnoTreeListBoxImpl, OnSelectionChangeHdl) );
1533 	SetDeselectHdl( LINK(this, UnoTreeListBoxImpl, OnSelectionChangeHdl) );
1534 
1535 	SetExpandingHdl( LINK(this, UnoTreeListBoxImpl, OnExpandingHdl) );
1536 	SetExpandedHdl( LINK(this, UnoTreeListBoxImpl, OnExpandedHdl) );
1537 
1538 }
1539 
1540 // --------------------------------------------------------------------
1541 
1542 UnoTreeListBoxImpl::~UnoTreeListBoxImpl()
1543 {
1544 	if( mxPeer.is() )
1545 		mxPeer->disposeControl();
1546 }
1547 
1548 // --------------------------------------------------------------------
1549 
1550 IMPL_LINK( UnoTreeListBoxImpl, OnSelectionChangeHdl, UnoTreeListBoxImpl*, EMPTYARG )
1551 {
1552 	if( mxPeer.is() )
1553 		mxPeer->onSelectionChanged();
1554 	return 0;
1555 }
1556 
1557 // --------------------------------------------------------------------
1558 
1559 IMPL_LINK(UnoTreeListBoxImpl, OnExpandingHdl, UnoTreeListBoxImpl*, EMPTYARG )
1560 {
1561 	UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( GetHdlEntry() );
1562 
1563 	if( pEntry && mxPeer.is() )
1564 	{
1565 		return mxPeer->onExpanding( pEntry->mxNode, !IsExpanded( pEntry ) ) ? 1 : 0;
1566 	}
1567 	return 0;
1568 }
1569 
1570 // --------------------------------------------------------------------
1571 
1572 IMPL_LINK(UnoTreeListBoxImpl, OnExpandedHdl, UnoTreeListBoxImpl*, EMPTYARG )
1573 {
1574 	UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( GetHdlEntry() );
1575 	if( pEntry && mxPeer.is() )
1576 	{
1577 		mxPeer->onExpanded( pEntry->mxNode, IsExpanded( pEntry ) );
1578 	}
1579 	return 0;
1580 }
1581 
1582 // --------------------------------------------------------------------
1583 
1584 sal_uInt32 UnoTreeListBoxImpl::insert( SvLBoxEntry* pEntry,SvLBoxEntry* pParent,sal_uLong nPos )
1585 {
1586 	if( pParent )
1587 		return SvTreeListBox::Insert( pEntry, pParent, nPos );
1588 	else
1589 		return SvTreeListBox::Insert( pEntry, nPos );
1590 }
1591 
1592 // --------------------------------------------------------------------
1593 
1594 void UnoTreeListBoxImpl::RequestingChilds( SvLBoxEntry* pParent )
1595 {
1596 	UnoTreeListEntry* pEntry = dynamic_cast< UnoTreeListEntry* >( pParent );
1597 	if( pEntry && pEntry->mxNode.is() && mxPeer.is() )
1598 		mxPeer->onRequestChildNodes( pEntry->mxNode );
1599 }
1600 
1601 // --------------------------------------------------------------------
1602 
1603 sal_Bool UnoTreeListBoxImpl::EditingEntry( SvLBoxEntry* pEntry, Selection& )
1604 {
1605 	return mxPeer.is() ? mxPeer->onEditingEntry( dynamic_cast< UnoTreeListEntry* >( pEntry ) ) : false;
1606 }
1607 
1608 // --------------------------------------------------------------------
1609 
1610 sal_Bool UnoTreeListBoxImpl::EditedEntry( SvLBoxEntry* pEntry, const XubString& rNewText )
1611 {
1612 	return mxPeer.is() ? mxPeer->onEditedEntry( dynamic_cast< UnoTreeListEntry* >( pEntry ), rNewText ) : false;
1613 }
1614 
1615 // ====================================================================
1616 // class UnoTreeListItem
1617 // ====================================================================
1618 
1619 UnoTreeListItem::UnoTreeListItem( SvLBoxEntry* pEntry )
1620 : SvLBoxItem( pEntry, 0 )
1621 {
1622 }
1623 
1624 // --------------------------------------------------------------------
1625 
1626 UnoTreeListItem::UnoTreeListItem()
1627 : SvLBoxItem()
1628 {
1629 }
1630 
1631 // --------------------------------------------------------------------
1632 
1633 UnoTreeListItem::~UnoTreeListItem()
1634 {
1635 }
1636 
1637 // --------------------------------------------------------------------
1638 
1639 sal_uInt16 UnoTreeListItem::IsA()
1640 {
1641 	return 0;
1642 }
1643 
1644 // --------------------------------------------------------------------
1645 
1646 void UnoTreeListItem::Paint( const Point& rPos, SvLBox& rDev, sal_uInt16 /* nFlags */, SvLBoxEntry* _pEntry)
1647 {
1648 	Point aPos( rPos );
1649 	if( _pEntry )
1650 	{
1651 		Size aSize( GetSize(&rDev,_pEntry) );
1652 		if( !!maImage )
1653 		{
1654 			rDev.DrawImage( aPos, maImage, rDev.IsEnabled() ? 0 : IMAGE_DRAW_DISABLE );
1655 			int nWidth = maImage.GetSizePixel().Width() + 6;
1656 			aPos.X() += nWidth;
1657 			aSize.Width() -= nWidth;
1658 		}
1659 		rDev.DrawText( Rectangle(aPos,aSize),maText, rDev.IsEnabled() ? 0 : TEXT_DRAW_DISABLE );
1660 	}
1661 	else
1662 	{
1663 		if( !!maImage )
1664 		{
1665 			rDev.DrawImage( aPos, maImage, rDev.IsEnabled() ? 0 : IMAGE_DRAW_DISABLE);
1666 			aPos.X() += maImage.GetSizePixel().Width() + 6;
1667 		}
1668 		rDev.DrawText( aPos, maText);
1669 	}
1670 }
1671 
1672 // --------------------------------------------------------------------
1673 
1674 SvLBoxItem* UnoTreeListItem::Create() const
1675 {
1676 	return new UnoTreeListItem;
1677 }
1678 
1679 // --------------------------------------------------------------------
1680 
1681 void UnoTreeListItem::Clone( SvLBoxItem* pSource )
1682 {
1683 	UnoTreeListItem* pSourceItem = dynamic_cast< UnoTreeListItem* >( pSource );
1684 	if( pSourceItem )
1685 	{
1686 		maText = pSourceItem->maText;
1687 		maImage = pSourceItem->maImage;
1688 	}
1689 }
1690 
1691 // --------------------------------------------------------------------
1692 
1693 OUString UnoTreeListItem::GetText() const
1694 {
1695 	return maText;
1696 }
1697 
1698 // --------------------------------------------------------------------
1699 
1700 void UnoTreeListItem::SetText( const OUString& rText )
1701 {
1702 	maText = rText;
1703 }
1704 
1705 // --------------------------------------------------------------------
1706 
1707 void UnoTreeListItem::SetImage( const Image& rImage )
1708 {
1709 	maImage = rImage;
1710 }
1711 
1712 // --------------------------------------------------------------------
1713 
1714 OUString UnoTreeListItem::GetGraphicURL() const
1715 {
1716 	return maGraphicURL;
1717 }
1718 
1719 // --------------------------------------------------------------------
1720 
1721 void UnoTreeListItem::SetGraphicURL( const OUString& rGraphicURL )
1722 {
1723 	maGraphicURL = rGraphicURL;
1724 }
1725 
1726 // --------------------------------------------------------------------
1727 
1728 void UnoTreeListItem::InitViewData( SvLBox* pView,SvLBoxEntry* pEntry, SvViewDataItem* pViewData)
1729 {
1730 	if( !pViewData )
1731 		pViewData = pView->GetViewDataItem( pEntry, this );
1732 
1733 	pViewData->aSize = maImage.GetSizePixel();
1734 
1735 	const Size aTextSize(pView->GetTextWidth( maText ), pView->GetTextHeight());
1736 	if( pViewData->aSize.Width() )
1737 	{
1738 		pViewData->aSize.Width() += 6 + aTextSize.Width();
1739 		if( pViewData->aSize.Height() < aTextSize.Height() )
1740 			pViewData->aSize.Height() = aTextSize.Height();
1741 	}
1742 	else
1743 	{
1744 		pViewData->aSize = aTextSize;
1745 	}
1746 }
1747 
1748 // --------------------------------------------------------------------
1749 
1750 UnoTreeListEntry::UnoTreeListEntry( const Reference< XTreeNode >& xNode, TreeControlPeer* pPeer )
1751 : SvLBoxEntry()
1752 , mxNode( xNode )
1753 , mpPeer( pPeer )
1754 {
1755 	if( mpPeer )
1756 		mpPeer->addEntry( this );
1757 }
1758 
1759 // --------------------------------------------------------------------
1760 
1761 UnoTreeListEntry::~UnoTreeListEntry()
1762 {
1763 	if( mpPeer )
1764 		mpPeer->removeEntry( this );
1765 }
1766