#import "Messenger.h"
#import "Nutation.h"
#import <dpsclient/psops.h>
#import <ctype.h>

 /**
 ** A  Messenger is used to send a single
 ** objc message.  The message is typed into
 ** the Messenger's NuText. 
 ** Messenger's implement a vary
 ** simple objc interpreter.
 ** The message receiver is specified as a TTree path
 ** (see below).
 ** Method argument types may be
 ** ints, floats, strings (char *)'s,
 ** NXPoint's (x@y,ex. 2.1@24.4), 
 ** NXSize's (width@height,ex. 34.4@34.5),
 ** NXRect's (origin,size, ex.  0.0@0.0,14.2@22.5)
 ** and Glyph *'s, which are specified as a path in the TTree
 ** which is interpreted by Glyphs glyphAtPath: method.
 ** Paths start at the messenger, and specify a path
 ** to their target. The path is specified by the letters:
 ** a ancestor
 ** i is
 ** t then
 ** p precursor
 ** s self
 ** x current target glyph
 ** f former target glyph (most useful!)
 ** r current root glyph
 ** e terminator
 ** For example, to refer to the Messenger's ancestor's then's ancestor,
 ** use the path ata. To message the current root glyph's is then is glyph,
 ** issue the path riti.  To message the current target (which will always
 ** be the messenger, because you have to click on it to send the message,
 ** and this will make it the target), you could use s or x. To message
 ** whatever was the target immediately before you sent a message (i.e.
 ** the target BEFORE you clicked), use f.
 **
 ** When the Messenger sends a message, it becomes the target, then it
 ** makes the former target the current target.
 **
 ** If there are any errors, they are cached, and you can see them by
 ** evaluating the code 
 ** #import "Messenger.h"
 **
 ** [Messenger printError] ;
 ** --this will print the error in the transcript window.
 **/

 // Superclass file goes on next line:
#pragma .h #import "RTFGlyph.h"
@implementation Messenger:RTFGlyph
{
}

- draw: (NXSize *) scale ;
{ NXRect bRect = frame ;
  // let NuText draw the text
  [super draw: scale] ;
  // draw a dark gray border
  bRect.origin.x = bRect.origin.y = 0.0 ;
  PSsetgray(0.333) ;
  NXFrameRectWithWidth(&bRect,3.0) ;
  PSsetgray(0.0) ;
  // draw the "send" button
  [self getButtonFrame: &bRect] ;
  [Glyph drawButton: &bRect] ;
  [Nu ps: "/Helvetica findfont 12 scalefont setfont\n"
	"%f 9 moveto (Send) show\n",
    (frame.size.width / 2.0) - 15.0] ;
  return self ;

}

- getButtonFrame: (NXRect *) aRect ;
{ // return the frame for the "Send" button, in
  // my coords
  aRect->origin.x = aRect->origin.y = 4.0 ;
  aRect->size.width = frame.size.width - 8.0 ;
  aRect->size.height = 16.0 ;
  return self ;
}

- getTextFrame: (NXRect *) aRect ;
{ // my textFrame is inset by a 4 pixel border,
  // plus an extra 20 pixels at the bottom for
  // the "send" button
  *aRect = frame ;
  aRect->origin.x = 4.0 ;
  aRect->origin.y = 24.0 ;
  aRect->size.width -= 8.0 ;
  aRect->size.height -=  28.0 ;
  return self ;
}
 


- mouseUp: (NXEvent *) anEvent ;
{ // find out if mouse is in our button area; 
  // appropriate action if it is...
  NXPoint location = anEvent->location ;
  [[Nu glyphView] convertPoint: &location fromView: nil] ;
  [self convertFromRootGlyph: &location] ;
  if((location.y < 20.0) && (location.y > 5.0) &&
     (location.x > 5.0) && (location.y < frame.size.width - 5.0))
  { char *theText ;
    Glyph *aGlyph ;
    NXRect aRect ;
    [self endEditing] ;
    theText = [self text] ;
    aGlyph = [self message: theText] ;
    free(theText) ;
    // provide visual feedback by "flashing" the button
    aRect.origin.x = aRect.origin.y = 4.0 ;
    aRect.size.width = frame.size.width - 8.0 ;
    aRect.size.height = 16.0 ;
    [self convertToRootGlyph: &aRect.origin] ;
    [[Nu glyphView] lockFocus] ;
    [Nu ps:
     "true setinstance newinstance \n"
     "%f %f %f %f rectfill\n"
     "/Helvetica findfont 12 scalefont setfont\n"
     "1 setgray %f %f moveto (%s) show 0 setgray\n",
     aRect.origin.x + 2.0,aRect.origin.y+3.0,
     aRect.size.width - 4.0,aRect.size.height - 4.0,
     aRect.origin.x + (frame.size.width / 2.0) - 15.0, 
     aRect.origin.y + 4.0, aGlyph? "Sent" : "Fail"] ;
    usleep(300000) ;
    [Nu ps: "false setinstance newinstance 0.0\n"] ;
    [[Nu glyphView] unlockFocus] ;
    // if we weren't the formerTarget, make the formerTarget the
    // current target
    aGlyph = [[Nu rootGlyph] formerTargetGlyph] ;
    if(aGlyph != self)
      [aGlyph becomeTarget] ;
  }
  return [super mouseUp: anEvent] ;
}


@end

