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