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

  1. //
  2. //    MiscSliderCell.m -- a TextFieldCell subclass that adds a SliderCell
  3. //       Written by David Fedchenko. Copyright 1994 by David Fedchenko.
  4. //                    Version 1.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 "MiscSliderCell.h"
  15. #import "MiscSliderField.h"
  16.  
  17. @implementation MiscSliderCell
  18.  
  19. - initTextCell:(const char *)sz
  20.     {
  21.     [super initTextCell:sz];
  22.  
  23.     layout = MSC_LEFT;
  24.     split = 0.5;
  25.     limitMinValue = 0;
  26.     limitMaxValue = 100;
  27.     limitMinBound = limitMinValue;
  28.     limitMaxBound = limitMaxValue;
  29.     fExpandMin = fExpandMax = NO;
  30.     
  31.     fValidRect = NO;
  32.     
  33.     idSlider = [[[[SliderCell allocFromZone:[self zone]] init]
  34.                               setTarget:self]
  35.                               setAction:@selector(moved:)];
  36.     [[idSlider setContinuous:YES]
  37.                sendActionOn:NX_MOUSEDOWNMASK | NX_MOUSEDRAGGEDMASK];
  38.     [[idSlider setMinValue:limitMinValue] setMaxValue:limitMaxValue];
  39.     
  40.     [[[self setBezeled:YES] setEditable:YES] setContinuous:NO];
  41.     
  42.     return self;
  43.     }
  44.  
  45. - copyFromZone:(NXZone *)zone
  46.     {
  47.     MiscSliderCell * idNew = [super copyFromZone:zone];
  48.     
  49.     if (idNew)
  50.         {
  51.         if ((idNew->idSlider = [idSlider copyFromZone:zone]))
  52.             {
  53.             [idNew->idSlider setTarget:idNew];
  54.             }
  55.         }
  56.     
  57.     return idNew;
  58.     }
  59.  
  60. - textRect:(NXRect *)rect
  61.     {
  62.     float width = rect->size.width;
  63.     
  64.     switch (layout)
  65.         {
  66.     case MSC_LEFT:
  67.             rect->size.width *= split;
  68.         rect->size.width = MIN(width - MSC_MINWIDTH, rect->size.width);
  69.             rect->size.width -= (MSC_SPACING / 2);
  70.         break;
  71.     
  72.     case MSC_RIGHT:
  73.         rect->size.width *= split;
  74.         rect->size.width = MAX(MSC_MINWIDTH, rect->size.width);
  75.         rect->size.width = MIN(width - MSC_MINWIDTH, rect->size.width);
  76.             rect->size.width -= (MSC_SPACING / 2);
  77.         rect->origin.x = width - rect->size.width;
  78.         break;
  79.         
  80.     case MSC_BELOWLEFT:
  81.     case MSC_BELOWCENTER:
  82.     case MSC_BELOWRIGHT:
  83.         // the view is flipped
  84.         rect->origin.y += MSC_WIDTH + MSC_SPACING;
  85.         // fall through
  86.         
  87.     case MSC_ABOVELEFT:
  88.     case MSC_ABOVECENTER:
  89.     case MSC_ABOVERIGHT:
  90.         // the view is flipped
  91.         rect->size.height -= MSC_WIDTH + MSC_SPACING;
  92.         rect->size.width *= split;
  93.         rect->size.width = MAX(MSC_MINWIDTH, rect->size.width);
  94.         rect->size.width = MIN(width, rect->size.width);
  95.         switch (layout)
  96.             {
  97.         case MSC_ABOVECENTER:
  98.         case MSC_BELOWCENTER:
  99.             rect->origin.x += (width - rect->size.width) / 2;
  100.             break;
  101.         
  102.         case MSC_ABOVERIGHT:
  103.         case MSC_BELOWRIGHT:
  104.             rect->origin.x += width - rect->size.width;
  105.             break;
  106.         }
  107.         break;
  108.         }
  109.     
  110.     return self;
  111.     }
  112.  
  113. - sliderRect:(NXRect *)rect
  114.     {
  115.     float width = rect->size.width;
  116.     
  117.     switch (layout)
  118.         {
  119.     case MSC_LEFT:
  120.         rect->size.width *= (1 - split);
  121.         rect->size.width = MAX(MSC_MINWIDTH, rect->size.width);
  122.         rect->size.width = MIN(width - MSC_MINWIDTH, rect->size.width);
  123.             rect->size.width -= (MSC_SPACING / 2);
  124.         rect->origin.x = width - rect->size.width;
  125.         rect->origin.y += (rect->size.height - MSC_WIDTH) / 2;
  126.         rect->size.height = MSC_WIDTH;
  127.         break;
  128.     
  129.     case MSC_RIGHT:
  130.         rect->size.width *= (1 - split);
  131.         rect->size.width = MAX(MSC_MINWIDTH, rect->size.width);
  132.         rect->size.width = MIN(width - MSC_MINWIDTH, rect->size.width);
  133.             rect->size.width -= (MSC_SPACING / 2);
  134.         rect->origin.y += (rect->size.height - MSC_WIDTH) / 2;
  135.         rect->size.height = MSC_WIDTH;
  136.         break;
  137.         
  138.     case MSC_BELOWLEFT:
  139.     case MSC_BELOWCENTER:
  140.     case MSC_BELOWRIGHT:
  141.         // the view is flipped
  142.         rect->size.height = MSC_WIDTH;
  143.         break;
  144.         
  145.     case MSC_ABOVELEFT:
  146.     case MSC_ABOVECENTER:
  147.     case MSC_ABOVERIGHT:
  148.         // the view is flipped
  149.         rect->origin.y += rect->size.height - MSC_WIDTH;
  150.         rect->size.height = MSC_WIDTH;
  151.         break;
  152.         }
  153.     
  154.     return self;
  155.     }
  156.  
  157. - drawInside:(const NXRect *)aRect inView:controlView
  158.     {
  159.     if (!fValidRect)
  160.         {
  161.         rectFrame = *aRect;
  162.         [self textRect:&rectFrame];
  163.         }
  164.     
  165.     [super drawInside:&rectFrame inView:controlView];
  166.     
  167.     return self;
  168.     }
  169.  
  170. - drawSelf:(const NXRect *)cellFrame inView:controlView
  171.     {
  172.     NXRect rectSlider;
  173.     
  174.     rectFrame = *cellFrame;
  175.     rectSlider = *cellFrame;
  176.     [self textRect:&rectFrame];
  177.     [self sliderRect:&rectSlider];
  178.     
  179.     fValidRect = YES;
  180.     [super drawSelf:&rectFrame inView:controlView];
  181.     fValidRect = NO;
  182.     
  183.     [idSlider drawSelf:&rectSlider inView:controlView];
  184.     
  185.     return self;
  186.     }
  187.  
  188. - resetCursorRect:(const NXRect *)cellFrame inView:aView
  189.     {
  190.     NXRect rect = *cellFrame;
  191.     
  192.     [self textRect:&rect];
  193.     [super resetCursorRect:&rect inView:aView];
  194.     
  195.     return self;
  196.     }
  197.  
  198. - calcCellSize:(NXSize *)theSize inRect:(const NXRect *)aRect
  199.     {
  200.     [super calcCellSize:theSize inRect:aRect];
  201.     
  202.     switch (layout)
  203.     {
  204.     case MSC_LEFT:
  205.     case MSC_RIGHT:
  206.         theSize->width = MSC_MINWIDTH * 2 + MSC_SPACING;
  207.         break;
  208.         
  209.     case MSC_ABOVELEFT:
  210.     case MSC_ABOVECENTER:
  211.     case MSC_ABOVERIGHT:
  212.     case MSC_BELOWLEFT:
  213.     case MSC_BELOWCENTER:
  214.     case MSC_BELOWRIGHT:
  215.         theSize->width = MSC_MINWIDTH;
  216.         theSize->height += MSC_WIDTH + MSC_SPACING;
  217.         break;
  218.     }
  219.  
  220.     return self;
  221.     }
  222.  
  223. - edit:(const NXRect *)aRect inView:controlView editor:textObj
  224.     delegate:anObject event:(NXEvent *)theEvent
  225.     {
  226.     NXRect  rectT = *aRect;
  227.     NXRect  rectS = *aRect;
  228.     NXPoint p = theEvent->location;
  229.     
  230.     [self textRect:&rectT];
  231.     [self sliderRect:&rectS];
  232.     
  233.     [controlView convertPoint:&p fromView:nil];
  234.     
  235.     if (NXPointInRect(&p, &rectT))
  236.         {
  237.         [super edit:&rectT inView:controlView editor:textObj
  238.             delegate:anObject event:theEvent];
  239.         }
  240.     else if (NXPointInRect(&p, &rectS))
  241.         {
  242.     id sl = stringList;
  243.     
  244.     if (!sl)
  245.             {
  246.         if ([[self controlView] class] == [MiscSliderField class])
  247.             {
  248.         sl = [[self controlView] stringList];
  249.         }
  250.         }
  251.     
  252.     if (sl)
  253.         {
  254.         [idSlider setMinValue:0];
  255.         [idSlider setMaxValue:[sl count]];
  256.         }
  257.     
  258.         [controlView lockFocus];
  259.         [idSlider trackMouse:theEvent inRect:NULL ofView:controlView];
  260.         [controlView unlockFocus];
  261.         
  262.         [NXApp sendAction:action to:target from:controlView];
  263.         }
  264.     
  265.     return self;
  266.     }
  267.  
  268. - getDrawRect:(NXRect *)theRect
  269.     {
  270.     [self textRect:theRect];
  271.     [super getDrawRect:theRect];
  272.     
  273.     return self;
  274.     }
  275.  
  276. - getTitleRect:(NXRect *)theRect
  277.     {
  278.     [self textRect:theRect];
  279.     [super getTitleRect:theRect];
  280.     
  281.     return self;
  282.     }
  283.  
  284. - highlight:(const NXRect *)cellFrame inView:aView lit:(BOOL)flag
  285.     {
  286.     NXRect rect = *cellFrame;
  287.     
  288.     [self textRect:&rect];
  289.     [super highlight:&rect inView:aView lit:flag];
  290.     
  291.     return self;
  292.     }
  293.  
  294. - select:(const NXRect *)aRect inView:aView editor:aTextObject
  295.     delegate:anObject start:(int)selStart length:(int)selLength
  296.     {
  297.     NXRect rect = *aRect;
  298.     
  299.     [self textRect:&rect];
  300.     [super select:&rect inView:aView editor:aTextObject
  301.         delegate:anObject start:selStart length:selLength];
  302.     
  303.     return self;
  304.     }
  305.  
  306. - setEditable:(BOOL)flag
  307.     {
  308.     [super setEditable:flag];
  309.     
  310.     if (!flag)
  311.         {
  312.         [self setSelectable:YES];
  313.         }
  314.     
  315.     return self;
  316.     }
  317.  
  318.  
  319. - setIntValue:(int)anInt
  320.     {
  321.     [self setDoubleValue:(double)anInt];
  322.     
  323.     return self;
  324.     }
  325.  
  326. - setFloatValue:(float)aFloat
  327.     {
  328.     [self setDoubleValue:(double)aFloat];
  329.     
  330.     return self;
  331.     }
  332.  
  333. - setDoubleValue:(double)aDouble
  334.     {
  335.     const char * sz;
  336.     id           sl = stringList;
  337.     
  338.     fLoop = YES; // so setStringValue doesn't get loopy
  339.     
  340.     if (!sl)
  341.         {
  342.     if ([[self controlView] class] == [MiscSliderField class])
  343.         {
  344.         sl = [[self controlView] stringList];
  345.         }
  346.         }
  347.     
  348.     if (sl)
  349.     {
  350.     int indx = (int)aDouble;
  351.     int cnt = (int)limitMaxValue;
  352.         
  353.     cnt = [sl count] - 1;
  354.         
  355.     indx = MAX(indx, 0);
  356.     indx = MIN(indx, cnt);
  357.     actualValue = indx;
  358.         
  359.     sz = (char *)[sl stringAt:indx];
  360.     if (sz)
  361.         {
  362.         [super setStringValue:sz];
  363.         }
  364.     else
  365.         {
  366.         [super setDoubleValue:actualValue];
  367.                }
  368.     }
  369.     else
  370.         {
  371.         aDouble = MIN(aDouble, limitMaxValue);
  372.         aDouble = MAX(aDouble, limitMinValue);
  373.         
  374.         if (!fFeedback)
  375.             {
  376.               if (fExpandMin && (aDouble < limitMinBound))
  377.             {
  378.             limitMinBound = aDouble;
  379.             [idSlider setMinValue:aDouble];
  380.             }
  381.         
  382.         if (fExpandMax && (aDouble > limitMaxBound))
  383.             {
  384.             limitMaxBound = aDouble;
  385.             [idSlider setMaxValue:aDouble];
  386.             }
  387.         }
  388.         
  389.         if (fInt)
  390.             {
  391.         aDouble = rint(aDouble);
  392.         }
  393.     
  394.         actualValue = aDouble;
  395.         [super setDoubleValue:aDouble];
  396.         if (!fFeedback)
  397.             {
  398.         [idSlider setDoubleValue:aDouble];
  399.         [[self controlView] updateCell:self];
  400.             }
  401.         }
  402.     
  403.     fLoop = NO;
  404.     
  405.     return self;
  406.     }
  407.  
  408. - setStringValue:(const char *)aString
  409.     {
  410.     double  value;
  411.     
  412.     [super setStringValue:aString];
  413.     
  414.     if (!fLoop)
  415.         {
  416.         sscanf(aString, "%lf", &value);
  417.         [self setDoubleValue:value];
  418.         }
  419.     
  420.     return self;
  421.     }
  422.  
  423. - takeDoubleValueFrom:sender
  424.     {
  425.     [self setDoubleValue:[sender doubleValue]];
  426.     
  427.     return self;
  428.     }
  429.  
  430. -(int) intValue
  431.     {
  432.     return (int)actualValue;
  433.     }
  434.  
  435. -(float) floatValue
  436.     {
  437.     return (float)actualValue;
  438.     }
  439.  
  440. -(double) doubleValue
  441.     {
  442.     return actualValue;
  443.     }
  444.  
  445.  
  446. - moved:sender
  447.     {
  448.     fFeedback = YES;
  449.     [self setDoubleValue:[idSlider doubleValue]];
  450.     fFeedback = NO;
  451.     
  452.     if ([self isContinuous])
  453.         {
  454.         [NXApp sendAction:action to:target from:[self controlView]];
  455.         }
  456.     
  457.     return self;
  458.     }
  459.  
  460.  
  461. - setMinValue:(double)value
  462.     {
  463.     limitMinValue = value;
  464.     
  465.     if (!fExpandMin && !stringList)
  466.         {
  467.     [idSlider setMinValue:value];
  468.     [self setDoubleValue:MAX(actualValue, value)];
  469.     }
  470.     
  471.     return self;
  472.     }
  473.  
  474. - setMaxValue:(double)value
  475.     {
  476.     limitMaxValue = value;
  477.  
  478.     if (!fExpandMax && !stringList)
  479.         {
  480.     [idSlider setMaxValue:value];
  481.     [self setDoubleValue:MIN(actualValue, value)];
  482.     }
  483.     
  484.     return self;
  485.     }
  486.  
  487. - setMinBoundary:(double)value
  488.     {
  489.     limitMinBound = value;
  490.  
  491.     if (fExpandMin && !stringList)
  492.         {
  493.     [idSlider setMinValue:value];
  494.     [self setDoubleValue:MAX(actualValue, value)];
  495.     }
  496.     
  497.     return self;
  498.     }
  499.  
  500. - setMaxBoundary:(double)value
  501.     {
  502.     limitMaxBound = value;
  503.  
  504.     if (fExpandMin && !stringList)
  505.         {
  506.     [idSlider setMinValue:value];
  507.     [self setDoubleValue:MIN(actualValue, value)];
  508.     }
  509.     
  510.     return self;
  511.     }
  512.  
  513. -(double) minValue
  514.     {
  515.     return limitMinValue;
  516.     }
  517.  
  518. -(double) maxValue
  519.     {
  520.     return limitMaxValue;
  521.     }
  522.  
  523. -(double) minBoundary
  524.     {
  525.     return limitMinBound;
  526.     }
  527.  
  528. -(double) maxBoundary
  529.     {
  530.     return limitMaxBound;
  531.     }
  532.  
  533. - setExpandMin:(BOOL)flag
  534.     {
  535.     fExpandMin = flag;
  536.     
  537.     if (flag)
  538.         {
  539.         if (!stringList)
  540.             {
  541.         [idSlider setMinValue:limitMinBound];
  542.         [self setDoubleValue:MAX(actualValue, limitMinBound)];
  543.             }
  544.     }
  545.     else
  546.         {
  547.         if (!stringList)
  548.             {
  549.             [idSlider setMinValue:limitMinValue];
  550.         [self setDoubleValue:actualValue];
  551.             }
  552.     }
  553.     
  554.     return self;
  555.     }
  556.  
  557. - setExpandMax:(BOOL)flag
  558.     {
  559.     fExpandMax = flag;
  560.     
  561.     if (flag)
  562.         {
  563.         if (!stringList)
  564.             {
  565.         [idSlider setMaxValue:limitMaxBound];
  566.         [self setDoubleValue:MIN(actualValue, limitMaxBound)];
  567.             }
  568.     }
  569.     else
  570.         {
  571.         if (!stringList)
  572.             {
  573.             [idSlider setMaxValue:limitMaxValue];
  574.         [self setDoubleValue:actualValue];
  575.             }
  576.     }
  577.     
  578.     return self;
  579.     }
  580.  
  581. -(BOOL) expandMin
  582.     {
  583.     return fExpandMin;
  584.     }
  585.  
  586. -(BOOL) expandMax
  587.     {
  588.     return fExpandMax;
  589.     }
  590.  
  591. - setPosition:(int)where
  592.     {
  593.     layout = where;
  594.     
  595.     return self;
  596.     }
  597.  
  598. - setSplit:(int)percent
  599.     {
  600.     split = percent / 100.0;
  601.     
  602.     return self;
  603.     }
  604.  
  605. - setIntegerOnly:(BOOL)flag
  606.     {
  607.     fInt = flag;
  608.     
  609.     return self;
  610.     }
  611.  
  612. -(int) position
  613.     {
  614.     return layout;
  615.     }
  616.  
  617. -(int) split
  618.     {
  619.     return (int)(split * 100);
  620.     }
  621.  
  622. -(BOOL) integerOnly
  623.     {
  624.     return fInt;
  625.     }
  626.  
  627.  
  628. - setStringList:anObject
  629.     {
  630.     if (anObject && [anObject respondsTo:@selector(stringAt:)] &&
  631.         [anObject respondsTo:@selector(count)])
  632.         {
  633.         stringList = anObject;
  634.     [self setEditable:NO];
  635.         [self setDoubleValue:actualValue];
  636.         }
  637.     else
  638.         {
  639.         [self setMinBoundary:limitMinBound];
  640.         [self setMaxBoundary:limitMaxBound];
  641.         [self setMinValue:limitMinValue];
  642.         [self setMaxValue:limitMaxValue];
  643.         }
  644.     
  645.     return self;
  646.     }
  647.  
  648. - stringList
  649.     {
  650.     return stringList;
  651.     }
  652.  
  653.  
  654. - write:(NXTypedStream *)stream
  655.     {
  656.     [super write:stream];
  657.     
  658.     NXWriteTypes(stream, "ifd", &layout, &split, &actualValue);
  659.     NXWriteTypes(stream, "dd", &limitMinValue, &limitMaxValue);
  660.     NXWriteTypes(stream, "dd", &limitMinBound, &limitMaxBound);
  661.     NXWriteType(stream, @encode(BOOL), &fExpandMin);
  662.     NXWriteType(stream, @encode(BOOL), &fExpandMax);
  663.     NXWriteType(stream, @encode(BOOL), &fInt);
  664.     NXWriteObject(stream, idSlider);
  665.     
  666.     return self;
  667.     }
  668.  
  669. - read:(NXTypedStream *)stream
  670.     {
  671.     [super read:stream];
  672.     
  673.     NXReadTypes(stream, "ifd", &layout, &split, &actualValue);
  674.     NXReadTypes(stream, "dd", &limitMinValue, &limitMaxValue);
  675.     NXReadTypes(stream, "dd", &limitMinBound, &limitMaxBound);
  676.     NXReadType(stream, @encode(BOOL), &fExpandMin);
  677.     NXReadType(stream, @encode(BOOL), &fExpandMax);
  678.     NXReadType(stream, @encode(BOOL), &fInt);
  679.     idSlider = NXReadObject(stream);
  680.     
  681.     return self;
  682.     }
  683.  
  684. - awake
  685.     {
  686.     [self setDoubleValue:actualValue];
  687.     
  688.     return self;
  689.     }
  690.  
  691. - awakeFromNib
  692.     {
  693.     [self awake];
  694.     
  695.     return self;
  696.     }
  697.  
  698. @end
  699.