1 |
/* Browser2.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 |
#include <Foundation/Foundation.h> |
26 |
#include <AppKit/AppKit.h> |
27 |
#include "GWProtocol.h" |
28 |
#include "GWFunctions.h" |
29 |
#include "GWNotifications.h" |
30 |
#include <math.h> |
31 |
#include "Browser2.h" |
32 |
#include "BColumn.h" |
33 |
#include "BCell.h" |
34 |
#include "BIcon.h" |
35 |
#include "BNameEditor.h" |
36 |
#include "GNUstep.h" |
37 |
|
38 |
#define NSBR_VOFFSET 4 |
39 |
#define BEZEL_BORDER_SIZE NSMakeSize(2, 2) |
40 |
#define ICON_FRAME_HEIGHT 52 |
41 |
#define ICON_SIZE_WIDTH 48 |
42 |
#define ICON_VOFFSET 14 |
43 |
#define LINE_SCROLL 10 |
44 |
#define LABEL_HEIGHT 14 |
45 |
#define LABEL_MARGIN 8 |
46 |
#define EDIT_MARGIN 4 |
47 |
|
48 |
#define CHECKRECT(rct) \ |
49 |
if (rct.size.width < 0) rct.size.width = 0; \ |
50 |
if (rct.size.height < 0) rct.size.height = 0 |
51 |
|
52 |
#define CHECKSIZE(sz) \ |
53 |
if (sz.width < 0) sz.width = 0; \ |
54 |
if (sz.height < 0) sz.height = 0 |
55 |
|
56 |
#ifndef max |
57 |
#define max(a,b) ((a) >= (b) ? (a):(b)) |
58 |
#endif |
59 |
|
60 |
#ifndef min |
61 |
#define min(a,b) ((a) <= (b) ? (a):(b)) |
62 |
#endif |
63 |
|
64 |
double myrintf(double a) |
65 |
{ |
66 |
return (floor(a + 0.5)); |
67 |
} |
68 |
|
69 |
@implementation Browser2 |
70 |
|
71 |
- (void)dealloc |
72 |
{ |
73 |
RELEASE (columns); |
74 |
if (colRects != NULL) { |
75 |
NSZoneFree (NSDefaultMallocZone(), colRects); |
76 |
} |
77 |
RELEASE (cellPrototype); |
78 |
RELEASE (scroller); |
79 |
RELEASE (pathSeparator); |
80 |
RELEASE (basePath); |
81 |
RELEASE (nameEditor); |
82 |
RELEASE (editorFont); |
83 |
TEST_RELEASE (doubleClickSelection); |
84 |
TEST_RELEASE (charBuffer); |
85 |
[super dealloc]; |
86 |
} |
87 |
|
88 |
- (id)initWithBasePath:(NSString *)bpath |
89 |
visibleColumns:(int)vcols |
90 |
styleMask:(int)mask |
91 |
delegate:(id)anobject |
92 |
{ |
93 |
self = [super init]; |
94 |
|
95 |
if (self) { |
96 |
#ifdef GNUSTEP |
97 |
Class gwclass = [[NSBundle mainBundle] principalClass]; |
98 |
#else |
99 |
Class gwclass = [[NSBundle mainBundle] classNamed: @"GWorkspace"]; |
100 |
#endif |
101 |
NSRect rect = NSMakeRect(0, 0, 600, 200); |
102 |
NSSize bs = BEZEL_BORDER_SIZE; |
103 |
int i; |
104 |
|
105 |
createEmptySel = @selector(createEmptyColumn); |
106 |
createEmpty = [self methodForSelector: createEmptySel]; |
107 |
|
108 |
addAndLoadSel = @selector(addAndLoadColumnForPaths:); |
109 |
addAndLoad = [self methodForSelector: addAndLoadSel]; |
110 |
|
111 |
unloadFromSel = @selector(unloadFromColumn:); |
112 |
unloadFrom = [self methodForSelector: unloadFromSel]; |
113 |
|
114 |
lastColumnSel = @selector(setLastColumn:); |
115 |
lastColumn = [self methodForSelector: lastColumnSel]; |
116 |
|
117 |
setPathsSel = @selector(setCurrentPaths:); |
118 |
setPaths = [[BColumn class] instanceMethodForSelector: setPathsSel]; |
119 |
|
120 |
gworkspace = (id<GWProtocol>)[gwclass gworkspace]; |
121 |
|
122 |
[self setFrame: rect]; |
123 |
visibleColumns = vcols; |
124 |
ASSIGN (basePath, bpath); |
125 |
delegate = anobject; |
126 |
styleMask = mask; |
127 |
canUpdateViews = YES; |
128 |
|
129 |
colRects = NULL; |
130 |
columnWidth = (rect.size.width / (float)visibleColumns); |
131 |
scrollerWidth = [NSScroller scrollerWidth]; |
132 |
iconsPathWidth = 96 - scrollerWidth; |
133 |
if (styleMask & GWColumnIconMask) { |
134 |
columnOriginY = 0; |
135 |
} else { |
136 |
columnOriginY = scrollerWidth + (4 * bs.height); |
137 |
} |
138 |
|
139 |
ASSIGN (pathSeparator, fixPath(@"/", 0)); |
140 |
|
141 |
if (styleMask & GWIconCellsMask) { |
142 |
cellPrototype = [[BCell alloc] initIconCell]; |
143 |
} else { |
144 |
cellPrototype = [[BCell alloc] init]; |
145 |
} |
146 |
|
147 |
columns = [[NSMutableArray alloc] init]; |
148 |
getSel = @selector(objectAtIndex:); |
149 |
getImp = [columns methodForSelector: getSel]; |
150 |
indexSel = @selector(indexOfObject:); |
151 |
indexImp = (intIMP)[columns methodForSelector: indexSel]; |
152 |
|
153 |
scrollerRect.origin.x = bs.width; |
154 |
if (styleMask & GWColumnIconMask) { |
155 |
scrollerRect.origin.y = [self frame].size.height - iconsPathWidth - scrollerWidth; |
156 |
} else { |
157 |
scrollerRect.origin.y = bs.height; |
158 |
} |
159 |
scrollerRect.size.width = [self frame].size.width - (2 * bs.width); |
160 |
scrollerRect.size.height = scrollerWidth; |
161 |
scroller = [[NSScroller alloc] initWithFrame: scrollerRect]; |
162 |
[scroller setTarget: self]; |
163 |
[scroller setAction: @selector(scrollViaScroller:)]; |
164 |
[self addSubview: scroller]; |
165 |
|
166 |
rect = [self frame]; |
167 |
|
168 |
for (i = 0; i < visibleColumns; i++) { |
169 |
(*createEmpty)(self, createEmptySel); |
170 |
} |
171 |
|
172 |
nameEditor = [[BNameEditor alloc] init]; |
173 |
[nameEditor setDelegate: self]; |
174 |
[nameEditor setTarget: self]; |
175 |
[nameEditor setAction: @selector(editorAction:)]; |
176 |
ASSIGN (editorFont, [NSFont systemFontOfSize: 12]); |
177 |
[nameEditor setFont: editorFont]; |
178 |
[nameEditor setBezeled: NO]; |
179 |
[nameEditor setAlignment: NSCenterTextAlignment]; |
180 |
[nameEditor setBackgroundColor: [NSColor whiteColor]]; |
181 |
edCol = nil; |
182 |
isEditingIconName = NO; |
183 |
|
184 |
firstVisibleColumn = 0; |
185 |
lastVisibleColumn = visibleColumns - 1; |
186 |
currentshift = 0; |
187 |
lastColumnLoaded = -1; |
188 |
alphaNumericalLastColumn = -1; |
189 |
|
190 |
skipUpdateScroller = NO; |
191 |
lastKeyPressed = 0.; |
192 |
charBuffer = nil; |
193 |
doubleClickSelection = nil; |
194 |
simulatingDoubleClick = NO; |
195 |
isLoaded = NO; |
196 |
} |
197 |
|
198 |
return self; |
199 |
} |
200 |
|
201 |
- (void)setPathAndSelection:(NSArray *)selection |
202 |
{ |
203 |
NSString *path; |
204 |
NSArray *subStrings; |
205 |
NSString *aStr; |
206 |
NSString *progrPath; |
207 |
unsigned numberOfSubStrings; |
208 |
unsigned i; |
209 |
int column; |
210 |
BColumn *selCol; |
211 |
|
212 |
canUpdateViews = NO; |
213 |
|
214 |
[self loadColumnZero]; |
215 |
|
216 |
if (selection == nil || [[selection objectAtIndex: 0] isEqual: basePath]) { |
217 |
canUpdateViews = YES; |
218 |
[self tile]; |
219 |
[self setNeedsDisplay: YES]; |
220 |
return; |
221 |
} |
222 |
|
223 |
if ([selection count] > 1) { |
224 |
path = [[selection objectAtIndex: 0] stringByDeletingLastPathComponent]; |
225 |
} else { |
226 |
path = [selection objectAtIndex: 0]; |
227 |
} |
228 |
|
229 |
if ([basePath isEqualToString: pathSeparator] == NO) { |
230 |
NSRange range = [path rangeOfString: basePath]; |
231 |
|
232 |
if (range.length == 0) { |
233 |
ASSIGN (basePath, pathSeparator); |
234 |
[self loadColumnZero]; |
235 |
subStrings = [path componentsSeparatedByString: pathSeparator]; |
236 |
|
237 |
} else { |
238 |
NSString *rpath = [path substringFromIndex: [basePath cStringLength]]; |
239 |
subStrings = [rpath componentsSeparatedByString: pathSeparator]; |
240 |
} |
241 |
|
242 |
} else { |
243 |
subStrings = [path componentsSeparatedByString: pathSeparator]; |
244 |
} |
245 |
|
246 |
numberOfSubStrings = [subStrings count]; |
247 |
|
248 |
// Ignore a trailing void component. |
249 |
if (numberOfSubStrings > 0 |
250 |
&& [[subStrings objectAtIndex: 0] isEqualToString: @""]) { |
251 |
numberOfSubStrings--; |
252 |
|
253 |
if (numberOfSubStrings) { |
254 |
NSRange theRange; |
255 |
|
256 |
theRange.location = 1; |
257 |
theRange.length = numberOfSubStrings; |
258 |
subStrings = [subStrings subarrayWithRange: theRange]; |
259 |
} |
260 |
|
261 |
[self loadColumnZero]; |
262 |
} |
263 |
|
264 |
column = lastColumnLoaded; |
265 |
if (column < 0) { |
266 |
column = 0; |
267 |
} |
268 |
|
269 |
progrPath = [NSString stringWithString: basePath]; |
270 |
|
271 |
for (i = 0; i < numberOfSubStrings; i++) { |
272 |
BColumn *bc = (*getImp)(columns, getSel, column + i); |
273 |
|
274 |
aStr = [subStrings objectAtIndex: i]; |
275 |
|
276 |
if ([aStr isEqualToString: @""] == NO) { |
277 |
BOOL found = NO; |
278 |
|
279 |
progrPath = [progrPath stringByAppendingPathComponent: aStr]; |
280 |
|
281 |
found = [bc selectMatrixCellsWithNames: [NSArray arrayWithObject: aStr] |
282 |
sendAction: NO]; |
283 |
|
284 |
if (found == NO) { |
285 |
NSLog(@"Browser: unable to find cell '%@' in column %d\n", aStr, column + i); |
286 |
break; |
287 |
} |
288 |
|
289 |
(*addAndLoad)(self, addAndLoadSel, [NSArray arrayWithObject: progrPath]); |
290 |
} |
291 |
} |
292 |
|
293 |
if ([selection count] > 1) { |
294 |
BColumn *bc = (*getImp)(columns, getSel, lastColumnLoaded); |
295 |
|
296 |
NSMutableArray *names = [NSMutableArray arrayWithCapacity: 1]; |
297 |
int i = 0; |
298 |
|
299 |
for (i = 0; i < [selection count]; i++) { |
300 |
[names addObject: [[selection objectAtIndex: i] lastPathComponent]]; |
301 |
} |
302 |
|
303 |
[bc selectMatrixCellsWithNames: names sendAction: NO]; |
304 |
|
305 |
(*addAndLoad)(self, addAndLoadSel, selection); |
306 |
} |
307 |
|
308 |
canUpdateViews = YES; |
309 |
[self tile]; |
310 |
[self setNeedsDisplay: YES]; |
311 |
|
312 |
selCol = [self selectedColumn]; |
313 |
if (selCol) { |
314 |
NSMatrix *matrix = [selCol cmatrix]; |
315 |
|
316 |
if (matrix) { |
317 |
[[self window] makeFirstResponder: matrix]; |
318 |
} |
319 |
} |
320 |
} |
321 |
|
322 |
- (void)loadColumnZero |
323 |
{ |
324 |
(*lastColumn)(self, lastColumnSel, -1); |
325 |
(*addAndLoad)(self, addAndLoadSel, [NSArray arrayWithObject: basePath]); |
326 |
isLoaded = YES; |
327 |
[self tile]; |
328 |
} |
329 |
|
330 |
- (BColumn *)createEmptyColumn |
331 |
{ |
332 |
unsigned int style = (styleMask & GWColumnIconMask) |
333 |
| (styleMask & GWIconCellsMask) |
334 |
| (styleMask & GWViewsPaksgesMask); |
335 |
|
336 |
BColumn *bc = [[BColumn alloc] initInBrowser: self |
337 |
atIndex: [columns count] |
338 |
cellPrototype: cellPrototype |
339 |
styleMask: style]; |
340 |
[columns addObject: bc]; |
341 |
[self addSubview: bc]; |
342 |
if (styleMask & GWColumnIconMask) { |
343 |
[self addSubview: [bc iconView]]; |
344 |
} |
345 |
RELEASE(bc); |
346 |
|
347 |
return bc; |
348 |
} |
349 |
|
350 |
- (void)addAndLoadColumnForPaths:(NSArray *)cpaths |
351 |
{ |
352 |
BColumn *bc; |
353 |
int i; |
354 |
|
355 |
if (lastColumnLoaded + 1 >= [columns count]) { |
356 |
i = (*indexImp)(columns, indexSel, (*createEmpty)(self, createEmptySel)); |
357 |
} else { |
358 |
i = lastColumnLoaded + 1; |
359 |
} |
360 |
|
361 |
bc = (*getImp)(columns, getSel, i); |
362 |
(*setPaths)(bc, setPathsSel, cpaths); |
363 |
(*lastColumn)(self, lastColumnSel, i); |
364 |
|
365 |
isLoaded = YES; |
366 |
|
367 |
[self tile]; |
368 |
|
369 |
if ((i > 0) && ((i - 1) == lastVisibleColumn)) { |
370 |
[self scrollColumnsRightBy: 1]; |
371 |
} |
372 |
} |
373 |
|
374 |
- (void)unloadFromColumn:(int)column |
375 |
{ |
376 |
BColumn *bc = nil; |
377 |
int i, count; |
378 |
|
379 |
count = [columns count]; |
380 |
|
381 |
for (i = column; i < count; ++i) { |
382 |
bc = (*getImp)(columns, getSel, i); |
383 |
|
384 |
if ([bc isLoaded]) { |
385 |
[bc setCurrentPaths: nil]; |
386 |
} |
387 |
|
388 |
if (i >= visibleColumns) { |
389 |
[bc removeFromSuperview]; |
390 |
if (styleMask & GWColumnIconMask) { |
391 |
[[bc iconView] removeFromSuperview]; |
392 |
} |
393 |
|
394 |
[columns removeObject: bc]; |
395 |
|
396 |
count--; |
397 |
i--; |
398 |
} |
399 |
} |
400 |
|
401 |
if (column == 0) { |
402 |
isLoaded = NO; |
403 |
} |
404 |
|
405 |
// Scrolls if needed. |
406 |
if (column <= lastVisibleColumn) { |
407 |
[self scrollColumnsLeftBy: lastVisibleColumn - column + 1]; |
408 |
} |
409 |
|
410 |
[self updateScroller]; |
411 |
} |
412 |
|
413 |
- (void)reloadColumnWithPath:(NSString *)cpath |
414 |
{ |
415 |
BColumn *col = [self columnWithPath: cpath]; |
416 |
|
417 |
if (col) { |
418 |
[col setCurrentPaths: [NSArray arrayWithObject: cpath]]; |
419 |
} |
420 |
} |
421 |
|
422 |
- (void)reloadFromColumnWithPath:(NSString *)cpath |
423 |
{ |
424 |
BColumn *col = [self columnWithPath: cpath]; |
425 |
|
426 |
if (col) { |
427 |
int index = [col index]; |
428 |
int i = 0; |
429 |
|
430 |
for (i = index; i < [columns count]; i++) { |
431 |
BColumn *nextcol = (*getImp)(columns, getSel, i); |
432 |
NSArray *selection = [self selectionInColumnBeforeColumn: nextcol]; |
433 |
|
434 |
if (selection) { |
435 |
[nextcol setCurrentPaths: selection]; |
436 |
|
437 |
} else { |
438 |
int last = (i > 0) ? i - 1 : 0; |
439 |
int shift = 0; |
440 |
int leftscr = 0; |
441 |
|
442 |
if (last >= visibleColumns) { |
443 |
if (last < firstVisibleColumn) { |
444 |
shift = visibleColumns - 1; |
445 |
} else if (last > lastVisibleColumn) { |
446 |
leftscr = last - lastVisibleColumn; |
447 |
} else { |
448 |
shift = lastVisibleColumn - last; |
449 |
} |
450 |
} |
451 |
|
452 |
(*lastColumn)(self, lastColumnSel, last); |
453 |
|
454 |
if (shift) { |
455 |
currentshift = 0; |
456 |
[self setShift: shift]; |
457 |
} else if (leftscr) { |
458 |
[self scrollColumnsLeftBy: leftscr]; |
459 |
} |
460 |
|
461 |
break; |
462 |
} |
463 |
} |
464 |
|
465 |
[self tile]; |
466 |
|
467 |
col = [self lastNotEmptyColumn]; |
468 |
|
469 |
if (col) { |
470 |
NSArray *selection = [col selection]; |
471 |
int index = [col index]; |
472 |
|
473 |
if (index < firstVisibleColumn) { |
474 |
[self scrollColumnToVisible: index]; |
475 |
} |
476 |
|
477 |
if (selection) { |
478 |
BColumn *nextcol = (*getImp)(columns, getSel, ([col index] + 1)); |
479 |
|
480 |
if (styleMask & GWColumnIconMask) { |
481 |
[nextcol updateIcon]; |
482 |
[nextcol selectIcon]; |
483 |
} |
484 |
|
485 |
[delegate currentSelectedPaths: selection]; |
486 |
|
487 |
} else { |
488 |
NSString *currpath = [col currentPath]; |
489 |
|
490 |
if (currpath) { |
491 |
[delegate currentSelectedPaths: [NSArray arrayWithObject: currpath]]; |
492 |
|
493 |
if (styleMask & GWColumnIconMask) { |
494 |
[col selectIcon]; |
495 |
} |
496 |
} |
497 |
} |
498 |
} |
499 |
} |
500 |
} |
501 |
|
502 |
- (void)setLastColumn:(int)column |
503 |
{ |
504 |
lastColumnLoaded = column; |
505 |
(*unloadFrom)(self, unloadFromSel, column + 1); |
506 |
} |
507 |
|
508 |
- (void)tile |
509 |
{ |
510 |
NSSize bs = BEZEL_BORDER_SIZE; |
511 |
float frameWidth; |
512 |
NSRect r; |
513 |
int i; |
514 |
|
515 |
if (canUpdateViews == NO) { |
516 |
return; |
517 |
} |
518 |
|
519 |
r = [self frame]; |
520 |
|
521 |
columnSize.height = r.size.height; |
522 |
if (styleMask & GWColumnIconMask) { |
523 |
columnOriginY = 0; |
524 |
} else { |
525 |
columnOriginY = scrollerWidth + (4 * bs.height); |
526 |
} |
527 |
|
528 |
// Horizontal scroller |
529 |
scrollerRect.origin.x = bs.width; |
530 |
if (styleMask & GWColumnIconMask) { |
531 |
scrollerRect.origin.y = r.size.height - iconsPathWidth - scrollerWidth - 1; |
532 |
} else { |
533 |
scrollerRect.origin.y = bs.height; |
534 |
} |
535 |
scrollerRect.size.width = r.size.width - (2 * bs.width); |
536 |
scrollerRect.size.height = scrollerWidth; |
537 |
|
538 |
if (styleMask & GWColumnIconMask) { |
539 |
columnSize.height -= iconsPathWidth + scrollerWidth + (3 * bs.height) + NSBR_VOFFSET; |
540 |
} else { |
541 |
columnSize.height -= scrollerWidth + (3 * bs.height) + NSBR_VOFFSET; |
542 |
} |
543 |
|
544 |
if (!NSEqualRects(scrollerRect, [scroller frame])) { |
545 |
CHECKRECT (scrollerRect); |
546 |
[scroller setFrame: scrollerRect]; |
547 |
} |
548 |
|
549 |
// Columns |
550 |
frameWidth = r.size.width - (4.0 + (float)visibleColumns); |
551 |
columnSize.width = (int)(frameWidth / (float)visibleColumns); |
552 |
CHECKSIZE (columnSize); |
553 |
|
554 |
[self makeColumnsRects]; |
555 |
|
556 |
for (i = 0; i < [columns count]; i++) { |
557 |
BColumn *bc = (*getImp)(columns, getSel, i); |
558 |
|
559 |
if (styleMask & GWColumnIconMask) { |
560 |
[[bc iconView] setFrame: NSMakeRect(colRects[i].origin.x, |
561 |
r.size.height - iconsPathWidth + (2 * bs.width), |
562 |
colRects[i].size.width, iconsPathWidth - (2 * bs.width))]; |
563 |
} |
564 |
|
565 |
[bc setFrame: colRects[i]]; |
566 |
} |
567 |
|
568 |
if (styleMask & GWColumnIconMask) { |
569 |
[self updateNameEditor]; |
570 |
} |
571 |
} |
572 |
|
573 |
- (void)makeColumnsRects |
574 |
{ |
575 |
int count = [columns count]; |
576 |
int i = 0; |
577 |
|
578 |
if (colRects != NULL) { |
579 |
NSZoneFree (NSDefaultMallocZone(), colRects); |
580 |
} |
581 |
colRects = NSZoneMalloc (NSDefaultMallocZone(), sizeof(NSRect) * count); |
582 |
|
583 |
for (i = 0; i < count; i++) { |
584 |
int n = i - firstVisibleColumn; |
585 |
|
586 |
colRects[i] = NSZeroRect; |
587 |
|
588 |
colRects[i].size = columnSize; |
589 |
|
590 |
if (i < firstVisibleColumn) { |
591 |
colRects[i].origin.x = (n * columnSize.width); |
592 |
} else { |
593 |
if (i == firstVisibleColumn) { |
594 |
colRects[i].origin.x = (n * columnSize.width) + 2; |
595 |
} else if (i <= lastVisibleColumn) { |
596 |
colRects[i].origin.x = (n * columnSize.width) + (n + 2); |
597 |
} else { |
598 |
colRects[i].origin.x = (n * columnSize.width) + (n + 8); |
599 |
} |
600 |
} |
601 |
|
602 |
if (i == lastVisibleColumn) { |
603 |
colRects[i].size.width = [self bounds].size.width - (colRects[i].origin.x + 2); |
604 |
} |
605 |
|
606 |
colRects[i].origin.y = columnOriginY; |
607 |
|
608 |
CHECKRECT (colRects[i]); |
609 |
} |
610 |
} |
611 |
|
612 |
- (void)scrollViaScroller:(NSScroller *)sender |
613 |
{ |
614 |
NSScrollerPart hit; |
615 |
|
616 |
if ([sender class] != [NSScroller class]) { |
617 |
return; |
618 |
} |
619 |
|
620 |
hit = [sender hitPart]; |
621 |
|
622 |
switch (hit) { |
623 |
// Scroll to the left |
624 |
case NSScrollerDecrementLine: |
625 |
case NSScrollerDecrementPage: |
626 |
[self scrollColumnsLeftBy: 1]; |
627 |
if (currentshift > 0) { |
628 |
(*lastColumn)(self, lastColumnSel, (lastColumnLoaded - currentshift)); |
629 |
[self setShift: currentshift - 1]; |
630 |
} |
631 |
break; |
632 |
|
633 |
// Scroll to the right |
634 |
case NSScrollerIncrementLine: |
635 |
case NSScrollerIncrementPage: |
636 |
[self scrollColumnsRightBy: 1]; |
637 |
break; |
638 |
|
639 |
// The knob or knob slot |
640 |
case NSScrollerKnob: |
641 |
case NSScrollerKnobSlot: |
642 |
{ |
643 |
float f = [sender floatValue]; |
644 |
float n = lastColumnLoaded + 1 - visibleColumns; |
645 |
|
646 |
skipUpdateScroller = YES; |
647 |
[self scrollColumnToVisible: myrintf(f * n) + visibleColumns - 1]; |
648 |
skipUpdateScroller = NO; |
649 |
|
650 |
(*lastColumn)(self, lastColumnSel, (lastColumnLoaded - currentshift)); |
651 |
currentshift = 0; |
652 |
} |
653 |
break; |
654 |
|
655 |
// NSScrollerNoPart ??? |
656 |
default: |
657 |
break; |
658 |
} |
659 |
} |
660 |
|
661 |
- (void)updateScroller |
662 |
{ |
663 |
if ((lastColumnLoaded == 0) || (lastColumnLoaded <= (visibleColumns - 1))) { |
664 |
[scroller setEnabled: NO]; |
665 |
|
666 |
} else { |
667 |
if (!skipUpdateScroller) { |
668 |
float prop = (float)visibleColumns / (float)(lastColumnLoaded + 1); |
669 |
float i = lastColumnLoaded - visibleColumns + 1; |
670 |
float f = 1 + ((lastVisibleColumn - lastColumnLoaded) / i); |
671 |
[scroller setFloatValue: f knobProportion: prop]; |
672 |
} |
673 |
|
674 |
[scroller setEnabled: YES]; |
675 |
} |
676 |
|
677 |
[scroller setNeedsDisplay: YES]; |
678 |
} |
679 |
|
680 |
- (void)scrollColumnsLeftBy:(int)shiftAmount |
681 |
{ |
682 |
// Cannot shift past the zero column |
683 |
if ((firstVisibleColumn - shiftAmount) < 0) { |
684 |
shiftAmount = firstVisibleColumn; |
685 |
} |
686 |
|
687 |
// No amount to shift then nothing to do |
688 |
if (shiftAmount <= 0) { |
689 |
return; |
690 |
} |
691 |
|
692 |
// Shift |
693 |
firstVisibleColumn = firstVisibleColumn - shiftAmount; |
694 |
lastVisibleColumn = lastVisibleColumn - shiftAmount; |
695 |
|
696 |
// Update the scroller |
697 |
[self updateScroller]; |
698 |
|
699 |
// Update the scrollviews |
700 |
[self tile]; |
701 |
} |
702 |
|
703 |
- (void)scrollColumnsRightBy:(int)shiftAmount |
704 |
{ |
705 |
// Cannot shift past the last loaded column |
706 |
if ((shiftAmount + lastVisibleColumn) > lastColumnLoaded) { |
707 |
shiftAmount = lastColumnLoaded - lastVisibleColumn; |
708 |
} |
709 |
|
710 |
// No amount to shift then nothing to do |
711 |
if (shiftAmount <= 0) { |
712 |
return; |
713 |
} |
714 |
|
715 |
// Shift |
716 |
firstVisibleColumn = firstVisibleColumn + shiftAmount; |
717 |
lastVisibleColumn = lastVisibleColumn + shiftAmount; |
718 |
|
719 |
// Update the scroller |
720 |
[self updateScroller]; |
721 |
|
722 |
// Update the scrollviews |
723 |
[self tile]; |
724 |
} |
725 |
|
726 |
- (void)scrollColumnToVisible:(int)column |
727 |
{ |
728 |
int i; |
729 |
|
730 |
// If its the last visible column then we are there already |
731 |
if (lastVisibleColumn == column) { |
732 |
return; |
733 |
} |
734 |
|
735 |
// If there are not enough columns to scroll with |
736 |
// then the column must be visible |
737 |
if (lastColumnLoaded + 1 <= visibleColumns) { |
738 |
return; |
739 |
} |
740 |
|
741 |
i = lastVisibleColumn - column; |
742 |
if (i > 0) { |
743 |
[self scrollColumnsLeftBy: i]; |
744 |
} else { |
745 |
[self scrollColumnsRightBy: (-i)]; |
746 |
} |
747 |
} |
748 |
|
749 |
- (void)moveLeft:(id)sender |
750 |
{ |
751 |
BColumn *selCol; |
752 |
int index; |
753 |
|
754 |
if (!(selCol = [self selectedColumn])) { |
755 |
return; |
756 |
} |
757 |
|
758 |
index = [selCol index]; |
759 |
|
760 |
if (index > 0) { |
761 |
(*lastColumn)(self, lastColumnSel, index); |
762 |
|
763 |
[selCol setLeaf: YES]; |
764 |
if (styleMask & GWColumnIconMask) { |
765 |
[selCol selectIcon]; |
766 |
} |
767 |
|
768 |
selCol = (*getImp)(columns, getSel, index - 1); |
769 |
[delegate currentSelectedPaths: [selCol selection]]; |
770 |
[[self window] makeFirstResponder: [selCol cmatrix]]; |
771 |
} |
772 |
} |
773 |
|
774 |
- (void)moveRight:(id)sender |
775 |
{ |
776 |
BColumn *selCol = [self selectedColumn]; |
777 |
|
778 |
if (selCol == nil) { |
779 |
selCol = (*getImp)(columns, getSel, 0); |
780 |
|
781 |
if ([selCol selectFirstCell]) { |
782 |
[[self window] makeFirstResponder: [selCol cmatrix]]; |
783 |
} |
784 |
} else { |
785 |
NSMatrix *matrix = [selCol cmatrix]; |
786 |
|
787 |
if (matrix) { |
788 |
int index = [selCol index]; |
789 |
|
790 |
[matrix sendAction]; |
791 |
|
792 |
if (index < ([columns count] - 1)) { |
793 |
selCol = (*getImp)(columns, getSel, index + 1); |
794 |
matrix = [selCol cmatrix]; |
795 |
if (matrix) { |
796 |
if ([selCol selectFirstCell]) { |
797 |
[matrix sendAction]; |
798 |
[[self window] makeFirstResponder: matrix]; |
799 |
} |
800 |
} |
801 |
} |
802 |
} |
803 |
} |
804 |
} |
805 |
|
806 |
- (void)setShift:(int)s |
807 |
{ |
808 |
int i; |
809 |
|
810 |
for (i = 0; i <= s; i++) { |
811 |
(*createEmpty)(self, createEmptySel); |
812 |
} |
813 |
|
814 |
currentshift = s; |
815 |
(*lastColumn)(self, lastColumnSel, (lastColumnLoaded + s)); |
816 |
[self scrollColumnsRightBy: s]; |
817 |
[self tile]; |
818 |
} |
819 |
|
820 |
- (NSString *)pathToLastColumn |
821 |
{ |
822 |
int i; |
823 |
|
824 |
for (i = 0; i < [columns count]; i++) { |
825 |
BColumn *col = (*getImp)(columns, getSel, i); |
826 |
|
827 |
if ([col isLeaf]) { |
828 |
NSString *cpath = [col currentPath]; |
829 |
BOOL is_dir = NO; |
830 |
|
831 |
is_dir = [gworkspace existsAndIsDirectoryFileAtPath: cpath]; |
832 |
|
833 |
if (is_dir) { |
834 |
if (([gworkspace isPakageAtPath: cpath] == NO) |
835 |
|| (styleMask & GWViewsPaksgesMask)) { |
836 |
return cpath; |
837 |
} else if (i > 0) { |
838 |
return [(*getImp)(columns, getSel, i - 1) currentPath]; |
839 |
} |
840 |
} else if (i > 0) { |
841 |
return [(*getImp)(columns, getSel, i - 1) currentPath]; |
842 |
} |
843 |
} |
844 |
} |
845 |
|
846 |
return nil; |
847 |
} |
848 |
|
849 |
- (BOOL)isShowingPath:(NSString *)path |
850 |
{ |
851 |
return ([self columnWithPath: path] ? YES : NO); |
852 |
} |
853 |
|
854 |
- (BColumn *)selectedColumn |
855 |
{ |
856 |
int i; |
857 |
|
858 |
for (i = lastColumnLoaded; i >= 0; i--) { |
859 |
BColumn *col = (*getImp)(columns, getSel, i); |
860 |
|
861 |
if ([col isSelected]) { |
862 |
return col; |
863 |
} |
864 |
} |
865 |
|
866 |
return nil; |
867 |
} |
868 |
|
869 |
- (NSArray *)selectionInColumn:(int)column |
870 |
{ |
871 |
return [(*getImp)(columns, getSel, column) selection]; |
872 |
} |
873 |
|
874 |
- (NSArray *)selectionInColumnBeforeColumn:(BColumn *)col |
875 |
{ |
876 |
int index = [col index]; |
877 |
|
878 |
if (index == 0) { |
879 |
return [NSArray arrayWithObject: basePath]; |
880 |
} |
881 |
|
882 |
return [(*getImp)(columns, getSel, (index - 1)) selection]; |
883 |
} |
884 |
|
885 |
- (void)selectCellsWithNames:(NSArray *)names |
886 |
inColumnWithPath:(NSString *)cpath |
887 |
sendAction:(BOOL)act |
888 |
{ |
889 |
BColumn *col = [self columnWithPath: cpath]; |
890 |
|
891 |
if (col) { |
892 |
[col selectMatrixCellsWithNames: names sendAction: act]; |
893 |
} |
894 |
} |
895 |
|
896 |
- (void)extendSelectionWithDimmedFiles:(NSArray *)dimmFiles |
897 |
fromColumnWithPath:(NSString *)cpath |
898 |
{ |
899 |
BColumn *col = [self columnWithPath: cpath]; |
900 |
|
901 |
if (col) { |
902 |
NSArray *selection = [col selection]; |
903 |
int i = 0; |
904 |
|
905 |
if (selection) { |
906 |
BOOL contained = NO; |
907 |
|
908 |
for (i = 0; i < [selection count]; i++) { |
909 |
NSString *selFile = [[selection objectAtIndex: i] lastPathComponent]; |
910 |
|
911 |
if ([dimmFiles containsObject: selFile]) { |
912 |
contained = YES; |
913 |
break; |
914 |
} |
915 |
} |
916 |
|
917 |
if (contained) { |
918 |
for (i = [col index] + 1; i < [columns count]; i++) { |
919 |
[(*getImp)(columns, getSel, i) lock]; |
920 |
} |
921 |
} |
922 |
} |
923 |
} |
924 |
} |
925 |
|
926 |
- (void)selectAllInLastColumn |
927 |
{ |
928 |
BColumn *col = [self lastNotEmptyColumn]; |
929 |
|
930 |
if (col) { |
931 |
[col selectAll]; |
932 |
} |
933 |
} |
934 |
|
935 |
- (void)selectForEditingInLastColumn |
936 |
{ |
937 |
// [nameEditor selectText: nil]; |
938 |
} |
939 |
|
940 |
- (void)unselectNameEditor |
941 |
{ |
942 |
[nameEditor setBackgroundColor: [NSColor windowBackgroundColor]]; |
943 |
[self setNeedsDisplayInRect: [nameEditor frame]]; |
944 |
} |
945 |
|
946 |
- (void)restoreSelectionAfterDndOfIcon:(BIcon *)dndicon |
947 |
{ |
948 |
BColumn *col = [self lastLoadedColumn]; |
949 |
|
950 |
if (col && (styleMask & GWColumnIconMask)) { |
951 |
[[col myIcon] select]; |
952 |
} |
953 |
|
954 |
[nameEditor setBackgroundColor: [NSColor whiteColor]]; |
955 |
[self updateNameEditor]; |
956 |
} |
957 |
|
958 |
- (void)renewLastIcon |
959 |
{ |
960 |
BColumn *col = [self lastLoadedColumn]; |
961 |
|
962 |
if (col && (styleMask & GWColumnIconMask)) { |
963 |
BIcon *icon = [col myIcon]; |
964 |
|
965 |
if (icon) { |
966 |
[icon renewIcon]; |
967 |
} |
968 |
} |
969 |
} |
970 |
|
971 |
- (void)addCellsWithNames:(NSArray *)names |
972 |
inColumnWithPath:(NSString *)cpath |
973 |
{ |
974 |
BColumn *col = [self columnWithPath: cpath]; |
975 |
|
976 |
if (col) { |
977 |
[col addMatrixCellsWithNames: names]; |
978 |
} |
979 |
} |
980 |
|
981 |
- (void)addDimmedCellsWithNames:(NSArray *)names |
982 |
inColumnWithPath:(NSString *)cpath |
983 |
{ |
984 |
BColumn *col = [self columnWithPath: cpath]; |
985 |
|
986 |
if (col) { |
987 |
[col addDimmedMatrixCellsWithNames: names]; |
988 |
} |
989 |
} |
990 |
|
991 |
- (void)removeCellsWithNames:(NSArray *)names |
992 |
inColumnWithPath:(NSString *)cpath |
993 |
{ |
994 |
BColumn *col = [self columnWithPath: cpath]; |
995 |
|
996 |
if (col) { |
997 |
[col removeMatrixCellsWithNames: names]; |
998 |
} |
999 |
} |
1000 |
|
1001 |
|
1002 |
- (void)lockCellsWithNames:(NSArray *)names |
1003 |
inColumnWithPath:(NSString *)cpath |
1004 |
{ |
1005 |
BColumn *col = [self columnWithPath: cpath]; |
1006 |
|
1007 |
if (col) { |
1008 |
[col lockCellsWithNames: names]; |
1009 |
} |
1010 |
} |
1011 |
|
1012 |
- (void)unLockCellsWithNames:(NSArray *)names |
1013 |
inColumnWithPath:(NSString *)cpath |
1014 |
mustExtend:(BOOL)extend |
1015 |
{ |
1016 |
BColumn *col = [self columnWithPath: cpath]; |
1017 |
int i = 0; |
1018 |
|
1019 |
if (col) { |
1020 |
[col unLockCellsWithNames: names]; |
1021 |
|
1022 |
if (extend) { |
1023 |
for (i = [col index] + 1; i < [columns count]; i++) { |
1024 |
[(*getImp)(columns, getSel, i) unLock]; |
1025 |
} |
1026 |
} |
1027 |
} |
1028 |
} |
1029 |
|
1030 |
- (int)firstVisibleColumn |
1031 |
{ |
1032 |
return firstVisibleColumn; |
1033 |
} |
1034 |
|
1035 |
- (BColumn *)lastLoadedColumn |
1036 |
{ |
1037 |
int i; |
1038 |
|
1039 |
for (i = [columns count] - 1; i >= 0; i--) { |
1040 |
BColumn *col = (*getImp)(columns, getSel, i); |
1041 |
|
1042 |
if ([col isLoaded] && [col isLeaf]) { |
1043 |
return col; |
1044 |
} |
1045 |
} |
1046 |
|
1047 |
return nil; |
1048 |
} |
1049 |
|
1050 |
- (BColumn *)lastNotEmptyColumn |
1051 |
{ |
1052 |
int i; |
1053 |
|
1054 |
for (i = 0; i < [columns count]; i++) { |
1055 |
BColumn *col = (*getImp)(columns, getSel, i); |
1056 |
|
1057 |
if ([col isLeaf]) { |
1058 |
id matrix = [col cmatrix]; |
1059 |
|
1060 |
if (matrix && [[matrix cells] count]) { |
1061 |
return col; |
1062 |
} else if (i > 0) { |
1063 |
return (*getImp)(columns, getSel, i - 1); |
1064 |
} |
1065 |
} |
1066 |
} |
1067 |
|
1068 |
return nil; |
1069 |
} |
1070 |
|
1071 |
- (BColumn *)columnWithPath:(NSString *)cpath |
1072 |
{ |
1073 |
int i; |
1074 |
|
1075 |
for (i = 0; i < [columns count]; i++) { |
1076 |
BColumn *col = (*getImp)(columns, getSel, i); |
1077 |
|
1078 |
if ([[col currentPath] isEqual: cpath]) { |
1079 |
return col; |
1080 |
} |
1081 |
} |
1082 |
|
1083 |
return nil; |
1084 |
} |
1085 |
|
1086 |
- (BColumn *)columnBeforeColumn:(BColumn *)col |
1087 |
{ |
1088 |
int index = [col index]; |
1089 |
|
1090 |
if (index > 0) { |
1091 |
return (*getImp)(columns, getSel, index - 1); |
1092 |
} |
1093 |
|
1094 |
return nil; |
1095 |
} |
1096 |
|
1097 |
- (BColumn *)columnAfterColumn:(BColumn *)col |
1098 |
{ |
1099 |
int index = [col index]; |
1100 |
|
1101 |
if (index < ([columns count] - 1)) { |
1102 |
return (*getImp)(columns, getSel, index + 1); |
1103 |
} |
1104 |
|
1105 |
return nil; |
1106 |
} |
1107 |
|
1108 |
- (NSArray *)columnsDifferentFromColumn:(BColumn *)col |
1109 |
{ |
1110 |
NSMutableArray *arr = [NSMutableArray arrayWithCapacity: 1]; |
1111 |
int i; |
1112 |
|
1113 |
for (i = 0; i < [columns count]; i++) { |
1114 |
BColumn *bc = (*getImp)(columns, getSel, i); |
1115 |
|
1116 |
if (bc != col) { |
1117 |
[arr addObject: bc]; |
1118 |
} |
1119 |
} |
1120 |
|
1121 |
return arr; |
1122 |
} |
1123 |
|
1124 |
- (NSPoint)positionOfLastIcon |
1125 |
{ |
1126 |
BColumn *col = [self lastLoadedColumn]; |
1127 |
|
1128 |
if (col && (styleMask & GWColumnIconMask)) { |
1129 |
NSRect r = [[col iconView] frame]; |
1130 |
NSSize s = [[col myIcon] iconShift]; |
1131 |
|
1132 |
return NSMakePoint(r.origin.x + s.width, |
1133 |
r.origin.y + s.height + ICON_VOFFSET); |
1134 |
} |
1135 |
|
1136 |
return NSZeroPoint; |
1137 |
} |
1138 |
|
1139 |
- (NSPoint)positionForSlidedImage |
1140 |
{ |
1141 |
if ((lastVisibleColumn < [columns count]) && (styleMask & GWColumnIconMask)) { |
1142 |
BColumn *col = (*getImp)(columns, getSel, lastVisibleColumn); |
1143 |
NSRect r = [[col iconView] frame]; |
1144 |
NSPoint p = [self positionOfLastIcon]; |
1145 |
|
1146 |
return NSMakePoint(r.origin.x + ((r.size.width - ICON_SIZE_WIDTH) / 2), p.y); |
1147 |
} |
1148 |
|
1149 |
return NSZeroPoint; |
1150 |
} |
1151 |
|
1152 |
- (BOOL)viewsapps |
1153 |
{ |
1154 |
return (styleMask & GWViewsPaksgesMask); |
1155 |
} |
1156 |
|
1157 |
- (void)mouseDown:(NSEvent*)theEvent |
1158 |
{ |
1159 |
if (simulatingDoubleClick) { |
1160 |
NSPoint p = [[self window] mouseLocationOutsideOfEventStream]; |
1161 |
|
1162 |
if ((max(p.x, mousePointX) - min(p.x, mousePointX)) <= 3 |
1163 |
&& (max(p.y, mousePointY) - min(p.y, mousePointY)) <= 3) { |
1164 |
[delegate openSelectedPaths: doubleClickSelection newViewer: NO]; |
1165 |
} |
1166 |
} |
1167 |
|
1168 |
[super mouseDown: theEvent]; |
1169 |
} |
1170 |
|
1171 |
- (void)doubleClikTimeOut:(id)sender |
1172 |
{ |
1173 |
simulatingDoubleClick = NO; |
1174 |
} |
1175 |
|
1176 |
- (void)clickInMatrixOfColumn:(BColumn *)col |
1177 |
{ |
1178 |
int index = [col index]; |
1179 |
int pos = index - firstVisibleColumn + 1; |
1180 |
BOOL mustshift = (firstVisibleColumn > 0) ? YES : NO; |
1181 |
NSArray *selection = [col selection]; |
1182 |
|
1183 |
if ((selection == nil) || ([selection count] == 0)) { |
1184 |
[self clickOnIcon: [col myIcon] ofColumn: col]; |
1185 |
return; |
1186 |
} |
1187 |
|
1188 |
if ((pos == visibleColumns) && (index == ([columns count] -1))) { |
1189 |
NSTimer *timer; |
1190 |
NSPoint p; |
1191 |
|
1192 |
p = [[self window] mouseLocationOutsideOfEventStream]; |
1193 |
mousePointX = p.x; |
1194 |
mousePointY = p.y; |
1195 |
ASSIGN (doubleClickSelection, selection); |
1196 |
simulatingDoubleClick = YES; |
1197 |
|
1198 |
timer = [NSTimer scheduledTimerWithTimeInterval: 0.3 |
1199 |
target: self selector: @selector(doubleClikTimeOut:) |
1200 |
userInfo: nil repeats: NO]; |
1201 |
} |
1202 |
|
1203 |
[delegate currentSelectedPaths: selection]; |
1204 |
|
1205 |
currentshift = 0; |
1206 |
canUpdateViews = NO; |
1207 |
|
1208 |
(*lastColumn)(self, lastColumnSel, index); |
1209 |
(*addAndLoad)(self, addAndLoadSel, selection); |
1210 |
|
1211 |
if ((mustshift == YES) && (pos < (visibleColumns - 1))) { |
1212 |
[self setShift: visibleColumns - pos - 1]; |
1213 |
} |
1214 |
|
1215 |
canUpdateViews = YES; |
1216 |
[self tile]; |
1217 |
|
1218 |
#ifndef GNUSTEP |
1219 |
[[self window] makeFirstResponder: self]; |
1220 |
#endif |
1221 |
} |
1222 |
|
1223 |
- (void)doubleClickInMatrixOfColumn:(BColumn *)col |
1224 |
{ |
1225 |
NSArray *selection = [col selection]; |
1226 |
|
1227 |
if (selection) { |
1228 |
[delegate openSelectedPaths: selection newViewer: NO]; |
1229 |
} |
1230 |
} |
1231 |
|
1232 |
- (void)clickOnIcon:(BIcon *)icon ofColumn:(BColumn *)col |
1233 |
{ |
1234 |
BColumn *column; |
1235 |
|
1236 |
if ([icon isSinglePath] == NO) { |
1237 |
return; |
1238 |
} |
1239 |
|
1240 |
column = [self columnBeforeColumn: col]; |
1241 |
|
1242 |
if (column) { |
1243 |
NSString *name = [icon name]; |
1244 |
|
1245 |
if ([column selectMatrixCellsWithNames: [NSArray arrayWithObject: name] |
1246 |
sendAction: YES] == NO) { |
1247 |
(*lastColumn)(self, lastColumnSel, [column index]); |
1248 |
[delegate currentSelectedPaths: [NSArray arrayWithObject: [column currentPath]]]; |
1249 |
} |
1250 |
|
1251 |
} else { |
1252 |
(*lastColumn)(self, lastColumnSel, 0); |
1253 |
[delegate currentSelectedPaths: [NSArray arrayWithObject: basePath]]; |
1254 |
[self tile]; |
1255 |
} |
1256 |
|
1257 |
[nameEditor setBackgroundColor: [NSColor whiteColor]]; |
1258 |
|
1259 |
[[self window] makeFirstResponder: self]; |
1260 |
} |
1261 |
|
1262 |
- (void)doubleClickOnIcon:(BIcon *)icon |
1263 |
ofColumn:(BColumn *)col |
1264 |
newViewer:(BOOL)isnew |
1265 |
{ |
1266 |
[delegate openSelectedPaths: [icon paths] newViewer: isnew]; |
1267 |
} |
1268 |
|
1269 |
- (void)updateNameEditor |
1270 |
{ |
1271 |
BColumn *col = [self lastLoadedColumn]; |
1272 |
|
1273 |
if ([[self subviews] containsObject: nameEditor]) { |
1274 |
NSRect edr = [nameEditor frame]; |
1275 |
|
1276 |
[nameEditor abortEditing]; |
1277 |
[nameEditor setName: nil paths: nil index: -1]; |
1278 |
[nameEditor removeFromSuperview]; |
1279 |
[self setNeedsDisplayInRect: edr]; |
1280 |
edCol = nil; |
1281 |
} |
1282 |
|
1283 |
isEditingIconName = NO; |
1284 |
|
1285 |
if (col && ([col index] <= lastVisibleColumn)) { |
1286 |
BIcon *icon = [col myIcon]; |
1287 |
NSArray *paths = [icon paths]; |
1288 |
NSString *name = [icon isRootIcon] ? [icon hostname] : [icon name]; |
1289 |
BOOL locked = [icon isLocked]; |
1290 |
BOOL canedit = ((!locked) && (paths && [paths count] == 1) && (![icon isRootIcon])); |
1291 |
NSRect r = [[col iconView] frame]; |
1292 |
float bw = [self bounds].size.width - EDIT_MARGIN; |
1293 |
float centerx = r.origin.x + (r.size.width / 2); |
1294 |
float labwidth = [editorFont widthOfString: name] + LABEL_MARGIN; |
1295 |
|
1296 |
if ((centerx + (labwidth / 2)) >= bw) { |
1297 |
centerx -= (centerx + (labwidth / 2) - bw); |
1298 |
} else if ((centerx - (labwidth / 2)) < LABEL_MARGIN) { |
1299 |
centerx += fabs(centerx - (labwidth / 2)) + LABEL_MARGIN; |
1300 |
} |
1301 |
|
1302 |
[[icon label] setFrame: NSMakeRect(centerx, r.origin.y, 1, 1)]; |
1303 |
|
1304 |
r = NSMakeRect(centerx - (labwidth / 2), r.origin.y, labwidth, LABEL_HEIGHT); |
1305 |
[nameEditor setFrame: r]; |
1306 |
[nameEditor setName: name paths: paths index: [col index]]; |
1307 |
[nameEditor setBackgroundColor: [NSColor whiteColor]]; |
1308 |
[nameEditor setTextColor: (locked ? [NSColor disabledControlTextColor] |
1309 |
: [NSColor controlTextColor])]; |
1310 |
[nameEditor setEditable: canedit]; |
1311 |
[nameEditor setSelectable: canedit]; |
1312 |
[self addSubview: nameEditor]; |
1313 |
} |
1314 |
} |
1315 |
|
1316 |
- (BOOL)isEditingIconName |
1317 |
{ |
1318 |
return isEditingIconName; |
1319 |
} |
1320 |
|
1321 |
- (void)controlTextDidChange:(NSNotification *)aNotification |
1322 |
{ |
1323 |
static NSRect edr = {{0, 0}, {0, 0}}; |
1324 |
static float crx = 0; |
1325 |
static float ory = 0; |
1326 |
static float bw = 0; |
1327 |
NSString *s; |
1328 |
float labwidth; |
1329 |
float labcenter; |
1330 |
|
1331 |
if (edCol == nil) { |
1332 |
edCol = [self lastLoadedColumn]; |
1333 |
edr = [[edCol iconView] frame]; |
1334 |
crx = edr.origin.x + (edr.size.width / 2); |
1335 |
ory = edr.origin.y; |
1336 |
bw = [self bounds].size.width - EDIT_MARGIN; |
1337 |
} |
1338 |
|
1339 |
s = [nameEditor stringValue]; |
1340 |
labwidth = [editorFont widthOfString: s] + LABEL_MARGIN; |
1341 |
|
1342 |
labcenter = crx; |
1343 |
|
1344 |
while ((labcenter + (labwidth / 2)) > bw) { |
1345 |
labcenter -= EDIT_MARGIN; |
1346 |
if (labcenter < EDIT_MARGIN) { |
1347 |
break; |
1348 |
} |
1349 |
} |
1350 |
|
1351 |
while ((labcenter - (labwidth / 2)) < EDIT_MARGIN) { |
1352 |
labcenter += EDIT_MARGIN; |
1353 |
if (labcenter >= bw) { |
1354 |
break; |
1355 |
} |
1356 |
} |
1357 |
|
1358 |
[self setNeedsDisplayInRect: [nameEditor frame]]; |
1359 |
[nameEditor setFrame: NSMakeRect((labcenter - (labwidth / 2)), ory, labwidth, LABEL_HEIGHT)]; |
1360 |
} |
1361 |
|
1362 |
- (void)controlTextDidBeginEditing:(NSNotification *)aNotification |
1363 |
{ |
1364 |
isEditingIconName = YES; |
1365 |
} |
1366 |
|
1367 |
- (void)controlTextDidEndEditing:(NSNotification *)aNotification |
1368 |
{ |
1369 |
NSString *oldpath = [[nameEditor paths] objectAtIndex: 0]; |
1370 |
NSString *basepath = [oldpath stringByDeletingLastPathComponent]; |
1371 |
NSString *oldname = [nameEditor name]; |
1372 |
NSString *newname = [nameEditor stringValue]; |
1373 |
NSString *newpath = [basepath stringByAppendingPathComponent: newname]; |
1374 |
NSFileManager *fm = [NSFileManager defaultManager]; |
1375 |
|
1376 |
#define CLEAREDITING \ |
1377 |
[self updateNameEditor]; \ |
1378 |
return |
1379 |
|
1380 |
isEditingIconName = NO; |
1381 |
[nameEditor setAlignment: NSCenterTextAlignment]; |
1382 |
|
1383 |
if ([fm isWritableFileAtPath: oldpath] == NO) { |
1384 |
NSRunAlertPanel(NSLocalizedString(@"Error", @""), |
1385 |
[NSString stringWithFormat: @"%@\"%@\"!\n", |
1386 |
NSLocalizedString(@"You have not write permission\nfor ", @""), |
1387 |
oldpath], NSLocalizedString(@"Continue", @""), nil, nil); |
1388 |
CLEAREDITING; |
1389 |
|
1390 |
} else if ([fm isWritableFileAtPath: basepath] == NO) { |
1391 |
NSRunAlertPanel(NSLocalizedString(@"Error", @""), |
1392 |
[NSString stringWithFormat: @"%@\"%@\"!\n", |
1393 |
NSLocalizedString(@"You have not write permission\nfor ", @""), |
1394 |
basepath], NSLocalizedString(@"Continue", @""), nil, nil); |
1395 |
CLEAREDITING; |
1396 |
|
1397 |
} else { |
1398 |
NSCharacterSet *notAllowSet = [NSCharacterSet characterSetWithCharactersInString: @"/\\*$|~\'\"`^!?"]; |
1399 |
NSRange range = [newname rangeOfCharacterFromSet: notAllowSet]; |
1400 |
NSArray *dirContents = [fm directoryContentsAtPath: basepath]; |
1401 |
NSMutableDictionary *notifObj = [NSMutableDictionary dictionaryWithCapacity: 1]; |
1402 |
|
1403 |
if (range.length > 0) { |
1404 |
NSRunAlertPanel(NSLocalizedString(@"Error", @""), |
1405 |
NSLocalizedString(@"Invalid char in name", @""), |
1406 |
NSLocalizedString(@"Continue", @""), nil, nil); |
1407 |
CLEAREDITING; |
1408 |
} |
1409 |
|
1410 |
if ([dirContents containsObject: newname]) { |
1411 |
if ([newname isEqualToString: oldname]) { |
1412 |
CLEAREDITING; |
1413 |
} else { |
1414 |
NSRunAlertPanel(NSLocalizedString(@"Error", @""), |
1415 |
[NSString stringWithFormat: @"%@\"%@\" %@\n", |
1416 |
NSLocalizedString(@"The name ", @""), |
1417 |
newname, NSLocalizedString(@" is already in use!", @"")], |
1418 |
NSLocalizedString(@"Continue", @""), nil, nil); |
1419 |
CLEAREDITING; |
1420 |
} |
1421 |
} |
1422 |
|
1423 |
[notifObj setObject: GWorkspaceRenameOperation forKey: @"operation"]; |
1424 |
[notifObj setObject: oldpath forKey: @"source"]; |
1425 |
[notifObj setObject: newpath forKey: @"destination"]; |
1426 |
[notifObj setObject: [NSArray arrayWithObject: @""] forKey: @"files"]; |
1427 |
|
1428 |
[[NSNotificationCenter defaultCenter] |
1429 |
postNotificationName: GWFileSystemWillChangeNotification |
1430 |
object: notifObj]; |
1431 |
|
1432 |
[fm movePath: oldpath toPath: newpath handler: self]; |
1433 |
|
1434 |
[[NSNotificationCenter defaultCenter] |
1435 |
postNotificationName: GWFileSystemDidChangeNotification |
1436 |
object: notifObj]; |
1437 |
|
1438 |
[self updateNameEditor]; |
1439 |
} |
1440 |
} |
1441 |
|
1442 |
- (void)editorAction:(id)sender |
1443 |
{ |
1444 |
} |
1445 |
|
1446 |
- (BOOL)fileManager:(NSFileManager *)manager |
1447 |
shouldProceedAfterError:(NSDictionary *)errorDict |
1448 |
{ |
1449 |
NSString *title = NSLocalizedString(@"Error", @""); |
1450 |
NSString *msg1 = NSLocalizedString(@"Cannot rename ", @""); |
1451 |
NSString *name = [nameEditor name]; |
1452 |
NSString *msg2 = NSLocalizedString(@"Continue", @""); |
1453 |
|
1454 |
NSRunAlertPanel(title, [NSString stringWithFormat: @"%@'%@'!", msg1, name], msg2, nil, nil); |
1455 |
|
1456 |
return NO; |
1457 |
} |
1458 |
|
1459 |
- (void)fileManager:(NSFileManager *)manager willProcessPath:(NSString *)path |
1460 |
{ |
1461 |
} |
1462 |
|
1463 |
- (BOOL)acceptsFirstResponder |
1464 |
{ |
1465 |
return YES; |
1466 |
} |
1467 |
|
1468 |
- (BOOL)becomeFirstResponder |
1469 |
{ |
1470 |
BColumn *selCol; |
1471 |
NSMatrix *matrix; |
1472 |
|
1473 |
selCol = [self selectedColumn]; |
1474 |
|
1475 |
if (selCol == nil) { |
1476 |
matrix = [(*getImp)(columns, getSel, 0) cmatrix]; |
1477 |
} else { |
1478 |
matrix = [selCol cmatrix]; |
1479 |
} |
1480 |
|
1481 |
if (matrix) { |
1482 |
[[self window] makeFirstResponder: matrix]; |
1483 |
} |
1484 |
|
1485 |
return YES; |
1486 |
} |
1487 |
|
1488 |
- (void)keyDown:(NSEvent *)theEvent |
1489 |
{ |
1490 |
NSString *characters; |
1491 |
unichar character; |
1492 |
BColumn *column; |
1493 |
NSMatrix *matrix; |
1494 |
|
1495 |
if (!(column = [self selectedColumn])) { |
1496 |
return; |
1497 |
} |
1498 |
if (!(matrix = [column cmatrix])) { |
1499 |
return; |
1500 |
} |
1501 |
|
1502 |
characters = [theEvent characters]; |
1503 |
character = 0; |
1504 |
|
1505 |
if ([characters length] > 0) { |
1506 |
character = [characters characterAtIndex: 0]; |
1507 |
} |
1508 |
|
1509 |
switch (character) { |
1510 |
case NSUpArrowFunctionKey: |
1511 |
case NSDownArrowFunctionKey: |
1512 |
return; |
1513 |
|
1514 |
case NSLeftArrowFunctionKey: |
1515 |
{ |
1516 |
if ([theEvent modifierFlags] & NSControlKeyMask) { |
1517 |
[super keyDown: theEvent]; |
1518 |
} else { |
1519 |
[self moveLeft: self]; |
1520 |
} |
1521 |
} |
1522 |
return; |
1523 |
|
1524 |
case NSRightArrowFunctionKey: |
1525 |
{ |
1526 |
if ([theEvent modifierFlags] & NSControlKeyMask) { |
1527 |
[super keyDown: theEvent]; |
1528 |
} else { |
1529 |
[self moveRight: self]; |
1530 |
} |
1531 |
} |
1532 |
return; |
1533 |
|
1534 |
case 13: |
1535 |
[matrix sendDoubleAction]; |
1536 |
return; |
1537 |
|
1538 |
case NSTabCharacter: |
1539 |
{ |
1540 |
if ([theEvent modifierFlags] & NSShiftKeyMask) |
1541 |
[[self window] selectKeyViewPrecedingView: self]; |
1542 |
else |
1543 |
[[self window] selectKeyViewFollowingView: self]; |
1544 |
} |
1545 |
return; |
1546 |
break; |
1547 |
} |
1548 |
|
1549 |
if ((character < 0xF700) && ([characters length] > 0)) { |
1550 |
// column = [self lastNotEmptyColumn]; |
1551 |
column = [self selectedColumn]; |
1552 |
|
1553 |
if (column) { |
1554 |
int index = [column index]; |
1555 |
|
1556 |
matrix = [column cmatrix]; |
1557 |
|
1558 |
if (matrix == nil) { |
1559 |
return; |
1560 |
} |
1561 |
|
1562 |
if (charBuffer == nil) { |
1563 |
charBuffer = [characters substringToIndex: 1]; |
1564 |
RETAIN (charBuffer); |
1565 |
} else { |
1566 |
if (([theEvent timestamp] - lastKeyPressed < 2000.0) |
1567 |
&& (alphaNumericalLastColumn == index)) { |
1568 |
ASSIGN (charBuffer, ([charBuffer stringByAppendingString: |
1569 |
[characters substringToIndex: 1]])); |
1570 |
} else { |
1571 |
ASSIGN (charBuffer, ([characters substringToIndex: 1])); |
1572 |
} |
1573 |
} |
1574 |
|
1575 |
alphaNumericalLastColumn = index; |
1576 |
lastKeyPressed = [theEvent timestamp]; |
1577 |
|
1578 |
if ([column selectCellWithPrefix: charBuffer]) { |
1579 |
// [[self window] makeFirstResponder: matrix]; |
1580 |
return; |
1581 |
} |
1582 |
} |
1583 |
|
1584 |
lastKeyPressed = 0.; |
1585 |
} |
1586 |
|
1587 |
[super keyDown: theEvent]; |
1588 |
} |
1589 |
|
1590 |
- (void)resizeSubviewsWithOldSize:(NSSize)oldSize |
1591 |
{ |
1592 |
[self tile]; |
1593 |
} |
1594 |
|
1595 |
- (void)drawRect:(NSRect)rect |
1596 |
{ |
1597 |
NSRect r; |
1598 |
NSSize bs; |
1599 |
NSPoint p1, p2; |
1600 |
NSRect browserRect; |
1601 |
NSRect scrollerBorderRect; |
1602 |
int i; |
1603 |
|
1604 |
r = [self bounds]; |
1605 |
bs = BEZEL_BORDER_SIZE; |
1606 |
|
1607 |
NSRectClip(rect); |
1608 |
[[[self window] backgroundColor] set]; |
1609 |
NSRectFill(rect); |
1610 |
|
1611 |
if (!isLoaded) { |
1612 |
[self loadColumnZero]; |
1613 |
} |
1614 |
|
1615 |
if (styleMask & GWColumnIconMask) { |
1616 |
scrollerBorderRect = NSMakeRect(scrollerRect.origin.x, |
1617 |
scrollerRect.origin.y, scrollerRect.size.width, |
1618 |
scrollerRect.size.height + iconsPathWidth - 2); |
1619 |
|
1620 |
scrollerBorderRect.origin.x = 0; |
1621 |
scrollerBorderRect.origin.y = scrollerRect.origin.y - 1; |
1622 |
scrollerBorderRect.size.width += 2 * bs.width; |
1623 |
scrollerBorderRect.size.height += (2 * bs.height); |
1624 |
|
1625 |
} else { |
1626 |
scrollerBorderRect = scrollerRect; |
1627 |
scrollerBorderRect.origin.x = 0; |
1628 |
scrollerBorderRect.origin.y = 1; |
1629 |
scrollerBorderRect.size.width += 2 * bs.width; |
1630 |
scrollerBorderRect.size.height += (2 * bs.height) - 1; |
1631 |
} |
1632 |
|
1633 |
if (NSIntersectsRect(scrollerBorderRect, r)) { |
1634 |
p1 = NSMakePoint(scrollerBorderRect.origin.x + 2, |
1635 |
scrollerBorderRect.origin.y + scrollerRect.size.height + 2); |
1636 |
p2 = NSMakePoint(scrollerBorderRect.origin.x + scrollerBorderRect.size.width - 2, |
1637 |
scrollerBorderRect.origin.y + scrollerRect.size.height + 2); |
1638 |
|
1639 |
NSDrawGrayBezel(scrollerBorderRect, r); |
1640 |
|
1641 |
if (styleMask & GWColumnIconMask) { |
1642 |
[[NSColor blackColor] set]; |
1643 |
[NSBezierPath strokeLineFromPoint: p1 toPoint: p2]; |
1644 |
} |
1645 |
} |
1646 |
|
1647 |
if (styleMask & GWColumnIconMask) { |
1648 |
browserRect = NSMakeRect(0, -2, r.size.width, columnSize.height + 4); |
1649 |
} else { |
1650 |
browserRect = NSMakeRect(0, columnOriginY - 2, r.size.width, |
1651 |
r.size.height - columnOriginY + 2); |
1652 |
} |
1653 |
NSDrawGrayBezel(browserRect, r); |
1654 |
|
1655 |
[[NSColor blackColor] set]; |
1656 |
|
1657 |
for (i = 1; i < visibleColumns; i++) { |
1658 |
p1 = NSMakePoint((columnSize.width * i) + 2 + (i-1), |
1659 |
columnSize.height + columnOriginY); |
1660 |
p2 = NSMakePoint((columnSize.width * i) + 2 + (i-1), columnOriginY); |
1661 |
[NSBezierPath strokeLineFromPoint: p1 toPoint: p2]; |
1662 |
} |
1663 |
} |
1664 |
|
1665 |
@end |
1666 |
|
1667 |
|
1668 |
|
1669 |
|
1670 |
|
1671 |
|
1672 |
|
1673 |
|
1674 |
|
1675 |
|
1676 |
|
1677 |
|
1678 |
|
1679 |
|
1680 |
|
1681 |
|
1682 |
|
1683 |
|