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
16package com.android.calendar.event;
17
18import android.app.Activity;
19import android.app.AlertDialog;
20import android.app.Dialog;
21import android.app.DialogFragment;
22import android.content.Context;
23import android.content.DialogInterface;
24import android.content.Intent;
25import android.database.Cursor;
26import android.os.Bundle;
27import android.provider.CalendarContract;
28import android.provider.CalendarContract.Calendars;
29import android.provider.Settings;
30import android.text.Editable;
31import android.text.TextWatcher;
32import android.text.format.DateUtils;
33import android.text.format.Time;
34import android.util.Log;
35import android.view.LayoutInflater;
36import android.view.View;
37import android.widget.Button;
38import android.widget.EditText;
39import android.widget.TextView;
40import android.widget.Toast;
41
42import com.android.calendar.AsyncQueryService;
43import com.android.calendar.CalendarController;
44import com.android.calendar.CalendarController.EventType;
45import com.android.calendar.CalendarEventModel;
46import com.android.calendar.GeneralPreferences;
47import com.android.calendar.R;
48import 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 */
54public 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         */
91        public CalendarQueryService(Context context) {
92            super(context);
93        }
94
95        @Override
96        public void onQueryComplete(int token, Object cookie, Cursor cursor) {
97            setDefaultCalendarView(cursor);
98            if (cursor != null) {
99                cursor.close();
100            }
101        }
102    }
103
104    public CreateEventDialogFragment() {
105        // Empty constructor required for DialogFragment.
106    }
107
108    public CreateEventDialogFragment(Time day) {
109        setDay(day);
110    }
111
112    public void setDay(Time day) {
113        mDateString = day.format(EVENT_DATE_FORMAT);
114        mDateInMillis = day.toMillis(true);
115    }
116
117    @Override
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
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
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
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
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
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
221    public void afterTextChanged(Editable s) {
222        // Do nothing.
223    }
224
225    @Override
226    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
227        // Do nothing.
228    }
229
230    @Override
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
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
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