EventViewUtils.java revision 06f3d6d0d3bd6d194f5a3822efd63830098284dc
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 */
16package com.android.calendar.event;
17
18import com.android.calendar.CalendarEventModel.ReminderEntry;
19import com.android.calendar.R;
20
21import android.app.Activity;
22import android.content.Context;
23import android.content.res.Resources;
24import android.util.Log;
25import android.view.LayoutInflater;
26import android.view.View;
27import android.widget.AdapterView.OnItemSelectedListener;
28import android.widget.ArrayAdapter;
29import android.widget.ImageButton;
30import android.widget.LinearLayout;
31import android.widget.Spinner;
32
33import java.util.ArrayList;
34
35public class EventViewUtils {
36    private static final String TAG = "EventViewUtils";
37
38    private EventViewUtils() {
39    }
40
41    // Constructs a label given an arbitrary number of minutes. For example,
42    // if the given minutes is 63, then this returns the string "63 minutes".
43    // As another example, if the given minutes is 120, then this returns
44    // "2 hours".
45    public static String constructReminderLabel(Context context, int minutes, boolean abbrev) {
46        Resources resources = context.getResources();
47        int value, resId;
48
49        if (minutes % 60 != 0) {
50            value = minutes;
51            if (abbrev) {
52                resId = R.plurals.Nmins;
53            } else {
54                resId = R.plurals.Nminutes;
55            }
56        } else if (minutes % (24 * 60) != 0) {
57            value = minutes / 60;
58            resId = R.plurals.Nhours;
59        } else {
60            value = minutes / (24 * 60);
61            resId = R.plurals.Ndays;
62        }
63
64        String format = resources.getQuantityString(resId, value);
65        return String.format(format, value);
66    }
67
68    /**
69     * Finds the index of the given "minutes" in the "values" list.
70     *
71     * @param values the list of minutes corresponding to the spinner choices
72     * @param minutes the minutes to search for in the values list
73     * @return the index of "minutes" in the "values" list
74     */
75    public static int findMinutesInReminderList(ArrayList<Integer> values, int minutes) {
76        int index = values.indexOf(minutes);
77        if (index == -1) {
78            // This should never happen.
79            Log.e(TAG, "Cannot find minutes (" + minutes + ") in list");
80            return 0;
81        }
82        return index;
83    }
84
85    /**
86     * Finds the index of the given method in the "methods" list.  If the method isn't present
87     * (perhaps because we don't think it's allowed for this calendar), we return zero (the
88     * first item in the list).
89     * <p>
90     * With the current definitions, this effectively converts DEFAULT and unsupported method
91     * types to ALERT.
92     *
93     * @param values the list of minutes corresponding to the spinner choices
94     * @param method the method to search for in the values list
95     * @return the index of the method in the "values" list
96     */
97    public static int findMethodInReminderList(ArrayList<Integer> values, int method) {
98        int index = values.indexOf(method);
99        if (index == -1) {
100            // If not allowed, or undefined, just use the first entry in the list.
101            //Log.d(TAG, "Cannot find method (" + method + ") in allowed list");
102            index = 0;
103        }
104        return index;
105    }
106
107    /**
108     * Extracts reminder minutes info from UI elements.
109     *
110     * @param reminderItems UI elements (layouts with spinners) that hold array indices.
111     * @param reminderMinuteValues Maps array index to time in minutes.
112     * @param reminderMethodValues Maps array index to alert method constant.
113     * @return Array with reminder data.
114     */
115    public static ArrayList<ReminderEntry> reminderItemsToReminders(
116            ArrayList<LinearLayout> reminderItems, ArrayList<Integer> reminderMinuteValues,
117            ArrayList<Integer> reminderMethodValues) {
118        int len = reminderItems.size();
119        ArrayList<ReminderEntry> reminders = new ArrayList<ReminderEntry>(len);
120        for (int index = 0; index < len; index++) {
121            LinearLayout layout = reminderItems.get(index);
122            Spinner minuteSpinner = (Spinner) layout.findViewById(R.id.reminder_minutes_value);
123            Spinner methodSpinner = (Spinner) layout.findViewById(R.id.reminder_method_value);
124            int minutes = reminderMinuteValues.get(minuteSpinner.getSelectedItemPosition());
125            int method = reminderMethodValues.get(methodSpinner.getSelectedItemPosition());
126            reminders.add(ReminderEntry.valueOf(minutes, method));
127        }
128        return reminders;
129    }
130
131    /**
132     * If "minutes" is not currently present in "values", we add an appropriate new entry
133     * to values and labels.
134     */
135    public static void addMinutesToList(Context context, ArrayList<Integer> values,
136            ArrayList<String> labels, int minutes) {
137        int index = values.indexOf(minutes);
138        if (index != -1) {
139            return;
140        }
141
142        // The requested "minutes" does not exist in the list, so insert it
143        // into the list.
144
145        String label = constructReminderLabel(context, minutes, false);
146        int len = values.size();
147        for (int i = 0; i < len; i++) {
148            if (minutes < values.get(i)) {
149                values.add(i, minutes);
150                labels.add(i, label);
151                return;
152            }
153        }
154
155        values.add(minutes);
156        labels.add(len, label);
157    }
158
159    /**
160     * Remove entries from the method list that aren't allowed for this calendar.
161     *
162     * @param values List of known method values.
163     * @param labels List of known method labels.
164     * @param allowedMethods Has the form "0,1,3", indicating method constants from Reminders.
165     */
166    public static void reduceMethodList(ArrayList<Integer> values, ArrayList<String> labels,
167            String allowedMethods)
168    {
169        // Parse "allowedMethods".
170        String[] allowedStrings = allowedMethods.split(",");
171        int[] allowedValues = new int[allowedStrings.length];
172
173        for (int i = 0; i < allowedValues.length; i++) {
174            try {
175                allowedValues[i] = Integer.parseInt(allowedStrings[i], 10);
176            } catch (NumberFormatException nfe) {
177                Log.w(TAG, "Bad allowed-strings list: '" + allowedStrings[i] +
178                        "' in '" + allowedMethods + "'");
179                return;
180            }
181        }
182
183        // Walk through the method list, removing entries that aren't in the allowed list.
184        for (int i = values.size() - 1; i >= 0; i--) {
185            int val = values.get(i);
186            int j;
187
188            for (j = allowedValues.length - 1; j >= 0; j--) {
189                if (val == allowedValues[j]) {
190                    break;
191                }
192            }
193            if (j < 0) {
194                values.remove(i);
195                labels.remove(i);
196            }
197        }
198    }
199
200    /**
201     * Set the list of labels on a reminder spinner.
202     */
203    private static void setReminderSpinnerLabels(Activity activity, Spinner spinner,
204            ArrayList<String> labels) {
205        Resources res = activity.getResources();
206        spinner.setPrompt(res.getString(R.string.reminders_label));
207        int resource = android.R.layout.simple_spinner_item;
208        ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity, resource, labels);
209        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
210        spinner.setAdapter(adapter);
211    }
212
213    /**
214     * Adds a reminder to the displayed list of reminders. The values/labels
215     * arrays must not change after calling here, or the spinners we created
216     * might index into the wrong entry. Returns true if successfully added
217     * reminder, false if no reminders can be added.
218     *
219     * onItemSelected allows a listener to be set for any changes to the
220     * spinners in the reminder. If a listener is set it will store the
221     * initial position of the spinner into the spinner's tag for comparison
222     * with any new position setting.
223     */
224    public static boolean addReminder(Activity activity, View view, View.OnClickListener listener,
225            ArrayList<LinearLayout> items, ArrayList<Integer> minuteValues,
226            ArrayList<String> minuteLabels, ArrayList<Integer> methodValues,
227            ArrayList<String> methodLabels, ReminderEntry newReminder, int maxReminders,
228            OnItemSelectedListener onItemSelected) {
229
230        if (items.size() >= maxReminders) {
231            return false;
232        }
233
234        LayoutInflater inflater = activity.getLayoutInflater();
235        LinearLayout parent = (LinearLayout) view.findViewById(R.id.reminder_items_container);
236        LinearLayout reminderItem = (LinearLayout) inflater.inflate(R.layout.edit_reminder_item,
237                null);
238        parent.addView(reminderItem);
239
240        ImageButton reminderRemoveButton;
241        reminderRemoveButton = (ImageButton) reminderItem.findViewById(R.id.reminder_remove);
242        reminderRemoveButton.setOnClickListener(listener);
243
244        /*
245         * The spinner has the default set of labels from the string resource file, but we
246         * want to drop in our custom set of labels because it may have additional entries.
247         */
248        Spinner spinner = (Spinner) reminderItem.findViewById(R.id.reminder_minutes_value);
249        setReminderSpinnerLabels(activity, spinner, minuteLabels);
250
251        int index = findMinutesInReminderList(minuteValues, newReminder.getMinutes());
252        spinner.setSelection(index);
253
254        if (onItemSelected != null) {
255            spinner.setTag(index);
256            spinner.setOnItemSelectedListener(onItemSelected);
257        }
258
259        /*
260         * Configure the alert-method spinner.  Methods not supported by the current Calendar
261         * will not be shown.
262         */
263        spinner = (Spinner) reminderItem.findViewById(R.id.reminder_method_value);
264        setReminderSpinnerLabels(activity, spinner, methodLabels);
265
266        index = findMethodInReminderList(methodValues, newReminder.getMethod());
267        spinner.setSelection(index);
268
269        if (onItemSelected != null) {
270            spinner.setTag(index);
271            spinner.setOnItemSelectedListener(onItemSelected);
272        }
273
274        items.add(reminderItem);
275
276        return true;
277    }
278
279    /**
280     * Enables/disables the 'add reminder' button depending on the current number of
281     * reminders.
282     */
283    public static void updateAddReminderButton(View view, ArrayList<LinearLayout> reminders,
284            int maxReminders) {
285        View reminderAddButton = view.findViewById(R.id.reminder_add);
286        if (reminderAddButton != null) {
287            if (reminders.size() >= maxReminders) {
288                reminderAddButton.setEnabled(false);
289                reminderAddButton.setVisibility(View.GONE);
290            } else {
291                reminderAddButton.setEnabled(true);
292                reminderAddButton.setVisibility(View.VISIBLE);
293            }
294        }
295    }
296}
297