home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.mdf / SourceCode / MiscKit1.2.6 / Palettes / MiscArrowButtonPalette / MiscArrowButton.subproj / MiscArrowButtonCell.m < prev    next >
Encoding:
Text File  |  1994-04-26  |  8.9 KB  |  372 lines

  1. /******************************************************************
  2.  * CLASS:        MiscArrowButtonCell
  3.  *
  4.  *    See the header for more information on this class.
  5.  *
  6.  * This object is included in the MiscKit by permission from the author
  7.  * and its use is governed by the MiscKit license, found in the file
  8.  * "LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
  9.  * for a list of all applicable permissions and restrictions.
  10.  *******************************************************************/
  11.  
  12. #import "wraps.h"
  13. #import <dpsclient/psops.h>
  14. #import <apps/InterfaceBuilder.h>
  15. #import "MiscArrowButtonCell.h"
  16.  
  17.  
  18. @implementation MiscArrowButtonCell
  19.  
  20. // The initializing methods just call the designated initializer
  21. // and give some default values.
  22.  
  23. - init
  24. {
  25.     return [self initTextCell: "Left" altTitle: "Right"];
  26. }
  27.  
  28.  
  29.  
  30. - initTextCell: (const char *)aString
  31. {
  32.     return [self initTextCell: aString altTitle: "Right"];
  33. }
  34.  
  35.  
  36.  
  37. // The desinated initializer for this class.
  38.  
  39. - initTextCell: (const char *)aString altTitle: (const char *)altString
  40. {
  41.     [super initTextCell: aString];
  42.     
  43.     [self setAltTitle: altString];
  44.     [self setState: 0];
  45.     [self setBordered: NO];
  46.     [self setShowsStateBy: NX_NONE];
  47.     [self setHighlightsBy: NX_NONE];
  48.     [self setArrowAlignment: MISC_ARROW_ABSOLUTE];
  49.     [self setType: NX_TOGGLE];
  50.     
  51.     return self;
  52. }
  53.  
  54.  
  55.  
  56. // Since the stringValue in Button does not do much, it now
  57. // returns the currently selected text.
  58.  
  59. - (const char *)stringValue
  60. {
  61.     if ([self state] == 0)
  62.         return (const char *)[self title];
  63.     else
  64.         return (const char *)[self altTitle];
  65. }
  66.  
  67.  
  68.  
  69. // I believe this method is supposed to calculate the minimum size needed to 
  70. // fit the currently displayed contents  (contents, altContents, and the arrow)
  71. // in the cellframe.
  72.  
  73. - calcCellSize: (NXSize *)theSize inRect: (NXRect *)theRect
  74. {
  75.   float  contentsWidth = [ [self font] getWidthOf: [self title] ];
  76.   float  altContentsWidth = [ [self font] getWidthOf: [self altTitle] ];
  77.   
  78.     // first calculate the width needed to draw all text and the arrow
  79.       
  80.       theSize->width = 0.0;
  81.     if ([self arrowAlignment] == MISC_ARROW_RELATIVE)
  82.     {
  83.         theSize->width += contentsWidth;
  84.         theSize->width += altContentsWidth;
  85.      }
  86.     else    // absolute alignment
  87.     {
  88.         if (contentsWidth > altContentsWidth)
  89.             theSize->width += contentsWidth * 2.0;
  90.         else
  91.             theSize->width += altContentsWidth * 2.0;
  92.      }
  93.      
  94.     theSize->width += cellHeight + 10.0;                    
  95.     
  96.     // now the height (which will usually be cellHeight)
  97.     
  98.     theSize->height = cellHeight;
  99.     
  100.     if ([ [self font] pointSize] > cellHeight)
  101.         theSize->height = [ [self font] pointSize];
  102.              
  103.     return self;
  104. }
  105.  
  106.  
  107.  
  108. // As far as I can tell (which may not be all that far) is that this 
  109. // function is only used by the Button's IBEditor to tell how large
  110. // the editor should be.
  111.  
  112. - getTitleRect : (NXRect *)theRect
  113. {
  114.   float  size = [ [self font] pointSize];
  115.   float  theY;
  116.   float  maxWidth = theRect->size.width/2.0;
  117.                 
  118.     // this is a hack so you can double click on the altTitle in IB
  119.  
  120.     if ([self state])
  121.         return [self getAltTitleRect: theRect];
  122.  
  123.     [self setAlignment: NX_LEFTALIGNED];    // used for the IBEditor
  124.         
  125.     theY = theRect->origin.y + theRect->size.height/2.0 - size/2.0;
  126.     
  127.     if ([self arrowAlignment] == MISC_ARROW_RELATIVE)
  128.           maxWidth = [ [self font] getWidthOf: [self title] ] + 10.0;      
  129.         
  130.     NXSetRect (theRect, theRect->origin.x, theY-2.0, maxWidth, size+2.0);               
  131.  
  132.     return self;
  133. }
  134.  
  135.  
  136.  
  137. // If the state is 1 (altContents selected), then this method will be
  138. // called. It returns the location for editor to appear when editing 
  139. // the altContents.
  140.  
  141. - getAltTitleRect: (NXRect *)theRect
  142. {
  143.   float  size = [ [self font] pointSize];
  144.   float  newX, newY, newWidth;
  145.     
  146.     [self setAlignment: NX_RIGHTALIGNED];    // used for the IBEditor
  147.  
  148.     newX = theRect->origin.x + theRect->size.width/2.0;              
  149.     newY = theRect->origin.y + theRect->size.height/2.0 - size/2.0;
  150.     newWidth = theRect->size.width/2.0;
  151.     
  152.     NXSetRect (theRect, newX, newY-2.0, newWidth, size+2.0);               
  153.     
  154.     return self;
  155. }
  156.  
  157.  
  158.  
  159. // New method to set the alignment of the arrow. MISC_ARROW_ABSOLUTE aligns
  160. // the arrow in the center of the cellFrame, where MISC_ARROW_RELATIVE
  161. // centers the arrow between the contents and altContents.
  162.  
  163. - setArrowAlignment: (int)alignment
  164. {
  165.     arrowAlignment = alignment;
  166.     return self;
  167. }
  168.  
  169.  
  170.  
  171. - (int)arrowAlignment
  172. {
  173.     return arrowAlignment;
  174. }
  175.  
  176.  
  177.  
  178. // This method is used to draw only the parts of the cell that
  179. // do change when the state changes. Therefore, only the black arrow
  180. // and the text are drawn here.
  181.  
  182. - drawInside: (const NXRect *)cellFrame inView: controlView
  183. {
  184.   float  gray;
  185.   float  size = [ [self font] pointSize];
  186.             
  187.     // draw the arrow
  188.  
  189.     if ([self arrowAlignment] == MISC_ARROW_RELATIVE)
  190.     {
  191.       NXRect  relativeFrame;
  192.       float  contentsWidth = [ [self font] getWidthOf: [self title] ];
  193.         float  altContentsWidth = [ [self font] getWidthOf: [self altTitle] ];
  194.  
  195.         // since it the arrow is drawn relative to the text, a little
  196.         // calculation is needed
  197.         
  198.         relativeFrame.origin.x = cellFrame->origin.x + contentsWidth;
  199.         relativeFrame.size.width = cellFrame->size.width - 
  200.                 (contentsWidth + altContentsWidth);
  201.  
  202.         PSABdrawarrow (relativeFrame.origin.x, cellFrame->origin.y + 3.0, 
  203.                 relativeFrame.size.width, cellFrame->size.height - 6.0, 
  204.                 (int)[self state], [self isEnabled]);
  205.      }
  206.     else
  207.         // draw the arrow in the center of the cellFrame
  208.         
  209.         PSABdrawarrow (cellFrame->origin.x, cellFrame->origin.y + 3.0, 
  210.                 cellFrame->size.width, cellFrame->size.height - 6.0, 
  211.                 (int)[self state], [self isEnabled]);
  212.     
  213.     // draw the left and right hand text
  214.     
  215.     [ [self font] set];
  216.             
  217.     if ([self title] != NULL)
  218.     {    
  219.       float  theY;
  220.                   
  221.         if ([self state] || ![self isEnabled])
  222.             gray = NX_DKGRAY;
  223.         else 
  224.             gray = 0.0;
  225.  
  226.         // calculate the placement of the contents and print it
  227.         
  228.         theY = cellFrame->origin.y + cellFrame->size.height/2.0 + size/3.0;            
  229.  
  230.         PSABshowstring (cellFrame->origin.x + 3.0, theY, gray, [self title]);
  231.      }
  232.          
  233.     if ([self altTitle] != NULL)
  234.     {    
  235.       float  theX, theY;
  236.       float  strWidth = [ [self font] getWidthOf: [self altTitle] ];
  237.                   
  238.         if ([self state] && [self isEnabled])
  239.             gray = 0.0;
  240.         else
  241.             gray = NX_DKGRAY;
  242.         
  243.         // calculate the placement of the altContents and print it
  244.         
  245.         theX = cellFrame->origin.x+(cellFrame->size.width - strWidth - 3.0);
  246.         theY = cellFrame->origin.y + cellFrame->size.height/2.0 + size/3.0;
  247.                     
  248.         PSABshowstring (theX, theY, gray, [self altTitle]);             
  249.      }
  250.              
  251.     return self;
  252. }
  253.  
  254.  
  255.  
  256. // This part of the drawing displays only the parts that don't change
  257. // often, which includes the diamond that encloses the arrow, and the
  258. // border when I get around to adding one. 
  259.  
  260. - drawSelf: (const NXRect *)cellFrame inView: controlView
  261. {          
  262.     // if transparent draw the background white (when in IB) and 
  263.     // same as the background when in an app (or testing interface)
  264.     
  265.     if ([self isTransparent])
  266.     {    
  267.         if ([NXApp respondsTo: @selector(isTestingInterface)])
  268.             if ([NXApp isTestingInterface])
  269.                 PSsetgray (NX_LTGRAY);
  270.             else
  271.                 PSsetgray (1.0);
  272.         else
  273.             PSsetgray (NX_LTGRAY);
  274.         
  275.         NXRectFill (cellFrame);
  276.  
  277.         return self;
  278.      }
  279.     
  280.     // set cellHeight since some of the calculations that are in other
  281.     // methods have to know the height of the cell (this is probably the
  282.     // wrong way to go about this)
  283.     
  284.     cellHeight = cellFrame->size.height;
  285.     
  286.     // draw the border or bezel, then call drawInside
  287.     
  288.     if ([self isBordered])
  289.         NXDrawButton (cellFrame, cellFrame);
  290.         
  291.     PSgsave();
  292.  
  293.     // have to flip drawing if we are drawing into a flipped view
  294.             
  295.     if ([controlView isFlipped])
  296.         PSABflipme (cellFrame->size.height + (cellFrame->origin.y * 2.0));
  297.     
  298.     if ([self arrowAlignment] == MISC_ARROW_RELATIVE)
  299.     {
  300.       NXRect  relativeFrame;
  301.       float  contentsWidth = [ [self font] getWidthOf: [self title] ];
  302.         float  altContentsWidth = [ [self font] getWidthOf: [self altTitle] ];
  303.  
  304.         relativeFrame.origin.x = cellFrame->origin.x + contentsWidth;
  305.         relativeFrame.size.width = cellFrame->size.width - 
  306.                 (contentsWidth + altContentsWidth);
  307.         
  308.         PSABdrawdiamond (relativeFrame.origin.x, cellFrame->origin.y + 3.0,
  309.                 relativeFrame.size.width, cellFrame->size.height - 6.0);
  310.      }
  311.     else
  312.         PSABdrawdiamond (cellFrame->origin.x, cellFrame->origin.y + 3.0, 
  313.             cellFrame->size.width, cellFrame->size.height - 6.0);
  314.         
  315.     PSgrestore();                
  316.  
  317.     // draw the rest of the cell
  318.                 
  319.     [self drawInside: cellFrame inView: controlView];
  320.      
  321.     return self;
  322. }
  323.  
  324.  
  325.  
  326. // Archiving methods
  327.  
  328. - read: (NXTypedStream *)stream
  329. {
  330.     [super read: stream];
  331.     
  332. //    NXReadType (stream, @encode(unsigned int), &arrowAlignment);
  333.     return self;
  334. }
  335.  
  336.  
  337.  
  338. - write: (NXTypedStream *)stream
  339. {
  340.     [super write: stream];
  341.     
  342. //    NXWriteType (stream, @encode(unsigned int), &arrowAlignment);
  343.     return self;
  344. }
  345.  
  346. @end
  347.  
  348.  
  349.  
  350. @implementation MiscArrowButtonCell (IB)
  351.  
  352. // This is used in IB when inspecting a matrix full of ArrowButton
  353. // cells. We just use the same inspector that ArrowButton uses.
  354.  
  355. - (const char *)getInspectorClassName
  356. {
  357.     return "ABInspector";
  358. }
  359.  
  360.  
  361.  
  362. // Here for when NeXT gets around to disclosing the rest of the API
  363. // for IBEditors.
  364.  
  365. - (const char *)getEditorClassName
  366. {
  367.     return "ArrowButtonEditor";
  368. }
  369.  
  370. @end
  371.  
  372.