This is MiscSliderCell.m in view mode; [Download] [Up]
//
// MiscSliderCell.m -- a TextFieldCell subclass that adds a SliderCell
// Written by David Fedchenko. Copyright 1994 by David Fedchenko.
// Version 1.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 "MiscSliderCell.h"
#import "MiscSliderField.h"
@implementation MiscSliderCell
- initTextCell:(const char *)sz
{
[super initTextCell:sz];
layout = MSC_LEFT;
split = 0.5;
limitMinValue = 0;
limitMaxValue = 100;
limitMinBound = limitMinValue;
limitMaxBound = limitMaxValue;
fExpandMin = fExpandMax = NO;
fValidRect = NO;
idSlider = [[[[SliderCell allocFromZone:[self zone]] init]
setTarget:self]
setAction:@selector(moved:)];
[[idSlider setContinuous:YES]
sendActionOn:NX_MOUSEDOWNMASK | NX_MOUSEDRAGGEDMASK];
[[idSlider setMinValue:limitMinValue] setMaxValue:limitMaxValue];
[[[self setBezeled:YES] setEditable:YES] setContinuous:NO];
return self;
}
- copyFromZone:(NXZone *)zone
{
MiscSliderCell * idNew = [super copyFromZone:zone];
if (idNew)
{
if ((idNew->idSlider = [idSlider copyFromZone:zone]))
{
[idNew->idSlider setTarget:idNew];
}
}
return idNew;
}
- textRect:(NXRect *)rect
{
float width = rect->size.width;
switch (layout)
{
case MSC_LEFT:
rect->size.width *= split;
rect->size.width = MIN(width - MSC_MINWIDTH, rect->size.width);
rect->size.width -= (MSC_SPACING / 2);
break;
case MSC_RIGHT:
rect->size.width *= split;
rect->size.width = MAX(MSC_MINWIDTH, rect->size.width);
rect->size.width = MIN(width - MSC_MINWIDTH, rect->size.width);
rect->size.width -= (MSC_SPACING / 2);
rect->origin.x = width - rect->size.width;
break;
case MSC_BELOWLEFT:
case MSC_BELOWCENTER:
case MSC_BELOWRIGHT:
// the view is flipped
rect->origin.y += MSC_WIDTH + MSC_SPACING;
// fall through
case MSC_ABOVELEFT:
case MSC_ABOVECENTER:
case MSC_ABOVERIGHT:
// the view is flipped
rect->size.height -= MSC_WIDTH + MSC_SPACING;
rect->size.width *= split;
rect->size.width = MAX(MSC_MINWIDTH, rect->size.width);
rect->size.width = MIN(width, rect->size.width);
switch (layout)
{
case MSC_ABOVECENTER:
case MSC_BELOWCENTER:
rect->origin.x += (width - rect->size.width) / 2;
break;
case MSC_ABOVERIGHT:
case MSC_BELOWRIGHT:
rect->origin.x += width - rect->size.width;
break;
}
break;
}
return self;
}
- sliderRect:(NXRect *)rect
{
float width = rect->size.width;
switch (layout)
{
case MSC_LEFT:
rect->size.width *= (1 - split);
rect->size.width = MAX(MSC_MINWIDTH, rect->size.width);
rect->size.width = MIN(width - MSC_MINWIDTH, rect->size.width);
rect->size.width -= (MSC_SPACING / 2);
rect->origin.x = width - rect->size.width;
rect->origin.y += (rect->size.height - MSC_WIDTH) / 2;
rect->size.height = MSC_WIDTH;
break;
case MSC_RIGHT:
rect->size.width *= (1 - split);
rect->size.width = MAX(MSC_MINWIDTH, rect->size.width);
rect->size.width = MIN(width - MSC_MINWIDTH, rect->size.width);
rect->size.width -= (MSC_SPACING / 2);
rect->origin.y += (rect->size.height - MSC_WIDTH) / 2;
rect->size.height = MSC_WIDTH;
break;
case MSC_BELOWLEFT:
case MSC_BELOWCENTER:
case MSC_BELOWRIGHT:
// the view is flipped
rect->size.height = MSC_WIDTH;
break;
case MSC_ABOVELEFT:
case MSC_ABOVECENTER:
case MSC_ABOVERIGHT:
// the view is flipped
rect->origin.y += rect->size.height - MSC_WIDTH;
rect->size.height = MSC_WIDTH;
break;
}
return self;
}
- drawInside:(const NXRect *)aRect inView:controlView
{
if (!fValidRect)
{
rectFrame = *aRect;
[self textRect:&rectFrame];
}
[super drawInside:&rectFrame inView:controlView];
return self;
}
- drawSelf:(const NXRect *)cellFrame inView:controlView
{
NXRect rectSlider;
rectFrame = *cellFrame;
rectSlider = *cellFrame;
[self textRect:&rectFrame];
[self sliderRect:&rectSlider];
fValidRect = YES;
[super drawSelf:&rectFrame inView:controlView];
fValidRect = NO;
[idSlider drawSelf:&rectSlider inView:controlView];
return self;
}
- resetCursorRect:(const NXRect *)cellFrame inView:aView
{
NXRect rect = *cellFrame;
[self textRect:&rect];
[super resetCursorRect:&rect inView:aView];
return self;
}
- calcCellSize:(NXSize *)theSize inRect:(const NXRect *)aRect
{
[super calcCellSize:theSize inRect:aRect];
switch (layout)
{
case MSC_LEFT:
case MSC_RIGHT:
theSize->width = MSC_MINWIDTH * 2 + MSC_SPACING;
break;
case MSC_ABOVELEFT:
case MSC_ABOVECENTER:
case MSC_ABOVERIGHT:
case MSC_BELOWLEFT:
case MSC_BELOWCENTER:
case MSC_BELOWRIGHT:
theSize->width = MSC_MINWIDTH;
theSize->height += MSC_WIDTH + MSC_SPACING;
break;
}
return self;
}
- edit:(const NXRect *)aRect inView:controlView editor:textObj
delegate:anObject event:(NXEvent *)theEvent
{
NXRect rectT = *aRect;
NXRect rectS = *aRect;
NXPoint p = theEvent->location;
[self textRect:&rectT];
[self sliderRect:&rectS];
[controlView convertPoint:&p fromView:nil];
if (NXPointInRect(&p, &rectT))
{
[super edit:&rectT inView:controlView editor:textObj
delegate:anObject event:theEvent];
}
else if (NXPointInRect(&p, &rectS))
{
id sl = stringList;
if (!sl)
{
if ([[self controlView] class] == [MiscSliderField class])
{
sl = [[self controlView] stringList];
}
}
if (sl)
{
[idSlider setMinValue:0];
[idSlider setMaxValue:[sl count]];
}
[controlView lockFocus];
[idSlider trackMouse:theEvent inRect:NULL ofView:controlView];
[controlView unlockFocus];
[NXApp sendAction:action to:target from:controlView];
}
return self;
}
- getDrawRect:(NXRect *)theRect
{
[self textRect:theRect];
[super getDrawRect:theRect];
return self;
}
- getTitleRect:(NXRect *)theRect
{
[self textRect:theRect];
[super getTitleRect:theRect];
return self;
}
- highlight:(const NXRect *)cellFrame inView:aView lit:(BOOL)flag
{
NXRect rect = *cellFrame;
[self textRect:&rect];
[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;
[self textRect:&rect];
[super select:&rect inView:aView editor:aTextObject
delegate:anObject start:selStart length:selLength];
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] == [MiscSliderField 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
{
aDouble = MIN(aDouble, limitMaxValue);
aDouble = MAX(aDouble, limitMinValue);
if (!fFeedback)
{
if (fExpandMin && (aDouble < limitMinBound))
{
limitMinBound = aDouble;
[idSlider setMinValue:aDouble];
}
if (fExpandMax && (aDouble > limitMaxBound))
{
limitMaxBound = aDouble;
[idSlider setMaxValue:aDouble];
}
}
if (fInt)
{
aDouble = rint(aDouble);
}
actualValue = aDouble;
[super setDoubleValue:aDouble];
if (!fFeedback)
{
[idSlider setDoubleValue:aDouble];
[[self controlView] updateCell:self];
}
}
fLoop = NO;
return self;
}
- setStringValue:(const char *)aString
{
double value;
[super setStringValue:aString];
if (!fLoop)
{
sscanf(aString, "%lf", &value);
[self setDoubleValue:value];
}
return self;
}
- takeDoubleValueFrom:sender
{
[self setDoubleValue:[sender doubleValue]];
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;
}
- moved:sender
{
fFeedback = YES;
[self setDoubleValue:[idSlider doubleValue]];
fFeedback = NO;
if ([self isContinuous])
{
[NXApp sendAction:action to:target from:[self controlView]];
}
return self;
}
- setMinValue:(double)value
{
limitMinValue = value;
if (!fExpandMin && !stringList)
{
[idSlider setMinValue:value];
[self setDoubleValue:MAX(actualValue, value)];
}
return self;
}
- setMaxValue:(double)value
{
limitMaxValue = value;
if (!fExpandMax && !stringList)
{
[idSlider setMaxValue:value];
[self setDoubleValue:MIN(actualValue, value)];
}
return self;
}
- setMinBoundary:(double)value
{
limitMinBound = value;
if (fExpandMin && !stringList)
{
[idSlider setMinValue:value];
[self setDoubleValue:MAX(actualValue, value)];
}
return self;
}
- setMaxBoundary:(double)value
{
limitMaxBound = value;
if (fExpandMin && !stringList)
{
[idSlider setMinValue:value];
[self setDoubleValue:MIN(actualValue, value)];
}
return self;
}
-(double) minValue
{
return limitMinValue;
}
-(double) maxValue
{
return limitMaxValue;
}
-(double) minBoundary
{
return limitMinBound;
}
-(double) maxBoundary
{
return limitMaxBound;
}
- setExpandMin:(BOOL)flag
{
fExpandMin = flag;
if (flag)
{
if (!stringList)
{
[idSlider setMinValue:limitMinBound];
[self setDoubleValue:MAX(actualValue, limitMinBound)];
}
}
else
{
if (!stringList)
{
[idSlider setMinValue:limitMinValue];
[self setDoubleValue:actualValue];
}
}
return self;
}
- setExpandMax:(BOOL)flag
{
fExpandMax = flag;
if (flag)
{
if (!stringList)
{
[idSlider setMaxValue:limitMaxBound];
[self setDoubleValue:MIN(actualValue, limitMaxBound)];
}
}
else
{
if (!stringList)
{
[idSlider setMaxValue:limitMaxValue];
[self setDoubleValue:actualValue];
}
}
return self;
}
-(BOOL) expandMin
{
return fExpandMin;
}
-(BOOL) expandMax
{
return fExpandMax;
}
- setPosition:(int)where
{
layout = where;
return self;
}
- setSplit:(int)percent
{
split = percent / 100.0;
return self;
}
- setIntegerOnly:(BOOL)flag
{
fInt = flag;
return self;
}
-(int) position
{
return layout;
}
-(int) split
{
return (int)(split * 100);
}
-(BOOL) integerOnly
{
return fInt;
}
- setStringList:anObject
{
if (anObject && [anObject respondsTo:@selector(stringAt:)] &&
[anObject respondsTo:@selector(count)])
{
stringList = anObject;
[self setEditable:NO];
[self setDoubleValue:actualValue];
}
else
{
[self setMinBoundary:limitMinBound];
[self setMaxBoundary:limitMaxBound];
[self setMinValue:limitMinValue];
[self setMaxValue:limitMaxValue];
}
return self;
}
- stringList
{
return stringList;
}
- write:(NXTypedStream *)stream
{
[super write:stream];
NXWriteTypes(stream, "ifd", &layout, &split, &actualValue);
NXWriteTypes(stream, "dd", &limitMinValue, &limitMaxValue);
NXWriteTypes(stream, "dd", &limitMinBound, &limitMaxBound);
NXWriteType(stream, @encode(BOOL), &fExpandMin);
NXWriteType(stream, @encode(BOOL), &fExpandMax);
NXWriteType(stream, @encode(BOOL), &fInt);
NXWriteObject(stream, idSlider);
return self;
}
- read:(NXTypedStream *)stream
{
[super read:stream];
NXReadTypes(stream, "ifd", &layout, &split, &actualValue);
NXReadTypes(stream, "dd", &limitMinValue, &limitMaxValue);
NXReadTypes(stream, "dd", &limitMinBound, &limitMaxBound);
NXReadType(stream, @encode(BOOL), &fExpandMin);
NXReadType(stream, @encode(BOOL), &fExpandMax);
NXReadType(stream, @encode(BOOL), &fInt);
idSlider = 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.