/* Blinking text object by Joe Freeman 1/10 */
/*	((Idea by Charles Oei)) */
/*      Broken to work with IB by David Stutz 2/6 */

/*
/* Purpose:
/*	supply a simple interface to make blinking text
/*	for warning or informational messages
/*
/* Defaults
/*	1.0 second blink rate
/*	centered text
/*	no bezel
/*	no border
/*	no support
/*	you really don't want to enable editing or selection, do you?
 */

#import "BlinkTextField.h"
#import <appkit/appkit.h>
#import <streams/error.h>

@implementation BlinkTextField


+ newFrame:(const NXRect *)frameRect
{
  self = [super newFrame:frameRect];

  [self setEditable:NO];
  [self setSelectable:NO];

  interval = 1.0;
  priority = NX_RUNMODALTHRESHOLD;
  which = 0;
  teNum = 0;

  [self setBackgroundGray:NX_LTGRAY];
  [self setTextGray:NX_BLACK];
  [self setAlignment:NX_CENTERED];
  [self setBezeled:NO];
  [self setBordered:NO];
  [self setFont:[Font newFont:"Helvetica" size:18]];
  [self setStringValue:"Blinker!"];
  [self setBlink:NO];

  return self;
}

- setTextGray:(float)newGray
{
  realGray = newGray;
  [super setTextGray:newGray];
  return self;
}

- blink:sender
{
  [self setBlink:YES];
  return self;
}

- stopBlink:sender
{
  [self setBlink:NO];
  return self;
}

- takeBlinkRateFrom:sender
{
  [self setBlinkRate:[sender doubleValue]];
  return self;
}

- flashGray
{ 
  if (which) {
    [super setTextGray:[self backgroundGray]];
    which = 0;
  } else {
    [super setTextGray:realGray];
    which = 1;
  }
  return self;
}

- setEditable:(BOOL)flag
{
  [super setEditable:NO];
  return self;
}

- setSelectable:(BOOL)flag
{
  [super setSelectable:NO];
  return self;
}

- (float)realGray
{ 
  return realGray;
}

- free
{
  [self setBlink:NO];
  // can't free here because of async notification from DPS
  // this could be fixed with a delayed free easily, but I'm just a lazy kind of guy
  return nil;
}

- read:(NXTypedStream*)s
{
  [super read:s];
  NXReadTypes(s,"fdii", &realGray, &interval, &active, &priority);
  if (active)
    [self setBlink:YES];
  return self;
}

- write:(NXTypedStream*)s
{
  [super write:s];
  NXWriteTypes(s,"fdii", &realGray, &interval, &active, &priority);
  return self;
}

DPSTimedEntryProc flashMsg (DPSTimedEntry teNum, double now, char* myself)
{
  if ([(id)myself isBlinking])
    [(id)myself flashGray];
}

- deferredSetBlink:(BOOL)flag
{
  active = flag;
  return self;
}

- setBlink:(BOOL)flag
{
  if (flag){
    teNum = DPSAddTimedEntry(interval, flashMsg, (void*)self, priority);
  }else{
    if (teNum != 0) {
      DPSRemoveTimedEntry (teNum);
      NXPing();
    }
    [super setTextGray:realGray];
    teNum = 0;
  }
  active = flag;
  return self;
}

- setBlinkRate:(double)theRate
{
  if (theRate > 0.0){
    interval = theRate;
    if (teNum != 0){
      [self setBlink:NO];
      NXPing();
      [self setBlink:YES];
    }
  }
  return self;
}

- (double)blinkRate
{
  return interval;
}

- (int)isBlinking
{
  return active;
}

- (const char*)inspectorName
{
  return "BTFInspector";
}

@end
