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