XPCOM Examples
This section provides some examples of using XPCOM along with some additional interfaces.
Window Management
The list of currently open Mozilla windows can be used as an RDF datasource. This allows you to create a Window menu with a list of the currently open windows in the application. The datasource for this is rdf:window-mediator. We can use this as in the following example:
Example 7.6.1: Source<toolbox> <menubar id="windowlist-menubar"> <menu label="Window"> <menupopup id="window-menu" datasources="rdf:window-mediator" ref="NC:WindowMediatorRoot"> <template> <rule> <menuitem uri="rdf:*" label="rdf:http://home.netscape.com/NC-rdf#Name"/> </rule> </template> </menupopup> </menu> </menubar> </toolbox>
A Window menu will be created with a list of all the open windows. Try this example by opening a number of browser windows and you'll see that they are all listed on the menu. This is fine for displaying a list of open windows, but we would like to enhance this so that clicking on the menu item will switch to that window. This is accomplished by using the window mediator component. It implements the interface nsIWindowDataSource. The code below shows how to get a component which implements it:
var wmdata = Components.classes["@mozilla.org/rdf/datasource;1?name=window-mediator"].getService(); wmdata.QueryInterface(Components.interfaces.nsIWindowDataSource);
This code retrieves a window mediator data source component. The component used here is the same one that handles the window-mediator RDF datasource. You can also get this component through the RDF service, which is another service that manages RDF datasources.
The nsIWindowDataSource interface has a function getWindowForResource, which can be used to get the window given a resource. In the earlier example, we generated the list of windows and added it to a menu via a template. The template generates an id attribute on each menuitem element. The value of this attribute can be used as the resource. That means that in order to switch the window focus, we need to do the following:
- Determine the element that the user clicked on.
- Get the value of the id attribute from the element.
- Pass this value to getWindowForResource to get a window object.
- Switch the focus to this window.
The example below shows how we might do this:
<toolbox> <menubar id="windowlist-menubar"> <menu label="Window" oncommand="switchFocus(event.target);"> <menupopup id="window-menu" datasources="rdf:window-mediator" ref="NC:WindowMediatorRoot"> <template> <rule> <menuitem uri="rdf:*" label="rdf:http://home.netscape.com/NC-rdf#Name"/> </rule> </template> </menupopup> </menu> </menubar> </toolbox> function switchFocus(elem) { var mediator = Components.classes["@mozilla.org/rdf/datasource;1?name=window-mediator"].getService(); mediator.QueryInterface(Components.interfaces.nsIWindowDataSource); var resource = elem.getAttribute('id'); switchwindow = mediator.getWindowForResource(resource); if (switchwindow){ switchwindow.focus(); } }
A command handler was added to the menu element which calls the function with a parameter of the element that was selected from the menu. The function switchFocus first gets a reference to a component which implements the window mediator interface. Next, we get the id attribute for the element. We can use the value of the id attribute as the resource. The function getWindowForResource takes the resource and returns a window that matches it. This window, stored in the switchwindow variable, is the same as the JavaScript window object. This means that you can call any of the functions provided by it, one of which is the focus function.
Cookies
Next, we will get a list of cookies that have been saved in the browser. The cookie service can be used for such a purpose. It implements the nsICookieManager interface which can be used to enumerate over all of the cookies. Here is an example which populates a menu list with the names of all of the cookies set from MozillaZine.
<script> function getCookies() { var menu = document.getElementById("cookieMenu"); menu.removeAllItems(); var cookieManager = Components.classes["@mozilla.org/cookiemanager;1"] .getService(Components.interfaces.nsICookieManager); var iter = cookieManager.enumerator; while (iter.hasMoreElements()){ var cookie = iter.getNext(); if (cookie instanceof Components.interfaces.nsICookie){ if (cookie.host == "www.mozillazine.org") menu.appendItem(cookie.name,cookie.value); } } } </script> <hbox> <menulist id="cookieMenu" onpopupshowing="getCookies();"/> </hbox>
The getCookies function will be called whenever the menu is opened, as indicated by the onpopupshowing attribute on the menulist. The first two lines of getCookies get the menulist and remove all of the existing items in the menu. This is done because getCookies is called every time the menu is opened and we don't want to leave the old items there each time.
Next, the cookie manager is retrieved. The cookie manager has an enumerator method which returns an object which implements nsISimpleEnumerator. This can be used to iterate over all of the cookies. An enumerator has a hasMoreElements method which will return true until we get to the last cookie. The getNext method gets a cookie and moves the enumerator index to the next cookie. Since an enumerator just returns a generic object, we need to QueryInterface it to an nsICookie before we can use it. In this case, we just use the instanceof operator to accomplish this.
Finally, an item is added to the menu for the cookie. The host, name and value properties of the cookie are used for this. Menus have an appendItem function which can be used to add an item to the menu, given a label and a value.
(Next) Next, we'll look at how to create trees.
Examples: 7.6.1