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 */ 16 package com.android.calendar.event; 17 18 import com.android.calendar.CalendarEventModel.ReminderEntry; 19 import com.android.calendar.R; 20 21 import android.app.Activity; 22 import android.content.Context; 23 import android.content.res.Resources; 24 import android.util.Log; 25 import android.view.LayoutInflater; 26 import android.view.View; 27 import android.widget.AdapterView.OnItemSelectedListener; 28 import android.widget.ArrayAdapter; 29 import android.widget.ImageButton; 30 import android.widget.LinearLayout; 31 import android.widget.Spinner; 32 33 import java.util.ArrayList; 34 35 public class EventViewUtils { 36 private static final String TAG = "EventViewUtils"; 37 EventViewUtils()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". constructReminderLabel(Context context, int minutes, boolean abbrev)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 */ findMinutesInReminderList(ArrayList<Integer> values, int minutes)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 */ findMethodInReminderList(ArrayList<Integer> values, int method)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 */ reminderItemsToReminders( ArrayList<LinearLayout> reminderItems, ArrayList<Integer> reminderMinuteValues, ArrayList<Integer> reminderMethodValues)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 */ addMinutesToList(Context context, ArrayList<Integer> values, ArrayList<String> labels, int minutes)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 */ reduceMethodList(ArrayList<Integer> values, ArrayList<String> labels, String allowedMethods)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 */ setReminderSpinnerLabels(Activity activity, Spinner spinner, ArrayList<String> labels)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 */ addReminder(Activity activity, View view, View.OnClickListener listener, ArrayList<LinearLayout> items, ArrayList<Integer> minuteValues, ArrayList<String> minuteLabels, ArrayList<Integer> methodValues, ArrayList<String> methodLabels, ReminderEntry newReminder, int maxReminders, OnItemSelectedListener onItemSelected)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 */ updateAddReminderButton(View view, ArrayList<LinearLayout> reminders, int maxReminders)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