Writing Extension Preferences UI for Firefox 1.1

Talk about add-ons and extension development.
User avatar
BenBasson
Moderator
Posts: 13671
Joined: February 13th, 2004, 5:49 am
Location: London, UK
Contact:

Writing Extension Preferences UI for Firefox 1.1

Post by BenBasson »

Writing Extension Preferences UI for Firefox 1.1
This is now out of date in places, do not rely on it!
There is a wiki page covering this on DevMo:
http://developer-test.mozilla.org/en/do ... ces_System

PrefWindowV
Firefox 1.1 (and Deer Park Developer Preview) will include an updated preferences window, dubbed PrefWindowV. The noticable change was the reorganisation of the user interface, but the more interesting changes are architectural.

PrefWindowV gives two main developer-friendly advantages over previous versions:
  • Instant-apply support (enabled by default on Linux and MacOS).
  • JavaScript is unnecessary.
These changes allow for native behaviour and much simpler code.

What do I need in order to use these?
Firstly, you'll have to grab a stable trunk build that has PrefWindowV, but that shouldn't be too hard as the code has been checked in for a couple of months now.

Secondly, you should build an extension to the point where you double-click on the extension's entry in the Extension Manager and an options window is opened. Doing so is already well documented by other guides, so is not covered here.

Example XUL
This is a mock-up example that you can use as a template when creating your own extension preferences window.

Code: Select all

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>

<prefwindow id="myExtensionOptions"
  type="prefwindow"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
  buttons="accept, cancel"
  title="myExtension Options">
 
  <prefpane id="myPane">

    <preferences>
      <preference id="myBool"
        name="extensions.myExtension.myBool"
        type="bool"/>
      <preference id="myInt"
        name="extensions.myExtension.myInt"
        type="int"/>
    </preferences>

    <vbox>
 
      <radiogroup id="radio_myBool"
        preference="myBool"> 
        <vbox>
          <radio id="default"
            label="Default"
            value="true"/>
          <radio id="custom"
            label="Custom"
            value="false"/>   
        </vbox>
      </radiogroup>

      <textbox id="text_myInt"
        preference="myInt"/>

    </vbox>

  </prefpane>

</prefwindow>

Notes
XUL input elements contained within a <code><prefwindow></code> can now modify preferences without interaction from JavaScript. To do this, you must create a <code><preferences></code> element as a child of <code><prefwindow></code> and place one or more <code><preference></code> elements inside it.

If the preference <code>browser.preferences.instantApply</code> is set to true (the default on Linux/MacOS), then the "Cancel" and "Apply" buttons will be hidden. Changes within that window will instantly update the corresponding preferences.

<code><prefwindow></code>
The <code>prefwindow</code> element can contain <code><prefpane></code> elements. It's attributes are similar to that of <code><dialog></code> with the addition of <code>type</code>, which should be set to <code>prefwindow</code>.

<code><prefpane></code>
This element can either directly contain <code><preferences></code> elements and other XUL as children, or can link to an external document using a <code>src</code> attribute. An example of this can be found by opening up the source of [url]chrome://browser/content/preferences/preferences.xul[/url] in a trunk nightly.

<code><preferences></code>
Contains one or more <code><preference></code> elements.

<code><preference></code>
<code>id</code>: A unique way of referring to that preference from an input element.
<code>name</code>: The preference it controls.
<code>type</code>: Possible values <code>int</code>, <code>bool</code>, <code>string</code> (for non-unicode strings), <code>wstring</code> (like nsIPrefLocalizedString), <code>unichar</code> (unicode string), <code>file</code> (nsIFile).

New attributes
XUL input elements now have new attributes. Again, there's no official documentation to confirm which elements these apply to, so I'll assume that all common input elements are covered.

