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/grid/XGridColumnModel.hpp>
24 #include <com/sun/star/awt/grid/XGridColumn.hpp>
25 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
26 #include <com/sun/star/lang/XServiceInfo.hpp>
27 #include <com/sun/star/uno/XComponentContext.hpp>
29 #include <comphelper/sequence.hxx>
30 #include <comphelper/servicehelper.hxx>
31 #include <comphelper/componentguard.hxx>
32 #include <comphelper/interfacecontainer4.hxx>
33 #include <comphelper/compbase.hxx>
34 #include <cppuhelper/supportsservice.hxx>
35 #include <o3tl/safeint.hxx>
36 #include <rtl/ref.hxx>
37 #include <sal/log.hxx>
38 #include <comphelper/diagnose_ex.hxx>
42 using namespace css::awt
;
43 using namespace css::awt::grid
;
44 using namespace css::container
;
45 using namespace css::lang
;
46 using namespace css::uno
;
47 using namespace toolkit
;
51 typedef ::comphelper::WeakComponentImplHelper
< css::awt::grid::XGridColumnModel
52 , css::lang::XServiceInfo
53 > DefaultGridColumnModel_Base
;
55 class DefaultGridColumnModel
: 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 disposing( std::unique_lock
<std::mutex
>& ) override
;
86 typedef ::std::vector
< rtl::Reference
< GridColumn
> > Columns
;
88 ::comphelper::OInterfaceContainerHelper4
<XContainerListener
> m_aContainerListeners
;
92 DefaultGridColumnModel::DefaultGridColumnModel()
96 DefaultGridColumnModel::DefaultGridColumnModel( DefaultGridColumnModel
const & i_copySource
)
99 aColumns
.reserve( i_copySource
.m_aColumns
.size() );
102 for ( Columns::const_iterator col
= i_copySource
.m_aColumns
.begin();
103 col
!= i_copySource
.m_aColumns
.end();
107 rtl::Reference
< GridColumn
> const xClone( new GridColumn(**col
) );
109 xClone
->setIndex( col
- i_copySource
.m_aColumns
.begin() );
111 aColumns
.push_back( xClone
);
114 catch( const Exception
& )
116 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
118 if ( aColumns
.size() == i_copySource
.m_aColumns
.size() )
119 m_aColumns
.swap( aColumns
);
122 ::sal_Int32 SAL_CALL
DefaultGridColumnModel::getColumnCount()
124 return m_aColumns
.size();
128 Reference
< XGridColumn
> SAL_CALL
DefaultGridColumnModel::createColumn( )
130 std::unique_lock
aGuard(m_aMutex
);
131 throwIfDisposed(aGuard
);
132 return new GridColumn();
136 ::sal_Int32 SAL_CALL
DefaultGridColumnModel::addColumn( const Reference
< XGridColumn
> & i_column
)
138 std::unique_lock
aGuard(m_aMutex
);
139 throwIfDisposed(aGuard
);
141 GridColumn
* const pGridColumn
= dynamic_cast<GridColumn
*>( i_column
.get() );
142 if ( pGridColumn
== nullptr )
143 throw css::lang::IllegalArgumentException( "invalid column implementation", *this, 1 );
145 m_aColumns
.push_back( pGridColumn
);
146 sal_Int32 index
= m_aColumns
.size() - 1;
147 pGridColumn
->setIndex( index
);
149 // fire insertion notifications
150 ContainerEvent aEvent
;
151 aEvent
.Source
= *this;
152 aEvent
.Accessor
<<= index
;
153 aEvent
.Element
<<= i_column
;
155 m_aContainerListeners
.notifyEach( aGuard
, &XContainerListener::elementInserted
, aEvent
);
161 void SAL_CALL
DefaultGridColumnModel::removeColumn( ::sal_Int32 i_columnIndex
)
163 std::unique_lock
aGuard(m_aMutex
);
164 throwIfDisposed(aGuard
);
166 if ( ( i_columnIndex
< 0 ) || ( o3tl::make_unsigned( i_columnIndex
) >= m_aColumns
.size() ) )
167 throw css::lang::IndexOutOfBoundsException( OUString(), *this );
169 Columns::iterator
const pos
= m_aColumns
.begin() + i_columnIndex
;
170 Reference
< XGridColumn
> const xColumn( *pos
);
171 m_aColumns
.erase( pos
);
173 // update indexes of all subsequent columns
174 sal_Int32
columnIndex( i_columnIndex
);
175 for ( Columns::iterator updatePos
= m_aColumns
.begin() + columnIndex
;
176 updatePos
!= m_aColumns
.end();
177 ++updatePos
, ++columnIndex
180 GridColumn
* pColumnImpl
= updatePos
->get();
181 pColumnImpl
->setIndex( columnIndex
);
184 // fire removal notifications
185 ContainerEvent aEvent
;
186 aEvent
.Source
= *this;
187 aEvent
.Accessor
<<= i_columnIndex
;
188 aEvent
.Element
<<= xColumn
;
190 m_aContainerListeners
.notifyEach( aGuard
, &XContainerListener::elementRemoved
, aEvent
);
194 // dispose the removed column
199 catch( const Exception
& )
201 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
206 Sequence
< Reference
< XGridColumn
> > SAL_CALL
DefaultGridColumnModel::getColumns()
208 std::unique_lock
aGuard(m_aMutex
);
209 throwIfDisposed(aGuard
);
210 return ::comphelper::containerToSequence
<Reference
<XGridColumn
>>( m_aColumns
);
214 Reference
< XGridColumn
> SAL_CALL
DefaultGridColumnModel::getColumn(::sal_Int32 index
)
216 std::unique_lock
aGuard(m_aMutex
);
217 throwIfDisposed(aGuard
);
219 if ( index
>=0 && o3tl::make_unsigned(index
) < m_aColumns
.size())
220 return m_aColumns
[index
];
222 throw css::lang::IndexOutOfBoundsException();
226 void SAL_CALL
DefaultGridColumnModel::setDefaultColumns(sal_Int32 rowElements
)
228 ::std::vector
< ContainerEvent
> aRemovedColumns
;
229 ::std::vector
< ContainerEvent
> aInsertedColumns
;
231 std::unique_lock
aGuard(m_aMutex
);
232 throwIfDisposed(aGuard
);
234 // remove existing columns
235 while ( !m_aColumns
.empty() )
237 const size_t lastColIndex
= m_aColumns
.size() - 1;
239 ContainerEvent aEvent
;
240 aEvent
.Source
= *this;
241 aEvent
.Accessor
<<= sal_Int32( lastColIndex
);
242 aEvent
.Element
<<= Reference
<XGridColumn
>(m_aColumns
[ lastColIndex
]);
243 aRemovedColumns
.push_back( aEvent
);
245 m_aColumns
.erase( m_aColumns
.begin() + lastColIndex
);
249 for ( sal_Int32 i
=0; i
<rowElements
; ++i
)
251 ::rtl::Reference
< GridColumn
> const pGridColumn
= new GridColumn();
252 OUString colTitle
= "Column " + OUString::number( i
+ 1 );
253 pGridColumn
->setTitle( colTitle
);
254 pGridColumn
->setColumnWidth( 80 /* APPFONT */ );
255 pGridColumn
->setFlexibility( 1 );
256 pGridColumn
->setResizeable( true );
257 pGridColumn
->setDataColumnIndex( i
);
259 ContainerEvent aEvent
;
260 aEvent
.Source
= *this;
261 aEvent
.Accessor
<<= i
;
262 aEvent
.Element
<<= Reference
<XGridColumn
>(pGridColumn
);
263 aInsertedColumns
.push_back( aEvent
);
265 m_aColumns
.push_back( pGridColumn
);
266 pGridColumn
->setIndex( i
);
269 // fire removal notifications
270 for (const auto& rEvent
: aRemovedColumns
)
272 m_aContainerListeners
.notifyEach( aGuard
, &XContainerListener::elementRemoved
, rEvent
);
275 // fire insertion notifications
276 for (const auto& rEvent
: aInsertedColumns
)
278 m_aContainerListeners
.notifyEach( aGuard
, &XContainerListener::elementInserted
, rEvent
);
283 // dispose removed columns
284 for (const auto& rEvent
: aRemovedColumns
)
288 const Reference
< XComponent
> xColComp( rEvent
.Element
, UNO_QUERY
);
292 catch( const Exception
& )
294 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
300 OUString SAL_CALL
DefaultGridColumnModel::getImplementationName( )
302 return "stardiv.Toolkit.DefaultGridColumnModel";
305 sal_Bool SAL_CALL
DefaultGridColumnModel::supportsService( const OUString
& i_serviceName
)
307 return cppu::supportsService(this, i_serviceName
);
310 Sequence
< OUString
> SAL_CALL
DefaultGridColumnModel::getSupportedServiceNames( )
312 return { "com.sun.star.awt.grid.DefaultGridColumnModel" };
316 void SAL_CALL
DefaultGridColumnModel::addContainerListener( const Reference
< XContainerListener
>& i_listener
)
318 std::unique_lock
aGuard(m_aMutex
);
319 if ( i_listener
.is() )
320 m_aContainerListeners
.addInterface( aGuard
, i_listener
);
324 void SAL_CALL
DefaultGridColumnModel::removeContainerListener( const Reference
< XContainerListener
>& i_listener
)
326 std::unique_lock
aGuard(m_aMutex
);
327 if ( i_listener
.is() )
328 m_aContainerListeners
.removeInterface( aGuard
, i_listener
);
332 void DefaultGridColumnModel::disposing( std::unique_lock
<std::mutex
>& rGuard
)
334 DefaultGridColumnModel_Base::disposing(rGuard
);
336 EventObject
aEvent( *this );
337 m_aContainerListeners
.disposeAndClear( rGuard
, aEvent
);
339 // remove, dispose and clear columns
340 while ( !m_aColumns
.empty() )
344 m_aColumns
[ 0 ]->dispose();
346 catch( const Exception
& )
348 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
351 m_aColumns
.erase( m_aColumns
.begin() );
354 Columns().swap(m_aColumns
);
358 Reference
< css::util::XCloneable
> SAL_CALL
DefaultGridColumnModel::createClone( )
360 std::unique_lock
aGuard(m_aMutex
);
361 throwIfDisposed(aGuard
);
362 return new DefaultGridColumnModel( *this );
367 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
368 stardiv_Toolkit_DefaultGridColumnModel_get_implementation(
369 css::uno::XComponentContext
*,
370 css::uno::Sequence
<css::uno::Any
> const &)
372 return cppu::acquire(new DefaultGridColumnModel());
375 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */