1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_toolkit.hxx"
30 
31 #include "gridcontrol.hxx"
32 #include "grideventforwarder.hxx"
33 
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <com/sun/star/view/SelectionType.hpp>
36 #include <com/sun/star/awt/grid/XGridDataModel.hpp>
37 #include <com/sun/star/awt/grid/XMutableGridDataModel.hpp>
38 #include <com/sun/star/awt/grid/DefaultGridDataModel.hpp>
39 #include <com/sun/star/awt/grid/SortableGridDataModel.hpp>
40 #include <com/sun/star/awt/grid/XGridColumnModel.hpp>
41 #include <toolkit/helper/unopropertyarrayhelper.hxx>
42 #include <toolkit/helper/property.hxx>
43 #include <com/sun/star/awt/XVclWindowPeer.hpp>
44 #include <comphelper/processfactory.hxx>
45 #include <tools/diagnose_ex.h>
46 #include <tools/color.hxx>
47 
48 using ::rtl::OUString;
49 using namespace ::com::sun::star;
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::awt;
52 using namespace ::com::sun::star::awt::grid;
53 using namespace ::com::sun::star::lang;
54 using namespace ::com::sun::star::beans;
55 using namespace ::com::sun::star::container;
56 using namespace ::com::sun::star::view;
57 using namespace ::com::sun::star::util;
58 
59 namespace toolkit
60 {
61 //======================================================================================================================
62 //= UnoGridModel
63 //======================================================================================================================
64 namespace
65 {
66     Reference< XGridDataModel > lcl_getDefaultDataModel_throw( ::comphelper::ComponentContext const & i_context )
67     {
68         Reference< XMutableGridDataModel > const xDelegatorModel( DefaultGridDataModel::create( i_context.getUNOContext() ), UNO_QUERY_THROW );
69         Reference< XGridDataModel > const xDataModel( SortableGridDataModel::create( i_context.getUNOContext(), xDelegatorModel ), UNO_QUERY_THROW );
70         return xDataModel;
71     }
72 
73     Reference< XGridColumnModel > lcl_getDefaultColumnModel_throw( ::comphelper::ComponentContext const & i_context )
74     {
75         Reference< XGridColumnModel > const xColumnModel( i_context.createComponent( "com.sun.star.awt.grid.DefaultGridColumnModel" ), UNO_QUERY_THROW );
76         return xColumnModel;
77     }
78 }
79 
80 //----------------------------------------------------------------------------------------------------------------------
81 UnoGridModel::UnoGridModel( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& i_factory )
82         :UnoControlModel( i_factory )
83 {
84 	ImplRegisterProperty( BASEPROPERTY_BACKGROUNDCOLOR );
85     ImplRegisterProperty( BASEPROPERTY_BORDER );
86 	ImplRegisterProperty( BASEPROPERTY_BORDERCOLOR );
87     ImplRegisterProperty( BASEPROPERTY_DEFAULTCONTROL );
88 	ImplRegisterProperty( BASEPROPERTY_ENABLED );
89 	ImplRegisterProperty( BASEPROPERTY_FILLCOLOR );
90     ImplRegisterProperty( BASEPROPERTY_HELPTEXT );
91 	ImplRegisterProperty( BASEPROPERTY_HELPURL );
92     ImplRegisterProperty( BASEPROPERTY_PRINTABLE );
93 	ImplRegisterProperty( BASEPROPERTY_SIZEABLE ); // resizeable
94 	ImplRegisterProperty( BASEPROPERTY_HSCROLL );
95 	ImplRegisterProperty( BASEPROPERTY_VSCROLL );
96 	ImplRegisterProperty( BASEPROPERTY_TABSTOP );
97 	ImplRegisterProperty( BASEPROPERTY_GRID_SHOWROWHEADER );
98 	ImplRegisterProperty( BASEPROPERTY_ROW_HEADER_WIDTH );
99 	ImplRegisterProperty( BASEPROPERTY_GRID_SHOWCOLUMNHEADER );
100 	ImplRegisterProperty( BASEPROPERTY_COLUMN_HEADER_HEIGHT );
101 	ImplRegisterProperty( BASEPROPERTY_ROW_HEIGHT );
102 	ImplRegisterProperty( BASEPROPERTY_GRID_DATAMODEL, makeAny( lcl_getDefaultDataModel_throw( maContext ) ) );
103 	ImplRegisterProperty( BASEPROPERTY_GRID_COLUMNMODEL, makeAny( lcl_getDefaultColumnModel_throw( maContext ) ) );
104 	ImplRegisterProperty( BASEPROPERTY_GRID_SELECTIONMODE );
105 	ImplRegisterProperty( BASEPROPERTY_FONTRELIEF );
106 	ImplRegisterProperty( BASEPROPERTY_FONTEMPHASISMARK );
107 	ImplRegisterProperty( BASEPROPERTY_FONTDESCRIPTOR );
108 	ImplRegisterProperty( BASEPROPERTY_TEXTCOLOR );
109 	ImplRegisterProperty( BASEPROPERTY_TEXTLINECOLOR );
110 	ImplRegisterProperty( BASEPROPERTY_USE_GRID_LINES );
111 	ImplRegisterProperty( BASEPROPERTY_GRID_LINE_COLOR );
112 	ImplRegisterProperty( BASEPROPERTY_GRID_HEADER_BACKGROUND );
113     ImplRegisterProperty( BASEPROPERTY_GRID_HEADER_TEXT_COLOR );
114     ImplRegisterProperty( BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS );
115     ImplRegisterProperty( BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR );
116     ImplRegisterProperty( BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR );
117     ImplRegisterProperty( BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR );
118     ImplRegisterProperty( BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR );
119 	ImplRegisterProperty( BASEPROPERTY_VERTICALALIGN );
120 }
121 
122 //----------------------------------------------------------------------------------------------------------------------
123 UnoGridModel::UnoGridModel( const UnoGridModel& rModel )
124     :UnoControlModel( rModel )
125 {
126     osl_incrementInterlockedCount( &m_refCount );
127     {
128         Reference< XGridDataModel > xDataModel;
129         // clone the data model
130         const Reference< XFastPropertySet > xCloneSource( &const_cast< UnoGridModel& >( rModel ) );
131         try
132         {
133             const Reference< XCloneable > xCloneable( xCloneSource->getFastPropertyValue( BASEPROPERTY_GRID_DATAMODEL ), UNO_QUERY_THROW );
134             xDataModel.set( xCloneable->createClone(), UNO_QUERY_THROW );
135         }
136         catch( const Exception& )
137         {
138     	    DBG_UNHANDLED_EXCEPTION();
139         }
140         if ( !xDataModel.is() )
141             xDataModel = lcl_getDefaultDataModel_throw( maContext );
142         UnoControlModel::setFastPropertyValue_NoBroadcast( BASEPROPERTY_GRID_DATAMODEL, makeAny( xDataModel ) );
143             // do *not* use setFastPropertyValue here: The UnoControlModel ctor did a simple copy of all property values,
144             // so before this call here, we share our data model with the own of the clone source. setFastPropertyValue,
145             // then, disposes the old data model - which means the data model which in fact belongs to the clone source.
146             // so, call the UnoControlModel's impl-method for setting the value.
147 
148         // clone the column model
149         Reference< XGridColumnModel > xColumnModel;
150         try
151         {
152             const Reference< XCloneable > xCloneable( xCloneSource->getFastPropertyValue( BASEPROPERTY_GRID_COLUMNMODEL ), UNO_QUERY_THROW );
153             xColumnModel.set( xCloneable->createClone(), UNO_QUERY_THROW );
154         }
155         catch( const Exception& )
156         {
157     	    DBG_UNHANDLED_EXCEPTION();
158         }
159         if ( !xColumnModel.is() )
160             xColumnModel = lcl_getDefaultColumnModel_throw( maContext );
161         UnoControlModel::setFastPropertyValue_NoBroadcast( BASEPROPERTY_GRID_COLUMNMODEL, makeAny( xColumnModel ) );
162             // same comment as above: do not use our own setPropertyValue here.
163     }
164     osl_decrementInterlockedCount( &m_refCount );
165 }
166 
167 //----------------------------------------------------------------------------------------------------------------------
168 UnoControlModel* UnoGridModel::Clone() const
169 {
170 	return new UnoGridModel( *this );
171 }
172 
173 //----------------------------------------------------------------------------------------------------------------------
174 namespace
175 {
176     void lcl_dispose_nothrow( const Any& i_component )
177     {
178         try
179         {
180             const Reference< XComponent > xComponent( i_component, UNO_QUERY_THROW );
181             xComponent->dispose();
182         }
183         catch( const Exception& )
184         {
185         	DBG_UNHANDLED_EXCEPTION();
186         }
187     }
188 }
189 
190 //----------------------------------------------------------------------------------------------------------------------
191 void SAL_CALL UnoGridModel::dispose(  ) throw(RuntimeException)
192 {
193     lcl_dispose_nothrow( getFastPropertyValue( BASEPROPERTY_GRID_COLUMNMODEL ) );
194     lcl_dispose_nothrow( getFastPropertyValue( BASEPROPERTY_GRID_DATAMODEL ) );
195 
196     UnoControlModel::dispose();
197 }
198 
199 //----------------------------------------------------------------------------------------------------------------------
200 void SAL_CALL UnoGridModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception)
201 {
202     Any aOldSubModel;
203     if ( ( nHandle == BASEPROPERTY_GRID_COLUMNMODEL ) || ( nHandle == BASEPROPERTY_GRID_DATAMODEL ) )
204     {
205         aOldSubModel = getFastPropertyValue( nHandle );
206         if ( aOldSubModel == rValue )
207         {
208             OSL_ENSURE( false, "UnoGridModel::setFastPropertyValue_NoBroadcast: setting the same value, again!" );
209                 // shouldn't this have been caught by convertFastPropertyValue?
210             aOldSubModel.clear();
211         }
212     }
213 
214     UnoControlModel::setFastPropertyValue_NoBroadcast( nHandle, rValue );
215 
216     if ( aOldSubModel.hasValue() )
217         lcl_dispose_nothrow( aOldSubModel );
218 }
219 
220 //----------------------------------------------------------------------------------------------------------------------
221 OUString UnoGridModel::getServiceName() throw(RuntimeException)
222 {
223 	return OUString::createFromAscii( szServiceName_GridControlModel );
224 }
225 
226 //----------------------------------------------------------------------------------------------------------------------
227 Any UnoGridModel::ImplGetDefaultValue( sal_uInt16 nPropId ) const
228 {
229 	switch( nPropId )
230 	{
231 		case BASEPROPERTY_DEFAULTCONTROL:
232 			return uno::makeAny( ::rtl::OUString::createFromAscii( szServiceName_GridControl ) );
233 		case BASEPROPERTY_GRID_SELECTIONMODE:
234 			return uno::makeAny( SelectionType(1) );
235 		case BASEPROPERTY_GRID_SHOWROWHEADER:
236         case BASEPROPERTY_USE_GRID_LINES:
237 			return uno::makeAny( (sal_Bool)sal_False );
238         case BASEPROPERTY_ROW_HEADER_WIDTH:
239             return uno::makeAny( sal_Int32( 10 ) );
240 		case BASEPROPERTY_GRID_SHOWCOLUMNHEADER:
241 			return uno::makeAny( (sal_Bool)sal_True );
242         case BASEPROPERTY_COLUMN_HEADER_HEIGHT:
243         case BASEPROPERTY_ROW_HEIGHT:
244 		case BASEPROPERTY_GRID_HEADER_BACKGROUND:
245         case BASEPROPERTY_GRID_HEADER_TEXT_COLOR:
246 		case BASEPROPERTY_GRID_LINE_COLOR:
247         case BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS:
248         case BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR:
249         case BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR:
250         case BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR:
251         case BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR:
252             return Any();
253 		default:
254 			return UnoControlModel::ImplGetDefaultValue( nPropId );
255 	}
256 
257 }
258 
259 //----------------------------------------------------------------------------------------------------------------------
260 ::cppu::IPropertyArrayHelper& UnoGridModel::getInfoHelper()
261 {
262 	static UnoPropertyArrayHelper* pHelper = NULL;
263 	if ( !pHelper )
264 	{
265 		Sequence<sal_Int32>	aIDs = ImplGetPropertyIds();
266 		pHelper = new UnoPropertyArrayHelper( aIDs );
267 	}
268 	return *pHelper;
269 }
270 
271 //----------------------------------------------------------------------------------------------------------------------
272 // XMultiPropertySet
273 Reference< XPropertySetInfo > UnoGridModel::getPropertySetInfo(  ) throw(RuntimeException)
274 {
275 	static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
276 	return xInfo;
277 }
278 
279 
280 //======================================================================================================================
281 //= UnoGridControl
282 //======================================================================================================================
283 UnoGridControl::UnoGridControl( const Reference< XMultiServiceFactory >& i_factory )
284     :UnoGridControl_Base( i_factory )
285     ,mSelectionMode(SelectionType(1))
286 	,m_aSelectionListeners( *this )
287     ,m_pEventForwarder( new GridEventForwarder( *this ) )
288 {
289 }
290 
291 //----------------------------------------------------------------------------------------------------------------------
292 UnoGridControl::~UnoGridControl()
293 {
294 }
295 
296 //----------------------------------------------------------------------------------------------------------------------
297 OUString UnoGridControl::GetComponentServiceName()
298 {
299 	return OUString::createFromAscii( "Grid" );
300 }
301 
302 //----------------------------------------------------------------------------------------------------------------------
303 void SAL_CALL UnoGridControl::dispose(  ) throw(RuntimeException)
304 {
305 	lang::EventObject aEvt;
306 	aEvt.Source = (::cppu::OWeakObject*)this;
307 	m_aSelectionListeners.disposeAndClear( aEvt );
308 	UnoControl::dispose();
309 }
310 
311 //----------------------------------------------------------------------------------------------------------------------
312 void SAL_CALL UnoGridControl::createPeer( const uno::Reference< awt::XToolkit > & rxToolkit, const uno::Reference< awt::XWindowPeer >  & rParentPeer ) throw(uno::RuntimeException)
313 {
314 	UnoControlBase::createPeer( rxToolkit, rParentPeer );
315 
316 	const Reference< XGridRowSelection > xGrid( getPeer(), UNO_QUERY_THROW );
317 	xGrid->addSelectionListener( &m_aSelectionListeners );
318 }
319 
320 //----------------------------------------------------------------------------------------------------------------------
321 namespace
322 {
323     void lcl_setEventForwarding( const Reference< XControlModel >& i_gridControlModel, const ::boost::scoped_ptr< GridEventForwarder >& i_listener,
324         bool const i_add )
325     {
326         const Reference< XPropertySet > xModelProps( i_gridControlModel, UNO_QUERY );
327         if ( !xModelProps.is() )
328             return;
329 
330         try
331         {
332             Reference< XContainer > const xColModel(
333                 xModelProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ColumnModel" ) ) ),
334                 UNO_QUERY_THROW );
335             if ( i_add )
336                 xColModel->addContainerListener( i_listener.get() );
337             else
338                 xColModel->removeContainerListener( i_listener.get() );
339 
340             Reference< XGridDataModel > const xDataModel(
341                 xModelProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "GridDataModel" ) ) ),
342                 UNO_QUERY_THROW
343             );
344             Reference< XMutableGridDataModel > const xMutableDataModel( xDataModel, UNO_QUERY );
345             if ( xMutableDataModel.is() )
346             {
347                 if ( i_add )
348                     xMutableDataModel->addGridDataListener( i_listener.get() );
349                 else
350                     xMutableDataModel->removeGridDataListener( i_listener.get() );
351             }
352         }
353         catch( const Exception& )
354         {
355 	        DBG_UNHANDLED_EXCEPTION();
356         }
357     }
358 }
359 
360 //----------------------------------------------------------------------------------------------------------------------
361 sal_Bool SAL_CALL UnoGridControl::setModel( const Reference< XControlModel >& i_model ) throw(RuntimeException)
362 {
363     lcl_setEventForwarding( getModel(), m_pEventForwarder, false );
364     if ( !UnoGridControl_Base::setModel( i_model ) )
365         return sal_False;
366     lcl_setEventForwarding( getModel(), m_pEventForwarder, true );
367     return sal_True;
368 }
369 
370 //----------------------------------------------------------------------------------------------------------------------
371 ::sal_Int32 UnoGridControl::getRowAtPoint(::sal_Int32 x, ::sal_Int32 y) throw (::com::sun::star::uno::RuntimeException)
372 {
373 	Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
374 	return xGrid->getRowAtPoint( x, y );
375 }
376 
377 //----------------------------------------------------------------------------------------------------------------------
378 ::sal_Int32 UnoGridControl::getColumnAtPoint(::sal_Int32 x, ::sal_Int32 y) throw (::com::sun::star::uno::RuntimeException)
379 {
380 	Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
381 	return xGrid->getColumnAtPoint( x, y );
382 }
383 
384 //----------------------------------------------------------------------------------------------------------------------
385 ::sal_Int32 SAL_CALL UnoGridControl::getCurrentColumn(  ) throw (RuntimeException)
386 {
387 	Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
388 	return xGrid->getCurrentColumn();
389 }
390 
391 //----------------------------------------------------------------------------------------------------------------------
392 ::sal_Int32 SAL_CALL UnoGridControl::getCurrentRow(  ) throw (RuntimeException)
393 {
394 	Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
395 	return xGrid->getCurrentRow();
396 }
397 
398 //----------------------------------------------------------------------------------------------------------------------
399 void SAL_CALL UnoGridControl::goToCell( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex ) throw (RuntimeException, IndexOutOfBoundsException, VetoException)
400 {
401 	Reference< XGridControl > const xGrid ( getPeer(), UNO_QUERY_THROW );
402 	xGrid->goToCell( i_columnIndex, i_rowIndex );
403 }
404 
405 //----------------------------------------------------------------------------------------------------------------------
406 void SAL_CALL UnoGridControl::selectRow( ::sal_Int32 i_rowIndex ) throw (RuntimeException, IndexOutOfBoundsException )
407 {
408 	Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->selectRow( i_rowIndex );
409 }
410 
411 //----------------------------------------------------------------------------------------------------------------------
412 void SAL_CALL UnoGridControl::selectAllRows() throw (::com::sun::star::uno::RuntimeException)
413 {
414 	Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->selectAllRows();
415 }
416 
417 //----------------------------------------------------------------------------------------------------------------------
418 void SAL_CALL UnoGridControl::deselectRow( ::sal_Int32 i_rowIndex ) throw (RuntimeException, IndexOutOfBoundsException )
419 {
420 	Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->deselectRow( i_rowIndex );
421 }
422 
423 //----------------------------------------------------------------------------------------------------------------------
424 void SAL_CALL UnoGridControl::deselectAllRows() throw (::com::sun::star::uno::RuntimeException)
425 {
426 	Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->deselectAllRows();
427 }
428 
429 //----------------------------------------------------------------------------------------------------------------------
430 ::com::sun::star::uno::Sequence< ::sal_Int32 > SAL_CALL UnoGridControl::getSelectedRows() throw (::com::sun::star::uno::RuntimeException)
431 {
432 	return Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->getSelectedRows();
433 }
434 
435 //----------------------------------------------------------------------------------------------------------------------
436 ::sal_Bool SAL_CALL UnoGridControl::hasSelectedRows() throw (::com::sun::star::uno::RuntimeException)
437 {
438 	return Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->hasSelectedRows();
439 }
440 
441 //----------------------------------------------------------------------------------------------------------------------
442 ::sal_Bool SAL_CALL UnoGridControl::isRowSelected(::sal_Int32 index) throw (::com::sun::star::uno::RuntimeException)
443 {
444 	return Reference< XGridRowSelection >( getPeer(), UNO_QUERY_THROW )->isRowSelected( index );
445 }
446 
447 //----------------------------------------------------------------------------------------------------------------------
448 void SAL_CALL UnoGridControl::addSelectionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridSelectionListener > & listener) throw (::com::sun::star::uno::RuntimeException)
449 {
450 	m_aSelectionListeners.addInterface( listener );
451 }
452 
453 //----------------------------------------------------------------------------------------------------------------------
454 void SAL_CALL UnoGridControl::removeSelectionListener(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::grid::XGridSelectionListener > & listener) throw (::com::sun::star::uno::RuntimeException)
455 {
456 	m_aSelectionListeners.removeInterface( listener );
457 }
458 
459 }//namespace toolkit
460 
461 Reference< XInterface > SAL_CALL GridControl_CreateInstance( const Reference< XMultiServiceFactory >& i_factory )
462 {
463 	return Reference < XInterface >( ( ::cppu::OWeakObject* ) new ::toolkit::UnoGridControl( i_factory ) );
464 }
465 
466 Reference< XInterface > SAL_CALL GridControlModel_CreateInstance( const Reference< XMultiServiceFactory >& i_factory )
467 {
468 	return Reference < XInterface >( ( ::cppu::OWeakObject* ) new ::toolkit::UnoGridModel( i_factory ) );
469 }
470