Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  vbaborders.cxx   Sprache: C

 
/* -*- 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 .
 */

#include "vbaborders.hxx"

#include <sal/macros.h>
#include <cppuhelper/implbase.hxx>
#include <ooo/vba/excel/XlBordersIndex.hpp>
#include <ooo/vba/excel/XlBorderWeight.hpp>
#include <ooo/vba/excel/XlLineStyle.hpp>
#include <ooo/vba/excel/XlColorIndex.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/table/TableBorder.hpp>
#include <com/sun/star/table/XCellRange.hpp>
#include <com/sun/star/table/XColumnRowRange.hpp>
#include <utility>

#include "vbapalette.hxx"

using namespace ::com::sun::star;
using namespace ::ooo::vba;
using namespace ::ooo::vba::excel;

typedef ::cppu::WeakImplHelper<container::XIndexAccess > RangeBorders_Base;
typedef InheritedHelperInterfaceWeakImpl<excel::XBorder > ScVbaBorder_Base;

// #TODO sort these indexes to match the order in which Excel iterates over the
// borders, the enumeration will match the order in this list
const sal_Int16 supportedIndexTable[] = {  XlBordersIndex::xlEdgeLeft, XlBordersIndex::xlEdgeTop, XlBordersIndex::xlEdgeBottom, XlBordersIndex::xlEdgeRight, XlBordersIndex::xlDiagonalDown, XlBordersIndex::xlDiagonalUp, XlBordersIndex::xlInsideVertical, XlBordersIndex::xlInsideHorizontal };

constexpr OUString sTableBorder = u"TableBorder"_ustr;

//  Equiv widths in 1/100 mm
const sal_Int32 OOLineThin = 26;
const sal_Int32 OOLineMedium = 88;
const sal_Int32 OOLineThick = 141;
const sal_Int32 OOLineHairline = 2;

namespace {

class ScVbaBorder : public ScVbaBorder_Base
{
private:
    uno::Reference< beans::XPropertySet > m_xProps;
    sal_Int32 m_LineType;
    ScVbaPalette m_Palette;
    void setBorderLine( const table::BorderLine& rBorderLine )
    {
        table::TableBorder aTableBorder;
        m_xProps->getPropertyValue( sTableBorder ) >>= aTableBorder;

        switch ( m_LineType )
        {
            case XlBordersIndex::xlEdgeLeft:
                aTableBorder.IsLeftLineValid = true;
                aTableBorder.LeftLine= rBorderLine;
                break;
            case XlBordersIndex::xlEdgeTop:
                aTableBorder.IsTopLineValid = true;
                aTableBorder.TopLine = rBorderLine;
                break;

            case XlBordersIndex::xlEdgeBottom:
                aTableBorder.IsBottomLineValid = true;
                aTableBorder.BottomLine = rBorderLine;
                break;
            case XlBordersIndex::xlEdgeRight:
                aTableBorder.IsRightLineValid = true;
                aTableBorder.RightLine = rBorderLine;
                break;
            case XlBordersIndex::xlInsideVertical:
                aTableBorder.IsVerticalLineValid = true;
                aTableBorder.VerticalLine = rBorderLine;
                break;
            case XlBordersIndex::xlInsideHorizontal:
                aTableBorder.IsHorizontalLineValid = true;
                aTableBorder.HorizontalLine = rBorderLine;
                break;
            case XlBordersIndex::xlDiagonalDown:
            case XlBordersIndex::xlDiagonalUp:
                // #TODO have to ignore at the moment, would be
                // nice to investigate what we can do here
                break;
            default:
                    return;
        }
        m_xProps->setPropertyValue( sTableBorder, uno::Any(aTableBorder) );
    }

