Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
240 lines (193 sloc) 6.86 KB
//
// MTILcdView.m
// Copyright 2009 Ryan Morlok
// http://softwareblog.morlok.net/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#import "MTILcdView.h"
#define LCD_DRAWING_UNSCALED_HEIGHT 90.0
#define LCD_DRAWING_UNSCALED_WIDTH 50.0
#define LCD_DRAWING_BETWEEN_DIGIT_SPACE 10.0
// The elements of the LCD digit are numbered as follows:
//
// /----3----\
// | |
// 2 4
// | |
// \ /
// ----7----
// / \
// | |
// 1 5
// | |
// \----6----/
//
// The following constants translate these positions into a bitmask
#define LCD_POS_1 0x01
#define LCD_POS_2 0x02
#define LCD_POS_3 0x04
#define LCD_POS_4 0x08
#define LCD_POS_5 0x10
#define LCD_POS_6 0x20
#define LCD_POS_7 0x40
// Translates a character into a bitmask for the LCD elements
NSUInteger BitmaskForDigit(char c)
{
switch (c) {
case '0' : return LCD_POS_1 | LCD_POS_2 | LCD_POS_3 | LCD_POS_4 | LCD_POS_5 | LCD_POS_6;
case '1' : return LCD_POS_4 | LCD_POS_5;
case '2' : return LCD_POS_3 | LCD_POS_4 | LCD_POS_7 | LCD_POS_1 | LCD_POS_6;
case '3' : return LCD_POS_3 | LCD_POS_4 | LCD_POS_7 | LCD_POS_5 | LCD_POS_6;
case '4' : return LCD_POS_2 | LCD_POS_7 | LCD_POS_4 | LCD_POS_5;
case '5' : return LCD_POS_3 | LCD_POS_2 | LCD_POS_7 | LCD_POS_5 | LCD_POS_6;
case '6' : return LCD_POS_3 | LCD_POS_2 | LCD_POS_7 | LCD_POS_1 | LCD_POS_6 | LCD_POS_5;
case '7' : return LCD_POS_3 | LCD_POS_4 | LCD_POS_5;
case '8' : return LCD_POS_1 | LCD_POS_2 | LCD_POS_3 | LCD_POS_4 | LCD_POS_5 | LCD_POS_6 | LCD_POS_7;
case '9' : return LCD_POS_2 | LCD_POS_3 | LCD_POS_4 | LCD_POS_5 | LCD_POS_6 | LCD_POS_7;
default : return 0;
}
}
@implementation MTILcdView
#pragma mark Private Methods
- (void) drawColonToContext:(CGContextRef)context
{
CGFloat size = 0.85 * LCD_DRAWING_BETWEEN_DIGIT_SPACE;
CGContextSaveGState(context);
CGContextSetFillColorWithColor(context, litColor);
CGContextAddEllipseInRect(context, CGRectMake((LCD_DRAWING_BETWEEN_DIGIT_SPACE - size)/2.0, 25.0 - (size/2.0), size, size));
CGContextAddEllipseInRect(context, CGRectMake((LCD_DRAWING_BETWEEN_DIGIT_SPACE - size)/2.0, 65.0 - (size/2.0), size, size));
CGContextFillPath(context);
CGContextRestoreGState(context);
}
- (void) drawDigit:(NSUInteger)digitDef toContext:(CGContextRef)context
{
CGContextSaveGState(context);
CGMutablePathRef myPath = CGPathCreateMutable();
CGPathMoveToPoint(myPath, NULL, 5.0, 1.0);
CGPathAddLineToPoint(myPath, NULL, 0.0, 6.0);
CGPathAddLineToPoint(myPath, NULL, 0.0, 34.0);
CGPathAddLineToPoint(myPath, NULL, 5.0, 39.0);
CGPathAddLineToPoint(myPath, NULL, 10.0, 34.0);
CGPathAddLineToPoint(myPath, NULL, 10.0, 6.0);
CGPathCloseSubpath(myPath);
CGContextSetFillColorWithColor(context, (digitDef & LCD_POS_1 ? litColor : dimColor));
CGContextTranslateCTM(context, 0.0, 5.0);
CGContextAddPath(context, myPath);
CGContextFillPath(context);
CGContextSetFillColorWithColor(context, (digitDef & LCD_POS_2 ? litColor : dimColor));
CGContextTranslateCTM(context, 0.0, 40.0);
CGContextAddPath(context, myPath);
CGContextFillPath(context);
CGContextSetFillColorWithColor(context, (digitDef & LCD_POS_3 ? litColor : dimColor));
CGContextTranslateCTM(context, 5.0, 45.0);
CGContextRotateCTM(context, -M_PI / 2.0);
CGContextAddPath(context, myPath);
CGContextFillPath(context);
CGContextSetFillColorWithColor(context, (digitDef & LCD_POS_4 ? litColor : dimColor));
CGContextTranslateCTM(context, 5.0, 45.0);
CGContextRotateCTM(context, -M_PI / 2.0);
CGContextAddPath(context, myPath);
CGContextFillPath(context);
CGContextSetFillColorWithColor(context, (digitDef & LCD_POS_5 ? litColor : dimColor));
CGContextTranslateCTM(context, 0.0, 40.0);
CGContextAddPath(context, myPath);
CGContextFillPath(context);
CGContextSetFillColorWithColor(context, (digitDef & LCD_POS_6 ? litColor : dimColor));
CGContextTranslateCTM(context, 5.0, 45.0);
CGContextRotateCTM(context, -M_PI / 2.0);
CGContextAddPath(context, myPath);
CGContextFillPath(context);
CGContextSetFillColorWithColor(context, (digitDef & LCD_POS_7 ? litColor : dimColor));
CGContextTranslateCTM(context, 40.0, 0.0);
CGContextAddPath(context, myPath);
CGContextFillPath(context);
CGPathRelease(myPath);
CGContextRestoreGState(context);
}
- (CGAffineTransform) scaleTranformForFrame
{
// Compute how much we should scale our drawing based on the
// needed height versus the height that is available.
CGFloat scale = [self bounds].size.height / LCD_DRAWING_UNSCALED_HEIGHT;
return CGAffineTransformMakeScale(scale, scale);
}
#pragma mark Public Methods
@synthesize litColor;
@synthesize dimColor;
@synthesize text;
- (void) setLitColor:(CGColorRef)color
{
if( color == litColor )
return;
CGColorRelease(litColor);
litColor = CGColorRetain(color);
[self setNeedsDisplay];
}
- (void) setDimColor:(CGColorRef)color
{
if( color == dimColor )
return;
CGColorRelease(dimColor);
dimColor = CGColorRetain(color);
[self setNeedsDisplay];
}
- (void) setText:(NSString*)t
{
if( text == t )
return;
[text release];
text = [t retain];
[self setNeedsDisplay];
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Nothing to see here...
}
return self;
}
- (void)drawRect:(CGRect)rect {
CGContextRef myContext = UIGraphicsGetCurrentContext();
// Transform coordinate system to account for different origin points
CGContextTranslateCTM(myContext, 0.0, rect.size.height);
CGContextScaleCTM(myContext, 1.0, -1.0);
// Scale the drawing for the current size of the view
CGContextConcatCTM(myContext, [self scaleTranformForFrame]);
// Draw the digits
for(NSUInteger i = 0; i < text.length; i++) {
if( ':' == [text characterAtIndex:i] ) {
// Colon is special case that fits in the normal space between two numbers
CGContextSaveGState(myContext);
if( i > 0 )
CGContextTranslateCTM(myContext, LCD_DRAWING_UNSCALED_WIDTH, 0);
[self drawColonToContext:myContext];
CGContextRestoreGState(myContext);
} else {
if( i > 0 )
CGContextTranslateCTM(myContext, LCD_DRAWING_UNSCALED_WIDTH + LCD_DRAWING_BETWEEN_DIGIT_SPACE, 0);
[self drawDigit:BitmaskForDigit([text characterAtIndex:i]) toContext:myContext];
}
}
}
- (void)dealloc
{
[text release];
CGColorRelease(litColor);
CGColorRelease(dimColor);
text = nil;
litColor = NULL;
dimColor = NULL;
[super dealloc];
}
@end