source: trunk/hiptop/pester/net/sabi/pester/AlarmSetDialog.java@ 255

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

Handle time changes by rescheduling (if it's time-based) or just updating the fire time (if it's interval-based, since those use real time when active).

File size: 8.1 KB
Line 
1package net.sabi.pester;
2
3import danger.app.Application;
4import danger.app.Event;
5import danger.audio.ToneClass;
6import danger.audio.ToneRights;
7import danger.internal.Date;
8import danger.ui.Button;
9import danger.ui.CheckBox;
10import danger.ui.Color;
11import danger.ui.DateTimeEditor;
12import danger.ui.DatePicker;
13import danger.ui.DialogWindow;
14import danger.ui.Font;
15import danger.ui.Layout;
16import danger.ui.MenuItem;
17import danger.ui.NumberEditor;
18import danger.ui.Pen;
19import danger.ui.PopupMenu;
20import danger.ui.RadioButton;
21import danger.ui.Rect;
22import danger.ui.RingTonePicker;
23import danger.ui.StaticTextBox;
24import danger.ui.TypeAheadTextField;
25import danger.util.DEBUG;
26
27public class AlarmSetDialog extends DialogWindow
28 implements Resources, Commands {
29
30 private TypeAheadTextField mMessageField;
31 private RadioButton mInButton, mAtButton;
32 private NumberEditor mPeriodField;
33 private PopupMenu mPeriodUnitsPopup;
34 // XXX don't allow <5 second repeating alarms
35 private CheckBox mRepeatCheckBox;
36 private DateTimeEditor mTimeEditor, mDateEditor;
37 private DatePicker mDatePicker;
38 private RingTonePicker mAlertPicker;
39 private Button mDiscardAlarmButton, mSetAlarmButton;
40 private StaticTextBox mStatusBox;
41
42 private Alarm mEditingAlarm;
43 private boolean mAlarmIsNew;
44 private boolean mHaveShownWindow = false;
45
46 private danger.app.Alarm mValidateAlarm;
47
48 public static AlarmSetDialog getDialog() {
49 AlarmSetDialog dialog = (AlarmSetDialog)
50 Application.getCurrentApp().getDialog(ID_ALARM_SET_DIALOG, null);
51 return dialog;
52 }
53
54 public void onDecoded() {
55 setCancelButtonEvent(new Event(this, EVENT_CANCEL_ALARM));
56 mMessageField =
57 (TypeAheadTextField)getDescendantWithID(ID_MESSAGE_FIELD);
58 disableBottomRightButtonOnEmptyField(mMessageField);
59 mInButton = (RadioButton)getDescendantWithID(ID_IN_BUTTON);
60 mAtButton = (RadioButton)getDescendantWithID(ID_AT_BUTTON);
61 mPeriodField = (NumberEditor)getDescendantWithID(ID_PERIOD_FIELD);
62 mPeriodUnitsPopup =
63 (PopupMenu)getDescendantWithID(ID_PERIOD_UNITS_POPUP);
64 mRepeatCheckBox =
65 (CheckBox)getDescendantWithID(ID_PERIOD_REPEAT_CHECKBOX);
66 mTimeEditor = (DateTimeEditor)getDescendantWithID(ID_TIME_EDITOR);
67 mDateEditor = (DateTimeEditor)getDescendantWithID(ID_DATE_EDITOR);
68 mDatePicker = (DatePicker)getDescendantWithID(ID_DATE_PICKER);
69 mAlertPicker = (RingTonePicker)getDescendantWithID(ID_ALERT_PICKER);
70 mSetAlarmButton = (Button)getDescendantWithID(ID_SET_ALARM_BUTTON);
71 mDiscardAlarmButton =
72 (Button)getDescendantWithID(ID_DISCARD_ALARM_BUTTON);
73 mInButton.setValue(1);
74 mDateEditor.limitToDangerEpoch();
75 mAlertPicker.setGroupFilter(ToneClass.FOREGROUND | ToneClass.CUSTOM);
76 mAlertPicker.setRights(ToneRights.FULL);
77 // this doesn't work properly yet
78 // mAlertPicker.setCanRecord(true);
79
80 mStatusBox = new StaticTextBox();
81 mStatusBox.setTransparent(true);
82 mStatusBox.setHasBorder(false);
83 mStatusBox.setFont(Font.findSystemFont());
84 mStatusBox.setAutoResize(false);
85
86 mValidateAlarm = new danger.app.Alarm(1, this);
87
88 super.onDecoded();
89 }
90
91 protected void editDateOrPeriod(Alarm alarm) {
92 boolean usesPeriod = alarm.getUsesPeriod();
93 if (usesPeriod) {
94 int period = alarm.getPeriod();
95 for (int i = mPeriodUnitsPopup.itemCount() - 1 ; i >= 0 ; --i) {
96 int unitsPerSec = mPeriodUnitsPopup.getItem(i).getEvent().data;
97 if (period % unitsPerSec == 0) {
98 mPeriodUnitsPopup.setValue(i);
99 mPeriodField.setValue(period / unitsPerSec);
100 break;
101 }
102 }
103 mRepeatCheckBox.setValue(alarm.getRepeating() ? 1 : 0);
104 }
105
106 Date date = new Date(alarm.getDate());
107 mTimeEditor.setDate(date);
108 mDateEditor.setDate(date);
109 mDatePicker.setDate(date);
110
111 mInButton.setValue(usesPeriod ? 1 : 0);
112 mAtButton.setValue(usesPeriod ? 0 : 1);
113 }
114
115 public void editAlarm(Alarm alarm, boolean asNew) {
116 mEditingAlarm = alarm;
117 mAlarmIsNew = asNew;
118 alarm.beginEditing();
119 if (asNew) {
120 mDiscardAlarmButton.hide();
121 // XXX default to now?
122 } else {
123 mMessageField.setText(alarm.getMessage());
124 mDiscardAlarmButton.show();
125 editDateOrPeriod(alarm);
126 mAlertPicker.setRingTone(mEditingAlarm.getAlert());
127 }
128 validate();
129 Application.registerForEvent(this, Event.EVENT_TIME_CHANGED);
130 show();
131 if (!mHaveShownWindow) {
132 Rect alarmRect = mSetAlarmButton.getFrame();
133 Rect contentRect = getContentRect();
134 mStatusBox.setPosition(contentRect.left + 8, alarmRect.top + 2);
135 mStatusBox.setSize(alarmRect.left - 8, 11);
136 mStatusBox.show();
137 addChild(mStatusBox);
138 mHaveShownWindow = true;
139 setAutoSize(false); // don't resize to contain it next time
140 }
141 }
142
143 protected boolean isIn() {
144 return (mInButton.getValue() == 1);
145 }
146
147 protected int editingInterval() {
148 int itemIndex = mPeriodUnitsPopup.getValue();
149 MenuItem itemAtIndex = mPeriodUnitsPopup.getItem(itemIndex);
150 Event event = itemAtIndex.getEvent();
151 return mPeriodField.getValue() * event.data;
152 }
153
154 protected Date editingDate() {
155 Date date;
156 if (isIn()) {
157 date = new Date();
158 date.addSeconds(editingInterval());
159 } else {
160 // XXX is it necessary to do this, or do the two share the
161 // XXX same physical Date object?
162 date = mDateEditor.getDate();
163 date.setTime(mTimeEditor.getDate().getTime());
164 date.setSeconds(0);
165 }
166 return date;
167 }
168
169 protected boolean isValid() {
170 // doesn't redraw properly otherwise
171 invalidate(mStatusBox.getBounds());
172 if (mMessageField.length() == 0) {
173 mStatusBox.setText("Specify a message.");
174 return false;
175 }
176 Date now = new Date();
177 mDateEditor.min(now);
178 mDatePicker.min(now);
179 Date editingDate = editingDate();
180 if (isIn()) {
181 mValidateAlarm.resetWake(60 - now.getSeconds());
182 } else {
183 int secondsUntilDate =
184 editingDate.getDangerTimeGMT() - now.getDangerTimeGMT();
185 if (secondsUntilDate <= 0) {
186 mStatusBox.setText("Specify a future date.");
187 return false;
188 }
189 mValidateAlarm.resetWake(secondsUntilDate);
190 }
191 mStatusBox.setText(Alarm.dateTimeString(editingDate, true));
192 return true;
193 }
194
195 // XXX make a timer-only version of this which doesn't try to extract
196 // XXX the editing date (it can cause odd behavior by forcing the
197 // XXX NumberEditor to spit out a value)
198 protected void validate() {
199 boolean isValid = isValid();
200 mSetAlarmButton.setEnabled(isValid);
201 if (!isValid)
202 mValidateAlarm.deactivate();
203 }
204
205 protected void stopEditing() {
206 mEditingAlarm = null;
207 mValidateAlarm.deactivate();
208 Application.unregisterForEvent(this, Event.EVENT_TIME_CHANGED);
209 }
210
211 public boolean receiveEvent(Event e) {
212 switch (e.type) {
213 case EVENT_SET_ALARM:
214 if (!isValid())
215 return true;
216 mEditingAlarm.setMessage(mMessageField.toString());
217 if (isIn()) {
218 mEditingAlarm.setPeriod(editingInterval(),
219 mRepeatCheckBox.getValue() == 1);
220 } else {
221 mEditingAlarm.setDate(editingDate());
222 }
223 mEditingAlarm.setAlert(mAlertPicker.getRingTone());
224 // schedule before adding so the tooltip is correct
225 mEditingAlarm.schedule();
226 if (mAlarmIsNew) Alarms.addAlarm(mEditingAlarm);
227 stopEditing();
228 return true;
229 case EVENT_CANCEL_ALARM:
230 if (!mAlarmIsNew) mEditingAlarm.resume();
231 stopEditing();
232 return true;
233 case EVENT_DISCARD_ALARM:
234 // XXX prompt for confirmation
235 stopEditing();
236 return true;
237 case Event.EVENT_TIME_CHANGED: // time on device changed
238 case Event.EVENT_ALARM: // computed time invalid
239 case EVENT_VALIDATE: // something changed
240 validate();
241 return true;
242 case EVENT_IN:
243 mAtButton.setValue(0);
244 validate();
245 return true;
246 case EVENT_AT:
247 mInButton.setValue(0);
248 validate();
249 return true;
250 case EVENT_TIME_EDITOR:
251 validate();
252 return true;
253 case EVENT_DATE_EDITOR_TOOK_FOCUS:
254 Date date = editingDate();
255 if (date.compareTo(new Date()) <= 0) {
256 date.addDays(1);
257 mDatePicker.setDate(date);
258 mDateEditor.setDate(date);
259 }
260 validate();
261 return true;
262 case EVENT_DATE_EDITOR:
263 mDatePicker.setDate(mDateEditor.getDate());
264 validate();
265 return true;
266 case EVENT_DATE_PICKER:
267 mDateEditor.setDate((Date)e.argument);
268 validate();
269 return true;
270 }
271 return super.receiveEvent(e);
272 }
273}
Note: See TracBrowser for help on using the repository browser.