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