Mozilla mail requires an event system to notify different subsystems that data has changed. This document describes the system that events are passed amongst the mail objects.
For example, when a folder gets a new message, its total message count increases. The folder pane needs to know that this changed so that it can update the message count so the user can see it.
The key interfaces here are:
Each event type has a two methods associated with it:
Here is an example of a possible flow of control when a new message is added to a folder. In this example, there is a dialog open that shows properties for this folder including the message count. This dialog is a listener on this particular folder.
At the time this document is being written, these are the current events:
nsIFolder | nsIFolderListener |
---|---|
NotifyItemAdded | OnItemAdded |
NotifyItemRemoved | OnItemRemoved |
NotifyItemPropertyChanged | OnItemPropertyChanged |
NotifyItemIntPropertyChanged | OnItemIntPropertyChanged |
NotifyItemBoolPropertyChanged | OnItemBoolPropertyChanged |
NotifyItemUnicharPropertyChanged | OnItemUnicharPropertyChanged |
NotifyItemPropertyFlagChanged | OnItemPropertyFlagChanged |
NotifyItemEvent | OnItemEvent |
NotifyFolderLoaded | OnFolderLoaded |
NotifyDeleteOrMoveMessages | OnDeleteOrMoveMessages |
In this example, a listener will be set up to be notified when the message count changes in a folder:
// our variable to know if the listener fired var listenerHasFired = false; var totalMessagesListenerHasFired = false; // the listening function that will react to changes function myOnIntPropertyChanged(item, property, oldValue, newValue) { listenerHasFired=true; var propertyString = property.GetUnicode(); dump("OnIntPropertyChanged has fired with property + " + propertyString + "!\n"); if (propertyString == "TotalMessages") { totalMessagesListenerHasFired=true; //now show us visually var folder = item.QueryInterface(Components.interfaces.nsIMsgFolder); dump("The folder " + folder.prettyName + " now has " + newValue + " messages."); } else if (propertyString == "TestProperty") { dump("Recieved integer test property fired on folder " + folder.prettyName + " with values " + oldValue + " and " + newValue + "\n"); } // set up the folder listener to point to the above function var folderListener = { OnItemAdded: function(parent, item, viewString) {}, OnItemRemoved: function(parent, item, viewString) {}, OnItemPropertyChanged: function(parent, item, viewString) {}, OnItemIntPropertyChanged: myOnIntPropertyChanged, OnItemBoolPropertyChanged: function(item, property, oldValue, newValue) {}, OnItemUnicharPropertyChanged: function(item, property, oldValue, newValue) {}, OnItemPropertyFlagChanged: function(item, property, oldFlag, newFlag) {}, OnItemEvent: function(item, event) = {}, OnFolderLoaded: function(aFolder) = {} OnDeleteOrMoveMessagesCompleted: function( aFolder) = {}, } // now register myself as a listener on every mail folder var mailSession = Components.classes["component://netscape/messenger/services/session"]. getService(Components.interfaces.nsIMsgMailSession); mailSession.addListener(folderListener); // now test to see if integer stuff is firing at all // let's say "folder" is a folder we know about // first we need an atom to play with atomService = Components.classes["component://netscape/atom-service"]. getService(Components.interfaces.nsIAtomService); var testPropertyAtom = atomService.getAtom("TestProperty"); // now fire the test notification folder.NotifyIntPropertyChanged(testPropertyAtom, 0, 100); // Now we would do some operations to change the message count, such // as copying a message into this folder or something. Then we could // verify that our listener fired by checking if listenerHasFired and // totalMessagesListenerHasFired are true // this is left as an exercise for the reader.
There are some of redundant methods between the nsIMsgMailSession and the nsIFolderListener interfaces. nsIMsgMailSession also contains a number of other methods that are completely unrealted to folder notification. It would make sense to collapse the nsIMsgMailSession simply into an object that implements the the nsIFolderListener interface to receive notifications from the folders. The notification functions should probably go to an nsIFolderBroadcaster interface or something, since they need to know what folder is being modified.