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
*