<code>preference</code>: The <code>id</code> value of the <code><preference></code> you wish this input to control. Should contain a value if <code>preference-editable</code> is set to <code>true</code>.
<code>preference-editable</code>: Allows the element to modify a preference. Defaults to <code>true</code> for the following elements: <code><checkbox></code>, <code><colorpicker></code>, <code><radiogroup></code>, <code><textbox></code>, <code><listitem></code>, <code><listbox></code> and <code><menulist></code>.
<code>onpreferenceread</code>: Code to execute when the preference is read - return value may be used.
<code>onpreferencewrite</code>: Code to execute when the preference is written - return value may be used.

Anything to add?
If you have any feedback / suggestions / questions, feel free to reply to this thread. See also the corresponding knowledgebase document:
Preferences bindings - MozillaZine Knowledge Base
Last edited by BenBasson on July 14th, 2005, 5:33 pm, edited 10 times in total.
asqueella
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post by asqueella »

Great.

"windowtype" is an attribute that can be put on any XUL window, it's used to enumerate windows of a given type only using nsIWindowMediator. So you shouldn't copy the windowtype from Firefox's options window.

Possible values for preference.type: int, bool, string (for non-unicode strings), wstring (like nsIPrefLocalizedString), unichar (unicode string), file (nsIFile).

Many things can be seen in the prefs bindings code in preferences.xml, but I don't feel like trying to read that.

[edit] about preference-editable:
it appears that these elements - checkbox, colorpicker, radiogroup, textbox, listitem, listbox, menulist - are "editable" by default. You can set preference-editable=true on an element to make it editable even if it's not one of elements above.

"Editable" means that the element participates in the automatic preferences setting magic.

If you set preference-editable=true, you should make sure it has a "value" property.

btw, onpreferenceread/write is more complicated that what you wrote. I'm not sure what exactly it does.
User avatar
BenBasson
Moderator
Posts: 13671
Joined: February 13th, 2004, 5:49 am
Location: London, UK
Contact:

Post by BenBasson »

Thanks asqueella, I'll make the appropriate edits. I think I'm right about onpreferenceread, though... I'm using it to update a folder icon (as it's used precisely in the Download Manager settings) by setting <code>onpreferenceread="return someFunction();"</code>. It may do more than just that, though...
asqueella
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post by asqueella »

I meant that their return values are used in a special way - not as with other event handlers. I believe that onpreferenceread can be used to override the value read from preferences and onpreferencewrite can override the value read from .value. That may have been obvious to you though.

Your description for "preference-editable" isn't easy to understand, not that I can write a consise correct description for that.

Remove the "/>" from the opening tag of <prefwindow>.

I think that "id" on prefpane is required.
User avatar
BenBasson
Moderator
Posts: 13671
Joined: February 13th, 2004, 5:49 am
Location: London, UK
Contact:

Post by BenBasson »

asqueella wrote:I meant that their return values are used in a special way - not as with other event handlers.

Oh, no I didn't realise this.

asqueella wrote:Your description for "preference-editable" isn't easy to understand, not that I can write a consise correct description for that.

I'll try and revise it.

asqueella wrote:Remove the "/>" from the opening tag of <prefwindow>.

Done.

asqueella wrote:I think that "id" on prefpane is required.

Works without, but it's probably a good idea.
asqueella
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post by asqueella »

Works without [the id on prefpane], but it's probably a good idea.

It didn't work in my testing with multiple panes. When animation is turned on, there were hundreds of JS Console errors.

More:
The example uses weird types of preferences. It should use "int" for radiogroup and "unichar" for the textbox.

there's an "inverted" attribute/property that applies to <preference type="bool"/>. Its meaning should be obvious.

about "type" attribute/property on prefwindow. It can be "prefwindow"/"child" (but only "child" value is tested for explicitly atm). "child" should be used for all subwindows prefwindow opens.
"child" windows have slightly different behavior, like, their prefs aren't set immediately if they are opened from the main prefwindow, they don't animate their prefpanes, in fact I don't think they are supposed to have more than a single prefpane.

