Preference Panel

The PreferencePanel() base class creates a new plugin that can be used to create a new section in the global preferences editor. Each section gets a top level item in the left side navigation and when activated will display a UI on the right side that allows users to configure something.

Creating a Preference Panel

A basic preference panel is created like this:

var plugin = new PreferencePanel("Your Name", main.consumes, {
    caption: "Panel Title",
    form: true,
    index: 50
});

And looks like this:

15701570

Preference Panel Properties

The following properties can be passed to the PreferencePanel() constructor.

captionThe caption of the navigation item
classNameA custom css class name set on the container of the UI elements
formBoolean specifying whether to enable the integrated form that is displayed on the right side of the preferences.
noscrollBoolean specifying whether to allow scrolling.
indexThe index of the navigation item determines its vertical position.

Adding your own contents

The most straightforward way to populate your preference panel is by adding custom html and css. The following example loads css from dialog.css and adds a div element to the body of the dialog.

plugin.on("draw", function(e){
    // Insert css
    ui.insertCss(require("text!./prefs.css"), options.staticPrefix, plugin);

    // Set some custom HTML
    e.html.innerHTML = "<div class='myCSS'>Hello World</div>";
});

However all current preference panes use the built-in form.

Using the built-in form

You can choose to use the built-in form or not, by enabling the form property when creating your panel. When this is enabled you can either create a flat form without any headings and without any navigational items, or you can create two-level headings in the navigation of which the 2nd level heading and the form elements will be displayed on the right.

The image below shows the use of headings on the left half and the use without headings on the right half.

28502850

Widgets

The form object allows you to describe widgets declaratively. It adds one widget on each row and pairs it with a label. You determine the sequence of the widgets. In addition you can add custom areas that you manage yourself.

For information on the different widgets that are supported by the form see this guide

Two-Level Headings

Use the add() method on your preference plugin to add headings and widgets to your preference panel. You can also let external plugins use this api to add additional elements to your preference panel.

In this example a top level navigational item called "General" is added at position 100. This top-level nav item is only shown in the navigation. This example has two sub headings called "User Interface" and "Tree" at position 20 and 40 respectively. Both have one widget, a checkbox and a textbox respectively.

prefPanel.add({
   "General" : {
        position: 100,
        "User Interface" : {
            position: 20,
            "Enable UI Animations" : {
                type: "checkbox",
                setting: "user/general/@animateui",
                position: 100
            }
        },
        "Tree": {
            position: 40,
            "Hidden File Pattern" : {
               type: "textbox",
               setting: "user/projecttree/@hiddenFilePattern",
               position: 100
            }
        }
    }
}, plugin);

Which looks like this:

15701570

No Headings

The alternative to using two-level headings is to not use any headings. This can be useful for when you have no need for categorization and is often combined with noscroll to set up a UI that fills the entire page - more on that below.

To get there call plugin.form.add() instead of plugin.add() and pass an array of widgets to it. In the example below there are two widgets, a button and a dropdown created. Make sure to add the "flatform" class to the className property in order for this to render correctly.

plugin.form.add([
    {
        type: "button",
        title: "Reset to Default Keybindings",
        caption: "Reset to Defaults",
        width: 140,
        onclick: function(){
            doReset();
        },
        position: 90
    },
    {
        title: "Keyboard Mode",
        type: "dropdown",
        setting: "user/ace/@keyboardmode",
        items: [
            { caption: "Default", value: "default" },
            { caption: "Vim", value: "vim" },
            { caption: "Emacs", value: "emacs" },
            { caption: "Sublime", value: "sublime" }
        ],
        position: 100
    }
], plugin);

Which looks like this:

15661566

Custom Widgets

A custom form widget allows you to add a row of any height to the form that you can fill in whichever way you want. The example below creates a custom widget with a ui.bar element as the container.

{
    type: "custom",
    title: "Keybindings Editor",
    position: 120,
    node: container = new ui.bar({
        style: "padding:44px 10px 10px 10px"
    })
}

You can then proceed to add other elements to the container either switching to html

container.$html.innerHTML = "<strong>Hello</strong>";

or adding more cloud9 ui elements.

container.appendChild(new ui.button({ caption: "Hello" }));

Intro Widget

The intro widget is a custom widget that is commonly used by preference panes to set a heading and some supportive text.

This is the base widget that is used.

{
    type: "custom",
    title: "Introduction",
    position: 1,
    node: intro = new ui.bar({
        height: 149,
        class : "intro",
        style: "padding:12px;position:relative;"
    })
},

You can set the height and any style you want as well.

Then populate the contents with html as follows.

intro.$html.innerHTML = 
    '<h1>Keybindings</h1><p>Change these settings to configure '
    + 'how Cloud9 responds to your keyboard commands.</p>'
    + '<p>You can also manually edit <a href="javascript:void(0)" '
    + '>your keymap file</a>.</p>'
    + '<p class="hint">Hint: Double click on the keystroke cell in the table below to change the keybinding.</p>';

intro.$html.querySelector("a").onclick = function(){ editUserKeys(); };

That looks like this:

15701570

No Scroll

Some preferences panels are not scrolling pages but instead keep a fixed height, with usually, a scrolling container such as a datagrid taking up the remainder of the space. A good example is the key bindings editor as well as the plugin manager.

Set noscroll to true to prevent scroll. If you are using form elements, set the positioning of your custom element such that it takes the rest of the space. Here's how you can do that with a last element of a form.

{
    type: "custom",
    title: "Keybindings Editor",
    position: 120,
    node: container = new ui.bar({
        anchors: "269 0 0 0"
    })
}

The anchors are set to a fixed distance from the top and then 0 pixels from the left right and bottom position.

Events

A preference panel has three additional events added to it's life cycle. The first one we mentioned above already is the draw event. The other two are activate and resize

Activate

The activate event is fired every time the panel is selected in the navigation.

plugin.on("activate", function(e) {
    datagrid && datagrid.resize();
});

Resize

The resize event is fired every time the panel's width and/or height changes.

plugin.on("resize", function(e) {
datagrid && datagrid.resize();
});