source: releases/Pester/1.0/Source/PSApplication.m @ 111

Last change on this file since 111 was 28, checked in by Nicholas Riley, 20 years ago

Pester 1.0

File size: 6.9 KB
Line 
1//
2//  PSApplication.m
3//  Pester
4//
5//  Created by Nicholas Riley on Fri Oct 11 2002.
6//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
7//
8
9#import "PSApplication.h"
10#import "PSAlarmSetController.h"
11#import "PSAlarmNotifierController.h"
12#import "PSAlarmsController.h"
13#import "PSAlarm.h"
14#import "PSAlarms.h"
15
16@implementation PSApplication
17
18- (void)finishLaunching;
19{
20    appIconImage = [[NSImage imageNamed: @"NSApplicationIcon"] retain];
21    [[NSNotificationCenter defaultCenter] addObserver: [PSAlarmNotifierController class] selector: @selector(controllerWithTimerExpiredNotification:) name: PSAlarmTimerExpiredNotification object: nil];
22    [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(nextAlarmDidChange:) name: PSAlarmsNextAlarmDidChangeNotification object: nil];
23    [PSAlarms setUp];
24    [self setDelegate: self];
25    [super finishLaunching];
26}
27
28- (IBAction)showHelp:(id)sender;
29{
30    [[NSWorkspace sharedWorkspace] openFile: [[NSBundle mainBundle] pathForResource: @"Read Me" ofType: @"rtfd"]];
31}
32
33- (IBAction)orderFrontSetAlarmPanel:(id)sender;
34{
35    [NSApp activateIgnoringOtherApps: YES];
36    [alarmSetController showWindow: self];
37}
38
39- (IBAction)orderFrontAlarmsPanel:(id)sender;
40{
41    [NSApp activateIgnoringOtherApps: YES];
42    if (alarmsController == nil) {
43        alarmsController = [[PSAlarmsController alloc] init];
44    }
45    [alarmsController showWindow: self];
46}
47
48- (void)_resetUpdateTimer;
49{
50    if (dockUpdateTimer != nil) {
51        [dockUpdateTimer invalidate];
52        [dockUpdateTimer release];
53        dockUpdateInterval = 0;
54        dockUpdateTimer = nil;
55    }
56}
57
58- (void)_setUpdateTimerForInterval:(NSTimeInterval)interval alarm:(PSAlarm *)alarm repeats:(BOOL)repeats;
59{
60    dockUpdateTimer = [NSTimer scheduledTimerWithTimeInterval: interval target: self selector: @selector(_updateDockTile:) userInfo: alarm repeats: repeats];
61    [dockUpdateTimer retain];
62    dockUpdateInterval = interval; // because [timer timeInterval] always returns 0 once set
63}
64
65- (void)_updateDockTile:(NSTimer *)timer;
66{
67    PSAlarm *alarm = [timer userInfo];
68    NSTimeInterval alarmInterval;
69    NSString *tileString;
70    if (timer == nil) alarm = [[PSAlarms allAlarms] nextAlarm];
71    if (alarm == nil) return;
72    tileString = [alarm timeRemainingString];
73    {
74        NSMutableDictionary *atts = [NSMutableDictionary dictionary];
75        NSSize imageSize = [appIconImage size];
76        NSImage *tile = [[NSImage alloc] initWithSize: imageSize];
77        NSSize textSize;
78        NSPoint textOrigin;
79        NSRect frameRect;
80        float fontSize = 37;
81       
82        do {
83            fontSize -= 1;
84            [atts setObject: [NSFont boldSystemFontOfSize: fontSize] forKey: NSFontAttributeName];
85            textSize = [tileString sizeWithAttributes: atts];
86        } while (textSize.width > imageSize.width - 8);
87
88        textOrigin = NSMakePoint(imageSize.width / 2 - textSize.width / 2,
89                                 imageSize.height / 2 - textSize.height / 2);
90        frameRect = NSInsetRect(NSMakeRect(textOrigin.x, textOrigin.y, textSize.width, textSize.height),
91                                -4, -2);
92       
93        [tile lockFocus];
94        // draw the grayed-out app icon
95        [appIconImage dissolveToPoint: NSZeroPoint fraction: 0.5];
96        // draw the frame
97        [[NSColor colorWithCalibratedWhite: 0.1 alpha: 0.5] set];
98        NSRectFill(frameRect);
99        // draw a gray two-pixel text shadow
100        [atts setObject: [NSColor grayColor] forKey: NSForegroundColorAttributeName];
101        textOrigin.x++; textOrigin.y--;
102        [tileString drawAtPoint: textOrigin withAttributes: atts];
103        textOrigin.x++; textOrigin.y--;
104        [tileString drawAtPoint: textOrigin withAttributes: atts];
105        // draw white text
106        textOrigin.x -= 2; textOrigin.y += 2;
107        [atts setObject: [NSColor whiteColor] forKey: NSForegroundColorAttributeName];
108        [tileString drawAtPoint: textOrigin withAttributes: atts];
109       
110        [tile unlockFocus];
111        [NSApp setApplicationIconImage: tile];
112        [tile release];
113    }
114    alarmInterval = [alarm interval];
115    // NSLog(@"_updateDockTile > time remaining %@ (%.0lf), last time interval %.0lf", tileString, alarmInterval, dockUpdateInterval);
116    if (alarmInterval > 61) {
117        NSTimeInterval nextUpdate = ((unsigned long long)alarmInterval) % 60;
118        if (nextUpdate <= 1) nextUpdate = 60;
119        [self _resetUpdateTimer];
120        [self _setUpdateTimerForInterval: nextUpdate alarm: alarm repeats: NO];
121        // NSLog(@"_updateDockTile > set timer for %.0lf seconds", nextUpdate);
122    } else if (timer == nil || dockUpdateInterval > 1) {
123        [self _resetUpdateTimer];
124        [self _setUpdateTimerForInterval: 1 alarm: alarm repeats: YES];
125        // NSLog(@"_updateDockTile > set timer for 1 second");
126    } else if (alarmInterval < 2) {
127        [self _resetUpdateTimer];
128    }
129}
130
131- (void)nextAlarmDidChange:(NSNotification *)notification;
132{
133    PSAlarm *nextAlarm = [notification object];
134    // NSLog(@"nextAlarmDidChange: %@", nextAlarm);
135    [self _resetUpdateTimer];
136    if (nextAlarm == nil) {
137        [NSApp setApplicationIconImage: appIconImage];
138    } else {
139        [self _updateDockTile: nil];
140    }
141}
142
143@end
144
145@implementation PSApplication (NSApplicationDelegate)
146
147- (BOOL)applicationShouldHandleReopen:(NSApplication *)sender hasVisibleWindows:(BOOL)flag;
148{
149    if (!flag) [alarmSetController showWindow: self];
150    return YES;
151}
152
153- (NSMenu *)applicationDockMenu:(NSApplication *)sender;
154{
155    NSMenu *dockMenu = [[NSMenu alloc] initWithTitle: @""];
156    PSAlarms *alarms = [PSAlarms allAlarms];
157    PSAlarm *nextAlarm = [alarms nextAlarm];
158    NSMenuItem *item;
159    if (nextAlarm == nil) {
160        [dockMenu addItemWithTitle: @"No Pending Alarms" action: nil keyEquivalent: @""];
161    } else {
162        [dockMenu addItemWithTitle: @"Next Alarm" action: nil keyEquivalent: @""];
163        [dockMenu addItemWithTitle: [NSString stringWithFormat: @"   %@", [nextAlarm message]] action: nil keyEquivalent: @""];
164        [dockMenu addItemWithTitle: [NSString stringWithFormat: @"   %@ %@", [nextAlarm shortDateString], [nextAlarm timeString]] action: nil keyEquivalent: @""];
165        [dockMenu addItemWithTitle: [NSString stringWithFormat: @"   Remaining: %@", [nextAlarm timeRemainingString]] action: nil keyEquivalent: @""];
166    }
167    [dockMenu addItem: [NSMenuItem separatorItem]];
168    item = [dockMenu addItemWithTitle: @"Set AlarmÉ" action: @selector(orderFrontSetAlarmPanel:) keyEquivalent: @""];
169    [item setTarget: self];
170    item = [dockMenu addItemWithTitle: [NSString stringWithFormat: @"All Alarms (%d)É", [alarms alarmCount]] action: @selector(orderFrontAlarmsPanel:) keyEquivalent: @""];
171    [item setTarget: self];
172    return [dockMenu autorelease];
173}
174
175@end
176
177@implementation PSApplication (NSApplicationNotifications)
178
179- (void)applicationWillTerminate:(NSNotification *)notification;
180{
181    [NSApp setApplicationIconImage: appIconImage];
182}
183
184@end
Note: See TracBrowser for help on using the repository browser.