defaultgridcolumnmodel.cxx 16.1 KB
Newer Older
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * 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 .
 */
19

20

21
#include "defaultgridcolumnmodel.hxx"
22
#include "gridcolumn.hxx"
23

24
#include <com/sun/star/awt/XVclWindowPeer.hpp>
25

26
#include <comphelper/sequence.hxx>
27
#include <comphelper/componentguard.hxx>
28
#include <comphelper/processfactory.hxx>
29
#include <toolkit/helper/servicenames.hxx>
30
#include <rtl/ustrbuf.hxx>
31
#include <tools/diagnose_ex.h>
32

33
//......................................................................................................................
34
namespace toolkit
35
//......................................................................................................................
36
{
37
    using ::com::sun::star::uno::Reference;
38
    using ::com::sun::star::uno::XComponentContext;
39 40 41 42 43 44 45 46 47 48 49 50
    using ::com::sun::star::lang::XMultiServiceFactory;
    using ::com::sun::star::uno::RuntimeException;
    using ::com::sun::star::uno::Sequence;
    using ::com::sun::star::uno::UNO_QUERY_THROW;
    using ::com::sun::star::uno::UNO_QUERY;
    using ::com::sun::star::awt::grid::XGridColumn;
    using ::com::sun::star::uno::XInterface;
    using ::com::sun::star::lang::XComponent;
    using ::com::sun::star::lang::EventObject;
    using ::com::sun::star::container::XContainerListener;
    using ::com::sun::star::container::ContainerEvent;
    using ::com::sun::star::uno::Exception;
51
    using ::com::sun::star::lang::IndexOutOfBoundsException;
52
    using ::com::sun::star::util::XCloneable;
53
    using ::com::sun::star::lang::IllegalArgumentException;
54 55 56 57 58

    //==================================================================================================================
    //= DefaultGridColumnModel
    //==================================================================================================================
    //------------------------------------------------------------------------------------------------------------------
59
    DefaultGridColumnModel::DefaultGridColumnModel( const Reference< XComponentContext >& i_context )
60
        :DefaultGridColumnModel_Base( m_aMutex )
61
        ,m_aContext( i_context )
62 63 64 65
        ,m_aContainerListeners( m_aMutex )
        ,m_aColumns()
    {
    }
66

67 68
    //------------------------------------------------------------------------------------------------------------------
    DefaultGridColumnModel::DefaultGridColumnModel( DefaultGridColumnModel const & i_copySource )
69 70
        :cppu::BaseMutex()
        ,DefaultGridColumnModel_Base( m_aMutex )
71 72 73 74 75 76 77 78 79 80 81 82 83
        ,m_aContext( i_copySource.m_aContext )
        ,m_aContainerListeners( m_aMutex )
        ,m_aColumns()
    {
        Columns aColumns;
        aColumns.reserve( i_copySource.m_aColumns.size() );
        try
        {
            for (   Columns::const_iterator col = i_copySource.m_aColumns.begin();
                    col != i_copySource.m_aColumns.end();
                    ++col
                )
            {
84 85 86 87 88
                Reference< XCloneable > const xCloneable( *col, UNO_QUERY_THROW );
                Reference< XGridColumn > const xClone( xCloneable->createClone(), UNO_QUERY_THROW );

                GridColumn* const pGridColumn = GridColumn::getImplementation( xClone );
                if ( pGridColumn == NULL )
89
                    throw RuntimeException( "invalid clone source implementation", *this );
90 91 92 93 94 95
                    // that's indeed a RuntimeException, not an IllegalArgumentException or some such:
                    // a DefaultGridColumnModel implementation whose columns are not GridColumn implementations
                    // is borked.
                pGridColumn->setIndex( col - i_copySource.m_aColumns.begin() );

                aColumns.push_back( xClone );
96 97 98 99 100 101 102 103 104
            }
        }
        catch( const Exception& )
        {
            DBG_UNHANDLED_EXCEPTION();
        }
        if ( aColumns.size() == i_copySource.m_aColumns.size() )
            m_aColumns.swap( aColumns );
    }
105

106 107 108 109
    //------------------------------------------------------------------------------------------------------------------
    DefaultGridColumnModel::~DefaultGridColumnModel()
    {
    }
110

111 112 113 114 115
    //------------------------------------------------------------------------------------------------------------------
    ::sal_Int32 SAL_CALL DefaultGridColumnModel::getColumnCount() throw (RuntimeException)
    {
        return m_aColumns.size();
    }
116

117 118 119
    //------------------------------------------------------------------------------------------------------------------
    Reference< XGridColumn > SAL_CALL DefaultGridColumnModel::createColumn(  ) throw (RuntimeException)
    {
120
        ::comphelper::ComponentGuard aGuard( *this, rBHelper );
121 122
        return new GridColumn();
    }
123

124
    //------------------------------------------------------------------------------------------------------------------
125
    ::sal_Int32 SAL_CALL DefaultGridColumnModel::addColumn( const Reference< XGridColumn > & i_column ) throw (RuntimeException, IllegalArgumentException)
126
    {
127
        ::comphelper::ComponentGuard aGuard( *this, rBHelper );
128

129 130
        GridColumn* const pGridColumn = GridColumn::getImplementation( i_column );
        if ( pGridColumn == NULL )
131
            throw IllegalArgumentException( "invalid column implementation", *this, 1 );
132

133 134
        m_aColumns.push_back( i_column );
        sal_Int32 index = m_aColumns.size() - 1;
135
        pGridColumn->setIndex( index );
136

137 138 139 140 141
        // fire insertion notifications
        ContainerEvent aEvent;
        aEvent.Source = *this;
        aEvent.Accessor <<= index;
        aEvent.Element <<= i_column;
142

143 144
        aGuard.clear();
        m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent );
145

146 147
        return index;
    }
