Line data Source code
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 "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 : using ::com::sun::star::lang::XMultiServiceFactory;
40 : using ::com::sun::star::uno::RuntimeException;
41 : using ::com::sun::star::uno::Sequence;
42 : using ::com::sun::star::uno::UNO_QUERY_THROW;
43 : using ::com::sun::star::uno::UNO_QUERY;
44 : using ::com::sun::star::awt::grid::XGridColumn;
45 : using ::com::sun::star::uno::XInterface;
46 : using ::com::sun::star::lang::XComponent;
47 : using ::com::sun::star::lang::EventObject;
48 : using ::com::sun::star::container::XContainerListener;
49 : using ::com::sun::star::container::ContainerEvent;
50 : 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 : //= DefaultGridColumnModel
57 : //==================================================================================================================
58 : //------------------------------------------------------------------------------------------------------------------
59 9 : DefaultGridColumnModel::DefaultGridColumnModel()
60 : :DefaultGridColumnModel_Base( m_aMutex )
61 : ,m_aContainerListeners( m_aMutex )
62 9 : ,m_aColumns()
63 : {
64 9 : }
65 :
66 : //------------------------------------------------------------------------------------------------------------------
67 1 : DefaultGridColumnModel::DefaultGridColumnModel( DefaultGridColumnModel const & i_copySource )
68 : :cppu::BaseMutex()
69 : ,DefaultGridColumnModel_Base( m_aMutex )
70 : ,m_aContainerListeners( m_aMutex )
71 1 : ,m_aColumns()
72 : {
73 1 : Columns aColumns;
74 1 : aColumns.reserve( i_copySource.m_aColumns.size() );
75 : try
76 : {
77 33 : for ( Columns::const_iterator col = i_copySource.m_aColumns.begin();
78 22 : col != i_copySource.m_aColumns.end();
79 : ++col
80 : )
81 : {
82 10 : Reference< XCloneable > const xCloneable( *col, UNO_QUERY_THROW );
83 20 : Reference< XGridColumn > const xClone( xCloneable->createClone(), UNO_QUERY_THROW );
84 :
85 10 : GridColumn* const pGridColumn = GridColumn::getImplementation( xClone );
86 10 : if ( pGridColumn == NULL )
87 0 : throw RuntimeException( "invalid clone source implementation", *this );
88 : // that's indeed a RuntimeException, not an IllegalArgumentException or some such:
89 : // a DefaultGridColumnModel implementation whose columns are not GridColumn implementations
90 : // is borked.
91 10 : pGridColumn->setIndex( col - i_copySource.m_aColumns.begin() );
92 :
93 10 : aColumns.push_back( xClone );
94 10 : }
95 : }
96 0 : catch( const Exception& )
97 : {
98 : DBG_UNHANDLED_EXCEPTION();
99 : }
100 1 : if ( aColumns.size() == i_copySource.m_aColumns.size() )
101 1 : m_aColumns.swap( aColumns );
102 1 : }
103 :
104 : //------------------------------------------------------------------------------------------------------------------
105 20 : DefaultGridColumnModel::~DefaultGridColumnModel()
106 : {
107 20 : }
108 :
109 : //------------------------------------------------------------------------------------------------------------------
110 56 : ::sal_Int32 SAL_CALL DefaultGridColumnModel::getColumnCount() throw (RuntimeException)
111 : {
112 56 : return m_aColumns.size();
113 : }
114 :
115 : //------------------------------------------------------------------------------------------------------------------
116 2 : Reference< XGridColumn > SAL_CALL DefaultGridColumnModel::createColumn( ) throw (RuntimeException)
117 : {
118 2 : ::comphelper::ComponentGuard aGuard( *this, rBHelper );
119 2 : return new GridColumn();
120 : }
121 :
122 : //------------------------------------------------------------------------------------------------------------------
123 3 : ::sal_Int32 SAL_CALL DefaultGridColumnModel::addColumn( const Reference< XGridColumn > & i_column ) throw (RuntimeException, IllegalArgumentException)
124 : {
125 3 : ::comphelper::ComponentGuard aGuard( *this, rBHelper );
126 :
127 3 : GridColumn* const pGridColumn = GridColumn::getImplementation( i_column );
128 3 : if ( pGridColumn == NULL )
129 1 : throw IllegalArgumentException( "invalid column implementation", *this, 1 );
130 :
131 2 : m_aColumns.push_back( i_column );
132 2 : sal_Int32 index = m_aColumns.size() - 1;
133 2 : pGridColumn->setIndex( index );
134 :
135 : // fire insertion notifications
136 4 : ContainerEvent aEvent;
137 2 : aEvent.Source = *this;
138 2 : aEvent.Accessor <<= index;
139 2 : aEvent.Element <<= i_column;
140 :
141 2 : aGuard.clear();
142 2 : m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, aEvent );
143 :
144 5 : return index;
145 : }
146 :
147 : //------------------------------------------------------------------------------------------------------------------
148 7 : void SAL_CALL DefaultGridColumnModel::removeColumn( ::sal_Int32 i_columnIndex ) throw (RuntimeException, IndexOutOfBoundsException)
149 : {
150 7 : ::comphelper::ComponentGuard aGuard( *this, rBHelper );
151 :
152 7 : if ( ( i_columnIndex < 0 ) || ( size_t( i_columnIndex ) >= m_aColumns.size() ) )
153 0 : throw IndexOutOfBoundsException( OUString(), *this );
154 :
155 7 : Columns::iterator const pos = m_aColumns.begin() + i_columnIndex;
156 14 : Reference< XGridColumn > const xColumn( *pos );
157 7 : m_aColumns.erase( pos );
158 :
159 : // update indexes of all subsequent columns
160 7 : sal_Int32 columnIndex( i_columnIndex );
161 33 : for ( Columns::iterator updatePos = m_aColumns.begin() + columnIndex;
162 22 : updatePos != m_aColumns.end();
163 : ++updatePos, ++columnIndex
164 : )
165 : {
166 4 : GridColumn* pColumnImpl = GridColumn::getImplementation( *updatePos );
167 4 : if ( !pColumnImpl )
168 : {
169 : SAL_WARN( "toolkit.controls", "DefaultGridColumnModel::removeColumn: invalid column implementation!" );
170 0 : continue;
171 : }
172 :
173 4 : pColumnImpl->setIndex( columnIndex );
174 : }
175 :
176 : // fire removal notifications
177 14 : ContainerEvent aEvent;
178 7 : aEvent.Source = *this;
179 7 : aEvent.Accessor <<= i_columnIndex;
180 7 : aEvent.Element <<= xColumn;
181 :
182 7 : aGuard.clear();
183 7 : m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, aEvent );
184 :
185 : // dispose the removed column
186 : try
187 : {
188 7 : xColumn->dispose();
189 : }
190 0 : catch( const Exception& )
191 : {
192 : DBG_UNHANDLED_EXCEPTION();
193 7 : }
194 7 : }
195 :
196 : //------------------------------------------------------------------------------------------------------------------
197 5 : Sequence< Reference< XGridColumn > > SAL_CALL DefaultGridColumnModel::getColumns() throw (RuntimeException)
198 : {
199 5 : ::comphelper::ComponentGuard aGuard( *this, rBHelper );
200 5 : return ::comphelper::containerToSequence( m_aColumns );
201 : }
202 :
203 : //------------------------------------------------------------------------------------------------------------------
204 42 : Reference< XGridColumn > SAL_CALL DefaultGridColumnModel::getColumn(::sal_Int32 index) throw (IndexOutOfBoundsException, RuntimeException)
205 : {
206 42 : ::comphelper::ComponentGuard aGuard( *this, rBHelper );
207 :
208 42 : if ( index >=0 && index < ((sal_Int32)m_aColumns.size()))
209 84 : return m_aColumns[index];
210 :
211 0 : throw IndexOutOfBoundsException();
212 : }
213 :
214 : //------------------------------------------------------------------------------------------------------------------
215 5 : void SAL_CALL DefaultGridColumnModel::setDefaultColumns(sal_Int32 rowElements) throw (RuntimeException)
216 : {
217 5 : ::std::vector< ContainerEvent > aRemovedColumns;
218 10 : ::std::vector< ContainerEvent > aInsertedColumns;
219 :
220 : {
221 5 : ::comphelper::ComponentGuard aGuard( *this, rBHelper );
222 :
223 : // remove existing columns
224 13 : while ( !m_aColumns.empty() )
225 : {
226 3 : const size_t lastColIndex = m_aColumns.size() - 1;
227 :
228 3 : ContainerEvent aEvent;
229 3 : aEvent.Source = *this;
230 3 : aEvent.Accessor <<= sal_Int32( lastColIndex );
231 3 : aEvent.Element <<= m_aColumns[ lastColIndex ];
232 3 : aRemovedColumns.push_back( aEvent );
233 :
234 3 : m_aColumns.erase( m_aColumns.begin() + lastColIndex );
235 3 : }
236 :
237 : // add new columns
238 29 : for ( sal_Int32 i=0; i<rowElements; ++i )
239 : {
240 24 : ::rtl::Reference< GridColumn > const pGridColumn = new GridColumn();
241 48 : Reference< XGridColumn > const xColumn( pGridColumn.get() );
242 48 : OUStringBuffer colTitle;
243 24 : colTitle.appendAscii( "Column " );
244 24 : colTitle.append( i + 1 );
245 24 : pGridColumn->setTitle( colTitle.makeStringAndClear() );
246 24 : pGridColumn->setColumnWidth( 80 /* APPFONT */ );
247 24 : pGridColumn->setFlexibility( 1 );
248 24 : pGridColumn->setResizeable( sal_True );
249 24 : pGridColumn->setDataColumnIndex( i );
250 :
251 48 : ContainerEvent aEvent;
252 24 : aEvent.Source = *this;
253 24 : aEvent.Accessor <<= i;
254 24 : aEvent.Element <<= xColumn;
255 24 : aInsertedColumns.push_back( aEvent );
256 :
257 24 : m_aColumns.push_back( xColumn );
258 24 : pGridColumn->setIndex( i );
259 29 : }
260 : }
261 :
262 : // fire removal notifications
263 24 : for ( ::std::vector< ContainerEvent >::const_iterator event = aRemovedColumns.begin();
264 16 : event != aRemovedColumns.end();
265 : ++event
266 : )
267 : {
268 3 : m_aContainerListeners.notifyEach( &XContainerListener::elementRemoved, *event );
269 : }
270 :
271 : // fire insertion notifications
272 87 : for ( ::std::vector< ContainerEvent >::const_iterator event = aInsertedColumns.begin();
273 58 : event != aInsertedColumns.end();
274 : ++event
275 : )
276 : {
277 24 : m_aContainerListeners.notifyEach( &XContainerListener::elementInserted, *event );
278 : }
279 :
280 : // dispose removed columns
281 24 : for ( ::std::vector< ContainerEvent >::const_iterator event = aRemovedColumns.begin();
282 16 : event != aRemovedColumns.end();
283 : ++event
284 : )
285 : {
286 : try
287 : {
288 3 : const Reference< XComponent > xColComp( event->Element, UNO_QUERY_THROW );
289 3 : xColComp->dispose();
290 : }
291 0 : catch( const Exception& )
292 : {
293 : DBG_UNHANDLED_EXCEPTION();
294 : }
295 5 : }
296 5 : }
297 :
298 : //------------------------------------------------------------------------------------------------------------------
299 0 : OUString SAL_CALL DefaultGridColumnModel::getImplementationName( ) throw (RuntimeException)
300 : {
301 0 : return OUString( "org.openoffice.comp.toolkit.DefaultGridColumnModel" );
302 : }
303 :
304 : //------------------------------------------------------------------------------------------------------------------
305 0 : sal_Bool SAL_CALL DefaultGridColumnModel::supportsService( const OUString& i_serviceName ) throw (RuntimeException)
306 : {
307 0 : const Sequence< OUString > aServiceNames( getSupportedServiceNames() );
308 0 : for ( sal_Int32 i=0; i<aServiceNames.getLength(); ++i )
309 0 : if ( aServiceNames[i] == i_serviceName )
310 0 : return sal_True;
311 0 : return sal_False;
312 : }
313 :
314 : //------------------------------------------------------------------------------------------------------------------
315 0 : Sequence< OUString > SAL_CALL DefaultGridColumnModel::getSupportedServiceNames( ) throw (RuntimeException)
316 : {
317 0 : const OUString aServiceName( OUString::createFromAscii( szServiceName_DefaultGridColumnModel ) );
318 0 : const Sequence< OUString > aSeq( &aServiceName, 1 );
319 0 : return aSeq;
320 : }
321 :
322 : //------------------------------------------------------------------------------------------------------------------
323 2 : void SAL_CALL DefaultGridColumnModel::addContainerListener( const Reference< XContainerListener >& i_listener ) throw (RuntimeException)
324 : {
325 2 : if ( i_listener.is() )
326 2 : m_aContainerListeners.addInterface( i_listener );
327 2 : }
328 :
329 : //------------------------------------------------------------------------------------------------------------------
330 1 : void SAL_CALL DefaultGridColumnModel::removeContainerListener( const Reference< XContainerListener >& i_listener ) throw (RuntimeException)
331 : {
332 1 : if ( i_listener.is() )
333 1 : m_aContainerListeners.removeInterface( i_listener );
334 1 : }
335 :
336 : //------------------------------------------------------------------------------------------------------------------
337 10 : void SAL_CALL DefaultGridColumnModel::disposing()
338 : {
339 10 : DefaultGridColumnModel_Base::disposing();
340 :
341 10 : EventObject aEvent( *this );
342 10 : m_aContainerListeners.disposeAndClear( aEvent );
343 :
344 20 : ::osl::MutexGuard aGuard( m_aMutex );
345 :
346 : // remove, dispose and clear columns
347 46 : while ( !m_aColumns.empty() )
348 : {
349 : try
350 : {
351 26 : const Reference< XComponent > xColComponent( m_aColumns[ 0 ], UNO_QUERY_THROW );
352 26 : xColComponent->dispose();
353 : }
354 0 : catch( const Exception& )
355 : {
356 : DBG_UNHANDLED_EXCEPTION();
357 : }
358 :
359 26 : m_aColumns.erase( m_aColumns.begin() );
360 : }
361 :
362 20 : Columns aEmpty;
363 20 : m_aColumns.swap( aEmpty );
364 10 : }
365 :
366 : //------------------------------------------------------------------------------------------------------------------
367 1 : Reference< XCloneable > SAL_CALL DefaultGridColumnModel::createClone( ) throw (RuntimeException)
368 : {
369 1 : ::comphelper::ComponentGuard aGuard( *this, rBHelper );
370 1 : return new DefaultGridColumnModel( *this );
371 : }
372 :
373 : //......................................................................................................................
374 : } // namespace toolkit
375 : //......................................................................................................................
376 :
377 : //----------------------------------------------------------------------------------------------------------------------
378 9 : ::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 >& )
379 : {
380 9 : return ::com::sun::star::uno::Reference < ::com::sun::star::uno::XInterface >( ( ::cppu::OWeakObject* ) new ::toolkit::DefaultGridColumnModel );
381 : }
382 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|