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