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