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