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 |
#ifdef GNUSTEP |
57 |
Class gwclass = [[NSBundle mainBundle] principalClass]; |
58 |
#else |
59 |
Class gwclass = [[NSBundle mainBundle] classNamed: @"GWorkspace"]; |
60 |
#endif |
61 |
|
62 |
gworkspace = (id<GWProtocol>)[gwclass gworkspace]; |
63 |
|
64 |
column = col; |
65 |
browser = [column browser]; |
66 |
dndTarget = nil; |
67 |
acceptDnd = dnd; |
68 |
|
69 |
if (acceptDnd) { |
70 |
[self registerForDraggedTypes: [NSArray arrayWithObject: NSFilenamesPboardType]]; |
71 |
} |
72 |
} |
73 |
|
74 |
return self; |
75 |
} |
76 |
|
77 |
- (NSArray *)getVisibleCellsAndTuneSpace:(float *)tspace |
78 |
{ |
79 |
NSArray *cells = [self cells]; |
80 |
|
81 |
if (cells && [cells count]) { |
82 |
NSRect vr = [self visibleRect]; |
83 |
float ylim = vr.origin.y + vr.size.height - [self cellSize].height; |
84 |
NSMutableArray *vCells = [NSMutableArray arrayWithCapacity: 1]; |
85 |
BOOL found = NO; |
86 |
int i; |
87 |
|
88 |
for (i = 0; i < [cells count]; i++) { |
89 |
NSRect cr = [self cellFrameAtRow: i column: 0]; |
90 |
|
91 |
if ((cr.origin.y >= vr.origin.y) && (cr.origin.y <= ylim)) { |
92 |
if (found == NO) { |
93 |
*tspace = cr.origin.y - vr.origin.y; |
94 |
found = YES; |
95 |
} |
96 |
[vCells addObject: [cells objectAtIndex: i]]; |
97 |
} |
98 |
} |
99 |
|
100 |
if ([vCells count]) { |
101 |
return vCells; |
102 |
} |
103 |
} |
104 |
|
105 |
return nil; |
106 |
} |
107 |
|
108 |
- (NSArray *)getNamesOfVisibleCellsAndTuneSpace:(float *)tspace |
109 |
{ |
110 |
NSArray *cells = [self cells]; |
111 |
|
112 |
if (cells && [cells count]) { |
113 |
NSRect vr = [self visibleRect]; |
114 |
float ylim = vr.origin.y + vr.size.height - [self cellSize].height; |
115 |
NSMutableArray *vCells = [NSMutableArray arrayWithCapacity: 1]; |
116 |
BOOL found = NO; |
117 |
int i; |
118 |
|
119 |
for (i = 0; i < [cells count]; i++) { |
120 |
NSRect cr = [self cellFrameAtRow: i column: 0]; |
121 |
|
122 |
if ((cr.origin.y >= vr.origin.y) && (cr.origin.y <= ylim)) { |
123 |
if (found == NO) { |
124 |
*tspace = cr.origin.y - vr.origin.y; |
125 |
found = YES; |
126 |
} |
127 |
[vCells addObject: [[cells objectAtIndex: i] stringValue]]; |
128 |
} |
129 |
} |
130 |
|
131 |
if ([vCells count]) { |
132 |
return vCells; |
133 |
} |
134 |
} |
135 |
|
136 |
return nil; |
137 |
} |
138 |
|
139 |
- (void)scrollToFirstPositionCell:(id)aCell withScrollTune:(float)vtune |
140 |
{ |
141 |
NSRect vr, cr; |
142 |
int row, col; |
143 |
|
144 |
vr = [self visibleRect]; |
145 |
|
146 |
[self getRow: &row column: &col ofCell: aCell]; |
147 |
cr = [self cellFrameAtRow: row column: col]; |
148 |
cr.size.height = vr.size.height - vtune; |
149 |
|
150 |
[self scrollRectToVisible: cr]; |
151 |
} |
152 |
|
153 |
- (void)selectIconOfCell:(id)aCell |
154 |
{ |
155 |
BCell *cell = (BCell *)aCell; |
156 |
|
157 |
if ([cell selectIcon]) { |
158 |
NSRect cellFrame; |
159 |
int row, col; |
160 |
|
161 |
[self getRow: &row column: &col ofCell: aCell]; |
162 |
cellFrame = [self cellFrameAtRow: row column: col]; |
163 |
[self setNeedsDisplayInRect: cellFrame]; |
164 |
} |
165 |
|
166 |
[self unSelectIconsOfCellsDifferentFrom: cell]; |
167 |
} |
168 |
|
169 |
- (void)unSelectIconsOfCellsDifferentFrom:(id)aCell |
170 |
{ |
171 |
NSArray *cells = [self cells]; |
172 |
int i = 0; |
173 |
|
174 |
for (i = 0; i < [cells count]; i++) { |
175 |
BCell *c = [cells objectAtIndex: i]; |
176 |
|
177 |
if (c != aCell) { |
178 |
if ([c unSelectIcon]) { |
179 |
NSRect cellFrame; |
180 |
int row, col; |
181 |
|
182 |
[self getRow: &row column: &col ofCell: c]; |
183 |
cellFrame = [self cellFrameAtRow: row column: col]; |
184 |
[self setNeedsDisplayInRect: cellFrame]; |
185 |
} |
186 |
} |
187 |
} |
188 |
} |
189 |
|
190 |
- (void)mouseDown:(NSEvent*)theEvent |
191 |
{ |
192 |
if (acceptDnd == NO) { |
193 |
[super mouseDown: theEvent]; |
194 |
return; |
195 |
|
196 |
} else { |
197 |
int clickCount; |
198 |
NSPoint lastLocation; |
199 |
int row, col; |
200 |
|
201 |
if (([self numberOfRows] == 0) || ([self numberOfColumns] == 0)) { |
202 |
[super mouseDown: theEvent]; |
203 |
return; |
204 |
} |
205 |
|
206 |
clickCount = [theEvent clickCount]; |
207 |
|
208 |
if (clickCount > 2) { |
209 |
return; |
210 |
} |
211 |
|
212 |
if (clickCount == 2) { |
213 |
[self sendDoubleAction]; |
214 |
return; |
215 |
} |
216 |
|
217 |
lastLocation = [theEvent locationInWindow]; |
218 |
lastLocation = [self convertPoint: lastLocation |
219 |
fromView: nil]; |
220 |
|
221 |
if ([self getRow: &row column: &col forPoint: lastLocation]) { |
222 |
BCell *cell = [[self cells] objectAtIndex: row]; |
223 |
NSRect rect = [self cellFrameAtRow: row column: col]; |
224 |
|
225 |
if ([cell isEnabled]) { |
226 |
NSSize size = [cell iconSize]; |
227 |
|
228 |
rect.size.width = size.width; |
229 |
rect.size.height = size.height; |
230 |
|
231 |
if (NSPointInRect(lastLocation, rect)) { |
232 |
NSEvent *nextEvent; |
233 |
BOOL startdnd = NO; |
234 |
int dragdelay = 0; |
235 |
|
236 |
if ([theEvent modifierFlags] & NSShiftKeyMask) { |
237 |
[super mouseDown: theEvent]; |
238 |
return; |
239 |
} |
240 |
|
241 |
[self deselectAllCells]; |
242 |
[self selectCellAtRow: row column: col]; |
243 |
[self sendAction]; |
244 |
|
245 |
while (1) { |
246 |
nextEvent = [[self window] nextEventMatchingMask: |
247 |
NSLeftMouseUpMask | NSLeftMouseDraggedMask]; |
248 |
|
249 |
if ([nextEvent type] == NSLeftMouseUp) { |
250 |
break; |
251 |
|
252 |
} else if ([nextEvent type] == NSLeftMouseDragged) { |
253 |
if(dragdelay < 5) { |
254 |
dragdelay++; |
255 |
} else { |
256 |
startdnd = YES; |
257 |
break; |
258 |
} |
259 |
} |
260 |
} |
261 |
|
262 |
if (startdnd == YES) { |
263 |
[self startExternalDragOnEvent: nextEvent]; |
264 |
} |
265 |
} else { |
266 |
[super mouseDown: theEvent]; |
267 |
} |
268 |
} |
269 |
} |
270 |
} |
271 |
} |
272 |
|
273 |
- (BOOL)acceptsFirstResponder |
274 |
{ |
275 |
return (![browser isEditingIconName]); |
276 |
} |
277 |
|
278 |
@end |
279 |
|
280 |
@implementation BMatrix (DraggingSource) |
281 |
|
282 |
- (void)startExternalDragOnEvent:(NSEvent *)event |
283 |
{ |
284 |
NSPoint dragPoint; |
285 |
NSPasteboard *pb; |
286 |
NSArray *selectedCells; |
287 |
NSImage *dragIcon; |
288 |
|
289 |
dragPoint = [event locationInWindow]; |
290 |
dragPoint = [self convertPoint: dragPoint fromView: nil]; |
291 |
|
292 |
pb = [NSPasteboard pasteboardWithName: NSDragPboard]; |
293 |
[self declareAndSetShapeOnPasteboard: pb]; |
294 |
|
295 |
selectedCells = [self selectedCells]; |
296 |
|
297 |
if ([selectedCells count] > 1) { |
298 |
dragIcon = [NSImage imageNamed: @"MultipleSelection.tiff"]; |
299 |
} else { |
300 |
NSArray *paths = [[selectedCells objectAtIndex: 0] paths]; |
301 |
|
302 |
if ([paths count] > 1) { |
303 |
dragIcon = [NSImage imageNamed: @"MultipleSelection.tiff"]; |
304 |
} else { |
305 |
NSString *path = [paths objectAtIndex: 0]; |
306 |
NSString *type = [gworkspace typeOfFileAt: path]; |
307 |
|
308 |
dragIcon = [gworkspace iconForFile: path ofType: type]; |
309 |
} |
310 |
} |
311 |
|
312 |
[self dragImage: dragIcon |
313 |
at: dragPoint |
314 |
offset: NSZeroSize |
315 |
event: event |
316 |
pasteboard: pb |
317 |
source: self |
318 |
slideBack: [gworkspace animateSlideBack]]; |
319 |
} |
320 |
|
321 |
- (void)draggedImage:(NSImage *)anImage |
322 |
endedAt:(NSPoint)aPoint |
323 |
deposited:(BOOL)flag |
324 |
{ |
325 |
} |
326 |
|
327 |
- (void)declareAndSetShapeOnPasteboard:(NSPasteboard *)pb |
328 |
{ |
329 |
NSArray *selectedCells = [self selectedCells]; |
330 |
NSMutableArray *selection = [NSMutableArray arrayWithCapacity: 1]; |
331 |
NSArray *dndtypes; |
332 |
int i; |
333 |
|
334 |
for (i = 0; i < [selectedCells count]; i++) { |
335 |
NSArray *paths = [[selectedCells objectAtIndex: i] paths]; |
336 |
[selection addObjectsFromArray: paths]; |
337 |
} |
338 |
|
339 |
dndtypes = [NSArray arrayWithObject: NSFilenamesPboardType]; |
340 |
[pb declareTypes: dndtypes owner: nil]; |
341 |
|
342 |
if ([pb setPropertyList: selection forType: NSFilenamesPboardType] == NO) { |
343 |
return; |
344 |
} |
345 |
} |
346 |
|
347 |
- (unsigned int)draggingSourceOperationMaskForLocal:(BOOL)flag |
348 |
{ |
349 |
return NSDragOperationAll; |
350 |
} |
351 |
|
352 |
@end |
353 |
|
354 |
@implementation BMatrix (DraggingDestination) |
355 |
|
356 |
- (unsigned int)checkReturnValueForCell:(NSCell *)acell |
357 |
withDraggingInfo:(id <NSDraggingInfo>)sender |
358 |
{ |
359 |
if (dndTarget != acell) { |
360 |
dndTarget = acell; |
361 |
dragOperation = [column draggingEntered: sender inMatrixCell: dndTarget]; |
362 |
|
363 |
if (dragOperation != NSDragOperationNone) { |
364 |
[self selectIconOfCell: dndTarget]; |
365 |
} else { |
366 |
[self unSelectIconsOfCellsDifferentFrom: nil]; |
367 |
} |
368 |
} |
369 |
|
370 |
return dragOperation; |
371 |
} |
372 |
|
373 |
- (unsigned int)draggingEntered:(id <NSDraggingInfo>)sender |
374 |
{ |
375 |
NSPoint location; |
376 |
int row, col; |
377 |
|
378 |
location = [[self window] mouseLocationOutsideOfEventStream]; |
379 |
location = [self convertPoint: location fromView: nil]; |
380 |
|
381 |
if ([self getRow: &row column: &col forPoint: location]) { |
382 |
dndTarget = [[self cells] objectAtIndex: row]; |
383 |
dragOperation = [column draggingEntered: sender inMatrixCell: dndTarget]; |
384 |
|
385 |
if (dragOperation != NSDragOperationNone) { |
386 |
[self selectIconOfCell: dndTarget]; |
387 |
} else { |
388 |
[self unSelectIconsOfCellsDifferentFrom: nil]; |
389 |
} |
390 |
|
391 |
return dragOperation; |
392 |
} |
393 |
|
394 |
return NSDragOperationNone; |
395 |
} |
396 |
|
397 |
- (unsigned int)draggingUpdated:(id <NSDraggingInfo>)sender |
398 |
{ |
399 |
NSPoint location; |
400 |
int row, col; |
401 |
|
402 |
location = [[self window] mouseLocationOutsideOfEventStream]; |
403 |
location = [self convertPoint: location fromView: nil]; |
404 |
|
405 |
if ([self getRow: &row column: &col forPoint: location]) { |
406 |
NSCell *cell = [[self cells] objectAtIndex: row]; |
407 |
return [self checkReturnValueForCell: cell withDraggingInfo: sender]; |
408 |
} |
409 |
|
410 |
return NSDragOperationNone; |
411 |
} |
412 |
|
413 |
- (void)draggingExited:(id <NSDraggingInfo>)sender |
414 |
{ |
415 |
[self unSelectIconsOfCellsDifferentFrom: nil]; |
416 |
dndTarget = nil; |
417 |
} |
418 |
|
419 |
- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender |
420 |
{ |
421 |
return (dndTarget ? YES : NO); |
422 |
} |
423 |
|
424 |
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender |
425 |
{ |
426 |
return (dndTarget ? YES : NO); |
427 |
} |
428 |
|
429 |
- (void)concludeDragOperation:(id <NSDraggingInfo>)sender |
430 |
{ |
431 |
[column concludeDragOperation: sender inMatrixCell: dndTarget]; |
432 |
[self unSelectIconsOfCellsDifferentFrom: nil]; |
433 |
} |
434 |
|
435 |
@end |