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.