diff --git a/calendar/base/content/calendar-event-dialog.js b/calendar/base/content/calendar-event-dialog.js index 9bd68b91c60a..819de4ab31e8 100644 --- a/calendar/base/content/calendar-event-dialog.js +++ b/calendar/base/content/calendar-event-dialog.js @@ -187,10 +187,7 @@ function loadDialog(item) /* Categories */ try { - var pb2 = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefBranch2); - var categoriesString = pb2.getComplexValue("calendar.categories.names", - Components.interfaces.nsISupportsString).data; + var categoriesString = getLocalizedPref("calendar.categories.names"); var categoriesList = categoriesString.split( "," ); // insert the category already in the menulist so it doesn't get lost @@ -210,10 +207,7 @@ function loadDialog(item) var indexToSelect = 0; // Add a 'none' option to allow users to cancel the category - var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"] - .getService(Components.interfaces.nsIStringBundleService); - var props = sbs.createBundle("chrome://calendar/locale/calendar.properties"); - var noneItem = categoryMenuList.appendItem(props.GetStringFromName("None"), "NONE"); + var noneItem = categoryMenuList.appendItem(calGetString("calendar", "None"), "NONE"); for (var i in categoriesList) { var catItem = categoryMenuList.appendItem(categoriesList[i], categoriesList[i]); @@ -222,7 +216,10 @@ function loadDialog(item) indexToSelect = parseInt(i)+1; // Add 1 because of 'None' } } + var newCategory = calGetString("calendar", "newCategory"); + categoryMenuList.appendItem(newCategory, "##NEW"); categoryMenuList.selectedIndex = indexToSelect; + gOldCatIndex = indexToSelect; } catch (ex) { // The app using this dialog doesn't support categories @@ -406,19 +403,16 @@ function saveDialog(item) function updateTitle() { var isNew = window.calendarItem.isMutable; - var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"] - .getService(Components.interfaces.nsIStringBundleService); - var props = sbs.createBundle("chrome://calendar/locale/calendar.properties"); if (isEvent(window.calendarItem)) { if (isNew) - document.title = props.GetStringFromName("newEventDialog"); + document.title = calGetString("calendar", "newEventDialog"); else - document.title = props.GetStringFromName("editEventDialog"); + document.title = calGetString("calendar", "editEventDialog"); } else if (isToDo(window.calendarItem)) { if (isNew) - document.title = props.GetStringFromName("newTaskDialog"); + document.title = calGetString("calendar", "newTaskDialog"); else - document.title = props.GetStringFromName("editTaskDialog"); + document.title = calGetString("calendar", "editTaskDialog"); } } @@ -1052,3 +1046,61 @@ function loadURL() launchBrowser(url); return; } + +var gOldCatIndex = 0; +function categorySelect(aValue) { + if (aValue != "##NEW") { + gOldCatIndex = document.getElementById("item-categories").selectedIndex; + return; + } + + // Make sure we don't leave 'New..' selected if they hit cancel + document.getElementById("item-categories").selectedIndex = gOldCatIndex; + + window.openDialog("chrome://calendar/content/preferences/editCategory.xul", + "addCategory", "modal,centerscreen,chrome,resizable=no", + "", null, calGetString("calendar", "addCategory")); +} + +// Trick the dialog into thinking we're the categories pane +var gCategoriesPane = { + saveCategory: function eventDialog_saveCategory(aName, aColor) { + //Check to make sure another category doesn't have the same name + var promptService = + Components.classes["@mozilla.org/embedcomp/prompt-service;1"] + .getService(Components.interfaces.nsIPromptService); + var categoriesString = getLocalizedPref("calendar.categories.names"); + var categoriesList = categoriesString.split( "," ); + for each (cat in categoriesList) { + if (aName.toLowerCase() == cat.toLowerCase()) { + var repTitle = calGetString("calendar", "categoryReplaceTitle"); + var rep = calGetString("calendar", "categoryReplace"); + if (promptService.confirm(null, repTitle, rep)) { + var categoryNameFix = aName.toLowerCase().replace(' ','_'); + setPref("calendar.category.color."+categoryNameFix, + "CHAR", aColor); + } + return; + } + } + + if (aName.length == 0) { + promptService.alert(null, null, noBlankCategories); + return; + } + + categoriesList.push(aName); + categoriesList.sort(); + + setLocalizedPref("calendar.categories.names", categoriesList.join(',')); + + if (aColor) { + var categoryNameFix = aName.toLowerCase().replace(' ','_'); + setPref("calendar.category.color."+categoryNameFix, "CHAR", aColor); + } + var catList = document.getElementById("item-categories"); + var index = categoriesList.indexOf(aName); + catList.insertItemAt(index, aName, aName); + catList.selectedIndex = index; + } +}; diff --git a/calendar/base/content/calendar-event-dialog.xul b/calendar/base/content/calendar-event-dialog.xul index 21c3b5e385eb..77c34a3396c8 100644 --- a/calendar/base/content/calendar-event-dialog.xul +++ b/calendar/base/content/calendar-event-dialog.xul @@ -156,7 +156,7 @@ diff --git a/calendar/locales/en-US/chrome/calendar/calendar.properties b/calendar/locales/en-US/chrome/calendar/calendar.properties index 684dcf30de41..7dadaf6e86b5 100644 --- a/calendar/locales/en-US/chrome/calendar/calendar.properties +++ b/calendar/locales/en-US/chrome/calendar/calendar.properties @@ -228,3 +228,9 @@ rotate=Rotate htmlDesc=HTML icsDesc=iCalendar outlookDesc=Comma Separated Values (from Outlook) + +# Categories +categoryReplace=A category already exists with that name. \n Do you want to replace it? +categoryReplaceTitle=Warning: Duplicate name +addCategory=Add Category +newCategory=New Category... diff --git a/calendar/resources/content/calendarUtils.js b/calendar/resources/content/calendarUtils.js index 40a97ddf2adc..a3dba27f381b 100644 --- a/calendar/resources/content/calendarUtils.js +++ b/calendar/resources/content/calendarUtils.js @@ -158,6 +158,89 @@ function isToDo(aObject) return aObject instanceof Components.interfaces.calITodo; } +/** + * Normal get*Pref calls will throw if the pref is undefined. This function + * will get a bool, int, or string pref. If the pref is undefined, it will + * return aDefault. + * + * @param aPrefName the (full) name of preference to get + * @param aDefault (optional) the value to return if the pref is undefined + */ +function getPrefSafe(aPrefName, aDefault) { + const nsIPrefBranch = Components.interfaces.nsIPrefBranch; + const prefB = Components.classes["@mozilla.org/preferences-service;1"] + .getService(nsIPrefBranch); + switch (prefB.getPrefType(aPrefName)) { + case nsIPrefBranch.PREF_BOOL: + return prefB.getBoolPref(aPrefName); + case nsIPrefBranch.PREF_INT: + return prefB.getIntPref(aPrefName); + case nsIPrefBranch.PREF_String: + return prefB.getCharPref(aPrefName); + default: // includes nsIPrefBranch.PREF_INVALID + return aDefault; + } +} + +/** + * Wrapper for setting prefs of various types + * + * @param aPrefName the (full) name of preference to set + * @param aPrefType the type of preference to set. Valid valuse are: + BOOL, INT, and CHAR + * @param aPrefValue the value to set the pref to + */ +function setPref(aPrefName, aPrefType, aPrefValue) { + const nsIPrefBranch = Components.interfaces.nsIPrefBranch; + const prefB = Components.classes["@mozilla.org/preferences-service;1"] + .getService(nsIPrefBranch); + switch (aPrefType) { + case "BOOL": + prefB.setBoolPref(aPrefName, aPrefValue); + break; + case "INT": + prefB.setIntPref(aPrefName, aPrefValue); + break; + case "CHAR": + prefB.setCharPref(aPrefName, aPrefValue); + break; + } +} + +/** + * Helper function to set a localized (complex) pref from a given string + * + * @param aPrefName the (full) name of preference to set + * @param aString the string to which the preference value should be set + */ +function setLocalizedPref(aPrefName, aString) { + const prefB = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranch); + var str = Components.classes["@mozilla.org/supports-string;1"] + .createInstance(Components.interfaces.nsISupportsString); + str.data = aString; + prefB.setComplexValue(aPrefName, Components.interfaces.nsISupportsString, str); +} + +/** + * Like getPrefSafe, except for complex prefs (those used for localized data). + * + * @param aPrefName the (full) name of preference to get + * @param aDefault (optional) the value to return if the pref is undefined + */ +function getLocalizedPref(aPrefName, aDefault) { + const pb2 = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranch2); + var result; + try { + result = pb2.getComplexValue(aPrefName, + Components.interfaces.nsISupportsString).data; + } catch(ex) { + return aDefault; + } + return result; +} + /** * Gets the value of a string in a .properties file *