/[gnustep]/gnustep/usr-apps/gworkspace/Viewers/IconsViewer/PathIcon.m
ViewVC logotype

Contents of /gnustep/usr-apps/gworkspace/Viewers/IconsViewer/PathIcon.m

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (show annotations) (download)
Tue Sep 30 15:38:06 2003 UTC (20 years, 7 months ago) by esersale
Branch: MAIN
Changes since 1.2: +11 -19 lines
*** empty log message ***

1 /* PathIcon.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 #ifdef GNUSTEP
29 #include "GWLib.h"
30 #include "GWProtocol.h"
31 #include "GWFunctions.h"
32 #include "GWNotifications.h"
33 #else
34 #include <GWorkspace/GWLib.h>
35 #include <GWorkspace/GWProtocol.h>
36 #include <GWorkspace/GWFunctions.h>
37 #include <GWorkspace/GWNotifications.h>
38 #endif
39 #include "PathIcon.h"
40 #include "PathIconLabel.h"
41 #include "IconsPath.h"
42 #include "GNUstep.h"
43
44 #define ICONPOSITION(s1, s2) (NSMakePoint(((int)(s1).width - (int)(s2).width) >> 1, \
45 ((int)(s1).height - (int)(s2).height) >> 1))
46
47 #define ONICON(p, s1, s2) ([self mouse: (p) \
48 inRect: NSMakeRect(((int)(s1).width - (int)(s2).width) >> 1,\
49 ((int)(s1).height - (int)(s2).height) >> 1, 48, 48)])
50
51 #define CHECK_LOCK if (locked) return
52 #define CHECK_LOCK_RET(x) if (locked) return x
53
54 @implementation PathIcon
55
56 - (void)dealloc
57 {
58 [[NSNotificationCenter defaultCenter] removeObserver: self];
59 TEST_RELEASE (paths);
60 TEST_RELEASE (fullpath);
61 TEST_RELEASE (name);
62 TEST_RELEASE (hostname);
63 TEST_RELEASE (type);
64 RELEASE (namelabel);
65 TEST_RELEASE (icon);
66 RELEASE (highlight);
67 RELEASE (arrow);
68 [super dealloc];
69 }
70
71 - (id)initWithDelegate:(id)aDelegate
72 {
73 self = [super init];
74
75 if (self) {
76 fm = [NSFileManager defaultManager];
77 ws = [NSWorkspace sharedWorkspace];
78
79 [self setDelegate: aDelegate];
80
81 ASSIGN (highlight, [NSImage imageNamed: @"CellHighlight.tiff"]);
82 ASSIGN (arrow, [NSImage imageNamed: @"common_3DArrowRight.tiff"]);
83 icon = nil;
84
85 namelabel = [[PathIconLabel alloc] initForPathIcon: self];
86 [namelabel setFont: [NSFont systemFontOfSize: 12]];
87 [namelabel setBezeled: NO];
88 [namelabel setEditable: NO];
89 [namelabel setSelectable: NO];
90 [namelabel setAlignment: NSCenterTextAlignment];
91 [namelabel setBackgroundColor: [NSColor windowBackgroundColor]];
92
93 contestualMenu = [[GWLib workspaceApp] usesContestualMenu];
94
95 hostname = nil;
96 isbranch = NO;
97 locked = NO;
98 singlepath = YES;
99 isSelect = NO;
100 dragdelay = 0;
101 isDragTarget = NO;
102 isRootIcon = NO;
103 isPakage = NO;
104
105 [self registerForDraggedTypes: [NSArray arrayWithObjects: NSFilenamesPboardType, nil]];
106 }
107
108 return self;
109 }
110
111 - (void)setPaths:(NSArray *)p
112 {
113 NSString *defapp = nil, *t = nil;
114 float width, labwidth;
115 int i, count;
116
117 if ([p isEqualToArray: paths]) {
118 return;
119 }
120
121 if (p == nil) {
122 TEST_RELEASE (paths);
123 paths = nil;
124 TEST_RELEASE (fullpath);
125 TEST_RELEASE (name);
126 TEST_RELEASE (type);
127 type = nil;
128 isPakage = NO;
129 TEST_RELEASE (icon);
130 icon = nil;
131 return;
132 }
133
134 ASSIGN (paths, p);
135 count = [paths count];
136
137 if (count == 1) {
138 singlepath = YES;
139 ASSIGN (fullpath, [paths objectAtIndex: 0]);
140 if ([fullpath isEqualToString: fixPath(@"/", 0)]) {
141 ASSIGN (name, fullpath);
142 isRootIcon = YES;
143 } else {
144 ASSIGN (name, [fullpath lastPathComponent]);
145 isRootIcon = NO;
146 }
147 [ws getInfoForFile: fullpath application: &defapp type: &t];
148 ASSIGN (type, t);
149 isPakage = [GWLib isPakageAtPath: fullpath];
150
151 } else {
152 singlepath = NO;
153 ASSIGN (name, ([NSString stringWithFormat: @"%i items", count]));
154 type = nil;
155 isRootIcon = NO;
156 isPakage = NO;
157 }
158
159 if (singlepath == YES) {
160 ASSIGN (icon, [GWLib iconForFile: fullpath ofType: type]);
161 } else {
162 ASSIGN (icon, [NSImage imageNamed: @"MultipleSelection.tiff"]);
163 }
164
165 width = [self frame].size.width;
166 labwidth = [[namelabel font] widthOfString: name] + 8;
167 if (labwidth > width) {
168 labwidth = width;
169 }
170 [namelabel setFrame: NSMakeRect(0, 0, labwidth, 14)];
171
172 if (isRootIcon == NO) {
173 [namelabel setStringValue: cutFileLabelText(name, namelabel, labwidth)];
174 } else {
175 NSHost *host = [NSHost currentHost];
176 NSString *hname = [host name];
177 NSRange range = [hname rangeOfString: @"."];
178
179 if (range.length != 0) {
180 hname = [hname substringToIndex: range.location];
181 }
182 ASSIGN (hostname, hname);
183 [namelabel setStringValue: hostname];
184 }
185
186 [self setLocked: NO];
187
188 for (i = 0; i < [paths count]; i++) {
189 NSString *path = [paths objectAtIndex: i];
190
191 if ([GWLib isLockedPath: path]) {
192 [self setLocked: YES];
193 break;
194 }
195 }
196
197 [delegate setLabelFrameOfIcon: self];
198 [self setNeedsDisplay: YES];
199 }
200
201 - (void)setFrame:(NSRect)frameRect
202 {
203 float width, labwidth;
204
205 [super setFrame: frameRect];
206
207 width = [self frame].size.width;
208
209 if (isRootIcon == NO) {
210 labwidth = [[namelabel font] widthOfString: name] + 8;
211 } else {
212 labwidth = [[namelabel font] widthOfString: hostname] + 8;
213 }
214 if (labwidth > width) {
215 labwidth = width;
216 }
217
218 [namelabel setFrame: NSMakeRect(0, 0, labwidth, 14)];
219
220 if (isRootIcon == NO) {
221 [namelabel setStringValue: cutFileLabelText(name, namelabel, labwidth)];
222 } else {
223 [namelabel setStringValue: hostname];
224 }
225
226 [delegate setLabelFrameOfIcon: self];
227
228 [self setNeedsDisplay: YES];
229 }
230
231 - (void)select
232 {
233 if (isSelect) {
234 return;
235 }
236
237 isSelect = YES;
238 [namelabel setBackgroundColor: [NSColor whiteColor]];
239 [delegate setLabelFrameOfIcon: self];
240 [delegate unselectIconsDifferentFrom: self];
241 [self setNeedsDisplay: YES];
242 }
243
244 - (void)unselect
245 {
246 if (isSelect == NO) {
247 return;
248 }
249
250 isSelect = NO;
251 [namelabel setBackgroundColor: [NSColor windowBackgroundColor]];
252 [self setNeedsDisplay: YES];
253 }
254
255 - (void)renewIcon
256 {
257 if (singlepath == YES) {
258 ASSIGN (icon, [GWLib iconForFile: fullpath ofType: type]);
259 } else {
260 ASSIGN (icon, [NSImage imageNamed: @"MultipleSelection.tiff"]);
261 }
262 [self setNeedsDisplay: YES];
263 }
264
265 - (void)openWithApp:(id)sender
266 {
267 NSString *appName = [[sender representedObject] objectForKey: @"appName"];
268 NSString *fullPath = [[sender representedObject] objectForKey: @"fullPath"];
269
270 [ws openFile: fullPath withApplication: appName];
271 }
272
273 - (void)openWith:(id)sender
274 {
275 [[GWLib workspaceApp] openSelectedPathsWith];
276 }
277
278 - (BOOL)isSelect
279 {
280 return isSelect;
281 }
282
283 - (NSTextField *)label
284 {
285 return namelabel;
286 }
287
288 - (void)setBranch:(BOOL)value
289 {
290 isbranch = value;
291 }
292
293 - (BOOL)isBranch
294 {
295 return isbranch;
296 }
297
298 - (void)setLocked:(BOOL)value
299 {
300 if (locked == value) {
301 return;
302 }
303 locked = value;
304 [namelabel setTextColor: (locked ? [NSColor disabledControlTextColor]
305 : [NSColor controlTextColor])];
306 [self setNeedsDisplay: YES];
307 [namelabel setNeedsDisplay: YES];
308 }
309
310 - (BOOL)isLocked
311 {
312 return locked;
313 }
314
315 - (BOOL)isRootIcon
316 {
317 return isRootIcon;
318 }
319
320 - (BOOL)isPakage
321 {
322 return isPakage;
323 }
324
325 - (NSArray *)paths
326 {
327 return paths;
328 }
329
330 - (NSString *)name
331 {
332 return name;
333 }
334
335 - (NSString *)hostname
336 {
337 return hostname;
338 }
339
340 - (NSString *)type
341 {
342 return type;
343 }
344
345 - (NSImage *)icon
346 {
347 return icon;
348 }
349
350 - (NSSize)iconShift
351 {
352 NSRect r = [self frame];
353 NSSize s = [icon size];
354
355 return NSMakeSize((r.size.width - s.width) / 2, (r.size.height - s.height) / 2);
356 }
357
358 - (void)clickOnLabel
359 {
360 CHECK_LOCK;
361 [self select];
362 [delegate clickedIcon: self];
363 }
364
365 - (void)mouseDown:(NSEvent *)theEvent
366 {
367 NSEvent *nextEvent;
368 BOOL startdnd = NO;
369 NSPoint p;
370
371 CHECK_LOCK;
372
373 p = [theEvent locationInWindow];
374 p = [self convertPoint: p fromView: nil];
375
376 if (ONICON(p, [self frame].size, [icon size]) == NO) {
377 return;
378 }
379
380 if ([theEvent clickCount] > 1) {
381 unsigned int modifier = [theEvent modifierFlags];
382
383 [delegate doubleClickedIcon: self newViewer: (modifier == NSControlKeyMask)];
384 return;
385 }
386
387 if (isSelect == NO) {
388 [self select];
389 [delegate unselectNameEditor];
390 }
391
392 while (1) {
393 nextEvent = [[self window] nextEventMatchingMask:
394 NSLeftMouseUpMask | NSLeftMouseDraggedMask];
395
396 if ([nextEvent type] == NSLeftMouseUp) {
397 [delegate clickedIcon: self];
398 break;
399
400 } else if ([nextEvent type] == NSLeftMouseDragged) {
401 if(dragdelay < 5) {
402 dragdelay++;
403 } else {
404 startdnd = YES;
405 break;
406 }
407 }
408 }
409
410 if (startdnd == YES) {
411 [self startExternalDragOnEvent: nextEvent];
412 }
413 }
414
415 - (NSMenu *)menuForEvent:(NSEvent *)theEvent
416 {
417 if (([theEvent type] != NSRightMouseDown) || (isSelect == NO)) {
418 return [super menuForEvent: theEvent];
419 } else if ([theEvent modifierFlags] == NSControlKeyMask) {
420 return [super menuForEvent: theEvent];
421 }
422 if ((name == nil) || ([[name pathExtension] length] == 0) ) {
423 return [super menuForEvent: theEvent];
424 }
425 if (contestualMenu == NO) {
426 return [super menuForEvent: theEvent];
427 }
428
429 if ((type == NSPlainFileType) || ([type isEqual: NSShellCommandFileType])) {
430 NSMenu *menu = [[NSMenu alloc] initWithTitle: NSLocalizedString(@"Open with", @"")];
431 NSString *ext = [name pathExtension];
432 NSDictionary *apps = [ws infoForExtension: ext];
433 NSEnumerator *app_enum = [[apps allKeys] objectEnumerator];
434 NSMenuItem *menuItem;
435 id key;
436
437 while ((key = [app_enum nextObject])) {
438 NSDictionary *dict = [apps objectForKey: key];
439 NSString *role = [dict objectForKey: @"NSRole"];
440 NSMutableDictionary *repObjDict = [NSMutableDictionary dictionary];
441
442 menuItem = [NSMenuItem new];
443
444 if (role) {
445 [menuItem setTitle: [NSString stringWithFormat: @"%@ - %@", key, role]];
446 } else {
447 [menuItem setTitle: [NSString stringWithFormat: @"%@", key]];
448 }
449
450 [menuItem setTarget: self];
451 [menuItem setAction: @selector(openWithApp:)];
452 [repObjDict setObject: key forKey: @"appName"];
453 [repObjDict setObject: fullpath forKey: @"fullPath"];
454 [menuItem setRepresentedObject: repObjDict];
455 [menu addItem: menuItem];
456 RELEASE (menuItem);
457 }
458
459 menuItem = [NSMenuItem new];
460 [menuItem setTitle: NSLocalizedString(@"Open with...", @"")];
461 [menuItem setTarget: self];
462 [menuItem setAction: @selector(openWith:)];
463 [menu addItem: menuItem];
464 RELEASE (menuItem);
465
466 AUTORELEASE (menu);
467 return menu;
468 }
469
470 return [super menuForEvent: theEvent];
471 }
472
473 - (BOOL)isSinglePath
474 {
475 return singlepath;
476 }
477
478 - (id)delegate
479 {
480 return delegate;
481 }
482
483 - (void)setDelegate:(id)aDelegate
484 {
485 delegate = aDelegate;
486 }
487
488 - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
489 {
490 return YES;
491 }
492
493 - (void)drawRect:(NSRect)rect
494 {
495 if(isSelect) {
496 [highlight compositeToPoint: ICONPOSITION(rect.size, [highlight size])
497 operation: NSCompositeSourceOver];
498 }
499
500 if (icon != nil) {
501 if (locked == NO) {
502 [icon compositeToPoint: ICONPOSITION(rect.size, [icon size])
503 operation: NSCompositeSourceOver];
504 } else {
505 [icon dissolveToPoint: ICONPOSITION(rect.size, [icon size]) fraction: 0.3];
506 }
507 }
508
509 if (isbranch == YES) {
510 [arrow compositeToPoint: NSMakePoint(rect.size.width - 15, 26)
511 operation: NSCompositeSourceOver];
512 }
513 }
514
515 @end
516
517
518 @implementation PathIcon (DraggingSource)
519
520 - (void)startExternalDragOnEvent:(NSEvent *)event
521 {
522 NSEvent *nextEvent;
523 NSPoint dragPoint;
524 NSPasteboard *pb;
525
526 nextEvent = [[self window] nextEventMatchingMask:
527 NSLeftMouseUpMask | NSLeftMouseDraggedMask];
528
529 if([nextEvent type] != NSLeftMouseDragged) {
530 [self unselect];
531 return;
532 }
533
534 dragPoint = [nextEvent locationInWindow];
535 dragPoint = [self convertPoint: dragPoint fromView: nil];
536
537 pb = [NSPasteboard pasteboardWithName: NSDragPboard];
538 [self declareAndSetShapeOnPasteboard: pb];
539
540 dragdelay = 0;
541
542 [self dragImage: icon
543 at: dragPoint
544 offset: NSZeroSize
545 event: event
546 pasteboard: pb
547 source: self
548 slideBack: [[GWLib workspaceApp] animateSlideBack]];
549 }
550
551 - (void)declareAndSetShapeOnPasteboard:(NSPasteboard *)pb
552 {
553 NSArray *dndtypes = [NSArray arrayWithObject: NSFilenamesPboardType];
554
555 [pb declareTypes: dndtypes owner: nil];
556
557 if ([pb setPropertyList: paths forType: NSFilenamesPboardType] == NO) {
558 return;
559 }
560 }
561
562 - (unsigned int)draggingSourceOperationMaskForLocal:(BOOL)flag
563 {
564 return NSDragOperationAll;
565 }
566
567 - (void)draggedImage:(NSImage *)anImage
568 endedAt:(NSPoint)aPoint
569 deposited:(BOOL)flag
570 {
571 dragdelay = 0;
572 [self setNeedsDisplay: YES];
573 [delegate restoreSelectionAfterDndOfIcon: self];
574 }
575
576 @end
577
578
579 @implementation PathIcon (DraggingDestination)
580
581 - (unsigned int)draggingEntered:(id <NSDraggingInfo>)sender
582 {
583 NSPasteboard *pb;
584 NSDragOperation sourceDragMask;
585 NSArray *sourcePaths;
586 NSString *fromPath;
587 NSString *buff;
588 NSString *iconPath;
589 int i, count;
590
591 CHECK_LOCK_RET (NSDragOperationNone);
592
593 if ((([type isEqualToString: NSDirectoryFileType] == NO)
594 && ([type isEqualToString: NSFilesystemFileType] == NO)) || isPakage) {
595 return NSDragOperationNone;
596 }
597
598 pb = [sender draggingPasteboard];
599 if ([[pb types] indexOfObject: NSFilenamesPboardType] != NSNotFound) {
600 sourcePaths = [pb propertyListForType: NSFilenamesPboardType];
601 count = [sourcePaths count];
602 fromPath = [[sourcePaths objectAtIndex: 0] stringByDeletingLastPathComponent];
603
604 if (count == 0) {
605 return NSDragOperationNone;
606 }
607
608 if ([fm isWritableFileAtPath: fullpath] == NO) {
609 return NSDragOperationNone;
610 }
611
612 if ([fullpath isEqualToString: fromPath]) {
613 return NSDragOperationNone;
614 }
615
616 for (i = 0; i < count; i++) {
617 if ([fullpath isEqualToString: [sourcePaths objectAtIndex: i]]) {
618 return NSDragOperationNone;
619 }
620 }
621
622 buff = [NSString stringWithString: fullpath];
623 while (1) {
624 for (i = 0; i < count; i++) {
625 if ([buff isEqualToString: [sourcePaths objectAtIndex: i]]) {
626 return NSDragOperationNone;
627 }
628 }
629 if ([buff isEqualToString: fixPath(@"/", 0)] == YES) {
630 break;
631 }
632 buff = [buff stringByDeletingLastPathComponent];
633 }
634
635 isDragTarget = YES;
636
637 iconPath = [fullpath stringByAppendingPathComponent: @".opendir.tiff"];
638
639 if ([fm isReadableFileAtPath: iconPath]) {
640 NSImage *img = [[NSImage alloc] initWithContentsOfFile: iconPath];
641
642 if (img) {
643 ASSIGN (icon, img);
644 RELEASE (img);
645 } else {
646 ASSIGN (icon, [NSImage imageNamed: @"FileIcon_Directory_Open.tiff"]);
647 }
648 } else {
649 ASSIGN (icon, [NSImage imageNamed: @"FileIcon_Directory_Open.tiff"]);
650 }
651
652 [self setNeedsDisplay: YES];
653
654 sourceDragMask = [sender draggingSourceOperationMask];
655
656 if (sourceDragMask == NSDragOperationCopy) {
657 return NSDragOperationCopy;
658 } else if (sourceDragMask == NSDragOperationLink) {
659 return NSDragOperationLink;
660 } else {
661 return NSDragOperationAll;
662 }
663 }
664
665 return NSDragOperationNone;
666 }
667
668 - (unsigned int)draggingUpdated:(id <NSDraggingInfo>)sender
669 {
670 NSDragOperation sourceDragMask;
671
672 CHECK_LOCK_RET (NSDragOperationNone);
673
674 if (isPakage) {
675 return NSDragOperationNone;
676 }
677 if (isDragTarget == NO) {
678 return NSDragOperationNone;
679 }
680
681 sourceDragMask = [sender draggingSourceOperationMask];
682
683 if (sourceDragMask == NSDragOperationCopy) {
684 return NSDragOperationCopy;
685 } else if (sourceDragMask == NSDragOperationLink) {
686 return NSDragOperationLink;
687 } else {
688 return NSDragOperationAll;
689 }
690
691 return NSDragOperationNone;
692 }
693
694 - (void)draggingExited:(id <NSDraggingInfo>)sender
695 {
696 if (isDragTarget == YES) {
697 isDragTarget = NO;
698 ASSIGN (icon, [GWLib iconForFile: fullpath ofType: type]);
699 [self setNeedsDisplay: YES];
700 }
701 }
702
703 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
704 {
705 CHECK_LOCK_RET (NO);
706 return isDragTarget;
707 }
708
709 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
710 {
711 CHECK_LOCK_RET (NO);
712 return YES;
713 }
714
715 - (void)concludeDragOperation:(id <NSDraggingInfo>)sender
716 {
717 NSPasteboard *pb;
718 NSDragOperation sourceDragMask;
719 NSArray *sourcePaths;
720 NSString *operation, *source;
721 NSMutableArray *files;
722 NSMutableDictionary *opDict;
723 NSString *trashPath;
724 int i;
725
726 CHECK_LOCK;
727
728 ASSIGN (icon, [GWLib iconForFile: fullpath ofType: type]);
729 [self setNeedsDisplay: YES];
730 isDragTarget = NO;
731
732 sourceDragMask = [sender draggingSourceOperationMask];
733 pb = [sender draggingPasteboard];
734 sourcePaths = [pb propertyListForType: NSFilenamesPboardType];
735 source = [[sourcePaths objectAtIndex: 0] stringByDeletingLastPathComponent];
736
737 trashPath = [[GWLib workspaceApp] trashPath];
738
739 if ([source isEqualToString: trashPath]) {
740 operation = GWorkspaceRecycleOutOperation;
741 } else {
742 if (sourceDragMask == NSDragOperationCopy) {
743 operation = NSWorkspaceCopyOperation;
744 } else if (sourceDragMask == NSDragOperationLink) {
745 operation = NSWorkspaceLinkOperation;
746 } else {
747 operation = NSWorkspaceMoveOperation;
748 }
749 }
750
751 files = [NSMutableArray arrayWithCapacity: 1];
752 for(i = 0; i < [sourcePaths count]; i++) {
753 [files addObject: [[sourcePaths objectAtIndex: i] lastPathComponent]];
754 }
755
756 opDict = [NSMutableDictionary dictionaryWithCapacity: 4];
757 [opDict setObject: operation forKey: @"operation"];
758 [opDict setObject: source forKey: @"source"];
759 [opDict setObject: fullpath forKey: @"destination"];
760 [opDict setObject: files forKey: @"files"];
761
762 [[GWLib workspaceApp] performFileOperationWithDictionary: opDict];
763 }
764
765 @end
766

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26