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