148

149
    //------------------------------------------------------------------------------------------------------------------
150
    void SAL_CALL DefaultGridColumnModel::removeColumn( ::sal_Int32 i_columnIndex )  throw (RuntimeException, IndexOutOfBoundsException)
151
    {
152
        ::comphelper::ComponentGuard aGuard( *this, rBHelper );
153 154

        if ( ( i_columnIndex < 0 ) || ( size_t( i_columnIndex ) >= m_aColumns.size() ) )
155
            throw IndexOutOfBoundsException( OUString(), *this );
156

157
        Columns::iterator const pos = m_aColumns.begin() + i_columnIndex;
158 159 160
        Reference< XGridColumn > const xColumn( *pos );
        m_aColumns.erase( pos );

161 162 163 164 165 166 167 168
        // update indexes of all subsequent columns
        sal_Int32 columnIndex( i_columnIndex );
        for (   Columns::iterator updatePos = m_aColumns.begin() + columnIndex;
                updatePos != m_aColumns.end();
                ++updatePos, ++columnIndex
            )
        {
            GridColumn* pColumnImpl = GridColumn::getImplementation( *updatePos );
169 170 171 172 173 174
            if ( !pColumnImpl )
            {
                SAL_WARN( "toolkit.controls", "DefaultGridColumnModel::removeColumn: invalid column implementation!" );
                continue;
            }

175 176 177
            pColumnImpl->setIndex( columnIndex );
        }

178 179 180 181 182 183 184 185
        // fire removal notifications
        ContainerEvent aEvent;
        aEvent.Source = *this;
        aEvent.Accessor <<= i_columnIndex;
        aEvent.Element <<= xColumn;

        aGuard.clear();
        m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent );
186 187 188 189 190 191 192 193 194 195 196

        // dispose the removed column
        try
        {
            Reference< XComponent > const xColComp( xColumn, UNO_QUERY_THROW );
            xColComp->dispose();
        }
        catch( const Exception& )
        {
            DBG_UNHANDLED_EXCEPTION();
        }
