1 |
/* BMatrix.m |
2 |
* |
3 |
* Copyright (C) 2003 Free Software Foundation, Inc. |
4 |
* |
5 |
* Author: Enrico Sersale <enrico@imago.ro> |
6 |
* Date: August 2001 |
7 |
* |
8 |
* This file is part of the GNUstep GWorkspace application |
9 |
* |
10 |
* This program is free software; you can redistribute it and/or modify |
11 |
* it under the terms of the GNU General Public License as published by |
12 |
* the Free Software Foundation; either version 2 of the License, or |
13 |
* (at your option) any later version. |
14 |
* |
15 |
* This program is distributed in the hope that it will be useful, |
16 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 |
* GNU General Public License for more details. |
19 |
* |
20 |
* You should have received a copy of the GNU General Public License |
21 |
* along with this program; if not, write to the Free Software |
22 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
23 |
*/ |
24 |
|
25 |
|
26 |
#include <Foundation/Foundation.h> |
27 |
#include <AppKit/AppKit.h> |
28 |
#include "GWProtocol.h" |
29 |
#include "GWLib.h" |
30 |
#include "GWNotifications.h" |
31 |
#include "BMatrix.h" |
32 |
#include "BColumn.h" |
33 |
#include "BCell.h" |
34 |
#include "Browser2.h" |
35 |
#include "GNUstep.h" |
36 |
|
37 |
@implementation BMatrix |
38 |
|
39 |
- (void)dealloc |
40 |
{ |
41 |
[super dealloc]; |
42 |
} |
43 |
|
44 |
- (id)initInColumn:(BColumn *)col |
45 |
withFrame:(NSRect)frameRect |
46 |
mode:(int)aMode |
47 |
prototype:(NSCell *)aCell |
48 |
numberOfRows:(int)numRows |
49 |
numberOfColumns:(int)numColumns |
50 |
acceptDnd:(BOOL)dnd |
51 |
{ |
52 |
self = [super initWithFrame: frameRect mode: aMode prototype: aCell |
53 |
numberOfRows: numRows numberOfColumns: numColumns]; |
54 |
|
55 |
if (self) { |
56 |
column = col; |
57 |
browser = [column browser]; |
58 |
dndTarget = nil; |
59 |
acceptDnd = dnd; |
60 |
|
61 |
if (acceptDnd) { |
62 |
[self registerForDraggedTypes: [NSArray arrayWithObject: NSFilenamesPboardType]]; |
63 |
} |
64 |
} |
65 |
|
66 |
return self; |
67 |
} |
68 |
|
69 |
- (NSArray *)getVisibleCellsAndTuneSpace:(float *)tspace |
70 |
{ |
71 |
NSArray *cells = [self cells]; |
72 |
|
73 |
if (cells && [cells count]) { |
74 |
NSRect vr = [self visibleRect]; |
75 |
float ylim = vr.origin.y + vr.size.height - [self cellSize].height; |
76 |
NSMutableArray *vCells = [NSMutableArray arrayWithCapacity: 1]; |
77 |
BOOL found = NO; |
78 |
int i; |
79 |
|
80 |
for (i = 0; i < [cells count]; i++) { |
81 |
NSRect cr = [self cellFrameAtRow: i column: 0]; |
82 |
|
83 |
if ((cr.origin.y >= vr.origin.y) && (cr.origin.y <= ylim)) { |
84 |
if (found == NO) { |
85 |
*tspace = cr.origin.y - vr.origin.y; |
86 |
found = YES; |
87 |
} |
88 |
[vCells addObject: [cells objectAtIndex: i]]; |
89 |
} |
90 |
} |
91 |
|
92 |
if ([vCells count]) { |
93 |
return vCells; |
94 |
} |
95 |
} |
96 |
|
97 |
return nil; |
98 |
} |
99 |
|
100 |
- (NSArray *)getNamesOfVisibleCellsAndTuneSpace:(float *)tspace |
101 |
{ |
102 |
NSArray *cells = [self cells]; |
103 |
|
104 |
if (cells && [cells count]) { |
105 |
NSRect vr = [self visibleRect]; |
106 |
float ylim = vr.origin.y + vr.size.height - [self cellSize].height; |
107 |
NSMutableArray *vCells = [NSMutableArray arrayWithCapacity: 1]; |
108 |
BOOL found = NO; |
109 |
int i; |
110 |
|
111 |
for (i = 0; i < [cells count]; i++) { |
112 |
NSRect cr = [self cellFrameAtRow: i column: 0]; |
113 |
|
114 |
if ((cr.origin.y >= vr.origin.y) && (cr.origin.y <= ylim)) { |
115 |
if (found == NO) { |
116 |
*tspace = cr.origin.y - vr.origin.y; |
117 |
found = YES; |
118 |
} |
119 |
[vCells addObject: [[cells objectAtIndex: i] stringValue]]; |
120 |
} |
121 |
} |
122 |
|
123 |
if ([vCells count]) { |
124 |
return vCells; |
125 |
} |
126 |
} |
127 |
|
128 |
return nil; |
129 |
} |
130 |
|
131 |
- (void)scrollToFirstPositionCell:(id)aCell withScrollTune:(float)vtune |
132 |
{ |
133 |
NSRect vr, cr; |
134 |
int row, col; |
135 |
|
136 |
vr = [self visibleRect]; |
137 |
|
138 |
[self getRow: &row column: &col ofCell: aCell]; |
139 |
cr = [self cellFrameAtRow: row column: col]; |
140 |
cr.size.height = vr.size.height - vtune; |
141 |
|
142 |
[self scrollRectToVisible: cr]; |
143 |
} |
144 |
|
145 |
- (void)selectIconOfCell:(id)aCell |
146 |
{ |
147 |
BCell *cell = (BCell *)aCell; |
148 |
|
149 |
if ([cell selectIcon]) { |
150 |
NSRect cellFrame; |
151 |
int row, col; |
152 |
|
153 |
[self getRow: &row column: &col ofCell: aCell]; |
154 |
cellFrame = [self cellFrameAtRow: row column: col]; |
155 |
[self setNeedsDisplayInRect: cellFrame]; |
156 |
} |
157 |
|
158 |
[self unSelectIconsOfCellsDifferentFrom: cell]; |
159 |
} |
160 |
|
161 |
- (void)unSelectIconsOfCellsDifferentFrom:(id)aCell |
162 |
{ |
163 |
NSArray *cells = [self cells]; |
164 |
int i = 0; |
165 |
|
166 |
for (i = 0; i < [cells count]; i++) { |
167 |
BCell *c = [cells objectAtIndex: i]; |
168 |
|
169 |
if (c != aCell) { |
170 |
if ([c unSelectIcon]) { |
171 |
NSRect cellFrame; |
172 |
int row, col; |
173 |
|
174 |
[self getRow: &row column: &col ofCell: c]; |
175 |
cellFrame = [self cellFrameAtRow: row column: col]; |
176 |
[self setNeedsDisplayInRect: cellFrame]; |
177 |
} |
178 |
} |
179 |
} |
180 |
} |
181 |
|
182 |
- (void)mouseDown:(NSEvent*)theEvent |
183 |
{ |
184 |
if (acceptDnd == NO) { |
185 |
[super mouseDown: theEvent]; |
186 |
return; |
187 |
|
188 |
} else { |
189 |
int clickCount; |
190 |
NSPoint lastLocation; |
191 |
int row, col; |
192 |
|
193 |
if (([self numberOfRows] == 0) || ([self numberOfColumns] == 0)) { |
194 |
[super mouseDown: theEvent]; |
195 |
return; |
196 |
} |
197 |
|
198 |
clickCount = [theEvent clickCount]; |
199 |
|
200 |
if (clickCount > 2) { |
201 |
return; |
202 |
} |
203 |
|
204 |
if (clickCount == 2) { |
205 |
[self sendDoubleAction]; |
206 |
return; |
207 |
} |
208 |
|
209 |
lastLocation = [theEvent locationInWindow]; |
210 |
lastLocation = [self convertPoint: lastLocation |
211 |
fromView: nil]; |
212 |
|
213 |
if ([self getRow: &row column: &col forPoint: lastLocation]) { |
214 |
BCell *cell = [[self cells] objectAtIndex: row]; |
215 |
NSRect rect = [self cellFrameAtRow: row column: col]; |
216 |
|
217 |
if ([cell isEnabled]) { |
218 |
NSSize size = [cell iconSize]; |
219 |
|
220 |
rect.size.width = size.width; |
221 |
rect.size.height = size.height; |
222 |
|
223 |
if (NSPointInRect(lastLocation, rect)) { |
224 |
NSEvent *nextEvent; |
225 |
BOOL startdnd = NO; |
226 |
int dragdelay = 0; |
227 |
|
228 |
if ([theEvent modifierFlags] & NSShiftKeyMask) { |
229 |
[super mouseDown: theEvent]; |
230 |
return; |
231 |
} |
232 |
|
233 |
[self deselectAllCells]; |
234 |
[self selectCellAtRow: row column: col]; |
235 |
[self sendAction]; |
236 |
|
237 |
while (1) { |
238 |
nextEvent = [[self window] nextEventMatchingMask: |
239 |
NSLeftMouseUpMask | NSLeftMouseDraggedMask]; |
240 |
|
241 |
if ([nextEvent type] == NSLeftMouseUp) { |
242 |
break; |
243 |
|
244 |
} else if ([nextEvent type] == NSLeftMouseDragged) { |
245 |
if(dragdelay < 5) { |
246 |
dragdelay++; |
247 |
} else { |
248 |
startdnd = YES; |
249 |
break; |
250 |
} |
251 |
} |
252 |
} |
253 |
|
254 |
if (startdnd == YES) { |
255 |
[self startExternalDragOnEvent: nextEvent]; |
256 |
} |
257 |
} else { |
258 |
[super mouseDown: theEvent]; |
259 |
} |
260 |
} |
261 |
} |
262 |
} |
263 |
} |
264 |
|
265 |
- (BOOL)acceptsFirstResponder |
266 |
{ |
267 |
return (![browser isEditingIconName]); |
268 |
} |
269 |
|
270 |
@end |
271 |
|
272 |
@implementation BMatrix (DraggingSource) |
273 |
|
274 |
- (void)startExternalDragOnEvent:(NSEvent *)event |
275 |
{ |
276 |
NSPoint dragPoint; |
277 |
NSPasteboard *pb; |
278 |
NSArray *selectedCells; |
279 |
NSImage *dragIcon; |
280 |
|
281 |
dragPoint = [event locationInWindow]; |
282 |
dragPoint = [self convertPoint: dragPoint fromView: nil]; |
283 |
|
284 |
pb = [NSPasteboard pasteboardWithName: NSDragPboard]; |
285 |
[self declareAndSetShapeOnPasteboard: pb]; |
286 |
|
287 |
selectedCells = [self selectedCells]; |
288 |
|
289 |
if ([selectedCells count] > 1) { |
290 |
dragIcon = [NSImage imageNamed: @"MultipleSelection.tiff"]; |
291 |
} else { |
292 |
NSArray *paths = [[selectedCells objectAtIndex: 0] paths]; |
293 |
|
294 |
if ([paths count] > 1) { |
295 |
dragIcon = [NSImage imageNamed: @"MultipleSelection.tiff"]; |
296 |
} else { |
297 |
NSString *path = [paths objectAtIndex: 0]; |
298 |
NSString *type = [GWLib typeOfFileAt: path]; |
299 |
|
300 |
dragIcon = [GWLib iconForFile: path ofType: type]; |
301 |
} |
302 |
} |
303 |
|
304 |
[self dragImage: dragIcon |
305 |
at: dragPoint |
306 |
offset: NSZeroSize |
307 |
event: event |
308 |
pasteboard: pb |
309 |
source: self |
310 |
slideBack: [[GWLib workspaceApp] animateSlideBack]]; |
311 |
} |
312 |
|
313 |
- (void)draggedImage:(NSImage *)anImage |
314 |
endedAt:(NSPoint)aPoint |
315 |
deposited:(BOOL)flag |
316 |
{ |
317 |
} |
318 |
|
319 |
- (void)declareAndSetShapeOnPasteboard:(NSPasteboard *)pb |
320 |
{ |
321 |
NSArray *selectedCells = [self selectedCells]; |
322 |
NSMutableArray *selection = [NSMutableArray arrayWithCapacity: 1]; |
323 |
NSArray *dndtypes; |
324 |
int i; |
325 |
|
326 |
for (i = 0; i < [selectedCells count]; i++) { |
327 |
NSArray *paths = [[selectedCells objectAtIndex: i] paths]; |
328 |
[selection addObjectsFromArray: paths]; |
329 |
} |
330 |
|
331 |
dndtypes = [NSArray arrayWithObject: NSFilenamesPboardType]; |
332 |
[pb declareTypes: dndtypes owner: nil]; |
333 |
|
334 |
if ([pb setPropertyList: selection forType: NSFilenamesPboardType] == NO) { |
335 |
return; |
336 |
} |
337 |
} |
338 |
|
339 |
- (unsigned int)draggingSourceOperationMaskForLocal:(BOOL)flag |
340 |
{ |
341 |
return NSDragOperationAll; |
342 |
} |
343 |
|
344 |
@end |
345 |
|
346 |
@implementation BMatrix (DraggingDestination) |
347 |
|
348 |
- (unsigned int)checkReturnValueForCell:(NSCell *)acell |
349 |
withDraggingInfo:(id <NSDraggingInfo>)sender |
350 |
{ |
351 |
if (dndTarget != acell) { |
352 |
dndTarget = acell; |
353 |
dragOperation = [column draggingEntered: sender inMatrixCell: dndTarget]; |
354 |
|
355 |
if (dragOperation != NSDragOperationNone) { |
356 |
[self selectIconOfCell: dndTarget]; |
357 |
} else { |
358 |
[self unSelectIconsOfCellsDifferentFrom: nil]; |
359 |
} |
360 |
} |
361 |
|
362 |
return dragOperation; |
363 |
} |
364 |
|
365 |
- (unsigned int)draggingEntered:(id <NSDraggingInfo>)sender |
366 |
{ |
367 |
NSPoint location; |
368 |
int row, col; |
369 |
|
370 |
location = [[self window] mouseLocationOutsideOfEventStream]; |
371 |
location = [self convertPoint: location fromView: nil]; |
372 |
|
373 |
if ([self getRow: &row column: &col forPoint: location]) { |
374 |
dndTarget = [[self cells] objectAtIndex: row]; |
375 |
dragOperation = [column draggingEntered: sender inMatrixCell: dndTarget]; |
376 |
|
377 |
if (dragOperation != NSDragOperationNone) { |
378 |
[self selectIconOfCell: dndTarget]; |
379 |
} else { |
380 |
[self unSelectIconsOfCellsDifferentFrom: nil]; |
381 |
} |
382 |
|
383 |
return dragOperation; |
384 |
} |
385 |
|
386 |
return NSDragOperationNone; |
387 |
} |
388 |
|
389 |
- (unsigned int)draggingUpdated:(id <NSDraggingInfo>)sender |
390 |
{ |
391 |
NSPoint location; |
392 |
int row, col; |
393 |
|
394 |
location = [[self window] mouseLocationOutsideOfEventStream]; |
395 |
location = [self convertPoint: location fromView: nil]; |
396 |
|
397 |
if ([self getRow: &row column: &col forPoint: location]) { |
398 |
NSCell *cell = [[self cells] objectAtIndex: row]; |
399 |
return [self checkReturnValueForCell: cell withDraggingInfo: sender]; |
400 |
} |
401 |
|
402 |
return NSDragOperationNone; |
403 |
} |
404 |
|
405 |
- (void)draggingExited:(id <NSDraggingInfo>)sender |
406 |
{ |
407 |
[self unSelectIconsOfCellsDifferentFrom: nil]; |
408 |
dndTarget = nil; |
409 |
} |
410 |
|
411 |
- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender |
412 |
{ |
413 |
return (dndTarget ? YES : NO); |
414 |
} |
415 |
|
416 |
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender |
417 |
{ |
418 |
return (dndTarget ? YES : NO); |
419 |
} |
420 |
|
421 |
- (void)concludeDragOperation:(id <NSDraggingInfo>)sender |
422 |
{ |
423 |
[column concludeDragOperation: sender inMatrixCell: dndTarget]; |
424 |
[self unSelectIconsOfCellsDifferentFrom: nil]; |
425 |
} |
426 |
|
427 |
@end |