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 "defaultgridcolumnmodel.hxx"
22 #include "gridcolumn.hxx"
24 #include <com/sun/star/awt/XVclWindowPeer.hpp>
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>
33 //......................................................................................................................
35 //......................................................................................................................
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
;
55 //==================================================================================================================
56 //= DefaultGridColumnModel
57 //==================================================================================================================
58 //------------------------------------------------------------------------------------------------------------------
59 DefaultGridColumnModel::DefaultGridColumnModel( const Reference
< XComponentContext
>& i_context
)
60 :DefaultGridColumnModel_Base( m_aMutex
)
61 ,m_aContext( i_context
)
62 ,m_aContainerListeners( m_aMutex
)
67 //------------------------------------------------------------------------------------------------------------------
68 DefaultGridColumnModel::DefaultGridColumnModel( DefaultGridColumnModel
const & i_copySource
)
70 ,DefaultGridColumnModel_Base( m_aMutex
)
71 ,m_aContext( i_copySource
.m_aContext
)
72 ,m_aContainerListeners( m_aMutex
)
76 aColumns
.reserve( i_copySource
.m_aColumns
.size() );
79 for ( Columns::const_iterator col
= i_copySource
.m_aColumns
.begin();
80 col
!= i_copySource
.m_aColumns
.end();
84 Reference
< XCloneable
> const xCloneable( *col
, UNO_QUERY_THROW
);
85 Reference
< XGridColumn
> const xClone( xCloneable
->createClone(), UNO_QUERY_THROW
);
87 GridColumn
* const pGridColumn
= GridColumn::getImplementation( xClone
);
88 if ( pGridColumn
== NULL
)
89 throw RuntimeException( "invalid clone source implementation", *this );
90 // that's indeed a RuntimeException, not an IllegalArgumentException or some such:
91 // a DefaultGridColumnModel implementation whose columns are not GridColumn implementations
93 pGridColumn
->setIndex( col
- i_copySource
.m_aColumns
.begin() );
95 aColumns
.push_back( xClone
);
98 catch( const Exception
& )
100 DBG_UNHANDLED_EXCEPTION();
102 if ( aColumns
.size() == i_copySource
.m_aColumns
.size() )
103 m_aColumns
.swap( aColumns
);
106 //------------------------------------------------------------------------------------------------------------------
107 DefaultGridColumnModel::~DefaultGridColumnModel()
111 //------------------------------------------------------------------------------------------------------------------
112 ::sal_Int32 SAL_CALL
DefaultGridColumnModel::getColumnCount() throw (RuntimeException
)
114 return m_aColumns
.size();
117 //------------------------------------------------------------------------------------------------------------------
118 Reference
< XGridColumn
> SAL_CALL
DefaultGridColumnModel::createColumn( ) throw (RuntimeException
)
120 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
121 return new GridColumn();
124 //------------------------------------------------------------------------------------------------------------------
125 ::sal_Int32 SAL_CALL
DefaultGridColumnModel::addColumn( const Reference
< XGridColumn
> & i_column
) throw (RuntimeException
, IllegalArgumentException
)
127 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
129 GridColumn
* const pGridColumn
= GridColumn::getImplementation( i_column
);
130 if ( pGridColumn
== NULL
)
131 throw IllegalArgumentException( "invalid column implementation", *this, 1 );
133 m_aColumns
.push_back( i_column
);
134 sal_Int32 index
= m_aColumns
.size() - 1;
135 pGridColumn
->setIndex( index
);
137 // fire insertion notifications
138 ContainerEvent aEvent
;
139 aEvent
.Source
= *this;
140 aEvent
.Accessor
<<= index
;
141 aEvent
.Element
<<= i_column
;
144 m_aContainerListeners
.notifyEach( &XContainerListener::elementInserted
, aEvent
);
149 //------------------------------------------------------------------------------------------------------------------
150 void SAL_CALL
DefaultGridColumnModel::removeColumn( ::sal_Int32 i_columnIndex
) throw (RuntimeException
, IndexOutOfBoundsException
)
152 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
154 if ( ( i_columnIndex
< 0 ) || ( size_t( i_columnIndex
) >= m_aColumns
.size() ) )
155 throw IndexOutOfBoundsException( OUString(), *this );
157 Columns::iterator
const pos
= m_aColumns
.begin() + i_columnIndex
;
158 Reference
< XGridColumn
> const xColumn( *pos
);
159 m_aColumns
.erase( pos
);
161 // update indexes of all subsequent columns
162 sal_Int32
columnIndex( i_columnIndex
);
163 for ( Columns::iterator updatePos
= m_aColumns
.begin() + columnIndex
;
164 updatePos
!= m_aColumns
.end();
165 ++updatePos
, ++columnIndex
168 GridColumn
* pColumnImpl
= GridColumn::getImplementation( *updatePos
);
171 SAL_WARN( "toolkit.controls", "DefaultGridColumnModel::removeColumn: invalid column implementation!" );
175 pColumnImpl
->setIndex( columnIndex
);
178 // fire removal notifications
179 ContainerEvent aEvent
;
180 aEvent
.Source
= *this;
181 aEvent
.Accessor
<<= i_columnIndex
;
182 aEvent
.Element
<<= xColumn
;
185 m_aContainerListeners
.notifyEach( &XContainerListener::elementRemoved
, aEvent
);
187 // dispose the removed column
190 Reference
< XComponent
> const xColComp( xColumn
, UNO_QUERY_THROW
);
193 catch( const Exception
& )
195 DBG_UNHANDLED_EXCEPTION();
199 //------------------------------------------------------------------------------------------------------------------
200 Sequence
< Reference
< XGridColumn
> > SAL_CALL
DefaultGridColumnModel::getColumns() throw (RuntimeException
)
202 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
203 return ::comphelper::containerToSequence( m_aColumns
);
206 //------------------------------------------------------------------------------------------------------------------
207 Reference
< XGridColumn
> SAL_CALL
DefaultGridColumnModel::getColumn(::sal_Int32 index
) throw (IndexOutOfBoundsException
, RuntimeException
)
209 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
211 if ( index
>=0 && index
< ((sal_Int32
)m_aColumns
.size()))
212 return m_aColumns
[index
];
214 throw IndexOutOfBoundsException();
217 //------------------------------------------------------------------------------------------------------------------
218 void SAL_CALL
DefaultGridColumnModel::setDefaultColumns(sal_Int32 rowElements
) throw (RuntimeException
)
220 ::std::vector
< ContainerEvent
> aRemovedColumns
;
221 ::std::vector
< ContainerEvent
> aInsertedColumns
;
224 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
226 // remove existing columns
227 while ( !m_aColumns
.empty() )
229 const size_t lastColIndex
= m_aColumns
.size() - 1;
231 ContainerEvent aEvent
;
232 aEvent
.Source
= *this;
233 aEvent
.Accessor
<<= sal_Int32( lastColIndex
);
234 aEvent
.Element
<<= m_aColumns
[ lastColIndex
];
235 aRemovedColumns
.push_back( aEvent
);
237 m_aColumns
.erase( m_aColumns
.begin() + lastColIndex
);
241 for ( sal_Int32 i
=0; i
<rowElements
; ++i
)
243 ::rtl::Reference
< GridColumn
> const pGridColumn
= new GridColumn();
244 Reference
< XGridColumn
> const xColumn( pGridColumn
.get() );
245 OUStringBuffer colTitle
;
246 colTitle
.appendAscii( "Column " );
247 colTitle
.append( i
+ 1 );
248 pGridColumn
->setTitle( colTitle
.makeStringAndClear() );
249 pGridColumn
->setColumnWidth( 80 /* APPFONT */ );
250 pGridColumn
->setFlexibility( 1 );
251 pGridColumn
->setResizeable( sal_True
);
252 pGridColumn
->setDataColumnIndex( i
);
254 ContainerEvent aEvent
;
255 aEvent
.Source
= *this;
256 aEvent
.Accessor
<<= i
;
257 aEvent
.Element
<<= xColumn
;
258 aInsertedColumns
.push_back( aEvent
);
260 m_aColumns
.push_back( xColumn
);
261 pGridColumn
->setIndex( i
);
265 // fire removal notifications
266 for ( ::std::vector
< ContainerEvent
>::const_iterator event
= aRemovedColumns
.begin();
267 event
!= aRemovedColumns
.end();
271 m_aContainerListeners
.notifyEach( &XContainerListener::elementRemoved
, *event
);
274 // fire insertion notifications
275 for ( ::std::vector
< ContainerEvent
>::const_iterator event
= aInsertedColumns
.begin();
276 event
!= aInsertedColumns
.end();
280 m_aContainerListeners
.notifyEach( &XContainerListener::elementInserted
, *event
);
283 // dispose removed columns
284 for ( ::std::vector
< ContainerEvent
>::const_iterator event
= aRemovedColumns
.begin();
285 event
!= aRemovedColumns
.end();
291 const Reference
< XComponent
> xColComp( event
->Element
, UNO_QUERY_THROW
);
294 catch( const Exception
& )
296 DBG_UNHANDLED_EXCEPTION();
301 //------------------------------------------------------------------------------------------------------------------
302 OUString SAL_CALL
DefaultGridColumnModel::getImplementationName( ) throw (RuntimeException
)
304 return OUString( "org.openoffice.comp.toolkit.DefaultGridColumnModel" );
307 //------------------------------------------------------------------------------------------------------------------
308 sal_Bool SAL_CALL
DefaultGridColumnModel::supportsService( const OUString
& i_serviceName
) throw (RuntimeException
)
310 const Sequence
< OUString
> aServiceNames( getSupportedServiceNames() );
311 for ( sal_Int32 i
=0; i
<aServiceNames
.getLength(); ++i
)
312 if ( aServiceNames
[i
] == i_serviceName
)
317 //------------------------------------------------------------------------------------------------------------------
318 Sequence
< OUString
> SAL_CALL
DefaultGridColumnModel::getSupportedServiceNames( ) throw (RuntimeException
)
320 const OUString
aServiceName( OUString::createFromAscii( szServiceName_DefaultGridColumnModel
) );
321 const Sequence
< OUString
> aSeq( &aServiceName
, 1 );
325 //------------------------------------------------------------------------------------------------------------------
326 void SAL_CALL
DefaultGridColumnModel::addContainerListener( const Reference
< XContainerListener
>& i_listener
) throw (RuntimeException
)
328 if ( i_listener
.is() )
329 m_aContainerListeners
.addInterface( i_listener
);
332 //------------------------------------------------------------------------------------------------------------------
333 void SAL_CALL
DefaultGridColumnModel::removeContainerListener( const Reference
< XContainerListener
>& i_listener
) throw (RuntimeException
)
335 if ( i_listener
.is() )
336 m_aContainerListeners
.removeInterface( i_listener
);
339 //------------------------------------------------------------------------------------------------------------------
340 void SAL_CALL
DefaultGridColumnModel::disposing()
342 DefaultGridColumnModel_Base::disposing();
344 EventObject
aEvent( *this );
345 m_aContainerListeners
.disposeAndClear( aEvent
);
347 ::osl::MutexGuard
aGuard( m_aMutex
);
349 // remove, dispose and clear columns
350 while ( !m_aColumns
.empty() )
354 const Reference
< XComponent
> xColComponent( m_aColumns
[ 0 ], UNO_QUERY_THROW
);
355 xColComponent
->dispose();
357 catch( const Exception
& )
359 DBG_UNHANDLED_EXCEPTION();
362 m_aColumns
.erase( m_aColumns
.begin() );
366 m_aColumns
.swap( aEmpty
);
369 //------------------------------------------------------------------------------------------------------------------
370 Reference
< XCloneable
> SAL_CALL
DefaultGridColumnModel::createClone( ) throw (RuntimeException
)
372 ::comphelper::ComponentGuard
aGuard( *this, rBHelper
);
373 return new DefaultGridColumnModel( *this );
376 //......................................................................................................................
377 } // namespace toolkit
378 //......................................................................................................................
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
)
383 return ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
>( ( ::cppu::OWeakObject
* ) new ::toolkit::DefaultGridColumnModel( comphelper::getComponentContext(_rFactory
) ) );
385 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */