EventFieldEditorView.java revision 18ffaa2561cc7dd2e3ef81737e6537931c0a9a11
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 17package com.android.contacts.editor; 18 19import com.android.contacts.R; 20import com.android.contacts.datepicker.DatePicker; 21import com.android.contacts.datepicker.DatePickerDialog; 22import com.android.contacts.datepicker.DatePickerDialog.OnDateSetListener; 23import com.android.contacts.model.AccountType.DataKind; 24import com.android.contacts.model.AccountType.EditField; 25import com.android.contacts.model.AccountType.EventEditType; 26import com.android.contacts.model.EntityDelta; 27import com.android.contacts.model.EntityDelta.ValuesDelta; 28import com.android.contacts.util.DateUtils; 29 30import android.app.Dialog; 31import android.content.Context; 32import android.os.Bundle; 33import android.text.TextUtils; 34import android.util.AttributeSet; 35import android.view.View; 36import android.widget.LinearLayout; 37import android.widget.TextView; 38 39import java.text.ParsePosition; 40import java.util.Calendar; 41import java.util.Date; 42 43/** 44 * Editor that allows editing Events using a {@link DatePickerDialog} 45 */ 46public class EventFieldEditorView extends LabeledEditorView { 47 /** 48 * Exchange requires 8:00 for birthdays 49 */ 50 private final int DEFAULT_HOUR = 8; 51 52 private TextView mDateView; 53 54 public EventFieldEditorView(Context context) { 55 super(context); 56 } 57 58 public EventFieldEditorView(Context context, AttributeSet attrs) { 59 super(context, attrs); 60 } 61 62 public EventFieldEditorView(Context context, AttributeSet attrs, int defStyle) { 63 super(context, attrs, defStyle); 64 } 65 66 @Override 67 protected void onLayout(boolean changed, int l, int t, int r, int b) { 68 super.onLayout(changed, l, t, r, b); 69 70 int l1 = getPaddingLeft(); 71 int t1 = getPaddingTop(); 72 int r1 = getMeasuredWidth() - getPaddingRight(); 73 74 // Fields 75 // Subtract buttons left and right if necessary 76 final int labelWidth = (getLabel() != null) ? getLabel().getMeasuredWidth() : 0; 77 final int deleteWidth = (getDelete() != null) ? getDelete().getMeasuredWidth() : 0; 78 final int r2 = r1 - deleteWidth - labelWidth; 79 if (mDateView != null) mDateView.layout(l1, t1, r2, t1 + mDateView.getMeasuredHeight()); 80 } 81 82 @Override 83 protected int getEditorHeight() { 84 return mDateView != null ? mDateView.getMeasuredHeight() : 0; 85 } 86 87 @Override 88 protected void requestFocusForFirstEditField() { 89 if (mDateView != null) mDateView.requestFocus(); 90 } 91 92 @Override 93 public void setEnabled(boolean enabled) { 94 super.setEnabled(enabled); 95 96 if (mDateView != null) mDateView.setEnabled(enabled); 97 } 98 99 @Override 100 public void setValues(DataKind kind, ValuesDelta entry, EntityDelta state, boolean readOnly, 101 ViewIdGenerator vig) { 102 if (kind.fieldList.size() != 1) throw new IllegalStateException("kind must have 1 field"); 103 super.setValues(kind, entry, state, readOnly, vig); 104 105 if (mDateView == null) { 106 mDateView = new TextView(getContext(), null, android.R.attr.dropDownSpinnerStyle); 107 mDateView.setFocusable(true); 108 mDateView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 109 LayoutParams.WRAP_CONTENT)); 110 mDateView.setEnabled(!readOnly); 111 mDateView.setOnClickListener(new OnClickListener() { 112 @Override 113 public void onClick(View v) { 114 showDialog(R.id.dialog_event_date_picker); 115 } 116 }); 117 addView(mDateView); 118 } 119 120 rebuildDateView(); 121 } 122 123 private void rebuildDateView() { 124 final EditField editField = getKind().fieldList.get(0); 125 final String column = editField.column; 126 final String data = DateUtils.formatDate(getContext(), getEntry().getAsString(column)); 127 mDateView.setText(data); 128 } 129 130 @Override 131 public Dialog createDialog(Bundle bundle) { 132 if (bundle == null) throw new IllegalArgumentException("bundle must not be null"); 133 int dialogId = bundle.getInt(DIALOG_ID_KEY); 134 switch (dialogId) { 135 case R.id.dialog_event_date_picker: 136 return createDatePickerDialog(); 137 default: 138 return super.createDialog(bundle); 139 } 140 } 141 142 @Override 143 protected EventEditType getType() { 144 return (EventEditType) super.getType(); 145 } 146 147 @Override 148 protected void onLabelRebuilt() { 149 // if we changed to a type that requires a year, ensure that it is actually set 150 final String column = getKind().fieldList.get(0).column; 151 final String oldValue = getEntry().getAsString(column); 152 final DataKind kind = getKind(); 153 154 final Calendar calendar = Calendar.getInstance(); 155 final int defaultYear = calendar.get(Calendar.YEAR); 156 157 // Check whether the year is optional 158 final boolean isYearOptional = getType().isYearOptional(); 159 160 if (!isYearOptional) { 161 final ParsePosition position = new ParsePosition(0); 162 final Date date2 = kind.dateFormatWithoutYear.parse(oldValue, position); 163 164 // Don't understand the date, lets not change it 165 if (date2 == null) return; 166 167 // This value is missing the year. Add it now 168 calendar.setTime(date2); 169 calendar.set(defaultYear, calendar.get(Calendar.MONTH), 170 calendar.get(Calendar.DAY_OF_MONTH), DEFAULT_HOUR, 0, 0); 171 172 onFieldChanged(column, kind.dateFormatWithYear.format(calendar.getTime())); 173 rebuildDateView(); 174 } 175 } 176 177 /** 178 * Prepare dialog for entering a date 179 */ 180 private Dialog createDatePickerDialog() { 181 final String column = getKind().fieldList.get(0).column; 182 final String oldValue = getEntry().getAsString(column); 183 final DataKind kind = getKind(); 184 185 final Calendar calendar = Calendar.getInstance(); 186 final int defaultYear = calendar.get(Calendar.YEAR); 187 188 // Check whether the year is optional 189 final boolean isYearOptional = getType().isYearOptional(); 190 191 final int oldYear, oldMonth, oldDay; 192 if (TextUtils.isEmpty(oldValue)) { 193 // Default to January first, 30 years ago 194 oldYear = defaultYear; 195 oldMonth = 0; 196 oldDay = 1; 197 } else { 198 final ParsePosition position = new ParsePosition(0); 199 // Try parsing with year 200 final Date date1 = kind.dateFormatWithYear.parse(oldValue, position); 201 if (date1 != null) { 202 calendar.setTime(date1); 203 oldYear = calendar.get(Calendar.YEAR); 204 oldMonth = calendar.get(Calendar.MONTH); 205 oldDay = calendar.get(Calendar.DAY_OF_MONTH); 206 } else { 207 final Date date2 = kind.dateFormatWithoutYear.parse(oldValue, position); 208 // Don't understand the date, lets not change it 209 if (date2 == null) return null; 210 calendar.setTime(date2); 211 oldYear = isYearOptional ? 0 : defaultYear; 212 oldMonth = calendar.get(Calendar.MONTH); 213 oldDay = calendar.get(Calendar.DAY_OF_MONTH); 214 } 215 } 216 final OnDateSetListener callBack = new OnDateSetListener() { 217 @Override 218 public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) { 219 if (year == 0 && !isYearOptional) throw new IllegalStateException(); 220 final Calendar outCalendar = Calendar.getInstance(); 221 222 // If no year specified, set it to 1900. The format string will ignore that year 223 // For formats other than Exchange, the time of the day is ignored 224 outCalendar.clear(); 225 outCalendar.set(year == 0 ? 1900 : year, monthOfYear, dayOfMonth, 226 DEFAULT_HOUR, 0, 0); 227 228 final String resultString; 229 if (year == 0) { 230 resultString = kind.dateFormatWithoutYear.format(outCalendar.getTime()); 231 } else { 232 resultString = kind.dateFormatWithYear.format(outCalendar.getTime()); 233 } 234 onFieldChanged(column, resultString); 235 rebuildDateView(); 236 } 237 }; 238 final DatePickerDialog resultDialog = new DatePickerDialog(getContext(), callBack, 239 oldYear, oldMonth, oldDay, isYearOptional); 240 return resultDialog; 241 } 242} 243