home *** CD-ROM | disk | FTP | other *** search
- //
- // 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
- {
- return (int)actualValue;
- }
-
- -(float) floatValue
- {
- return (float)actualValue;
- }
-
- -(double) doubleValue
- {
- 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
-