source: trunk/hiptop/pester/net/sabi/pester/Alarm.java@ 253

Last change on this file since 253 was 253, checked in by Nicholas Riley, 18 years ago

Add timer in alarm set dialog to update alarm time display. Send events on number picker accept (work around probable bug). Fixed cancel not cancelling if you're using a fixed-time alarm.

File size: 6.8 KB
Line 
1package net.sabi.pester;
2
3import java.io.ByteArrayInputStream;
4import java.io.ByteArrayOutputStream;
5import java.io.DataInputStream;
6import java.io.DataOutputStream;
7import danger.app.Application;
8import danger.audio.RingToneObject;
9import danger.internal.Date;
10import danger.util.LocaleUtils;
11import danger.util.StdActiveList;
12import danger.util.StdActiveObject;
13import danger.util.DEBUG;
14import danger.util.format.DateFormat;
15import danger.util.format.StringFormat;
16
17public class Alarm extends StdActiveObject {
18 private static final int VERSION_1 = 1;
19
20 // persisted
21 private String mMessage;
22 private int mType;
23 private int mPeriod;
24 private Date mDate;
25 private RingToneObject mAlert;
26
27 // transient
28 private int mState;
29 private danger.app.Alarm mAlarm;
30
31 public Alarm() {
32 mState = STATE_INVALID;
33 mAlarm = new danger.app.Alarm(0, Application.getCurrentApp(), this);
34 }
35
36 public String getMessage() {
37 return mMessage;
38 }
39 public int getPeriod() {
40 return mPeriod;
41 }
42 public boolean getUsesPeriod() {
43 return mType != TYPE_DATE;
44 }
45 public boolean getRepeating() {
46 return mType == TYPE_PERIODIC_REPEATING;
47 }
48 public Date getDate() {
49 return mDate;
50 }
51 public RingToneObject getAlert() {
52 return mAlert;
53 }
54
55 public void setMessage(String message) {
56 mMessage = message;
57 }
58 public void setPeriod(int period, boolean repeating) {
59 mType = repeating ? TYPE_PERIODIC_REPEATING : TYPE_PERIODIC;
60 mPeriod = period;
61 }
62 public void setDate(Date date) {
63 mType = TYPE_DATE;
64 mDate = date;
65 }
66 public void setAlert(RingToneObject alert) {
67 mAlert = alert.isValid() ? alert : null;
68 }
69
70 public byte[] toByteArray() {
71 try {
72 ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
73 DataOutputStream dataStream = new DataOutputStream(byteStream);
74
75 dataStream.writeByte(VERSION_1);
76 dataStream.writeUTF(mMessage);
77 dataStream.writeInt(mPeriod);
78 dataStream.writeInt(mDate.getUnixTimeGMT());
79 dataStream.writeInt(mType);
80 dataStream.writeInt(mAlert == null ? 0 : mAlert.getID());
81 dataStream.flush();
82 return byteStream.toByteArray();
83 } catch (Exception e) {
84 // XXX do something
85 DEBUG.p("failed to write alarm:" + e);
86 }
87 return null;
88 }
89
90 public void fromByteArray(byte[] data) {
91 try {
92 ByteArrayInputStream byteStream = new ByteArrayInputStream(data);
93 DataInputStream dataStream = new DataInputStream(byteStream);
94
95 byte version = dataStream.readByte();
96 if (version != VERSION_1) {
97 // XXX barf
98 }
99 mMessage = dataStream.readUTF();
100 mPeriod = dataStream.readInt();
101 mDate = new Date(dataStream.readInt());
102 mType = dataStream.readInt();
103 int alertID = dataStream.readInt();
104 mAlert = (alertID == 0 ? null : new RingToneObject(alertID));
105 } catch (Exception e) {
106 // XXX do something
107 DEBUG.p("failed to read alarm:" + e);
108 }
109 }
110
111 void beginEditing() {
112 mState = STATE_EDITING;
113 mAlarm.deactivate();
114 }
115
116 public static int secondsFromNow(Date date) {
117 return date.getDangerTimeGMT() - new Date().getDangerTimeGMT();
118 }
119
120 protected int remainingInterval() {
121 return secondsFromNow(mDate);
122 }
123
124 // XXX trigger on EVENT_TIME_CHANGED
125 void resume() {
126 mState = STATE_SCHEDULED;
127 int interval = remainingInterval();
128 if (interval < 0) interval = 0;
129 mAlarm.resetWake(interval);
130 DEBUG.p("resetWake: " + description() + " - " + interval + "s left");
131 update();
132 }
133
134 void schedule() {
135 if (getUsesPeriod()) {
136 mDate = new Date();
137 mDate.addSeconds(mPeriod);
138 }
139 resume();
140 }
141
142 void dismiss() {
143 if (getRepeating())
144 schedule();
145 else
146 ((StdActiveList)getDelegate()).removeItem(this);
147 }
148
149 void cancel() {
150 mState = STATE_INVALID;
151 mAlarm.deactivate();
152 }
153
154 public String description() {
155 StringBuffer sb = new StringBuffer();
156 switch (mState) {
157 case STATE_INVALID: sb.append("invalid "); break;
158 case STATE_EDITING: sb.append("editing "); break;
159 case STATE_SCHEDULED: sb.append("scheduled "); break;
160 }
161 switch (mType) {
162 case TYPE_PERIODIC:
163 sb.append("periodic (").append(mPeriod).append("s) "); break;
164 case TYPE_PERIODIC_REPEATING:
165 sb.append("repeating periodic (").append(mPeriod).append("s) ");
166 break;
167 case TYPE_DATE:
168 sb.append("date (").append(getDateTimeString()).append(") "); break;
169 }
170 sb.append("alarm: ");
171 sb.append('"').append(mMessage).append('"');
172 return sb.toString();
173 }
174
175 public static String dateTimeString(Date date, boolean relative) {
176 if (date == null)
177 return null;
178 String layout = LocaleUtils.getDateTimePattern();
179 String dateFormat = LocaleUtils.getMediumDateFormat();
180 String dateString;
181 String timeFormat;
182 if (relative) {
183 timeFormat = LocaleUtils.getShortTimeFormat();
184 int daysFromToday = date.getDaysBetween(new Date());
185 if (daysFromToday == 0)
186 dateString = "Today"; // XXX localize
187 else if (daysFromToday == 1)
188 dateString = "Tomorrow"; // XXX localize
189 else if (daysFromToday < 7)
190 dateString = date.getDayString();
191 else
192 dateString = DateFormat.withFormat(dateFormat, date);
193 } else {
194 dateString = DateFormat.withFormat(dateFormat, date);
195 timeFormat = LocaleUtils.getMediumTimeFormat();
196 }
197 String timeString = DateFormat.withFormat(timeFormat, date);
198 return StringFormat.withFormat(layout, timeString, dateString);
199 }
200
201 protected static void addUnit(StringBuffer sb, int n, String unit) {
202 if (n == 0) return;
203 if (sb.length() > 0) sb.append(", ");
204 if (n == 1) sb.append("one ").append(unit);
205 else sb.append(n).append(' ').append(unit).append("s");
206 }
207
208 public static String intervalString(int i) { // XXX localize
209 if (i < 0)
210 return "expired";
211 StringBuffer sb = new StringBuffer();
212 if (i < 60) {
213 addUnit(sb, i, "second");
214 } else {
215 i /= 60; // minutes
216 if (i < 24 * 60) {
217 addUnit(sb, i / 60, "hour");
218 addUnit(sb, i % 60, "minute");
219 } else {
220 i /= 60; // hours
221 if (i < 365) {
222 addUnit(sb, i / 24, "day");
223 addUnit(sb, i % 24, "hour");
224 } else {
225 i /= 24; // days
226 addUnit(sb, i / 365, "year"); // XXX actually 365.242199
227 addUnit(sb, i % 365, "day");
228 }
229 }
230 }
231 return sb.toString();
232 }
233
234 public String getDateTimeString(boolean relative) {
235 return dateTimeString(mDate, relative);
236 }
237
238 public String getDateTimeString() {
239 return getDateTimeString(false);
240 }
241
242 public String getIntervalString() {
243 return intervalString(remainingInterval());
244 }
245
246 public String toString() {
247 return getDateTimeString(true) + " - " + mMessage;
248 }
249
250 public static final int TYPE_PERIODIC = 0;
251 public static final int TYPE_PERIODIC_REPEATING = 1;
252 public static final int TYPE_DATE = 2;
253
254 public static final int STATE_INVALID = 0;
255 public static final int STATE_EDITING = 1;
256 public static final int STATE_SCHEDULED = 2;
257}
Note: See TracBrowser for help on using the repository browser.