blob: 8afcc0ad3b870ecdbd01c7d37117fd7a51d64788 [file] [log] [blame]
Daniel Lehmann392ccec2010-11-01 20:50:03 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dmitri Plotnikov18ffaa22010-12-03 14:28:00 -080017package com.android.contacts.editor;
Daniel Lehmann392ccec2010-11-01 20:50:03 -070018
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070019import android.app.Dialog;
20import android.content.Context;
21import android.content.res.Resources;
22import android.os.Bundle;
Wenyi Wang2da5d2f2015-09-29 22:15:38 -070023import android.provider.ContactsContract;
24import android.provider.ContactsContract.CommonDataKinds.Event;
Chiao Chenge0b2f1e2012-06-12 13:07:56 -070025import android.text.TextUtils;
26import android.util.AttributeSet;
27import android.view.View;
28import android.widget.Button;
29
Daniel Lehmann392ccec2010-11-01 20:50:03 -070030import com.android.contacts.R;
31import com.android.contacts.datepicker.DatePicker;
32import com.android.contacts.datepicker.DatePickerDialog;
33import com.android.contacts.datepicker.DatePickerDialog.OnDateSetListener;
Yorke Leecd321f62013-10-28 15:20:15 -070034import com.android.contacts.common.model.RawContactDelta;
Chiao Cheng738ff862012-11-30 12:06:03 -080035import com.android.contacts.common.model.ValuesDelta;
Chiao Cheng428f0082012-11-13 18:38:56 -080036import com.android.contacts.common.model.account.AccountType.EditField;
37import com.android.contacts.common.model.account.AccountType.EventEditType;
38import com.android.contacts.common.model.dataitem.DataKind;
Yorke Leecd321f62013-10-28 15:20:15 -070039import com.android.contacts.common.util.CommonDateUtils;
40import com.android.contacts.common.util.DateUtils;
Daniel Lehmann392ccec2010-11-01 20:50:03 -070041
Daniel Lehmann392ccec2010-11-01 20:50:03 -070042import java.text.ParsePosition;
43import java.util.Calendar;
44import java.util.Date;
Daniel Lehmann4b648482011-03-04 14:59:04 -080045import java.util.Locale;
Daniel Lehmann392ccec2010-11-01 20:50:03 -070046
47/**
48 * Editor that allows editing Events using a {@link DatePickerDialog}
49 */
50public class EventFieldEditorView extends LabeledEditorView {
Daniel Lehmann392ccec2010-11-01 20:50:03 -070051
Katherine Kuanfd709032011-08-02 14:18:16 -070052 /**
53 * Default string to show when there is no date selected yet.
54 */
55 private String mNoDateString;
56 private int mPrimaryTextColor;
Brian Attwelld690dff2014-12-02 15:04:56 -080057 private int mHintTextColor;
Katherine Kuanfd709032011-08-02 14:18:16 -070058
Dmitri Plotnikov135b44c2011-01-19 11:05:04 -080059 private Button mDateView;
Daniel Lehmann392ccec2010-11-01 20:50:03 -070060
61 public EventFieldEditorView(Context context) {
62 super(context);
63 }
64
65 public EventFieldEditorView(Context context, AttributeSet attrs) {
66 super(context, attrs);
67 }
68
69 public EventFieldEditorView(Context context, AttributeSet attrs, int defStyle) {
70 super(context, attrs, defStyle);
71 }
72
Katherine Kuan63ffb902011-04-26 19:53:40 -070073 /** {@inheritDoc} */
Daniel Lehmann392ccec2010-11-01 20:50:03 -070074 @Override
Katherine Kuan63ffb902011-04-26 19:53:40 -070075 protected void onFinishInflate() {
76 super.onFinishInflate();
Dmitri Plotnikov91d8e892010-12-07 20:36:51 -080077
Brian Attwellf1402272014-12-16 16:00:08 -080078 Resources resources = getContext().getResources();
Katherine Kuanfd709032011-08-02 14:18:16 -070079 mPrimaryTextColor = resources.getColor(R.color.primary_text_color);
Brian Attwelld690dff2014-12-02 15:04:56 -080080 mHintTextColor = resources.getColor(R.color.editor_disabled_text_color);
Brian Attwellf1402272014-12-16 16:00:08 -080081 mNoDateString = getContext().getString(R.string.event_edit_field_hint_text);
Katherine Kuanfd709032011-08-02 14:18:16 -070082
Katherine Kuan63ffb902011-04-26 19:53:40 -070083 mDateView = (Button) findViewById(R.id.date_view);
84 mDateView.setOnClickListener(new OnClickListener() {
85 @Override
86 public void onClick(View v) {
87 showDialog(R.id.dialog_event_date_picker);
88 }
89 });
Daniel Lehmann392ccec2010-11-01 20:50:03 -070090 }
91
92 @Override
Josh Gargus26918da2012-02-02 16:58:04 -080093 public void editNewlyAddedField() {
94 showDialog(R.id.dialog_event_date_picker);
95 }
96
97 @Override
Daniel Lehmann392ccec2010-11-01 20:50:03 -070098 protected void requestFocusForFirstEditField() {
Katherine Kuan63ffb902011-04-26 19:53:40 -070099 mDateView.requestFocus();
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700100 }
101
102 @Override
103 public void setEnabled(boolean enabled) {
104 super.setEnabled(enabled);
105
Katherine Kuan63ffb902011-04-26 19:53:40 -0700106 mDateView.setEnabled(!isReadOnly() && enabled);
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700107 }
108
109 @Override
Maurice Chu851222a2012-06-21 11:43:08 -0700110 public void setValues(DataKind kind, ValuesDelta entry, RawContactDelta state, boolean readOnly,
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700111 ViewIdGenerator vig) {
112 if (kind.fieldList.size() != 1) throw new IllegalStateException("kind must have 1 field");
113 super.setValues(kind, entry, state, readOnly, vig);
114
Katherine Kuan63ffb902011-04-26 19:53:40 -0700115 mDateView.setEnabled(isEnabled() && !readOnly);
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700116
117 rebuildDateView();
Brian Attwell8f9d84f2014-11-03 23:17:04 -0800118 updateEmptiness();
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700119 }
120
121 private void rebuildDateView() {
122 final EditField editField = getKind().fieldList.get(0);
123 final String column = editField.column;
Yorke Lee4b294d62012-12-19 12:04:38 -0800124 String data = DateUtils.formatDate(getContext(), getEntry().getAsString(column),
125 false /*Use the short DateFormat to ensure that it fits inside the EditText*/);
Dmitri Plotnikov135b44c2011-01-19 11:05:04 -0800126 if (TextUtils.isEmpty(data)) {
Katherine Kuanfd709032011-08-02 14:18:16 -0700127 mDateView.setText(mNoDateString);
Brian Attwelld690dff2014-12-02 15:04:56 -0800128 mDateView.setTextColor(mHintTextColor);
Katherine Kuan5e330ed2011-07-15 15:06:06 -0700129 setDeleteButtonVisible(false);
130 } else {
Katherine Kuanfd709032011-08-02 14:18:16 -0700131 mDateView.setText(data);
132 mDateView.setTextColor(mPrimaryTextColor);
Katherine Kuan5e330ed2011-07-15 15:06:06 -0700133 setDeleteButtonVisible(true);
Dmitri Plotnikov135b44c2011-01-19 11:05:04 -0800134 }
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700135 }
136
Katherine Kuan25914362011-04-29 19:42:01 -0700137 @Override
138 public boolean isEmpty() {
Josh Gargus296cca52011-12-01 17:57:48 -0800139 final EditField editField = getKind().fieldList.get(0);
140 final String column = editField.column;
141 return TextUtils.isEmpty(getEntry().getAsString(column));
Katherine Kuan1b220732011-04-28 18:45:39 -0700142 }
143
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700144 @Override
145 public Dialog createDialog(Bundle bundle) {
146 if (bundle == null) throw new IllegalArgumentException("bundle must not be null");
147 int dialogId = bundle.getInt(DIALOG_ID_KEY);
148 switch (dialogId) {
149 case R.id.dialog_event_date_picker:
150 return createDatePickerDialog();
151 default:
152 return super.createDialog(bundle);
153 }
154 }
155
156 @Override
157 protected EventEditType getType() {
158 return (EventEditType) super.getType();
159 }
160
161 @Override
162 protected void onLabelRebuilt() {
163 // if we changed to a type that requires a year, ensure that it is actually set
164 final String column = getKind().fieldList.get(0).column;
165 final String oldValue = getEntry().getAsString(column);
166 final DataKind kind = getKind();
167
Daniel Lehmann4b648482011-03-04 14:59:04 -0800168 final Calendar calendar = Calendar.getInstance(DateUtils.UTC_TIMEZONE, Locale.US);
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700169 final int defaultYear = calendar.get(Calendar.YEAR);
170
171 // Check whether the year is optional
Jay Shrauner7bcdf512015-05-26 15:45:36 -0700172 final boolean isYearOptional = getType() != null && getType().isYearOptional();
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700173
Dmitri Plotnikov17e6f9d2011-01-03 11:27:49 -0800174 if (!isYearOptional && !TextUtils.isEmpty(oldValue)) {
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700175 final ParsePosition position = new ParsePosition(0);
Walter Jang5f8932d2016-10-12 17:45:44 -0700176 final Date date2 = kind.dateFormatWithoutYear == null
177 ? null : kind.dateFormatWithoutYear.parse(oldValue, position);
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700178
179 // Don't understand the date, lets not change it
180 if (date2 == null) return;
181
182 // This value is missing the year. Add it now
183 calendar.setTime(date2);
184 calendar.set(defaultYear, calendar.get(Calendar.MONTH),
Yorke Leecd321f62013-10-28 15:20:15 -0700185 calendar.get(Calendar.DAY_OF_MONTH), CommonDateUtils.DEFAULT_HOUR, 0, 0);
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700186
Walter Jang5f8932d2016-10-12 17:45:44 -0700187 final String formattedDate = kind.dateFormatWithYear == null
188 ? null : kind.dateFormatWithYear.format(calendar.getTime());
189 if (formattedDate == null) return;
190
191 onFieldChanged(column, formattedDate);
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700192 rebuildDateView();
193 }
194 }
195
196 /**
197 * Prepare dialog for entering a date
198 */
199 private Dialog createDatePickerDialog() {
200 final String column = getKind().fieldList.get(0).column;
201 final String oldValue = getEntry().getAsString(column);
202 final DataKind kind = getKind();
203
Daniel Lehmann4b648482011-03-04 14:59:04 -0800204 final Calendar calendar = Calendar.getInstance(DateUtils.UTC_TIMEZONE, Locale.US);
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700205 final int defaultYear = calendar.get(Calendar.YEAR);
206
207 // Check whether the year is optional
208 final boolean isYearOptional = getType().isYearOptional();
209
210 final int oldYear, oldMonth, oldDay;
Yorke Leeec6bfa02012-12-19 15:45:37 -0800211
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700212 if (TextUtils.isEmpty(oldValue)) {
Yorke Lee78253a92012-12-04 12:22:12 -0800213 // Default to the current date
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700214 oldYear = defaultYear;
Yorke Lee78253a92012-12-04 12:22:12 -0800215 oldMonth = calendar.get(Calendar.MONTH);
216 oldDay = calendar.get(Calendar.DAY_OF_MONTH);
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700217 } else {
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700218 // Try parsing with year
Yorke Leeec6bfa02012-12-19 15:45:37 -0800219 Calendar cal = DateUtils.parseDate(oldValue, false);
220 if (cal != null) {
221 if (DateUtils.isYearSet(cal)) {
222 oldYear = cal.get(Calendar.YEAR);
Daniel Lehmann5a7a2692012-08-03 21:39:01 -0700223 } else {
Yorke Leeec6bfa02012-12-19 15:45:37 -0800224 //cal.set(Calendar.YEAR, 0);
Daniel Lehmann5a7a2692012-08-03 21:39:01 -0700225 oldYear = isYearOptional ? DatePickerDialog.NO_YEAR : defaultYear;
Daniel Lehmann5a7a2692012-08-03 21:39:01 -0700226 }
Yorke Leeec6bfa02012-12-19 15:45:37 -0800227 oldMonth = cal.get(Calendar.MONTH);
228 oldDay = cal.get(Calendar.DAY_OF_MONTH);
229 } else {
230 return null;
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700231 }
232 }
233 final OnDateSetListener callBack = new OnDateSetListener() {
234 @Override
235 public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
236 if (year == 0 && !isYearOptional) throw new IllegalStateException();
Daniel Lehmann4b648482011-03-04 14:59:04 -0800237 final Calendar outCalendar =
238 Calendar.getInstance(DateUtils.UTC_TIMEZONE, Locale.US);
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700239
Daniel Lehmann11812c52012-03-29 17:50:29 -0700240 // If no year specified, set it to 2000 (we could pick any leap year here).
241 // The format string will ignore that year.
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700242 // For formats other than Exchange, the time of the day is ignored
243 outCalendar.clear();
Daniel Lehmann5a7a2692012-08-03 21:39:01 -0700244 outCalendar.set(year == DatePickerDialog.NO_YEAR ? 2000 : year, monthOfYear,
Yorke Leecd321f62013-10-28 15:20:15 -0700245 dayOfMonth, CommonDateUtils.DEFAULT_HOUR, 0, 0);
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700246
247 final String resultString;
248 if (year == 0) {
Walter Jang5f8932d2016-10-12 17:45:44 -0700249 resultString = kind.dateFormatWithoutYear == null
250 ? null : kind.dateFormatWithoutYear.format(outCalendar.getTime());
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700251 } else {
Walter Jang5f8932d2016-10-12 17:45:44 -0700252 resultString = kind.dateFormatWithYear == null
253 ? null : kind.dateFormatWithYear.format(outCalendar.getTime());
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700254 }
Walter Jang5f8932d2016-10-12 17:45:44 -0700255 if (resultString == null) return;
256
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700257 onFieldChanged(column, resultString);
258 rebuildDateView();
259 }
260 };
261 final DatePickerDialog resultDialog = new DatePickerDialog(getContext(), callBack,
262 oldYear, oldMonth, oldDay, isYearOptional);
263 return resultDialog;
264 }
Daisuke Miyakawad37a8912011-03-27 09:35:28 -0700265
Katherine Kuan2293e552011-07-21 20:25:44 -0700266 @Override
267 public void clearAllFields() {
268 // Update UI
Katherine Kuanfd709032011-08-02 14:18:16 -0700269 mDateView.setText(mNoDateString);
Brian Attwelld690dff2014-12-02 15:04:56 -0800270 mDateView.setTextColor(mHintTextColor);
Katherine Kuan2293e552011-07-21 20:25:44 -0700271
272 // Update state
273 final String column = getKind().fieldList.get(0).column;
274 onFieldChanged(column, "");
275 }
Wenyi Wang2da5d2f2015-09-29 22:15:38 -0700276
277 /**
278 * Sets the typeColumn of entry as TYPE_BIRTHDAY and calls rebuildValues() to refresh the view.
279 */
280 public void restoreBirthday() {
281 saveValue(getKind().typeColumn, Integer.toString(Event.TYPE_BIRTHDAY));
282 rebuildValues();
283 }
284
285 /**
286 * EventEditType Birthday:
287 * rawValue=3 labelRes=17039911 secondary=false specificMax=1 customColumn=null
288 * mYearOptional=true
289 */
290 public boolean isBirthdayType(){
291 final EventEditType eventType = getType();
292 return eventType.rawValue == Event.TYPE_BIRTHDAY && !eventType.secondary
293 && eventType.specificMax == 1 && eventType.customColumn == null
294 && eventType.isYearOptional();
295 }
Daniel Lehmann392ccec2010-11-01 20:50:03 -0700296}