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 "unocontroltablemodel.hxx"
31 #include "unogridcolumnfacade.hxx"
32 
33 #include "svtools/table/defaultinputhandler.hxx"
34 #include "svtools/table/gridtablerenderer.hxx"
35 #include "svtools/table/tablecontrol.hxx"
36 
37 /** === begin UNO includes === **/
38 #include <com/sun/star/awt/grid/XGridColumn.hpp>
39 #include <com/sun/star/view/SelectionType.hpp>
40 #include <com/sun/star/awt/grid/XGridColumnListener.hpp>
41 #include <com/sun/star/awt/grid/XSortableGridData.hpp>
42 /** === end UNO includes === **/
43 
44 #include <comphelper/stlunosequence.hxx>
45 #include <cppuhelper/weakref.hxx>
46 #include <tools/debug.hxx>
47 #include <tools/diagnose_ex.h>
48 #include <vcl/svapp.hxx>
49 #include <vos/mutex.hxx>
50 
51 // .....................................................................................................................
52 namespace svt { namespace table
53 {
54 // .....................................................................................................................
55 
56     /** === begin UNO using === **/
57     using ::com::sun::star::uno::Reference;
58     using ::com::sun::star::uno::RuntimeException;
59     using ::com::sun::star::uno::Sequence;
60     using ::com::sun::star::uno::UNO_QUERY_THROW;
61     using ::com::sun::star::uno::UNO_QUERY;
62     using ::com::sun::star::awt::grid::XGridColumn;
63     using ::com::sun::star::uno::XInterface;
64     using ::com::sun::star::uno::Exception;
65     using ::com::sun::star::awt::grid::XGridColumnListener;
66     using ::com::sun::star::lang::EventObject;
67     using ::com::sun::star::awt::grid::GridColumnEvent;
68     using ::com::sun::star::awt::grid::XGridDataModel;
69     using ::com::sun::star::awt::grid::XGridColumnModel;
70     using ::com::sun::star::uno::Any;
71     using ::com::sun::star::style::HorizontalAlignment_LEFT;
72     using ::com::sun::star::style::HorizontalAlignment;
73     using ::com::sun::star::style::VerticalAlignment_TOP;
74     using ::com::sun::star::style::VerticalAlignment;
75     using ::com::sun::star::uno::WeakReference;
76     using ::com::sun::star::awt::grid::GridDataEvent;
77     using ::com::sun::star::awt::grid::XSortableGridData;
78     using ::com::sun::star::beans::Pair;
79     /** === end UNO using === **/
80 
81 	//==================================================================================================================
82 	//= UnoControlTableModel_Impl
83 	//==================================================================================================================
84     typedef ::std::vector< PTableModelListener >    ModellListeners;
85     typedef ::std::vector< PColumnModel >           ColumnModels;
86     struct UnoControlTableModel_Impl
87     {
88         ColumnModels                                    aColumns;
89         bool                                            bHasColumnHeaders;
90         bool                                            bHasRowHeaders;
91         ScrollbarVisibility                             eVScrollMode;
92         ScrollbarVisibility                             eHScrollMode;
93         PTableRenderer                                  pRenderer;
94         PTableInputHandler                              pInputHandler;
95         TableMetrics                                    nRowHeight;
96         TableMetrics                                    nColumnHeaderHeight;
97         TableMetrics                                    nRowHeaderWidth;
98         ::boost::optional< ::Color >                    m_aGridLineColor;
99         ::boost::optional< ::Color >                    m_aHeaderBackgroundColor;
100         ::boost::optional< ::Color >                    m_aHeaderTextColor;
101         ::boost::optional< ::Color >                    m_aActiveSelectionBackColor;
102         ::boost::optional< ::Color >                    m_aInactiveSelectionBackColor;
103         ::boost::optional< ::Color >                    m_aActiveSelectionTextColor;
104         ::boost::optional< ::Color >                    m_aInactiveSelectionTextColor;
105         ::boost::optional< ::Color >                    m_aTextColor;
106         ::boost::optional< ::Color >                    m_aTextLineColor;
107         ::boost::optional< ::std::vector< ::Color > >   m_aRowColors;
108         VerticalAlignment                               m_eVerticalAlign;
109         ModellListeners                                 m_aListeners;
110         WeakReference< XGridDataModel >                 m_aDataModel;
111         WeakReference< XGridColumnModel >               m_aColumnModel;
112 
113         UnoControlTableModel_Impl()
114             :aColumns                       ( )
115             ,bHasColumnHeaders              ( true      )
116             ,bHasRowHeaders                 ( false     )
117             ,eVScrollMode                   ( ScrollbarShowNever )
118             ,eHScrollMode                   ( ScrollbarShowNever )
119             ,pRenderer                      ( )
120             ,pInputHandler                  ( )
121             ,nRowHeight                     ( 10 )
122             ,nColumnHeaderHeight            ( 10 )
123             ,nRowHeaderWidth                ( 10 )
124             ,m_aGridLineColor               ( )
125             ,m_aHeaderBackgroundColor       ( )
126             ,m_aHeaderTextColor             ( )
127             ,m_aActiveSelectionBackColor    ( )
128             ,m_aInactiveSelectionBackColor  ( )
129             ,m_aActiveSelectionTextColor    ( )
130             ,m_aInactiveSelectionTextColor  ( )
131             ,m_aTextColor                   ( )
132             ,m_aTextLineColor               ( )
133             ,m_aRowColors                   ( )
134             ,m_eVerticalAlign               ( VerticalAlignment_TOP )
135         {
136         }
137     };
138 
139 	//==================================================================================================================
140 	//= UnoControlTableModel
141 	//==================================================================================================================
142 #ifdef DBG_UTIL
143     const char* UnoControlTableModel_checkInvariants( const void* _pInstance )
144     {
145         return static_cast< const UnoControlTableModel* >( _pInstance )->checkInvariants();
146     }
147 
148 	//------------------------------------------------------------------------------------------------------------------
149     const char* UnoControlTableModel::checkInvariants() const
150     {
151         Reference< XGridDataModel > const xDataModel( m_pImpl->m_aDataModel );
152         if ( !xDataModel.is() )
153             return "data model anymore";
154 
155         // TODO: more?
156 
157         return NULL;
158     }
159 #endif
160 
161 #define DBG_CHECK_ME() \
162     DBG_TESTSOLARMUTEX(); \
163     DBG_CHKTHIS( UnoControlTableModel, UnoControlTableModel_checkInvariants )
164 
165 	//------------------------------------------------------------------------------------------------------------------
166     DBG_NAME( UnoControlTableModel )
167     UnoControlTableModel::UnoControlTableModel()
168         :m_pImpl( new UnoControlTableModel_Impl )
169 	{
170         DBG_CTOR( UnoControlTableModel, UnoControlTableModel_checkInvariants );
171         m_pImpl->bHasColumnHeaders = true;
172         m_pImpl->bHasRowHeaders = false;
173         m_pImpl->pRenderer.reset( new GridTableRenderer( *this ) );
174         m_pImpl->pInputHandler.reset( new DefaultInputHandler );
175     }
176 
177 	//------------------------------------------------------------------------------------------------------------------
178     UnoControlTableModel::~UnoControlTableModel()
179     {
180         DBG_DTOR( UnoControlTableModel, UnoControlTableModel_checkInvariants );
181         DELETEZ( m_pImpl );
182     }
183 
184 	//------------------------------------------------------------------------------------------------------------------
185     TableSize UnoControlTableModel::getColumnCount() const
186     {
187         DBG_CHECK_ME();
188 		return (TableSize)m_pImpl->aColumns.size();
189     }
190 
191 	//------------------------------------------------------------------------------------------------------------------
192     TableSize UnoControlTableModel::getRowCount() const
193     {
194         DBG_CHECK_ME();
195 
196         TableSize nRowCount = 0;
197         try
198         {
199             Reference< XGridDataModel > const xDataModel( m_pImpl->m_aDataModel );
200             ENSURE_OR_THROW( xDataModel.is(), "no data model anymore!" );
201             nRowCount = xDataModel->getRowCount();
202         }
203         catch( const Exception& )
204         {
205         	DBG_UNHANDLED_EXCEPTION();
206         }
207         return nRowCount;
208     }
209 
210 	//------------------------------------------------------------------------------------------------------------------
211     bool UnoControlTableModel::hasColumnHeaders() const
212     {
213         DBG_CHECK_ME();
214         return m_pImpl->bHasColumnHeaders;
215     }
216 
217 	//------------------------------------------------------------------------------------------------------------------
218     bool UnoControlTableModel::hasRowHeaders() const
219     {
220         DBG_CHECK_ME();
221         return m_pImpl->bHasRowHeaders;
222     }
223 
224 	//------------------------------------------------------------------------------------------------------------------
225     void UnoControlTableModel::setRowHeaders(bool _bRowHeaders)
226     {
227         DBG_CHECK_ME();
228         if ( m_pImpl->bHasRowHeaders == _bRowHeaders )
229             return;
230 
231         m_pImpl->bHasRowHeaders = _bRowHeaders;
232         impl_notifyTableMetricsChanged();
233     }
234 
235     //------------------------------------------------------------------------------------------------------------------
236     void UnoControlTableModel::setColumnHeaders(bool _bColumnHeaders)
237     {
238         DBG_CHECK_ME();
239         if ( m_pImpl->bHasColumnHeaders == _bColumnHeaders )
240             return;
241 
242         m_pImpl->bHasColumnHeaders = _bColumnHeaders;
243         impl_notifyTableMetricsChanged();
244     }
245 
246 	//------------------------------------------------------------------------------------------------------------------
247     bool UnoControlTableModel::isCellEditable( ColPos col, RowPos row ) const
248     {
249         DBG_CHECK_ME();
250         (void)col;
251         (void)row;
252         return false;
253     }
254 
255 	//------------------------------------------------------------------------------------------------------------------
256     PColumnModel UnoControlTableModel::getColumnModel( ColPos column )
257     {
258         DBG_CHECK_ME();
259         ENSURE_OR_RETURN( ( column >= 0 ) && ( column < getColumnCount() ),
260             "DefaultTableModel::getColumnModel: invalid index!", PColumnModel() );
261         return m_pImpl->aColumns[ column ];
262     }
263 
264 	//------------------------------------------------------------------------------------------------------------------
265     void UnoControlTableModel::appendColumn( Reference< XGridColumn > const & i_column )
266     {
267         DBG_CHECK_ME();
268         insertColumn( m_pImpl->aColumns.size(), i_column );
269     }
270 
271 	//------------------------------------------------------------------------------------------------------------------
272     void UnoControlTableModel::insertColumn( ColPos const i_position, Reference< XGridColumn > const & i_column )
273     {
274         DBG_CHECK_ME();
275         ENSURE_OR_RETURN_VOID( ( i_position >= 0 ) && ( size_t( i_position ) <= m_pImpl->aColumns.size() ),
276             "UnoControlTableModel::insertColumn: illegal position!" );
277 
278         const PColumnModel pColumn( new UnoGridColumnFacade( *this, i_column ) );
279         m_pImpl->aColumns.insert( m_pImpl->aColumns.begin() + i_position, pColumn );
280 
281         // notify listeners
282         ModellListeners aListeners( m_pImpl->m_aListeners );
283         for (   ModellListeners::const_iterator loop = aListeners.begin();
284                 loop != aListeners.end();
285                 ++loop
286             )
287         {
288             (*loop)->columnInserted( i_position );
289         }
290     }
291 
292 	//------------------------------------------------------------------------------------------------------------------
293     void UnoControlTableModel::removeColumn( ColPos const i_position )
294     {
295         DBG_CHECK_ME();
296         ENSURE_OR_RETURN_VOID( ( i_position >= 0 ) && ( size_t( i_position ) <= m_pImpl->aColumns.size() ),
297             "UnoControlTableModel::removeColumn: illegal position!" );
298 
299         // remove the column
300         ColumnModels::iterator pos = m_pImpl->aColumns.begin() + i_position;
301         const PColumnModel pColumn = *pos;
302         m_pImpl->aColumns.erase( pos );
303 
304         // notify listeners
305         ModellListeners aListeners( m_pImpl->m_aListeners );
306         for (   ModellListeners::const_iterator loop = aListeners.begin();
307                 loop != aListeners.end();
308                 ++loop
309             )
310         {
311             (*loop)->columnRemoved( i_position );
312         }
313 
314         // dispose the column
315         UnoGridColumnFacade* pColumnImpl = dynamic_cast< UnoGridColumnFacade* >( pColumn.get() );
316         OSL_ENSURE( pColumnImpl != NULL, "UnoControlTableModel::removeColumn: illegal column implementation!" );
317         if ( pColumnImpl )
318             pColumnImpl->dispose();
319     }
320 
321 	//------------------------------------------------------------------------------------------------------------------
322     void UnoControlTableModel::removeAllColumns()
323     {
324         DBG_CHECK_ME();
325         if ( m_pImpl->aColumns.empty() )
326             return;
327 
328         // dispose the column instances
329         for (   ColumnModels::const_iterator col = m_pImpl->aColumns.begin();
330                 col != m_pImpl->aColumns.end();
331                 ++col
332             )
333         {
334             UnoGridColumnFacade* pColumn = dynamic_cast< UnoGridColumnFacade* >( col->get() );
335             ENSURE_OR_CONTINUE( pColumn != NULL, "UnoControlTableModel::removeAllColumns: illegal column implementation!" );
336             pColumn->dispose();
337         }
338         m_pImpl->aColumns.clear();
339 
340         // notify listeners
341         ModellListeners aListeners( m_pImpl->m_aListeners );
342         for (   ModellListeners::const_iterator loop = aListeners.begin();
343                 loop != aListeners.end();
344                 ++loop
345             )
346         {
347             (*loop)->allColumnsRemoved();
348         }
349     }
350 
351     //------------------------------------------------------------------------------------------------------------------
352     void UnoControlTableModel::impl_notifyTableMetricsChanged() const
353     {
354         ModellListeners aListeners( m_pImpl->m_aListeners );
355         for (   ModellListeners::const_iterator loop = aListeners.begin();
356                 loop != aListeners.end();
357                 ++loop
358             )
359         {
360             (*loop)->tableMetricsChanged();
361         }
362     }
363 
364     //------------------------------------------------------------------------------------------------------------------
365     PTableRenderer UnoControlTableModel::getRenderer() const
366     {
367         DBG_CHECK_ME();
368         return m_pImpl->pRenderer;
369     }
370 
371     //------------------------------------------------------------------------------------------------------------------
372     PTableInputHandler UnoControlTableModel::getInputHandler() const
373     {
374         DBG_CHECK_ME();
375         return m_pImpl->pInputHandler;
376     }
377 
378     //------------------------------------------------------------------------------------------------------------------
379     TableMetrics UnoControlTableModel::getRowHeight() const
380     {
381         DBG_CHECK_ME();
382         return m_pImpl->nRowHeight;
383     }
384 
385     //------------------------------------------------------------------------------------------------------------------
386     void UnoControlTableModel::setRowHeight(TableMetrics _nRowHeight)
387     {
388         DBG_CHECK_ME();
389         if ( m_pImpl->nRowHeight == _nRowHeight )
390             return;
391 
392         m_pImpl->nRowHeight = _nRowHeight;
393         impl_notifyTableMetricsChanged();
394     }
395 
396     //------------------------------------------------------------------------------------------------------------------
397     TableMetrics UnoControlTableModel::getColumnHeaderHeight() const
398     {
399         DBG_CHECK_ME();
400         DBG_ASSERT( hasColumnHeaders(), "DefaultTableModel::getColumnHeaderHeight: invalid call!" );
401         return m_pImpl->nColumnHeaderHeight;
402     }
403 
404     //------------------------------------------------------------------------------------------------------------------
405     TableMetrics UnoControlTableModel::getRowHeaderWidth() const
406     {
407         DBG_CHECK_ME();
408         DBG_ASSERT( hasRowHeaders(), "DefaultTableModel::getRowHeaderWidth: invalid call!" );
409         return m_pImpl->nRowHeaderWidth;
410     }
411 	//------------------------------------------------------------------------------------------------------------------
412     void UnoControlTableModel::setColumnHeaderHeight(TableMetrics _nHeight)
413     {
414         DBG_CHECK_ME();
415         if ( m_pImpl->nColumnHeaderHeight == _nHeight )
416             return;
417 
418         m_pImpl->nColumnHeaderHeight = _nHeight;
419         impl_notifyTableMetricsChanged();
420     }
421 
422     //------------------------------------------------------------------------------------------------------------------
423     void UnoControlTableModel::setRowHeaderWidth(TableMetrics _nWidth)
424     {
425         DBG_CHECK_ME();
426         if ( m_pImpl->nRowHeaderWidth == _nWidth )
427             return;
428 
429         m_pImpl->nRowHeaderWidth = _nWidth;
430         impl_notifyTableMetricsChanged();
431     }
432 
433     //------------------------------------------------------------------------------------------------------------------
434     ScrollbarVisibility UnoControlTableModel::getVerticalScrollbarVisibility() const
435     {
436         DBG_CHECK_ME();
437         return m_pImpl->eVScrollMode;
438     }
439 
440     //------------------------------------------------------------------------------------------------------------------
441     ScrollbarVisibility UnoControlTableModel::getHorizontalScrollbarVisibility() const
442     {
443         DBG_CHECK_ME();
444         return m_pImpl->eHScrollMode;
445     }
446 
447     //------------------------------------------------------------------------------------------------------------------
448     void UnoControlTableModel::addTableModelListener( const PTableModelListener& i_listener )
449     {
450         DBG_CHECK_ME();
451         ENSURE_OR_RETURN_VOID( !!i_listener, "illegal NULL listener" );
452         m_pImpl->m_aListeners.push_back( i_listener );
453     }
454 
455     //------------------------------------------------------------------------------------------------------------------
456     void UnoControlTableModel::removeTableModelListener( const PTableModelListener& i_listener )
457     {
458         DBG_CHECK_ME();
459         for (   ModellListeners::iterator lookup = m_pImpl->m_aListeners.begin();
460                 lookup != m_pImpl->m_aListeners.end();
461                 ++lookup
462             )
463         {
464             if ( *lookup == i_listener )
465             {
466                 m_pImpl->m_aListeners.erase( lookup );
467                 return;
468             }
469         }
470         OSL_ENSURE( false, "UnoControlTableModel::removeTableModelListener: listener is not registered - sure you're doing the right thing here?" );
471     }
472 
473     //------------------------------------------------------------------------------------------------------------------
474     void UnoControlTableModel::setVerticalScrollbarVisibility( ScrollbarVisibility const i_visibility ) const
475     {
476         DBG_CHECK_ME();
477 		m_pImpl->eVScrollMode = i_visibility;
478     }
479 
480     //------------------------------------------------------------------------------------------------------------------
481     void UnoControlTableModel::setHorizontalScrollbarVisibility( ScrollbarVisibility const i_visibility ) const
482     {
483         DBG_CHECK_ME();
484 		m_pImpl->eHScrollMode = i_visibility;
485     }
486 
487     //------------------------------------------------------------------------------------------------------------------
488     void UnoControlTableModel::setDataModel( Reference< XGridDataModel > const & i_gridDataModel )
489     {
490         DBG_CHECK_ME();
491         m_pImpl->m_aDataModel = i_gridDataModel;
492         // TODO: register as listener, so we're notified of row/data changes, and can multiplex them to our
493         // own listeners
494     }
495 
496     //------------------------------------------------------------------------------------------------------------------
497     Reference< XGridDataModel > UnoControlTableModel::getDataModel() const
498     {
499         Reference< XGridDataModel > const xDataModel( m_pImpl->m_aDataModel );
500         return xDataModel;
501     }
502 
503     //------------------------------------------------------------------------------------------------------------------
504     bool UnoControlTableModel::hasDataModel() const
505     {
506         return getDataModel().is();
507     }
508 
509     //------------------------------------------------------------------------------------------------------------------
510     void UnoControlTableModel::setColumnModel( Reference< XGridColumnModel > const & i_gridColumnModel )
511     {
512         DBG_CHECK_ME();
513         m_pImpl->m_aColumnModel = i_gridColumnModel;
514     }
515 
516     //------------------------------------------------------------------------------------------------------------------
517     Reference< XGridColumnModel > UnoControlTableModel::getColumnModel() const
518     {
519         Reference< XGridColumnModel > const xColumnModel( m_pImpl->m_aColumnModel );
520         return xColumnModel;
521     }
522 
523     //------------------------------------------------------------------------------------------------------------------
524     bool UnoControlTableModel::hasColumnModel() const
525     {
526         return getColumnModel().is();
527     }
528 
529     //------------------------------------------------------------------------------------------------------------------
530     void UnoControlTableModel::getCellContent( ColPos const i_col, RowPos const i_row, Any& o_cellContent )
531     {
532         DBG_CHECK_ME();
533 
534         o_cellContent.clear();
535         try
536         {
537             Reference< XGridDataModel > const xDataModel( m_pImpl->m_aDataModel );
538             ENSURE_OR_RETURN_VOID( xDataModel.is(), "UnoControlTableModel::getCellContent: no data model anymore!" );
539 
540             PColumnModel const pColumn = getColumnModel( i_col );
541             UnoGridColumnFacade* pColumnImpl = dynamic_cast< UnoGridColumnFacade* >( pColumn.get() );
542             ENSURE_OR_RETURN_VOID( pColumnImpl != NULL, "UnoControlTableModel::getCellContent: no (valid) column at this position!" );
543             sal_Int32 const nDataColumnIndex = pColumnImpl->getDataColumnIndex() >= 0 ? pColumnImpl->getDataColumnIndex() : i_col;
544 
545             if ( nDataColumnIndex >= xDataModel->getColumnCount() )
546             {
547                 // this is allowed, in case the column model has been dynamically extended, but the data model does
548                 // not (yet?) know about it.
549                 // So, handle it gracefully.
550             #if OSL_DEBUG_LEVEL > 0
551                 {
552                     Reference< XGridColumnModel > const xColumnModel( m_pImpl->m_aColumnModel );
553                     OSL_ENSURE( xColumnModel.is() && i_col < xColumnModel->getColumnCount(),
554                         "UnoControlTableModel::getCellContent: request a column's value which the ColumnModel doesn't know about!" );
555                 }
556             #endif
557             }
558             else
559             {
560                 o_cellContent = xDataModel->getCellData( nDataColumnIndex, i_row );
561             }
562         }
563         catch( const Exception& )
564         {
565         	DBG_UNHANDLED_EXCEPTION();
566         }
567     }
568 
569     //------------------------------------------------------------------------------------------------------------------
570     void UnoControlTableModel::getCellToolTip( ColPos const i_col, RowPos const i_row, Any& o_cellToolTip )
571     {
572         DBG_CHECK_ME();
573         try
574         {
575             Reference< XGridDataModel > const xDataModel( m_pImpl->m_aDataModel );
576             ENSURE_OR_THROW( xDataModel.is(), "no data model anymore!" );
577 
578             o_cellToolTip = xDataModel->getCellToolTip( i_col, i_row );
579         }
580         catch( const Exception& )
581         {
582         	DBG_UNHANDLED_EXCEPTION();
583         }
584     }
585 
586     //------------------------------------------------------------------------------------------------------------------
587     Any UnoControlTableModel::getRowHeading( RowPos const i_rowPos ) const
588     {
589         DBG_CHECK_ME();
590 
591         Any aRowHeading;
592 
593         Reference< XGridDataModel > const xDataModel( m_pImpl->m_aDataModel );
594         ENSURE_OR_RETURN( xDataModel.is(), "UnoControlTableModel::getRowHeading: no data model anymore!", aRowHeading );
595 
596         try
597         {
598             aRowHeading = xDataModel->getRowHeading( i_rowPos );
599         }
600         catch( const Exception& )
601         {
602         	DBG_UNHANDLED_EXCEPTION();
603         }
604         return aRowHeading;
605     }
606 
607     //------------------------------------------------------------------------------------------------------------------
608     namespace
609     {
610         void lcl_setColor( Any const & i_color, ::boost::optional< ::Color > & o_convertedColor )
611         {
612             if ( !i_color.hasValue() )
613                 o_convertedColor.reset();
614             else
615             {
616                 sal_Int32 nColor = COL_TRANSPARENT;
617                 if ( i_color >>= nColor )
618                 {
619                     o_convertedColor.reset( ::Color( nColor ) );
620                 }
621                 else
622                 {
623                     OSL_ENSURE( false, "lcl_setColor: could not extract color value!" );
624                 }
625             }
626         }
627     }
628 
629     //------------------------------------------------------------------------------------------------------------------
630     ::boost::optional< ::Color > UnoControlTableModel::getLineColor() const
631     {
632         DBG_CHECK_ME();
633         return m_pImpl->m_aGridLineColor;
634     }
635 
636     //------------------------------------------------------------------------------------------------------------------
637     void UnoControlTableModel::setLineColor( Any const & i_color )
638     {
639         DBG_CHECK_ME();
640         lcl_setColor( i_color, m_pImpl->m_aGridLineColor );
641     }
642 
643     //------------------------------------------------------------------------------------------------------------------
644     ::boost::optional< ::Color > UnoControlTableModel::getHeaderBackgroundColor() const
645     {
646         DBG_CHECK_ME();
647         return m_pImpl->m_aHeaderBackgroundColor;
648     }
649 
650     //------------------------------------------------------------------------------------------------------------------
651     void UnoControlTableModel::setHeaderBackgroundColor( Any const & i_color )
652     {
653         DBG_CHECK_ME();
654         lcl_setColor( i_color, m_pImpl->m_aHeaderBackgroundColor );
655     }
656 
657     //------------------------------------------------------------------------------------------------------------------
658     ::boost::optional< ::Color > UnoControlTableModel::getHeaderTextColor() const
659     {
660         DBG_CHECK_ME();
661         return m_pImpl->m_aHeaderTextColor;
662     }
663 
664     //------------------------------------------------------------------------------------------------------------------
665     ::boost::optional< ::Color > UnoControlTableModel::getActiveSelectionBackColor() const
666     {
667         DBG_CHECK_ME();
668         return m_pImpl->m_aActiveSelectionBackColor;
669     }
670 
671     //------------------------------------------------------------------------------------------------------------------
672     ::boost::optional< ::Color > UnoControlTableModel::getInactiveSelectionBackColor() const
673     {
674         DBG_CHECK_ME();
675         return m_pImpl->m_aInactiveSelectionBackColor;
676     }
677 
678     //------------------------------------------------------------------------------------------------------------------
679     ::boost::optional< ::Color > UnoControlTableModel::getActiveSelectionTextColor() const
680     {
681         DBG_CHECK_ME();
682         return m_pImpl->m_aActiveSelectionTextColor;
683     }
684 
685     //------------------------------------------------------------------------------------------------------------------
686     ::boost::optional< ::Color > UnoControlTableModel::getInactiveSelectionTextColor() const
687     {
688         DBG_CHECK_ME();
689         return m_pImpl->m_aInactiveSelectionTextColor;
690     }
691 
692     //------------------------------------------------------------------------------------------------------------------
693     void UnoControlTableModel::setHeaderTextColor( Any const & i_color )
694     {
695         DBG_CHECK_ME();
696         lcl_setColor( i_color, m_pImpl->m_aHeaderTextColor );
697     }
698 
699     //------------------------------------------------------------------------------------------------------------------
700     void UnoControlTableModel::setActiveSelectionBackColor( Any const & i_color )
701     {
702         DBG_CHECK_ME();
703         lcl_setColor( i_color, m_pImpl->m_aActiveSelectionBackColor );
704     }
705 
706     //------------------------------------------------------------------------------------------------------------------
707     void UnoControlTableModel::setInactiveSelectionBackColor( Any const & i_color )
708     {
709         DBG_CHECK_ME();
710         lcl_setColor( i_color, m_pImpl->m_aInactiveSelectionBackColor );
711     }
712 
713     //------------------------------------------------------------------------------------------------------------------
714     void UnoControlTableModel::setActiveSelectionTextColor( Any const & i_color )
715     {
716         DBG_CHECK_ME();
717         lcl_setColor( i_color, m_pImpl->m_aActiveSelectionTextColor );
718     }
719 
720     //------------------------------------------------------------------------------------------------------------------
721     void UnoControlTableModel::setInactiveSelectionTextColor( Any const & i_color )
722     {
723         DBG_CHECK_ME();
724         lcl_setColor( i_color, m_pImpl->m_aInactiveSelectionTextColor );
725     }
726 
727     //------------------------------------------------------------------------------------------------------------------
728     ::boost::optional< ::Color > UnoControlTableModel::getTextColor() const
729     {
730         DBG_CHECK_ME();
731         return m_pImpl->m_aTextColor;
732     }
733 
734     //------------------------------------------------------------------------------------------------------------------
735     void UnoControlTableModel::setTextColor( Any const & i_color )
736     {
737         DBG_CHECK_ME();
738         lcl_setColor( i_color, m_pImpl->m_aTextColor );
739     }
740 
741     //------------------------------------------------------------------------------------------------------------------
742     ::boost::optional< ::Color > UnoControlTableModel::getTextLineColor() const
743     {
744         DBG_CHECK_ME();
745         return m_pImpl->m_aTextColor;
746     }
747 
748     //------------------------------------------------------------------------------------------------------------------
749     void UnoControlTableModel::setTextLineColor( Any const & i_color )
750     {
751         DBG_CHECK_ME();
752         lcl_setColor( i_color, m_pImpl->m_aTextLineColor );
753     }
754 
755     //------------------------------------------------------------------------------------------------------------------
756     ::boost::optional< ::std::vector< ::Color > > UnoControlTableModel::getRowBackgroundColors() const
757     {
758         DBG_CHECK_ME();
759         return m_pImpl->m_aRowColors;
760     }
761 
762     //------------------------------------------------------------------------------------------------------------------
763     void UnoControlTableModel::setRowBackgroundColors( ::com::sun::star::uno::Any const & i_APIValue )
764     {
765         DBG_CHECK_ME();
766         Sequence< ::com::sun::star::util::Color > aAPIColors;
767         if ( !( i_APIValue >>= aAPIColors ) )
768             m_pImpl->m_aRowColors.reset();
769         else
770         {
771             ::std::vector< ::Color > aColors( aAPIColors.getLength() );
772             for ( sal_Int32 i=0; i<aAPIColors.getLength(); ++i )
773             {
774                 aColors[i] = ::Color( aAPIColors[i] );
775             }
776             m_pImpl->m_aRowColors.reset( aColors );
777         }
778     }
779 
780     //------------------------------------------------------------------------------------------------------------------
781     VerticalAlignment UnoControlTableModel::getVerticalAlign() const
782     {
783         DBG_CHECK_ME();
784         return  m_pImpl->m_eVerticalAlign;
785     }
786 
787     //------------------------------------------------------------------------------------------------------------------
788     void UnoControlTableModel::setVerticalAlign( VerticalAlignment _xAlign )
789     {
790         DBG_CHECK_ME();
791         m_pImpl->m_eVerticalAlign = _xAlign;
792     }
793 
794     //------------------------------------------------------------------------------------------------------------------
795     ColPos UnoControlTableModel::getColumnPos( UnoGridColumnFacade const & i_column ) const
796     {
797         DBG_CHECK_ME();
798         for (   ColumnModels::const_iterator col = m_pImpl->aColumns.begin();
799                 col != m_pImpl->aColumns.end();
800                 ++col
801             )
802         {
803             if ( &i_column == col->get() )
804                 return col - m_pImpl->aColumns.begin();
805         }
806         OSL_ENSURE( false, "UnoControlTableModel::getColumnPos: column not found!" );
807         return COL_INVALID;
808     }
809 
810     //------------------------------------------------------------------------------------------------------------------
811     ITableDataSort* UnoControlTableModel::getSortAdapter()
812     {
813         DBG_CHECK_ME();
814 
815         Reference< XSortableGridData > const xSortAccess( getDataModel(), UNO_QUERY );
816         if ( xSortAccess.is() )
817             return this;
818         return NULL;
819     }
820 
821     //------------------------------------------------------------------------------------------------------------------
822     void UnoControlTableModel::sortByColumn( ColPos const i_column, ColumnSortDirection const i_sortDirection )
823     {
824         DBG_CHECK_ME();
825 
826         try
827         {
828             Reference< XSortableGridData > const xSortAccess( getDataModel(), UNO_QUERY_THROW );
829             xSortAccess->sortByColumn( i_column, i_sortDirection == ColumnSortAscending );
830         }
831         catch( const Exception& )
832         {
833         	DBG_UNHANDLED_EXCEPTION();
834         }
835     }
836 
837     //------------------------------------------------------------------------------------------------------------------
838     ColumnSort UnoControlTableModel::getCurrentSortOrder() const
839     {
840         DBG_CHECK_ME();
841 
842         ColumnSort currentSort;
843         try
844         {
845             Reference< XSortableGridData > const xSortAccess( getDataModel(), UNO_QUERY_THROW );
846             Pair< ::sal_Int32, ::sal_Bool > const aCurrentSortOrder( xSortAccess->getCurrentSortOrder() );
847             currentSort.nColumnPos = aCurrentSortOrder.First;
848             currentSort.eSortDirection = aCurrentSortOrder.Second ? ColumnSortAscending : ColumnSortDescending;
849         }
850         catch( const Exception& )
851         {
852         	DBG_UNHANDLED_EXCEPTION();
853         }
854         return currentSort;
855     }
856 
857     //--------------------------------------------------------------------
858     void UnoControlTableModel::notifyColumnChange( ColPos const i_columnPos, ColumnAttributeGroup const i_attributeGroup ) const
859     {
860         DBG_CHECK_ME();
861         ENSURE_OR_RETURN_VOID( ( i_columnPos >= 0 ) && ( i_columnPos < getColumnCount() ),
862             "UnoControlTableModel::notifyColumnChange: invalid column index!" );
863 
864         ModellListeners aListeners( m_pImpl->m_aListeners );
865         for (   ModellListeners::const_iterator loop = aListeners.begin();
866                 loop != aListeners.end();
867                 ++loop
868             )
869         {
870             (*loop)->columnChanged( i_columnPos, i_attributeGroup );
871         }
872     }
873 
874     //------------------------------------------------------------------------------------------------------------------
875     void UnoControlTableModel::notifyRowsInserted( GridDataEvent const & i_event ) const
876     {
877         // check sanity of the event
878         ENSURE_OR_RETURN_VOID( i_event.FirstRow >= 0, "UnoControlTableModel::notifyRowsInserted: invalid first row!" );
879         ENSURE_OR_RETURN_VOID( i_event.LastRow >= i_event.FirstRow, "UnoControlTableModel::notifyRowsInserted: invalid row indexes!" );
880 
881         // check own sanity
882         Reference< XGridColumnModel > const xColumnModel( m_pImpl->m_aColumnModel );
883         ENSURE_OR_RETURN_VOID( xColumnModel.is(), "UnoControlTableModel::notifyRowsInserted: no column model anymore!" );
884 
885         Reference< XGridDataModel > const xDataModel( m_pImpl->m_aDataModel );
886         ENSURE_OR_RETURN_VOID( xDataModel.is(), "UnoControlTableModel::notifyRowsInserted: no data model anymore!" );
887 
888         // implicitly add columns to the column model
889         // TODO: is this really a good idea?
890         sal_Int32 const dataColumnCount = xDataModel->getColumnCount();
891         OSL_ENSURE( dataColumnCount > 0, "UnoControlTableModel::notifyRowsInserted: no columns at all?" );
892 
893         sal_Int32 const modelColumnCount = xColumnModel->getColumnCount();
894         if ( ( modelColumnCount == 0 ) && ( dataColumnCount > 0 ) )
895         {
896             // TODO: shouldn't we clear the mutexes guard for this call?
897 		    xColumnModel->setDefaultColumns( dataColumnCount );
898         }
899 
900         // multiplex the event to our own listeners
901         ModellListeners aListeners( m_pImpl->m_aListeners );
902         for (   ModellListeners::const_iterator loop = aListeners.begin();
903                 loop != aListeners.end();
904                 ++loop
905             )
906         {
907             (*loop)->rowsInserted( i_event.FirstRow, i_event.LastRow );
908         }
909     }
910 
911     //------------------------------------------------------------------------------------------------------------------
912     void UnoControlTableModel::notifyRowsRemoved( GridDataEvent const & i_event ) const
913     {
914         ModellListeners aListeners( m_pImpl->m_aListeners );
915         for (   ModellListeners::const_iterator loop = aListeners.begin();
916                 loop != aListeners.end();
917                 ++loop
918             )
919         {
920             (*loop)->rowsRemoved( i_event.FirstRow, i_event.LastRow );
921         }
922     }
923 
924     //------------------------------------------------------------------------------------------------------------------
925     void UnoControlTableModel::notifyDataChanged( ::com::sun::star::awt::grid::GridDataEvent const & i_event ) const
926     {
927         ColPos const firstCol = i_event.FirstColumn == -1 ? 0 : i_event.FirstColumn;
928         ColPos const lastCol = i_event.FirstColumn == -1 ? getColumnCount() - 1 : i_event.LastColumn;
929         RowPos const firstRow = i_event.FirstRow == -1 ? 0 : i_event.FirstRow;
930         RowPos const lastRow = i_event.FirstRow == -1 ? getRowCount() - 1 : i_event.LastRow;
931 
932         ModellListeners aListeners( m_pImpl->m_aListeners );
933         for (   ModellListeners::const_iterator loop = aListeners.begin();
934                 loop != aListeners.end();
935                 ++loop
936             )
937         {
938             (*loop)->cellsUpdated( firstCol, lastCol, firstRow, lastRow );
939         }
940     }
941 
942     //------------------------------------------------------------------------------------------------------------------
943     void UnoControlTableModel::notifyAllDataChanged() const
944     {
945         ModellListeners aListeners( m_pImpl->m_aListeners );
946         for (   ModellListeners::const_iterator loop = aListeners.begin();
947                 loop != aListeners.end();
948                 ++loop
949             )
950         {
951             (*loop)->cellsUpdated( 0, getColumnCount() - 1, 0, getRowCount() - 1 );
952         }
953     }
954 
955 // .....................................................................................................................
956 } } // svt::table
957 // .....................................................................................................................
958