197
    }
198

199 200
    //------------------------------------------------------------------------------------------------------------------
    Sequence< Reference< XGridColumn > > SAL_CALL DefaultGridColumnModel::getColumns() throw (RuntimeException)
201
    {
202
        ::comphelper::ComponentGuard aGuard( *this, rBHelper );
203
        return ::comphelper::containerToSequence( m_aColumns );
204
    }
205

206
    //------------------------------------------------------------------------------------------------------------------
207
    Reference< XGridColumn > SAL_CALL DefaultGridColumnModel::getColumn(::sal_Int32 index) throw (IndexOutOfBoundsException, RuntimeException)
208
    {
209
        ::comphelper::ComponentGuard aGuard( *this, rBHelper );
210

211 212
        if ( index >=0 && index < ((sal_Int32)m_aColumns.size()))
            return m_aColumns[index];
213

214
        throw IndexOutOfBoundsException();
215
    }
216

217 218 219 220 221 222 223
    //------------------------------------------------------------------------------------------------------------------
    void SAL_CALL DefaultGridColumnModel::setDefaultColumns(sal_Int32 rowElements) throw (RuntimeException)
    {
        ::std::vector< ContainerEvent > aRemovedColumns;
        ::std::vector< ContainerEvent > aInsertedColumns;

        {
224
            ::comphelper::ComponentGuard aGuard( *this, rBHelper );
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242

            // remove existing columns
            while ( !m_aColumns.empty() )
            {
                const size_t lastColIndex = m_aColumns.size() - 1;

                ContainerEvent aEvent;
                aEvent.Source = *this;
                aEvent.Accessor <<= sal_Int32( lastColIndex );
                aEvent.Element <<= m_aColumns[ lastColIndex ];
                aRemovedColumns.push_back( aEvent );

                m_aColumns.erase( m_aColumns.begin() + lastColIndex );
            }

            // add new columns
            for ( sal_Int32 i=0; i<rowElements; ++i )
            {
243 244
                ::rtl::Reference< GridColumn > const pGridColumn = new GridColumn();
                Reference< XGridColumn > const xColumn( pGridColumn.get() );
245
                OUStringBuffer colTitle;
246
                colTitle.appendAscii( "Column " );
247
                colTitle.append( i + 1 );
248
                pGridColumn->setTitle( colTitle.makeStringAndClear() );
249 250 251
                pGridColumn->setColumnWidth( 80 /* APPFONT */ );
                pGridColumn->setFlexibility( 1 );
                pGridColumn->setResizeable( sal_True );
252
                pGridColumn->setDataColumnIndex( i );
253 254 255 256 257 258 259 260

                ContainerEvent aEvent;
                aEvent.Source = *this;
                aEvent.Accessor <<= i;
                aEvent.Element <<= xColumn;
                aInsertedColumns.push_back( aEvent );

                m_aColumns.push_back( xColumn );
261
                pGridColumn->setIndex( i );
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
            }
        }

        // fire removal notifications
        for (   ::std::vector< ContainerEvent >::const_iterator event = aRemovedColumns.begin();
                event != aRemovedColumns.end();
                ++event
            )
        {
            m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, *event );
        }

        // fire insertion notifications
        for (   ::std::vector< ContainerEvent >::const_iterator event = aInsertedColumns.begin();
                event != aInsertedColumns.end();
                ++event
            )
        {
            m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, *event );
        }

        // dispose removed columns
        for (   ::std::vector< ContainerEvent >::const_iterator event = aRemovedColumns.begin();
                event != aRemovedColumns.end();
                ++event
            )
        {
            try
            {
                const Reference< XComponent > xColComp( event->Element, UNO_QUERY_THROW );
                xColComp->dispose();
            }
            catch( const Exception& )
            {
                DBG_UNHANDLED_EXCEPTION();
            }
        }
    }
