Coverage Report

Created: 2025-11-16 09:57

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