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