Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/unoobj/cellvaluebinding.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
#include "cellvaluebinding.hxx"
21
#include <rtl/math.hxx>
22
#include <com/sun/star/form/binding/IncompatibleTypesException.hpp>
23
#include <com/sun/star/lang/NotInitializedException.hpp>
24
#include <com/sun/star/text/XTextRange.hpp>
25
#include <com/sun/star/table/XCellRange.hpp>
26
#include <com/sun/star/sheet/FormulaResult.hpp>
27
#include <com/sun/star/sheet/XCellAddressable.hpp>
28
#include <com/sun/star/sheet/XCellRangeData.hpp>
29
#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
30
#include <com/sun/star/container/XIndexAccess.hpp>
31
#include <com/sun/star/beans/PropertyAttribute.hpp>
32
#include <com/sun/star/beans/NamedValue.hpp>
33
#include <com/sun/star/util/XNumberFormatsSupplier.hpp>
34
#include <com/sun/star/util/XNumberFormatTypes.hpp>
35
#include <com/sun/star/util/NumberFormat.hpp>
36
#include <cppuhelper/supportsservice.hxx>
37
#include <comphelper/types.hxx>
38
#include <comphelper/diagnose_ex.hxx>
39
40
namespace calc
41
{
42
43
0
#define PROP_HANDLE_BOUND_CELL  1
44
45
    namespace lang = css::lang;
46
    using namespace ::com::sun::star::uno;
47
    using namespace ::com::sun::star::lang;
48
    using namespace ::com::sun::star::table;
49
    using namespace ::com::sun::star::text;
50
    using namespace ::com::sun::star::sheet;
51
    using namespace ::com::sun::star::container;
52
    using namespace ::com::sun::star::beans;
53
    using namespace ::com::sun::star::util;
54
    using namespace ::com::sun::star::form::binding;
55
56
    OCellValueBinding::OCellValueBinding( const Reference< XSpreadsheetDocument >& _rxDocument, bool _bListPos )
57
0
        :m_xDocument( _rxDocument )
58
0
        ,m_bInitialized( false )
59
0
        ,m_bListPos( _bListPos )
60
0
    {
61
        // register our property at the base class
62
0
        registerPropertyNoMember(
63
0
            u"BoundCell"_ustr,
64
0
            PROP_HANDLE_BOUND_CELL,
65
0
            PropertyAttribute::BOUND | PropertyAttribute::READONLY,
66
0
            cppu::UnoType<CellAddress>::get(),
67
0
            css::uno::Any(CellAddress())
68
0
        );
69
70
        // TODO: implement a ReadOnly property as required by the service,
71
        // which probably maps to the cell being locked
72
0
    }
Unexecuted instantiation: calc::OCellValueBinding::OCellValueBinding(com::sun::star::uno::Reference<com::sun::star::sheet::XSpreadsheetDocument> const&, bool)
Unexecuted instantiation: calc::OCellValueBinding::OCellValueBinding(com::sun::star::uno::Reference<com::sun::star::sheet::XSpreadsheetDocument> const&, bool)
73
74
    OCellValueBinding::~OCellValueBinding( )
75
0
    {
76
0
        if ( !m_bDisposed )
77
0
        {
78
0
            acquire();  // prevent duplicate dtor
79
0
            dispose();
80
0
        }
81
0
    }
82
83
    IMPLEMENT_FORWARD_XINTERFACE2( OCellValueBinding, OCellValueBinding_Base, OCellValueBinding_PBase )
84
85
    IMPLEMENT_FORWARD_XTYPEPROVIDER2( OCellValueBinding, OCellValueBinding_Base, OCellValueBinding_PBase )
86
87
    void OCellValueBinding::disposing( std::unique_lock<std::mutex>& rGuard )
88
0
    {
89
0
        Reference<XModifyBroadcaster> xBroadcaster( m_xCell, UNO_QUERY );
90
0
        if ( xBroadcaster.is() )
91
0
        {
92
0
            xBroadcaster->removeModifyListener( this );
93
0
        }
94
95
0
        WeakComponentImplHelperBase::disposing(rGuard);
96
97
        // TODO: clean up here whatever you need to clean up (e.g. deregister as XEventListener
98
        // for the cell)
99
0
    }
100
101
    Reference< XPropertySetInfo > SAL_CALL OCellValueBinding::getPropertySetInfo(  )
102
0
    {
103
0
        return createPropertySetInfo( getInfoHelper() ) ;
104
0
    }
105
106
    ::cppu::IPropertyArrayHelper& OCellValueBinding::getInfoHelper()
107
0
    {
108
0
        return *OCellValueBinding_PABase::getArrayHelper();
109
0
    }
110
111
    ::cppu::IPropertyArrayHelper* OCellValueBinding::createArrayHelper( ) const
112
0
    {
113
0
        Sequence< Property > aProps;
114
0
        describeProperties( aProps );
115
0
        return new ::cppu::OPropertyArrayHelper(aProps);
116
0
    }
117
118
    void OCellValueBinding::getFastPropertyValue( std::unique_lock<std::mutex>& /*rGuard*/, Any& _rValue, sal_Int32 _nHandle ) const
119
0
    {
120
0
        OSL_ENSURE( _nHandle == PROP_HANDLE_BOUND_CELL, "OCellValueBinding::getFastPropertyValue: invalid handle!" );
121
            // we only have this one property...
122
123
0
        _rValue.clear();
124
0
        Reference< XCellAddressable > xCellAddress( m_xCell, UNO_QUERY );
125
0
        if ( xCellAddress.is() )
126
0
            _rValue <<= xCellAddress->getCellAddress( );
127
0
    }
128
129
    Sequence< Type > SAL_CALL OCellValueBinding::getSupportedValueTypes(  )
130
0
    {
131
0
        std::unique_lock<std::mutex> aGuard(m_aMutex);
132
0
        throwIfDisposed(aGuard);
133
0
        checkInitialized( );
134
0
        return getSupportedValueTypes(aGuard);
135
0
    }
136
137
    Sequence< Type > OCellValueBinding::getSupportedValueTypes( std::unique_lock<std::mutex>& /*rGuard*/  ) const
138
0
    {
139
0
        sal_Int32 nCount = m_xCellText.is() ? 3 : m_xCell.is() ? 1 : 0;
140
0
        if ( m_bListPos )
141
0
            ++nCount;
142
143
0
        Sequence< Type > aTypes( nCount );
144
0
        if ( m_xCell.is() )
145
0
        {
146
0
            auto pTypes = aTypes.getArray();
147
148
            // an XCell can be used to set/get "double" values
149
0
            pTypes[0] = ::cppu::UnoType<double>::get();
150
0
            if ( m_xCellText.is() )
151
0
            {
152
                // an XTextRange can be used to set/get "string" values
153
0
                pTypes[1] = ::cppu::UnoType<OUString>::get();
154
                // and additionally, we use it to handle booleans
155
0
                pTypes[2] = ::cppu::UnoType<sal_Bool>::get();
156
0
            }
157
158
            // add sal_Int32 only if constructed as ListPositionCellBinding
159
0
            if ( m_bListPos )
160
0
                pTypes[nCount-1] = cppu::UnoType<sal_Int32>::get();
161
0
        }
162
163
0
        return aTypes;
164
0
    }
165
166
    sal_Bool SAL_CALL OCellValueBinding::supportsType( const Type& aType )
167
0
    {
168
0
        std::unique_lock<std::mutex> aGuard(m_aMutex);
169
0
        throwIfDisposed(aGuard);
170
0
        checkInitialized( );
171
0
        return supportsType(aGuard, aType);
172
0
    }
173
174
    bool OCellValueBinding::supportsType( std::unique_lock<std::mutex>& rGuard, const Type& aType ) const
175
0
    {
176
        // look up in our sequence
177
0
        const Sequence< Type > aSupportedTypes( getSupportedValueTypes(rGuard) );
178
0
        for ( auto const & i : aSupportedTypes )
179
0
            if ( aType == i )
180
0
                return true;
181
182
0
        return false;
183
0
    }
184
185
    Any SAL_CALL OCellValueBinding::getValue( const Type& aType )
186
0
    {
187
0
        std::unique_lock<std::mutex> aGuard(m_aMutex);
188
0
        throwIfDisposed(aGuard);
189
0
        checkInitialized( );
190
0
        checkValueType( aGuard, aType );
191
192
0
        Any aReturn;
193
0
        switch ( aType.getTypeClass() )
194
0
        {
195
0
        case TypeClass_STRING:
196
0
            OSL_ENSURE( m_xCellText.is(), "OCellValueBinding::getValue: don't have a text!" );
197
0
            if ( m_xCellText.is() )
198
0
                aReturn <<= m_xCellText->getString();
199
0
            else
200
0
                aReturn <<= OUString();
201
0
            break;
202
203
0
        case TypeClass_BOOLEAN:
204
0
            OSL_ENSURE( m_xCell.is(), "OCellValueBinding::getValue: don't have a double value supplier!" );
205
0
            if ( m_xCell.is() )
206
0
            {
207
                // check if the cell has a numeric value (this might go into a helper function):
208
209
0
                bool bHasValue = false;
210
0
                CellContentType eCellType = m_xCell->getType();
211
0
                if ( eCellType == CellContentType_VALUE )
212
0
                    bHasValue = true;
213
0
                else if ( eCellType == CellContentType_FORMULA )
214
0
                {
215
                    // check if the formula result is a value
216
0
                    if ( m_xCell->getError() == 0 )
217
0
                    {
218
0
                        Reference<XPropertySet> xProp( m_xCell, UNO_QUERY );
219
0
                        if ( xProp.is() )
220
0
                        {
221
0
                            sal_Int32 nResultType;
222
0
                            if ( (xProp->getPropertyValue(u"FormulaResultType2"_ustr) >>= nResultType)
223
0
                                    && nResultType == FormulaResult::VALUE )
224
0
                                bHasValue = true;
225
0
                        }
226
0
                    }
227
0
                }
228
229
0
                if ( bHasValue )
230
0
                {
231
                    // 0 is "unchecked", any other value is "checked", regardless of number format
232
0
                    double nCellValue = m_xCell->getValue();
233
0
                    bool bBoolValue = ( nCellValue != 0.0 );
234
0
                    aReturn <<= bBoolValue;
235
0
                }
236
                // empty cells, text cells and text or error formula results: leave return value empty
237
0
            }
238
0
            break;
239
240
0
        case TypeClass_DOUBLE:
241
0
            OSL_ENSURE( m_xCell.is(), "OCellValueBinding::getValue: don't have a double value supplier!" );
242
0
            if ( m_xCell.is() )
243
0
                aReturn <<= m_xCell->getValue();
244
0
            else
245
0
                aReturn <<= double(0);
246
0
            break;
247
248
0
        case TypeClass_LONG:
249
0
            OSL_ENSURE( m_xCell.is(), "OCellValueBinding::getValue: don't have a double value supplier!" );
250
0
            if ( m_xCell.is() )
251
0
            {
252
                // The list position value in the cell is 1-based.
253
                // We subtract 1 from any cell value (no special handling for 0 or negative values).
254
255
0
                sal_Int32 nValue = static_cast<sal_Int32>(rtl::math::approxFloor( m_xCell->getValue() ));
256
0
                --nValue;
257
258
0
                aReturn <<= nValue;
259
0
            }
260
0
            else
261
0
                aReturn <<= sal_Int32(0);
262
0
            break;
263
264
0
        default:
265
0
            OSL_FAIL( "OCellValueBinding::getValue: unreachable code!" );
266
                // a type other than double and string should never have survived the checkValueType
267
                // above
268
0
        }
269
0
        return aReturn;
270
0
    }
271
272
    void SAL_CALL OCellValueBinding::setValue( const Any& aValue )
273
0
    {
274
0
        std::unique_lock<std::mutex> aGuard(m_aMutex);
275
0
        throwIfDisposed(aGuard);
276
0
        checkInitialized( );
277
0
        if ( aValue.hasValue() )
278
0
            checkValueType( aGuard, aValue.getValueType() );
279
280
0
        switch ( aValue.getValueTypeClass() )
281
0
        {
282
0
        case TypeClass_STRING:
283
0
            {
284
0
                OSL_ENSURE( m_xCellText.is(), "OCellValueBinding::setValue: don't have a text!" );
285
286
0
                OUString sText;
287
0
                aValue >>= sText;
288
0
                if ( m_xCellText.is() )
289
0
                {
290
                    // might call back into us via modified(EventObject&)
291
0
                    aGuard.unlock();
292
0
                    m_xCellText->setString( sText );
293
0
                    aGuard.lock();
294
0
                }
295
0
            }
296
0
            break;
297
298
0
        case TypeClass_BOOLEAN:
299
0
            {
300
0
                OSL_ENSURE( m_xCell.is(), "OCellValueBinding::setValue: don't have a double value supplier!" );
301
302
                // boolean is stored as values 0 or 1
303
                // TODO: set the number format to boolean if no format is set?
304
305
0
                bool bValue( false );
306
0
                aValue >>= bValue;
307
0
                double nCellValue = bValue ? 1.0 : 0.0;
308
309
0
                if ( m_xCell.is() )
310
0
                {
311
                    // might call back into us via modified(EventObject&)
312
0
                    aGuard.unlock();
313
0
                    m_xCell->setValue( nCellValue );
314
0
                    aGuard.lock();
315
0
                }
316
317
0
                setBooleanFormat();
318
0
            }
319
0
            break;
320
321
0
        case TypeClass_DOUBLE:
322
0
            {
323
0
                OSL_ENSURE( m_xCell.is(), "OCellValueBinding::setValue: don't have a double value supplier!" );
324
325
0
                double nValue = 0;
326
0
                aValue >>= nValue;
327
0
                if ( m_xCell.is() )
328
0
                {
329
                    // might call back into us via modified(EventObject&)
330
0
                    aGuard.unlock();
331
0
                    m_xCell->setValue( nValue );
332
0
                    aGuard.lock();
333
0
                }
334
0
            }
335
0
            break;
336
337
0
        case TypeClass_LONG:
338
0
            {
339
0
                OSL_ENSURE( m_xCell.is(), "OCellValueBinding::setValue: don't have a double value supplier!" );
340
341
0
                sal_Int32 nValue = 0;
342
0
                aValue >>= nValue;      // list index from control layer (0-based)
343
0
                ++nValue;               // the list position value in the cell is 1-based
344
0
                if ( m_xCell.is() )
345
0
                {
346
                    // might call back into us via modified(EventObject&)
347
0
                    aGuard.unlock();
348
0
                    m_xCell->setValue( nValue );
349
0
                    aGuard.lock();
350
0
                }
351
0
            }
352
0
            break;
353
354
0
        case TypeClass_VOID:
355
0
            {
356
                // #N/A error value can only be set using XCellRangeData
357
358
0
                Reference<XCellRangeData> xData( m_xCell, UNO_QUERY );
359
0
                OSL_ENSURE( xData.is(), "OCellValueBinding::setValue: don't have XCellRangeData!" );
360
0
                if ( xData.is() )
361
0
                {
362
0
                    Sequence<Any> aInner(1);                            // one empty element
363
0
                    Sequence< Sequence<Any> > aOuter( &aInner, 1 );     // one row
364
                    // might call back into us via modified(EventObject&)
365
0
                    aGuard.unlock();
366
0
                    xData->setDataArray( aOuter );
367
0
                    aGuard.lock();
368
0
                }
369
0
            }
370
0
            break;
371
372
0
        default:
373
0
            OSL_FAIL( "OCellValueBinding::setValue: unreachable code!" );
374
                // a type other than double and string should never have survived the checkValueType
375
                // above
376
0
        }
377
0
    }
378
379
    void OCellValueBinding::setBooleanFormat()
380
0
    {
381
        // set boolean number format if not already set
382
383
0
        OUString sPropName( u"NumberFormat"_ustr );
384
0
        Reference<XPropertySet> xCellProp( m_xCell, UNO_QUERY );
385
0
        Reference<XNumberFormatsSupplier> xSupplier( m_xDocument, UNO_QUERY );
386
0
        if ( !(xSupplier.is() && xCellProp.is()) )
387
0
            return;
388
389
0
        Reference<XNumberFormats> xFormats(xSupplier->getNumberFormats());
390
0
        Reference<XNumberFormatTypes> xTypes( xFormats, UNO_QUERY );
391
0
        if ( !xTypes.is() )
392
0
            return;
393
394
0
        lang::Locale aLocale;
395
0
        bool bWasBoolean = false;
396
397
0
        sal_Int32 nOldIndex = ::comphelper::getINT32( xCellProp->getPropertyValue( sPropName ) );
398
0
        Reference<XPropertySet> xOldFormat;
399
0
        try
400
0
        {
401
0
            xOldFormat.set(xFormats->getByKey( nOldIndex ));
402
0
        }
403
0
        catch ( Exception& )
404
0
        {
405
            // non-existing format - can happen, use defaults
406
0
        }
407
0
        if ( xOldFormat.is() )
408
0
        {
409
            // use the locale of the existing format
410
0
            xOldFormat->getPropertyValue(u"Locale"_ustr) >>= aLocale;
411
412
0
            sal_Int16 nOldType = ::comphelper::getINT16(
413
0
                xOldFormat->getPropertyValue(u"Type"_ustr) );
414
0
            if ( nOldType & NumberFormat::LOGICAL )
415
0
                bWasBoolean = true;
416
0
        }
417
418
0
        if ( !bWasBoolean )
419
0
        {
420
0
            sal_Int32 nNewIndex = xTypes->getStandardFormat( NumberFormat::LOGICAL, aLocale );
421
0
            xCellProp->setPropertyValue( sPropName, Any( nNewIndex ) );
422
0
        }
423
0
    }
424
425
    void OCellValueBinding::checkInitialized()
426
0
    {
427
0
        if ( !m_bInitialized )
428
0
            throw NotInitializedException(u"CellValueBinding is not initialized"_ustr, getXWeak());
429
0
    }
430
431
    void OCellValueBinding::checkValueType( std::unique_lock<std::mutex>& rGuard, const Type& _rType ) const
432
0
    {
433
0
        if ( !supportsType( rGuard, _rType ) )
434
0
        {
435
0
            OUString sMessage = "The given type (" +
436
0
                _rType.getTypeName() +
437
0
                ") is not supported by this binding.";
438
                // TODO: localize this error message
439
440
0
            throw IncompatibleTypesException( sMessage, const_cast<OCellValueBinding&>(*this) );
441
                // TODO: alternatively use a type converter service for this?
442
0
        }
443
0
    }
444
445
    OUString SAL_CALL OCellValueBinding::getImplementationName(  )
446
0
    {
447
0
        return u"com.sun.star.comp.sheet.OCellValueBinding"_ustr;
448
0
    }
449
450
    sal_Bool SAL_CALL OCellValueBinding::supportsService( const OUString& _rServiceName )
451
0
    {
452
0
        return cppu::supportsService(this, _rServiceName);
453
0
    }
454
455
    Sequence< OUString > SAL_CALL OCellValueBinding::getSupportedServiceNames(  )
456
0
    {
457
0
        Sequence< OUString > aServices( m_bListPos ? 3 : 2 );
458
0
        auto pServices = aServices.getArray();
459
0
        pServices[ 0 ] = "com.sun.star.table.CellValueBinding";
460
0
        pServices[ 1 ] = "com.sun.star.form.binding.ValueBinding";
461
0
        if ( m_bListPos )
462
0
            pServices[ 2 ] = "com.sun.star.table.ListPositionCellBinding";
463
0
        return aServices;
464
0
    }
465
466
    void SAL_CALL OCellValueBinding::addModifyListener( const Reference< XModifyListener >& _rxListener )
467
0
    {
468
0
       if ( _rxListener.is() )
469
0
       {
470
0
           std::unique_lock<std::mutex> aGuard(m_aMutex);
471
0
           m_aModifyListeners.addInterface( aGuard, _rxListener );
472
0
       }
473
0
    }
474
475
    void SAL_CALL OCellValueBinding::removeModifyListener( const Reference< XModifyListener >& _rxListener )
476
0
    {
477
0
       if ( _rxListener.is() )
478
0
       {
479
0
           std::unique_lock<std::mutex> aGuard(m_aMutex);
480
0
           m_aModifyListeners.removeInterface( aGuard, _rxListener );
481
0
       }
482
0
    }
483
484
    void OCellValueBinding::notifyModified()
485
0
    {
486
0
        EventObject aEvent;
487
0
        aEvent.Source.set(*this);
488
489
0
        std::unique_lock<std::mutex> aGuard(m_aMutex);
490
0
        m_aModifyListeners.forEach(aGuard,
491
0
            [&aEvent] (const css::uno::Reference<css::util::XModifyListener> & l)
492
0
            {
493
0
                try
494
0
                {
495
0
                    l->modified( aEvent );
496
0
                }
497
0
                catch( const RuntimeException& )
498
0
                {
499
                    // silent this
500
0
                }
501
0
                catch( const Exception& )
502
0
                {
503
0
                    TOOLS_WARN_EXCEPTION( "sc", "OCellValueBinding::notifyModified: caught a (non-runtime) exception!" );
504
0
                }
505
0
            });
506
0
    }
507
508
    void SAL_CALL OCellValueBinding::modified( const EventObject& /* aEvent */ )
509
0
    {
510
0
        notifyModified();
511
0
    }
512
513
    void SAL_CALL OCellValueBinding::disposing( const EventObject& aEvent )
514
0
    {
515
0
        Reference<XInterface> xCellInt( m_xCell, UNO_QUERY );
516
0
        if ( xCellInt == aEvent.Source )
517
0
        {
518
            // release references to cell object
519
0
            m_xCell.clear();
520
0
            m_xCellText.clear();
521
0
        }
522
0
    }
523
524
    void SAL_CALL OCellValueBinding::initialize( const Sequence< Any >& _rArguments )
525
0
    {
526
0
        if ( m_bInitialized )
527
0
            throw RuntimeException(u"CellValueBinding is already initialized"_ustr, getXWeak());
528
529
        // get the cell address
530
0
        CellAddress aAddress;
531
0
        bool bFoundAddress = false;
532
533
0
        for ( const Any& rArg : _rArguments )
534
0
        {
535
0
            NamedValue aValue;
536
0
            if ( rArg >>= aValue )
537
0
            {
538
0
                if ( aValue.Name == "BoundCell" )
539
0
                {
540
0
                    if ( aValue.Value >>= aAddress )
541
0
                    {
542
0
                        bFoundAddress = true;
543
0
                        break;
544
0
                    }
545
0
                }
546
0
            }
547
0
        }
548
549
0
        if ( !bFoundAddress )
550
0
            throw RuntimeException(u"Cell not found"_ustr, getXWeak());
551
552
        // get the cell object
553
0
        try
554
0
        {
555
            // first the sheets collection
556
0
            Reference< XIndexAccess > xSheets;
557
0
            if ( m_xDocument.is() )
558
0
                xSheets.set(m_xDocument->getSheets( ), css::uno::UNO_QUERY);
559
0
            OSL_ENSURE( xSheets.is(), "OCellValueBinding::initialize: could not retrieve the sheets!" );
560
561
0
            if ( xSheets.is() )
562
0
            {
563
                // the concrete sheet
564
0
                Reference< XCellRange > xSheet(xSheets->getByIndex( aAddress.Sheet ), UNO_QUERY);
565
0
                OSL_ENSURE( xSheet.is(), "OCellValueBinding::initialize: NULL sheet, but no exception!" );
566
567
                // the concrete cell
568
0
                if ( xSheet.is() )
569
0
                {
570
0
                    m_xCell.set(xSheet->getCellByPosition( aAddress.Column, aAddress.Row ));
571
0
                    Reference< XCellAddressable > xAddressAccess( m_xCell, UNO_QUERY );
572
0
                    OSL_ENSURE( xAddressAccess.is(), "OCellValueBinding::initialize: either NULL cell, or cell without address access!" );
573
0
                }
574
0
            }
575
0
        }
576
0
        catch( const Exception& )
577
0
        {
578
0
            TOOLS_WARN_EXCEPTION( "sc", "OCellValueBinding::initialize: caught an exception while retrieving the cell object!" );
579
0
        }
580
581
0
        if ( !m_xCell.is() )
582
0
            throw RuntimeException(u"Failed to retrieve cell object"_ustr, getXWeak());
583
584
0
        m_xCellText.set(m_xCell, css::uno::UNO_QUERY);
585
586
0
        Reference<XModifyBroadcaster> xBroadcaster( m_xCell, UNO_QUERY );
587
0
        if ( xBroadcaster.is() )
588
0
        {
589
0
            xBroadcaster->addModifyListener( this );
590
0
        }
591
592
        // TODO: add as XEventListener to the cell, so we get notified when it dies,
593
        // and can dispose ourself then
594
595
        // TODO: somehow add as listener so we get notified when the address of the cell changes
596
        // We need to forward this as change in our BoundCell property to our property change listeners
597
598
        // TODO: be an XModifyBroadcaster, so that changes in our cell can be notified
599
        // to the BindableValue which is/will be bound to this instance.
600
601
0
        m_bInitialized = true;
602
        // TODO: place your code here
603
0
    }
604
605
}   // namespace calc
606
607
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */