Browse Source

Added Otacon Alert Animation, testing alert functionality

Thomas Buck 8 years ago
parent
commit
06cda087ad

+ 2
- 2
OtaClock/Base.lproj/MainMenu.xib View File

@@ -273,9 +273,9 @@
273 273
             <point key="canvasLocation" x="292.5" y="80.5"/>
274 274
         </menu>
275 275
         <datePicker verticalHuggingPriority="750" id="A2I-e6-ur5">
276
-            <rect key="frame" x="0.0" y="0.0" width="278" height="148"/>
276
+            <rect key="frame" x="0.0" y="0.0" width="200" height="31"/>
277 277
             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
278
-            <datePickerCell key="cell" borderStyle="bezel" alignment="left" datePickerStyle="clockAndCalendar" id="aSU-YP-y5q">
278
+            <datePickerCell key="cell" borderStyle="bezel" alignment="left" id="aSU-YP-y5q">
279 279
                 <font key="font" metaFont="system"/>
280 280
                 <calendarDate key="date" timeIntervalSinceReferenceDate="-595929600" calendarFormat="%Y-%m-%d %H:%M:%S %z">
281 281
                     <!--1982-02-12 16:00:00 +0000-->

+ 21
- 0
OtaClock/Images.xcassets/otacon_1.imageset/Contents.json View File

@@ -0,0 +1,21 @@
1
+{
2
+  "images" : [
3
+    {
4
+      "idiom" : "universal",
5
+      "scale" : "1x",
6
+      "filename" : "otacon_1.png"
7
+    },
8
+    {
9
+      "idiom" : "universal",
10
+      "scale" : "2x"
11
+    },
12
+    {
13
+      "idiom" : "universal",
14
+      "scale" : "3x"
15
+    }
16
+  ],
17
+  "info" : {
18
+    "version" : 1,
19
+    "author" : "xcode"
20
+  }
21
+}

BIN
OtaClock/Images.xcassets/otacon_1.imageset/otacon_1.png View File


+ 21
- 0
OtaClock/Images.xcassets/otacon_2.imageset/Contents.json View File

@@ -0,0 +1,21 @@
1
+{
2
+  "images" : [
3
+    {
4
+      "idiom" : "universal",
5
+      "scale" : "1x",
6
+      "filename" : "otacon_2.png"
7
+    },
8
+    {
9
+      "idiom" : "universal",
10
+      "scale" : "2x"
11
+    },
12
+    {
13
+      "idiom" : "universal",
14
+      "scale" : "3x"
15
+    }
16
+  ],
17
+  "info" : {
18
+    "version" : 1,
19
+    "author" : "xcode"
20
+  }
21
+}

BIN
OtaClock/Images.xcassets/otacon_2.imageset/otacon_2.png View File


+ 21
- 0
OtaClock/Images.xcassets/otacon_3.imageset/Contents.json View File

@@ -0,0 +1,21 @@
1
+{
2
+  "images" : [
3
+    {
4
+      "idiom" : "universal",
5
+      "scale" : "1x",
6
+      "filename" : "otacon_3.png"
7
+    },
8
+    {
9
+      "idiom" : "universal",
10
+      "scale" : "2x"
11
+    },
12
+    {
13
+      "idiom" : "universal",
14
+      "scale" : "3x"
15
+    }
16
+  ],
17
+  "info" : {
18
+    "version" : 1,
19
+    "author" : "xcode"
20
+  }
21
+}

BIN
OtaClock/Images.xcassets/otacon_3.imageset/otacon_3.png View File


+ 1
- 1
OtaClock/Info.plist View File

@@ -19,7 +19,7 @@
19 19
 	<key>CFBundleSignature</key>
20 20
 	<string>????</string>
21 21
 	<key>CFBundleVersion</key>
22
-	<string>291</string>
22
+	<string>371</string>
23 23
 	<key>LSApplicationCategoryType</key>
24 24
 	<string>public.app-category.utilities</string>
25 25
 	<key>LSMinimumSystemVersion</key>

+ 46
- 3
OtaClock/MainWindow.m View File

@@ -31,6 +31,12 @@
31 31
 
32 32
 #define MAX_BLINK_DELAY 5.0
33 33
 #define UNBLINK_DELAY 0.1
34
+#define TIME_KEEPING_DELAY 0.25
35
+
36
+// The shadow is not properly recomputed if we don't do it multiple times
37
+#define ANIMATION_SHADOW_HACK 3
38
+#define ALARM_ANIMATION_DELAY (0.25 / ANIMATION_SHADOW_HACK)
39
+#define ALARM_ANIMATION_DELAY_END 3.0
34 40
 
35 41
 @interface MainWindow ()
36 42
 
@@ -137,7 +143,6 @@
137 143
     [self unblink]; // Schedule next blinking
138 144
     
139 145
     // Start time keeping
140
-    [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(updateTime:) userInfo:nil repeats:YES];
141 146
     [self updateTime:nil];
142 147
     
143 148
     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
@@ -167,8 +172,45 @@
167 172
     [self setFrame:frame display:YES];
168 173
 }
169 174
 
175
+- (void)drawAnimation:(NSNumber *)anim {
176
+    if ([anim integerValue] > (3 * ANIMATION_SHADOW_HACK)) {
177
+        [[self.mainView render] drawAnimation:0]; // reset
178
+    } else {
179
+        [[self.mainView render] drawAnimation:([anim integerValue] / ANIMATION_SHADOW_HACK)];
180
+    }
181
+    
182
+    if ([anim integerValue] < (3 * ANIMATION_SHADOW_HACK)) {
183
+        [self performSelector:@selector(drawAnimation:) withObject:[NSNumber numberWithInteger:([anim integerValue] + 1)] afterDelay:ALARM_ANIMATION_DELAY];
184
+    } else if ([anim integerValue] < (4 * ANIMATION_SHADOW_HACK)) {
185
+        [self performSelector:@selector(drawAnimation:) withObject:[NSNumber numberWithInteger:([anim integerValue] + 1)] afterDelay:ALARM_ANIMATION_DELAY_END];
186
+    }
187
+    
188
+    [self invalidateShadow];
189
+    self.mainView.needsDisplay = YES;
190
+}
191
+
170 192
 - (void)updateTime:(id)sender {
171
-    [[self.mainView render] drawWithDate:[NSDate date]];
193
+    [self performSelector:@selector(updateTime:) withObject:nil afterDelay:TIME_KEEPING_DELAY];
194
+    
195
+    // Check if a second went by
196
+    NSDate *now = [NSDate date];
197
+    NSDateComponents *components = [[NSCalendar currentCalendar] components:NSSecondCalendarUnit fromDate:now];
198
+    static NSInteger lastSec = -1;
199
+    if (lastSec == [components second]) {
200
+        return;
201
+    }
202
+    lastSec = [components second];
203
+    
204
+    [[self.mainView render] drawWithDate:now];
205
+    [[self.mainView render] blinkDots];
206
+    
207
+    NSTimeInterval in = [now timeIntervalSinceDate:self.alarmDatePicker.dateValue];
208
+    if ((in >= -0.5) && (in <= 0.5)) {
209
+        // We have reached the alarm time
210
+        NSLog(@"Alarm time reached!");
211
+        [self drawAnimation:[NSNumber numberWithInteger:1]];
212
+    }
213
+    
172 214
     self.mainView.needsDisplay = YES;
173 215
 }
174 216
 
@@ -193,7 +235,8 @@
193 235
 }
194 236
 
195 237
 - (IBAction)alarmDateSelected:(id)sender {
196
-    // TODO do something with this alarm time...
238
+    [[self.mainView render] drawAlarmDate:self.alarmDatePicker.dateValue];
239
+    self.mainView.needsDisplay = YES;
197 240
     
198 241
     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
199 242
     [defaults setObject:self.alarmDatePicker.dateValue forKey:CONFIG_ALARM_TIME];

+ 3
- 0
OtaClock/Render.h View File

@@ -15,6 +15,9 @@
15 15
 - (id)initWithParent:(MainView *)par;
16 16
 - (NSSize)baseSize;
17 17
 
18
+- (void)blinkDots;
19
+- (void)drawAnimation:(NSInteger)state;
20
+- (void)drawAlarmDate:(NSDate *)alarm;
18 21
 - (void)drawDate:(BOOL)draw;
19 22
 - (void)drawWithDate:(NSDate *)date;
20 23
 - (void)drawWithEye:(NSInteger)eyeIndex;

+ 77
- 14
OtaClock/Render.m View File

@@ -12,7 +12,10 @@
12 12
 #define FULL_IMAGE_WIDTH 86
13 13
 #define FULL_IMAGE_HEIGHT 80
14 14
 #define BUBBLE_Y_OFFSET 45
15
-#define OTACON_X_OFFSET 1
15
+#define OTACON_0_X_OFFSET 1
16
+#define OTACON_1_X_OFFSET 0
17
+#define OTACON_2_X_OFFSET -6
18
+#define OTACON_3_X_OFFSET -6
16 19
 #define EYE_X_OFFSET 60
17 20
 #define EYE_Y_OFFSET 45
18 21
 
@@ -66,12 +69,13 @@
66 69
 @interface Render ()
67 70
 
68 71
 @property (assign) CGImageRef otaconGraphic, bubbleGraphic, alarmGraphic, blankGraphic;
72
+@property (assign) CGImageRef otacon1Graphic, otacon2Graphic, otacon3Graphic;
69 73
 @property (assign) CGImageRef eye0, eye1, eye2, eye3, eye4, dotSmallGraphic, dotLargeGraphic;
70 74
 @property (assign) CGImageRef fontMonday, fontTuesday, fontWednesday, fontThursday, fontFriday, fontSaturday, fontSunday;
71 75
 @property (assign) CGImageRef fontSmall1, fontSmall2, fontSmall3, fontSmall4, fontSmall5, fontSmall6, fontSmall7, fontSmall8, fontSmall9, fontSmall0;
72 76
 @property (assign) CGImageRef fontLarge1, fontLarge2, fontLarge3, fontLarge4, fontLarge5, fontLarge6, fontLarge7, fontLarge8, fontLarge9, fontLarge0;
73 77
 
74
-@property (assign) NSInteger eyeToDraw, dayOfWeek;
78
+@property (assign) NSInteger eyeToDraw, dayOfWeek, animState;
75 79
 @property (assign) NSInteger dateDigit0, dateDigit1, dateDigit2, dateDigit3;
76 80
 @property (assign) NSInteger alarmDigit0, alarmDigit1, alarmDigit2, alarmDigit3;
77 81
 @property (assign) NSInteger timeDigit0, timeDigit1, timeDigit2, timeDigit3, timeDigit4, timeDigit5;
@@ -87,12 +91,13 @@
87 91
 @implementation Render
88 92
 
89 93
 @synthesize otaconGraphic, bubbleGraphic, alarmGraphic, blankGraphic;
94
+@synthesize otacon1Graphic, otacon2Graphic, otacon3Graphic;
90 95
 @synthesize eye0, eye1, eye2, eye3, eye4, dotSmallGraphic, dotLargeGraphic;
91 96
 @synthesize fontMonday, fontTuesday, fontWednesday, fontThursday, fontFriday, fontSaturday, fontSunday;
92 97
 @synthesize fontSmall1, fontSmall2, fontSmall3, fontSmall4, fontSmall5, fontSmall6, fontSmall7, fontSmall8, fontSmall9, fontSmall0;
93 98
 @synthesize fontLarge1, fontLarge2, fontLarge3, fontLarge4, fontLarge5, fontLarge6, fontLarge7, fontLarge8, fontLarge9, fontLarge0;
94 99
 
95
-@synthesize eyeToDraw, dayOfWeek;
100
+@synthesize eyeToDraw, dayOfWeek, animState;
96 101
 @synthesize dateDigit0, dateDigit1, dateDigit2, dateDigit3;
97 102
 @synthesize alarmDigit0, alarmDigit1, alarmDigit2, alarmDigit3;
98 103
 @synthesize timeDigit0, timeDigit1, timeDigit2, timeDigit3, timeDigit4, timeDigit5;
@@ -179,6 +184,9 @@
179 184
     NSImage *dotsSmallImage = [NSImage imageNamed:@"dots_small"];
180 185
     NSImage *dotsLargeImage = [NSImage imageNamed:@"dots_large"];
181 186
     NSImage *blankImage = [NSImage imageNamed:@"blank"];
187
+    NSImage *otacon1Image = [NSImage imageNamed:@"otacon_1"];
188
+    NSImage *otacon2Image = [NSImage imageNamed:@"otacon_2"];
189
+    NSImage *otacon3Image = [NSImage imageNamed:@"otacon_3"];
182 190
     
183 191
     NSGraphicsContext *context = [NSGraphicsContext graphicsContextWithAttributes:nil];
184 192
     
@@ -193,6 +201,9 @@
193 201
     eye2 = [eye2Image CGImageForProposedRect:nil context:context hints:nil];
194 202
     eye3 = [eye3Image CGImageForProposedRect:nil context:context hints:nil];
195 203
     eye4 = [eye4Image CGImageForProposedRect:nil context:context hints:nil];
204
+    otacon1Graphic = [otacon1Image CGImageForProposedRect:nil context:context hints:nil];
205
+    otacon2Graphic = [otacon2Image CGImageForProposedRect:nil context:context hints:nil];
206
+    otacon3Graphic = [otacon3Image CGImageForProposedRect:nil context:context hints:nil];
196 207
     
197 208
     CGImageRef fontDays = [fontDaysImage CGImageForProposedRect:nil context:context hints:nil];
198 209
     NSRect rectDay;
@@ -270,6 +281,7 @@
270 281
     
271 282
     drawContext = CGBitmapContextCreate(NULL, fullSize.width, fullSize.height, 8, 0, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault);
272 283
     
284
+    animState = 0;
273 285
     eyeToDraw = 0;
274 286
     dayOfWeek = 0;
275 287
     dateDigit0 = 1;
@@ -320,6 +332,39 @@
320 332
     } \
321 333
 } while (0);
322 334
 
