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