There's "changed" event dispatched to <preference> elements when corresponding preferences are changed (a preferences observer is used for listening). You can define "onchange" handlers on those elements too.

[edit] I listed properties/methods here: http://kb.mozillazine.org/Preferences_bindings
twanno
Posts: 284
Joined: February 10th, 2004, 8:58 am
Contact:

Post by twanno »

According to preferences.xml I think you should also be able to assign an image to the prefpane, I suppose by doing something like this

Code: Select all

<prefpane image="chrome://myExtension/skin/prefpane.png" id="myPane">

This image should then be loaded as the image of the button that selects that prefpane, if you know what I mean: the button in the white bar on top.

But the image won't show, although DOMi shows that the src attribute of the radiobutton (the button is actually a radiobutton) is correctly set to that image.

I wonder if this is a bug, or if there is something I am missing about the image attribute.

If I put something like this

Code: Select all

<radiobutton src="chrome://myExtension/skin/prefpane.png" label="some label" />

in an xul file, the associated image does show.
twanno
Posts: 284
Joined: February 10th, 2004, 8:58 am
Contact:

Post by twanno »

OK, I found out it actually is a bug:

Code: Select all

  <binding id="panebutton" extends="chrome://global/content/bindings/radio.xml#radio">
    <resources>
      <stylesheet src="chrome://global/skin/preferences.css"/>
    </resources>
    <content>
-->   <xul:image class="paneButtonIcon" xbl:inherits="image"/>
      <xul:label class="paneButtonLabel" xbl:inherits="value=label"/>
    </content>
  </binding>

should be

Code: Select all

<xul:image class="paneButtonIcon" xbl:inherits="src"/>

Edit: Filed bug #293755, can any of you confirm the bug?
and does anyone know who to ask review for the patch?
Last edited by twanno on May 11th, 2005, 6:55 am, edited 1 time in total.
asqueella
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post by asqueella »

The preferred way is to set images from the skin in CSS, anyways.
twanno
Posts: 284
Joined: February 10th, 2004, 8:58 am
Contact:

Post by twanno »

It may be preferred, but it is easier to set the image like this.
But anyway, I was just trying to test the new preferences UI and what I could do with it, when I encountered this issue.
And the attribute is defined so why leave it not working?
asqueella
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post by asqueella »

I'm not saying you shouldn't file a bug, I'm trying to explain why it's broken :)
User avatar
BenBasson
Moderator
Posts: 13671
Joined: February 13th, 2004, 5:49 am
Location: London, UK
Contact:

Post by BenBasson »

twanno wrote:and does anyone know who to ask review for the patch?

Probably Ben, since it was his rewrite.
asqueella
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post by asqueella »

see https://bugzilla.mozilla.org/show_bug.cgi?id=283675

btw, Cusser, could you add http://kb.mozillazine.org/Preferences_bindings to main post.

also, the bindings file says it's PrefWindow 6 (?)
User avatar
BenBasson
Moderator
Posts: 13671
Joined: February 13th, 2004, 5:49 am
Location: London, UK
Contact:

Post by BenBasson »

I'm guessing that's a typo... but sure, added.
asqueella
Posts: 4019
Joined: November 16th, 2003, 3:05 am
Location: Russia, Moscow

Post by asqueella »

1068 #
1069 # This is PrefWindow 6. The Code Could Well Be Ready, Are You?
1070 #
1071 # Historical References:
1072 # PrefWindow V (February 1, 2003)
1073 # PrefWindow IV (April 24, 2000)
1074 # PrefWindow III (January 6, 2000)
1075 # PrefWindow II (???)
1076 # PrefWindow I (June 4, 1999)
1077 #

doesn't look like a typo. I believe ben said this was PrefWindow V on several occasions though.

btw, I'm not producing that wiki doc, I just created a stub for others to contribute. And it's complementary to information you're collecting.
Post Reply