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