| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| #ifndef SVTOOLS_TABLECONTROL_IMPL_HXX |
| #define SVTOOLS_TABLECONTROL_IMPL_HXX |
| |
| #include "svtools/table/tablemodel.hxx" |
| #include "svtools/table/tablecontrolinterface.hxx" |
| |
| #include "svtaccessiblefactory.hxx" |
| |
| #include <vcl/seleng.hxx> |
| |
| #include <vector> |
| |
| #include <boost/scoped_ptr.hpp> |
| |
| class ScrollBar; |
| class ScrollBarBox; |
| |
| //........................................................................ |
| namespace svt { namespace table |
| { |
| //........................................................................ |
| |
| struct MutableColumnMetrics : protected ColumnMetrics |
| { |
| MutableColumnMetrics() |
| :ColumnMetrics() |
| { |
| } |
| |
| MutableColumnMetrics( long const i_startPixel, long const i_endPixel ) |
| :ColumnMetrics( i_startPixel, i_endPixel ) |
| { |
| } |
| |
| long getStart() const { return nStartPixel; } |
| long getEnd() const { return nEndPixel; } |
| |
| void setEnd( long const i_end ) { nEndPixel = i_end; } |
| void move( long const i_offset ) { nStartPixel += i_offset; nEndPixel += i_offset; } |
| |
| long getWidth() const { return nEndPixel - nStartPixel; } |
| |
| ColumnMetrics const & operator()() { return *this; } |
| }; |
| |
| struct ColumnInfoPositionLess |
| { |
| bool operator()( MutableColumnMetrics const& i_colInfo, long const i_position ) |
| { |
| return i_colInfo.getEnd() < i_position; |
| } |
| bool operator()( long const i_position, MutableColumnMetrics const& i_colInfo ) |
| { |
| return i_position < i_colInfo.getStart(); |
| } |
| }; |
| |
| typedef ::std::vector< MutableColumnMetrics > ColumnPositions; |
| |
| class TableControl; |
| class TableDataWindow; |
| class TableFunctionSet; |
| |
| //==================================================================== |
| //= TableControl_Impl |
| //==================================================================== |
| class TableControl_Impl :public ITableControl |
| ,public ITableModelListener |
| { |
| friend class TableGeometry; |
| friend class TableRowGeometry; |
| friend class TableColumnGeometry; |
| friend class SuspendInvariants; |
| |
| private: |
| /// the control whose impl-instance we implemnt |
| TableControl& m_rAntiImpl; |
| /// the model of the table control |
| PTableModel m_pModel; |
| /// the input handler to use, usually the input handler as provided by ->m_pModel |
| PTableInputHandler m_pInputHandler; |
| /// info about the widths of our columns |
| ColumnPositions m_aColumnWidths; |
| |
| /// the height of a single row in the table, measured in pixels |
| long m_nRowHeightPixel; |
| /// the height of the column header row in the table, measured in pixels |
| long m_nColHeaderHeightPixel; |
| /// the width of the row header column in the table, measured in pixels |
| long m_nRowHeaderWidthPixel; |
| |
| /// the number of columns in the table control. Cached model value. |
| TableSize m_nColumnCount; |
| |
| /// the number of rows in the table control. Cached model value. |
| TableSize m_nRowCount; |
| |
| /// denotes whether or not the columns fitted into the available width, last time we checked |
| long m_bColumnsFit; |
| |
| ColPos m_nCurColumn; |
| RowPos m_nCurRow; |
| ColPos m_nLeftColumn; |
| RowPos m_nTopRow; |
| |
| sal_Int32 m_nCursorHidden; |
| |
| /** the window to contain all data content, including header bars |
| |
| The window's upper left corner is at position (0,0), relative to the |
| table control, which is the direct parent of the data window. |
| */ |
| ::boost::scoped_ptr< TableDataWindow > |
| m_pDataWindow; |
| /// the vertical scrollbar, if any |
| ScrollBar* m_pVScroll; |
| /// the horizontal scrollbar, if any |
| ScrollBar* m_pHScroll; |
| ScrollBarBox* m_pScrollCorner; |
| //selection engine - for determining selection range, e.g. single, multiple |
| SelectionEngine* m_pSelEngine; |
| //vector which contains the selected rows |
| std::vector<RowPos> m_aSelectedRows; |
| //part of selection engine |
| TableFunctionSet* m_pTableFunctionSet; |
| //part of selection engine |
| RowPos m_nAnchor; |
| bool m_bUpdatingColWidths; |
| |
| Link m_aSelectHdl; |
| |
| AccessibleFactoryAccess m_aFactoryAccess; |
| IAccessibleTableControl* m_pAccessibleTable; |
| |
| #if DBG_UTIL |
| #define INV_SCROLL_POSITION 1 |
| /** represents a bitmask of invariants to check |
| |
| Actually, impl_checkInvariants checks more invariants than denoted in this |
| bit mask, but only those present here can be disabled temporarily. |
| */ |
| sal_Int32 m_nRequiredInvariants; |
| #endif |
| |
| public: |
| void setModel( PTableModel _pModel ); |
| |
| inline const PTableInputHandler& getInputHandler() const { return m_pInputHandler; } |
| |
| inline RowPos getCurRow() const { return m_nCurRow; } |
| inline void setCurRow( RowPos i_curRow ){ m_nCurRow = i_curRow; } |
| |
| RowPos getAnchor() const { return m_nAnchor; } |
| void setAnchor( RowPos const i_anchor ) { m_nAnchor = i_anchor; } |
| |
| inline RowPos getTopRow() const { return m_nTopRow; } |
| inline ColPos getLeftColumn() const { return m_nLeftColumn; } |
| |
| inline const TableControl& getAntiImpl() const { return m_rAntiImpl; } |
| inline TableControl& getAntiImpl() { return m_rAntiImpl; } |
| |
| public: |
| TableControl_Impl( TableControl& _rAntiImpl ); |
| ~TableControl_Impl(); |
| |
| #if DBG_UTIL |
| const sal_Char* impl_checkInvariants() const; |
| #endif |
| /** to be called when the anti-impl instance has been resized |
| */ |
| void onResize(); |
| |
| /** paints the table control content which intersects with the given rectangle |
| */ |
| void doPaintContent( const Rectangle& _rUpdateRect ); |
| |
| /** moves the cursor to the cell with the given coordinates |
| |
| To ease the caller's code, the coordinates must not necessarily denote a |
| valid position. If they don't, <FALSE/> will be returned. |
| */ |
| bool goTo( ColPos _nColumn, RowPos _nRow ); |
| |
| /** ensures that the given coordinate is visible |
| @param _nColumn |
| the column position which should be visible. Must be non-negative, and smaller |
| than the column count. |
| @param _nRow |
| the row position which should be visibleMust be non-negative, and smaller |
| than the row count. |
| @param _bAcceptPartialVisibility |
| <TRUE/> if it's okay that the given cooordinate is only partially visible |
| */ |
| void ensureVisible( ColPos _nColumn, RowPos _nRow, bool _bAcceptPartialVisibility ); |
| |
| /** retrieves the content of the given cell, converted to a string |
| */ |
| ::rtl::OUString getCellContentAsString( RowPos const i_row, ColPos const i_col ); |
| |
| /** returns the position of the current row in the selection vector */ |
| int getRowSelectedNumber(const ::std::vector<RowPos>& selectedRows, RowPos current); |
| |
| /** ??? */ |
| void invalidateSelectedRegion( RowPos _nPrevRow, RowPos _nCurRow ); |
| |
| /** invalidates the part of the data window which is covered by the given rows |
| @param i_firstRow |
| the index of the first row to include in the invalidation |
| @param i_lastRow |
| the index of the last row to include in the invalidation, or ROW_INVALID if the invalidation |
| should happen down to the bottom of the data window. |
| */ |
| void invalidateRowRange( RowPos const i_firstRow, RowPos const i_lastRow ); |
| |
| /** invalidates the part of the data window which is covered by the given row |
| */ |
| void invalidateRow( RowPos const i_row ) { invalidateRowRange( i_row, i_row ); } |
| |
| /** invalidates all selected rows |
| */ |
| void invalidateSelectedRows(); |
| |
| void checkCursorPosition(); |
| |
| bool hasRowSelection() const { return !m_aSelectedRows.empty(); } |
| size_t getSelectedRowCount() const { return m_aSelectedRows.size(); } |
| RowPos getSelectedRowIndex( size_t const i_selectionIndex ) const; |
| |
| /** removes the given row index from m_aSelectedRows |
| |
| @return |
| <TRUE/> if and only if the row was previously marked as selected |
| */ |
| bool markRowAsDeselected( RowPos const i_rowIndex ); |
| |
| /** marks the given row as selectged, by putting it into m_aSelectedRows |
| @return |
| <TRUE/> if and only if the row was previously <em>not</em> marked as selected |
| */ |
| bool markRowAsSelected( RowPos const i_rowIndex ); |
| |
| /** marks all rows as deselected |
| @return |
| <TRUE/> if and only if the selection actually changed by this operation |
| */ |
| bool markAllRowsAsDeselected(); |
| |
| /** marks all rows as selected |
| @return |
| <FALSE/> if and only if all rows were selected already. |
| */ |
| bool markAllRowsAsSelected(); |
| |
| void setSelectHandler( Link const & i_selectHandler ) { m_aSelectHdl = i_selectHandler; } |
| Link const& getSelectHandler() const { return m_aSelectHdl; } |
| |
| void commitAccessibleEvent( sal_Int16 const i_eventID, const com::sun::star::uno::Any& i_newValue, const com::sun::star::uno::Any& i_oldValue ); |
| void commitCellEvent( sal_Int16 const i_eventID, const com::sun::star::uno::Any& i_newValue, const com::sun::star::uno::Any& i_oldValue ); |
| void commitTableEvent( sal_Int16 const i_eventID, const com::sun::star::uno::Any& i_newValue, const com::sun::star::uno::Any& i_oldValue ); |
| |
| // ITableControl |
| virtual void hideCursor(); |
| virtual void showCursor(); |
| virtual bool dispatchAction( TableControlAction _eAction ); |
| virtual SelectionEngine* getSelEngine(); |
| virtual PTableModel getModel() const; |
| virtual ColPos getCurrentColumn() const; |
| virtual RowPos getCurrentRow() const; |
| virtual bool activateCell( ColPos const i_col, RowPos const i_row ); |
| virtual ::Size getTableSizePixel() const; |
| virtual void setPointer( Pointer const & i_pointer ); |
| virtual void captureMouse(); |
| virtual void releaseMouse(); |
| virtual void invalidate( TableArea const i_what ); |
| virtual long pixelWidthToAppFont( long const i_pixels ) const; |
| virtual void hideTracking(); |
| virtual void showTracking( Rectangle const & i_location, sal_uInt16 const i_flags ); |
| virtual RowPos getRowAtPoint( const Point& rPoint ) const; |
| virtual ColPos getColAtPoint( const Point& rPoint ) const; |
| virtual TableCell hitTest( const Point& rPoint ) const; |
| virtual ColumnMetrics getColumnMetrics( ColPos const i_column ) const; |
| virtual bool isRowSelected( RowPos i_row ) const; |
| |
| |
| long appFontWidthToPixel( long const i_appFontUnits ) const; |
| |
| TableDataWindow& getDataWindow() { return *m_pDataWindow; } |
| const TableDataWindow& getDataWindow() const { return *m_pDataWindow; } |
| ScrollBar* getHorzScrollbar(); |
| ScrollBar* getVertScrollbar(); |
| |
| Rectangle calcHeaderRect( bool bColHeader ); |
| Rectangle calcHeaderCellRect( bool bColHeader, sal_Int32 nPos ); |
| Rectangle calcTableRect(); |
| Rectangle calcCellRect( sal_Int32 nRow, sal_Int32 nCol ); |
| |
| // A11Y |
| ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > |
| getAccessible( Window& i_parentWindow ); |
| void disposeAccessible(); |
| |
| inline bool isAccessibleAlive() const { return impl_isAccessibleAlive(); } |
| |
| // ITableModelListener |
| virtual void rowsInserted( RowPos first, RowPos last ); |
| virtual void rowsRemoved( RowPos first, RowPos last ); |
| virtual void columnInserted( ColPos const i_colIndex ); |
| virtual void columnRemoved( ColPos const i_colIndex ); |
| virtual void allColumnsRemoved(); |
| virtual void cellsUpdated( ColPos const i_firstCol, ColPos i_lastCol, RowPos const i_firstRow, RowPos const i_lastRow ); |
| virtual void columnChanged( ColPos const i_column, ColumnAttributeGroup const i_attributeGroup ); |
| virtual void tableMetricsChanged(); |
| |
| private: |
| bool impl_isAccessibleAlive() const; |
| void impl_commitAccessibleEvent( |
| sal_Int16 const i_eventID, |
| ::com::sun::star::uno::Any const & i_newValue, |
| ::com::sun::star::uno::Any const & i_oldValue |
| ); |
| |
| /** toggles the cursor visibility |
| |
| The method is not bound to the classes public invariants, as it's used in |
| situations where the they must not necessarily be fullfilled. |
| */ |
| void impl_ni_doSwitchCursor( bool _bOn ); |
| |
| /** returns the number of visible rows. |
| |
| @param _bAcceptPartialRow |
| specifies whether a possible only partially visible last row is |
| counted, too. |
| */ |
| TableSize impl_getVisibleRows( bool _bAcceptPartialRow ) const; |
| |
| /** returns the number of visible columns |
| |
| The value may change with different horizontal scroll positions, as |
| different columns have different widths. For instance, if your control is |
| 100 pixels wide, and has three columns of width 50, 50, 100, respectively, |
| then this method will return either "2" or "1", depending on which column |
| is the first visible one. |
| |
| @param _bAcceptPartialRow |
| specifies whether a possible only partially visible last row is |
| counted, too. |
| */ |
| TableSize impl_getVisibleColumns( bool _bAcceptPartialCol ) const; |
| |
| /** determines the rectangle occupied by the given cell |
| */ |
| void impl_getCellRect( ColPos _nColumn, RowPos _nRow, Rectangle& _rCellRect ) const; |
| |
| /** updates all cached model values |
| |
| The method is not bound to the classes public invariants, as it's used in |
| situations where the they must not necessarily be fullfilled. |
| */ |
| void impl_ni_updateCachedModelValues(); |
| |
| /** updates the cached table metrics (row height etc.) |
| */ |
| void impl_ni_updateCachedTableMetrics(); |
| |
| /** does a relayout of the table control |
| |
| Column widths, and consequently the availability of the vertical and horizontal scrollbar, are updated |
| with a call to this method. |
| |
| @param i_assumeInflexibleColumnsUpToIncluding |
| the index of a column up to which all columns should be considered as inflexible, or |
| <code>COL_INVALID</code>. |
| */ |
| void impl_ni_relayout( ColPos const i_assumeInflexibleColumnsUpToIncluding = COL_INVALID ); |
| |
| /** calculates the new width of our columns, taking into account their min and max widths, and their relative |
| flexibility. |
| |
| @param i_assumeInflexibleColumnsUpToIncluding |
| the index of a column up to which all columns should be considered as inflexible, or |
| <code>COL_INVALID</code>. |
| |
| @param i_assumeVerticalScrollbar |
| controls whether or not we should assume the presence of a vertical scrollbar. If <true/>, and |
| if the model has a VerticalScrollbarVisibility != ScrollbarShowNever, the method will leave |
| space for a vertical scrollbar. |
| |
| @return |
| the overall width of the grid, which is available for columns |
| */ |
| long impl_ni_calculateColumnWidths( |
| ColPos const i_assumeInflexibleColumnsUpToIncluding, |
| bool const i_assumeVerticalScrollbar, |
| ::std::vector< long >& o_newColWidthsPixel |
| ) const; |
| |
| /** positions all child windows, e.g. the both scrollbars, the corner window, and the data window |
| */ |
| void impl_ni_positionChildWindows( |
| Rectangle const & i_dataCellPlayground, |
| bool const i_verticalScrollbar, |
| bool const i_horizontalScrollbar |
| ); |
| |
| /** scrolls the view by the given number of rows |
| |
| The method is not bound to the classes public invariants, as it's used in |
| situations where the they must not necessarily be fullfilled. |
| |
| @return |
| the number of rows by which the viewport was scrolled. This may differ |
| from the given numbers to scroll in case the begin or the end of the |
| row range were reached. |
| */ |
| TableSize impl_ni_ScrollRows( TableSize _nRowDelta ); |
| |
| /** equivalent to impl_ni_ScrollRows, but checks the instances invariants beforehand (in a non-product build only) |
| */ |
| TableSize impl_scrollRows( TableSize const i_rowDelta ); |
| |
| /** scrolls the view by the given number of columns |
| |
| The method is not bound to the classes public invariants, as it's used in |
| situations where the they must not necessarily be fullfilled. |
| |
| @return |
| the number of columns by which the viewport was scrolled. This may differ |
| from the given numbers to scroll in case the begin or the end of the |
| column range were reached. |
| */ |
| TableSize impl_ni_ScrollColumns( TableSize _nColumnDelta ); |
| |
| /** equivalent to impl_ni_ScrollColumns, but checks the instances invariants beforehand (in a non-product build only) |
| */ |
| TableSize impl_scrollColumns( TableSize const i_columnDelta ); |
| |
| /** retrieves the area occupied by the totality of (at least partially) visible cells |
| |
| The returned area includes row and column headers. Also, it takes into |
| account the the fact that there might be less columns than would normally |
| find room in the control. |
| |
| As a result of respecting the partial visibility of rows and columns, |
| the returned area might be larger than the data window's output size. |
| */ |
| Rectangle impl_getAllVisibleCellsArea() const; |
| |
| /** retrieves the area occupied by all (at least partially) visible data cells. |
| |
| Effectively, the returned area is the same as returned by ->impl_getAllVisibleCellsArea, |
| minus the row and column header areas. |
| */ |
| Rectangle impl_getAllVisibleDataCellArea() const; |
| |
| /** retrieves the column which covers the given ordinate |
| */ |
| ColPos impl_getColumnForOrdinate( long const i_ordinate ) const; |
| |
| /** retrieves the row which covers the given abscissa |
| */ |
| RowPos impl_getRowForAbscissa( long const i_abscissa ) const; |
| |
| /// invalidates the window area occupied by the given column |
| void impl_invalidateColumn( ColPos const i_column ); |
| |
| DECL_LINK( OnScroll, ScrollBar* ); |
| DECL_LINK( OnUpdateScrollbars, void* ); |
| }; |
| |
| //see seleng.hxx, seleng.cxx, FunctionSet overridables, part of selection engine |
| class TableFunctionSet : public FunctionSet |
| { |
| private: |
| TableControl_Impl* m_pTableControl; |
| RowPos m_nCurrentRow; |
| |
| public: |
| TableFunctionSet(TableControl_Impl* _pTableControl); |
| virtual ~TableFunctionSet(); |
| |
| virtual void BeginDrag(); |
| virtual void CreateAnchor(); |
| virtual void DestroyAnchor(); |
| virtual sal_Bool SetCursorAtPoint(const Point& rPoint, sal_Bool bDontSelectAtCursor); |
| virtual sal_Bool IsSelectionAtPoint( const Point& rPoint ); |
| virtual void DeselectAtPoint( const Point& rPoint ); |
| virtual void DeselectAll(); |
| }; |
| |
| |
| //........................................................................ |
| } } // namespace svt::table |
| //........................................................................ |
| |
| #endif // SVTOOLS_TABLECONTROL_IMPL_HXX |