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