This is MiscValueCell.m in view mode; [Download] [Up]
//
// MiscValueCell.m -- a TextFieldCell subclass that adds arrow buttons
// Written by David Fedchenko. Copyright 1994 by David Fedchenko.
// Version 2.0 All rights reserved.
//
// This notice may not be removed from this source code.
//
// This object is included in the MiscKit by permission from the author
// and its use is governed by the MiscKit license, found in the file
// "LICENSE.rtf" in the MiscKit distribution. Please refer to that file
// for a list of all applicable permissions and restrictions.
//
#import "MiscValueCell.h"
#import "MiscValueField.h"
@implementation MiscValueCell
- initTextCell:(const char *)sz
{
[super initTextCell:sz];
actualValue = 0;
limitMinValue = 0;
limitMaxValue = 100;
limitMinBound = 0;
limitMaxBound = 100;
fExpandLow = NO;
fExpandHigh = NO;
sizeStep = 1;
sizeAltStep = 10;
fLoop = fValidRect = NO;
// Set up the NXImages so they can draw without the files.
// This only works it's magic for cells set up in IB since
// a regular initialization will look for the images.
if (![NXImage findImageNamed:"MVCUpImage"])
{
char buf[MAXPATHLEN + 1];
NXImage * idImage;
[[NXBundle bundleForClass:[self class]] getPath:buf
forResource:"MVCUp" ofType:"tiff"];
idImage = [[[NXImage alloc] init] setDataRetained:YES];
[idImage loadFromFile:buf];
[idImage setName:"MVCUpImage"];
[[NXBundle bundleForClass:[self class]] getPath:buf
forResource:"MVCDown" ofType:"tiff"];
idImage = [[[NXImage alloc] init] setDataRetained:YES];
[idImage loadFromFile:buf];
[idImage setName:"MVCDownImage"];
}
idUp = [[[[ButtonCell allocFromZone:[self zone]]
initIconCell:"MVCUpImage"]
setTarget:self]
setAction:@selector(increment:)];
[[idUp setContinuous:YES]
sendActionOn:NX_MOUSEDOWNMASK | NX_PERIODICMASK];
idDown = [[[[ButtonCell allocFromZone:[self zone]]
initIconCell:"MVCDownImage"]
setTarget:self]
setAction:@selector(decrement:)];
[[idDown setContinuous:YES]
sendActionOn:NX_MOUSEDOWNMASK | NX_PERIODICMASK];
[[[self setBezeled:YES] setEditable:YES] setContinuous:NO];
return self;
}
- copyFromZone:(NXZone *)zone
{
MiscValueCell * idNew = [super copyFromZone:zone];
if (idNew)
{
if ((idNew->idUp = [idUp copyFromZone:zone]))
{
[idNew->idUp setTarget:idNew];
}
if ((idNew->idDown = [idDown copyFromZone:zone]))
{
[idNew->idDown setTarget:idNew];
}
}
return idNew;
}
- drawInside:(const NXRect *)aRect inView:controlView
{
if (!fValidRect)
{
rectFrame = *aRect;
rectFrame.size.width -= 17;
}
[super drawInside:&rectFrame inView:controlView];
return self;
}
- drawSelf:(const NXRect *)cellFrame inView:controlView
{
rectFrame = *cellFrame;
rectFrame.size.width -= 17;
fValidRect = YES;
[super drawSelf:&rectFrame inView:controlView];
fValidRect = NO;
rectFrame.origin.x += rectFrame.size.width + 1;
rectFrame.size.width = 16;
rectFrame.size.height /= 2;
[idUp drawSelf:&rectFrame inView:controlView];
rectFrame.origin.y += rectFrame.size.height;
[idDown drawSelf:&rectFrame inView:controlView];
return self;
}
- resetCursorRect:(const NXRect *)cellFrame inView:aView
{
NXRect rect = *cellFrame;
rect.size.width -= 17;
[super resetCursorRect:&rect inView:aView];
return self;
}
- calcCellSize:(NXSize *)theSize inRect:(const NXRect *)aRect
{
NXRect rect = *aRect;
rect.size.width -= 17;
[super calcCellSize:theSize inRect:&rect];
theSize->height = MAX(21, theSize->height);
theSize->width += 17;
return self;
}
- edit:(const NXRect *)aRect inView:controlView editor:textObj
delegate:anObject event:(NXEvent *)theEvent
{
NXRect rect = *aRect;
NXPoint p = theEvent->location;
id idWhich;
BOOL fR;
BOOL fSpin;
int oldMask;
float delay;
float interv;
rect.size.width -= 17;
[controlView convertPoint:&p fromView:nil];
if (NXPointInRect(&p, &rect))
{
[super edit:&rect inView:controlView editor:textObj
delegate:anObject event:theEvent];
}
else
{
rect = *aRect;
rect.origin.x += rect.size.width - 16;
rect.size.width = 16;
rect.size.height /= 2;
fAltKeyDown = theEvent->flags & NX_ALTERNATEMASK;
if (p.y < aRect->origin.y + (aRect->size.height / 2))
{
idWhich = idUp;
}
else
{
rect.origin.y += rect.size.height;
idWhich = idDown;
}
oldMask = [[controlView window] addToEventMask:NX_MOUSEDRAGGEDMASK];
[controlView lockFocus];
[idWhich getPeriodicDelay:&delay andInterval:&interv];
fSpin = YES;
do
{
[idWhich highlight:&rect inView:controlView lit:YES];
fR = [idWhich trackMouse:theEvent inRect:&rect ofView:controlView];
[idWhich highlight:&rect inView:controlView lit:NO];
[controlView display:&rect :1];
[idWhich setPeriodicDelay:0.0 andInterval:interv];
if (fR)
{
fSpin = NO;
}
else
{
theEvent = [NXApp
getNextEvent:NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK];
if (theEvent->type == NX_MOUSEUP)
{
fSpin = NO;
}
}
} while (fSpin);
[idWhich setPeriodicDelay:delay andInterval:interv];
[controlView unlockFocus];
[[controlView window] setEventMask:oldMask];
[NXApp sendAction:action to:target from:controlView];
}
return self;
}
- getDrawRect:(NXRect *)theRect
{
theRect->size.width -= 17;
[super getDrawRect:theRect];
return self;
}
- getTitleRect:(NXRect *)theRect
{
theRect->size.width -= 17;
[super getTitleRect:theRect];
return self;
}
- highlight:(const NXRect *)cellFrame inView:aView lit:(BOOL)flag
{
NXRect rect = *cellFrame;
rect.size.width -= 17;
[super highlight:&rect inView:aView lit:flag];
return self;
}
- select:(const NXRect *)aRect inView:aView editor:aTextObject
delegate:anObject start:(int)selStart length:(int)selLength
{
NXRect rect = *aRect;
rect.size.width -= 17;
[super select:&rect inView:aView editor:aTextObject
delegate:anObject start:selStart length:selLength];
return self;
}
- setBezeled:(BOOL)flag
{
[super setBezeled:flag];
[idUp setBordered:flag];
[idDown setBordered:flag];
return self;
}
- setBordered:(BOOL)flag
{
[super setBordered:flag];
[idUp setBordered:NO];
[idDown setBordered:NO];
return self;
}
- setEditable:(BOOL)flag
{
[super setEditable:flag];
if (!flag)
{
[self setSelectable:YES];
}
return self;
}
- setIntValue:(int)anInt
{
[self setDoubleValue:(double)anInt];
return self;
}
- setFloatValue:(float)aFloat
{
[self setDoubleValue:(double)aFloat];
return self;
}
- setDoubleValue:(double)aDouble
{
const char * sz;
id sl = stringList;
fLoop = YES; // so setStringValue doesn't get loopy
if (!sl)
{
if ([[self controlView] class] == [MiscValueField class])
{
sl = [[self controlView] stringList];
}
}
if (sl)
{
int indx = (int)aDouble;
int cnt = (int)limitMaxValue;
cnt = [sl count] - 1;
indx = MAX(indx, 0);
indx = MIN(indx, cnt);
actualValue = indx;
sz = (char *)[sl stringAt:indx];
if (sz)
{
[super setStringValue:sz];
}
else
{
[super setDoubleValue:actualValue];
}
}
else
{
actualValue = MIN(aDouble, limitMaxValue);
actualValue = MAX(actualValue, limitMinValue);
if (fExpandLow && (actualValue < limitMinBound))
{
limitMinBound = actualValue;
}
if (fExpandHigh && (actualValue > limitMaxBound))
{
limitMaxBound = actualValue;
}
[super setDoubleValue:actualValue];
}
fLoop = NO;
return self;
}
- setStringValue:(const char *)aString
{
double value;
[super setStringValue:aString];
if (!fLoop)
{
sscanf(aString, "%lf", &value);
[self setDoubleValue:value];
}
return self;
}
-(int) intValue
{
[[self controlView] validateEditing];
return (int)actualValue;
}
-(float) floatValue
{
[[self controlView] validateEditing];
return (float)actualValue;
}
-(double) doubleValue
{
[[self controlView] validateEditing];
return actualValue;
}
- increment:sender
{
double val;
id sl = stringList;
if (!sl)
{
if ([[self controlView] class] == [MiscValueField class])
{
sl = [[self controlView] stringList];
}
}
if (sl)
{
[self setIntValue:[self intValue] + ((fAltKeyDown) ? sizeAltStep : 1)];
}
else
{
val = [self doubleValue] + ((fAltKeyDown) ? sizeAltStep : sizeStep);
if (fExpandHigh && (val > limitMaxBound))
{
val = limitMaxBound;
}
[self setDoubleValue:val];
}
if ([self isContinuous])
{
[NXApp sendAction:action to:target from:[self controlView]];
}
return self;
}
- decrement:sender
{
double val;
id sl = stringList;
if (!sl)
{
if ([[self controlView] class] == [MiscValueField class])
{
sl = [[self controlView] stringList];
}
}
if (sl)
{
[self setIntValue:[self intValue] - ((fAltKeyDown) ? sizeAltStep : 1)];
}
else
{
val = [self doubleValue] - ((fAltKeyDown) ? sizeAltStep : sizeStep);
if (fExpandLow && (val < limitMinBound))
{
val = limitMinBound;
}
[self setDoubleValue:val];
}
if ([self isContinuous])
{
[NXApp sendAction:action to:target from:[self controlView]];
}
return self;
}
- setMinValue:(double)value
{
limitMinValue = value;
return self;
}
- setMaxValue:(double)value
{
limitMaxValue = value;
return self;
}
- setMinBoundary:(double)value
{
limitMinBound = value;
return self;
}
- setMaxBoundary:(double)value
{
limitMaxBound = value;
return self;
}
-(double) minValue
{
return limitMinValue;
}
-(double) maxValue
{
return limitMaxValue;
}
-(double) minBoundary
{
return limitMinBound;
}
-(double) maxBoundary
{
return limitMaxBound;
}
- setStepSize:(double)size
{
sizeStep = size;
return self;
}
- setAltStepSize:(double)size
{
sizeAltStep = size;
return self;
}
-(double) stepSize
{
return sizeStep;
}
-(double) altStepSize
{
return sizeAltStep;
}
- setExpandMin:(BOOL)flag
{
fExpandLow = flag;
[self setDoubleValue:actualValue];
return self;
}
- setExpandMax:(BOOL)flag
{
fExpandHigh = flag;
[self setDoubleValue:actualValue];
return self;
}
-(BOOL) expandMin
{
return fExpandLow;
}
-(BOOL) expandMax
{
return fExpandHigh;
}
- setStringList:anObject
{
if (anObject && [anObject respondsTo:@selector(stringAt:)] &&
[anObject respondsTo:@selector(count)])
{
stringList = anObject;
[self setEditable:NO];
[self setIntValue:(int)actualValue];
}
return self;
}
- stringList
{
return stringList;
}
- write:(NXTypedStream *)stream
{
[super write:stream];
NXWriteTypes(stream, "ddd", &actualValue, &sizeStep, &sizeAltStep);
NXWriteTypes(stream, "dd", &limitMinValue, &limitMaxValue);
NXWriteTypes(stream, "dd", &limitMinBound, &limitMaxBound);
NXWriteType(stream, @encode(BOOL), &fExpandLow);
NXWriteType(stream, @encode(BOOL), &fExpandHigh);
NXWriteObject(stream, idUp);
NXWriteObject(stream, idDown);
return self;
}
- read:(NXTypedStream *)stream
{
[super read:stream];
NXReadTypes(stream, "ddd", &actualValue, &sizeStep, &sizeAltStep);
NXReadTypes(stream, "dd", &limitMinValue, &limitMaxValue);
NXReadTypes(stream, "dd", &limitMinBound, &limitMaxBound);
NXReadType(stream, @encode(BOOL), &fExpandLow);
NXReadType(stream, @encode(BOOL), &fExpandHigh);
idUp = NXReadObject(stream);
idDown = NXReadObject(stream);
return self;
}
- awake
{
[self setDoubleValue:actualValue];
return self;
}
- awakeFromNib
{
[self awake];
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.