    bool getBorderLine( table::BorderLine& rBorderLine )
    {
        table::TableBorder aTableBorder;
        m_xProps->getPropertyValue( sTableBorder ) >>= aTableBorder;
        switch ( m_LineType )
        {
            case XlBordersIndex::xlEdgeLeft:
                if ( aTableBorder.IsLeftLineValid )
                    rBorderLine = aTableBorder.LeftLine;
                break;
            case XlBordersIndex::xlEdgeTop:
                if ( aTableBorder.IsTopLineValid )
                    rBorderLine = aTableBorder.TopLine;
                break;

            case XlBordersIndex::xlEdgeBottom:
                if ( aTableBorder.IsBottomLineValid )
                    rBorderLine = aTableBorder.BottomLine;
                break;
            case XlBordersIndex::xlEdgeRight:
                if ( aTableBorder.IsRightLineValid )
                    rBorderLine = aTableBorder.RightLine;
                break;
            case XlBordersIndex::xlInsideVertical:
                if ( aTableBorder.IsVerticalLineValid )
                    rBorderLine = aTableBorder.VerticalLine;
                break;
            case XlBordersIndex::xlInsideHorizontal:
                if ( aTableBorder.IsHorizontalLineValid )
                    rBorderLine = aTableBorder.HorizontalLine;
                break;

            case XlBordersIndex::xlDiagonalDown:
            case XlBordersIndex::xlDiagonalUp:
                // #TODO have to ignore at the moment, would be
                // nice to investigate what we can do here
                break;
            default:
                    return false;
        }
        return true;
    }

protected:
    virtual OUString getServiceImplName() override
    {
        return u"ScVbaBorder"_ustr;
    }
    virtual css::uno::Sequence<OUString> getServiceNames() override
    {
        static uno::Sequence< OUString > const aServiceNames
        {
            u"ooo.vba.excel.Border"_ustr
        };
        return aServiceNames;
    }
public:
    ScVbaBorder( const uno::Reference< beans::XPropertySet > & xProps, const uno::Reference< uno::XComponentContext >& xContext, sal_Int32 lineType, const ScVbaPalette& rPalette) : ScVbaBorder_Base( uno::Reference< XHelperInterface >( xProps, uno::UNO_QUERY ), xContext ), m_xProps( xProps ), m_LineType( lineType ), m_Palette( rPalette ) {}

    // XBorder
    uno::Any SAL_CALL getColor() override
    {
        table::BorderLine aBorderLine;
        if ( getBorderLine( aBorderLine ) )
            return uno::Any( OORGBToXLRGB( Color(ColorTransparency, aBorderLine.Color) ) );
        throw uno::RuntimeException(u"No Implementation available"_ustr );
    }
    void SAL_CALL setColor( const uno::Any& _color ) override
    {
        sal_Int32 nColor = 0;
        _color >>= nColor;
        table::BorderLine aBorderLine;
        if ( !getBorderLine( aBorderLine ) )
            throw uno::RuntimeException(u"No Implementation available"_ustr );

        aBorderLine.Color = XLRGBToOORGB( nColor );
        setBorderLine( aBorderLine );

    }

    uno::Any SAL_CALL getColorIndex() override
    {
        sal_Int32 nColor = 0;
        XLRGBToOORGB( getColor() ) >>= nColor;
        uno::Reference< container::XIndexAccess > xIndex = m_Palette.getPalette();
        sal_Int32 nElems = xIndex->getCount();
        sal_Int32 nIndex = -1;
        for ( sal_Int32 count=0; count<nElems; ++count )
        {
            sal_Int32 nPaletteColor = 0;
            xIndex->getByIndex( count ) >>= nPaletteColor;
            if ( nPaletteColor == nColor )
            {
                nIndex = count + 1;
                break;
            }
        }
        return uno::Any(nIndex);
    }

