1*5900e8ecSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*5900e8ecSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*5900e8ecSAndrew Rist * or more contributor license agreements. See the NOTICE file 5*5900e8ecSAndrew Rist * distributed with this work for additional information 6*5900e8ecSAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*5900e8ecSAndrew Rist * to you under the Apache License, Version 2.0 (the 8*5900e8ecSAndrew Rist * "License"); you may not use this file except in compliance 9*5900e8ecSAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*5900e8ecSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*5900e8ecSAndrew Rist * Unless required by applicable law or agreed to in writing, 14*5900e8ecSAndrew Rist * software distributed under the License is distributed on an 15*5900e8ecSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*5900e8ecSAndrew Rist * KIND, either express or implied. See the License for the 17*5900e8ecSAndrew Rist * specific language governing permissions and limitations 18*5900e8ecSAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*5900e8ecSAndrew Rist *************************************************************/ 21*5900e8ecSAndrew Rist 22*5900e8ecSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #include "precompiled_svtools.hxx" 25cdf0e10cSrcweir 26cdf0e10cSrcweir #include "mousefunction.hxx" 27cdf0e10cSrcweir #include "svtools/table/tablecontrolinterface.hxx" 28cdf0e10cSrcweir 29cdf0e10cSrcweir #include <tools/diagnose_ex.h> 30cdf0e10cSrcweir #include <vcl/window.hxx> 31cdf0e10cSrcweir 32cdf0e10cSrcweir //...................................................................................................................... 33cdf0e10cSrcweir namespace svt { namespace table 34cdf0e10cSrcweir { 35cdf0e10cSrcweir //...................................................................................................................... 36cdf0e10cSrcweir 37cdf0e10cSrcweir //================================================================================================================== 38cdf0e10cSrcweir //= MouseFunction 39cdf0e10cSrcweir //================================================================================================================== 40cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ acquire()41cdf0e10cSrcweir oslInterlockedCount MouseFunction::acquire() 42cdf0e10cSrcweir { 43cdf0e10cSrcweir return osl_incrementInterlockedCount( &m_refCount ); 44cdf0e10cSrcweir } 45cdf0e10cSrcweir 46cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ release()47cdf0e10cSrcweir oslInterlockedCount MouseFunction::release() 48cdf0e10cSrcweir { 49cdf0e10cSrcweir oslInterlockedCount newCount = osl_decrementInterlockedCount( &m_refCount ); 50cdf0e10cSrcweir if ( newCount == 0 ) 51cdf0e10cSrcweir { 52cdf0e10cSrcweir delete this; 53cdf0e10cSrcweir return 0; 54cdf0e10cSrcweir } 55cdf0e10cSrcweir return newCount; 56cdf0e10cSrcweir } 57cdf0e10cSrcweir 58cdf0e10cSrcweir //================================================================================================================== 59cdf0e10cSrcweir //= ColumnResize 60cdf0e10cSrcweir //================================================================================================================== 61cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ handleMouseMove(ITableControl & i_tableControl,MouseEvent const & i_event)62cdf0e10cSrcweir FunctionResult ColumnResize::handleMouseMove( ITableControl& i_tableControl, MouseEvent const & i_event ) 63cdf0e10cSrcweir { 64cdf0e10cSrcweir Point const aPoint = i_event.GetPosPixel(); 65cdf0e10cSrcweir 66cdf0e10cSrcweir if ( m_nResizingColumn == COL_INVALID ) 67cdf0e10cSrcweir { 68cdf0e10cSrcweir // if we hit a column divider, change the mosue pointer accordingly 69cdf0e10cSrcweir Pointer aNewPointer( POINTER_ARROW ); 70cdf0e10cSrcweir TableCell const tableCell = i_tableControl.hitTest( aPoint ); 71cdf0e10cSrcweir if ( ( tableCell.nRow == ROW_COL_HEADERS ) && ( tableCell.eArea == ColumnDivider ) ) 72cdf0e10cSrcweir { 73cdf0e10cSrcweir aNewPointer = Pointer( POINTER_HSPLIT ); 74cdf0e10cSrcweir } 75cdf0e10cSrcweir i_tableControl.setPointer( aNewPointer ); 76cdf0e10cSrcweir 77cdf0e10cSrcweir return SkipFunction; // TODO: is this correct? 78cdf0e10cSrcweir } 79cdf0e10cSrcweir 80cdf0e10cSrcweir ::Size const tableSize = i_tableControl.getTableSizePixel(); 81cdf0e10cSrcweir 82cdf0e10cSrcweir // set proper pointer 83cdf0e10cSrcweir Pointer aNewPointer( POINTER_ARROW ); 84cdf0e10cSrcweir ColumnMetrics const & columnMetrics( i_tableControl.getColumnMetrics( m_nResizingColumn ) ); 85cdf0e10cSrcweir if ( ( aPoint.X() > tableSize.Width() ) 86cdf0e10cSrcweir || ( aPoint.X() < columnMetrics.nStartPixel ) 87cdf0e10cSrcweir ) 88cdf0e10cSrcweir { 89cdf0e10cSrcweir aNewPointer = Pointer( POINTER_NOTALLOWED ); 90cdf0e10cSrcweir } 91cdf0e10cSrcweir else 92cdf0e10cSrcweir { 93cdf0e10cSrcweir aNewPointer = Pointer( POINTER_HSPLIT ); 94cdf0e10cSrcweir } 95cdf0e10cSrcweir i_tableControl.setPointer( aNewPointer ); 96cdf0e10cSrcweir 97cdf0e10cSrcweir // show tracking line 98cdf0e10cSrcweir i_tableControl.hideTracking(); 99cdf0e10cSrcweir i_tableControl.showTracking( 100cdf0e10cSrcweir Rectangle( 101cdf0e10cSrcweir Point( aPoint.X(), 0 ), 102cdf0e10cSrcweir Size( 1, tableSize.Height() ) 103cdf0e10cSrcweir ), 104cdf0e10cSrcweir SHOWTRACK_SPLIT | SHOWTRACK_WINDOW 105cdf0e10cSrcweir ); 106cdf0e10cSrcweir 107cdf0e10cSrcweir (void)i_event; 108cdf0e10cSrcweir return ContinueFunction; 109cdf0e10cSrcweir } 110cdf0e10cSrcweir 111cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ handleMouseDown(ITableControl & i_tableControl,MouseEvent const & i_event)112cdf0e10cSrcweir FunctionResult ColumnResize::handleMouseDown( ITableControl& i_tableControl, MouseEvent const & i_event ) 113cdf0e10cSrcweir { 114cdf0e10cSrcweir if ( m_nResizingColumn != COL_INVALID ) 115cdf0e10cSrcweir { 116cdf0e10cSrcweir OSL_ENSURE( false, "ColumnResize::handleMouseDown: suspicious: MouseButtonDown while still tracking?" ); 117cdf0e10cSrcweir return ContinueFunction; 118cdf0e10cSrcweir } 119cdf0e10cSrcweir 120cdf0e10cSrcweir TableCell const tableCell( i_tableControl.hitTest( i_event.GetPosPixel() ) ); 121cdf0e10cSrcweir if ( tableCell.nRow == ROW_COL_HEADERS ) 122cdf0e10cSrcweir { 123cdf0e10cSrcweir if ( ( tableCell.nColumn != COL_INVALID ) 124cdf0e10cSrcweir && ( tableCell.eArea == ColumnDivider ) 125cdf0e10cSrcweir ) 126cdf0e10cSrcweir { 127cdf0e10cSrcweir m_nResizingColumn = tableCell.nColumn; 128cdf0e10cSrcweir i_tableControl.captureMouse(); 129cdf0e10cSrcweir return ActivateFunction; 130cdf0e10cSrcweir } 131cdf0e10cSrcweir } 132cdf0e10cSrcweir 133cdf0e10cSrcweir return SkipFunction; 134cdf0e10cSrcweir } 135cdf0e10cSrcweir 136cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ handleMouseUp(ITableControl & i_tableControl,MouseEvent const & i_event)137cdf0e10cSrcweir FunctionResult ColumnResize::handleMouseUp( ITableControl& i_tableControl, MouseEvent const & i_event ) 138cdf0e10cSrcweir { 139cdf0e10cSrcweir if ( m_nResizingColumn == COL_INVALID ) 140cdf0e10cSrcweir return SkipFunction; 141cdf0e10cSrcweir 142cdf0e10cSrcweir Point const aPoint = i_event.GetPosPixel(); 143cdf0e10cSrcweir 144cdf0e10cSrcweir i_tableControl.hideTracking(); 145cdf0e10cSrcweir PColumnModel const pColumn = i_tableControl.getModel()->getColumnModel( m_nResizingColumn ); 146cdf0e10cSrcweir long const maxWidthLogical = pColumn->getMaxWidth(); 147cdf0e10cSrcweir long const minWidthLogical = pColumn->getMinWidth(); 148cdf0e10cSrcweir 149cdf0e10cSrcweir // new position of mouse 150cdf0e10cSrcweir long const requestedEnd = aPoint.X(); 151cdf0e10cSrcweir 152cdf0e10cSrcweir // old position of right border 153cdf0e10cSrcweir long const oldEnd = i_tableControl.getColumnMetrics( m_nResizingColumn ).nEndPixel; 154cdf0e10cSrcweir 155cdf0e10cSrcweir // position of left border if cursor in the to-be-resized column 156cdf0e10cSrcweir long const columnStart = i_tableControl.getColumnMetrics( m_nResizingColumn ).nStartPixel; 157cdf0e10cSrcweir long const requestedWidth = requestedEnd - columnStart; 158cdf0e10cSrcweir // TODO: this is not correct, strictly: It assumes that the mouse was pressed exactly on the "end" pos, 159cdf0e10cSrcweir // but for a while now, we have relaxed this, and allow clicking a few pixels aside, too 160cdf0e10cSrcweir 161cdf0e10cSrcweir if ( requestedEnd >= columnStart ) 162cdf0e10cSrcweir { 163cdf0e10cSrcweir long requestedWidthLogical = i_tableControl.pixelWidthToAppFont( requestedWidth ); 164cdf0e10cSrcweir // respect column width limits 165cdf0e10cSrcweir if ( oldEnd > requestedEnd ) 166cdf0e10cSrcweir { 167cdf0e10cSrcweir // column has become smaller, check against minimum width 168cdf0e10cSrcweir if ( ( minWidthLogical != 0 ) && ( requestedWidthLogical < minWidthLogical ) ) 169cdf0e10cSrcweir requestedWidthLogical = minWidthLogical; 170cdf0e10cSrcweir } 171cdf0e10cSrcweir else if ( oldEnd < requestedEnd ) 172cdf0e10cSrcweir { 173cdf0e10cSrcweir // column has become larger, check against max width 174cdf0e10cSrcweir if ( ( maxWidthLogical != 0 ) && ( requestedWidthLogical >= maxWidthLogical ) ) 175cdf0e10cSrcweir requestedWidthLogical = maxWidthLogical; 176cdf0e10cSrcweir } 177cdf0e10cSrcweir pColumn->setWidth( requestedWidthLogical ); 178cdf0e10cSrcweir i_tableControl.invalidate( TableAreaAll ); 179cdf0e10cSrcweir } 180cdf0e10cSrcweir 181cdf0e10cSrcweir i_tableControl.setPointer( Pointer() ); 182cdf0e10cSrcweir i_tableControl.releaseMouse(); 183cdf0e10cSrcweir 184cdf0e10cSrcweir m_nResizingColumn = COL_INVALID; 185cdf0e10cSrcweir return DeactivateFunction; 186cdf0e10cSrcweir } 187cdf0e10cSrcweir 188cdf0e10cSrcweir //================================================================================================================== 189cdf0e10cSrcweir //= RowSelection 190cdf0e10cSrcweir //================================================================================================================== 191cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ handleMouseMove(ITableControl & i_tableControl,MouseEvent const & i_event)192cdf0e10cSrcweir FunctionResult RowSelection::handleMouseMove( ITableControl& i_tableControl, MouseEvent const & i_event ) 193cdf0e10cSrcweir { 194cdf0e10cSrcweir OSL_UNUSED( i_tableControl ); 195cdf0e10cSrcweir OSL_UNUSED( i_event ); 196cdf0e10cSrcweir return SkipFunction; 197cdf0e10cSrcweir } 198cdf0e10cSrcweir 199cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ handleMouseDown(ITableControl & i_tableControl,MouseEvent const & i_event)200cdf0e10cSrcweir FunctionResult RowSelection::handleMouseDown( ITableControl& i_tableControl, MouseEvent const & i_event ) 201cdf0e10cSrcweir { 202cdf0e10cSrcweir bool handled = false; 203cdf0e10cSrcweir 204cdf0e10cSrcweir TableCell const tableCell( i_tableControl.hitTest( i_event.GetPosPixel() ) ); 205cdf0e10cSrcweir if ( tableCell.nRow >= 0 ) 206cdf0e10cSrcweir { 207cdf0e10cSrcweir if ( i_tableControl.getSelEngine()->GetSelectionMode() == NO_SELECTION ) 208cdf0e10cSrcweir { 209cdf0e10cSrcweir i_tableControl.activateCell( tableCell.nColumn, tableCell.nRow ); 210cdf0e10cSrcweir handled = true; 211cdf0e10cSrcweir } 212cdf0e10cSrcweir else 213cdf0e10cSrcweir { 214cdf0e10cSrcweir handled = i_tableControl.getSelEngine()->SelMouseButtonDown( i_event ); 215cdf0e10cSrcweir } 216cdf0e10cSrcweir } 217cdf0e10cSrcweir 218cdf0e10cSrcweir if ( handled ) 219cdf0e10cSrcweir m_bActive = true; 220cdf0e10cSrcweir return handled ? ActivateFunction : SkipFunction; 221cdf0e10cSrcweir } 222cdf0e10cSrcweir 223cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ handleMouseUp(ITableControl & i_tableControl,MouseEvent const & i_event)224cdf0e10cSrcweir FunctionResult RowSelection::handleMouseUp( ITableControl& i_tableControl, MouseEvent const & i_event ) 225cdf0e10cSrcweir { 226cdf0e10cSrcweir TableCell const tableCell = i_tableControl.hitTest( i_event.GetPosPixel() ); 227cdf0e10cSrcweir if ( tableCell.nRow >= 0 ) 228cdf0e10cSrcweir { 229cdf0e10cSrcweir if ( i_tableControl.getSelEngine()->GetSelectionMode() != NO_SELECTION ) 230cdf0e10cSrcweir { 231cdf0e10cSrcweir i_tableControl.getSelEngine()->SelMouseButtonUp( i_event ); 232cdf0e10cSrcweir } 233cdf0e10cSrcweir } 234cdf0e10cSrcweir if ( m_bActive ) 235cdf0e10cSrcweir { 236cdf0e10cSrcweir m_bActive = false; 237cdf0e10cSrcweir return DeactivateFunction; 238cdf0e10cSrcweir } 239cdf0e10cSrcweir return SkipFunction; 240cdf0e10cSrcweir } 241cdf0e10cSrcweir 242cdf0e10cSrcweir //================================================================================================================== 243cdf0e10cSrcweir //= ColumnSortHandler 244cdf0e10cSrcweir //================================================================================================================== 245cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ handleMouseMove(ITableControl & i_tableControl,MouseEvent const & i_event)246cdf0e10cSrcweir FunctionResult ColumnSortHandler::handleMouseMove( ITableControl& i_tableControl, MouseEvent const & i_event ) 247cdf0e10cSrcweir { 248cdf0e10cSrcweir OSL_UNUSED( i_tableControl ); 249cdf0e10cSrcweir OSL_UNUSED( i_event ); 250cdf0e10cSrcweir return SkipFunction; 251cdf0e10cSrcweir } 252cdf0e10cSrcweir 253cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ handleMouseDown(ITableControl & i_tableControl,MouseEvent const & i_event)254cdf0e10cSrcweir FunctionResult ColumnSortHandler::handleMouseDown( ITableControl& i_tableControl, MouseEvent const & i_event ) 255cdf0e10cSrcweir { 256cdf0e10cSrcweir if ( m_nActiveColumn != COL_INVALID ) 257cdf0e10cSrcweir { 258cdf0e10cSrcweir OSL_ENSURE( false, "ColumnSortHandler::handleMouseDown: called while already active - suspicious!" ); 259cdf0e10cSrcweir return ContinueFunction; 260cdf0e10cSrcweir } 261cdf0e10cSrcweir 262cdf0e10cSrcweir if ( i_tableControl.getModel()->getSortAdapter() == NULL ) 263cdf0e10cSrcweir // no sorting support at the model 264cdf0e10cSrcweir return SkipFunction; 265cdf0e10cSrcweir 266cdf0e10cSrcweir TableCell const tableCell( i_tableControl.hitTest( i_event.GetPosPixel() ) ); 267cdf0e10cSrcweir if ( ( tableCell.nRow != ROW_COL_HEADERS ) || ( tableCell.nColumn < 0 ) ) 268cdf0e10cSrcweir return SkipFunction; 269cdf0e10cSrcweir 270cdf0e10cSrcweir // TODO: ensure the column header is rendered in some special way, indicating its current state 271cdf0e10cSrcweir 272cdf0e10cSrcweir m_nActiveColumn = tableCell.nColumn; 273cdf0e10cSrcweir return ActivateFunction; 274cdf0e10cSrcweir } 275cdf0e10cSrcweir 276cdf0e10cSrcweir //------------------------------------------------------------------------------------------------------------------ handleMouseUp(ITableControl & i_tableControl,MouseEvent const & i_event)277cdf0e10cSrcweir FunctionResult ColumnSortHandler::handleMouseUp( ITableControl& i_tableControl, MouseEvent const & i_event ) 278cdf0e10cSrcweir { 279cdf0e10cSrcweir if ( m_nActiveColumn == COL_INVALID ) 280cdf0e10cSrcweir return SkipFunction; 281cdf0e10cSrcweir 282cdf0e10cSrcweir TableCell const tableCell( i_tableControl.hitTest( i_event.GetPosPixel() ) ); 283cdf0e10cSrcweir if ( ( tableCell.nRow == ROW_COL_HEADERS ) && ( tableCell.nColumn == m_nActiveColumn ) ) 284cdf0e10cSrcweir { 285cdf0e10cSrcweir ITableDataSort* pSort = i_tableControl.getModel()->getSortAdapter(); 286cdf0e10cSrcweir ENSURE_OR_RETURN( pSort != NULL, "ColumnSortHandler::handleMouseUp: somebody is mocking with us!", DeactivateFunction ); 287cdf0e10cSrcweir // in handleMousButtonDown, the model claimed to have sort support ... 288cdf0e10cSrcweir 289cdf0e10cSrcweir ColumnSortDirection eSortDirection = ColumnSortAscending; 290cdf0e10cSrcweir ColumnSort const aCurrentSort = pSort->getCurrentSortOrder(); 291cdf0e10cSrcweir if ( aCurrentSort.nColumnPos == m_nActiveColumn ) 292cdf0e10cSrcweir // invert existing sort order 293cdf0e10cSrcweir eSortDirection = ( aCurrentSort.eSortDirection == ColumnSortAscending ) ? ColumnSortDescending : ColumnSortAscending; 294cdf0e10cSrcweir 295cdf0e10cSrcweir pSort->sortByColumn( m_nActiveColumn, eSortDirection ); 296cdf0e10cSrcweir } 297cdf0e10cSrcweir 298cdf0e10cSrcweir m_nActiveColumn = COL_INVALID; 299cdf0e10cSrcweir return DeactivateFunction; 300cdf0e10cSrcweir } 301cdf0e10cSrcweir 302cdf0e10cSrcweir //...................................................................................................................... 303cdf0e10cSrcweir } } // namespace svt::table 304cdf0e10cSrcweir //...................................................................................................................... 305