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 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svtools.hxx"
26 
27 #include "svtools/table/tablecontrol.hxx"
28 
29 #include "tablegeometry.hxx"
30 #include "tablecontrol_impl.hxx"
31 #include "tabledatawindow.hxx"
32 
33 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
34 #include <com/sun/star/accessibility/AccessibleRole.hpp>
35 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
36 
37 #include <tools/diagnose_ex.h>
38 
39 using namespace ::com::sun::star::uno;
40 using ::com::sun::star::accessibility::XAccessible;
41 using namespace ::com::sun::star::accessibility;
42 using namespace ::com::sun::star::lang;
43 using namespace utl;
44 
45 //......................................................................................................................
46 namespace svt { namespace table
47 {
48 //......................................................................................................................
49 
50     namespace AccessibleEventId = ::com::sun::star::accessibility::AccessibleEventId;
51 
52     //==================================================================================================================
53 	//= TableControl
54     //==================================================================================================================
55     // -----------------------------------------------------------------------------------------------------------------
TableControl(Window * _pParent,WinBits _nStyle)56     TableControl::TableControl( Window* _pParent, WinBits _nStyle )
57         :Control( _pParent, _nStyle )
58         ,m_pImpl( new TableControl_Impl( *this ) )
59     {
60 		TableDataWindow& rDataWindow = m_pImpl->getDataWindow();
61 		rDataWindow.SetSelectHdl( LINK( this, TableControl, ImplSelectHdl ) );
62 
63         // by default, use the background as determined by the style settings
64         const Color aWindowColor( GetSettings().GetStyleSettings().GetFieldColor() );
65 		SetBackground( Wallpaper( aWindowColor ) );
66 		SetFillColor( aWindowColor );
67 
68         SetCompoundControl( true );
69     }
70 
71     // -----------------------------------------------------------------------------------------------------------------
~TableControl()72     TableControl::~TableControl()
73     {
74 		ImplCallEventListeners( VCLEVENT_OBJECT_DYING );
75 
76         m_pImpl->setModel( PTableModel() );
77         m_pImpl->disposeAccessible();
78         m_pImpl.reset();
79     }
80 
81     // -----------------------------------------------------------------------------------------------------------------
GetFocus()82     void TableControl::GetFocus()
83     {
84         if ( !m_pImpl->getInputHandler()->GetFocus( *m_pImpl ) )
85             Control::GetFocus();
86     }
87 
88     // -----------------------------------------------------------------------------------------------------------------
LoseFocus()89     void TableControl::LoseFocus()
90     {
91         if ( !m_pImpl->getInputHandler()->LoseFocus( *m_pImpl ) )
92             Control::LoseFocus();
93     }
94 
95     // -----------------------------------------------------------------------------------------------------------------
KeyInput(const KeyEvent & rKEvt)96     void TableControl::KeyInput( const KeyEvent& rKEvt )
97     {
98         if ( !m_pImpl->getInputHandler()->KeyInput( *m_pImpl, rKEvt ) )
99             Control::KeyInput( rKEvt );
100         else
101         {
102             if ( m_pImpl->isAccessibleAlive() )
103             {
104                 m_pImpl->commitCellEvent( AccessibleEventId::STATE_CHANGED,
105                                           makeAny( AccessibleStateType::FOCUSED ),
106                                           Any()
107                                         );
108                     // Huh? What the heck? Why do we unconditionally notify a STATE_CHANGE/FOCUSED after each and every
109                     // (handled) key stroke?
110 
111                 m_pImpl->commitTableEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
112                                            Any(),
113                                            Any()
114                                          );
115                     // ditto: Why do we notify this unconditionally? We should find the right place to notify the
116                     // ACTIVE_DESCENDANT_CHANGED event.
117                     // Also, we should check if STATE_CHANGED/FOCUSED is really necessary: finally, the children are
118                     // transient, aren't they?
119             }
120         }
121     }
122 
123 
124     // -----------------------------------------------------------------------------------------------------------------
StateChanged(StateChangedType i_nStateChange)125     void TableControl::StateChanged( StateChangedType i_nStateChange )
126     {
127         Control::StateChanged( i_nStateChange );
128 
129         // forward certain settings to the data window
130         switch ( i_nStateChange )
131         {
132         case STATE_CHANGE_CONTROL_FOCUS:
133             m_pImpl->invalidateSelectedRows();
134             break;
135 
136         case STATE_CHANGE_CONTROLBACKGROUND:
137             if ( IsControlBackground() )
138                 getDataWindow().SetControlBackground( GetControlBackground() );
139             else
140                 getDataWindow().SetControlBackground();
141             break;
142 
143         case STATE_CHANGE_CONTROLFOREGROUND:
144             if ( IsControlForeground() )
145                 getDataWindow().SetControlForeground( GetControlForeground() );
146             else
147                 getDataWindow().SetControlForeground();
148             break;
149 
150         case STATE_CHANGE_CONTROLFONT:
151             if ( IsControlFont() )
152                 getDataWindow().SetControlFont( GetControlFont() );
153             else
154                 getDataWindow().SetControlFont();
155             break;
156         }
157     }
158 
159     // -----------------------------------------------------------------------------------------------------------------
Resize()160     void TableControl::Resize()
161     {
162         Control::Resize();
163         m_pImpl->onResize();
164     }
165 
166     // -----------------------------------------------------------------------------------------------------------------
SetModel(PTableModel _pModel)167     void TableControl::SetModel( PTableModel _pModel )
168     {
169         m_pImpl->setModel( _pModel );
170     }
171 
172     // -----------------------------------------------------------------------------------------------------------------
GetModel() const173     PTableModel TableControl::GetModel() const
174     {
175         return m_pImpl->getModel();
176     }
177 
178     // -----------------------------------------------------------------------------------------------------------------
GetTopRow() const179     RowPos TableControl::GetTopRow() const
180     {
181         return m_pImpl->getTopRow();
182     }
183 
184     // -----------------------------------------------------------------------------------------------------------------
SetTopRow(RowPos _nRow)185     void TableControl::SetTopRow( RowPos _nRow )
186     {
187         OSL_ENSURE( false, "TableControl::SetTopRow: not implemented!" );
188         OSL_UNUSED( _nRow );
189     }
190 
191     // -----------------------------------------------------------------------------------------------------------------
GetCurrentRow() const192     sal_Int32 TableControl::GetCurrentRow() const
193     {
194         return m_pImpl->getCurrentRow();
195     }
196 
197     // -----------------------------------------------------------------------------------------------------------------
GetCurrentColumn() const198     sal_Int32 TableControl::GetCurrentColumn() const
199     {
200         return m_pImpl->getCurrentColumn();
201     }
202 
203     // -----------------------------------------------------------------------------------------------------------------
GoTo(ColPos _nColumn,RowPos _nRow)204     bool TableControl::GoTo( ColPos _nColumn, RowPos _nRow )
205     {
206         return m_pImpl->goTo( _nColumn, _nRow );
207     }
208 
209 	// -----------------------------------------------------------------------------------------------------------------
GoToCell(sal_Int32 _nColPos,sal_Int32 _nRowPos)210 	sal_Bool TableControl::GoToCell(sal_Int32 _nColPos, sal_Int32 _nRowPos)
211 	{
212 		return m_pImpl->goTo( _nColPos, _nRowPos );
213 	}
214 
215     //------------------------------------------------------------------------------------------------------------------
GetSelectedRowCount() const216     sal_Int32 TableControl::GetSelectedRowCount() const
217     {
218 	    return sal_Int32( m_pImpl->getSelectedRowCount() );
219     }
220 
221     //------------------------------------------------------------------------------------------------------------------
GetSelectedRowIndex(sal_Int32 const i_selectionIndex) const222     sal_Int32 TableControl::GetSelectedRowIndex( sal_Int32 const i_selectionIndex ) const
223     {
224 	    return sal_Int32( m_pImpl->getSelectedRowIndex( i_selectionIndex ) );
225     }
226 
227     //------------------------------------------------------------------------------------------------------------------
IsRowSelected(sal_Int32 const i_rowIndex) const228     bool TableControl::IsRowSelected( sal_Int32 const i_rowIndex ) const
229     {
230 	    return m_pImpl->isRowSelected( i_rowIndex );
231     }
232 
233     // -----------------------------------------------------------------------------------------------------------------
SelectRow(RowPos const i_rowIndex,bool const i_select)234     void TableControl::SelectRow( RowPos const i_rowIndex, bool const i_select )
235     {
236         ENSURE_OR_RETURN_VOID( ( i_rowIndex >= 0 ) && ( i_rowIndex < m_pImpl->getModel()->getRowCount() ),
237             "TableControl::SelectRow: invalid row index!" );
238 
239         if ( i_select )
240         {
241             if ( !m_pImpl->markRowAsSelected( i_rowIndex ) )
242                 // nothing to do
243                 return;
244         }
245         else
246         {
247             m_pImpl->markRowAsDeselected( i_rowIndex );
248         }
249 
250 		m_pImpl->invalidateRowRange( i_rowIndex, i_rowIndex );
251 	    Select();
252     }
253 
254     // -----------------------------------------------------------------------------------------------------------------
SelectAllRows(bool const i_select)255     void TableControl::SelectAllRows( bool const i_select )
256     {
257         if ( i_select )
258         {
259             if ( !m_pImpl->markAllRowsAsSelected() )
260                 // nothing to do
261                 return;
262         }
263         else
264         {
265             if ( !m_pImpl->markAllRowsAsDeselected() )
266                 // nothing to do
267                 return;
268         }
269 
270 
271         Invalidate();
272             // TODO: can't we do better than this, and invalidate only the rows which changed?
273         Select();
274     }
275 
276     // -----------------------------------------------------------------------------------------------------------------
getTableControlInterface()277     ITableControl& TableControl::getTableControlInterface()
278     {
279         return *m_pImpl;
280     }
281 
282     // -----------------------------------------------------------------------------------------------------------------
getSelEngine()283 	SelectionEngine* TableControl::getSelEngine()
284 	{
285 		return m_pImpl->getSelEngine();
286 	}
287 
288     // -----------------------------------------------------------------------------------------------------------------
getDataWindow()289 	Window& TableControl::getDataWindow()
290 	{
291 		return m_pImpl->getDataWindow();
292 	}
293 
294     // -----------------------------------------------------------------------------------------------------------------
CreateAccessible()295 	Reference< XAccessible > TableControl::CreateAccessible()
296 	{
297 		Window* pParent = GetAccessibleParentWindow();
298 		ENSURE_OR_RETURN( pParent, "TableControl::CreateAccessible - parent not found", NULL );
299 
300         return m_pImpl->getAccessible( *pParent );
301 	}
302 
303     // -----------------------------------------------------------------------------------------------------------------
CreateAccessibleControl(sal_Int32 _nIndex)304 	Reference<XAccessible> TableControl::CreateAccessibleControl( sal_Int32 _nIndex )
305 	{
306 		(void)_nIndex;
307 		DBG_ASSERT( sal_False, "TableControl::CreateAccessibleControl: to be overwritten!" );
308 		return NULL;
309 	}
310 
311     // -----------------------------------------------------------------------------------------------------------------
GetAccessibleObjectName(AccessibleTableControlObjType eObjType,sal_Int32 _nRow,sal_Int32 _nCol) const312 	::rtl::OUString TableControl::GetAccessibleObjectName( AccessibleTableControlObjType eObjType, sal_Int32 _nRow, sal_Int32 _nCol) const
313 	{
314 		::rtl::OUString aRetText;
315 		//Window* pWin;
316 		switch( eObjType )
317 		{
318 			case TCTYPE_GRIDCONTROL:
319 				aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Grid control" ) );
320 				break;
321 			case TCTYPE_TABLE:
322 				aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Grid conrol" ) );
323 				break;
324 			case TCTYPE_ROWHEADERBAR:
325 				aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RowHeaderBar" ) );
326 				break;
327 			case TCTYPE_COLUMNHEADERBAR:
328 				aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ColumnHeaderBar" ) );
329 				break;
330 			case TCTYPE_TABLECELL:
331 				//the name of the cell constists of column name and row name if defined
332 				//if the name is equal to cell content, it'll be read twice
333 				if(GetModel()->hasColumnHeaders())
334 				{
335 					aRetText = GetColumnName(_nCol);
336 					aRetText += rtl::OUString::createFromAscii(" , ");
337 				}
338 				if(GetModel()->hasRowHeaders())
339 				{
340 					aRetText += GetRowName(_nRow);
341 					aRetText += rtl::OUString::createFromAscii(" , ");
342 				}
343 				//aRetText = GetAccessibleCellText(_nRow, _nCol);
344 				break;
345 			case TCTYPE_ROWHEADERCELL:
346 				aRetText = GetRowName(_nRow);
347 				break;
348 			case TCTYPE_COLUMNHEADERCELL:
349 				aRetText = GetColumnName(_nCol);
350 				break;
351 			default:
352 				OSL_ENSURE(0,"GridControl::GetAccessibleName: invalid enum!");
353 		}
354 		return aRetText;
355 	}
356 
357     //------------------------------------------------------------------------------------------------------------------
GetAccessibleObjectDescription(AccessibleTableControlObjType eObjType,sal_Int32) const358     ::rtl::OUString TableControl::GetAccessibleObjectDescription( AccessibleTableControlObjType eObjType, sal_Int32 ) const
359     {
360         ::rtl::OUString aRetText;
361         switch( eObjType )
362         {
363             case TCTYPE_GRIDCONTROL:
364 			    aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Grid control description" ) );
365 			    break;
366             case TCTYPE_TABLE:
367 				    aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TABLE description" ) );
368 			    break;
369             case TCTYPE_ROWHEADERBAR:
370 				    aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ROWHEADERBAR description" ) );
371 			    break;
372             case TCTYPE_COLUMNHEADERBAR:
373 				    aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "COLUMNHEADERBAR description" ) );
374 			    break;
375             case TCTYPE_TABLECELL:
376                 // the description of the cell consists of column name and row name if defined
377                 // if the name is equal to cell content, it'll be read twice
378                 if ( GetModel()->hasColumnHeaders() )
379                 {
380                     aRetText = GetColumnName( GetCurrentColumn() );
381                     aRetText += rtl::OUString::createFromAscii( " , " );
382                 }
383                 if ( GetModel()->hasRowHeaders() )
384                 {
385                     aRetText += GetRowName( GetCurrentRow() );
386                 }
387                 break;
388             case TCTYPE_ROWHEADERCELL:
389 				    aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ROWHEADERCELL description" ) );
390 			    break;
391             case TCTYPE_COLUMNHEADERCELL:
392 				    aRetText = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "COLUMNHEADERCELL description" ) );
393 			    break;
394         }
395         return aRetText;
396     }
397 
398     //------------------------------------------------------------------------------------------------------------------
GetRowDescription(sal_Int32 _nRow) const399     ::rtl::OUString TableControl::GetRowDescription( sal_Int32 _nRow) const
400     {
401 	    (void)_nRow;
402 	    return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "row description" ) );
403     }
404 
405     //------------------------------------------------------------------------------------------------------------------
GetRowName(sal_Int32 _nIndex) const406     ::rtl::OUString TableControl::GetRowName( sal_Int32 _nIndex) const
407     {
408         ::rtl::OUString sRowName;
409         GetModel()->getRowHeading( _nIndex ) >>= sRowName;
410         return sRowName;
411     }
412 
413     //------------------------------------------------------------------------------------------------------------------
GetColumnDescription(sal_uInt16 _nColumn) const414     ::rtl::OUString TableControl::GetColumnDescription( sal_uInt16 _nColumn) const
415     {
416 	    (void)_nColumn;
417 	    return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "col description" ) );
418     }
419 
420     //------------------------------------------------------------------------------------------------------------------
GetColumnName(sal_Int32 _nIndex) const421     ::rtl::OUString TableControl::GetColumnName( sal_Int32 _nIndex) const
422     {
423 	    return GetModel()->getColumnModel(_nIndex)->getName();
424     }
425 
426     //------------------------------------------------------------------------------------------------------------------
GetCellContent(sal_Int32 _nRowPos,sal_Int32 _nColPos) const427     ::com::sun::star::uno::Any TableControl::GetCellContent( sal_Int32 _nRowPos, sal_Int32 _nColPos ) const
428     {
429         Any aCellContent;
430         GetModel()->getCellContent( _nColPos, _nRowPos, aCellContent );
431         return aCellContent;
432     }
433 
434     //------------------------------------------------------------------------------------------------------------------
GetAccessibleCellText(sal_Int32 _nRowPos,sal_Int32 _nColPos) const435     ::rtl::OUString TableControl::GetAccessibleCellText( sal_Int32 _nRowPos, sal_Int32 _nColPos) const
436     {
437 	    return m_pImpl->getCellContentAsString( _nRowPos, _nColPos );
438     }
439 
440     //------------------------------------------------------------------------------------------------------------------
FillAccessibleStateSet(::utl::AccessibleStateSetHelper & rStateSet,AccessibleTableControlObjType eObjType) const441     void TableControl::FillAccessibleStateSet(
442             ::utl::AccessibleStateSetHelper& rStateSet,
443             AccessibleTableControlObjType eObjType ) const
444     {
445 	    switch( eObjType )
446         {
447             case TCTYPE_GRIDCONTROL:
448 		    case TCTYPE_TABLE:
449 
450 			    rStateSet.AddState( AccessibleStateType::FOCUSABLE );
451 
452                 if ( m_pImpl->getSelEngine()->GetSelectionMode() == MULTIPLE_SELECTION )
453 			        rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE);
454 
455                 if ( HasChildPathFocus() )
456 				    rStateSet.AddState( AccessibleStateType::FOCUSED );
457 
458                 if ( IsActive() )
459 				    rStateSet.AddState( AccessibleStateType::ACTIVE );
460 
461                 if ( m_pImpl->getDataWindow().IsEnabled() )
462                 {
463                     rStateSet.AddState( AccessibleStateType::ENABLED );
464                     rStateSet.AddState( AccessibleStateType::SENSITIVE );
465                 }
466 
467                 if ( IsReallyVisible() )
468 				    rStateSet.AddState( AccessibleStateType::VISIBLE );
469 
470                 if ( eObjType == TCTYPE_TABLE )
471 			        rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
472 			    break;
473 
474             case TCTYPE_ROWHEADERBAR:
475 			    rStateSet.AddState( AccessibleStateType::VISIBLE );
476 			    rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
477 			    break;
478 
479             case TCTYPE_COLUMNHEADERBAR:
480 			    rStateSet.AddState( AccessibleStateType::VISIBLE );
481 			    rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS );
482 			    break;
483 
484             case TCTYPE_TABLECELL:
485 			    {
486                     rStateSet.AddState( AccessibleStateType::FOCUSABLE );
487                     if ( HasChildPathFocus() )
488 	                    rStateSet.AddState( AccessibleStateType::FOCUSED );
489                     rStateSet.AddState( AccessibleStateType::ACTIVE );
490 				    rStateSet.AddState( AccessibleStateType::TRANSIENT );
491 				    rStateSet.AddState( AccessibleStateType::SELECTABLE);
492                     rStateSet.AddState( AccessibleStateType::VISIBLE );
493                     rStateSet.AddState( AccessibleStateType::SHOWING );
494                     if ( IsRowSelected( GetCurrentRow() ) )
495                         // Hmm? Wouldn't we expect the affected row to be a parameter to this function?
496 					    rStateSet.AddState( AccessibleStateType::SELECTED );
497 			    }
498 			    break;
499 
500             case TCTYPE_ROWHEADERCELL:
501 			    rStateSet.AddState( AccessibleStateType::VISIBLE );
502 			    rStateSet.AddState( AccessibleStateType::TRANSIENT );
503 			    break;
504 
505             case TCTYPE_COLUMNHEADERCELL:
506 			    rStateSet.AddState( AccessibleStateType::VISIBLE );
507 			    break;
508 	    }
509     }
510 
511     //------------------------------------------------------------------------------------------------------------------
commitCellEventIfAccessibleAlive(sal_Int16 const i_eventID,const Any & i_newValue,const Any & i_oldValue)512     void TableControl::commitCellEventIfAccessibleAlive( sal_Int16 const i_eventID, const Any& i_newValue, const Any& i_oldValue )
513     {
514         if ( m_pImpl->isAccessibleAlive() )
515             m_pImpl->commitCellEvent( i_eventID, i_newValue, i_oldValue );
516     }
517 
518     //------------------------------------------------------------------------------------------------------------------
commitTableEventIfAccessibleAlive(sal_Int16 const i_eventID,const Any & i_newValue,const Any & i_oldValue)519     void TableControl::commitTableEventIfAccessibleAlive( sal_Int16 const i_eventID, const Any& i_newValue, const Any& i_oldValue )
520     {
521         if ( m_pImpl->isAccessibleAlive() )
522             m_pImpl->commitTableEvent( i_eventID, i_newValue, i_oldValue );
523     }
524 
525     //------------------------------------------------------------------------------------------------------------------
GetWindowExtentsRelative(Window * pRelativeWindow) const526     Rectangle TableControl::GetWindowExtentsRelative( Window *pRelativeWindow ) const
527     {
528 	    return Control::GetWindowExtentsRelative( pRelativeWindow );
529     }
530 
531     //------------------------------------------------------------------------------------------------------------------
GrabFocus()532     void TableControl::GrabFocus()
533     {
534 	    Control::GrabFocus();
535     }
536 
537     //------------------------------------------------------------------------------------------------------------------
GetAccessible(sal_Bool bCreate)538     Reference< XAccessible > TableControl::GetAccessible( sal_Bool bCreate )
539     {
540 	    return Control::GetAccessible( bCreate );
541     }
542 
543     //------------------------------------------------------------------------------------------------------------------
GetAccessibleParentWindow() const544     Window* TableControl::GetAccessibleParentWindow() const
545     {
546 	    return Control::GetAccessibleParentWindow();
547     }
548 
549     //------------------------------------------------------------------------------------------------------------------
GetWindowInstance()550     Window* TableControl::GetWindowInstance()
551     {
552 	    return this;
553     }
554 
555     //------------------------------------------------------------------------------------------------------------------
HasRowHeader()556     sal_Bool TableControl::HasRowHeader()
557     {
558 	    return GetModel()->hasRowHeaders();
559     }
560 
561     //------------------------------------------------------------------------------------------------------------------
HasColHeader()562     sal_Bool TableControl::HasColHeader()
563     {
564 	    return GetModel()->hasColumnHeaders();
565     }
566 
567     //------------------------------------------------------------------------------------------------------------------
GetAccessibleControlCount() const568     sal_Int32 TableControl::GetAccessibleControlCount() const
569     {
570         // TC_TABLE is always defined, no matter whether empty or not
571         sal_Int32 count = 1;
572 	    if ( GetModel()->hasRowHeaders() )
573 		    ++count;
574 	    if ( GetModel()->hasColumnHeaders() )
575 		    ++count;
576 	    return count;
577     }
578 
579     //------------------------------------------------------------------------------------------------------------------
ConvertPointToControlIndex(sal_Int32 & _rnIndex,const Point & _rPoint)580     sal_Bool TableControl::ConvertPointToControlIndex( sal_Int32& _rnIndex, const Point& _rPoint )
581     {
582 	    sal_Int32 nRow = m_pImpl->getRowAtPoint( _rPoint );
583 	    sal_Int32 nCol = m_pImpl->getColAtPoint( _rPoint );
584 	    _rnIndex = nRow * GetColumnCount() + nCol;
585         return nRow >= 0 ? sal_True : sal_False;
586     }
587 
588     //------------------------------------------------------------------------------------------------------------------
GetRowCount() const589     long TableControl::GetRowCount() const
590     {
591 	    return GetModel()->getRowCount();
592     }
593 
594     //------------------------------------------------------------------------------------------------------------------
GetColumnCount() const595     long TableControl::GetColumnCount() const
596     {
597 	    return GetModel()->getColumnCount();
598     }
599 
600     //------------------------------------------------------------------------------------------------------------------
HasRowHeader() const601     sal_Bool TableControl::HasRowHeader() const
602     {
603 	    return GetModel()->hasRowHeaders();
604     }
605 
606     //------------------------------------------------------------------------------------------------------------------
ConvertPointToCellAddress(sal_Int32 & _rnRow,sal_Int32 & _rnColPos,const Point & _rPoint)607     sal_Bool TableControl::ConvertPointToCellAddress( sal_Int32& _rnRow, sal_Int32& _rnColPos, const Point& _rPoint )
608     {
609 	    _rnRow = m_pImpl->getRowAtPoint( _rPoint );
610 	    _rnColPos = m_pImpl->getColAtPoint( _rPoint );
611 	    return _rnRow >= 0 ? sal_True : sal_False;
612     }
613 
614     //------------------------------------------------------------------------------------------------------------------
FillAccessibleStateSetForCell(::utl::AccessibleStateSetHelper & _rStateSet,sal_Int32 _nRow,sal_uInt16 _nColumnPos) const615     void TableControl::FillAccessibleStateSetForCell( ::utl::AccessibleStateSetHelper& _rStateSet, sal_Int32 _nRow, sal_uInt16 _nColumnPos ) const
616     {
617         if ( IsRowSelected( _nRow ) )
618             _rStateSet.AddState( AccessibleStateType::SELECTED );
619 	    if ( HasChildPathFocus() )
620 		    _rStateSet.AddState( AccessibleStateType::FOCUSED );
621 	    else // only transient when column is not focused
622 		    _rStateSet.AddState( AccessibleStateType::TRANSIENT );
623 
624         _rStateSet.AddState( AccessibleStateType::VISIBLE );
625         _rStateSet.AddState( AccessibleStateType::SHOWING );
626         _rStateSet.AddState( AccessibleStateType::ENABLED );
627         _rStateSet.AddState( AccessibleStateType::SENSITIVE );
628         _rStateSet.AddState( AccessibleStateType::ACTIVE );
629 
630         (void)_nColumnPos;
631     }
632 
633     //------------------------------------------------------------------------------------------------------------------
GetFieldCharacterBounds(sal_Int32 _nRow,sal_Int32 _nColumnPos,sal_Int32 nIndex)634     Rectangle TableControl::GetFieldCharacterBounds(sal_Int32 _nRow,sal_Int32 _nColumnPos,sal_Int32 nIndex)
635     {
636 	    (void)_nRow;
637 	    (void)_nColumnPos;
638 	    return GetCharacterBounds(nIndex);
639     }
640 
641     //------------------------------------------------------------------------------------------------------------------
GetFieldIndexAtPoint(sal_Int32 _nRow,sal_Int32 _nColumnPos,const Point & _rPoint)642     sal_Int32 TableControl::GetFieldIndexAtPoint(sal_Int32 _nRow,sal_Int32 _nColumnPos,const Point& _rPoint)
643     {
644 	    (void)_nRow;
645 	    (void)_nColumnPos;
646 	    return GetIndexForPoint(_rPoint);
647     }
648 
649     //------------------------------------------------------------------------------------------------------------------
calcHeaderRect(sal_Bool _bIsColumnBar,sal_Bool _bOnScreen)650     Rectangle TableControl::calcHeaderRect(sal_Bool _bIsColumnBar,sal_Bool _bOnScreen)
651     {
652 	    (void)_bOnScreen;
653         return m_pImpl->calcHeaderRect( _bIsColumnBar ? false : true );
654     }
655 
656     //------------------------------------------------------------------------------------------------------------------
calcHeaderCellRect(sal_Bool _bIsColumnBar,sal_Int32 nPos)657     Rectangle TableControl::calcHeaderCellRect( sal_Bool _bIsColumnBar, sal_Int32 nPos )
658     {
659         return m_pImpl->calcHeaderCellRect( _bIsColumnBar, nPos );
660     }
661 
662     //------------------------------------------------------------------------------------------------------------------
calcTableRect(sal_Bool _bOnScreen)663     Rectangle TableControl::calcTableRect(sal_Bool _bOnScreen)
664     {
665 	    (void)_bOnScreen;
666 	    return m_pImpl->calcTableRect();
667     }
668 
669     //------------------------------------------------------------------------------------------------------------------
calcCellRect(sal_Int32 _nRowPos,sal_Int32 _nColPos)670     Rectangle TableControl::calcCellRect( sal_Int32 _nRowPos, sal_Int32 _nColPos )
671     {
672         return m_pImpl->calcCellRect( _nRowPos, _nColPos );
673     }
674     //------------------------------------------------------------------------------------------------------------------
IMPL_LINK(TableControl,ImplSelectHdl,void *,EMPTYARG)675     IMPL_LINK( TableControl, ImplSelectHdl, void*, EMPTYARG )
676     {
677 	    Select();
678 	    return 1;
679     }
680 
681     //------------------------------------------------------------------------------------------------------------------
Select()682     void TableControl::Select()
683     {
684         ImplCallEventListenersAndHandler( VCLEVENT_TABLEROW_SELECT, m_pImpl->getSelectHandler(), this );
685 
686         if ( m_pImpl->isAccessibleAlive() )
687         {
688             m_pImpl->commitAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
689 
690             m_pImpl->commitTableEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, Any(), Any() );
691                 // TODO: why do we notify this when the *selection* changed? Shouldn't we find a better place for this,
692                 // actually, when the active descendant, i.e. the current cell, *really* changed?
693         }
694     }
695 
696     //------------------------------------------------------------------------------------------------------------------
SetSelectHdl(const Link & i_selectHandler)697     void TableControl::SetSelectHdl( const Link& i_selectHandler )
698     {
699         m_pImpl->setSelectHandler( i_selectHandler );
700     }
701 
702     //------------------------------------------------------------------------------------------------------------------
GetSelectHdl() const703     const Link& TableControl::GetSelectHdl() const
704     {
705         return m_pImpl->getSelectHandler();
706     }
707 
708 //......................................................................................................................
709 }} // namespace svt::table
710 //......................................................................................................................
711