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