xref: /AOO41X/main/svtools/source/table/mousefunction.cxx (revision 5900e8ec128faec89519683efce668ccd8cc6084)
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