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