1999-02-19 20:19:58 +00:00
|
|
|
/*
|
1996-05-30 20:03:15 +00:00
|
|
|
NSBrowser.m
|
|
|
|
|
1997-10-31 01:24:08 +00:00
|
|
|
Control to display and select from hierarchal lists
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1997-10-31 01:24:08 +00:00
|
|
|
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
Author: Scott Christley <scottc@net-community.com>
|
|
|
|
Date: 1996
|
1998-11-25 17:16:48 +00:00
|
|
|
Author: Felipe A. Rodriguez <far@ix.netcom.com>
|
|
|
|
Date: August 1998
|
1999-02-19 20:19:58 +00:00
|
|
|
|
1996-05-30 20:03:15 +00:00
|
|
|
This file is part of the GNUstep GUI Library.
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
1999-02-19 20:19:58 +00:00
|
|
|
|
1996-05-30 20:03:15 +00:00
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public
|
1996-10-18 17:14:13 +00:00
|
|
|
License along with this library; see the file COPYING.LIB.
|
|
|
|
If not, write to the Free Software Foundation,
|
|
|
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
1999-02-19 20:19:58 +00:00
|
|
|
*/
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1997-09-23 22:43:24 +00:00
|
|
|
#include <gnustep/gui/config.h>
|
1997-02-18 00:29:25 +00:00
|
|
|
#include <AppKit/NSBrowser.h>
|
1997-10-31 01:24:08 +00:00
|
|
|
#include <AppKit/NSBrowserCell.h>
|
|
|
|
#include <Foundation/NSArray.h>
|
|
|
|
#include <Foundation/NSException.h>
|
|
|
|
#include <AppKit/AppKitExceptions.h>
|
|
|
|
#include <AppKit/NSScroller.h>
|
|
|
|
#include <AppKit/NSCell.h>
|
|
|
|
#include <AppKit/NSColor.h>
|
|
|
|
#include <AppKit/NSScrollView.h>
|
1999-04-18 06:11:29 +00:00
|
|
|
#include <AppKit/NSGraphics.h>
|
1997-10-31 01:24:08 +00:00
|
|
|
#include <AppKit/NSMatrix.h>
|
1997-11-01 21:20:49 +00:00
|
|
|
#include <AppKit/NSTextFieldCell.h>
|
1999-03-24 11:31:06 +00:00
|
|
|
#include <AppKit/PSOperators.h>
|
1997-10-31 01:24:08 +00:00
|
|
|
|
|
|
|
#define COLUMN_SEP 6
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1997-10-31 01:24:08 +00:00
|
|
|
//
|
|
|
|
// Internal class for maintaining information about columns
|
|
|
|
//
|
|
|
|
@interface NSBrowserColumn : NSObject
|
|
|
|
{
|
|
|
|
BOOL _isLoaded;
|
|
|
|
id _columnScrollView;
|
|
|
|
id _columnMatrix;
|
|
|
|
id _emptyView;
|
|
|
|
int _numberOfRows;
|
|
|
|
NSString *_columnTitle;
|
|
|
|
}
|
|
|
|
|
1999-03-16 10:53:42 +00:00
|
|
|
- (void)setIsLoaded: (BOOL)flag;
|
1997-10-31 01:24:08 +00:00
|
|
|
- (BOOL)isLoaded;
|
1999-03-16 10:53:42 +00:00
|
|
|
- (void)setColumnScrollView: (id)aView;
|
1997-10-31 01:24:08 +00:00
|
|
|
- columnScrollView;
|
1999-03-16 10:53:42 +00:00
|
|
|
- (void)setColumnMatrix: (id)aMatrix;
|
1997-10-31 01:24:08 +00:00
|
|
|
- columnMatrix;
|
1999-03-16 10:53:42 +00:00
|
|
|
- (void)setNumberOfRows: (int)num;
|
1997-10-31 01:24:08 +00:00
|
|
|
- (int)numberOfRows;
|
1999-03-16 10:53:42 +00:00
|
|
|
- (void)setColumnTitle: (NSString *)aString;
|
1997-10-31 01:24:08 +00:00
|
|
|
- (NSString *)columnTitle;
|
|
|
|
- emptyView;
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation NSBrowserColumn
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (id) init
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
[super init];
|
|
|
|
|
|
|
|
_isLoaded = NO;
|
|
|
|
_emptyView = [[NSView alloc] init];
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void) dealloc
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
1998-01-30 00:34:25 +00:00
|
|
|
[_columnScrollView release];
|
|
|
|
[_columnMatrix release];
|
|
|
|
[_emptyView release];
|
1997-10-31 01:24:08 +00:00
|
|
|
[_columnTitle release];
|
|
|
|
[super dealloc];
|
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void) setIsLoaded: (BOOL)flag
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_isLoaded = flag;
|
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (BOOL) isLoaded
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
return _isLoaded;
|
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void) setColumnScrollView: (id)aView
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
1999-02-19 20:19:58 +00:00
|
|
|
ASSIGN(_columnScrollView, aView);
|
1997-10-31 01:24:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- columnScrollView
|
|
|
|
{
|
|
|
|
return _columnScrollView;
|
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setColumnMatrix: (id)aMatrix
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
1999-02-19 20:19:58 +00:00
|
|
|
ASSIGN(_columnMatrix, aMatrix);
|
1997-10-31 01:24:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- columnMatrix
|
|
|
|
{
|
|
|
|
return _columnMatrix;
|
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void) setNumberOfRows: (int)num
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_numberOfRows = num;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (int)numberOfRows
|
|
|
|
{
|
|
|
|
return _numberOfRows;
|
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setColumnTitle: (NSString *)aString
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
[aString retain];
|
|
|
|
[_columnTitle release];
|
|
|
|
_columnTitle = aString;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *)columnTitle
|
|
|
|
{
|
|
|
|
return _columnTitle;
|
|
|
|
}
|
|
|
|
|
|
|
|
- emptyView
|
|
|
|
{
|
|
|
|
return _emptyView;
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
1999-10-25 03:14:56 +00:00
|
|
|
@interface GSBrowserTitleCell: NSTextFieldCell
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation GSBrowserTitleCell
|
|
|
|
- (id) initTextCell: (NSString *)aString
|
|
|
|
{
|
|
|
|
[super initTextCell: aString];
|
|
|
|
|
|
|
|
[self setTextColor: [NSColor windowFrameTextColor]];
|
|
|
|
[self setBackgroundColor: [NSColor controlShadowColor]];
|
|
|
|
[self setEditable: NO];
|
|
|
|
[self setBezeled: YES];
|
|
|
|
[self setAlignment: NSCenterTextAlignment];
|
1999-11-12 07:41:24 +00:00
|
|
|
//draw_background = YES;
|
1999-10-25 03:14:56 +00:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
- (void) drawWithFrame: (NSRect)cellFrame inView: (NSView*)controlView
|
|
|
|
{
|
|
|
|
if (NSIsEmptyRect (cellFrame))
|
|
|
|
return;
|
|
|
|
|
|
|
|
[controlView lockFocus];
|
|
|
|
NSDrawGrayBezel (cellFrame, NSZeroRect);
|
|
|
|
[controlView unlockFocus];
|
|
|
|
[self drawInteriorWithFrame: cellFrame inView: controlView];
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
1997-10-31 01:24:08 +00:00
|
|
|
//
|
|
|
|
// Private NSBrowser methods
|
|
|
|
//
|
|
|
|
@interface NSBrowser (Private)
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)_adjustMatrixOfColumn: (int)column;
|
1999-03-16 10:53:42 +00:00
|
|
|
- (void)_adjustScrollerFrameOfColumn: (int)column force: (BOOL)flag;
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)_adjustScrollerFrames: (BOOL)flag;
|
|
|
|
- (void)_performLoadOfColumn: (int)column;
|
|
|
|
- (void)_unloadFromColumn: (int)column;
|
1997-10-31 01:24:08 +00:00
|
|
|
@end
|
|
|
|
|
|
|
|
//
|
|
|
|
// NSBrowser implementation
|
|
|
|
//
|
1996-05-30 20:03:15 +00:00
|
|
|
@implementation NSBrowser
|
|
|
|
|
|
|
|
//
|
|
|
|
// Class methods
|
|
|
|
//
|
|
|
|
+ (void)initialize
|
|
|
|
{
|
|
|
|
if (self == [NSBrowser class])
|
|
|
|
{
|
|
|
|
// Initial version
|
1999-02-19 20:19:58 +00:00
|
|
|
[self setVersion: 1];
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Setting Component Classes
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
|
|
|
+ (Class)cellClass
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return [NSBrowserCell class];
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-08-31 09:19:39 +00:00
|
|
|
/*
|
|
|
|
* Instance methods
|
|
|
|
*/
|
|
|
|
- (id) initWithFrame: (NSRect)rect
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
NSSize bs;
|
|
|
|
|
|
|
|
[super initWithFrame: rect];
|
|
|
|
|
|
|
|
_browserCellClass = [NSBrowser cellClass];
|
|
|
|
_browserCellPrototype = [[_browserCellClass alloc] init];
|
|
|
|
_browserMatrixClass = [NSMatrix class];
|
1998-01-30 00:34:25 +00:00
|
|
|
_pathSeparator = @"/";
|
1997-10-31 01:24:08 +00:00
|
|
|
_isLoaded = NO;
|
|
|
|
_allowsBranchSelection = YES;
|
|
|
|
_allowsEmptySelection = YES;
|
|
|
|
_allowsMultipleSelection = YES;
|
|
|
|
_reusesColumns = NO;
|
|
|
|
_maxVisibleColumns = 1;
|
|
|
|
bs = [NSCell sizeForBorderType: NSBezelBorder];
|
|
|
|
_minColumnWidth = [NSScroller scrollerWidth] + (2 * bs.width);
|
|
|
|
_separatesColumns = YES;
|
|
|
|
_takesTitleFromPreviousColumn = YES;
|
|
|
|
_isTitled = YES;
|
|
|
|
_hasHorizontalScroller = YES;
|
1999-10-27 13:33:03 +00:00
|
|
|
_scrollerRect.origin.x = bs.width;
|
|
|
|
_scrollerRect.origin.y = bs.height;
|
|
|
|
_scrollerRect.size.width = frame.size.width - (2 * bs.width);
|
1999-10-26 22:37:36 +00:00
|
|
|
_scrollerRect.size.height = [NSScroller scrollerWidth];
|
|
|
|
_horizontalScroller = [[NSScroller alloc] initWithFrame: _scrollerRect];
|
1997-10-31 01:24:08 +00:00
|
|
|
[_horizontalScroller setTarget: self];
|
1999-08-31 09:19:39 +00:00
|
|
|
[_horizontalScroller setAction: @selector(scrollViaScroller:)];
|
1997-10-31 01:24:08 +00:00
|
|
|
[self addSubview: _horizontalScroller];
|
|
|
|
_acceptsArrowKeys = YES;
|
|
|
|
_sendsActionOnArrowKeys = YES;
|
|
|
|
_browserDelegate = nil;
|
|
|
|
_passiveDelegate = YES;
|
|
|
|
_doubleAction = NULL;
|
|
|
|
_browserColumns = [[NSMutableArray alloc] init];
|
1999-10-25 03:14:56 +00:00
|
|
|
_titleCell = [GSBrowserTitleCell new];
|
1997-10-31 01:24:08 +00:00
|
|
|
|
|
|
|
// Calculate geometry
|
|
|
|
[self tile];
|
|
|
|
|
|
|
|
// Create a single column
|
|
|
|
_lastColumnLoaded = -1;
|
|
|
|
_firstVisibleColumn = 0;
|
|
|
|
_lastVisibleColumn = 0;
|
|
|
|
[self addColumn];
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)dealloc
|
|
|
|
{
|
|
|
|
[_browserCellPrototype release];
|
|
|
|
[_pathSeparator release];
|
|
|
|
[_horizontalScroller release];
|
|
|
|
[_browserColumns release];
|
|
|
|
[_titleCell release];
|
|
|
|
|
|
|
|
[super dealloc];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-03-27 06:34:07 +00:00
|
|
|
//
|
|
|
|
// Target-actions stuff
|
|
|
|
//
|
|
|
|
- (void) setTarget: (id)t
|
|
|
|
{
|
|
|
|
_target = t;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) target
|
|
|
|
{
|
|
|
|
return _target;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) setAction: (SEL)s
|
|
|
|
{
|
|
|
|
_action = s;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (SEL) action
|
|
|
|
{
|
|
|
|
return _action;
|
|
|
|
}
|
|
|
|
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Setting the Delegate
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
|
|
|
- (id)delegate
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _browserDelegate;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setDelegate: (id)anObject
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
BOOL flag = NO;
|
|
|
|
BOOL both = NO;
|
|
|
|
|
1999-06-04 14:02:18 +00:00
|
|
|
if (![anObject respondsToSelector:
|
1999-08-31 09:19:39 +00:00
|
|
|
@selector(browser:willDisplayCell:atRow:column:)])
|
1997-10-31 01:24:08 +00:00
|
|
|
[NSException raise: NSBrowserIllegalDelegateException
|
|
|
|
format: @"Delegate does not respond to %s\n",
|
1999-03-16 10:53:42 +00:00
|
|
|
"browser: willDisplayCell: atRow: column: "];
|
1997-10-31 01:24:08 +00:00
|
|
|
|
1999-06-04 14:02:18 +00:00
|
|
|
if ([anObject respondsToSelector:
|
1999-08-31 09:19:39 +00:00
|
|
|
@selector(browser:numberOfRowsInColumn:)])
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_passiveDelegate = YES;
|
|
|
|
flag = YES;
|
|
|
|
}
|
|
|
|
|
1999-06-04 14:02:18 +00:00
|
|
|
if ([anObject respondsToSelector:
|
1999-08-31 09:19:39 +00:00
|
|
|
@selector(browser:createRowsForColumn:inMatrix:)])
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_passiveDelegate = NO;
|
|
|
|
|
|
|
|
// If flag is already set
|
|
|
|
// then delegate must respond to both methods
|
|
|
|
if (flag)
|
|
|
|
both = YES;
|
|
|
|
|
|
|
|
flag = YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!flag)
|
|
|
|
[NSException raise: NSBrowserIllegalDelegateException
|
|
|
|
format: @"Delegate does not respond to %s or %s\n",
|
1999-03-16 10:53:42 +00:00
|
|
|
"browser: numberOfRowsInColumn: ",
|
|
|
|
"browser: createRowsForColumn: inMatrix: "];
|
1997-10-31 01:24:08 +00:00
|
|
|
|
|
|
|
if (both)
|
|
|
|
[NSException raise: NSBrowserIllegalDelegateException
|
|
|
|
format: @"Delegate responds to both %s and %s\n",
|
1999-03-16 10:53:42 +00:00
|
|
|
"browser: numberOfRowsInColumn: ",
|
|
|
|
"browser: createRowsForColumn: inMatrix: "];
|
1997-10-31 01:24:08 +00:00
|
|
|
|
|
|
|
[anObject retain];
|
|
|
|
[_browserDelegate release];
|
|
|
|
_browserDelegate = anObject;
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Target and Action
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
|
|
|
- (SEL)doubleAction
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _doubleAction;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)sendAction
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return [self sendAction: [self action] to: [self target]];
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setDoubleAction: (SEL)aSelector
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_doubleAction = aSelector;
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Setting Component Classes
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
|
|
|
- (id)cellPrototype
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _browserCellPrototype;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (Class)matrixClass
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _browserMatrixClass;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setCellClass: (Class)classId
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_browserCellClass = classId;
|
|
|
|
|
|
|
|
// set the prototype for the new class
|
1997-11-01 21:20:49 +00:00
|
|
|
[self setCellPrototype: [[[_browserCellClass alloc] init] autorelease]];
|
1997-10-31 01:24:08 +00:00
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setCellPrototype: (NSCell *)aCell
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
[aCell retain];
|
|
|
|
[_browserCellPrototype release];
|
|
|
|
_browserCellPrototype = aCell;
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setMatrixClass: (Class)classId
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_browserMatrixClass = classId;
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Setting NSBrowser Behavior
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
|
|
|
- (BOOL)reusesColumns
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _reusesColumns;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setReusesColumns: (BOOL)flag
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_reusesColumns = flag;
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setTakesTitleFromPreviousColumn: (BOOL)flag
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_takesTitleFromPreviousColumn = flag;
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
- (BOOL)takesTitleFromPreviousColumn
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _takesTitleFromPreviousColumn;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Allowing Different Types of Selection
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
|
|
|
- (BOOL)allowsBranchSelection
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _allowsBranchSelection;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)allowsEmptySelection
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _allowsEmptySelection;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)allowsMultipleSelection
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _allowsMultipleSelection;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setAllowsBranchSelection: (BOOL)flag
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_allowsBranchSelection = flag;
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setAllowsEmptySelection: (BOOL)flag
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_allowsEmptySelection = flag;
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setAllowsMultipleSelection: (BOOL)flag
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_allowsMultipleSelection = flag;
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Setting Arrow Key Behavior
|
|
|
|
//
|
|
|
|
- (BOOL)acceptsArrowKeys
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _acceptsArrowKeys;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)sendsActionOnArrowKeys
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _sendsActionOnArrowKeys;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setAcceptsArrowKeys: (BOOL)flag
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_acceptsArrowKeys = flag;
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setSendsActionOnArrowKeys: (BOOL)flag
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_sendsActionOnArrowKeys = flag;
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Showing a Horizontal Scroller
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setHasHorizontalScroller: (BOOL)flag
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_hasHorizontalScroller = flag;
|
|
|
|
|
|
|
|
if (!flag)
|
|
|
|
[_horizontalScroller removeFromSuperview];
|
|
|
|
|
|
|
|
[self tile];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
- (BOOL)hasHorizontalScroller
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _hasHorizontalScroller;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Setting the NSBrowser's Appearance
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
|
|
|
- (int)maxVisibleColumns
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _maxVisibleColumns;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (int)minColumnWidth
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _minColumnWidth;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)separatesColumns
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _separatesColumns;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setMaxVisibleColumns: (int)columnCount
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
int i, count = [_browserColumns count];
|
|
|
|
|
|
|
|
_maxVisibleColumns = columnCount;
|
|
|
|
|
|
|
|
// Create additional columns if necessary
|
|
|
|
for (i = count; i < _maxVisibleColumns; ++i)
|
|
|
|
[self addColumn];
|
|
|
|
|
|
|
|
_lastVisibleColumn = _maxVisibleColumns - _firstVisibleColumn - 1;
|
|
|
|
|
|
|
|
[self tile];
|
|
|
|
[self _adjustScrollerFrames: NO];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setMinColumnWidth: (int)columnWidth
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
float sw = [NSScroller scrollerWidth];
|
|
|
|
NSSize bs = [NSCell sizeForBorderType: NSBezelBorder];
|
|
|
|
float bw = 2 * bs.width;
|
|
|
|
|
|
|
|
// Take the border into account
|
|
|
|
if (_separatesColumns)
|
|
|
|
sw += bw;
|
|
|
|
|
|
|
|
// Column width cannot be less than scroller and border
|
|
|
|
if (columnWidth < sw)
|
|
|
|
_minColumnWidth = sw;
|
|
|
|
else
|
|
|
|
_minColumnWidth = columnWidth;
|
|
|
|
|
|
|
|
[self tile];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setSeparatesColumns: (BOOL)flag
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_separatesColumns = flag;
|
|
|
|
|
|
|
|
[self tile];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Manipulating Columns
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
|
|
|
- (void)addColumn
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
NSBrowserColumn *bc;
|
|
|
|
NSScrollView *sc;
|
|
|
|
int n = [_browserColumns count];
|
|
|
|
|
1997-11-01 21:20:49 +00:00
|
|
|
bc = [[[NSBrowserColumn alloc] init] autorelease];
|
1997-10-31 01:24:08 +00:00
|
|
|
|
|
|
|
// Create a scrollview
|
1998-01-30 00:34:25 +00:00
|
|
|
sc = [[[NSScrollView alloc]
|
|
|
|
initWithFrame: [self frameOfInsideOfColumn: n]]
|
|
|
|
autorelease];
|
1997-10-31 01:24:08 +00:00
|
|
|
[sc setHasHorizontalScroller: NO];
|
|
|
|
[sc setHasVerticalScroller: YES];
|
|
|
|
[bc setColumnScrollView: sc];
|
|
|
|
[self addSubview: sc];
|
|
|
|
|
|
|
|
[_browserColumns addObject: bc];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (int)columnOfMatrix: (NSMatrix *)matrix
|
1996-05-30 20:03:15 +00:00
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
NSBrowserColumn *bc;
|
|
|
|
int i, count = [_browserColumns count];
|
|
|
|
|
|
|
|
// Loop through columns and compare matrixes
|
|
|
|
for (i = 0;i < count; ++i)
|
|
|
|
{
|
|
|
|
bc = [_browserColumns objectAtIndex: i];
|
|
|
|
if (matrix == [bc columnMatrix])
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not found
|
|
|
|
return NSNotFound;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void) displayAllColumns
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
int i, count = [_browserColumns count];
|
|
|
|
|
|
|
|
for (i = 0; i < count; ++i)
|
|
|
|
{
|
|
|
|
//NSBrowserColumn *bc = [_browserColumns objectAtIndex: i];
|
|
|
|
|
|
|
|
// Only display if loaded
|
|
|
|
//if ([bc isLoaded])
|
|
|
|
[self displayColumn: i];
|
|
|
|
}
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void) displayColumn: (int)column
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
NSBrowserColumn *bc;
|
|
|
|
|
|
|
|
// If not visible then nothing to display
|
|
|
|
if ((column < _firstVisibleColumn) || (column > _lastVisibleColumn))
|
|
|
|
return;
|
|
|
|
|
|
|
|
bc = [_browserColumns objectAtIndex: column];
|
|
|
|
|
|
|
|
// Ask the delegate for the column title
|
1999-06-04 14:02:18 +00:00
|
|
|
if ([_browserDelegate respondsToSelector:
|
1999-08-31 09:19:39 +00:00
|
|
|
@selector(browser:titleOfColumn:)])
|
1997-10-31 01:24:08 +00:00
|
|
|
[self setTitle: [_browserDelegate browser: self
|
|
|
|
titleOfColumn: column]
|
|
|
|
ofColumn: column];
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Check if we take title from previous column
|
|
|
|
if ([self takesTitleFromPreviousColumn])
|
|
|
|
{
|
|
|
|
// If first column then use the path separator
|
|
|
|
if (column == 0)
|
|
|
|
[self setTitle: _pathSeparator ofColumn: 0];
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Get the selected cell
|
|
|
|
// Use its string value as the title
|
|
|
|
// Only if it is not a leaf
|
|
|
|
id c = [self selectedCellInColumn: column - 1];
|
|
|
|
if ([c isLeaf])
|
|
|
|
[self setTitle: @"" ofColumn: column];
|
|
|
|
else
|
|
|
|
[self setTitle: [c stringValue] ofColumn: column];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
[self setTitle: @"" ofColumn: column];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw the title
|
|
|
|
[self drawTitle: [bc columnTitle]
|
|
|
|
inRect: [self titleFrameOfColumn: column]
|
|
|
|
ofColumn: column];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
- (int)firstVisibleColumn
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _firstVisibleColumn;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)isLoaded
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _isLoaded;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (int)lastColumn
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _lastColumnLoaded;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (int)lastVisibleColumn
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _lastVisibleColumn;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)loadColumnZero
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
// load column 0
|
|
|
|
[self _performLoadOfColumn: 0];
|
|
|
|
|
|
|
|
// Unload other columns
|
|
|
|
[self _unloadFromColumn: 1];
|
|
|
|
|
|
|
|
// set last column loaded
|
|
|
|
[self setLastColumn: 0];
|
|
|
|
|
|
|
|
_isLoaded = YES;
|
|
|
|
[self tile];
|
|
|
|
[self _adjustScrollerFrames: YES];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
- (int)numberOfVisibleColumns
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
int i, j, count = [_browserColumns count];
|
|
|
|
BOOL done;
|
|
|
|
|
|
|
|
// As I interpret it, the number of visible columns
|
|
|
|
// is the total number of scrollviews in the scrolling
|
|
|
|
// region regardless of whether they are actually
|
|
|
|
// visible or not.
|
|
|
|
|
|
|
|
// We have at least upto the last visible column
|
|
|
|
i = _lastVisibleColumn;
|
|
|
|
|
|
|
|
// Plus any loaded columns after that
|
|
|
|
done = NO;
|
|
|
|
j = i + 1;
|
|
|
|
while ((!done) && (j < count))
|
|
|
|
{
|
|
|
|
NSBrowserColumn *bc = [_browserColumns objectAtIndex: j];
|
|
|
|
if ([bc isLoaded])
|
|
|
|
{
|
|
|
|
i = j;
|
|
|
|
++j;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
done = YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Should be at least the max visible columns
|
|
|
|
if (i < _maxVisibleColumns)
|
|
|
|
return _maxVisibleColumns;
|
|
|
|
else
|
|
|
|
return i + 1;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)reloadColumn: (int)column
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
NSBrowserColumn *bc;
|
|
|
|
|
|
|
|
// Make sure the column even exists
|
|
|
|
if (column >= (int)[_browserColumns count])
|
|
|
|
return;
|
|
|
|
|
|
|
|
bc = [_browserColumns objectAtIndex: column];
|
|
|
|
|
|
|
|
// If the column has not be loaded then do not reload
|
|
|
|
if (![bc isLoaded])
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Perform the data load
|
|
|
|
[self _performLoadOfColumn: column];
|
|
|
|
|
|
|
|
// Unload the columns after
|
|
|
|
[self _unloadFromColumn: column + 1];
|
|
|
|
|
|
|
|
// set last column loaded
|
|
|
|
[self setLastColumn: column];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)selectAll: (id)sender
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
id matrix = [self matrixInColumn: _lastVisibleColumn];
|
|
|
|
[matrix selectAll: sender];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
- (int)selectedColumn
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
id o, e = [_browserColumns reverseObjectEnumerator];
|
|
|
|
BOOL found = NO;
|
|
|
|
id c = nil;
|
|
|
|
int i = [_browserColumns count] - 1;
|
|
|
|
|
|
|
|
while ((!found) && (o = [e nextObject]))
|
|
|
|
{
|
1999-09-21 20:03:46 +00:00
|
|
|
if ([o isLoaded])
|
|
|
|
{
|
|
|
|
c = [[o columnMatrix] selectedCell];
|
|
|
|
if (c)
|
|
|
|
found = YES;
|
|
|
|
else
|
|
|
|
--i;
|
|
|
|
}
|
|
|
|
else
|
1997-10-31 01:24:08 +00:00
|
|
|
--i;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (found)
|
|
|
|
return i;
|
|
|
|
else
|
|
|
|
return NSNotFound;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-01-19 10:42:50 +00:00
|
|
|
- (int) selectedRowInColumn: (int)column
|
|
|
|
{
|
|
|
|
return [[self matrixInColumn: column] selectedRow];
|
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setLastColumn: (int)column
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_lastColumnLoaded = column;
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
- (void)validateVisibleColumns
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
// xxx Should we trigger an exception?
|
1999-06-04 14:02:18 +00:00
|
|
|
if (![_browserDelegate respondsToSelector:
|
1999-08-31 09:19:39 +00:00
|
|
|
@selector(browser:isColumnValid:)])
|
1997-10-31 01:24:08 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Loop through the visible columns
|
|
|
|
for (i = _firstVisibleColumn; i <= _lastVisibleColumn; ++i)
|
|
|
|
{
|
|
|
|
// Ask delegate if the column is valid and if not
|
|
|
|
// then reload the column
|
|
|
|
BOOL v = [_browserDelegate browser: self isColumnValid: i];
|
|
|
|
if (!v)
|
|
|
|
[self reloadColumn: i];
|
|
|
|
}
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Manipulating Column Titles
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)drawTitle: (NSString *)title
|
|
|
|
inRect: (NSRect)aRect
|
|
|
|
ofColumn: (int)column
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
// Not titled then nothing to draw
|
|
|
|
if (![self isTitled])
|
|
|
|
return;
|
|
|
|
|
|
|
|
// If column is not visible then nothing to draw
|
|
|
|
if ((column < _firstVisibleColumn) || (column > _lastVisibleColumn))
|
|
|
|
return;
|
|
|
|
|
|
|
|
[_titleCell setStringValue: title];
|
|
|
|
[_titleCell drawWithFrame: aRect inView: self];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
- (BOOL)isTitled
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _isTitled;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setTitled: (BOOL)flag
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
_isTitled = flag;
|
|
|
|
|
|
|
|
[self tile];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setTitle: (NSString *)aString
|
|
|
|
ofColumn: (int)column
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
NSBrowserColumn *bc = [_browserColumns objectAtIndex: column];
|
|
|
|
[bc setColumnTitle: aString];
|
|
|
|
|
|
|
|
// If column is not visible then nothing to redisplay
|
|
|
|
if ((column < _firstVisibleColumn) || (column > _lastVisibleColumn))
|
|
|
|
return;
|
|
|
|
else
|
|
|
|
[self setNeedsDisplayInRect: [self titleFrameOfColumn: column]];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (NSRect)titleFrameOfColumn: (int)column
|
1996-05-30 20:03:15 +00:00
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
NSRect r;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
// Not titled then no frame
|
|
|
|
if (![self isTitled])
|
|
|
|
return NSZeroRect;
|
|
|
|
|
|
|
|
// Number of columns over from the first
|
|
|
|
n = column - _firstVisibleColumn;
|
|
|
|
|
|
|
|
// Calculate the frame
|
|
|
|
r.origin.x = n * _columnSize.width;
|
|
|
|
r.origin.y = frame.size.height - [self titleHeight] + 2;
|
|
|
|
r.size.width = _columnSize.width;
|
|
|
|
r.size.height = [self titleHeight] - 4;
|
|
|
|
|
|
|
|
if (_separatesColumns)
|
|
|
|
r.origin.x += n * COLUMN_SEP;
|
|
|
|
|
|
|
|
return r;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (float)titleHeight
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return 24;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (NSString *)titleOfColumn: (int)column
|
1996-05-30 20:03:15 +00:00
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
NSBrowserColumn *bc = [_browserColumns objectAtIndex: column];
|
|
|
|
return [bc columnTitle];
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Scrolling an NSBrowser
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)scrollColumnsLeftBy: (int)shiftAmount
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
// Cannot shift past the zero column
|
|
|
|
if ((_firstVisibleColumn - shiftAmount) < 0)
|
|
|
|
shiftAmount = _firstVisibleColumn;
|
|
|
|
|
|
|
|
// No amount to shift then nothing to do
|
|
|
|
if (shiftAmount == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Notify the delegate
|
1999-08-31 09:19:39 +00:00
|
|
|
if ([_browserDelegate respondsToSelector: @selector(browserWillScroll:)])
|
1997-10-31 01:24:08 +00:00
|
|
|
[_browserDelegate browserWillScroll: self];
|
|
|
|
|
|
|
|
// Shift
|
|
|
|
_firstVisibleColumn = _firstVisibleColumn - shiftAmount;
|
|
|
|
_lastVisibleColumn = _lastVisibleColumn - shiftAmount;
|
|
|
|
|
|
|
|
// Update the scrollviews
|
|
|
|
[self _adjustScrollerFrames: YES];
|
|
|
|
|
|
|
|
// Update the scroller
|
|
|
|
[self updateScroller];
|
|
|
|
|
|
|
|
// Notify the delegate
|
1999-08-31 09:19:39 +00:00
|
|
|
if ([_browserDelegate respondsToSelector: @selector(browserDidScroll:)])
|
1997-10-31 01:24:08 +00:00
|
|
|
[_browserDelegate browserDidScroll: self];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)scrollColumnsRightBy: (int)shiftAmount
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
// Cannot shift past the last loaded column
|
|
|
|
if ((shiftAmount + _lastVisibleColumn) > _lastColumnLoaded)
|
|
|
|
shiftAmount = _lastColumnLoaded - _lastVisibleColumn;
|
|
|
|
|
|
|
|
// No amount to shift then nothing to do
|
|
|
|
if (shiftAmount == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Notify the delegate
|
1999-08-31 09:19:39 +00:00
|
|
|
if ([_browserDelegate respondsToSelector: @selector(browserWillScroll:)])
|
1997-10-31 01:24:08 +00:00
|
|
|
[_browserDelegate browserWillScroll: self];
|
|
|
|
|
|
|
|
// Shift
|
|
|
|
_firstVisibleColumn = _firstVisibleColumn + shiftAmount;
|
|
|
|
_lastVisibleColumn = _lastVisibleColumn + shiftAmount;
|
|
|
|
|
|
|
|
// Update the scrollviews
|
|
|
|
[self _adjustScrollerFrames: YES];
|
|
|
|
|
|
|
|
// Update the scroller
|
|
|
|
[self updateScroller];
|
|
|
|
|
|
|
|
// Notify the delegate
|
1999-08-31 09:19:39 +00:00
|
|
|
if ([_browserDelegate respondsToSelector: @selector(browserDidScroll:)])
|
1997-10-31 01:24:08 +00:00
|
|
|
[_browserDelegate browserDidScroll: self];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)scrollColumnToVisible: (int)column
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
// If its the last visible column then we are there already
|
|
|
|
if (_lastVisibleColumn == column)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// If there are not enough columns to scroll with
|
|
|
|
// then the column must be visible
|
|
|
|
if ([self numberOfVisibleColumns] <= _maxVisibleColumns)
|
|
|
|
return;
|
|
|
|
|
|
|
|
i = _lastVisibleColumn - column;
|
|
|
|
if (i > 0)
|
|
|
|
[self scrollColumnsLeftBy: i];
|
|
|
|
else
|
|
|
|
[self scrollColumnsRightBy: (-i)];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)scrollViaScroller: (NSScroller *)sender
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
NSScrollerPart hit = [sender hitPart];
|
|
|
|
|
|
|
|
// Scroll to the left
|
|
|
|
if ((hit == NSScrollerDecrementLine) || (hit == NSScrollerDecrementPage))
|
|
|
|
{
|
|
|
|
[self scrollColumnsLeftBy: 1];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Scroll to the right
|
|
|
|
if ((hit == NSScrollerIncrementLine) || (hit == NSScrollerIncrementPage))
|
|
|
|
{
|
|
|
|
[self scrollColumnsRightBy: 1];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The knob or knob slot
|
|
|
|
if ((hit == NSScrollerKnob) || (hit == NSScrollerKnobSlot))
|
|
|
|
{
|
|
|
|
float f = [sender floatValue];
|
|
|
|
int c = [self numberOfVisibleColumns] - 1;
|
|
|
|
float i;
|
|
|
|
|
|
|
|
// If the number of loaded columns has shrunk then
|
|
|
|
// there will be more columns displayed then loaded
|
|
|
|
// so use that value instead
|
|
|
|
if (c > _lastColumnLoaded)
|
|
|
|
i = c - _maxVisibleColumns + 1;
|
|
|
|
else
|
|
|
|
i = _lastColumnLoaded - _maxVisibleColumns + 1;
|
|
|
|
|
|
|
|
if (_lastColumnLoaded != 0)
|
|
|
|
{
|
|
|
|
f = (f - 1) * i;
|
|
|
|
f += _lastColumnLoaded;
|
|
|
|
[self scrollColumnToVisible: (int)f];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
[self updateScroller];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void) updateScroller
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
// If there are not enough columns to scroll with
|
|
|
|
// then the column must be visible
|
|
|
|
if ((_lastColumnLoaded == 0) ||
|
|
|
|
(_lastColumnLoaded <= (_maxVisibleColumns - 1)))
|
|
|
|
[_horizontalScroller setEnabled: NO];
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float prop = (float)_maxVisibleColumns / (float)(_lastColumnLoaded + 1);
|
|
|
|
float i = _lastColumnLoaded - _maxVisibleColumns + 1;
|
|
|
|
float f = 1 + ((_lastVisibleColumn - _lastColumnLoaded) / i);
|
|
|
|
[_horizontalScroller setFloatValue: f knobProportion: prop];
|
|
|
|
[_horizontalScroller setEnabled: YES];
|
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
[self setNeedsDisplay: YES];
|
1997-10-31 01:24:08 +00:00
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Event Handling
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
1999-09-28 15:53:25 +00:00
|
|
|
- (void)mouseDown: (NSEvent *)aEvent
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)doClick: (id)sender
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
int column = [self columnOfMatrix: sender];
|
|
|
|
NSArray *a;
|
|
|
|
BOOL shouldSelect = YES;
|
|
|
|
|
|
|
|
// If the matrix isn't ours then just return
|
|
|
|
if (column == NSNotFound)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Ask delegate if selection is ok
|
1999-06-04 14:02:18 +00:00
|
|
|
if ([_browserDelegate respondsToSelector:
|
1999-08-31 09:19:39 +00:00
|
|
|
@selector(browser:selectRow:inColumn:)])
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
int row = [sender selectedRow];
|
|
|
|
shouldSelect = [_browserDelegate browser: self selectRow: row
|
|
|
|
inColumn: column];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Try the other method
|
1999-06-04 14:02:18 +00:00
|
|
|
if ([_browserDelegate respondsToSelector:
|
1999-08-31 09:19:39 +00:00
|
|
|
@selector(browser:selectCellWithString:inColumn:)])
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
id c = [sender selectedCell];
|
|
|
|
shouldSelect = [_browserDelegate browser: self
|
1999-06-04 14:02:18 +00:00
|
|
|
selectCellWithString:
|
1997-10-31 01:24:08 +00:00
|
|
|
[c stringValue]
|
|
|
|
inColumn: column];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we should not select the cell
|
|
|
|
// then select it and return
|
|
|
|
if (!shouldSelect)
|
|
|
|
{
|
|
|
|
[sender deselectSelectedCell];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
a = [sender selectedCells];
|
|
|
|
|
|
|
|
// If only one cell is selected
|
|
|
|
if ([a count] == 1)
|
|
|
|
{
|
|
|
|
id c = [a objectAtIndex: 0];
|
|
|
|
|
|
|
|
// If the cell is a leaf
|
|
|
|
// then unload the columns after
|
|
|
|
if ([c isLeaf])
|
|
|
|
{
|
|
|
|
[self _unloadFromColumn: column + 1];
|
|
|
|
[self setLastColumn: column];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// The cell is not a leaf so we need to load a column
|
|
|
|
|
|
|
|
// If last column then add a column
|
|
|
|
if (column == (int)([_browserColumns count] - 1))
|
|
|
|
[self addColumn];
|
|
|
|
|
|
|
|
// Load column
|
|
|
|
[self _performLoadOfColumn: column + 1];
|
|
|
|
[self setLastColumn: column + 1];
|
|
|
|
[self _adjustMatrixOfColumn: column + 1];
|
|
|
|
[self _unloadFromColumn: column + 2];
|
|
|
|
|
|
|
|
// If this column is the last visible
|
|
|
|
// then scroll right by one column
|
|
|
|
if (column == _lastVisibleColumn)
|
|
|
|
[self scrollColumnsRightBy: 1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// If multiple selection
|
|
|
|
// then we unload the columns after
|
|
|
|
[self _unloadFromColumn: column + 1];
|
|
|
|
[self setLastColumn: column];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send the action to target
|
|
|
|
[self sendAction];
|
1999-02-19 20:19:58 +00:00
|
|
|
[self setNeedsDisplay: YES];
|
1997-10-31 01:24:08 +00:00
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)doDoubleClick: (id)sender
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
// We have already handled the single click
|
|
|
|
// so send the double action
|
|
|
|
[self sendAction: _doubleAction to: [self target]];
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Getting Matrices and Cells
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
- (id)loadedCellAtRow: (int)row
|
|
|
|
column: (int)column
|
1996-05-30 20:03:15 +00:00
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
NSBrowserColumn *bc;
|
|
|
|
NSArray *columnCells;
|
|
|
|
id matrix;
|
|
|
|
int count = [_browserColumns count];
|
|
|
|
id aCell;
|
|
|
|
|
|
|
|
// column range check
|
|
|
|
if (column >= count)
|
|
|
|
return nil;
|
|
|
|
|
|
|
|
bc = [_browserColumns objectAtIndex: column];
|
|
|
|
matrix = [bc columnMatrix];
|
|
|
|
columnCells = [matrix cells];
|
|
|
|
count = [columnCells count];
|
|
|
|
|
|
|
|
// row range check
|
|
|
|
if (row >= count)
|
|
|
|
return nil;
|
|
|
|
|
|
|
|
// Get the cell
|
|
|
|
aCell = [matrix cellAtRow: row column: 0];
|
|
|
|
|
|
|
|
// Load if not already loaded
|
|
|
|
if ([aCell isLoaded])
|
|
|
|
return aCell;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[_browserDelegate browser: self willDisplayCell: aCell
|
|
|
|
atRow: row column: column];
|
|
|
|
[aCell setLoaded: YES];
|
|
|
|
}
|
|
|
|
|
|
|
|
return aCell;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (NSMatrix *)matrixInColumn: (int)column
|
1996-05-30 20:03:15 +00:00
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
NSBrowserColumn *bc = [_browserColumns objectAtIndex: column];
|
|
|
|
return [bc columnMatrix];
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (id)selectedCell
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
int i = [self selectedColumn];
|
|
|
|
id matrix;
|
|
|
|
|
|
|
|
// Nothing selected
|
|
|
|
if (i == NSNotFound)
|
|
|
|
return nil;
|
|
|
|
|
|
|
|
matrix = [self matrixInColumn: i];
|
|
|
|
return [matrix selectedCell];
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (id)selectedCellInColumn: (int)column
|
1996-05-30 20:03:15 +00:00
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
id matrix = [self matrixInColumn: column];
|
|
|
|
return [matrix selectedCell];
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray *)selectedCells
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
int i = [self selectedColumn];
|
|
|
|
id matrix;
|
|
|
|
|
|
|
|
// Nothing selected
|
|
|
|
if (i == NSNotFound)
|
|
|
|
return nil;
|
|
|
|
|
|
|
|
matrix = [self matrixInColumn: i];
|
|
|
|
return [matrix selectedCells];
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Getting Column Frames
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
- (NSRect)frameOfColumn: (int)column
|
1996-05-30 20:03:15 +00:00
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
NSRect r = NSZeroRect;
|
|
|
|
int n;
|
1999-10-27 13:33:03 +00:00
|
|
|
NSSize bs = [NSCell sizeForBorderType: NSBezelBorder];
|
1997-10-31 01:24:08 +00:00
|
|
|
|
|
|
|
// Number of columns over from the first
|
|
|
|
n = column - _firstVisibleColumn;
|
|
|
|
|
|
|
|
// Calculate the frame
|
|
|
|
r.size = _columnSize;
|
|
|
|
r.origin.x = n * _columnSize.width;
|
|
|
|
|
|
|
|
if (_separatesColumns)
|
|
|
|
r.origin.x += n * COLUMN_SEP;
|
|
|
|
|
|
|
|
// Adjust for horizontal scroller
|
|
|
|
if (_hasHorizontalScroller)
|
1999-10-27 13:33:03 +00:00
|
|
|
r.origin.y = [NSScroller scrollerWidth] + (2 * bs.height) + 4;
|
1997-10-31 01:24:08 +00:00
|
|
|
|
|
|
|
return r;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (NSRect)frameOfInsideOfColumn: (int)column
|
1996-05-30 20:03:15 +00:00
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
// xxx what does this one do?
|
|
|
|
return [self frameOfColumn: column];
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Manipulating Paths
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
|
|
|
- (NSString *)path
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return [self pathToColumn: _lastColumnLoaded + 1];
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *)pathSeparator
|
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
return _pathSeparator;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (NSString *)pathToColumn: (int)column
|
1996-05-30 20:03:15 +00:00
|
|
|
{
|
1999-06-04 14:02:18 +00:00
|
|
|
NSMutableString *s = [_pathSeparator mutableCopy];
|
|
|
|
unsigned i;
|
1997-10-31 01:24:08 +00:00
|
|
|
|
1999-06-04 14:02:18 +00:00
|
|
|
/*
|
|
|
|
* Cannot go past the number of loaded columns
|
|
|
|
*/
|
1997-10-31 01:24:08 +00:00
|
|
|
if (column > _lastColumnLoaded)
|
|
|
|
column = _lastColumnLoaded + 1;
|
|
|
|
|
|
|
|
for (i = 0;i < column; ++i)
|
|
|
|
{
|
1999-06-04 14:02:18 +00:00
|
|
|
id c = [self selectedCellInColumn: i];
|
|
|
|
|
1997-10-31 01:24:08 +00:00
|
|
|
if (i != 0)
|
|
|
|
[s appendString: _pathSeparator];
|
|
|
|
[s appendString: [c stringValue]];
|
|
|
|
}
|
1999-06-04 14:02:18 +00:00
|
|
|
/*
|
|
|
|
* We actually return a mutable string, but that's ok since a mutable
|
|
|
|
* string is a string and the documentation specifically says that
|
|
|
|
* people should not depend on methods that return strings to return
|
|
|
|
* immutable strings.
|
|
|
|
*/
|
|
|
|
return s;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-06-04 14:02:18 +00:00
|
|
|
- (BOOL) setPath: (NSString *)path
|
1996-05-30 20:03:15 +00:00
|
|
|
{
|
1999-06-04 14:02:18 +00:00
|
|
|
NSArray *subStrings;
|
1999-04-18 06:11:29 +00:00
|
|
|
NSString *aStr;
|
1999-06-04 14:02:18 +00:00
|
|
|
unsigned numberOfSubStrings;
|
1999-11-09 20:57:15 +00:00
|
|
|
unsigned i, j;
|
1999-04-18 06:11:29 +00:00
|
|
|
|
1999-11-09 20:57:15 +00:00
|
|
|
// Column Zero is always present.
|
|
|
|
[self loadColumnZero];
|
|
|
|
|
|
|
|
// If that's all, return.
|
|
|
|
if ([path isEqualToString: _pathSeparator])
|
|
|
|
return YES;
|
|
|
|
|
|
|
|
// Otherwise, decompose the path.
|
1999-06-04 14:02:18 +00:00
|
|
|
subStrings = [path componentsSeparatedByString: _pathSeparator];
|
1999-04-18 06:11:29 +00:00
|
|
|
numberOfSubStrings = [subStrings count];
|
|
|
|
|
1999-11-09 20:57:15 +00:00
|
|
|
// Ignore a trailing void component.
|
|
|
|
if (![subStrings objectAtIndex: 0])
|
1999-04-18 06:11:29 +00:00
|
|
|
{
|
1999-11-09 20:57:15 +00:00
|
|
|
NSRange theRange;
|
|
|
|
|
|
|
|
theRange.location = 1;
|
|
|
|
numberOfSubStrings--;
|
|
|
|
theRange.length = numberOfSubStrings;
|
|
|
|
subStrings = [subStrings subarrayWithRange: theRange];
|
1999-04-18 06:11:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// cycle thru str's array created from path
|
|
|
|
for (i = 1; i < numberOfSubStrings; i++)
|
|
|
|
{
|
|
|
|
NSBrowserColumn *bc = [_browserColumns objectAtIndex: i-1];
|
|
|
|
NSMatrix *matrix = [bc columnMatrix];
|
|
|
|
NSArray *cells = [matrix cells];
|
1999-11-09 20:57:15 +00:00
|
|
|
unsigned numOfRows = [cells count];
|
1999-04-18 06:11:29 +00:00
|
|
|
NSBrowserCell *selectedCell = nil;
|
1999-11-09 20:57:15 +00:00
|
|
|
BOOL found = NO;
|
|
|
|
|
1999-04-18 06:11:29 +00:00
|
|
|
aStr = [subStrings objectAtIndex: i];
|
1999-11-09 20:57:15 +00:00
|
|
|
if (aStr)
|
1999-04-18 06:11:29 +00:00
|
|
|
{
|
1999-11-09 20:57:15 +00:00
|
|
|
// find the cell in the browser matrix with the equal to aStr
|
|
|
|
for (j = 0; j < numOfRows; j++)
|
1999-04-18 06:11:29 +00:00
|
|
|
{
|
|
|
|
NSString *cellString;
|
1999-11-09 20:57:15 +00:00
|
|
|
|
|
|
|
selectedCell = [cells objectAtIndex: j];
|
1999-04-18 06:11:29 +00:00
|
|
|
cellString = [selectedCell stringValue];
|
1999-11-09 20:57:15 +00:00
|
|
|
|
1999-06-04 14:02:18 +00:00
|
|
|
if ([cellString isEqualToString: aStr])
|
1999-04-18 06:11:29 +00:00
|
|
|
{
|
1999-11-09 20:57:15 +00:00
|
|
|
[matrix selectCellAtRow: j column: 0];
|
|
|
|
found = YES;
|
|
|
|
break;
|
1999-04-18 06:11:29 +00:00
|
|
|
}
|
|
|
|
}
|
1999-11-09 20:57:15 +00:00
|
|
|
// if unable to find a cell whose title matches aStr return NO
|
|
|
|
if (found == NO)
|
|
|
|
{
|
|
|
|
NSLog (@"NSBrowser: unable to find cell '%@' in column %d\n",
|
|
|
|
aStr, i - 1);
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
// if the cell is not a leaf add a column to the browser for it
|
|
|
|
if (![selectedCell isLeaf])
|
|
|
|
{
|
|
|
|
[self addColumn];
|
|
|
|
[self _performLoadOfColumn: i];
|
|
|
|
[self setLastColumn: i];
|
|
|
|
[self _adjustMatrixOfColumn: i];
|
|
|
|
[self scrollColumnsRightBy: 1];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
1999-04-18 06:11:29 +00:00
|
|
|
}
|
|
|
|
}
|
1999-11-09 20:57:15 +00:00
|
|
|
|
1999-04-18 06:11:29 +00:00
|
|
|
return YES;
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)setPathSeparator: (NSString *)aString
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
[aString retain];
|
|
|
|
[_pathSeparator release];
|
|
|
|
_pathSeparator = aString;
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Arranging an NSBrowser's Components
|
1996-05-30 20:03:15 +00:00
|
|
|
//
|
|
|
|
- (void)tile
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
int num;
|
1999-10-27 13:33:03 +00:00
|
|
|
NSSize bs = [NSCell sizeForBorderType: NSBezelBorder];
|
1997-10-31 01:24:08 +00:00
|
|
|
|
|
|
|
// It is assumed the frame/bounds are set appropriately
|
|
|
|
// before calling this method
|
|
|
|
|
|
|
|
// Determine number of columns and their widths
|
|
|
|
num = _maxVisibleColumns;
|
|
|
|
if (_separatesColumns)
|
|
|
|
_columnSize.width = (frame.size.width - ((num - 1) * COLUMN_SEP))
|
|
|
|
/ (float)num;
|
|
|
|
else
|
|
|
|
_columnSize.width = frame.size.width / (float)num;
|
|
|
|
_columnSize.height = frame.size.height;
|
|
|
|
|
|
|
|
// Horizontal scroller
|
|
|
|
if (_hasHorizontalScroller)
|
|
|
|
{
|
1999-10-27 13:33:03 +00:00
|
|
|
_scrollerRect.origin.x = bs.width;
|
|
|
|
_scrollerRect.origin.y = bs.height;
|
|
|
|
_scrollerRect.size.width = frame.size.width - (2* bs.width);
|
|
|
|
_scrollerRect.size.height = [NSScroller scrollerWidth];
|
|
|
|
_columnSize.height -= _scrollerRect.size.height + 4 + (2 * bs.height);
|
1997-10-31 01:24:08 +00:00
|
|
|
}
|
|
|
|
else
|
1999-10-26 22:37:36 +00:00
|
|
|
_scrollerRect = NSZeroRect;
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1997-10-31 01:24:08 +00:00
|
|
|
// Title
|
|
|
|
if (_isTitled)
|
|
|
|
_columnSize.height -= [self titleHeight];
|
|
|
|
|
|
|
|
if (_columnSize.height < 0)
|
|
|
|
_columnSize.height = 0;
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)drawRect: (NSRect)rect
|
1996-05-30 20:03:15 +00:00
|
|
|
{
|
1997-10-31 01:24:08 +00:00
|
|
|
int i;
|
|
|
|
|
1999-03-24 11:31:06 +00:00
|
|
|
NSRectClip(rect);
|
1997-10-31 01:24:08 +00:00
|
|
|
// Load the first column if not already done
|
|
|
|
if (!_isLoaded)
|
|
|
|
{
|
|
|
|
[self loadColumnZero];
|
|
|
|
[self displayAllColumns];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Loop through the visible columns
|
|
|
|
for (i = _firstVisibleColumn; i <= _lastVisibleColumn; ++i)
|
|
|
|
{
|
|
|
|
// If the column title intersects with the rect to be drawn
|
|
|
|
// then draw that column
|
|
|
|
NSRect r = NSIntersectionRect([self titleFrameOfColumn: i], rect);
|
|
|
|
if (! NSIsEmptyRect(r))
|
|
|
|
[self displayColumn: i];
|
|
|
|
}
|
1999-10-27 13:33:03 +00:00
|
|
|
|
|
|
|
if (_hasHorizontalScroller)
|
|
|
|
{
|
|
|
|
NSRect scrollerBorderRect = _scrollerRect;
|
|
|
|
NSSize bs = [NSCell sizeForBorderType: NSBezelBorder];
|
|
|
|
|
|
|
|
scrollerBorderRect.origin.x = 0;
|
|
|
|
scrollerBorderRect.origin.y = 0;
|
|
|
|
scrollerBorderRect.size.width += 2 * bs.width;
|
|
|
|
scrollerBorderRect.size.height += 2 * bs.height;
|
|
|
|
|
|
|
|
// Draw the horizontal scroller border
|
|
|
|
NSDrawGrayBezel (scrollerBorderRect, rect);
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1997-10-31 01:24:08 +00:00
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
// Displaying the Control and Cell
|
1997-10-31 01:24:08 +00:00
|
|
|
//
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)drawCell: (NSCell *)aCell
|
1996-05-30 20:03:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)drawCellInside: (NSCell *)aCell
|
1996-05-30 20:03:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)selectCell: (NSCell *)aCell
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)updateCell: (NSCell *)aCell
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)updateCellInside: (NSCell *)aCell
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
}
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// NSCoding protocol
|
|
|
|
//
|
1999-03-02 08:58:30 +00:00
|
|
|
- (void) encodeWithCoder: (NSCoder*)aCoder
|
1996-05-30 20:03:15 +00:00
|
|
|
{
|
1999-02-19 20:19:58 +00:00
|
|
|
[super encodeWithCoder: aCoder];
|
1996-05-30 20:03:15 +00:00
|
|
|
}
|
|
|
|
|
1999-03-02 08:58:30 +00:00
|
|
|
- (id) initWithCoder: (NSCoder*)aDecoder
|
1996-05-30 20:03:15 +00:00
|
|
|
{
|
1999-02-19 20:19:58 +00:00
|
|
|
[super initWithCoder: aDecoder];
|
1996-05-30 20:03:15 +00:00
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
1997-10-31 01:24:08 +00:00
|
|
|
|
|
|
|
//
|
|
|
|
// Private NSBrowser methods
|
|
|
|
//
|
|
|
|
@implementation NSBrowser (Private)
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)_adjustMatrixOfColumn: (int)column
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
1999-04-06 14:09:13 +00:00
|
|
|
NSBrowserColumn *bc;
|
|
|
|
NSScrollView *sc;
|
|
|
|
id matrix;
|
|
|
|
NSSize cs, ms;
|
|
|
|
NSRect mr;
|
|
|
|
|
|
|
|
if (column >= (int)[_browserColumns count])
|
|
|
|
return;
|
|
|
|
|
|
|
|
bc = [_browserColumns objectAtIndex: column];
|
|
|
|
sc = [bc columnScrollView];
|
|
|
|
matrix = [bc columnMatrix];
|
|
|
|
|
|
|
|
// Adjust matrix to fit in scrollview if column has been loaded
|
|
|
|
if (sc && matrix && [bc isLoaded])
|
|
|
|
{
|
|
|
|
cs = [sc contentSize];
|
|
|
|
ms = [matrix cellSize];
|
|
|
|
ms.width = cs.width;
|
|
|
|
[matrix setCellSize: ms];
|
|
|
|
mr = [matrix frame];
|
|
|
|
|
|
|
|
// matrix smaller than scrollview's content
|
|
|
|
if (mr.size.height < cs.height)
|
|
|
|
{
|
|
|
|
// view requires origin adjustment for it to appear at top
|
|
|
|
mr.origin.y = cs.height;
|
|
|
|
[matrix setFrame: mr];
|
|
|
|
}
|
|
|
|
|
|
|
|
[sc setDocumentView: matrix];
|
|
|
|
}
|
1997-10-31 01:24:08 +00:00
|
|
|
}
|
|
|
|
|
1999-03-16 10:53:42 +00:00
|
|
|
- (void)_adjustScrollerFrameOfColumn: (int)column force: (BOOL)flag
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
// Only if we've loaded the first column
|
|
|
|
if ((_isLoaded) || (flag))
|
|
|
|
{
|
|
|
|
NSBrowserColumn *bc;
|
|
|
|
NSScrollView *sc;
|
|
|
|
|
|
|
|
if (column >= (int)[_browserColumns count])
|
|
|
|
return;
|
|
|
|
|
|
|
|
bc = [_browserColumns objectAtIndex: column];
|
|
|
|
sc = [bc columnScrollView];
|
|
|
|
|
|
|
|
// Set the scrollview frame
|
|
|
|
// Only set before the column has been loaded
|
|
|
|
// Or we are being forced
|
|
|
|
if (sc && ((![bc isLoaded]) || flag))
|
|
|
|
[sc setFrame: [self frameOfInsideOfColumn: column]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)_adjustScrollerFrames: (BOOL)force
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
int i, count = [_browserColumns count];
|
|
|
|
|
|
|
|
// Loop through the columns
|
|
|
|
for (i = 0;i < count; ++i)
|
|
|
|
{
|
|
|
|
// If its a visible column
|
|
|
|
if ((i >= _firstVisibleColumn) && (i <= _lastVisibleColumn))
|
|
|
|
{
|
|
|
|
NSBrowserColumn *bc = [_browserColumns objectAtIndex: i];
|
|
|
|
id sc = [bc columnScrollView];
|
|
|
|
|
|
|
|
// Add as subview if necessary
|
|
|
|
if (sc)
|
|
|
|
if (![sc superview])
|
|
|
|
[self addSubview: sc];
|
|
|
|
|
|
|
|
[self _adjustScrollerFrameOfColumn: i force: force];
|
|
|
|
[self _adjustMatrixOfColumn: i];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-06-04 14:02:18 +00:00
|
|
|
NSBrowserColumn *bc = [_browserColumns objectAtIndex: i];
|
|
|
|
id sc = [bc columnScrollView];
|
1997-10-31 01:24:08 +00:00
|
|
|
|
|
|
|
// Remove it from its superview if it has one
|
|
|
|
if (sc)
|
1999-06-04 14:02:18 +00:00
|
|
|
{
|
|
|
|
if ([sc superview])
|
|
|
|
{
|
|
|
|
[sc removeFromSuperview];
|
|
|
|
}
|
|
|
|
}
|
1997-10-31 01:24:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)_performLoadOfColumn: (int)column
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
NSBrowserColumn *bc = [_browserColumns objectAtIndex: column];
|
|
|
|
|
|
|
|
// Loading is different based upon passive/active delegate
|
|
|
|
if (_passiveDelegate)
|
|
|
|
{
|
|
|
|
// Ask the delegate for the number of rows
|
|
|
|
int n = [_browserDelegate browser: self numberOfRowsInColumn: column];
|
|
|
|
|
|
|
|
if (_reusesColumns)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
id matrix;
|
|
|
|
id sc = [bc columnScrollView];
|
|
|
|
NSRect matrixRect = {{0, 0}, {100, 100}};
|
|
|
|
int i;
|
|
|
|
|
1999-04-06 14:09:13 +00:00
|
|
|
// create a new col matrix
|
|
|
|
matrix = [[[_browserMatrixClass alloc]
|
1998-07-14 17:51:44 +00:00
|
|
|
initWithFrame: matrixRect
|
|
|
|
mode: NSListModeMatrix
|
|
|
|
prototype: _browserCellPrototype
|
|
|
|
numberOfRows: n
|
|
|
|
numberOfColumns: 1]
|
|
|
|
autorelease];
|
1997-10-31 01:24:08 +00:00
|
|
|
[matrix setAllowsEmptySelection: _allowsEmptySelection];
|
|
|
|
if (!_allowsMultipleSelection)
|
|
|
|
[matrix setMode: NSRadioModeMatrix];
|
|
|
|
[matrix setTarget: self];
|
1999-08-31 09:19:39 +00:00
|
|
|
[matrix setAction: @selector(doClick:)];
|
|
|
|
[matrix setDoubleAction: @selector(doDoubleClick:)];
|
1997-10-31 01:24:08 +00:00
|
|
|
|
1999-04-06 14:09:13 +00:00
|
|
|
// set new col matrix and release old
|
|
|
|
[bc setColumnMatrix: matrix];
|
1997-10-31 01:24:08 +00:00
|
|
|
[sc setDocumentView: matrix];
|
|
|
|
|
|
|
|
// Now loop through the cells and load each one
|
|
|
|
for (i = 0;i < n; ++i)
|
|
|
|
[self loadedCellAtRow: i column: column];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (_reusesColumns)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
id matrix;
|
|
|
|
id sc = [bc columnScrollView];
|
|
|
|
NSRect matrixRect = {{0, 0}, {100, 100}};
|
|
|
|
|
1999-04-06 14:09:13 +00:00
|
|
|
// create a new col matrix
|
|
|
|
matrix = [[[_browserMatrixClass alloc]
|
1998-07-14 17:51:44 +00:00
|
|
|
initWithFrame: matrixRect
|
|
|
|
mode: NSListModeMatrix
|
|
|
|
prototype: _browserCellPrototype
|
|
|
|
numberOfRows: 0
|
|
|
|
numberOfColumns: 0]
|
|
|
|
autorelease];
|
1997-10-31 01:24:08 +00:00
|
|
|
[matrix setAllowsEmptySelection: _allowsEmptySelection];
|
|
|
|
if (!_allowsMultipleSelection)
|
|
|
|
[matrix setMode: NSRadioModeMatrix];
|
|
|
|
[matrix setTarget: self];
|
1999-08-31 09:19:39 +00:00
|
|
|
[matrix setAction: @selector(doClick:)];
|
|
|
|
[matrix setDoubleAction: @selector(doDoubleClick:)];
|
1997-10-31 01:24:08 +00:00
|
|
|
|
1999-04-06 14:09:13 +00:00
|
|
|
// set new col matrix and release old
|
|
|
|
[bc setColumnMatrix: matrix];
|
1997-10-31 01:24:08 +00:00
|
|
|
[sc setDocumentView: matrix];
|
|
|
|
|
|
|
|
// Tell the delegate to create the rows
|
1999-04-06 14:09:13 +00:00
|
|
|
[_browserDelegate browser: self
|
|
|
|
createRowsForColumn: column
|
|
|
|
inMatrix: matrix];
|
1997-10-31 01:24:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[bc setIsLoaded: YES];
|
1999-04-06 14:09:13 +00:00
|
|
|
[self setNeedsDisplayInRect: [self frameOfColumn: column]];
|
1997-10-31 01:24:08 +00:00
|
|
|
}
|
|
|
|
|
1999-02-19 20:19:58 +00:00
|
|
|
- (void)_unloadFromColumn: (int)column
|
1997-10-31 01:24:08 +00:00
|
|
|
{
|
|
|
|
int i, count = [_browserColumns count];
|
|
|
|
|
|
|
|
for (i = column; i < count; ++i)
|
|
|
|
{
|
|
|
|
NSBrowserColumn *bc = [_browserColumns objectAtIndex: i];
|
|
|
|
if ([bc isLoaded])
|
|
|
|
{
|
|
|
|
id sc = [bc columnScrollView];
|
|
|
|
|
|
|
|
// Make the column appear empty
|
|
|
|
// by removing the matrix
|
|
|
|
[sc setDocumentView: [bc emptyView]];
|
|
|
|
|
|
|
|
[bc setIsLoaded: NO];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-03-16 10:53:42 +00:00
|
|
|
- (void) resizeSubviewsWithOldSize: (NSSize)oldSize
|
1998-11-25 17:16:48 +00:00
|
|
|
{
|
1999-03-16 10:53:42 +00:00
|
|
|
[super resizeSubviewsWithOldSize: oldSize];
|
|
|
|
[self tile];
|
|
|
|
[self _adjustScrollerFrames: YES];
|
1999-10-26 22:37:36 +00:00
|
|
|
[_horizontalScroller setFrame: _scrollerRect];
|
1998-11-25 17:16:48 +00:00
|
|
|
}
|
|
|
|
|
1997-10-31 01:24:08 +00:00
|
|
|
@end
|