| /************************************************************** |
| * |
| * 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. |
| * |
| *************************************************************/ |
| |
| |
| |
| #include "precompiled_svtools.hxx" |
| |
| #include "mousefunction.hxx" |
| #include "svtools/table/tablecontrolinterface.hxx" |
| |
| #include <tools/diagnose_ex.h> |
| #include <vcl/window.hxx> |
| |
| //...................................................................................................................... |
| namespace svt { namespace table |
| { |
| //...................................................................................................................... |
| |
| //================================================================================================================== |
| //= MouseFunction |
| //================================================================================================================== |
| //------------------------------------------------------------------------------------------------------------------ |
| oslInterlockedCount MouseFunction::acquire() |
| { |
| return osl_incrementInterlockedCount( &m_refCount ); |
| } |
| |
| //------------------------------------------------------------------------------------------------------------------ |
| oslInterlockedCount MouseFunction::release() |
| { |
| oslInterlockedCount newCount = osl_decrementInterlockedCount( &m_refCount ); |
| if ( newCount == 0 ) |
| { |
| delete this; |
| return 0; |
| } |
| return newCount; |
| } |
| |
| //================================================================================================================== |
| //= ColumnResize |
| //================================================================================================================== |
| //------------------------------------------------------------------------------------------------------------------ |
| FunctionResult ColumnResize::handleMouseMove( ITableControl& i_tableControl, MouseEvent const & i_event ) |
| { |
| Point const aPoint = i_event.GetPosPixel(); |
| |
| if ( m_nResizingColumn == COL_INVALID ) |
| { |
| // if we hit a column divider, change the mosue pointer accordingly |
| Pointer aNewPointer( POINTER_ARROW ); |
| TableCell const tableCell = i_tableControl.hitTest( aPoint ); |
| if ( ( tableCell.nRow == ROW_COL_HEADERS ) && ( tableCell.eArea == ColumnDivider ) ) |
| { |
| aNewPointer = Pointer( POINTER_HSPLIT ); |
| } |
| i_tableControl.setPointer( aNewPointer ); |
| |
| return SkipFunction; // TODO: is this correct? |
| } |
| |
| ::Size const tableSize = i_tableControl.getTableSizePixel(); |
| |
| // set proper pointer |
| Pointer aNewPointer( POINTER_ARROW ); |
| ColumnMetrics const & columnMetrics( i_tableControl.getColumnMetrics( m_nResizingColumn ) ); |
| if ( ( aPoint.X() > tableSize.Width() ) |
| || ( aPoint.X() < columnMetrics.nStartPixel ) |
| ) |
| { |
| aNewPointer = Pointer( POINTER_NOTALLOWED ); |
| } |
| else |
| { |
| aNewPointer = Pointer( POINTER_HSPLIT ); |
| } |
| i_tableControl.setPointer( aNewPointer ); |
| |
| // show tracking line |
| i_tableControl.hideTracking(); |
| i_tableControl.showTracking( |
| Rectangle( |
| Point( aPoint.X(), 0 ), |
| Size( 1, tableSize.Height() ) |
| ), |
| SHOWTRACK_SPLIT | SHOWTRACK_WINDOW |
| ); |
| |
| (void)i_event; |
| return ContinueFunction; |
| } |
| |
| //------------------------------------------------------------------------------------------------------------------ |
| FunctionResult ColumnResize::handleMouseDown( ITableControl& i_tableControl, MouseEvent const & i_event ) |
| { |
| if ( m_nResizingColumn != COL_INVALID ) |
| { |
| OSL_ENSURE( false, "ColumnResize::handleMouseDown: suspicious: MouseButtonDown while still tracking?" ); |
| return ContinueFunction; |
| } |
| |
| TableCell const tableCell( i_tableControl.hitTest( i_event.GetPosPixel() ) ); |
| if ( tableCell.nRow == ROW_COL_HEADERS ) |
| { |
| if ( ( tableCell.nColumn != COL_INVALID ) |
| && ( tableCell.eArea == ColumnDivider ) |
| ) |
| { |
| m_nResizingColumn = tableCell.nColumn; |
| i_tableControl.captureMouse(); |
| return ActivateFunction; |
| } |
| } |
| |
| return SkipFunction; |
| } |
| |
| //------------------------------------------------------------------------------------------------------------------ |
| FunctionResult ColumnResize::handleMouseUp( ITableControl& i_tableControl, MouseEvent const & i_event ) |
| { |
| if ( m_nResizingColumn == COL_INVALID ) |
| return SkipFunction; |
| |
| Point const aPoint = i_event.GetPosPixel(); |
| |
| i_tableControl.hideTracking(); |
| PColumnModel const pColumn = i_tableControl.getModel()->getColumnModel( m_nResizingColumn ); |
| long const maxWidthLogical = pColumn->getMaxWidth(); |
| long const minWidthLogical = pColumn->getMinWidth(); |
| |
| // new position of mouse |
| long const requestedEnd = aPoint.X(); |
| |
| // old position of right border |
| long const oldEnd = i_tableControl.getColumnMetrics( m_nResizingColumn ).nEndPixel; |
| |
| // position of left border if cursor in the to-be-resized column |
| long const columnStart = i_tableControl.getColumnMetrics( m_nResizingColumn ).nStartPixel; |
| long const requestedWidth = requestedEnd - columnStart; |
| // TODO: this is not correct, strictly: It assumes that the mouse was pressed exactly on the "end" pos, |
| // but for a while now, we have relaxed this, and allow clicking a few pixels aside, too |
| |
| if ( requestedEnd >= columnStart ) |
| { |
| long requestedWidthLogical = i_tableControl.pixelWidthToAppFont( requestedWidth ); |
| // respect column width limits |
| if ( oldEnd > requestedEnd ) |
| { |
| // column has become smaller, check against minimum width |
| if ( ( minWidthLogical != 0 ) && ( requestedWidthLogical < minWidthLogical ) ) |
| requestedWidthLogical = minWidthLogical; |
| } |
| else if ( oldEnd < requestedEnd ) |
| { |
| // column has become larger, check against max width |
| if ( ( maxWidthLogical != 0 ) && ( requestedWidthLogical >= maxWidthLogical ) ) |
| requestedWidthLogical = maxWidthLogical; |
| } |
| pColumn->setWidth( requestedWidthLogical ); |
| i_tableControl.invalidate( TableAreaAll ); |
| } |
| |
| i_tableControl.setPointer( Pointer() ); |
| i_tableControl.releaseMouse(); |
| |
| m_nResizingColumn = COL_INVALID; |
| return DeactivateFunction; |
| } |
| |
| //================================================================================================================== |
| //= RowSelection |
| //================================================================================================================== |
| //------------------------------------------------------------------------------------------------------------------ |
| FunctionResult RowSelection::handleMouseMove( ITableControl& i_tableControl, MouseEvent const & i_event ) |
| { |
| OSL_UNUSED( i_tableControl ); |
| OSL_UNUSED( i_event ); |
| return SkipFunction; |
| } |
| |
| //------------------------------------------------------------------------------------------------------------------ |
| FunctionResult RowSelection::handleMouseDown( ITableControl& i_tableControl, MouseEvent const & i_event ) |
| { |
| bool handled = false; |
| |
| TableCell const tableCell( i_tableControl.hitTest( i_event.GetPosPixel() ) ); |
| if ( tableCell.nRow >= 0 ) |
| { |
| if ( i_tableControl.getSelEngine()->GetSelectionMode() == NO_SELECTION ) |
| { |
| i_tableControl.activateCell( tableCell.nColumn, tableCell.nRow ); |
| handled = true; |
| } |
| else |
| { |
| handled = i_tableControl.getSelEngine()->SelMouseButtonDown( i_event ); |
| } |
| } |
| |
| if ( handled ) |
| m_bActive = true; |
| return handled ? ActivateFunction : SkipFunction; |
| } |
| |
| //------------------------------------------------------------------------------------------------------------------ |
| FunctionResult RowSelection::handleMouseUp( ITableControl& i_tableControl, MouseEvent const & i_event ) |
| { |
| TableCell const tableCell = i_tableControl.hitTest( i_event.GetPosPixel() ); |
| if ( tableCell.nRow >= 0 ) |
| { |
| if ( i_tableControl.getSelEngine()->GetSelectionMode() != NO_SELECTION ) |
| { |
| i_tableControl.getSelEngine()->SelMouseButtonUp( i_event ); |
| } |
| } |
| if ( m_bActive ) |
| { |
| m_bActive = false; |
| return DeactivateFunction; |
| } |
| return SkipFunction; |
| } |
| |
| //================================================================================================================== |
| //= ColumnSortHandler |
| //================================================================================================================== |
| //------------------------------------------------------------------------------------------------------------------ |
| FunctionResult ColumnSortHandler::handleMouseMove( ITableControl& i_tableControl, MouseEvent const & i_event ) |
| { |
| OSL_UNUSED( i_tableControl ); |
| OSL_UNUSED( i_event ); |
| return SkipFunction; |
| } |
| |
| //------------------------------------------------------------------------------------------------------------------ |
| FunctionResult ColumnSortHandler::handleMouseDown( ITableControl& i_tableControl, MouseEvent const & i_event ) |
| { |
| if ( m_nActiveColumn != COL_INVALID ) |
| { |
| OSL_ENSURE( false, "ColumnSortHandler::handleMouseDown: called while already active - suspicious!" ); |
| return ContinueFunction; |
| } |
| |
| if ( i_tableControl.getModel()->getSortAdapter() == NULL ) |
| // no sorting support at the model |
| return SkipFunction; |
| |
| TableCell const tableCell( i_tableControl.hitTest( i_event.GetPosPixel() ) ); |
| if ( ( tableCell.nRow != ROW_COL_HEADERS ) || ( tableCell.nColumn < 0 ) ) |
| return SkipFunction; |
| |
| // TODO: ensure the column header is rendered in some special way, indicating its current state |
| |
| m_nActiveColumn = tableCell.nColumn; |
| return ActivateFunction; |
| } |
| |
| //------------------------------------------------------------------------------------------------------------------ |
| FunctionResult ColumnSortHandler::handleMouseUp( ITableControl& i_tableControl, MouseEvent const & i_event ) |
| { |
| if ( m_nActiveColumn == COL_INVALID ) |
| return SkipFunction; |
| |
| TableCell const tableCell( i_tableControl.hitTest( i_event.GetPosPixel() ) ); |
| if ( ( tableCell.nRow == ROW_COL_HEADERS ) && ( tableCell.nColumn == m_nActiveColumn ) ) |
| { |
| ITableDataSort* pSort = i_tableControl.getModel()->getSortAdapter(); |
| ENSURE_OR_RETURN( pSort != NULL, "ColumnSortHandler::handleMouseUp: somebody is mocking with us!", DeactivateFunction ); |
| // in handleMousButtonDown, the model claimed to have sort support ... |
| |
| ColumnSortDirection eSortDirection = ColumnSortAscending; |
| ColumnSort const aCurrentSort = pSort->getCurrentSortOrder(); |
| if ( aCurrentSort.nColumnPos == m_nActiveColumn ) |
| // invert existing sort order |
| eSortDirection = ( aCurrentSort.eSortDirection == ColumnSortAscending ) ? ColumnSortDescending : ColumnSortAscending; |
| |
| pSort->sortByColumn( m_nActiveColumn, eSortDirection ); |
| } |
| |
| m_nActiveColumn = COL_INVALID; |
| return DeactivateFunction; |
| } |
| |
| //...................................................................................................................... |
| } } // namespace svt::table |
| //...................................................................................................................... |