xref: /trunk/main/svtools/source/uno/svtxgridcontrol.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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