source: trunk/Cocoa/Pester/Source/PSAlarms.m@ 28

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

Pester 1.0

File size: 4.7 KB
Line 
1//
2// PSAlarms.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 "PSAlarms.h"
10#import "PSAlarm.h"
11
12NSString * const PSAlarmsDidChangeNotification = @"PSAlarmsDidChangeNotification";
13NSString * const PSAlarmsNextAlarmDidChangeNotification = @"PSAlarmsNextAlarmDidChangeNotification";
14
15static NSString * const PSPendingAlarms = @"Pester pending alarms"; // NSUserDefaults key
16
17static PSAlarms *PSAlarmsAllAlarms = nil;
18
19@interface PSAlarms (Private)
20
21- (void)_updateNextAlarm;
22
23@end
24
25@implementation PSAlarms
26
27+ (void)setUp;
28{
29 if (PSAlarmsAllAlarms == nil) {
30 PSAlarmsAllAlarms = [[self alloc] init];
31 [PSAlarmsAllAlarms _updateNextAlarm]; // only generate notifications after singleton established
32 }
33}
34
35+ (PSAlarms *)allAlarms;
36{
37 NSAssert(PSAlarmsAllAlarms != nil, @"Attempt to use +[PSAlarms allAlarms] before setup complete");
38 return PSAlarmsAllAlarms;
39}
40
41- (void)_updateNextAlarm;
42{
43 NSEnumerator *e;
44 PSAlarm *alarm, *oldNextAlarm = nextAlarm;
45 [nextAlarm release];
46 nextAlarm = nil;
47 // sort alarms so earliest is first
48 [alarms sortUsingSelector: @selector(compare:)];
49 // find first un-expired alarm
50 e = [alarms objectEnumerator];
51 while ( (alarm = [e nextObject]) != nil) {
52 if ([alarm isValid]) {
53 nextAlarm = [alarm retain];
54 break;
55 }
56 }
57 if (oldNextAlarm != nextAlarm)
58 [[NSNotificationCenter defaultCenter] postNotificationName: PSAlarmsNextAlarmDidChangeNotification object: nextAlarm];
59}
60
61- (id)init;
62{
63 if ( (self = [super init]) != nil) {
64 alarms = [[NSMutableArray alloc] init];
65 NS_DURING
66 NSArray *alarmsData = [[NSUserDefaults standardUserDefaults] arrayForKey: PSPendingAlarms];
67 NSEnumerator *e = [alarmsData objectEnumerator];
68 NSData *alarmData;
69 PSAlarm *alarm;
70 while ( (alarmData = [e nextObject]) != nil) {
71 alarm = [NSUnarchiver unarchiveObjectWithData: alarmData];
72 if (alarm != nil)
73 [alarms addObject: alarm];
74 }
75 NS_HANDLER
76 // XXX need better error handling here, don't stomp on data
77 NSLog(@"An error occurred while attempting to restore the alarm list: %@", localException);
78 NS_ENDHANDLER
79 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_alarmTimerSet:) name: PSAlarmTimerSetNotification object: nil];
80 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_alarmTimerExpired:) name: PSAlarmTimerExpiredNotification object: nil];
81 }
82 return self;
83}
84
85- (void)dealloc;
86{
87 [alarms release];
88 [[NSNotificationCenter defaultCenter] removeObserver: self];
89 [super dealloc];
90}
91
92- (void)_changed;
93{
94 NSMutableArray *alarmsData = [[NSMutableArray alloc] init];
95 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
96 NSEnumerator *e;
97 PSAlarm *alarm;
98 [self _updateNextAlarm];
99 // NSLog(@"PSAlarms _changed:\n%@", alarms);
100 // archive
101 e = [alarms objectEnumerator];
102 while ( (alarm = [e nextObject]) != nil) {
103 [alarmsData addObject: [NSArchiver archivedDataWithRootObject: alarm]];
104 }
105 [defaults setObject: alarmsData forKey: PSPendingAlarms];
106 [defaults synchronize];
107 [alarmsData release];
108 [[NSNotificationCenter defaultCenter] postNotificationName: PSAlarmsDidChangeNotification object: self];
109}
110
111- (void)_alarmTimerExpired:(NSNotification *)notification;
112{
113 [alarms removeObject: [notification object]];
114 [self _changed];
115}
116
117- (void)_alarmTimerSet:(NSNotification *)notification;
118{
119 [alarms addObject: [notification object]];
120 [self _changed];
121}
122
123- (PSAlarm *)nextAlarm;
124{
125 return nextAlarm;
126}
127
128- (int)alarmCount;
129{
130 return [alarms count];
131}
132
133- (PSAlarm *)alarmAtIndex:(int)index;
134{
135 return [alarms objectAtIndex: index];
136}
137
138- (void)removeAlarmAtIndex:(int)index;
139{
140 [(PSAlarm *)[alarms objectAtIndex: index] cancel];
141 [alarms removeObjectAtIndex: index];
142}
143
144- (void)removeAlarmsAtIndices:(NSArray *)indices;
145{
146 NSEnumerator *e = [indices objectEnumerator];
147 NSNumber *n;
148 int indexCount = [indices count], i = 0, alarmIndex;
149 int *indexArray = (int *)malloc(indexCount * sizeof(int));
150 NS_DURING
151 while ( (n = [e nextObject]) != nil) {
152 alarmIndex = [n intValue];
153 [(PSAlarm *)[alarms objectAtIndex: alarmIndex] cancel];
154 indexArray[i] = alarmIndex;
155 i++;
156 }
157 [alarms removeObjectsFromIndices: indexArray numIndices: indexCount];
158 [self _changed];
159 NS_HANDLER
160 free(indexArray);
161 [self _changed];
162 [localException raise];
163 NS_ENDHANDLER
164}
165
166@end
Note: See TracBrowser for help on using the repository browser.