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