1 /* Copyright (C) 2012 The Android Open Source Project 2 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 */ 15 16 package com.android.calendar.event; 17 18 import android.app.Activity; 19 import android.app.AlertDialog; 20 import android.app.Dialog; 21 import android.app.DialogFragment; 22 import android.content.Context; 23 import android.content.DialogInterface; 24 import android.content.Intent; 25 import android.database.Cursor; 26 import android.os.Bundle; 27 import android.provider.CalendarContract; 28 import android.provider.CalendarContract.Calendars; 29 import android.provider.Settings; 30 import android.text.Editable; 31 import android.text.TextWatcher; 32 import android.text.format.DateUtils; 33 import android.text.format.Time; 34 import android.util.Log; 35 import android.view.LayoutInflater; 36 import android.view.View; 37 import android.widget.Button; 38 import android.widget.EditText; 39 import android.widget.TextView; 40 import android.widget.Toast; 41 42 import com.android.calendar.AsyncQueryService; 43 import com.android.calendar.CalendarController; 44 import com.android.calendar.CalendarController.EventType; 45 import com.android.calendar.CalendarEventModel; 46 import com.android.calendar.GeneralPreferences; 47 import com.android.calendar.R; 48 import com.android.calendar.Utils; 49 50 51 /** 52 * Allows the user to quickly create a new all-day event from the calendar's month view. 53 */ 54 public class CreateEventDialogFragment extends DialogFragment implements TextWatcher { 55 56 private static final String TAG = "CreateEventDialogFragment"; 57 58 private static final int TOKEN_CALENDARS = 1 << 3; 59 60 private static final String KEY_DATE_STRING = "date_string"; 61 private static final String KEY_DATE_IN_MILLIS = "date_in_millis"; 62 private static final String EVENT_DATE_FORMAT = "%a, %b %d, %Y"; 63 64 private AlertDialog mAlertDialog; 65 66 private CalendarQueryService mService; 67 68 private EditText mEventTitle; 69 private View mColor; 70 71 private TextView mCalendarName; 72 private TextView mAccountName; 73 private TextView mDate; 74 private Button mButtonAddEvent; 75 76 private CalendarController mController; 77 private EditEventHelper mEditEventHelper; 78 79 private String mDateString; 80 private long mDateInMillis; 81 82 private CalendarEventModel mModel; 83 private long mCalendarId = -1; 84 private String mCalendarOwner; 85 86 private class CalendarQueryService extends AsyncQueryService { 87 88 /** 89 * @param context 90 */ CalendarQueryService(Context context)91 public CalendarQueryService(Context context) { 92 super(context); 93 } 94 95 @Override onQueryComplete(int token, Object cookie, Cursor cursor)96 public void onQueryComplete(int token, Object cookie, Cursor cursor) { 97 setDefaultCalendarView(cursor); 98 if (cursor != null) { 99 cursor.close(); 100 } 101 } 102 } 103 CreateEventDialogFragment()104 public CreateEventDialogFragment() { 105 // Empty constructor required for DialogFragment. 106 } 107 CreateEventDialogFragment(Time day)108 public CreateEventDialogFragment(Time day) { 109 setDay(day); 110 } 111 setDay(Time day)112 public void setDay(Time day) { 113 mDateString = day.format(EVENT_DATE_FORMAT); 114 mDateInMillis = day.toMillis(true); 115 } 116 117 @Override onCreate(Bundle savedInstanceState)118 public void onCreate(Bundle savedInstanceState) { 119 super.onCreate(savedInstanceState); 120 if (savedInstanceState != null) { 121 mDateString = savedInstanceState.getString(KEY_DATE_STRING); 122 mDateInMillis = savedInstanceState.getLong(KEY_DATE_IN_MILLIS); 123 } 124 } 125 126 @Override onCreateDialog(Bundle savedInstanceState)127 public Dialog onCreateDialog(Bundle savedInstanceState) { 128 final Activity activity = getActivity(); 129 final LayoutInflater layoutInflater = (LayoutInflater) activity 130 .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 131 View view = layoutInflater.inflate(R.layout.create_event_dialog, null); 132 133 mColor = view.findViewById(R.id.color); 134 mCalendarName = (TextView) view.findViewById(R.id.calendar_name); 135 mAccountName = (TextView) view.findViewById(R.id.account_name); 136 137 mEventTitle = (EditText) view.findViewById(R.id.event_title); 138 mEventTitle.addTextChangedListener(this); 139 140 mDate = (TextView) view.findViewById(R.id.event_day); 141 if (mDateString != null) { 142 mDate.setText(mDateString); 143 } 144 145 mAlertDialog = new AlertDialog.Builder(activity) 146 .setTitle(R.string.new_event_dialog_label) 147 .setView(view) 148 .setPositiveButton(R.string.create_event_dialog_save, 149 new DialogInterface.OnClickListener() { 150 151 @Override 152 public void onClick(DialogInterface dialog, int which) { 153 createAllDayEvent(); 154 dismiss(); 155 } 156 }) 157 .setNeutralButton(R.string.edit_label, 158 new DialogInterface.OnClickListener() { 159 160 @Override 161 public void onClick(DialogInterface dialog, int which) { 162 mController.sendEventRelatedEventWithExtraWithTitleWithCalendarId(this, 163 EventType.CREATE_EVENT, -1, mDateInMillis, 164 mDateInMillis + DateUtils.DAY_IN_MILLIS, 0, 0, 165 CalendarController.EXTRA_CREATE_ALL_DAY, -1, 166 mEventTitle.getText().toString(), 167 mCalendarId); 168 dismiss(); 169 } 170 }) 171 .setNegativeButton(android.R.string.cancel, null) 172 .create(); 173 174 return mAlertDialog; 175 } 176 177 @Override onResume()178 public void onResume() { 179 super.onResume(); 180 if (mButtonAddEvent == null) { 181 mButtonAddEvent = mAlertDialog.getButton(DialogInterface.BUTTON_POSITIVE); 182 mButtonAddEvent.setEnabled(mEventTitle.getText().toString().length() > 0); 183 } 184 } 185 186 @Override onSaveInstanceState(Bundle outState)187 public void onSaveInstanceState(Bundle outState) { 188 super.onSaveInstanceState(outState); 189 outState.putString(KEY_DATE_STRING, mDateString); 190 outState.putLong(KEY_DATE_IN_MILLIS, mDateInMillis); 191 } 192 193 @Override onActivityCreated(Bundle args)194 public void onActivityCreated(Bundle args) { 195 super.onActivityCreated(args); 196 final Context context = getActivity(); 197 mController = CalendarController.getInstance(getActivity()); 198 mEditEventHelper = new EditEventHelper(context); 199 mModel = new CalendarEventModel(context); 200 mService = new CalendarQueryService(context); 201 mService.startQuery(TOKEN_CALENDARS, null, Calendars.CONTENT_URI, 202 EditEventHelper.CALENDARS_PROJECTION, 203 EditEventHelper.CALENDARS_WHERE_WRITEABLE_VISIBLE, null, 204 null); 205 } 206 createAllDayEvent()207 private void createAllDayEvent() { 208 mModel.mStart = mDateInMillis; 209 mModel.mEnd = mDateInMillis + DateUtils.DAY_IN_MILLIS; 210 mModel.mTitle = mEventTitle.getText().toString(); 211 mModel.mAllDay = true; 212 mModel.mCalendarId = mCalendarId; 213 mModel.mOwnerAccount = mCalendarOwner; 214 215 if (mEditEventHelper.saveEvent(mModel, null, 0)) { 216 Toast.makeText(getActivity(), R.string.creating_event, Toast.LENGTH_SHORT).show(); 217 } 218 } 219 220 @Override afterTextChanged(Editable s)221 public void afterTextChanged(Editable s) { 222 // Do nothing. 223 } 224 225 @Override beforeTextChanged(CharSequence s, int start, int count, int after)226 public void beforeTextChanged(CharSequence s, int start, int count, int after) { 227 // Do nothing. 228 } 229 230 @Override onTextChanged(CharSequence s, int start, int before, int count)231 public void onTextChanged(CharSequence s, int start, int before, int count) { 232 if (mButtonAddEvent != null) { 233 mButtonAddEvent.setEnabled(s.length() > 0); 234 } 235 } 236 237 // Find the calendar position in the cursor that matches calendar in 238 // preference setDefaultCalendarView(Cursor cursor)239 private void setDefaultCalendarView(Cursor cursor) { 240 if (cursor == null || cursor.getCount() == 0) { 241 // Create an error message for the user that, when clicked, 242 // will exit this activity without saving the event. 243 dismiss(); 244 AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 245 builder.setTitle(R.string.no_syncable_calendars).setIconAttribute( 246 android.R.attr.alertDialogIcon).setMessage(R.string.no_calendars_found) 247 .setPositiveButton(R.string.add_account, new DialogInterface.OnClickListener() { 248 249 @Override 250 public void onClick(DialogInterface dialog, int which) { 251 final Activity activity = getActivity(); 252 if (activity != null) { 253 Intent nextIntent = new Intent(Settings.ACTION_ADD_ACCOUNT); 254 final String[] array = {"com.android.calendar"}; 255 nextIntent.putExtra(Settings.EXTRA_AUTHORITIES, array); 256 nextIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | 257 Intent.FLAG_ACTIVITY_NEW_TASK); 258 activity.startActivity(nextIntent); 259 } 260 } 261 }) 262 .setNegativeButton(android.R.string.no, null); 263 builder.show(); 264 return; 265 } 266 267 268 String defaultCalendar = null; 269 final Activity activity = getActivity(); 270 if (activity != null) { 271 defaultCalendar = Utils.getSharedPreference(activity, 272 GeneralPreferences.KEY_DEFAULT_CALENDAR, (String) null); 273 } else { 274 Log.e(TAG, "Activity is null, cannot load default calendar"); 275 } 276 277 int calendarOwnerIndex = cursor.getColumnIndexOrThrow(Calendars.OWNER_ACCOUNT); 278 int accountNameIndex = cursor.getColumnIndexOrThrow(Calendars.ACCOUNT_NAME); 279 int accountTypeIndex = cursor.getColumnIndexOrThrow(Calendars.ACCOUNT_TYPE); 280 281 cursor.moveToPosition(-1); 282 while (cursor.moveToNext()) { 283 String calendarOwner = cursor.getString(calendarOwnerIndex); 284 if (defaultCalendar == null) { 285 // There is no stored default upon the first time running. Use a primary 286 // calendar in this case. 287 if (calendarOwner != null && 288 calendarOwner.equals(cursor.getString(accountNameIndex)) && 289 !CalendarContract.ACCOUNT_TYPE_LOCAL.equals( 290 cursor.getString(accountTypeIndex))) { 291 setCalendarFields(cursor); 292 return; 293 } 294 } else if (defaultCalendar.equals(calendarOwner)) { 295 // Found the default calendar. 296 setCalendarFields(cursor); 297 return; 298 } 299 } 300 cursor.moveToFirst(); 301 setCalendarFields(cursor); 302 } 303 setCalendarFields(Cursor cursor)304 private void setCalendarFields(Cursor cursor) { 305 int calendarIdIndex = cursor.getColumnIndexOrThrow(Calendars._ID); 306 int colorIndex = cursor.getColumnIndexOrThrow(Calendars.CALENDAR_COLOR); 307 int calendarNameIndex = cursor.getColumnIndexOrThrow(Calendars.CALENDAR_DISPLAY_NAME); 308 int accountNameIndex = cursor.getColumnIndexOrThrow(Calendars.ACCOUNT_NAME); 309 int calendarOwnerIndex = cursor.getColumnIndexOrThrow(Calendars.OWNER_ACCOUNT); 310 311 mCalendarId = cursor.getLong(calendarIdIndex); 312 mCalendarOwner = cursor.getString(calendarOwnerIndex); 313 mColor.setBackgroundColor(Utils.getDisplayColorFromColor(cursor 314 .getInt(colorIndex))); 315 String accountName = cursor.getString(accountNameIndex); 316 String calendarName = cursor.getString(calendarNameIndex); 317 mCalendarName.setText(calendarName); 318 if (calendarName.equals(accountName)) { 319 mAccountName.setVisibility(View.GONE); 320 } else { 321 mAccountName.setVisibility(View.VISIBLE); 322 mAccountName.setText(accountName); 323 } 324 } 325 } 326