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 // MARKER(update_precomp.py): autogen include statement, do not remove
28 #include "precompiled_svtools.hxx"
29 
30 #include "svtxgridcontrol.hxx"
31 #include <com/sun/star/view/SelectionType.hpp>
32 #include "svtools/table/tablecontrolinterface.hxx"
33 #include "svtools/table/gridtablerenderer.hxx"
34 #include "svtools/table/tablecontrol.hxx"
35 #include "unocontroltablemodel.hxx"
36 #include <comphelper/sequence.hxx>
37 #include <rtl/ref.hxx>
38 #include <tools/diagnose_ex.h>
39 #include <toolkit/helper/property.hxx>
40 #include <toolkit/helper/vclunohelper.hxx>
41 #include <comphelper/processfactory.hxx>
42 #include <com/sun/star/awt/grid/XGridColumn.hpp>
43 #include <com/sun/star/awt/XControl.hpp>
44 #include <com/sun/star/awt/grid/GridInvalidDataException.hpp>
45 #include <com/sun/star/awt/grid/GridInvalidModelException.hpp>
46 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
47 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
48 #include <com/sun/star/util/Color.hpp>
49 #include <com/sun/star/awt/FontDescriptor.hpp>
50 
51 /** === begin UNO using === **/
52 using ::com::sun::star::uno::RuntimeException;
53 using ::com::sun::star::uno::Reference;
54 using ::com::sun::star::uno::Exception;
55 using ::com::sun::star::uno::UNO_QUERY;
56 using ::com::sun::star::uno::UNO_QUERY_THROW;
57 using ::com::sun::star::uno::Any;
58 using ::com::sun::star::uno::makeAny;
59 using ::com::sun::star::uno::Sequence;
60 using ::com::sun::star::awt::grid::XGridSelectionListener;
61 using ::com::sun::star::style::VerticalAlignment;
62 using ::com::sun::star::style::VerticalAlignment_TOP;
63 using ::com::sun::star::view::SelectionType;
64 using ::com::sun::star::view::SelectionType_NONE;
65 using ::com::sun::star::view::SelectionType_RANGE;
66 using ::com::sun::star::view::SelectionType_SINGLE;
67 using ::com::sun::star::view::SelectionType_MULTI;
68 using ::com::sun::star::awt::grid::XGridDataModel;
69 using ::com::sun::star::awt::grid::GridInvalidDataException;
70 using ::com::sun::star::lang::EventObject;
71 using ::com::sun::star::lang::IndexOutOfBoundsException;
72 using ::com::sun::star::awt::grid::XGridColumnModel;
73 using ::com::sun::star::awt::grid::GridSelectionEvent;
74 using ::com::sun::star::awt::grid::XGridColumn;
75 using ::com::sun::star::container::ContainerEvent;
76 using ::com::sun::star::awt::grid::GridDataEvent;
77 using ::com::sun::star::awt::grid::GridInvalidModelException;
78 using ::com::sun::star::util::VetoException;
79 /** === end UNO using === **/
80 
81 namespace AccessibleEventId = ::com::sun::star::accessibility::AccessibleEventId;
82 namespace AccessibleStateType = ::com::sun::star::accessibility::AccessibleStateType;
83 
84 using namespace ::svt::table;
85 
86 typedef ::com::sun::star::util::Color   UnoColor;
87 
88 // ---------------------------------------------------------------------------------------------------------------------
89 SVTXGridControl::SVTXGridControl()
90     :m_pTableModel( new UnoControlTableModel() )
91     ,m_bTableModelInitCompleted( false )
92 	,m_aSelectionListeners( *this )
93 {
94 }
95 
96 // ---------------------------------------------------------------------------------------------------------------------
97 SVTXGridControl::~SVTXGridControl()
98 {
99 }
100 
101 // ---------------------------------------------------------------------------------------------------------------------
102 void SVTXGridControl::SetWindow( Window* pWindow )
103 {
104     SVTXGridControl_Base::SetWindow( pWindow );
105     impl_checkTableModelInit();
106 }
107 
108 // ---------------------------------------------------------------------------------------------------------------------
109 void SVTXGridControl::impl_checkColumnIndex_throw( ::svt::table::TableControl const & i_table, sal_Int32 const i_columnIndex ) const
110 {
111     if ( ( i_columnIndex < 0 ) || ( i_columnIndex >= i_table.GetColumnCount() ) )
112         throw IndexOutOfBoundsException( ::rtl::OUString(), *const_cast< SVTXGridControl* >( this ) );
113 }
114 
115 // ---------------------------------------------------------------------------------------------------------------------
116 void SVTXGridControl::impl_checkRowIndex_throw( ::svt::table::TableControl const & i_table, sal_Int32 const i_rowIndex ) const
117 {
118     if ( ( i_rowIndex < 0 ) || ( i_rowIndex >= i_table.GetRowCount() ) )
119         throw IndexOutOfBoundsException( ::rtl::OUString(), *const_cast< SVTXGridControl* >( this ) );
120 }
121 
122 // ---------------------------------------------------------------------------------------------------------------------
123 sal_Int32 SAL_CALL SVTXGridControl::getRowAtPoint(::sal_Int32 x, ::sal_Int32 y) throw (RuntimeException)
124 {
125     ::vos::OGuard aGuard( GetMutex() );
126 
127 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
128     ENSURE_OR_RETURN( pTable != NULL, "SVTXGridControl::getRowAtPoint: no control (anymore)!", -1 );
129 
130     TableCell const tableCell = pTable->getTableControlInterface().hitTest( Point( x, y ) );
131     return ( tableCell.nRow >= 0 ) ? tableCell.nRow : -1;
132 }
133 
134 // ---------------------------------------------------------------------------------------------------------------------
135 sal_Int32 SAL_CALL SVTXGridControl::getColumnAtPoint(::sal_Int32 x, ::sal_Int32 y) throw (RuntimeException)
136 {
137     ::vos::OGuard aGuard( GetMutex() );
138 
139 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
140     ENSURE_OR_RETURN( pTable != NULL, "SVTXGridControl::getColumnAtPoint: no control (anymore)!", -1 );
141 
142     TableCell const tableCell = pTable->getTableControlInterface().hitTest( Point( x, y ) );
143     return ( tableCell.nColumn >= 0 ) ? tableCell.nColumn : -1;
144 }
145 
146 // ---------------------------------------------------------------------------------------------------------------------
147 sal_Int32 SAL_CALL SVTXGridControl::getCurrentColumn(  ) throw (RuntimeException)
148 {
149     ::vos::OGuard aGuard( GetMutex() );
150 
151 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
152     ENSURE_OR_RETURN( pTable != NULL, "SVTXGridControl::getCurrentColumn: no control (anymore)!", -1 );
153 
154     sal_Int32 const nColumn = pTable->GetCurrentColumn();
155     return ( nColumn >= 0 ) ? nColumn : -1;
156 }
157 
158 // ---------------------------------------------------------------------------------------------------------------------
159 sal_Int32 SAL_CALL SVTXGridControl::getCurrentRow(  ) throw (RuntimeException)
160 {
161     ::vos::OGuard aGuard( GetMutex() );
162 
163 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
164     ENSURE_OR_RETURN( pTable != NULL, "SVTXGridControl::getCurrentRow: no control (anymore)!", -1 );
165 
166     sal_Int32 const nRow = pTable->GetCurrentRow();
167     return ( nRow >= 0 ) ? nRow : -1;
168 }
169 
170 //----------------------------------------------------------------------------------------------------------------------
171 void SAL_CALL SVTXGridControl::goToCell( ::sal_Int32 i_columnIndex, ::sal_Int32 i_rowIndex ) throw (RuntimeException, IndexOutOfBoundsException, VetoException)
172 {
173     ::vos::OGuard aGuard( GetMutex() );
174 
175 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
176     ENSURE_OR_RETURN_VOID( pTable != NULL, "SVTXGridControl::getCurrentRow: no control (anymore)!" );
177 
178     impl_checkColumnIndex_throw( *pTable, i_columnIndex );
179     impl_checkRowIndex_throw( *pTable, i_rowIndex );
180 
181     pTable->GoTo( i_columnIndex, i_rowIndex );
182 }
183 
184 // ---------------------------------------------------------------------------------------------------------------------
185 void SAL_CALL SVTXGridControl::addSelectionListener(const Reference< XGridSelectionListener > & listener) throw (RuntimeException)
186 {
187 	m_aSelectionListeners.addInterface(listener);
188 }
189 
190 // ---------------------------------------------------------------------------------------------------------------------
191 void SAL_CALL SVTXGridControl::removeSelectionListener(const Reference< XGridSelectionListener > & listener) throw (RuntimeException)
192 {
193 	m_aSelectionListeners.removeInterface(listener);
194 }
195 
196 // ---------------------------------------------------------------------------------------------------------------------
197 void SVTXGridControl::setProperty( const ::rtl::OUString& PropertyName, const Any& aValue) throw(RuntimeException)
198 {
199 	::vos::OGuard aGuard( GetMutex() );
200 
201 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
202     ENSURE_OR_RETURN_VOID( pTable != NULL, "SVTXGridControl::setProperty: no control (anymore)!" );
203 
204 	switch( GetPropertyId( PropertyName ) )
205 	{
206         case BASEPROPERTY_ROW_HEADER_WIDTH:
207 	    {
208 		    sal_Int32 rowHeaderWidth( -1 );
209 		    aValue >>= rowHeaderWidth;
210             ENSURE_OR_BREAK( rowHeaderWidth > 0, "SVTXGridControl::setProperty: illegal row header width!" );
211 		    m_pTableModel->setRowHeaderWidth( rowHeaderWidth );
212             // TODO: the model should broadcast this change itself, and the table should invalidate itself as needed
213 		    pTable->Invalidate();
214 	    }
215         break;
216 
217         case BASEPROPERTY_COLUMN_HEADER_HEIGHT:
218         {
219             sal_Int32 columnHeaderHeight = 0;
220             if ( !aValue.hasValue() )
221             {
222 			    columnHeaderHeight = pTable->PixelToLogic( Size( 0, pTable->GetTextHeight() + 3 ), MAP_APPFONT ).Height();
223             }
224 			else
225             {
226                 aValue >>= columnHeaderHeight;
227             }
228             ENSURE_OR_BREAK( columnHeaderHeight > 0, "SVTXGridControl::setProperty: illegal column header height!" );
229 			m_pTableModel->setColumnHeaderHeight( columnHeaderHeight );
230             // TODO: the model should broadcast this change itself, and the table should invalidate itself as needed
231 		    pTable->Invalidate();
232         }
233         break;
234 
235         case BASEPROPERTY_USE_GRID_LINES:
236         {
237             GridTableRenderer* pGridRenderer = dynamic_cast< GridTableRenderer* >(
238                 m_pTableModel->getRenderer().get() );
239             ENSURE_OR_BREAK( pGridRenderer != NULL, "SVTXGridControl::setProperty(UseGridLines): invalid renderer!" );
240             sal_Bool bUseGridLines = sal_False;
241             OSL_VERIFY( aValue >>= bUseGridLines );
242             pGridRenderer->useGridLines( bUseGridLines );
243             pTable->Invalidate();
244         }
245         break;
246 
247         case BASEPROPERTY_ROW_HEIGHT:
248         {
249             sal_Int32 rowHeight = 0;
250             if ( !aValue.hasValue() )
251             {
252 			    rowHeight = pTable->PixelToLogic( Size( 0, pTable->GetTextHeight() + 3 ), MAP_APPFONT ).Height();
253             }
254             else
255             {
256                 aValue >>= rowHeight;
257             }
258 			m_pTableModel->setRowHeight( rowHeight );
259             ENSURE_OR_BREAK( rowHeight > 0, "SVTXGridControl::setProperty: illegal row height!" );
260             // TODO: the model should broadcast this change itself, and the table should invalidate itself as needed
261             pTable->Invalidate();
262         }
263         break;
264 
265 		case BASEPROPERTY_BACKGROUNDCOLOR:
266         {
267             // let the base class handle this for the TableControl
268             VCLXWindow::setProperty( PropertyName, aValue );
269             // and forward to the grid control's data window
270             if ( pTable->IsBackground() )
271                 pTable->getDataWindow().SetBackground( pTable->GetBackground() );
272             else
273                 pTable->getDataWindow().SetBackground();
274         }
275         break;
276 
277 		case BASEPROPERTY_GRID_SELECTIONMODE:
278 		{
279 			SelectionType eSelectionType;
280 			if( aValue >>= eSelectionType )
281 			{
282 				SelectionMode eSelMode;
283 				switch( eSelectionType )
284 				{
285 				case SelectionType_SINGLE:	eSelMode = SINGLE_SELECTION; break;
286 				case SelectionType_RANGE:	eSelMode = RANGE_SELECTION; break;
287 				case SelectionType_MULTI:	eSelMode = MULTIPLE_SELECTION; break;
288 				default:					eSelMode = NO_SELECTION; break;
289 				}
290 				if( pTable->getSelEngine()->GetSelectionMode() != eSelMode )
291 					pTable->getSelEngine()->SetSelectionMode( eSelMode );
292 			}
293 			break;
294 		}
295 		case BASEPROPERTY_HSCROLL:
296 		{
297 			sal_Bool bHScroll = true;
298 			if( aValue >>= bHScroll )
299 				m_pTableModel->setHorizontalScrollbarVisibility( bHScroll ? ScrollbarShowAlways : ScrollbarShowSmart );
300 			break;
301 		}
302 
303 		case BASEPROPERTY_VSCROLL:
304 		{
305 			sal_Bool bVScroll = true;
306 			if( aValue >>= bVScroll )
307 			{
308                 m_pTableModel->setVerticalScrollbarVisibility( bVScroll ? ScrollbarShowAlways : ScrollbarShowSmart );
309 			}
310 			break;
311 		}
312 
313 		case BASEPROPERTY_GRID_SHOWROWHEADER:
314 		{
315 			sal_Bool rowHeader = true;
316 			if( aValue >>= rowHeader )
317 			{
318 				m_pTableModel->setRowHeaders(rowHeader);
319 			}
320 			break;
321 		}
322 
323         case BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS:
324             m_pTableModel->setRowBackgroundColors( aValue );
325             pTable->Invalidate();
326             break;
327 
328         case BASEPROPERTY_GRID_LINE_COLOR:
329             m_pTableModel->setLineColor( aValue );
330             pTable->Invalidate();
331 			break;
332 
333         case BASEPROPERTY_GRID_HEADER_BACKGROUND:
334             m_pTableModel->setHeaderBackgroundColor( aValue );
335             pTable->Invalidate();
336 			break;
337 
338 		case BASEPROPERTY_GRID_HEADER_TEXT_COLOR:
339             m_pTableModel->setHeaderTextColor( aValue );
340             pTable->Invalidate();
341 			break;
342 
343 		case BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR:
344             m_pTableModel->setActiveSelectionBackColor( aValue );
345             pTable->Invalidate();
346 			break;
347 
348 		case BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR:
349             m_pTableModel->setInactiveSelectionBackColor( aValue );
350             pTable->Invalidate();
351 			break;
352 
353 		case BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR:
354             m_pTableModel->setActiveSelectionTextColor( aValue );
355             pTable->Invalidate();
356 			break;
357 
358         case BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR:
359             m_pTableModel->setInactiveSelectionTextColor( aValue );
360             pTable->Invalidate();
361 			break;
362 
363 
364 		case BASEPROPERTY_TEXTCOLOR:
365             m_pTableModel->setTextColor( aValue );
366             pTable->Invalidate();
367 			break;
368 
369 		case BASEPROPERTY_TEXTLINECOLOR:
370             m_pTableModel->setTextLineColor( aValue );
371             pTable->Invalidate();
372 			break;
373 
374         case BASEPROPERTY_VERTICALALIGN:
375 		{
376 			VerticalAlignment eAlign( VerticalAlignment_TOP );
377 			if ( aValue >>= eAlign )
378                 m_pTableModel->setVerticalAlign( eAlign );
379 			break;
380 		}
381 
382 		case BASEPROPERTY_GRID_SHOWCOLUMNHEADER:
383 		{
384 			sal_Bool colHeader = true;
385 			if( aValue >>= colHeader )
386 			{
387 				m_pTableModel->setColumnHeaders(colHeader);
388 			}
389 			break;
390 		}
391 		case BASEPROPERTY_GRID_DATAMODEL:
392 		{
393             Reference< XGridDataModel > const xDataModel( aValue, UNO_QUERY );
394 			if ( !xDataModel.is() )
395                 throw GridInvalidDataException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid data model." ) ), *this );
396 
397             m_pTableModel->setDataModel( xDataModel );
398             impl_checkTableModelInit();
399 		}
400 		break;
401 
402         case BASEPROPERTY_GRID_COLUMNMODEL:
403 		{
404             // obtain new col model
405             Reference< XGridColumnModel > const xColumnModel( aValue, UNO_QUERY );
406             if ( !xColumnModel.is() )
407                 throw GridInvalidModelException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid column model." ) ), *this );
408 
409             // remove all old columns
410             m_pTableModel->removeAllColumns();
411 
412             // announce to the TableModel
413             m_pTableModel->setColumnModel( xColumnModel );
414             impl_checkTableModelInit();
415 
416             // add new columns
417             impl_updateColumnsFromModel_nothrow();
418             break;
419 		}
420 		default:
421 			VCLXWindow::setProperty( PropertyName, aValue );
422 		break;
423 	}
424 }
425 
426 
427 void SVTXGridControl::impl_checkTableModelInit()
428 {
429     if ( !m_bTableModelInitCompleted && m_pTableModel->hasColumnModel() && m_pTableModel->hasDataModel() )
430     {
431         TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
432         if ( pTable )
433         {
434             pTable->SetModel( PTableModel( m_pTableModel ) );
435 
436             m_bTableModelInitCompleted = true;
437 
438             // ensure default columns exist, if they have not previously been added
439             Reference< XGridDataModel > const xDataModel( m_pTableModel->getDataModel(), UNO_QUERY_THROW );
440             Reference< XGridColumnModel > const xColumnModel( m_pTableModel->getColumnModel(), UNO_QUERY_THROW );
441 
442             sal_Int32 const nDataColumnCount = xDataModel->getColumnCount();
443             if ( ( nDataColumnCount > 0 ) && ( xColumnModel->getColumnCount() == 0 ) )
444 				xColumnModel->setDefaultColumns( nDataColumnCount );
445                 // this will trigger notifications, which in turn will let us update our m_pTableModel
446         }
447     }
448 }
449 
450 namespace
451 {
452     void lcl_convertColor( ::boost::optional< ::Color > const & i_color, Any & o_colorValue )
453     {
454         if ( !i_color )
455             o_colorValue.clear();
456         else
457             o_colorValue <<= i_color->GetColor();
458     }
459 }
460 
461 Any SVTXGridControl::getProperty( const ::rtl::OUString& PropertyName ) throw(RuntimeException)
462 {
463 	::vos::OGuard aGuard( GetMutex() );
464 
465 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
466     ENSURE_OR_RETURN( pTable != NULL, "SVTXGridControl::getProperty: no control (anymore)!", Any() );
467 
468     Any aPropertyValue;
469 
470 	const sal_uInt16 nPropId = GetPropertyId( PropertyName );
471 	switch(nPropId)
472 	{
473 	case BASEPROPERTY_GRID_SELECTIONMODE:
474 	{
475 		SelectionType eSelectionType;
476 
477 		SelectionMode eSelMode = pTable->getSelEngine()->GetSelectionMode();
478 		switch( eSelMode )
479 		{
480 			case SINGLE_SELECTION:	eSelectionType = SelectionType_SINGLE; break;
481 			case RANGE_SELECTION:	eSelectionType = SelectionType_RANGE; break;
482 			case MULTIPLE_SELECTION:eSelectionType = SelectionType_MULTI; break;
483 			default:				eSelectionType = SelectionType_NONE; break;
484 		}
485 		aPropertyValue <<= eSelectionType;
486         break;
487 	}
488 
489 	case BASEPROPERTY_GRID_SHOWROWHEADER:
490 		aPropertyValue <<=  sal_Bool( m_pTableModel->hasRowHeaders() );
491         break;
492 
493     case BASEPROPERTY_GRID_SHOWCOLUMNHEADER:
494 		aPropertyValue <<=  sal_Bool( m_pTableModel->hasColumnHeaders() );
495         break;
496 
497     case BASEPROPERTY_GRID_DATAMODEL:
498 		aPropertyValue <<= m_pTableModel->getDataModel();
499         break;
500 
501     case BASEPROPERTY_GRID_COLUMNMODEL:
502 		aPropertyValue <<= m_pTableModel->getColumnModel();
503         break;
504 
505     case BASEPROPERTY_HSCROLL:
506         {
507             sal_Bool const bHasScrollbar = ( m_pTableModel->getHorizontalScrollbarVisibility() != ScrollbarShowNever );
508             aPropertyValue <<= bHasScrollbar;
509             break;
510         }
511 
512     case BASEPROPERTY_VSCROLL:
513         {
514             sal_Bool const bHasScrollbar = ( m_pTableModel->getVerticalScrollbarVisibility() != ScrollbarShowNever );
515             aPropertyValue <<= bHasScrollbar;
516             break;
517         }
518 
519     case BASEPROPERTY_USE_GRID_LINES:
520     {
521         GridTableRenderer* pGridRenderer = dynamic_cast< GridTableRenderer* >(
522             m_pTableModel->getRenderer().get() );
523         ENSURE_OR_BREAK( pGridRenderer != NULL, "SVTXGridControl::getProperty(UseGridLines): invalid renderer!" );
524         aPropertyValue <<= pGridRenderer->useGridLines();
525     }
526     break;
527 
528     case BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS:
529     {
530         ::boost::optional< ::std::vector< ::Color > > aColors( m_pTableModel->getRowBackgroundColors() );
531         if ( !aColors )
532             aPropertyValue.clear();
533         else
534         {
535             Sequence< UnoColor > aAPIColors( aColors->size() );
536             for ( size_t i=0; i<aColors->size(); ++i )
537             {
538                 aAPIColors[i] = aColors->at(i).GetColor();
539             }
540             aPropertyValue <<= aAPIColors;
541         }
542     }
543     break;
544 
545     case BASEPROPERTY_GRID_LINE_COLOR:
546         lcl_convertColor( m_pTableModel->getLineColor(), aPropertyValue );
547 		break;
548 
549     case BASEPROPERTY_GRID_HEADER_BACKGROUND:
550         lcl_convertColor( m_pTableModel->getHeaderBackgroundColor(), aPropertyValue );
551 		break;
552 
553 	case BASEPROPERTY_GRID_HEADER_TEXT_COLOR:
554         lcl_convertColor( m_pTableModel->getHeaderTextColor(), aPropertyValue );
555 		break;
556 
557 	case BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR:
558         lcl_convertColor( m_pTableModel->getActiveSelectionBackColor(), aPropertyValue );
559 		break;
560 
561 	case BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR:
562         lcl_convertColor( m_pTableModel->getInactiveSelectionBackColor(), aPropertyValue );
563 		break;
564 
565 	case BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR:
566         lcl_convertColor( m_pTableModel->getActiveSelectionTextColor(), aPropertyValue );
567 		break;
568 
569 	case BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR:
570         lcl_convertColor( m_pTableModel->getInactiveSelectionTextColor(), aPropertyValue );
571 		break;
572 
573 	case BASEPROPERTY_TEXTCOLOR:
574         lcl_convertColor( m_pTableModel->getTextColor(), aPropertyValue );
575 		break;
576 
577 	case BASEPROPERTY_TEXTLINECOLOR:
578         lcl_convertColor( m_pTableModel->getTextLineColor(), aPropertyValue );
579         break;
580 
581     default:
582         aPropertyValue = VCLXWindow::getProperty( PropertyName );
583         break;
584 	}
585 
586     return aPropertyValue;
587 }
588 
589 void SVTXGridControl::ImplGetPropertyIds( std::list< sal_uInt16 > &rIds )
590 {
591     PushPropertyIds( rIds,
592         BASEPROPERTY_GRID_SHOWROWHEADER,
593         BASEPROPERTY_GRID_SHOWCOLUMNHEADER,
594         BASEPROPERTY_GRID_DATAMODEL,
595         BASEPROPERTY_GRID_COLUMNMODEL,
596         BASEPROPERTY_GRID_SELECTIONMODE,
597         BASEPROPERTY_GRID_HEADER_BACKGROUND,
598         BASEPROPERTY_GRID_HEADER_TEXT_COLOR,
599         BASEPROPERTY_GRID_LINE_COLOR,
600         BASEPROPERTY_GRID_ROW_BACKGROUND_COLORS,
601         BASEPROPERTY_ACTIVE_SEL_BACKGROUND_COLOR,
602         BASEPROPERTY_INACTIVE_SEL_BACKGROUND_COLOR,
603         BASEPROPERTY_ACTIVE_SEL_TEXT_COLOR,
604         BASEPROPERTY_INACTIVE_SEL_TEXT_COLOR,
605         0
606     );
607     VCLXWindow::ImplGetPropertyIds( rIds, true );
608 }
609 
610 //----------------------------------------------------------------------------------------------------------------------
611 void SAL_CALL SVTXGridControl::rowsInserted( const GridDataEvent& i_event ) throw (RuntimeException)
612 {
613     ::vos::OGuard aGuard( GetMutex() );
614     m_pTableModel->notifyRowsInserted( i_event );
615 }
616 
617 //----------------------------------------------------------------------------------------------------------------------
618 void SAL_CALL//----------------------------------------------------------------------------------------------------------------------
619  SVTXGridControl::rowsRemoved( const GridDataEvent& i_event ) throw (RuntimeException)
620 {
621     ::vos::OGuard aGuard( GetMutex() );
622     m_pTableModel->notifyRowsRemoved( i_event );
623 }
624 
625 //----------------------------------------------------------------------------------------------------------------------
626 void SAL_CALL SVTXGridControl::dataChanged( const GridDataEvent& i_event ) throw (RuntimeException)
627 {
628     ::vos::OGuard aGuard( GetMutex() );
629 
630     m_pTableModel->notifyDataChanged( i_event );
631 
632     // if the data model is sortable, a dataChanged event is also fired in case the sort order changed.
633     // So, just in case, invalidate the column header area, too.
634 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
635     ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::dataChanged: no control (anymore)!" );
636     pTable->getTableControlInterface().invalidate( TableAreaColumnHeaders );
637 }
638 
639 //----------------------------------------------------------------------------------------------------------------------
640 void SAL_CALL SVTXGridControl::rowHeadingChanged( const GridDataEvent& i_event ) throw (RuntimeException)
641 {
642     ::vos::OGuard aGuard( GetMutex() );
643     OSL_UNUSED( i_event );
644 
645 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
646     ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::rowHeadingChanged: no control (anymore)!" );
647 
648     // TODO: we could do better than this - invalidate the header area only
649 	pTable->getTableControlInterface().invalidate( TableAreaRowHeaders );
650 }
651 
652 //----------------------------------------------------------------------------------------------------------------------
653 void SAL_CALL SVTXGridControl::elementInserted( const ContainerEvent& i_event ) throw (RuntimeException)
654 {
655     ::vos::OGuard aGuard( GetMutex() );
656 
657     Reference< XGridColumn > const xGridColumn( i_event.Element, UNO_QUERY_THROW );
658 
659     sal_Int32 nIndex( m_pTableModel->getColumnCount() );
660     OSL_VERIFY( i_event.Accessor >>= nIndex );
661 	m_pTableModel->insertColumn( nIndex, xGridColumn );
662 }
663 
664 //----------------------------------------------------------------------------------------------------------------------
665 void SAL_CALL SVTXGridControl::elementRemoved( const ContainerEvent& i_event ) throw (RuntimeException)
666 {
667     ::vos::OGuard aGuard( GetMutex() );
668 
669     sal_Int32 nIndex( -1 );
670     OSL_VERIFY( i_event.Accessor >>= nIndex );
671     m_pTableModel->removeColumn( nIndex );
672 }
673 
674 //----------------------------------------------------------------------------------------------------------------------
675 void SAL_CALL SVTXGridControl::elementReplaced( const ContainerEvent& i_event ) throw (RuntimeException)
676 {
677     OSL_ENSURE( false, "SVTXGridControl::elementReplaced: not implemented!" );
678         // at the moment, the XGridColumnModel API does not allow replacing columns
679     OSL_UNUSED( i_event );
680     // TODO: replace the respective column in our table model
681 }
682 
683 
684 //----------------------------------------------------------------------------------------------------------------------
685 void SAL_CALL SVTXGridControl::disposing( const EventObject& Source ) throw(RuntimeException)
686 {
687 	VCLXWindow::disposing( Source );
688 }
689 
690 //----------------------------------------------------------------------------------------------------------------------
691 void SAL_CALL SVTXGridControl::selectRow( ::sal_Int32 i_rowIndex ) throw (RuntimeException, IndexOutOfBoundsException )
692 {
693     ::vos::OGuard aGuard( GetMutex() );
694 
695 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
696     ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::selectRow: no control (anymore)!" );
697 
698     impl_checkRowIndex_throw( *pTable, i_rowIndex );
699 
700     pTable->SelectRow( i_rowIndex, true );
701 }
702 
703 //----------------------------------------------------------------------------------------------------------------------
704 void SAL_CALL SVTXGridControl::selectAllRows() throw (RuntimeException)
705 {
706     ::vos::OGuard aGuard( GetMutex() );
707 
708 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
709     ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::selectAllRows: no control (anymore)!" );
710 
711     pTable->SelectAllRows( true );
712 }
713 
714 //----------------------------------------------------------------------------------------------------------------------
715 void SAL_CALL SVTXGridControl::deselectRow( ::sal_Int32 i_rowIndex ) throw (RuntimeException, IndexOutOfBoundsException )
716 {
717     ::vos::OGuard aGuard( GetMutex() );
718 
719 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
720     ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::deselectRow: no control (anymore)!" );
721 
722     impl_checkRowIndex_throw( *pTable, i_rowIndex );
723 
724     pTable->SelectRow( i_rowIndex, false );
725 }
726 
727 //----------------------------------------------------------------------------------------------------------------------
728 void SAL_CALL SVTXGridControl::deselectAllRows() throw (RuntimeException)
729 {
730     ::vos::OGuard aGuard( GetMutex() );
731 
732 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
733     ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::deselectAllRows: no control (anymore)!" );
734 
735     pTable->SelectAllRows( false );
736 }
737 
738 //----------------------------------------------------------------------------------------------------------------------
739 Sequence< ::sal_Int32 > SAL_CALL SVTXGridControl::getSelectedRows() throw (RuntimeException)
740 {
741     ::vos::OGuard aGuard( GetMutex() );
742 
743 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
744     ENSURE_OR_RETURN( pTable, "SVTXGridControl::getSelectedRows: no control (anymore)!", Sequence< sal_Int32 >() );
745 
746     sal_Int32 selectionCount = pTable->GetSelectedRowCount();
747     Sequence< sal_Int32 > selectedRows( selectionCount );
748     for ( sal_Int32 i=0; i<selectionCount; ++i )
749         selectedRows[i] = pTable->GetSelectedRowIndex(i);
750 	return selectedRows;
751 }
752 
753 //----------------------------------------------------------------------------------------------------------------------
754 ::sal_Bool SAL_CALL SVTXGridControl::hasSelectedRows() throw (RuntimeException)
755 {
756     ::vos::OGuard aGuard( GetMutex() );
757 
758 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
759     ENSURE_OR_RETURN( pTable, "SVTXGridControl::hasSelectedRows: no control (anymore)!", sal_True );
760 
761     return pTable->GetSelectedRowCount() > 0;
762 }
763 
764 //----------------------------------------------------------------------------------------------------------------------
765 ::sal_Bool SAL_CALL SVTXGridControl::isRowSelected( ::sal_Int32 index ) throw (RuntimeException)
766 {
767     ::vos::OGuard aGuard( GetMutex() );
768 
769 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
770     ENSURE_OR_RETURN( pTable, "SVTXGridControl::isRowSelected: no control (anymore)!", sal_False );
771 
772     return pTable->IsRowSelected( index );
773 }
774 
775 //----------------------------------------------------------------------------------------------------------------------
776 void SVTXGridControl::dispose() throw(RuntimeException)
777 {
778 	EventObject aObj;
779 	aObj.Source = (::cppu::OWeakObject*)this;
780 	m_aSelectionListeners.disposeAndClear( aObj );
781 	VCLXWindow::dispose();
782 }
783 
784 //----------------------------------------------------------------------------------------------------------------------
785 void SVTXGridControl::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
786 {
787     ::vos::OGuard aGuard( GetMutex() );
788 
789     Reference< XWindow > xKeepAlive( this );
790 
791     TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
792     ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::ProcessWindowEvent: no control (anymore)!" );
793 
794     bool handled = false;
795 	switch ( rVclWindowEvent.GetId() )
796 	{
797 		case VCLEVENT_TABLEROW_SELECT:
798 		{
799 		    if ( m_aSelectionListeners.getLength() )
800 			    ImplCallItemListeners();
801             handled = true;
802         }
803 		break;
804 
805         case VCLEVENT_CONTROL_GETFOCUS:
806         {
807             // TODO: this doesn't belong here. It belongs into the TableControl/_Impl, so A11Y also
808             // works when the control is used outside the UNO context
809              if ( pTable->GetRowCount()>0 )
810              {
811                 pTable->commitCellEventIfAccessibleAlive(
812                     AccessibleEventId::STATE_CHANGED,
813                     makeAny( AccessibleStateType::FOCUSED ),
814                     Any()
815                 );
816                 pTable->commitTableEventIfAccessibleAlive(
817                     AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
818                     Any(),
819                     Any()
820                 );
821             }
822             else
823             {
824                 pTable->commitTableEventIfAccessibleAlive(
825                     AccessibleEventId::STATE_CHANGED,
826                     makeAny( AccessibleStateType::FOCUSED ),
827                     Any()
828                 );
829              }
830         }
831         break;
832 
833         case VCLEVENT_CONTROL_LOSEFOCUS:
834         {
835             // TODO: this doesn't belong here. It belongs into the TableControl/_Impl, so A11Y also
836             // works when the control is used outside the UNO context
837             if ( pTable->GetRowCount()>0 )
838             {
839                 pTable->commitCellEventIfAccessibleAlive(
840                     AccessibleEventId::STATE_CHANGED,
841                     Any(),
842                     makeAny( AccessibleStateType::FOCUSED )
843                 );
844             }
845             else
846             {
847                 pTable->commitTableEventIfAccessibleAlive(
848                     AccessibleEventId::STATE_CHANGED,
849                     Any(),
850                     makeAny( AccessibleStateType::FOCUSED )
851                 );
852             }
853         }
854         break;
855 	}
856 
857     if ( !handled )
858 		VCLXWindow::ProcessWindowEvent( rVclWindowEvent );
859 }
860 
861 //----------------------------------------------------------------------------------------------------------------------
862 void SVTXGridControl::ImplCallItemListeners()
863 {
864 	TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
865     ENSURE_OR_RETURN_VOID( pTable, "SVTXGridControl::ImplCallItemListeners: no control (anymore)!" );
866 
867 	if ( m_aSelectionListeners.getLength() )
868 	{
869 		GridSelectionEvent aEvent;
870 		aEvent.Source = (::cppu::OWeakObject*)this;
871 
872         sal_Int32 const nSelectedRowCount( pTable->GetSelectedRowCount() );
873         aEvent.SelectedRowIndexes.realloc( nSelectedRowCount );
874         for ( sal_Int32 i=0; i<nSelectedRowCount; ++i )
875             aEvent.SelectedRowIndexes[i] = pTable->GetSelectedRowIndex( i );
876 		m_aSelectionListeners.selectionChanged( aEvent );
877 	}
878 }
879 
880 //----------------------------------------------------------------------------------------------------------------------
881 void SVTXGridControl::impl_updateColumnsFromModel_nothrow()
882 {
883     Reference< XGridColumnModel > const xColumnModel( m_pTableModel->getColumnModel() );
884     ENSURE_OR_RETURN_VOID( xColumnModel.is(), "no model!" );
885     TableControl* pTable = dynamic_cast< TableControl* >( GetWindow() );
886     ENSURE_OR_RETURN_VOID( pTable != NULL, "no table!" );
887 
888     try
889     {
890         const Sequence< Reference< XGridColumn > > columns = xColumnModel->getColumns();
891         for (   const Reference< XGridColumn >* colRef = columns.getConstArray();
892                 colRef != columns.getConstArray() + columns.getLength();
893                 ++colRef
894             )
895         {
896             ENSURE_OR_CONTINUE( colRef->is(), "illegal column!" );
897 
898 			m_pTableModel->appendColumn( *colRef );
899 		}
900     }
901     catch( const Exception& )
902     {
903     	DBG_UNHANDLED_EXCEPTION();
904     }
905 }
906