300

301
    //------------------------------------------------------------------------------------------------------------------
302
    OUString SAL_CALL DefaultGridColumnModel::getImplementationName(  ) throw (RuntimeException)
303
    {
304
        return OUString( "org.openoffice.comp.toolkit.DefaultGridColumnModel" );
305
    }
306

307
    //------------------------------------------------------------------------------------------------------------------
308
    sal_Bool SAL_CALL DefaultGridColumnModel::supportsService( const OUString& i_serviceName ) throw (RuntimeException)
309
    {
310
        const Sequence< OUString > aServiceNames( getSupportedServiceNames() );
311 312 313 314 315
        for ( sal_Int32 i=0; i<aServiceNames.getLength(); ++i )
            if ( aServiceNames[i] == i_serviceName )
                return sal_True;
        return sal_False;
    }
316

317
    //------------------------------------------------------------------------------------------------------------------
318
    Sequence< OUString > SAL_CALL DefaultGridColumnModel::getSupportedServiceNames(  ) throw (RuntimeException)
319
    {
320 321
        const OUString aServiceName( OUString::createFromAscii( szServiceName_DefaultGridColumnModel ) );
        const Sequence< OUString > aSeq( &aServiceName, 1 );
322 323
        return aSeq;
    }
324

325 326 327 328 329 330
    //------------------------------------------------------------------------------------------------------------------
    void SAL_CALL DefaultGridColumnModel::addContainerListener( const Reference< XContainerListener >& i_listener ) throw (RuntimeException)
    {
        if ( i_listener.is() )
            m_aContainerListeners.addInterface( i_listener );
    }
331

332 333 334 335 336 337
    //------------------------------------------------------------------------------------------------------------------
    void SAL_CALL DefaultGridColumnModel::removeContainerListener( const Reference< XContainerListener >& i_listener ) throw (RuntimeException)
    {
        if ( i_listener.is() )
            m_aContainerListeners.removeInterface( i_listener );
    }
338

339 340 341 342 343 344 345 346 347
    //------------------------------------------------------------------------------------------------------------------
    void SAL_CALL DefaultGridColumnModel::disposing()
    {
        DefaultGridColumnModel_Base::disposing();

        EventObject aEvent( *this );
        m_aContainerListeners.disposeAndClear( aEvent );

        ::osl::MutexGuard aGuard( m_aMutex );
348

349
        // remove, dispose and clear columns
350
        while ( !m_aColumns.empty() )
351
        {
352
            try
353
            {
354 355 356 357 358 359
                const Reference< XComponent > xColComponent( m_aColumns[ 0 ], UNO_QUERY_THROW );
                xColComponent->dispose();
            }
            catch( const Exception& )
            {
                DBG_UNHANDLED_EXCEPTION();
360 361
            }

362
            m_aColumns.erase( m_aColumns.begin() );
363
        }
364 365 366

        Columns aEmpty;
        m_aColumns.swap( aEmpty );
367
    }
368

369 370 371
    //------------------------------------------------------------------------------------------------------------------
    Reference< XCloneable > SAL_CALL DefaultGridColumnModel::createClone(  ) throw (RuntimeException)
    {
372
        ::comphelper::ComponentGuard aGuard( *this, rBHelper );
373 374
        return new DefaultGridColumnModel( *this );
    }
375

376 377 378
//......................................................................................................................
}   // namespace toolkit
//......................................................................................................................
379

380 381
//----------------------------------------------------------------------------------------------------------------------
::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL DefaultGridColumnModel_CreateInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rFactory)
382
{
383
    return ::com::sun::star::uno::Reference < ::com::sun::star::uno::XInterface >( ( ::cppu::OWeakObject* ) new ::toolkit::DefaultGridColumnModel( comphelper::getComponentContext(_rFactory) ) );
384
}
Christian Lohmaier's avatar
Christian Lohmaier committed
385
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */