• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.contacts.editor;
18 
19 import com.android.contacts.R;
20 import com.android.contacts.datepicker.DatePicker;
21 import com.android.contacts.datepicker.DatePickerDialog;
22 import com.android.contacts.datepicker.DatePickerDialog.OnDateSetListener;
23 import com.android.contacts.model.AccountType.EditField;
24 import com.android.contacts.model.AccountType.EventEditType;
25 import com.android.contacts.model.DataKind;
26 import com.android.contacts.model.EntityDelta;
27 import com.android.contacts.model.EntityDelta.ValuesDelta;
28 import com.android.contacts.util.DateUtils;
29 
30 import android.app.Dialog;
31 import android.content.Context;
32 import android.content.res.Resources;
33 import android.os.Bundle;
34 import android.text.TextUtils;
35 import android.util.AttributeSet;
36 import android.view.View;
37 import android.widget.Button;
38 
39 import java.text.ParsePosition;
40 import java.util.Calendar;
41 import java.util.Date;
42 import java.util.Locale;
43 
44 /**
45  * Editor that allows editing Events using a {@link DatePickerDialog}
46  */
47 public class EventFieldEditorView extends LabeledEditorView {
48     /**
49      * Exchange requires 8:00 for birthdays
50      */
51     private final static int DEFAULT_HOUR = 8;
52 
53     /**
54      * Default string to show when there is no date selected yet.
55      */
56     private String mNoDateString;
57     private int mPrimaryTextColor;
58     private int mSecondaryTextColor;
59 
60     private Button mDateView;
61 
EventFieldEditorView(Context context)62     public EventFieldEditorView(Context context) {
63         super(context);
64     }
65 
EventFieldEditorView(Context context, AttributeSet attrs)66     public EventFieldEditorView(Context context, AttributeSet attrs) {
67         super(context, attrs);
68     }
69 
EventFieldEditorView(Context context, AttributeSet attrs, int defStyle)70     public EventFieldEditorView(Context context, AttributeSet attrs, int defStyle) {
71         super(context, attrs, defStyle);
72     }
73 
74     /** {@inheritDoc} */
75     @Override
onFinishInflate()76     protected void onFinishInflate() {
77         super.onFinishInflate();
78 
79         Resources resources = mContext.getResources();
80         mPrimaryTextColor = resources.getColor(R.color.primary_text_color);
81         mSecondaryTextColor = resources.getColor(R.color.secondary_text_color);
82         mNoDateString = mContext.getString(R.string.event_edit_field_hint_text);
83 
84         mDateView = (Button) findViewById(R.id.date_view);
85         mDateView.setOnClickListener(new OnClickListener() {
86             @Override
87             public void onClick(View v) {
88                 showDialog(R.id.dialog_event_date_picker);
89             }
90         });
91     }
92 
93     @Override
editNewlyAddedField()94     public void editNewlyAddedField() {
95         showDialog(R.id.dialog_event_date_picker);
96     }
97 
98     @Override
requestFocusForFirstEditField()99     protected void requestFocusForFirstEditField() {
100         mDateView.requestFocus();
101     }
102 
103     @Override
setEnabled(boolean enabled)104     public void setEnabled(boolean enabled) {
105         super.setEnabled(enabled);
106 
107         mDateView.setEnabled(!isReadOnly() && enabled);
108     }
109 
110     @Override
setValues(DataKind kind, ValuesDelta entry, EntityDelta state, boolean readOnly, ViewIdGenerator vig)111     public void setValues(DataKind kind, ValuesDelta entry, EntityDelta state, boolean readOnly,
112             ViewIdGenerator vig) {
113         if (kind.fieldList.size() != 1) throw new IllegalStateException("kind must have 1 field");
114         super.setValues(kind, entry, state, readOnly, vig);
115 
116         mDateView.setEnabled(isEnabled() && !readOnly);
117 
118         rebuildDateView();
119     }
120 
rebuildDateView()121     private void rebuildDateView() {
122         final EditField editField = getKind().fieldList.get(0);
123         final String column = editField.column;
124         String data = DateUtils.formatDate(getContext(), getEntry().getAsString(column));
125         if (TextUtils.isEmpty(data)) {
126             mDateView.setText(mNoDateString);
127             mDateView.setTextColor(mSecondaryTextColor);
128             setDeleteButtonVisible(false);
129         } else {
130             mDateView.setText(data);
131             mDateView.setTextColor(mPrimaryTextColor);
132             setDeleteButtonVisible(true);
133         }
134     }
135 
136     @Override
isEmpty()137     public boolean isEmpty() {
138         final EditField editField = getKind().fieldList.get(0);
139         final String column = editField.column;
140         return TextUtils.isEmpty(getEntry().getAsString(column));
141     }
142 
143     @Override
createDialog(Bundle bundle)144     public Dialog createDialog(Bundle bundle) {
145         if (bundle == null) throw new IllegalArgumentException("bundle must not be null");
146         int dialogId = bundle.getInt(DIALOG_ID_KEY);
147         switch (dialogId) {
148             case R.id.dialog_event_date_picker:
149                 return createDatePickerDialog();
150             default:
151                 return super.createDialog(bundle);
152         }
153     }
154 
155     @Override
getType()156     protected EventEditType getType() {
157         return (EventEditType) super.getType();
158     }
159 
160     @Override
onLabelRebuilt()161     protected void onLabelRebuilt() {
162         // if we changed to a type that requires a year, ensure that it is actually set
163         final String column = getKind().fieldList.get(0).column;
164         final String oldValue = getEntry().getAsString(column);
165         final DataKind kind = getKind();
166 
167         final Calendar calendar = Calendar.getInstance(DateUtils.UTC_TIMEZONE, Locale.US);
168         final int defaultYear = calendar.get(Calendar.YEAR);
169 
170         // Check whether the year is optional
171         final boolean isYearOptional = getType().isYearOptional();
172 
173         if (!isYearOptional && !TextUtils.isEmpty(oldValue)) {
174             final ParsePosition position = new ParsePosition(0);
175             final Date date2 = kind.dateFormatWithoutYear.parse(oldValue, position);
176 
177             // Don't understand the date, lets not change it
178             if (date2 == null) return;
179 
180             // This value is missing the year. Add it now
181             calendar.setTime(date2);
182             calendar.set(defaultYear, calendar.get(Calendar.MONTH),
183                     calendar.get(Calendar.DAY_OF_MONTH), DEFAULT_HOUR, 0, 0);
184 
185             onFieldChanged(column, kind.dateFormatWithYear.format(calendar.getTime()));
186             rebuildDateView();
187         }
188     }
189 
190     /**
191      * Prepare dialog for entering a date
192      */
createDatePickerDialog()193     private Dialog createDatePickerDialog() {
194         final String column = getKind().fieldList.get(0).column;
195         final String oldValue = getEntry().getAsString(column);
196         final DataKind kind = getKind();
197 
198         final Calendar calendar = Calendar.getInstance(DateUtils.UTC_TIMEZONE, Locale.US);
199         final int defaultYear = calendar.get(Calendar.YEAR);
200 
201         // Check whether the year is optional
202         final boolean isYearOptional = getType().isYearOptional();
203 
204         final int oldYear, oldMonth, oldDay;
205         if (TextUtils.isEmpty(oldValue)) {
206             // Default to January first, 30 years ago
207             oldYear = defaultYear;
208             oldMonth = 0;
209             oldDay = 1;
210         } else {
211             final ParsePosition position = new ParsePosition(0);
212             // Try parsing with year
213             Date date1 = kind.dateFormatWithYear.parse(oldValue, position);
214             if (date1 == null) {
215                 // If that format does not fit, try guessing the right format
216                 date1 = DateUtils.parseDate(oldValue);
217             }
218             if (date1 != null) {
219                 calendar.setTime(date1);
220                 oldYear = calendar.get(Calendar.YEAR);
221                 oldMonth = calendar.get(Calendar.MONTH);
222                 oldDay = calendar.get(Calendar.DAY_OF_MONTH);
223             } else {
224                 final Date date2 = kind.dateFormatWithoutYear.parse(oldValue, position);
225                 // Don't understand the date, lets not change it
226                 if (date2 == null) return null;
227                 calendar.setTime(date2);
228                 oldYear = isYearOptional ? 0 : defaultYear;
229                 oldMonth = calendar.get(Calendar.MONTH);
230                 oldDay = calendar.get(Calendar.DAY_OF_MONTH);
231             }
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();
237                 final Calendar outCalendar =
238                         Calendar.getInstance(DateUtils.UTC_TIMEZONE, Locale.US);
239 
240                 // If no year specified, set it to 2000 (we could pick any leap year here).
241                 // The format string will ignore that year.
242                 // For formats other than Exchange, the time of the day is ignored
243                 outCalendar.clear();
244                 outCalendar.set(year == 0 ? 2000 : year, monthOfYear, dayOfMonth,
245                         DEFAULT_HOUR, 0, 0);
246 
247                 final String resultString;
248                 if (year == 0) {
249                     resultString = kind.dateFormatWithoutYear.format(outCalendar.getTime());
250                 } else {
251                     resultString = kind.dateFormatWithYear.format(outCalendar.getTime());
252                 }
253 
254                 onFieldChanged(column, resultString);
255                 rebuildDateView();
256             }
257         };
258         final DatePickerDialog resultDialog = new DatePickerDialog(getContext(), callBack,
259                 oldYear, oldMonth, oldDay, isYearOptional);
260         return resultDialog;
261     }
262 
263     /**
264      * @return Default hour which should be used for birthday field.
265      */
getDefaultHourForBirthday()266     public static int getDefaultHourForBirthday() {
267         return DEFAULT_HOUR;
268     }
269 
270     @Override
clearAllFields()271     public void clearAllFields() {
272         // Update UI
273         mDateView.setText(mNoDateString);
274         mDateView.setTextColor(mSecondaryTextColor);
275 
276         // Update state
277         final String column = getKind().fieldList.get(0).column;
278         onFieldChanged(column, "");
279     }
280 }
281