// I grew up programming-wise on the Apple //+. Back then we had flashing text, and we liked it.
/ / I recently needed it in a Cocoa app I was writing. So I wrote a simple subclass of NSLabel/UILabel to flash text.
// Because I think flashing text is the future of computing, here it is.
// Of course, works fine on iOS too, just define __FORIOS__
// And yes I know all my OS X/iOS ifdefs look backwards. This is the way my brain works.
// Download the source files so you don't have to cut and paste aiiFlashingText
// Provided under the Fredware License

//
// aiiFlashingText.h
//
// Created by C.K. Haun on 12/24/13.
// Copyright (c) 2013 C.K. Haun and Ravenware Industries LLC. All rights reserved.
//
#ifndef __FORIPHONE__
#import <Cocoa/Cocoa.h>
#else
#import <UIKit/UIKit.h>
#endif
typedef enum textFlashSpeed{
textFlashSpeedFast=0,
textFlashSpeedMedium,
textFlashSpeedSlow
}textFlashSpeed;

// silly macros to harmonize OS X and iOS which already should be harmonized
#ifndef __FORIPHONE__
#define aiiColor NSColor
#define aiiRect NSRect
#else
#define aiiColor UIColor
#define aiiRect CGRect
#endif

@interface aiiFlashingText :
#ifndef __FORIPHONE__
NSTextField
#else
UILabel
#endif
{
aiiColor *textColor;
NSTimer *timit;
BOOL onoff;
BOOL flashing;
BOOL oldFlashing;
NSTimeInterval currentSpeed;
NSTimeInterval flashSpeed[3];
}

-(void)applyColor:(aiiColor *)newColor;
-(void)setFlashSpeed:(textFlashSpeed)speed;
-(void)flash:(BOOL)startStop;
@end

//
// aiiFlashingText.m
// Machine Essays
//
// Created by C.K. Haun on 12/24/13.
// Copyright (c) 2013 C.K. Haun and Ravenware Industries LLC. All rights reserved.
//

#import "aiiFlashingText.h"
@interface aiiFlashingText()
-(void)doFlashie:(NSTimer *)thi;
-(void)innerInit;

@end
@implementation aiiFlashingText
-(void)innerInit{
int qq;
NSTimeInterval aa[]={.2,.7,1.3};
for(qq=0;qq<3;qq++)
flashSpeed[qq]=aa[qq];
currentSpeed=.7;
}
- (id)initWithFrame:(aiiRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self innerInit];
}
return self;
}
-(void)awakeFromNib {
[self innerInit];
}
-(void)applyColor:(aiiColor *)newColor{
[self setTextColor:newColor];
}
-(void)setFlashSpeed:(textFlashSpeed)speed{
currentSpeed=flashSpeed[speed];
if(flashing)
[timit invalidate];
timit = [NSTimer scheduledTimerWithTimeInterval: currentSpeed target:self selector:@selector(doFlashie:) userInfo:nil repeats: YES];
onoff = NO;
flashing=YES;
}
// override setHidden to turn off the timer
-(void)setHidden:(BOOL)flag{
[super setHidden:flag];
if(flag==NO){
// if it was previously hidden flashing, turn it visible again flashing. If not, well, don't
[self flash :oldFlashing];
}else {
oldFlashing=flashing;
[self flash:NO];
}
}

// inner routine called byu the timer to ramp between solid and transparent
-(void)doFlashie:(NSTimer *)thi{
if(onoff){
onoff=NO;
#ifndef __FORIPHONE__
[[self animator] setAlphaValue:0];
#else
[UIView animateWithDuration:currentSpeed animations:^(void) {
self.alpha = 0;
}];
#endif
}else{
onoff=YES;
#ifndef __FORIPHONE__

[[self animator] setAlphaValue:1];
#else
[UIView animateWithDuration:currentSpeed animations:^(void) {
self.alpha = 1;
}];
#endif

}
}

// start or stop flashing here
-(void)flash:(BOOL)startStop{
if(startStop){
// want to start in fully visible
#ifndef __FORIPHONE__

[[self animator] setAlphaValue:1];
#else
[UIView animateWithDuration:currentSpeed animations:^(void) {
self.alpha = 1;
}];
#endif
timit = [NSTimer scheduledTimerWithTimeInterval: currentSpeed target:self selector:@selector(doFlashie:) userInfo:nil repeats: YES];
flashing=YES;
} else {
onoff=YES;
if(timit)
[timit invalidate];
timit = nil;
#ifndef __FORIPHONE__

[[self animator] setAlphaValue:1];
#else
[UIView animateWithDuration:currentSpeed animations:^(void) {
self.alpha = 1;
}];
#endif
flashing=NO;

}
}
// overriding dealloc even with ARC to kill the timer. Not strictly necessary since the timer will
// be cleared at some point and ARC will handle it, but I don't want it to fire off when the text is in an indeterminate state.
-(void)dealloc{
if(timit!=nil)
[timit invalidate];
}
@end