1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "gridcolumn.hxx"
23 #include <com/sun/star/awt/XVclWindowPeer.hpp>
24 #include <com/sun/star/awt/grid/XGridColumnModel.hpp>
25 #include <com/sun/star/awt/grid/XGridColumn.hpp>
26 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
27 #include <com/sun/star/lang/XServiceInfo.hpp>
28 #include <com/sun/star/uno/XComponentContext.hpp>
30 #include <comphelper/sequence.hxx>
31 #include <comphelper/componentguard.hxx>
32 #include <comphelper/interfacecontainer2.hxx>
33 #include <cppuhelper/basemutex.hxx>
34 #include <cppuhelper/compbase.hxx>
35 #include <cppuhelper/supportsservice.hxx>
36 #include <rtl/ustrbuf.hxx>
37 #include <tools/diagnose_ex.h>
41 using namespace css::awt
;
42 using namespace css::awt::grid
;
43 using namespace css::container
;
44 using namespace css::lang
;
45 using namespace css::uno
;
46 using namespace toolkit
;
50 typedef ::cppu::WeakComponentImplHelper
< css::awt::grid::XGridColumnModel
51 , css::lang::XServiceInfo
52 > DefaultGridColumnModel_Base
;
54 class DefaultGridColumnModel
:public ::cppu::BaseMutex
55 ,public DefaultGridColumnModel_Base
58 DefaultGridColumnModel();
59 DefaultGridColumnModel( DefaultGridColumnModel
const & i_copySource
);
62 virtual ::sal_Int32 SAL_CALL
getColumnCount() override
;
63 virtual css::uno::Reference
< css::awt::grid::XGridColumn
> SAL_CALL
createColumn( ) override
;
64 virtual ::sal_Int32 SAL_CALL
addColumn(const css::uno::Reference
< css::awt::grid::XGridColumn
> & column
) override
;
65 virtual void SAL_CALL
removeColumn( ::sal_Int32 i_columnIndex
) override
;
66 virtual css::uno::Sequence
< css::uno::Reference
< css::awt::grid::XGridColumn
> > SAL_CALL
getColumns() override
;
67 virtual css::uno::Reference
< css::awt::grid::XGridColumn
> SAL_CALL
getColumn(::sal_Int32 index
) override
;
68 virtual void SAL_CALL
setDefaultColumns(sal_Int32 rowElements
) override
;
71 virtual OUString SAL_CALL
getImplementationName( ) override
;
72 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) override
;
73 virtual css::uno::Sequence
< OUString
> SAL_CALL
getSupportedServiceNames( ) override
;
76 virtual void SAL_CALL
addContainerListener( const css::uno::Reference
< css::container::XContainerListener
>& xListener
) override
;
77 virtual void SAL_CALL
removeContainerListener( const css::uno::Reference
< css::container::XContainerListener
>& xListener
) override
;
80 virtual css::uno::Reference
< css::util::XCloneable
> SAL_CALL
createClone( ) override
;
83 virtual void SAL_CALL
disposing() override
;
86 typedef ::std::vector
< css::uno::Reference
< css::awt::grid::XGridColumn
> > Columns
;
88 ::comphelper::OInterfaceContainerHelper2 m_aContainerListeners
;
92 DefaultGridColumnModel::DefaultGridColumnModel()
93 :DefaultGridColumnModel_Base( m_aMutex
)
94 ,m_aContainerListeners( m_aMutex
)
99 DefaultGridColumnModel::DefaultGridColumnModel( DefaultGridColumnModel
const & i_copySource
)
101 ,DefaultGridColumnModel_Base( m_aMutex
)
102 ,m_aContainerListeners( m_aMutex
)
106 aColumns
.reserve( i_copySource
.m_aColumns
.size() );
109 for ( Columns::const_iterator col
= i_copySource
.m_aColumns
.begin();
110 col
!= i_copySource
.m_aColumns
.end();
114 Reference
< css::util::XCloneable
> const xCloneable( *col
, UNO_QUERY_THROW
);
115 Reference
< XGridColumn
> const xClone( xCloneable
->createClone(), UNO_QUERY_THROW
);
117 GridColumn
* const pGridColumn
= GridColumn::getImplementation( xClone
);
118 if ( pGridColumn
== nullptr )
119 throw RuntimeException( "invalid clone source implementation", *this );
120 // that's indeed a RuntimeException, not an IllegalArgumentException or some such:
121 // a DefaultGridColumnModel implementation whose columns are not GridColumn implementations
123 pGridColumn
->setIndex( col
- i_copySource
.m_aColumns
.begin() );
125 aColumns
.push_back( xClone
);
128 catch( const Exception
& )
130 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
132 if ( aColumns
.size() == i_copySource
.m_aColumns
.size() )
133 m_aColumns
.swap( aColumns
);
136 ::sal_Int32 SAL_CALL
DefaultGridColumnModel::getColumnCount()
138 return m_aColumns
.size();
142 Reference
< XGridColumn
> SAL_CALL
DefaultGridColumnModel::createColumn( )
144 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
145 return new GridColumn();
149 ::sal_Int32 SAL_CALL
DefaultGridColumnModel::addColumn( const Reference
< XGridColumn
> & i_column
)
151 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
153 GridColumn
* const pGridColumn
= GridColumn::getImplementation( i_column
);
154 if ( pGridColumn
== nullptr )
155 throw css::lang::IllegalArgumentException( "invalid column implementation", *this, 1 );
157 m_aColumns
.push_back( i_column
);
158 sal_Int32 index
= m_aColumns
.size() - 1;
159 pGridColumn
->setIndex( index
);
161 // fire insertion notifications
162 ContainerEvent aEvent
;
163 aEvent
.Source
= *this;
164 aEvent
.Accessor
<<= index
;
165 aEvent
.Element
<<= i_column
;
168 m_aContainerListeners
.notifyEach( &XContainerListener::elementInserted
, aEvent
);
174 void SAL_CALL
DefaultGridColumnModel::removeColumn( ::sal_Int32 i_columnIndex
)
176 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
178 if ( ( i_columnIndex
< 0 ) || ( size_t( i_columnIndex
) >= m_aColumns
.size() ) )
179 throw css::lang::IndexOutOfBoundsException( OUString(), *this );
181 Columns::iterator
const pos
= m_aColumns
.begin() + i_columnIndex
;
182 Reference
< XGridColumn
> const xColumn( *pos
);
183 m_aColumns
.erase( pos
);
185 // update indexes of all subsequent columns
186 sal_Int32
columnIndex( i_columnIndex
);
187 for ( Columns::iterator updatePos
= m_aColumns
.begin() + columnIndex
;
188 updatePos
!= m_aColumns
.end();
189 ++updatePos
, ++columnIndex
192 GridColumn
* pColumnImpl
= GridColumn::getImplementation( *updatePos
);
195 SAL_WARN( "toolkit.controls", "DefaultGridColumnModel::removeColumn: invalid column implementation!" );
199 pColumnImpl
->setIndex( columnIndex
);
202 // fire removal notifications
203 ContainerEvent aEvent
;
204 aEvent
.Source
= *this;
205 aEvent
.Accessor
<<= i_columnIndex
;
206 aEvent
.Element
<<= xColumn
;
209 m_aContainerListeners
.notifyEach( &XContainerListener::elementRemoved
, aEvent
);
211 // dispose the removed column
216 catch( const Exception
& )
218 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
223 Sequence
< Reference
< XGridColumn
> > SAL_CALL
DefaultGridColumnModel::getColumns()
225 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
226 return ::comphelper::containerToSequence( m_aColumns
);
230 Reference
< XGridColumn
> SAL_CALL
DefaultGridColumnModel::getColumn(::sal_Int32 index
)
232 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
234 if ( index
>=0 && index
< static_cast<sal_Int32
>(m_aColumns
.size()))
235 return m_aColumns
[index
];
237 throw css::lang::IndexOutOfBoundsException();
241 void SAL_CALL
DefaultGridColumnModel::setDefaultColumns(sal_Int32 rowElements
)
243 ::std::vector
< ContainerEvent
> aRemovedColumns
;
244 ::std::vector
< ContainerEvent
> aInsertedColumns
;
247 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
249 // remove existing columns
250 while ( !m_aColumns
.empty() )
252 const size_t lastColIndex
= m_aColumns
.size() - 1;
254 ContainerEvent aEvent
;
255 aEvent
.Source
= *this;
256 aEvent
.Accessor
<<= sal_Int32( lastColIndex
);
257 aEvent
.Element
<<= m_aColumns
[ lastColIndex
];
258 aRemovedColumns
.push_back( aEvent
);
260 m_aColumns
.erase( m_aColumns
.begin() + lastColIndex
);
264 for ( sal_Int32 i
=0; i
<rowElements
; ++i
)
266 ::rtl::Reference
< GridColumn
> const pGridColumn
= new GridColumn();
267 Reference
< XGridColumn
> const xColumn( pGridColumn
.get() );
268 OUStringBuffer colTitle
;
269 colTitle
.append( "Column " );
270 colTitle
.append( i
+ 1 );
271 pGridColumn
->setTitle( colTitle
.makeStringAndClear() );
272 pGridColumn
->setColumnWidth( 80 /* APPFONT */ );
273 pGridColumn
->setFlexibility( 1 );
274 pGridColumn
->setResizeable( true );
275 pGridColumn
->setDataColumnIndex( i
);
277 ContainerEvent aEvent
;
278 aEvent
.Source
= *this;
279 aEvent
.Accessor
<<= i
;
280 aEvent
.Element
<<= xColumn
;
281 aInsertedColumns
.push_back( aEvent
);
283 m_aColumns
.push_back( xColumn
);
284 pGridColumn
->setIndex( i
);
288 // fire removal notifications
289 for ( ::std::vector
< ContainerEvent
>::const_iterator event
= aRemovedColumns
.begin();
290 event
!= aRemovedColumns
.end();
294 m_aContainerListeners
.notifyEach( &XContainerListener::elementRemoved
, *event
);
297 // fire insertion notifications
298 for ( ::std::vector
< ContainerEvent
>::const_iterator event
= aInsertedColumns
.begin();
299 event
!= aInsertedColumns
.end();
303 m_aContainerListeners
.notifyEach( &XContainerListener::elementInserted
, *event
);
306 // dispose removed columns
307 for ( ::std::vector
< ContainerEvent
>::const_iterator event
= aRemovedColumns
.begin();
308 event
!= aRemovedColumns
.end();
314 const Reference
< XComponent
> xColComp( event
->Element
, UNO_QUERY_THROW
);
317 catch( const Exception
& )
319 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
325 OUString SAL_CALL
DefaultGridColumnModel::getImplementationName( )
327 return OUString("stardiv.Toolkit.DefaultGridColumnModel");
330 sal_Bool SAL_CALL
DefaultGridColumnModel::supportsService( const OUString
& i_serviceName
)
332 return cppu::supportsService(this, i_serviceName
);
335 Sequence
< OUString
> SAL_CALL
DefaultGridColumnModel::getSupportedServiceNames( )
337 const OUString
aServiceName("com.sun.star.awt.grid.DefaultGridColumnModel");
338 const Sequence
< OUString
> aSeq( &aServiceName
, 1 );
343 void SAL_CALL
DefaultGridColumnModel::addContainerListener( const Reference
< XContainerListener
>& i_listener
)
345 if ( i_listener
.is() )
346 m_aContainerListeners
.addInterface( i_listener
);
350 void SAL_CALL
DefaultGridColumnModel::removeContainerListener( const Reference
< XContainerListener
>& i_listener
)
352 if ( i_listener
.is() )
353 m_aContainerListeners
.removeInterface( i_listener
);
357 void SAL_CALL
DefaultGridColumnModel::disposing()
359 DefaultGridColumnModel_Base::disposing();
361 EventObject
aEvent( *this );
362 m_aContainerListeners
.disposeAndClear( aEvent
);
364 ::osl::MutexGuard
aGuard( m_aMutex
);
366 // remove, dispose and clear columns
367 while ( !m_aColumns
.empty() )
371 const Reference
< XComponent
> xColComponent( m_aColumns
[ 0 ], UNO_QUERY_THROW
);
372 xColComponent
->dispose();
374 catch( const Exception
& )
376 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
379 m_aColumns
.erase( m_aColumns
.begin() );
383 m_aColumns
.swap( aEmpty
);
387 Reference
< css::util::XCloneable
> SAL_CALL
DefaultGridColumnModel::createClone( )
389 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
390 return new DefaultGridColumnModel( *this );
395 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
396 stardiv_Toolkit_DefaultGridColumnModel_get_implementation(
397 css::uno::XComponentContext
*,
398 css::uno::Sequence
<css::uno::Any
> const &)
400 return cppu::acquire(new DefaultGridColumnModel());
403 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */