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