335
+- (void)blinkDots {
336
+    timeDots = !timeDots;
337
+    if ((alarmDigit0 != -1) || (alarmDigit1 != -1) || (alarmDigit2 != -1) || (alarmDigit3 != -1)) {
338
+        alarmDots = timeDots;
339
+    }
340
+}
341
+
342
+- (void)drawAnimation:(NSInteger)state {
343
+    if (animState != state) {
344
+        [[self.parent window] invalidateShadow];
345
+    }
346
+    animState = state;
347
+}
348
+
349
+- (void)drawAlarmDate:(NSDate *)alarm {
350
+    if (alarm == nil) {
351
+        alarmDigit0 = -1;
352
+        alarmDigit1 = -1;
353
+        alarmDigit2 = -1;
354
+        alarmDigit3 = -1;
355
+        alarmSign = NO;
356
+        alarmDots = NO;
357
+        return;
358
+    }
359
+    
360
+    alarmSign = YES;
361
+    alarmDots = YES;
362
+    
363
+    NSDateComponents *components = [[NSCalendar currentCalendar] components:(NSHourCalendarUnit | NSMinuteCalendarUnit) fromDate:alarm];
364
+    CONVERT_DECIMAL([components hour], alarmDigit0, alarmDigit1);
365
+    CONVERT_DECIMAL([components minute], alarmDigit2, alarmDigit3);
366
+}
367
+
323 368
 - (void)drawDate:(BOOL)draw {
324 369
     drawDate = draw;
325 370
 }
@@ -470,19 +515,37 @@
470 515
         CGContextDrawImage(drawContext, size, [self smallHelper:alarmDigit3]);
471 516
     }
472 517
     
473
-    // Draw Otacon
474
-    size.size.width = CGImageGetWidth(otaconGraphic);
475
-    size.size.height = CGImageGetHeight(otaconGraphic);
476 518
     size.origin = NSZeroPoint;
477
-    size.origin.x = CGImageGetWidth(bubbleGraphic) + OTACON_X_OFFSET;
478
-    CGContextDrawImage(drawContext, size, otaconGraphic);
519
+    if (animState == 0) {
520
+        // Draw Otacon
521
+        size.size.width = CGImageGetWidth(otaconGraphic);
522
+        size.size.height = CGImageGetHeight(otaconGraphic);
523
+        size.origin.x = CGImageGetWidth(bubbleGraphic) + OTACON_0_X_OFFSET;
524
+        CGContextDrawImage(drawContext, size, otaconGraphic);
479 525
     
480
-    // Draw eyes
481
-    size.size.width = CGImageGetWidth([self eyeHelper:eyeToDraw]);
482
-    size.size.height = CGImageGetHeight([self eyeHelper:eyeToDraw]);
483
-    size.origin.x = EYE_X_OFFSET;
484
-    size.origin.y = EYE_Y_OFFSET;
485
-    CGContextDrawImage(drawContext, size, [self eyeHelper:eyeToDraw]);
526
+        // Draw eyes
527
+        size.size.width = CGImageGetWidth([self eyeHelper:eyeToDraw]);
528
+        size.size.height = CGImageGetHeight([self eyeHelper:eyeToDraw]);
529
+        size.origin.x = EYE_X_OFFSET;
530
+        size.origin.y = EYE_Y_OFFSET;
531
+        CGContextDrawImage(drawContext, size, [self eyeHelper:eyeToDraw]);
532
+    } else if (animState == 1) {
533
+        size.size.width = CGImageGetWidth(otacon1Graphic);
534
+        size.size.height = CGImageGetHeight(otacon1Graphic);
535
+        size.origin.x = CGImageGetWidth(bubbleGraphic) + OTACON_1_X_OFFSET;
536
+        CGContextDrawImage(drawContext, size, otacon1Graphic);
537
+    } else if (animState == 2) {
538
+        size.size.width = CGImageGetWidth(otacon2Graphic);
539
+        size.size.height = CGImageGetHeight(otacon2Graphic);
540
+        size.origin.x = CGImageGetWidth(bubbleGraphic) + OTACON_2_X_OFFSET;
541
+        CGContextDrawImage(drawContext, size, otacon2Graphic);
542
+    } else {
543
+        size.size.width = CGImageGetWidth(otacon3Graphic);
544
+        size.size.height = CGImageGetHeight(otacon3Graphic);
545
+        size.origin.x = CGImageGetWidth(bubbleGraphic) + OTACON_3_X_OFFSET;
546
+        CGContextDrawImage(drawContext, size, otacon3Graphic);
547
+        
548
+    }
486 549
     
487 550
     // Render resulting canvas into bitmap and scale this into our window
488 551
     CGImageRef drawnImage = CGBitmapContextCreateImage(drawContext);

Loading…
Cancel
Save