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