home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / SourceCode / MiscKit1.7.1 / MiscKit / Palettes / MiscValueFieldPalette / MiscSliderField.subproj / MiscSliderCell.m < prev    next >
Encoding:
Text File  |  1995-12-20  |  14.1 KB  |  705 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.     [[self controlView] validateEditing];
  433.  
  434.     return (int)actualValue;
  435.     }
  436.  
  437. -(float) floatValue
  438.     {
  439.     [[self controlView] validateEditing];
  440.  
  441.     return (float)actualValue;
  442.     }
  443.  
  444. -(double) doubleValue
  445.     {
  446.     [[self controlView] validateEditing];
  447.  
  448.     return actualValue;
  449.     }
  450.  
  451.  
  452. - moved:sender
  453.     {
  454.     fFeedback = YES;
  455.     [self setDoubleValue:[idSlider doubleValue]];
  456.     fFeedback = NO;
  457.     
  458.     if ([self isContinuous])
  459.         {
  460.         [NXApp sendAction:action to:target from:[self controlView]];
  461.         }
  462.     
  463.     return self;
  464.     }
  465.  
  466.  
  467. - setMinValue:(double)value
  468.     {
  469.     limitMinValue = value;
  470.     
  471.     if (!fExpandMin && !stringList)
  472.         {
  473.     [idSlider setMinValue:value];
  474.     [self setDoubleValue:MAX(actualValue, value)];
  475.     }
  476.     
  477.     return self;
  478.     }
  479.  
  480. - setMaxValue:(double)value
  481.     {
  482.     limitMaxValue = value;
  483.  
  484.     if (!fExpandMax && !stringList)
  485.         {
  486.     [idSlider setMaxValue:value];
  487.     [self setDoubleValue:MIN(actualValue, value)];
  488.     }
  489.     
  490.     return self;
  491.     }
  492.  
  493. - setMinBoundary:(double)value
  494.     {
  495.     limitMinBound = value;
  496.  
  497.     if (fExpandMin && !stringList)
  498.         {
  499.     [idSlider setMinValue:value];
  500.     [self setDoubleValue:MAX(actualValue, value)];
  501.     }
  502.     
  503.     return self;
  504.     }
  505.  
  506. - setMaxBoundary:(double)value
  507.     {
  508.     limitMaxBound = value;
  509.  
  510.     if (fExpandMin && !stringList)
  511.         {
  512.     [idSlider setMinValue:value];
  513.     [self setDoubleValue:MIN(actualValue, value)];
  514.     }
  515.     
  516.     return self;
  517.     }
  518.  
  519. -(double) minValue
  520.     {
  521.     return limitMinValue;
  522.     }
  523.  
  524. -(double) maxValue
  525.     {
  526.     return limitMaxValue;
  527.     }
  528.  
  529. -(double) minBoundary
  530.     {
  531.     return limitMinBound;
  532.     }
  533.  
  534. -(double) maxBoundary
  535.     {
  536.     return limitMaxBound;
  537.     }
  538.  
  539. - setExpandMin:(BOOL)flag
  540.     {
  541.     fExpandMin = flag;
  542.     
  543.     if (flag)
  544.         {
  545.         if (!stringList)
  546.             {
  547.         [idSlider setMinValue:limitMinBound];
  548.         [self setDoubleValue:MAX(actualValue, limitMinBound)];
  549.             }
  550.     }
  551.     else
  552.         {
  553.         if (!stringList)
  554.             {
  555.             [idSlider setMinValue:limitMinValue];
  556.         [self setDoubleValue:actualValue];
  557.             }
  558.     }
  559.     
  560.     return self;
  561.     }
  562.  
  563. - setExpandMax:(BOOL)flag
  564.     {
  565.     fExpandMax = flag;
  566.     
  567.     if (flag)
  568.         {
  569.         if (!stringList)
  570.             {
  571.         [idSlider setMaxValue:limitMaxBound];
  572.         [self setDoubleValue:MIN(actualValue, limitMaxBound)];
  573.             }
  574.     }
  575.     else
  576.         {
  577.         if (!stringList)
  578.             {
  579.             [idSlider setMaxValue:limitMaxValue];
  580.         [self setDoubleValue:actualValue];
  581.             }
  582.     }
  583.     
  584.     return self;
  585.     }
  586.  
  587. -(BOOL) expandMin
  588.     {
  589.     return fExpandMin;
  590.     }
  591.  
  592. -(BOOL) expandMax
  593.     {
  594.     return fExpandMax;
  595.     }
  596.  
  597. - setPosition:(int)where
  598.     {
  599.     layout = where;
  600.     
  601.     return self;
  602.     }
  603.  
  604. - setSplit:(int)percent
  605.     {
  606.     split = percent / 100.0;
  607.     
  608.     return self;
  609.     }
  610.  
  611. - setIntegerOnly:(BOOL)flag
  612.     {
  613.     fInt = flag;
  614.     
  615.     return self;
  616.     }
  617.  
  618. -(int) position
  619.     {
  620.     return layout;
  621.     }
  622.  
  623. -(int) split
  624.     {
  625.     return (int)(split * 100);
  626.     }
  627.  
  628. -(BOOL) integerOnly
  629.     {
  630.     return fInt;
  631.     }
  632.  
  633.  
  634. - setStringList:anObject
  635.     {
  636.     if (anObject && [anObject respondsTo:@selector(stringAt:)] &&
  637.         [anObject respondsTo:@selector(count)])
  638.         {
  639.         stringList = anObject;
  640.     [self setEditable:NO];
  641.         [self setDoubleValue:actualValue];
  642.         }
  643.     else
  644.         {
  645.         [self setMinBoundary:limitMinBound];
  646.         [self setMaxBoundary:limitMaxBound];
  647.         [self setMinValue:limitMinValue];
  648.         [self setMaxValue:limitMaxValue];
  649.         }
  650.     
  651.     return self;
  652.     }
  653.  
  654. - stringList
  655.     {
  656.     return stringList;
  657.     }
  658.  
  659.  
  660. - write:(NXTypedStream *)stream
  661.     {
  662.     [super write:stream];
  663.     
  664.     NXWriteTypes(stream, "ifd", &layout, &split, &actualValue);
  665.     NXWriteTypes(stream, "dd", &limitMinValue, &limitMaxValue);
  666.     NXWriteTypes(stream, "dd", &limitMinBound, &limitMaxBound);
  667.     NXWriteType(stream, @encode(BOOL), &fExpandMin);
  668.     NXWriteType(stream, @encode(BOOL), &fExpandMax);
  669.     NXWriteType(stream, @encode(BOOL), &fInt);
  670.     NXWriteObject(stream, idSlider);
  671.     
  672.     return self;
  673.     }
  674.  
  675. - read:(NXTypedStream *)stream
  676.     {
  677.     [super read:stream];
  678.     
  679.     NXReadTypes(stream, "ifd", &layout, &split, &actualValue);
  680.     NXReadTypes(stream, "dd", &limitMinValue, &limitMaxValue);
  681.     NXReadTypes(stream, "dd", &limitMinBound, &limitMaxBound);
  682.     NXReadType(stream, @encode(BOOL), &fExpandMin);
  683.     NXReadType(stream, @encode(BOOL), &fExpandMax);
  684.     NXReadType(stream, @encode(BOOL), &fInt);
  685.     idSlider = NXReadObject(stream);
  686.     
  687.     return self;
  688.     }
  689.  
  690. - awake
  691.     {
  692.     [self setDoubleValue:actualValue];
  693.     
  694.     return self;
  695.     }
  696.  
  697. - awakeFromNib
  698.     {
  699.     [self awake];
  700.     
  701.     return self;
  702.     }
  703.  
  704. @end
  705.