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