1 /************************************************************************* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * Copyright 2000, 2010 Oracle and/or its affiliates. 5 * 6 * OpenOffice.org - a multi-platform office productivity suite 7 * 8 * This file is part of OpenOffice.org. 9 * 10 * OpenOffice.org is free software: you can redistribute it and/or modify 11 * it under the terms of the GNU Lesser General Public License version 3 12 * only, as published by the Free Software Foundation. 13 * 14 * OpenOffice.org is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU Lesser General Public License version 3 for more details 18 * (a copy is included in the LICENSE file that accompanied this code). 19 * 20 * You should have received a copy of the GNU Lesser General Public License 21 * version 3 along with OpenOffice.org. If not, see 22 * <http://www.openoffice.org/license.html> 23 * for a copy of the LGPLv3 License. 24 * 25 ************************************************************************/ 26 27 #ifndef SVTOOLS_TABLECONTROL_IMPL_HXX 28 #define SVTOOLS_TABLECONTROL_IMPL_HXX 29 30 #include "svtools/table/tablemodel.hxx" 31 #include "svtools/table/tablecontrolinterface.hxx" 32 33 #include "svtaccessiblefactory.hxx" 34 35 #include <vcl/seleng.hxx> 36 37 #include <vector> 38 39 #include <boost/scoped_ptr.hpp> 40 41 class ScrollBar; 42 class ScrollBarBox; 43 44 //........................................................................ 45 namespace svt { namespace table 46 { 47 //........................................................................ 48 49 struct MutableColumnMetrics : protected ColumnMetrics 50 { 51 MutableColumnMetrics() 52 :ColumnMetrics() 53 { 54 } 55 56 MutableColumnMetrics( long const i_startPixel, long const i_endPixel ) 57 :ColumnMetrics( i_startPixel, i_endPixel ) 58 { 59 } 60 61 long getStart() const { return nStartPixel; } 62 long getEnd() const { return nEndPixel; } 63 64 void setEnd( long const i_end ) { nEndPixel = i_end; } 65 void move( long const i_offset ) { nStartPixel += i_offset; nEndPixel += i_offset; } 66 67 long getWidth() const { return nEndPixel - nStartPixel; } 68 69 ColumnMetrics const & operator()() { return *this; } 70 }; 71 72 struct ColumnInfoPositionLess 73 { 74 bool operator()( MutableColumnMetrics const& i_colInfo, long const i_position ) 75 { 76 return i_colInfo.getEnd() < i_position; 77 } 78 bool operator()( long const i_position, MutableColumnMetrics const& i_colInfo ) 79 { 80 return i_position < i_colInfo.getStart(); 81 } 82 }; 83 84 typedef ::std::vector< MutableColumnMetrics > ColumnPositions; 85 86 class TableControl; 87 class TableDataWindow; 88 class TableFunctionSet; 89 90 //==================================================================== 91 //= TableControl_Impl 92 //==================================================================== 93 class TableControl_Impl :public ITableControl 94 ,public ITableModelListener 95 { 96 friend class TableGeometry; 97 friend class TableRowGeometry; 98 friend class TableColumnGeometry; 99 friend class SuspendInvariants; 100 101 private: 102 /// the control whose impl-instance we implemnt 103 TableControl& m_rAntiImpl; 104 /// the model of the table control 105 PTableModel m_pModel; 106 /// the input handler to use, usually the input handler as provided by ->m_pModel 107 PTableInputHandler m_pInputHandler; 108 /// info about the widths of our columns 109 ColumnPositions m_aColumnWidths; 110 111 /// the height of a single row in the table, measured in pixels 112 long m_nRowHeightPixel; 113 /// the height of the column header row in the table, measured in pixels 114 long m_nColHeaderHeightPixel; 115 /// the width of the row header column in the table, measured in pixels 116 long m_nRowHeaderWidthPixel; 117 118 /// the number of columns in the table control. Cached model value. 119 TableSize m_nColumnCount; 120 121 /// the number of rows in the table control. Cached model value. 122 TableSize m_nRowCount; 123 124 /// denotes whether or not the columns fitted into the available width, last time we checked 125 long m_bColumnsFit; 126 127 ColPos m_nCurColumn; 128 RowPos m_nCurRow; 129 ColPos m_nLeftColumn; 130 RowPos m_nTopRow; 131 132 sal_Int32 m_nCursorHidden; 133 134 /** the window to contain all data content, including header bars 135 136 The window's upper left corner is at position (0,0), relative to the 137 table control, which is the direct parent of the data window. 138 */ 139 ::boost::scoped_ptr< TableDataWindow > 140 m_pDataWindow; 141 /// the vertical scrollbar, if any 142 ScrollBar* m_pVScroll; 143 /// the horizontal scrollbar, if any 144 ScrollBar* m_pHScroll; 145 ScrollBarBox* m_pScrollCorner; 146 //selection engine - for determining selection range, e.g. single, multiple 147 SelectionEngine* m_pSelEngine; 148 //vector which contains the selected rows 149 std::vector<RowPos> m_aSelectedRows; 150 //part of selection engine 151 TableFunctionSet* m_pTableFunctionSet; 152 //part of selection engine 153 RowPos m_nAnchor; 154 bool m_bUpdatingColWidths; 155 156 Link m_aSelectHdl; 157 158 AccessibleFactoryAccess m_aFactoryAccess; 159 IAccessibleTableControl* m_pAccessibleTable; 160 161 #if DBG_UTIL 162 #define INV_SCROLL_POSITION 1 163 /** represents a bitmask of invariants to check 164 165 Actually, impl_checkInvariants checks more invariants than denoted in this 166 bit mask, but only those present here can be disabled temporarily. 167 */ 168 sal_Int32 m_nRequiredInvariants; 169 #endif 170 171 public: 172 void setModel( PTableModel _pModel ); 173 174 inline const PTableInputHandler& getInputHandler() const { return m_pInputHandler; } 175 176 inline RowPos getCurRow() const { return m_nCurRow; } 177 inline void setCurRow( RowPos i_curRow ){ m_nCurRow = i_curRow; } 178 179 RowPos getAnchor() const { return m_nAnchor; } 180 void setAnchor( RowPos const i_anchor ) { m_nAnchor = i_anchor; } 181 182 inline RowPos getTopRow() const { return m_nTopRow; } 183 inline ColPos getLeftColumn() const { return m_nLeftColumn; } 184 185 inline const TableControl& getAntiImpl() const { return m_rAntiImpl; } 186 inline TableControl& getAntiImpl() { return m_rAntiImpl; } 187 188 public: 189 TableControl_Impl( TableControl& _rAntiImpl ); 190 ~TableControl_Impl(); 191 192 #if DBG_UTIL 193 const sal_Char* impl_checkInvariants() const; 194 #endif 195 /** to be called when the anti-impl instance has been resized 196 */ 197 void onResize(); 198 199 /** paints the table control content which intersects with the given rectangle 200 */ 201 void doPaintContent( const Rectangle& _rUpdateRect ); 202 203 /** moves the cursor to the cell with the given coordinates 204 205 To ease the caller's code, the coordinates must not necessarily denote a 206 valid position. If they don't, <FALSE/> will be returned. 207 */ 208 bool goTo( ColPos _nColumn, RowPos _nRow ); 209 210 /** ensures that the given coordinate is visible 211 @param _nColumn 212 the column position which should be visible. Must be non-negative, and smaller 213 than the column count. 214 @param _nRow 215 the row position which should be visibleMust be non-negative, and smaller 216 than the row count. 217 @param _bAcceptPartialVisibility 218 <TRUE/> if it's okay that the given cooordinate is only partially visible 219 */ 220 void ensureVisible( ColPos _nColumn, RowPos _nRow, bool _bAcceptPartialVisibility ); 221 222 /** retrieves the content of the given cell, converted to a string 223 */ 224 ::rtl::OUString getCellContentAsString( RowPos const i_row, ColPos const i_col ); 225 226 /** returns the position of the current row in the selection vector */ 227 int getRowSelectedNumber(const ::std::vector<RowPos>& selectedRows, RowPos current); 228 229 /** ??? */ 230 void invalidateSelectedRegion( RowPos _nPrevRow, RowPos _nCurRow ); 231 232 /** invalidates the part of the data window which is covered by the given rows 233 @param i_firstRow 234 the index of the first row to include in the invalidation 235 @param i_lastRow 236 the index of the last row to include in the invalidation, or ROW_INVALID if the invalidation 237 should happen down to the bottom of the data window. 238 */ 239 void invalidateRowRange( RowPos const i_firstRow, RowPos const i_lastRow ); 240 241 /** invalidates the part of the data window which is covered by the given row 242 */ 243 void invalidateRow( RowPos const i_row ) { invalidateRowRange( i_row, i_row ); } 244 245 /** invalidates all selected rows 246 */ 247 void invalidateSelectedRows(); 248 249 void checkCursorPosition(); 250 251 bool hasRowSelection() const { return !m_aSelectedRows.empty(); } 252 size_t getSelectedRowCount() const { return m_aSelectedRows.size(); } 253 RowPos getSelectedRowIndex( size_t const i_selectionIndex ) const; 254 255 /** removes the given row index from m_aSelectedRows 256 257 @return 258 <TRUE/> if and only if the row was previously marked as selected 259 */ 260 bool markRowAsDeselected( RowPos const i_rowIndex ); 261 262 /** marks the given row as selectged, by putting it into m_aSelectedRows 263 @return 264 <TRUE/> if and only if the row was previously <em>not</em> marked as selected 265 */ 266 bool markRowAsSelected( RowPos const i_rowIndex ); 267 268 /** marks all rows as deselected 269 @return 270 <TRUE/> if and only if the selection actually changed by this operation 271 */ 272 bool markAllRowsAsDeselected(); 273 274 /** marks all rows as selected 275 @return 276 <FALSE/> if and only if all rows were selected already. 277 */ 278 bool markAllRowsAsSelected(); 279 280 void setSelectHandler( Link const & i_selectHandler ) { m_aSelectHdl = i_selectHandler; } 281 Link const& getSelectHandler() const { return m_aSelectHdl; } 282 283 void commitAccessibleEvent( sal_Int16 const i_eventID, const com::sun::star::uno::Any& i_newValue, const com::sun::star::uno::Any& i_oldValue ); 284 void commitCellEvent( sal_Int16 const i_eventID, const com::sun::star::uno::Any& i_newValue, const com::sun::star::uno::Any& i_oldValue ); 285 void commitTableEvent( sal_Int16 const i_eventID, const com::sun::star::uno::Any& i_newValue, const com::sun::star::uno::Any& i_oldValue ); 286 287 // ITableControl 288 virtual void hideCursor(); 289 virtual void showCursor(); 290 virtual bool dispatchAction( TableControlAction _eAction ); 291 virtual SelectionEngine* getSelEngine(); 292 virtual PTableModel getModel() const; 293 virtual ColPos getCurrentColumn() const; 294 virtual RowPos getCurrentRow() const; 295 virtual bool activateCell( ColPos const i_col, RowPos const i_row ); 296 virtual ::Size getTableSizePixel() const; 297 virtual void setPointer( Pointer const & i_pointer ); 298 virtual void captureMouse(); 299 virtual void releaseMouse(); 300 virtual void invalidate( TableArea const i_what ); 301 virtual long pixelWidthToAppFont( long const i_pixels ) const; 302 virtual void hideTracking(); 303 virtual void showTracking( Rectangle const & i_location, sal_uInt16 const i_flags ); 304 virtual RowPos getRowAtPoint( const Point& rPoint ) const; 305 virtual ColPos getColAtPoint( const Point& rPoint ) const; 306 virtual TableCell hitTest( const Point& rPoint ) const; 307 virtual ColumnMetrics getColumnMetrics( ColPos const i_column ) const; 308 virtual bool isRowSelected( RowPos i_row ) const; 309 310 311 long appFontWidthToPixel( long const i_appFontUnits ) const; 312 313 TableDataWindow& getDataWindow() { return *m_pDataWindow; } 314 const TableDataWindow& getDataWindow() const { return *m_pDataWindow; } 315 ScrollBar* getHorzScrollbar(); 316 ScrollBar* getVertScrollbar(); 317 318 Rectangle calcHeaderRect( bool bColHeader ); 319 Rectangle calcHeaderCellRect( bool bColHeader, sal_Int32 nPos ); 320 Rectangle calcTableRect(); 321 Rectangle calcCellRect( sal_Int32 nRow, sal_Int32 nCol ); 322 323 // A11Y 324 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > 325 getAccessible( Window& i_parentWindow ); 326 void disposeAccessible(); 327 328 inline bool isAccessibleAlive() const { return impl_isAccessibleAlive(); } 329 330 // ITableModelListener 331 virtual void rowsInserted( RowPos first, RowPos last ); 332 virtual void rowsRemoved( RowPos first, RowPos last ); 333 virtual void columnInserted( ColPos const i_colIndex ); 334 virtual void columnRemoved( ColPos const i_colIndex ); 335 virtual void allColumnsRemoved(); 336 virtual void cellsUpdated( ColPos const i_firstCol, ColPos i_lastCol, RowPos const i_firstRow, RowPos const i_lastRow ); 337 virtual void columnChanged( ColPos const i_column, ColumnAttributeGroup const i_attributeGroup ); 338 virtual void tableMetricsChanged(); 339 340 private: 341 bool impl_isAccessibleAlive() const; 342 void impl_commitAccessibleEvent( 343 sal_Int16 const i_eventID, 344 ::com::sun::star::uno::Any const & i_newValue, 345 ::com::sun::star::uno::Any const & i_oldValue 346 ); 347 348 /** toggles the cursor visibility 349 350 The method is not bound to the classes public invariants, as it's used in 351 situations where the they must not necessarily be fullfilled. 352 */ 353 void impl_ni_doSwitchCursor( bool _bOn ); 354 355 /** returns the number of visible rows. 356 357 @param _bAcceptPartialRow 358 specifies whether a possible only partially visible last row is 359 counted, too. 360 */ 361 TableSize impl_getVisibleRows( bool _bAcceptPartialRow ) const; 362 363 /** returns the number of visible columns 364 365 The value may change with different horizontal scroll positions, as 366 different columns have different widths. For instance, if your control is 367 100 pixels wide, and has three columns of width 50, 50, 100, respectively, 368 then this method will return either "2" or "1", depending on which column 369 is the first visible one. 370 371 @param _bAcceptPartialRow 372 specifies whether a possible only partially visible last row is 373 counted, too. 374 */ 375 TableSize impl_getVisibleColumns( bool _bAcceptPartialCol ) const; 376 377 /** determines the rectangle occupied by the given cell 378 */ 379 void impl_getCellRect( ColPos _nColumn, RowPos _nRow, Rectangle& _rCellRect ) const; 380 381 /** updates all cached model values 382 383 The method is not bound to the classes public invariants, as it's used in 384 situations where the they must not necessarily be fullfilled. 385 */ 386 void impl_ni_updateCachedModelValues(); 387 388 /** updates the cached table metrics (row height etc.) 389 */ 390 void impl_ni_updateCachedTableMetrics(); 391 392 /** does a relayout of the table control 393 394 Column widths, and consequently the availability of the vertical and horizontal scrollbar, are updated 395 with a call to this method. 396 397 @param i_assumeInflexibleColumnsUpToIncluding 398 the index of a column up to which all columns should be considered as inflexible, or 399 <code>COL_INVALID</code>. 400 */ 401 void impl_ni_relayout( ColPos const i_assumeInflexibleColumnsUpToIncluding = COL_INVALID ); 402 403 /** calculates the new width of our columns, taking into account their min and max widths, and their relative 404 flexibility. 405 406 @param i_assumeInflexibleColumnsUpToIncluding 407 the index of a column up to which all columns should be considered as inflexible, or 408 <code>COL_INVALID</code>. 409 410 @param i_assumeVerticalScrollbar 411 controls whether or not we should assume the presence of a vertical scrollbar. If <true/>, and 412 if the model has a VerticalScrollbarVisibility != ScrollbarShowNever, the method will leave 413 space for a vertical scrollbar. 414 415 @return 416 the overall width of the grid, which is available for columns 417 */ 418 long impl_ni_calculateColumnWidths( 419 ColPos const i_assumeInflexibleColumnsUpToIncluding, 420 bool const i_assumeVerticalScrollbar, 421 ::std::vector< long >& o_newColWidthsPixel 422 ) const; 423 424 /** positions all child windows, e.g. the both scrollbars, the corner window, and the data window 425 */ 426 void impl_ni_positionChildWindows( 427 Rectangle const & i_dataCellPlayground, 428 bool const i_verticalScrollbar, 429 bool const i_horizontalScrollbar 430 ); 431 432 /** scrolls the view by the given number of rows 433 434 The method is not bound to the classes public invariants, as it's used in 435 situations where the they must not necessarily be fullfilled. 436 437 @return 438 the number of rows by which the viewport was scrolled. This may differ 439 from the given numbers to scroll in case the begin or the end of the 440 row range were reached. 441 */ 442 TableSize impl_ni_ScrollRows( TableSize _nRowDelta ); 443 444 /** equivalent to impl_ni_ScrollRows, but checks the instances invariants beforehand (in a non-product build only) 445 */ 446 TableSize impl_scrollRows( TableSize const i_rowDelta ); 447 448 /** scrolls the view by the given number of columns 449 450 The method is not bound to the classes public invariants, as it's used in 451 situations where the they must not necessarily be fullfilled. 452 453 @return 454 the number of columns by which the viewport was scrolled. This may differ 455 from the given numbers to scroll in case the begin or the end of the 456 column range were reached. 457 */ 458 TableSize impl_ni_ScrollColumns( TableSize _nColumnDelta ); 459 460 /** equivalent to impl_ni_ScrollColumns, but checks the instances invariants beforehand (in a non-product build only) 461 */ 462 TableSize impl_scrollColumns( TableSize const i_columnDelta ); 463 464 /** retrieves the area occupied by the totality of (at least partially) visible cells 465 466 The returned area includes row and column headers. Also, it takes into 467 account the the fact that there might be less columns than would normally 468 find room in the control. 469 470 As a result of respecting the partial visibility of rows and columns, 471 the returned area might be larger than the data window's output size. 472 */ 473 Rectangle impl_getAllVisibleCellsArea() const; 474 475 /** retrieves the area occupied by all (at least partially) visible data cells. 476 477 Effectively, the returned area is the same as returned by ->impl_getAllVisibleCellsArea, 478 minus the row and column header areas. 479 */ 480 Rectangle impl_getAllVisibleDataCellArea() const; 481 482 /** retrieves the column which covers the given ordinate 483 */ 484 ColPos impl_getColumnForOrdinate( long const i_ordinate ) const; 485 486 /** retrieves the row which covers the given abscissa 487 */ 488 RowPos impl_getRowForAbscissa( long const i_abscissa ) const; 489 490 /// invalidates the window area occupied by the given column 491 void impl_invalidateColumn( ColPos const i_column ); 492 493 DECL_LINK( OnScroll, ScrollBar* ); 494 DECL_LINK( OnUpdateScrollbars, void* ); 495 }; 496 497 //see seleng.hxx, seleng.cxx, FunctionSet overridables, part of selection engine 498 class TableFunctionSet : public FunctionSet 499 { 500 private: 501 TableControl_Impl* m_pTableControl; 502 RowPos m_nCurrentRow; 503 504 public: 505 TableFunctionSet(TableControl_Impl* _pTableControl); 506 virtual ~TableFunctionSet(); 507 508 virtual void BeginDrag(); 509 virtual void CreateAnchor(); 510 virtual void DestroyAnchor(); 511 virtual sal_Bool SetCursorAtPoint(const Point& rPoint, sal_Bool bDontSelectAtCursor); 512 virtual sal_Bool IsSelectionAtPoint( const Point& rPoint ); 513 virtual void DeselectAtPoint( const Point& rPoint ); 514 virtual void DeselectAll(); 515 }; 516 517 518 //........................................................................ 519 } } // namespace svt::table 520 //........................................................................ 521 522 #endif // SVTOOLS_TABLECONTROL_IMPL_HXX 523