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