Home | History | Annotate | Download | only in calendar
      1 /*
      2  * Copyright (C) 2013 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.calendar;
     18 
     19 import android.app.Activity;
     20 import android.app.Dialog;
     21 import android.content.ContentUris;
     22 import android.content.ContentValues;
     23 import android.content.Context;
     24 import android.database.Cursor;
     25 import android.net.Uri;
     26 import android.os.Bundle;
     27 import android.provider.CalendarContract.Calendars;
     28 import android.provider.CalendarContract.Colors;
     29 import android.util.SparseIntArray;
     30 
     31 import com.android.colorpicker.ColorPickerDialog;
     32 import com.android.colorpicker.ColorPickerSwatch.OnColorSelectedListener;
     33 import com.android.colorpicker.HsvColorComparator;
     34 
     35 import java.util.ArrayList;
     36 import java.util.Arrays;
     37 
     38 public class CalendarColorPickerDialog extends ColorPickerDialog {
     39 
     40     private static final int NUM_COLUMNS = 4;
     41 
     42     private static final String KEY_CALENDAR_ID = "calendar_id";
     43     private static final String KEY_COLOR_KEYS = "color_keys";
     44 
     45     private static final int TOKEN_QUERY_CALENDARS = 1 << 1;
     46     private static final int TOKEN_QUERY_COLORS = 1 << 2;
     47 
     48     static final String[] CALENDARS_PROJECTION = new String[] {
     49             Calendars.ACCOUNT_NAME,
     50             Calendars.ACCOUNT_TYPE,
     51             Calendars.CALENDAR_COLOR
     52     };
     53 
     54     static final int CALENDARS_INDEX_ACCOUNT_NAME = 0;
     55     static final int CALENDARS_INDEX_ACCOUNT_TYPE = 1;
     56     static final int CALENDARS_INDEX_CALENDAR_COLOR = 2;
     57 
     58     static final String[] COLORS_PROJECTION = new String[] {
     59             Colors.COLOR,
     60             Colors.COLOR_KEY
     61     };
     62 
     63     static final String COLORS_WHERE = Colors.ACCOUNT_NAME + "=? AND " + Colors.ACCOUNT_TYPE +
     64             "=? AND " + Colors.COLOR_TYPE + "=" + Colors.TYPE_CALENDAR;
     65 
     66     public static final int COLORS_INDEX_COLOR = 0;
     67     public static final int COLORS_INDEX_COLOR_KEY = 1;
     68 
     69 
     70     private QueryService mService;
     71     private SparseIntArray mColorKeyMap = new SparseIntArray();
     72     private long mCalendarId;
     73 
     74     private class QueryService extends AsyncQueryService {
     75 
     76         private QueryService(Context context) {
     77             super(context);
     78         }
     79 
     80         @Override
     81         protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
     82             // If the query didn't return a cursor for some reason return
     83             if (cursor == null) {
     84                 return;
     85             }
     86 
     87             // If the Activity is finishing, then close the cursor.
     88             // Otherwise, use the new cursor in the adapter.
     89             final Activity activity = getActivity();
     90             if (activity == null || activity.isFinishing()) {
     91                 cursor.close();
     92                 return;
     93             }
     94 
     95             switch (token) {
     96                 case TOKEN_QUERY_CALENDARS:
     97                     if (!cursor.moveToFirst()) {
     98                         cursor.close();
     99                         dismiss();
    100                         break;
    101                     }
    102                     mSelectedColor = Utils.getDisplayColorFromColor(
    103                             cursor.getInt(CALENDARS_INDEX_CALENDAR_COLOR));
    104                     Uri uri = Colors.CONTENT_URI;
    105                     String[] args = new String[] {
    106                             cursor.getString(CALENDARS_INDEX_ACCOUNT_NAME),
    107                             cursor.getString(CALENDARS_INDEX_ACCOUNT_TYPE) };
    108                     cursor.close();
    109                     startQuery(TOKEN_QUERY_COLORS, null, uri, COLORS_PROJECTION, COLORS_WHERE,
    110                             args, null);
    111                     break;
    112                 case TOKEN_QUERY_COLORS:
    113                     if (!cursor.moveToFirst()) {
    114                         cursor.close();
    115                         dismiss();
    116                         break;
    117                     }
    118                     mColorKeyMap.clear();
    119                     ArrayList<Integer> colors = new ArrayList<Integer>();
    120                     do
    121                     {
    122                         int colorKey = cursor.getInt(COLORS_INDEX_COLOR_KEY);
    123                         int rawColor = cursor.getInt(COLORS_INDEX_COLOR);
    124                         int displayColor = Utils.getDisplayColorFromColor(rawColor);
    125                         mColorKeyMap.put(displayColor, colorKey);
    126                         colors.add(displayColor);
    127                     } while (cursor.moveToNext());
    128                     Integer[] colorsToSort = colors.toArray(new Integer[colors.size()]);
    129                     Arrays.sort(colorsToSort, new HsvColorComparator());
    130                     mColors = new int[colorsToSort.length];
    131                     for (int i = 0; i < mColors.length; i++) {
    132                         mColors[i] = colorsToSort[i];
    133                     }
    134                     showPaletteView();
    135                     cursor.close();
    136                     break;
    137             }
    138         }
    139     }
    140 
    141     private class OnCalendarColorSelectedListener implements OnColorSelectedListener {
    142 
    143         @Override
    144         public void onColorSelected(int color) {
    145             if (color == mSelectedColor || mService == null) {
    146                 return;
    147             }
    148 
    149             ContentValues values = new ContentValues();
    150             values.put(Calendars.CALENDAR_COLOR_KEY, mColorKeyMap.get(color));
    151             mService.startUpdate(mService.getNextToken(), null, ContentUris.withAppendedId(
    152                     Calendars.CONTENT_URI, mCalendarId), values, null, null, Utils.UNDO_DELAY);
    153         }
    154     }
    155 
    156     public CalendarColorPickerDialog() {
    157         // Empty constructor required for dialog fragments.
    158     }
    159 
    160     public static CalendarColorPickerDialog newInstance(long calendarId, boolean isTablet) {
    161         CalendarColorPickerDialog ret = new CalendarColorPickerDialog();
    162         ret.setArguments(R.string.calendar_color_picker_dialog_title, NUM_COLUMNS,
    163                 isTablet ? SIZE_LARGE : SIZE_SMALL);
    164         ret.setCalendarId(calendarId);
    165         return ret;
    166     }
    167 
    168     @Override
    169     public void onSaveInstanceState(Bundle outState) {
    170         super.onSaveInstanceState(outState);
    171         outState.putLong(KEY_CALENDAR_ID, mCalendarId);
    172         saveColorKeys(outState);
    173     }
    174 
    175     private void saveColorKeys(Bundle outState) {
    176         // No color keys to save, so just return
    177         if (mColors == null) {
    178             return;
    179         }
    180         int[] colorKeys = new int[mColors.length];
    181         for (int i = 0; i < mColors.length; i++) {
    182             colorKeys[i] = mColorKeyMap.get(mColors[i]);
    183         }
    184         outState.putIntArray(KEY_COLOR_KEYS, colorKeys);
    185     }
    186 
    187     @Override
    188     public void onCreate(Bundle savedInstanceState) {
    189         super.onCreate(savedInstanceState);
    190         if (savedInstanceState != null) {
    191             mCalendarId = savedInstanceState.getLong(KEY_CALENDAR_ID);
    192             retrieveColorKeys(savedInstanceState);
    193         }
    194         setOnColorSelectedListener(new OnCalendarColorSelectedListener());
    195     }
    196 
    197     private void retrieveColorKeys(Bundle savedInstanceState) {
    198         int[] colorKeys = savedInstanceState.getIntArray(KEY_COLOR_KEYS);
    199         if (mColors != null && colorKeys != null) {
    200             for (int i = 0; i < mColors.length; i++) {
    201                 mColorKeyMap.put(mColors[i], colorKeys[i]);
    202             }
    203         }
    204     }
    205 
    206     @Override
    207     public void setColors(int[] colors) {
    208         throw new IllegalStateException("Must call setCalendarId() to update calendar colors");
    209     }
    210 
    211     @Override
    212     public void setColors(int[] colors, int selectedColor) {
    213         throw new IllegalStateException("Must call setCalendarId() to update calendar colors");
    214     }
    215 
    216     public void setCalendarId(long calendarId) {
    217         if (calendarId != mCalendarId) {
    218             mCalendarId = calendarId;
    219             startQuery();
    220         }
    221     }
    222 
    223     @Override
    224     public Dialog onCreateDialog(Bundle savedInstanceState) {
    225         Dialog dialog = super.onCreateDialog(savedInstanceState);
    226         mService = new QueryService(getActivity());
    227         if (mColors == null) {
    228             startQuery();
    229         }
    230         return dialog;
    231     }
    232 
    233     private void startQuery() {
    234         if (mService != null) {
    235             showProgressBarView();
    236             mService.startQuery(TOKEN_QUERY_CALENDARS, null,
    237                     ContentUris.withAppendedId(Calendars.CONTENT_URI, mCalendarId),
    238                     CALENDARS_PROJECTION, null, null, null);
    239         }
    240     }
    241 }
    242