home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.mdf / SourceCode / MiscKit1.2.6 / Palettes / MiscValueFieldPalette / MiscValueField.subproj / MiscValueCell.m < prev    next >
Encoding:
Text File  |  1994-05-28  |  13.1 KB  |  636 lines

  1. //
  2. //    MiscValueCell.m -- a TextFieldCell subclass that adds arrow buttons
  3. //       Written by David Fedchenko. Copyright 1994 by David Fedchenko.
  4. //                    Version 2.0  All rights reserved.
  5. //
  6. //        This notice may not be removed from this source code.
  7. //
  8. //    This object is included in the MiscKit by permission from the author
  9. //    and its use is governed by the MiscKit license, found in the file
  10. //    "LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
  11. //    for a list of all applicable permissions and restrictions.
  12. //    
  13.  
  14. #import "MiscValueCell.h"
  15. #import "MiscValueField.h"
  16.  
  17. @implementation MiscValueCell
  18.  
  19. - initTextCell:(const char *)sz
  20.     {
  21.     [super initTextCell:sz];
  22.     
  23.     actualValue = 0;
  24.     limitMinValue = 0;
  25.     limitMaxValue = 100;
  26.     limitMinBound = 0;
  27.     limitMaxBound = 100;
  28.     fExpandLow = NO;
  29.     fExpandHigh = NO;
  30.     sizeStep = 1;
  31.     sizeAltStep = 10;
  32.     fLoop = fValidRect = NO;
  33.     
  34.     // Set up the NXImages so they can draw without the files.
  35.     // This only works it's magic for cells set up in IB since
  36.     // a regular initialization will look for the images.
  37.     if (![NXImage findImageNamed:"MVCUpImage"])
  38.         {
  39.         char buf[MAXPATHLEN + 1];
  40.         NXImage * idImage;
  41.         
  42.         [[NXBundle bundleForClass:[self class]] getPath:buf 
  43.             forResource:"MVCUp" ofType:"tiff"];
  44.         idImage = [[[NXImage alloc] init] setDataRetained:YES];
  45.         [idImage loadFromFile:buf];
  46.         [idImage setName:"MVCUpImage"];
  47.         [[NXBundle bundleForClass:[self class]] getPath:buf 
  48.             forResource:"MVCDown" ofType:"tiff"];
  49.         idImage = [[[NXImage alloc] init] setDataRetained:YES];
  50.         [idImage loadFromFile:buf];
  51.         [idImage setName:"MVCDownImage"];
  52.         }
  53.     
  54.     idUp = [[[[ButtonCell allocFromZone:[self zone]]
  55.                           initIconCell:"MVCUpImage"]
  56.                           setTarget:self]
  57.                           setAction:@selector(increment:)];
  58.     [[idUp setContinuous:YES]
  59.            sendActionOn:NX_MOUSEDOWNMASK | NX_PERIODICMASK];
  60.     
  61.     idDown = [[[[ButtonCell allocFromZone:[self zone]]
  62.                             initIconCell:"MVCDownImage"]
  63.                             setTarget:self]
  64.                             setAction:@selector(decrement:)];
  65.     [[idDown setContinuous:YES]
  66.              sendActionOn:NX_MOUSEDOWNMASK | NX_PERIODICMASK];
  67.     
  68.     [[[self setBezeled:YES] setEditable:YES] setContinuous:NO];
  69.     
  70.     return self;
  71.     }
  72.  
  73. - copyFromZone:(NXZone *)zone
  74.     {
  75.     MiscValueCell * idNew = [super copyFromZone:zone];
  76.     
  77.     if (idNew)
  78.         {
  79.         if ((idNew->idUp = [idUp copyFromZone:zone]))
  80.             {
  81.             [idNew->idUp setTarget:idNew];
  82.             }
  83.         
  84.         if ((idNew->idDown = [idDown copyFromZone:zone]))
  85.             {
  86.             [idNew->idDown setTarget:idNew];
  87.             }
  88.         }
  89.     
  90.     return idNew;
  91.     }
  92.  
  93. - drawInside:(const NXRect *)aRect inView:controlView
  94.     {
  95.     if (!fValidRect)
  96.         {
  97.         rectFrame = *aRect;
  98.         rectFrame.size.width -= 17;
  99.         }
  100.     
  101.     [super drawInside:&rectFrame inView:controlView];
  102.     
  103.     return self;
  104.     }
  105.  
  106. - drawSelf:(const NXRect *)cellFrame inView:controlView
  107.     {
  108.     rectFrame = *cellFrame;
  109.     rectFrame.size.width -= 17;
  110.     
  111.     fValidRect = YES;
  112.     [super drawSelf:&rectFrame inView:controlView];
  113.     fValidRect = NO;
  114.     
  115.     rectFrame.origin.x += rectFrame.size.width + 1;
  116.     rectFrame.size.width = 16;
  117.     rectFrame.size.height /= 2;
  118.     [idUp drawSelf:&rectFrame inView:controlView];
  119.     
  120.     rectFrame.origin.y += rectFrame.size.height;
  121.     [idDown drawSelf:&rectFrame inView:controlView];
  122.     
  123.     return self;
  124.     }
  125.  
  126. - resetCursorRect:(const NXRect *)cellFrame inView:aView
  127.     {
  128.     NXRect rect = *cellFrame;
  129.     
  130.     rect.size.width -= 17;
  131.     [super resetCursorRect:&rect inView:aView];
  132.     
  133.     return self;
  134.     }
  135.  
  136. - calcCellSize:(NXSize *)theSize inRect:(const NXRect *)aRect
  137.     {
  138.     NXRect rect = *aRect;
  139.     
  140.     rect.size.width -= 17;
  141.     [super calcCellSize:theSize inRect:&rect];
  142.     
  143.     theSize->height = MAX(21, theSize->height);
  144.     theSize->width += 17;
  145.     
  146.     return self;
  147.     }
  148.  
  149. - edit:(const NXRect *)aRect inView:controlView editor:textObj
  150.     delegate:anObject event:(NXEvent *)theEvent
  151.     {
  152.     NXRect  rect = *aRect;
  153.     NXPoint p = theEvent->location;
  154.     id      idWhich;
  155.     BOOL    fR;
  156.     BOOL    fSpin;
  157.     int     oldMask;
  158.     float   delay;
  159.     float   interv;
  160.     
  161.     rect.size.width -= 17;
  162.     
  163.     [controlView convertPoint:&p fromView:nil];
  164.     
  165.     if (NXPointInRect(&p, &rect))
  166.         {
  167.         [super edit:&rect inView:controlView editor:textObj
  168.             delegate:anObject event:theEvent];
  169.         }
  170.     else
  171.         {
  172.         rect = *aRect;
  173.         rect.origin.x += rect.size.width - 16;
  174.         rect.size.width = 16;
  175.         rect.size.height /= 2;
  176.         fAltKeyDown = theEvent->flags & NX_ALTERNATEMASK;
  177.         
  178.         if (p.y < aRect->origin.y + (aRect->size.height / 2))
  179.             {
  180.             idWhich = idUp;
  181.             }
  182.         else
  183.             {
  184.             rect.origin.y += rect.size.height;
  185.             idWhich = idDown;
  186.             }
  187.         
  188.         oldMask = [[controlView window] addToEventMask:NX_MOUSEDRAGGEDMASK];
  189.         [controlView lockFocus];
  190.         [idWhich getPeriodicDelay:&delay andInterval:&interv];
  191.         fSpin = YES;
  192.         do
  193.             {
  194.             [idWhich highlight:&rect inView:controlView lit:YES];
  195.             fR = [idWhich trackMouse:theEvent inRect:&rect ofView:controlView];
  196.             [idWhich highlight:&rect inView:controlView lit:NO];
  197.             [controlView display:&rect :1];
  198.             [idWhich setPeriodicDelay:0.0 andInterval:interv];
  199.             if (fR)
  200.                 {
  201.                 fSpin = NO;
  202.                 }
  203.             else
  204.                 {
  205.                 theEvent = [NXApp
  206.                             getNextEvent:NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK];
  207.                 if (theEvent->type == NX_MOUSEUP)
  208.                     {
  209.                     fSpin = NO;
  210.                     }
  211.                 }
  212.             } while (fSpin);
  213.         [idWhich setPeriodicDelay:delay andInterval:interv];
  214.         [controlView unlockFocus];
  215.         [[controlView window] setEventMask:oldMask];
  216.         
  217.         [NXApp sendAction:action to:target from:controlView];
  218.         }
  219.     
  220.     return self;
  221.     }
  222.  
  223. - getDrawRect:(NXRect *)theRect
  224.     {
  225.     theRect->size.width -= 17;
  226.     [super getDrawRect:theRect];
  227.     
  228.     return self;
  229.     }
  230.  
  231. - getTitleRect:(NXRect *)theRect
  232.     {
  233.     theRect->size.width -= 17;
  234.     [super getTitleRect:theRect];
  235.     
  236.     return self;
  237.     }
  238.  
  239. - highlight:(const NXRect *)cellFrame inView:aView lit:(BOOL)flag
  240.     {
  241.     NXRect rect = *cellFrame;
  242.     
  243.     rect.size.width -= 17;
  244.     [super highlight:&rect inView:aView lit:flag];
  245.     
  246.     return self;
  247.     }
  248.  
  249. - select:(const NXRect *)aRect inView:aView editor:aTextObject
  250.     delegate:anObject start:(int)selStart length:(int)selLength
  251.     {
  252.     NXRect rect = *aRect;
  253.     
  254.     rect.size.width -= 17;
  255.     [super select:&rect inView:aView editor:aTextObject
  256.         delegate:anObject start:selStart length:selLength];
  257.     
  258.     return self;
  259.     }
  260.  
  261. - setBezeled:(BOOL)flag
  262.     {
  263.     [super setBezeled:flag];
  264.     
  265.     [idUp setBordered:flag];
  266.     [idDown setBordered:flag];
  267.     
  268.     return self;
  269.     }
  270.  
  271. - setBordered:(BOOL)flag
  272.     {
  273.     [super setBordered:flag];
  274.     
  275.     [idUp setBordered:NO];
  276.     [idDown setBordered:NO];
  277.     
  278.     return self;
  279.     }
  280.  
  281. - setEditable:(BOOL)flag
  282.     {
  283.     [super setEditable:flag];
  284.     
  285.     if (!flag)
  286.         {
  287.         [self setSelectable:YES];
  288.         }
  289.  
  290.     return self;
  291.     }
  292.  
  293.  
  294. - setIntValue:(int)anInt
  295.     {
  296.     [self setDoubleValue:(double)anInt];
  297.     
  298.     return self;
  299.     }
  300.  
  301. - setFloatValue:(float)aFloat
  302.     {
  303.     [self setDoubleValue:(double)aFloat];
  304.     
  305.     return self;
  306.     }
  307.  
  308. - setDoubleValue:(double)aDouble
  309.     {
  310.     const char *    sz;
  311.     id      sl = stringList;
  312.     
  313.     fLoop = YES; // so setStringValue doesn't get loopy
  314.     
  315.     if (!sl)
  316.         {
  317.     if ([[self controlView] class] == [MiscValueField class])
  318.         {
  319.         sl = [[self controlView] stringList];
  320.         }
  321.         }
  322.     
  323.     if (sl)
  324.     {
  325.     int indx = (int)aDouble;
  326.     int cnt = (int)limitMaxValue;
  327.         
  328.     cnt = [sl count] - 1;
  329.     
  330.     indx = MAX(indx, 0);
  331.     indx = MIN(indx, cnt);
  332.     actualValue = indx;
  333.         
  334.     sz = (char *)[sl stringAt:indx];
  335.     if (sz)
  336.         {
  337.         [super setStringValue:sz];
  338.         }
  339.     else
  340.         {
  341.         [super setDoubleValue:actualValue];
  342.         }
  343.     }
  344.     else
  345.         {
  346.     actualValue = MIN(aDouble, limitMaxValue);
  347.     actualValue = MAX(actualValue, limitMinValue);
  348.     
  349.     if (fExpandLow && (actualValue < limitMinBound))
  350.             {
  351.         limitMinBound = actualValue;
  352.         }
  353.     
  354.     if (fExpandHigh && (actualValue > limitMaxBound))
  355.             {
  356.         limitMaxBound = actualValue;
  357.         }
  358.         
  359.         [super setDoubleValue:actualValue];
  360.         }
  361.     
  362.     fLoop = NO;
  363.     
  364.     return self;
  365.     }
  366.  
  367. - setStringValue:(const char *)aString
  368.     {
  369.     double  value;
  370.     
  371.     [super setStringValue:aString];
  372.     
  373.     if (!fLoop)
  374.         {
  375.         sscanf(aString, "%lf", &value);
  376.         [self setDoubleValue:value];
  377.         }
  378.     
  379.     return self;
  380.     }
  381.  
  382. -(int) intValue
  383.     {
  384.     return (int)actualValue;
  385.     }
  386.  
  387. -(float) floatValue
  388.     {
  389.     return (float)actualValue;
  390.     }
  391.  
  392. -(double) doubleValue
  393.     {
  394.     return actualValue;
  395.     }
  396.  
  397.  
  398. - increment:sender
  399.     {
  400.     double  val;
  401.     id      sl = stringList;
  402.     
  403.     if (!sl)
  404.         {
  405.     if ([[self controlView] class] == [MiscValueField class])
  406.         {
  407.         sl = [[self controlView] stringList];
  408.         }
  409.         }
  410.     
  411.     if (sl)
  412.         {
  413.     [self setIntValue:[self intValue] + ((fAltKeyDown) ? sizeAltStep : 1)];
  414.     }
  415.     else
  416.         {
  417.     val = [self doubleValue] + ((fAltKeyDown) ? sizeAltStep : sizeStep);
  418.     
  419.     if (fExpandHigh && (val > limitMaxBound))
  420.             {
  421.         val = limitMaxBound;
  422.         }
  423.     [self setDoubleValue:val];
  424.     }
  425.     
  426.     if ([self isContinuous])
  427.         {
  428.         [NXApp sendAction:action to:target from:[self controlView]];
  429.         }
  430.     
  431.     return self;
  432.     }
  433.  
  434. - decrement:sender
  435.     {
  436.     double  val;
  437.     id      sl = stringList;
  438.     
  439.     if (!sl)
  440.         {
  441.     if ([[self controlView] class] == [MiscValueField class])
  442.         {
  443.         sl = [[self controlView] stringList];
  444.         }
  445.         }
  446.     
  447.     if (sl)
  448.         {
  449.     [self setIntValue:[self intValue] - ((fAltKeyDown) ? sizeAltStep : 1)];
  450.     }
  451.     else
  452.         {
  453.     val = [self doubleValue] - ((fAltKeyDown) ? sizeAltStep : sizeStep);
  454.     
  455.     if (fExpandLow && (val < limitMinBound))
  456.             {
  457.         val = limitMinBound;
  458.         }
  459.     [self setDoubleValue:val];
  460.     }
  461.     
  462.     if ([self isContinuous])
  463.         {
  464.         [NXApp sendAction:action to:target from:[self controlView]];
  465.         }
  466.     
  467.     return self;
  468.     }
  469.  
  470.  
  471. - setMinValue:(double)value
  472.     {
  473.     limitMinValue = value;
  474.     
  475.     return self;
  476.     }
  477.  
  478. - setMaxValue:(double)value
  479.     {
  480.     limitMaxValue = value;
  481.     
  482.     return self;
  483.     }
  484.  
  485. - setMinBoundary:(double)value
  486.     {
  487.     limitMinBound = value;
  488.     
  489.     return self;
  490.     }
  491.  
  492. - setMaxBoundary:(double)value
  493.     {
  494.     limitMaxBound = value;
  495.     
  496.     return self;
  497.     }
  498.  
  499. -(double) minValue
  500.     {
  501.     return limitMinValue;
  502.     }
  503.  
  504. -(double) maxValue
  505.     {
  506.     return limitMaxValue;
  507.     }
  508.  
  509. -(double) minBoundary
  510.     {
  511.     return limitMinBound;
  512.     }
  513.  
  514. -(double) maxBoundary
  515.     {
  516.     return limitMaxBound;
  517.     }
  518.  
  519. - setStepSize:(double)size
  520.     {
  521.     sizeStep = size;
  522.     
  523.     return self;
  524.     }
  525.  
  526. - setAltStepSize:(double)size
  527.     {
  528.     sizeAltStep = size;
  529.     
  530.     return self;
  531.     }
  532.  
  533. -(double) stepSize
  534.     {
  535.     return sizeStep;
  536.     }
  537.  
  538. -(double) altStepSize
  539.     {
  540.     return sizeAltStep;
  541.     }
  542.  
  543. - setExpandMin:(BOOL)flag
  544.     {
  545.     fExpandLow = flag;
  546.     
  547.     [self setDoubleValue:actualValue];
  548.     
  549.     return self;
  550.     }
  551.  
  552. - setExpandMax:(BOOL)flag
  553.     {
  554.     fExpandHigh = flag;
  555.     
  556.     [self setDoubleValue:actualValue];
  557.     
  558.     return self;
  559.     }
  560.  
  561. -(BOOL) expandMin
  562.     {
  563.     return fExpandLow;
  564.     }
  565.  
  566. -(BOOL) expandMax
  567.     {
  568.     return fExpandHigh;
  569.     }
  570.  
  571.  
  572. - setStringList:anObject
  573.     {
  574.     if (anObject && [anObject respondsTo:@selector(stringAt:)] &&
  575.     [anObject respondsTo:@selector(count)])
  576.         {
  577.     stringList = anObject;
  578.     [self setEditable:NO];
  579.     [self setIntValue:(int)actualValue];
  580.     }
  581.     
  582.     return self;
  583.     }
  584.  
  585. - stringList
  586.     {
  587.     return stringList;
  588.     }
  589.  
  590.  
  591. - write:(NXTypedStream *)stream
  592.     {
  593.     [super write:stream];
  594.     
  595.     NXWriteTypes(stream, "ddd", &actualValue, &sizeStep, &sizeAltStep);
  596.     NXWriteTypes(stream, "dd", &limitMinValue, &limitMaxValue);
  597.     NXWriteTypes(stream, "dd", &limitMinBound, &limitMaxBound);
  598.     NXWriteType(stream, @encode(BOOL), &fExpandLow);
  599.     NXWriteType(stream, @encode(BOOL), &fExpandHigh);
  600.     NXWriteObject(stream, idUp);
  601.     NXWriteObject(stream, idDown);
  602.     
  603.     return self;
  604.     }
  605.  
  606. - read:(NXTypedStream *)stream
  607.     {
  608.     [super read:stream];
  609.     
  610.     NXReadTypes(stream, "ddd", &actualValue, &sizeStep, &sizeAltStep);
  611.     NXReadTypes(stream, "dd", &limitMinValue, &limitMaxValue);
  612.     NXReadTypes(stream, "dd", &limitMinBound, &limitMaxBound);
  613.     NXReadType(stream, @encode(BOOL), &fExpandLow);
  614.     NXReadType(stream, @encode(BOOL), &fExpandHigh);
  615.     idUp = NXReadObject(stream);
  616.     idDown = NXReadObject(stream);
  617.     
  618.     return self;
  619.     }
  620.  
  621. - awake
  622.     {
  623.     [self setDoubleValue:actualValue];
  624.     
  625.     return self;
  626.     }
  627.  
  628. - awakeFromNib
  629.     {
  630.     [self awake];
  631.     
  632.     return self;
  633.     }
  634.  
  635. @end
  636.