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

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

Refactor editing, coalese Alarms and alarm list. Try (and fail) to recognize exit from alarm time editor.

File size: 6.4 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.flush();
81 return byteStream.toByteArray();
82 } catch (Exception e) {
83 // XXX do something
84 }
85 return null;
86 }
87
88 public void fromByteArray(byte[] data) {
89 try {
90 ByteArrayInputStream byteStream = new ByteArrayInputStream(data);
91 DataInputStream dataStream = new DataInputStream(byteStream);
92
93 byte version = dataStream.readByte();
94 if (version != VERSION_1) {
95 // XXX barf
96 }
97 mMessage = dataStream.readUTF();
98 mPeriod = dataStream.readInt();
99 mType = dataStream.readInt();
100 } catch (Exception e) {
101 // XXX do something
102 }
103 }
104
105 void beginEditing() {
106 mState = STATE_EDITING;
107 mAlarm.deactivate();
108 }
109
110 public static int secondsFromNow(Date date) {
111 return date.getDangerTimeGMT() - new Date().getDangerTimeGMT();
112 }
113
114 protected int remainingInterval() {
115 return secondsFromNow(mDate);
116 }
117
118 void resume() {
119 mState = STATE_SCHEDULED;
120 int interval = remainingInterval();
121 if (interval < 0) interval = 0;
122 mAlarm.resetWake(interval);
123 DEBUG.p("resetWake: " + description() + " - " + interval + "s left");
124 update();
125 }
126
127 void schedule() {
128 if (getUsesPeriod()) {
129 mDate = new Date();
130 mDate.addSeconds(mPeriod);
131 }
132 resume();
133 }
134
135 void dismiss() {
136 if (getRepeating())
137 schedule();
138 else
139 ((StdActiveList)getDelegate()).removeItem(this);
140 }
141
142 void cancel() {
143 mState = STATE_INVALID;
144 mAlarm.deactivate();
145 }
146
147 public String description() {
148 StringBuffer sb = new StringBuffer();
149 switch (mState) {
150 case STATE_INVALID: sb.append("invalid "); break;
151 case STATE_EDITING: sb.append("editing "); break;
152 case STATE_SCHEDULED: sb.append("scheduled "); break;
153 }
154 switch (mType) {
155 case TYPE_PERIODIC:
156 sb.append("periodic (").append(mPeriod).append("s) "); break;
157 case TYPE_PERIODIC_REPEATING:
158 sb.append("repeating periodic (").append(mPeriod).append("s) ");
159 break;
160 case TYPE_DATE:
161 sb.append("date (").append(getDateTimeString()).append(") "); break;
162 }
163 sb.append("alarm: ");
164 sb.append('"').append(mMessage).append('"');
165 return sb.toString();
166 }
167
168 public static String dateTimeString(Date date, boolean relative) {
169 if (date == null)
170 return null;
171 String layout = LocaleUtils.getDateTimePattern();
172 String dateFormat = LocaleUtils.getMediumDateFormat();
173 String dateString;
174 String timeFormat;
175 if (relative) {
176 timeFormat = LocaleUtils.getShortTimeFormat();
177 int daysFromToday = date.getDaysBetween(new Date());
178 if (daysFromToday == 0)
179 dateString = "Today"; // XXX localize
180 else if (daysFromToday == 1)
181 dateString = "Tomorrow"; // XXX localize
182 else if (daysFromToday < 7)
183 dateString = date.getDayString();
184 else
185 dateString = DateFormat.withFormat(dateFormat, date);
186 } else {
187 dateString = DateFormat.withFormat(dateFormat, date);
188 timeFormat = LocaleUtils.getMediumTimeFormat();
189 }
190 String timeString = DateFormat.withFormat(timeFormat, date);
191 return StringFormat.withFormat(layout, timeString, dateString);
192 }
193
194 protected static void addUnit(StringBuffer sb, int n, String unit) {
195 if (n == 0) return;
196 if (sb.length() > 0) sb.append(", ");
197 if (n == 1) sb.append("one ").append(unit);
198 else sb.append(n).append(' ').append(unit).append("s");
199 }
200
201 public static String intervalString(int i) { // XXX localize
202 if (i < 0)
203 return "expired";
204 StringBuffer sb = new StringBuffer();
205 if (i < 60) {
206 addUnit(sb, i, "second");
207 } else {
208 i /= 60; // minutes
209 if (i < 24 * 60) {
210 addUnit(sb, i / 60, "hour");
211 addUnit(sb, i % 60, "minute");
212 } else {
213 i /= 60; // hours
214 if (i < 365) {
215 addUnit(sb, i / 24, "day");
216 addUnit(sb, i % 24, "hour");
217 } else {
218 i /= 24; // days
219 addUnit(sb, i / 365, "year"); // XXX actually 365.242199
220 addUnit(sb, i % 365, "day");
221 }
222 }
223 }
224 return sb.toString();
225 }
226
227 public String getDateTimeString(boolean relative) {
228 return dateTimeString(mDate, relative);
229 }
230
231 public String getDateTimeString() {
232 return getDateTimeString(false);
233 }
234
235 public String getIntervalString() {
236 return intervalString(remainingInterval());
237 }
238
239 public String toString() {
240 return getDateTimeString(true) + " - " + mMessage;
241 }
242
243 public static final int TYPE_PERIODIC = 0;
244 public static final int TYPE_PERIODIC_REPEATING = 1;
245 public static final int TYPE_DATE = 2;
246
247 public static final int STATE_INVALID = 0;
248 public static final int STATE_EDITING = 1;
249 public static final int STATE_SCHEDULED = 2;
250}
Note: See TracBrowser for help on using the repository browser.