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