LibreOffice Module toolkit (master) 1
defaultgridcolumnmodel.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20
21#include "gridcolumn.hxx"
22
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>
28
35#include <o3tl/safeint.hxx>
36#include <rtl/ref.hxx>
37#include <sal/log.hxx>
39
40#include <vector>
41
42using namespace css::awt;
43using namespace css::awt::grid;
44using namespace css::container;
45using namespace css::lang;
46using namespace css::uno;
47using namespace toolkit;
48
49namespace {
50
51typedef ::comphelper::WeakComponentImplHelper < css::awt::grid::XGridColumnModel
52 , css::lang::XServiceInfo
53 > DefaultGridColumnModel_Base;
54
55class DefaultGridColumnModel : public DefaultGridColumnModel_Base
56{
57public:
58 DefaultGridColumnModel();
59 DefaultGridColumnModel( DefaultGridColumnModel const & i_copySource );
60
61 // XGridColumnModel
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;
69
70 // XServiceInfo
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;
74
75 // XContainer
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;
78
79 // XCloneable
80 virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone( ) override;
81
82 // OComponentHelper
83 virtual void disposing( std::unique_lock<std::mutex>& ) override;
84
85private:
86 typedef ::std::vector< rtl::Reference< GridColumn > > Columns;
87
89 Columns m_aColumns;
90};
91
92 DefaultGridColumnModel::DefaultGridColumnModel()
93 {
94 }
95
96 DefaultGridColumnModel::DefaultGridColumnModel( DefaultGridColumnModel const & i_copySource )
97 {
98 Columns aColumns;
99 aColumns.reserve( i_copySource.m_aColumns.size() );
100 try
101 {
102 for ( Columns::const_iterator col = i_copySource.m_aColumns.begin();
103 col != i_copySource.m_aColumns.end();
104 ++col
105 )
106 {
107 rtl::Reference< GridColumn > const xClone( new GridColumn(**col) );
108
109 xClone->setIndex( col - i_copySource.m_aColumns.begin() );
110
111 aColumns.push_back( xClone );
112 }
113 }
114 catch( const Exception& )
115 {
116 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
117 }
118 if ( aColumns.size() == i_copySource.m_aColumns.size() )
119 m_aColumns.swap( aColumns );
120 }
121
122 ::sal_Int32 SAL_CALL DefaultGridColumnModel::getColumnCount()
123 {
124 return m_aColumns.size();
125 }
126
127
128 Reference< XGridColumn > SAL_CALL DefaultGridColumnModel::createColumn( )
129 {
130 std::unique_lock aGuard(m_aMutex);
131 throwIfDisposed(aGuard);
132 return new GridColumn();
133 }
134
135
136 ::sal_Int32 SAL_CALL DefaultGridColumnModel::addColumn( const Reference< XGridColumn > & i_column )
137 {
138 std::unique_lock aGuard(m_aMutex);
139 throwIfDisposed(aGuard);
140
141 GridColumn* const pGridColumn = dynamic_cast<GridColumn*>( i_column.get() );
142 if ( pGridColumn == nullptr )
143 throw css::lang::IllegalArgumentException( "invalid column implementation", *this, 1 );
144
145 m_aColumns.push_back( pGridColumn );
146 sal_Int32 index = m_aColumns.size() - 1;
147 pGridColumn->setIndex( index );
148
149 // fire insertion notifications
150 ContainerEvent aEvent;
151 aEvent.Source = *this;
152 aEvent.Accessor <<= index;
153 aEvent.Element <<= i_column;
154
155 m_aContainerListeners.notifyEach( aGuard, &XContainerListener::elementInserted, aEvent );
156
157 return index;
158 }
159
160
161 void SAL_CALL DefaultGridColumnModel::removeColumn( ::sal_Int32 i_columnIndex )
162 {
163 std::unique_lock aGuard(m_aMutex);
164 throwIfDisposed(aGuard);
165
166 if ( ( i_columnIndex < 0 ) || ( o3tl::make_unsigned( i_columnIndex ) >= m_aColumns.size() ) )
167 throw css::lang::IndexOutOfBoundsException( OUString(), *this );
168
169 Columns::iterator const pos = m_aColumns.begin() + i_columnIndex;
170 Reference< XGridColumn > const xColumn( *pos );
171 m_aColumns.erase( pos );
172
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
178 )
179 {
180 GridColumn* pColumnImpl = updatePos->get();
181 pColumnImpl->setIndex( columnIndex );
182 }
183
184 // fire removal notifications
185 ContainerEvent aEvent;
186 aEvent.Source = *this;
187 aEvent.Accessor <<= i_columnIndex;
188 aEvent.Element <<= xColumn;
189
190 m_aContainerListeners.notifyEach( aGuard, &XContainerListener::elementRemoved, aEvent );
191
192 aGuard.unlock();
193
194 // dispose the removed column
195 try
196 {
197 xColumn->dispose();
198 }
199 catch( const Exception& )
200 {
201 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
202 }
203 }
204
205
206 Sequence< Reference< XGridColumn > > SAL_CALL DefaultGridColumnModel::getColumns()
207 {
208 std::unique_lock aGuard(m_aMutex);
209 throwIfDisposed(aGuard);
210 return ::comphelper::containerToSequence<Reference<XGridColumn>>( m_aColumns );
211 }
212
213
214 Reference< XGridColumn > SAL_CALL DefaultGridColumnModel::getColumn(::sal_Int32 index)
215 {
216 std::unique_lock aGuard(m_aMutex);
217 throwIfDisposed(aGuard);
218
219 if ( index >=0 && o3tl::make_unsigned(index) < m_aColumns.size())
220 return m_aColumns[index];
221
222 throw css::lang::IndexOutOfBoundsException();
223 }
224
225
226 void SAL_CALL DefaultGridColumnModel::setDefaultColumns(sal_Int32 rowElements)
227 {
228 ::std::vector< ContainerEvent > aRemovedColumns;
229 ::std::vector< ContainerEvent > aInsertedColumns;
230
231 std::unique_lock aGuard(m_aMutex);
232 throwIfDisposed(aGuard);
233
234 // remove existing columns
235 while ( !m_aColumns.empty() )
236 {
237 const size_t lastColIndex = m_aColumns.size() - 1;
238
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 );
244
245 m_aColumns.erase( m_aColumns.begin() + lastColIndex );
246 }
247
248 // add new columns
249 for ( sal_Int32 i=0; i<rowElements; ++i )
250 {
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 );
258
259 ContainerEvent aEvent;
260 aEvent.Source = *this;
261 aEvent.Accessor <<= i;
262 aEvent.Element <<= Reference<XGridColumn>(pGridColumn);
263 aInsertedColumns.push_back( aEvent );
264
265 m_aColumns.push_back( pGridColumn );
266 pGridColumn->setIndex( i );
267 }
268
269 // fire removal notifications
270 for (const auto& rEvent : aRemovedColumns)
271 {
272 m_aContainerListeners.notifyEach( aGuard, &XContainerListener::elementRemoved, rEvent );
273 }
274
275 // fire insertion notifications
276 for (const auto& rEvent : aInsertedColumns)
277 {
278 m_aContainerListeners.notifyEach( aGuard, &XContainerListener::elementInserted, rEvent );
279 }
280
281 aGuard.unlock();
282
283 // dispose removed columns
284 for (const auto& rEvent : aRemovedColumns)
285 {
286 try
287 {
288 const Reference< XComponent > xColComp( rEvent.Element, UNO_QUERY_THROW );
289 xColComp->dispose();
290 }
291 catch( const Exception& )
292 {
293 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
294 }
295 }
296 }
297
298
299 OUString SAL_CALL DefaultGridColumnModel::getImplementationName( )
300 {
301 return "stardiv.Toolkit.DefaultGridColumnModel";
302 }
303
304 sal_Bool SAL_CALL DefaultGridColumnModel::supportsService( const OUString& i_serviceName )
305 {
306 return cppu::supportsService(this, i_serviceName);
307 }
308
309 Sequence< OUString > SAL_CALL DefaultGridColumnModel::getSupportedServiceNames( )
310 {
311 return { "com.sun.star.awt.grid.DefaultGridColumnModel" };
312 }
313
314
315 void SAL_CALL DefaultGridColumnModel::addContainerListener( const Reference< XContainerListener >& i_listener )
316 {
317 std::unique_lock aGuard(m_aMutex);
318 if ( i_listener.is() )
319 m_aContainerListeners.addInterface( aGuard, i_listener );
320 }
321
322
323 void SAL_CALL DefaultGridColumnModel::removeContainerListener( const Reference< XContainerListener >& i_listener )
324 {
325 std::unique_lock aGuard(m_aMutex);
326 if ( i_listener.is() )
327 m_aContainerListeners.removeInterface( aGuard, i_listener );
328 }
329
330
331 void DefaultGridColumnModel::disposing( std::unique_lock<std::mutex>& rGuard )
332 {
333 DefaultGridColumnModel_Base::disposing(rGuard);
334
335 EventObject aEvent( *this );
336 m_aContainerListeners.disposeAndClear( rGuard, aEvent );
337
338 // remove, dispose and clear columns
339 while ( !m_aColumns.empty() )
340 {
341 try
342 {
343 m_aColumns[ 0 ]->dispose();
344 }
345 catch( const Exception& )
346 {
347 DBG_UNHANDLED_EXCEPTION("toolkit.controls");
348 }
349
350 m_aColumns.erase( m_aColumns.begin() );
351 }
352
353 Columns().swap(m_aColumns);
354 }
355
356
357 Reference< css::util::XCloneable > SAL_CALL DefaultGridColumnModel::createClone( )
358 {
359 std::unique_lock aGuard(m_aMutex);
360 throwIfDisposed(aGuard);
361 return new DefaultGridColumnModel( *this );
362 }
363
364}
365
366extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
368 css::uno::XComponentContext *,
369 css::uno::Sequence<css::uno::Any> const &)
370{
371 return cppu::acquire(new DefaultGridColumnModel());
372}
373
374/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
AnyEventRef aEvent
void setIndex(sal_Int32 const i_index)
Definition: gridcolumn.cxx:237
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * stardiv_Toolkit_DefaultGridColumnModel_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
#define DBG_UNHANDLED_EXCEPTION(...)
Reference< XColumn > xColumn
void SAL_CALL elementRemoved(const css::container::ContainerEvent &Event) override
DECL_LISTENERMULTIPLEXER_END void SAL_CALL elementInserted(const css::container::ContainerEvent &Event) override
B2DTuple getColumn(const B2DHomMatrix &rMatrix, sal_uInt16 nCol)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
index
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
unsigned char sal_Bool
size_t pos