    void SAL_CALL setColorIndex( const uno::Any& _colorindex ) override
    {
        sal_Int32 nColor = 0;
        _colorindex >>= nColor;
        if ( !nColor || nColor == XlColorIndex::xlColorIndexAutomatic )
            nColor = 1;
        setColor( OORGBToXLRGB( m_Palette.getPalette()->getByIndex( --nColor )  ) );
    }
    uno::Any SAL_CALL getWeight() override
    {
        table::BorderLine aBorderLine;
        if ( getBorderLine( aBorderLine ) )
        {
            switch ( aBorderLine.OuterLineWidth )
            {
                case 0: // Thin = default OO thickness
                case OOLineThin:
                    return uno::Any( XlBorderWeight::xlThin );
                case OOLineMedium:
                    return uno::Any( XlBorderWeight::xlMedium );
                case OOLineThick:
                    return uno::Any( XlBorderWeight::xlThick );
                case OOLineHairline:
                    return uno::Any( XlBorderWeight::xlHairline );
                default:
                    break;
            }
        }
        throw uno::RuntimeException(u"Method failed"_ustr );
    }
    void SAL_CALL setWeight( const uno::Any& _weight ) override
    {
        sal_Int32 nWeight = 0;
        _weight >>= nWeight;
        table::BorderLine aBorderLine;
        if ( !getBorderLine( aBorderLine ) )
                    throw uno::RuntimeException(u"Method failed"_ustr );

        switch ( nWeight )
        {
            case XlBorderWeight::xlThin:
                aBorderLine.OuterLineWidth = OOLineThin;
                break;
            case XlBorderWeight::xlMedium:
                aBorderLine.OuterLineWidth = OOLineMedium;
                break;
            case XlBorderWeight::xlThick:
                aBorderLine.OuterLineWidth = OOLineThick;
                break;
            case XlBorderWeight::xlHairline:
                aBorderLine.OuterLineWidth = OOLineHairline;
                break;
            default:
                throw uno::RuntimeException(u"Bad param"_ustr );
        }
        setBorderLine( aBorderLine );

    }

    void SAL_CALL setTintAndShade( const uno::Any& /*rAny*/ ) override
    {
        // TODO implement
    }
    uno::Any SAL_CALL getTintAndShade() override
    {
        // TODO implement
        return uno::Any(static_cast<double>(0));
    }

    uno::Any SAL_CALL getLineStyle() override
    {
        // always return xlContinuous;
        return uno::Any( XlLineStyle::xlContinuous );
    }
    void SAL_CALL setLineStyle( const uno::Any& _linestyle ) override
    {
        // Urk no choice but to silently ignore we don't support this attribute
        // #TODO would be nice to support the excel line styles
        sal_Int32 nLineStyle = 0;
        _linestyle >>= nLineStyle;
        table::BorderLine aBorderLine;
        if ( !getBorderLine( aBorderLine ) )
            throw uno::RuntimeException(u"Method failed"_ustr );

        switch ( nLineStyle )
        {
            case XlLineStyle::xlContinuous:
            case XlLineStyle::xlDash:
            case XlLineStyle::xlDashDot:
            case XlLineStyle::xlDashDotDot:
            case XlLineStyle::xlDot:
            case XlLineStyle::xlDouble:
            case XlLineStyle::xlLineStyleNone:
            case XlLineStyle::xlSlantDashDot:
                break;
            default:
                throw uno::RuntimeException(u"Bad param"_ustr );
        }
        setBorderLine( aBorderLine );

    }
};

class RangeBorders : public RangeBorders_Base
{
private:
    uno::Reference< table::XCellRange > m_xRange;
    uno::Reference< uno::XComponentContext > m_xContext;
    ScVbaPalette m_Palette;
    sal_Int32 getTableIndex( sal_Int32 nConst )
    {
        // okay return position of the index in the table
        sal_Int32 nIndexes = getCount();
        sal_Int32 realIndex = 0;
        const sal_Int16* pTableEntry = supportedIndexTable;
        for ( ; realIndex < nIndexes; ++realIndex, ++pTableEntry )
        {
            if ( *pTableEntry == nConst )
                return realIndex;
        }
        return getCount(); // error condition
    }
public:
    RangeBorders(  uno::Reference< table::XCellRange > xRange,  uno::Reference< uno::XComponentContext > xContext, const ScVbaPalette& rPalette ) : m_xRange(std::move( xRange )), m_xContext(std::move( xContext )), m_Palette( rPalette )
    {
    }
    // XIndexAccess
    virtual ::sal_Int32 SAL_CALL getCount(  ) override
    {
        return SAL_N_ELEMENTS( supportedIndexTable );
    }
    virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) override
    {

        sal_Int32 nIndex = getTableIndex( Index );
        if ( nIndex >= 0 && nIndex < getCount() )
        {
            uno::Reference< beans::XPropertySet > xProps( m_xRange, uno::UNO_QUERY_THROW );
            return uno::Any( uno::Reference< excel::XBorder >( new ScVbaBorder( xProps, m_xContext, supportedIndexTable[ nIndex ], m_Palette )) );
        }
        throw lang::IndexOutOfBoundsException();
    }
    virtual uno::Type SAL_CALL getElementType(  ) override
    {
        return  cppu::UnoType<excel::XBorder>::get();
    }
    virtual sal_Bool SAL_CALL hasElements(  ) override
    {
        return true;
    }
};

}

static uno::Reference< container::XIndexAccess >
rangeToBorderIndexAccess( const uno::Reference< table::XCellRange >& xRange,  const uno::Reference< uno::XComponentContext > & xContext, const ScVbaPalette& rPalette )
{
    return new RangeBorders( xRange, xContext, rPalette );
}

namespace {

class RangeBorderEnumWrapper : public EnumerationHelper_BASE
{
    uno::Reference<container::XIndexAccess > m_xIndexAccess;
    sal_Int32 m_nIndex;
public:
    explicit RangeBorderEnumWrapper( uno::Reference< container::XIndexAccess > xIndexAccess ) : m_xIndexAccess(std::move( xIndexAccess )), m_nIndex( 0 ) {}
    virtual sal_Bool SAL_CALL hasMoreElements(  ) override
    {
        return ( m_nIndex < m_xIndexAccess->getCount() );
    }

    virtual uno::Any SAL_CALL nextElement(  ) override
    {
        if ( m_nIndex < m_xIndexAccess->getCount() )
            return m_xIndexAccess->getByIndex( m_nIndex++ );
        throw container::NoSuchElementException();
    }
};

}

ScVbaBorders::ScVbaBorders( const uno::Reference< XHelperInterface >& xParent,
                            const uno::Reference< uno::XComponentContext > & xContext,
                            const uno::Reference< table::XCellRange >& xRange,
                            const ScVbaPalette& rPalette  )
    :  ScVbaBorders_BASE( xParent, xContext, rangeToBorderIndexAccess( xRange ,xContext, rPalette ) ), bRangeIsSingleCell( false )
{
    uno::Reference< table::XColumnRowRange > xColumnRowRange(xRange, uno::UNO_QUERY_THROW );
    if ( xColumnRowRange->getRows()->getCount() == 1 && xColumnRowRange->getColumns()->getCount() == 1 )
        bRangeIsSingleCell = true;
    m_xProps.set( xRange, uno::UNO_QUERY_THROW );
}

uno::Reference< container::XEnumeration >
ScVbaBorders::createEnumeration()
{
    return new RangeBorderEnumWrapper( m_xIndexAccess );
}

uno::Any
ScVbaBorders::createCollectionObject( const css::uno::Any& aSource )
{
    return aSource; // it's already a Border object
}

uno::Type
ScVbaBorders::getElementType()
{
    return cppu::UnoType<excel::XBorders>::get();
}

uno::Any
ScVbaBorders::getItemByIntIndex( const sal_Int32 nIndex )
{
    return createCollectionObject( m_xIndexAccess->getByIndex( nIndex ) );
}

uno::Any SAL_CALL ScVbaBorders::getColor()
{
    sal_Int32 count = getCount();
    uno::Any color;
    for( sal_Int32 i = 0; i < count ; i++ )
    {
        if( XlBordersIndex::xlDiagonalDown != supportedIndexTable[i] && XlBordersIndex::xlDiagonalUp != supportedIndexTable[i] )
        {
            uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
            if( color.hasValue() )
            {
                if( color != xBorder->getColor() )
                    return uno::Any( uno::Reference< uno::XInterface >() );
            }
            else
                color = xBorder->getColor();
        }
    }
    return  color;
}
void SAL_CALL ScVbaBorders::setColor( const uno::Any& _color )
{
    sal_Int32 count = getCount();
    for( sal_Int32 i = 0; i < count ; i++ )
    {
        uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
        xBorder->setColor( _color );
    }
}
uno::Any SAL_CALL ScVbaBorders::getColorIndex()
{
    sal_Int32 count = getCount();
    uno::Any nColorIndex;
    for( sal_Int32 i = 0; i < count ; i++ )
    {
        if( XlBordersIndex::xlDiagonalDown != supportedIndexTable[i] && XlBordersIndex::xlDiagonalUp != supportedIndexTable[i] )
        {
            uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
            if( nColorIndex.hasValue() )
            {
                if( nColorIndex != xBorder->getColorIndex() )
                    return uno::Any( uno::Reference< uno::XInterface >() );
            }
            else
                nColorIndex = xBorder->getColorIndex();
        }
    }
    return  nColorIndex;
}
void SAL_CALL ScVbaBorders::setColorIndex( const uno::Any& _colorindex )
{
    sal_Int32 count = getCount();
    for( sal_Int32 i = 0; i < count ; i++ )
    {
        uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
        xBorder->setColorIndex( _colorindex );
    }
}

static bool
lcl_areAllLineWidthsSame( const table::TableBorder& maTableBorder, bool bIsCell )
{

    bool bRes = false;
    if (bIsCell)
    {
        bRes = ((maTableBorder.TopLine.OuterLineWidth == maTableBorder.BottomLine.OuterLineWidth) &&
(maTableBorder.TopLine.OuterLineWidth == maTableBorder.LeftLine.OuterLineWidth) &&
(maTableBorder.TopLine.OuterLineWidth == maTableBorder.RightLine.OuterLineWidth));
    }
    else
    {
        bRes = ((maTableBorder.TopLine.OuterLineWidth == maTableBorder.BottomLine.OuterLineWidth) &&
(maTableBorder.TopLine.OuterLineWidth == maTableBorder.LeftLine.OuterLineWidth) &&
(maTableBorder.TopLine.OuterLineWidth == maTableBorder.HorizontalLine.OuterLineWidth) &&
(maTableBorder.TopLine.OuterLineWidth == maTableBorder.VerticalLine.OuterLineWidth) &&
(maTableBorder.TopLine.OuterLineWidth == maTableBorder.RightLine.OuterLineWidth));
    }
    return bRes;
}

uno::Any SAL_CALL ScVbaBorders::getLineStyle()
{
    table::TableBorder aTableBorder;
    m_xProps->getPropertyValue( sTableBorder ) >>= aTableBorder;

    sal_Int32 aLinestyle =  XlLineStyle::xlLineStyleNone;

    if ( lcl_areAllLineWidthsSame( aTableBorder, bRangeIsSingleCell ))
    {
        if (aTableBorder.TopLine.LineDistance != 0)
        {
            aLinestyle = XlLineStyle::xlDouble;
        }
        else if ( aTableBorder.TopLine.OuterLineWidth != 0 )
        {
            aLinestyle = XlLineStyle::xlContinuous;
        }
    }
    return uno::Any( aLinestyle );
}
void SAL_CALL ScVbaBorders::setLineStyle( const uno::Any& _linestyle )
{
    sal_Int32 count = getCount();
    for( sal_Int32 i = 0; i < count ; i++ )
    {
        uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
        xBorder->setLineStyle( _linestyle );
    }
}
uno::Any SAL_CALL ScVbaBorders::getWeight()
{
    sal_Int32 count = getCount();
    uno::Any weight;
    for( sal_Int32 i = 0; i < count ; i++ )
    {
        if( XlBordersIndex::xlDiagonalDown != supportedIndexTable[i] && XlBordersIndex::xlDiagonalUp != supportedIndexTable[i] )
        {
            uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
            if( weight.hasValue() )
            {
                if( weight != xBorder->getWeight() )
                    return uno::Any( uno::Reference< uno::XInterface >() );
            }
            else
                weight = xBorder->getWeight();
        }
    }
    return  weight;
}

uno::Any SAL_CALL ScVbaBorders::getTintAndShade()
{
    // TODO implement
    return uno::Any(static_cast<double>(0));
}

void SAL_CALL ScVbaBorders::setTintAndShade(const uno::Any& /*rAny*/)
{
    // TODO implement
}

void SAL_CALL ScVbaBorders::setWeight( const uno::Any& _weight )
{
    sal_Int32 count = getCount();
    for( sal_Int32 i = 0; i < count ; i++ )
    {
        uno::Reference< XBorder > xBorder( getItemByIntIndex( supportedIndexTable[i] ), uno::UNO_QUERY_THROW );
        xBorder->setWeight( _weight );
    }
}

OUString
ScVbaBorders::getServiceImplName()
{
    return u"ScVbaBorders"_ustr;
}

uno::Sequence< OUString >
ScVbaBorders::getServiceNames()
{
    static uno::Sequence< OUString > const aServiceNames
    {
        u"ooo.vba.excel.Borders"_ustr
    };
    return aServiceNames;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=96 H=97 G=96

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge