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