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 16 : MutableColumnMetrics( long const i_startPixel, long const i_endPixel )
50 16 : :ColumnMetrics( i_startPixel, i_endPixel )
51 : {
52 16 : }
53 :
54 0 : long getStart() const { return nStartPixel; }
55 10 : 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 31 : 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 : #ifdef 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 2 : 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 1 : inline TableControl& getAntiImpl() { return m_rAntiImpl; }
176 :
177 : public:
178 : TableControl_Impl( TableControl& _rAntiImpl );
179 : ~TableControl_Impl();
180 :
181 : #ifdef 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 : 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 : void invalidateRect(const Rectangle &rInvalidateRect);
219 :
220 : /** ??? */
221 : void invalidateSelectedRegion( RowPos _nPrevRow, RowPos _nCurRow );
222 :
223 : /** invalidates the part of the data window which is covered by the given rows
224 : @param i_firstRow
225 : the index of the first row to include in the invalidation
226 : @param i_lastRow
227 : the index of the last row to include in the invalidation, or ROW_INVALID if the invalidation
228 : should happen down to the bottom of the data window.
229 : */
230 : void invalidateRowRange( RowPos const i_firstRow, RowPos const i_lastRow );
231 :
232 : /** invalidates the part of the data window which is covered by the given row
233 : */
234 0 : void invalidateRow( RowPos const i_row ) { invalidateRowRange( i_row, i_row ); }
235 :
236 : /** invalidates all selected rows
237 : */
238 : void invalidateSelectedRows();
239 :
240 : void checkCursorPosition();
241 :
242 0 : bool hasRowSelection() const { return !m_aSelectedRows.empty(); }
243 0 : size_t getSelectedRowCount() const { return m_aSelectedRows.size(); }
244 : RowPos getSelectedRowIndex( size_t const i_selectionIndex ) const;
245 :
246 : /** removes the given row index from m_aSelectedRows
247 :
248 : @return
249 : <TRUE/> if and only if the row was previously marked as selected
250 : */
251 : bool markRowAsDeselected( RowPos const i_rowIndex );
252 :
253 : /** marks the given row as selectged, by putting it into m_aSelectedRows
254 : @return
255 : <TRUE/> if and only if the row was previously <em>not</em> marked as selected
256 : */
257 : bool markRowAsSelected( RowPos const i_rowIndex );
258 :
259 : /** marks all rows as deselected
260 : @return
261 : <TRUE/> if and only if the selection actually changed by this operation
262 : */
263 : bool markAllRowsAsDeselected();
264 :
265 : /** marks all rows as selected
266 : @return
267 : <FALSE/> if and only if all rows were selected already.
268 : */
269 : bool markAllRowsAsSelected();
270 :
271 : void setSelectHandler( Link const & i_selectHandler ) { m_aSelectHdl = i_selectHandler; }
272 0 : Link const& getSelectHandler() const { return m_aSelectHdl; }
273 :
274 : void commitAccessibleEvent( sal_Int16 const i_eventID, const com::sun::star::uno::Any& i_newValue, const com::sun::star::uno::Any& i_oldValue );
275 : void commitCellEvent( sal_Int16 const i_eventID, const com::sun::star::uno::Any& i_newValue, const com::sun::star::uno::Any& i_oldValue );
276 : void commitTableEvent( sal_Int16 const i_eventID, const com::sun::star::uno::Any& i_newValue, const com::sun::star::uno::Any& i_oldValue );
277 :
278 : // ITableControl
279 : virtual void hideCursor();
280 : virtual void showCursor();
281 : virtual bool dispatchAction( TableControlAction _eAction );
282 : virtual SelectionEngine* getSelEngine();
283 : virtual PTableModel getModel() const;
284 : virtual ColPos getCurrentColumn() const;
285 : virtual RowPos getCurrentRow() const;
286 : virtual bool activateCell( ColPos const i_col, RowPos const i_row );
287 : virtual ::Size getTableSizePixel() const;
288 : virtual void setPointer( Pointer const & i_pointer );
289 : virtual void captureMouse();
290 : virtual void releaseMouse();
291 : virtual void invalidate( TableArea const i_what );
292 : virtual long pixelWidthToAppFont( long const i_pixels ) const;
293 : virtual void hideTracking();
294 : virtual void showTracking( Rectangle const & i_location, sal_uInt16 const i_flags );
295 : virtual RowPos getRowAtPoint( const Point& rPoint ) const;
296 : virtual ColPos getColAtPoint( const Point& rPoint ) const;
297 : virtual TableCell hitTest( const Point& rPoint ) const;
298 : virtual ColumnMetrics getColumnMetrics( ColPos const i_column ) const;
299 : virtual bool isRowSelected( RowPos i_row ) const;
300 :
301 :
302 : long appFontWidthToPixel( long const i_appFontUnits ) const;
303 :
304 2 : TableDataWindow& getDataWindow() { return *m_pDataWindow; }
305 : const TableDataWindow& getDataWindow() const { return *m_pDataWindow; }
306 : ScrollBar* getHorzScrollbar();
307 : ScrollBar* getVertScrollbar();
308 :
309 : Rectangle calcHeaderRect( bool bColHeader );
310 : Rectangle calcHeaderCellRect( bool bColHeader, sal_Int32 nPos );
311 : Rectangle calcTableRect();
312 : Rectangle calcCellRect( sal_Int32 nRow, sal_Int32 nCol );
313 :
314 : // A11Y
315 : ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >
316 : getAccessible( Window& i_parentWindow );
317 : void disposeAccessible();
318 :
319 0 : inline bool isAccessibleAlive() const { return impl_isAccessibleAlive(); }
320 :
321 : // ITableModelListener
322 : virtual void rowsInserted( RowPos first, RowPos last );
323 : virtual void rowsRemoved( RowPos first, RowPos last );
324 : virtual void columnInserted( ColPos const i_colIndex );
325 : virtual void columnRemoved( ColPos const i_colIndex );
326 : virtual void allColumnsRemoved();
327 : virtual void cellsUpdated( ColPos const i_firstCol, ColPos i_lastCol, RowPos const i_firstRow, RowPos const i_lastRow );
328 : virtual void columnChanged( ColPos const i_column, ColumnAttributeGroup const i_attributeGroup );
329 : virtual void tableMetricsChanged();
330 :
331 : private:
332 : bool impl_isAccessibleAlive() const;
333 : void impl_commitAccessibleEvent(
334 : sal_Int16 const i_eventID,
335 : ::com::sun::star::uno::Any const & i_newValue,
336 : ::com::sun::star::uno::Any const & i_oldValue
337 : );
338 :
339 : /** toggles the cursor visibility
340 :
341 : The method is not bound to the classes public invariants, as it's used in
342 : situations where the they must not necessarily be fullfilled.
343 : */
344 : void impl_ni_doSwitchCursor( bool _bOn );
345 :
346 : /** returns the number of visible rows.
347 :
348 : @param _bAcceptPartialRow
349 : specifies whether a possible only partially visible last row is
350 : counted, too.
351 : */
352 : TableSize impl_getVisibleRows( bool _bAcceptPartialRow ) const;
353 :
354 : /** returns the number of visible columns
355 :
356 : The value may change with different horizontal scroll positions, as
357 : different columns have different widths. For instance, if your control is
358 : 100 pixels wide, and has three columns of width 50, 50, 100, respectively,
359 : then this method will return either "2" or "1", depending on which column
360 : is the first visible one.
361 :
362 : @param _bAcceptPartialRow
363 : specifies whether a possible only partially visible last row is
364 : counted, too.
365 : */
366 : TableSize impl_getVisibleColumns( bool _bAcceptPartialCol ) const;
367 :
368 : /** determines the rectangle occupied by the given cell
369 : */
370 : void impl_getCellRect( ColPos _nColumn, RowPos _nRow, Rectangle& _rCellRect ) const;
371 :
372 : /** updates all cached model values
373 :
374 : The method is not bound to the classes public invariants, as it's used in
375 : situations where the they must not necessarily be fullfilled.
376 : */
377 : void impl_ni_updateCachedModelValues();
378 :
379 : /** updates the cached table metrics (row height etc.)
380 : */
381 : void impl_ni_updateCachedTableMetrics();
382 :
383 : /** does a relayout of the table control
384 :
385 : Column widths, and consequently the availability of the vertical and horizontal scrollbar, are updated
386 : with a call to this method.
387 :
388 : @param i_assumeInflexibleColumnsUpToIncluding
389 : the index of a column up to which all columns should be considered as inflexible, or
390 : <code>COL_INVALID</code>.
391 : */
392 : void impl_ni_relayout( ColPos const i_assumeInflexibleColumnsUpToIncluding = COL_INVALID );
393 :
394 : /** calculates the new width of our columns, taking into account their min and max widths, and their relative
395 : flexibility.
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 : @param i_assumeVerticalScrollbar
402 : controls whether or not we should assume the presence of a vertical scrollbar. If <true/>, and
403 : if the model has a VerticalScrollbarVisibility != ScrollbarShowNever, the method will leave
404 : space for a vertical scrollbar.
405 :
406 : @return
407 : the overall width of the grid, which is available for columns
408 : */
409 : long impl_ni_calculateColumnWidths(
410 : ColPos const i_assumeInflexibleColumnsUpToIncluding,
411 : bool const i_assumeVerticalScrollbar,
412 : ::std::vector< long >& o_newColWidthsPixel
413 : ) const;
414 :
415 : /** positions all child windows, e.g. the both scrollbars, the corner window, and the data window
416 : */
417 : void impl_ni_positionChildWindows(
418 : Rectangle const & i_dataCellPlayground,
419 : bool const i_verticalScrollbar,
420 : bool const i_horizontalScrollbar
421 : );
422 :
423 : /** scrolls the view by the given number of rows
424 :
425 : The method is not bound to the classes public invariants, as it's used in
426 : situations where the they must not necessarily be fullfilled.
427 :
428 : @return
429 : the number of rows by which the viewport was scrolled. This may differ
430 : from the given numbers to scroll in case the begin or the end of the
431 : row range were reached.
432 : */
433 : TableSize impl_ni_ScrollRows( TableSize _nRowDelta );
434 :
435 : /** equivalent to impl_ni_ScrollRows, but checks the instances invariants beforehand (in a non-product build only)
436 : */
437 : TableSize impl_scrollRows( TableSize const i_rowDelta );
438 :
439 : /** scrolls the view by the given number of columns
440 :
441 : The method is not bound to the classes public invariants, as it's used in
442 : situations where the they must not necessarily be fullfilled.
443 :
444 : @return
445 : the number of columns by which the viewport was scrolled. This may differ
446 : from the given numbers to scroll in case the begin or the end of the
447 : column range were reached.
448 : */
449 : TableSize impl_ni_ScrollColumns( TableSize _nColumnDelta );
450 :
451 : /** equivalent to impl_ni_ScrollColumns, but checks the instances invariants beforehand (in a non-product build only)
452 : */
453 : TableSize impl_scrollColumns( TableSize const i_columnDelta );
454 :
455 : /** retrieves the area occupied by the totality of (at least partially) visible cells
456 :
457 : The returned area includes row and column headers. Also, it takes into
458 : account the fact that there might be less columns than would normally
459 : find room in the control.
460 :
461 : As a result of respecting the partial visibility of rows and columns,
462 : the returned area might be larger than the data window's output size.
463 : */
464 : Rectangle impl_getAllVisibleCellsArea() const;
465 :
466 : /** retrieves the area occupied by all (at least partially) visible data cells.
467 :
468 : Effectively, the returned area is the same as returned by ->impl_getAllVisibleCellsArea,
469 : minus the row and column header areas.
470 : */
471 : Rectangle impl_getAllVisibleDataCellArea() const;
472 :
473 : /** retrieves the column which covers the given ordinate
474 : */
475 : ColPos impl_getColumnForOrdinate( long const i_ordinate ) const;
476 :
477 : /** retrieves the row which covers the given abscissa
478 : */
479 : RowPos impl_getRowForAbscissa( long const i_abscissa ) const;
480 :
481 : /// invalidates the window area occupied by the given column
482 : void impl_invalidateColumn( ColPos const i_column );
483 :
484 : DECL_LINK( OnScroll, ScrollBar* );
485 : DECL_LINK( OnUpdateScrollbars, void* );
486 : };
487 :
488 : //see seleng.hxx, seleng.cxx, FunctionSet overridables, part of selection engine
489 : class TableFunctionSet : public FunctionSet
490 : {
491 : private:
492 : TableControl_Impl* m_pTableControl;
493 : RowPos m_nCurrentRow;
494 :
495 : public:
496 : TableFunctionSet(TableControl_Impl* _pTableControl);
497 : virtual ~TableFunctionSet();
498 :
499 : virtual void BeginDrag();
500 : virtual void CreateAnchor();
501 : virtual void DestroyAnchor();
502 : virtual sal_Bool SetCursorAtPoint(const Point& rPoint, sal_Bool bDontSelectAtCursor);
503 : virtual sal_Bool IsSelectionAtPoint( const Point& rPoint );
504 : virtual void DeselectAtPoint( const Point& rPoint );
505 : virtual void DeselectAll();
506 : };
507 :
508 :
509 : //........................................................................
510 : } } // namespace svt::table
511 : //........................................................................
512 :
513 : #endif // SVTOOLS_TABLECONTROL_IMPL_HXX
514 :
515 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|