/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
Sequence< Type > aTypes( nCount ); if ( m_xCell.is() )
{ auto pTypes = aTypes.getArray();
// an XCell can be used to set/get "double" values
pTypes[0] = ::cppu::UnoType<double>::get(); if ( m_xCellText.is() )
{ // an XTextRange can be used to set/get "string" values
pTypes[1] = ::cppu::UnoType<OUString>::get(); // and additionally, we use it to handle booleans
pTypes[2] = ::cppu::UnoType<sal_Bool>::get();
}
// add sal_Int32 only if constructed as ListPositionCellBinding if ( m_bListPos )
pTypes[nCount-1] = cppu::UnoType<sal_Int32>::get();
}
Any aReturn; switch ( aType.getTypeClass() )
{ case TypeClass_STRING:
OSL_ENSURE( m_xCellText.is(), "OCellValueBinding::getValue: don't have a text!" ); if ( m_xCellText.is() )
aReturn <<= m_xCellText->getString(); else
aReturn <<= OUString(); break;
case TypeClass_BOOLEAN:
OSL_ENSURE( m_xCell.is(), "OCellValueBinding::getValue: don't have a double value supplier!" ); if ( m_xCell.is() )
{ // check if the cell has a numeric value (this might go into a helper function):
bool bHasValue = false;
CellContentType eCellType = m_xCell->getType(); if ( eCellType == CellContentType_VALUE )
bHasValue = true; elseif ( eCellType == CellContentType_FORMULA )
{ // check if the formula result is a value if ( m_xCell->getError() == 0 )
{
Reference<XPropertySet> xProp( m_xCell, UNO_QUERY ); if ( xProp.is() )
{
sal_Int32 nResultType; if ( (xProp->getPropertyValue(u"FormulaResultType2"_ustr) >>= nResultType)
&& nResultType == FormulaResult::VALUE )
bHasValue = true;
}
}
}
if ( bHasValue )
{ // 0 is "unchecked", any other value is "checked", regardless of number format double nCellValue = m_xCell->getValue(); bool bBoolValue = ( nCellValue != 0.0 );
aReturn <<= bBoolValue;
} // empty cells, text cells and text or error formula results: leave return value empty
} break;
case TypeClass_DOUBLE:
OSL_ENSURE( m_xCell.is(), "OCellValueBinding::getValue: don't have a double value supplier!" ); if ( m_xCell.is() )
aReturn <<= m_xCell->getValue(); else
aReturn <<= double(0); break;
case TypeClass_LONG:
OSL_ENSURE( m_xCell.is(), "OCellValueBinding::getValue: don't have a double value supplier!" ); if ( m_xCell.is() )
{ // The list position value in the cell is 1-based. // We subtract 1 from any cell value (no special handling for 0 or negative values).
default:
OSL_FAIL( "OCellValueBinding::getValue: unreachable code!" ); // a type other than double and string should never have survived the checkValueType // above
} return aReturn;
}
if ( m_xCell.is() )
{ // might call back into us via modified(EventObject&)
aGuard.unlock();
m_xCell->setValue( nCellValue );
aGuard.lock();
}
setBooleanFormat();
} break;
case TypeClass_DOUBLE:
{
OSL_ENSURE( m_xCell.is(), "OCellValueBinding::setValue: don't have a double value supplier!" );
double nValue = 0;
aValue >>= nValue; if ( m_xCell.is() )
{ // might call back into us via modified(EventObject&)
aGuard.unlock();
m_xCell->setValue( nValue );
aGuard.lock();
}
} break;
case TypeClass_LONG:
{
OSL_ENSURE( m_xCell.is(), "OCellValueBinding::setValue: don't have a double value supplier!" );
sal_Int32 nValue = 0;
aValue >>= nValue; // list index from control layer (0-based)
++nValue; // the list position value in the cell is 1-based if ( m_xCell.is() )
{ // might call back into us via modified(EventObject&)
aGuard.unlock();
m_xCell->setValue( nValue );
aGuard.lock();
}
} break;
case TypeClass_VOID:
{ // #N/A error value can only be set using XCellRangeData
Reference<XCellRangeData> xData( m_xCell, UNO_QUERY );
OSL_ENSURE( xData.is(), "OCellValueBinding::setValue: don't have XCellRangeData!" ); if ( xData.is() )
{
Sequence<Any> aInner(1); // one empty element
Sequence< Sequence<Any> > aOuter( &aInner, 1 ); // one row // might call back into us via modified(EventObject&)
aGuard.unlock();
xData->setDataArray( aOuter );
aGuard.lock();
}
} break;
default:
OSL_FAIL( "OCellValueBinding::setValue: unreachable code!" ); // a type other than double and string should never have survived the checkValueType // above
}
}
void OCellValueBinding::setBooleanFormat()
{ // set boolean number format if not already set
void OCellValueBinding::checkInitialized()
{ if ( !m_bInitialized ) throw NotInitializedException(u"CellValueBinding is not initialized"_ustr, getXWeak());
}
void OCellValueBinding::checkValueType( std::unique_lock<std::mutex>& rGuard, const Type& _rType ) const
{ if ( !supportsType( rGuard, _rType ) )
{
OUString sMessage = "The given type (" +
_rType.getTypeName() + ") is not supported by this binding."; // TODO: localize this error message
throw IncompatibleTypesException( sMessage, const_cast<OCellValueBinding&>(*this) ); // TODO: alternatively use a type converter service for this?
}
}
void SAL_CALL OCellValueBinding::initialize( const Sequence< Any >& _rArguments )
{ if ( m_bInitialized ) throw RuntimeException(u"CellValueBinding is already initialized"_ustr, getXWeak());
// get the cell address
CellAddress aAddress; bool bFoundAddress = false;
for ( const Any& rArg : _rArguments )
{
NamedValue aValue; if ( rArg >>= aValue )
{ if ( aValue.Name == "BoundCell" )
{ if ( aValue.Value >>= aAddress )
{
bFoundAddress = true; break;
}
}
}
}
if ( !bFoundAddress ) throw RuntimeException(u"Cell not found"_ustr, getXWeak());
// get the cell object try
{ // first the sheets collection
Reference< XIndexAccess > xSheets; if ( m_xDocument.is() )
xSheets.set(m_xDocument->getSheets( ), css::uno::UNO_QUERY);
OSL_ENSURE( xSheets.is(), "OCellValueBinding::initialize: could not retrieve the sheets!" );
if ( xSheets.is() )
{ // the concrete sheet
Reference< XCellRange > xSheet(xSheets->getByIndex( aAddress.Sheet ), UNO_QUERY);
OSL_ENSURE( xSheet.is(), "OCellValueBinding::initialize: NULL sheet, but no exception!" );
// the concrete cell if ( xSheet.is() )
{
m_xCell.set(xSheet->getCellByPosition( aAddress.Column, aAddress.Row ));
Reference< XCellAddressable > xAddressAccess( m_xCell, UNO_QUERY );
OSL_ENSURE( xAddressAccess.is(), "OCellValueBinding::initialize: either NULL cell, or cell without address access!" );
}
}
} catch( const Exception& )
{
TOOLS_WARN_EXCEPTION( "sc", "OCellValueBinding::initialize: caught an exception while retrieving the cell object!" );
}
if ( !m_xCell.is() ) throw RuntimeException(u"Failed to retrieve cell object"_ustr, getXWeak());
m_xCellText.set(m_xCell, css::uno::UNO_QUERY);
Reference<XModifyBroadcaster> xBroadcaster( m_xCell, UNO_QUERY ); if ( xBroadcaster.is() )
{
xBroadcaster->addModifyListener( this );
}
// TODO: add as XEventListener to the cell, so we get notified when it dies, // and can dispose ourself then
// TODO: somehow add as listener so we get notified when the address of the cell changes // We need to forward this as change in our BoundCell property to our property change listeners
// TODO: be an XModifyBroadcaster, so that changes in our cell can be notified // to the BindableValue which is/will be bound to this instance.
m_bInitialized = true; // TODO: place your code here
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.