Snippets code from my daily experience

January 8, 2010

How to programmatically change XUL tree’s pseudo-classes

Filed under: extension,nsITreeView,xul — dafi @ 3:45 pm

I encountered the following problem: Change font and color for XUL tree based on user input. The user chooses the font and picks the color from a dialog and the tree widget is immediately redrawn with the new styles.

Changing styles for XUL trees requires the implementation of a nsITreeView, some nsIAtomService manipulation and some Mozilla CSS Extensions, definitively a bit verbose but enough simple after a dozen of attempts :P.

The Mozilla CSS tree extensions are mainly pseudo-classes that can’t be modified from code, so you need to create a CSS text snippet with new values and then “reload” it.

Reloading CSS files can be accomplished using the nsIStyleSheetService service, it only requires a nsIURI pointing to the CSS resource.

Based on the scenario described above the styles are generated at runtime so I need to create a CSS style representation and stores it for example on a temp file. The styles don’t really need to be persisted on disk so why do I need to create an unuseful file?

Well using the “data:” protocol it is possible to encode the generated CSS string and pass to nsIURI the data uri without needs to create temporary files as shown below.

function applyUserStyles(cssStyles) {
    // myTreeChildren is the CSS class name used for the tree
    // obviously can be parametrized
    var css = '.myTreeChildren::-moz-tree-cell-text {' + cssStyles + '}';
    var data = 'data:text/css;charset=utf-8,' + encodeURI(css);
    var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
                .getService(Components.interfaces.nsIStyleSheetService);
    var ios = Components.classes["@mozilla.org/network/io-service;1"]
                .getService(Components.interfaces.nsIIOService);
    var u = ios.newURI(data, null, null);
    if (sss.sheetRegistered(u, sss.USER_SHEET)) {
        sss.unregisterSheet(u, sss.USER_SHEET);
    }
    sss.loadAndRegisterSheet(u, sss.USER_SHEET);
}
 

Maybe a simpler solution exists and my code is the worst way to proceed, if you know a better way please tell me 🙂

Advertisements

May 9, 2008

How to detect XUL trees scroll event

My extension VisualDiffer contains two nsITreeViews that must synchronize scrolling, when user scrolls one the other tree moves the selection to the corresponding row.

Apparently XUL trees don’t have any event handler to intercept scrolling operations so I run the risk to became crazy.

After days spent to find a solution (using google) without result I’ve tried to use the DOMAttrModified event and amazingly it worked.

First I add a listener to the tree (VisualDiffer adds listeners to left and right trees)

document.getElementById(“left-tree”).addEventListener(“DOMAttrModified”,
function(event) { gFolderDiffer.onLeftScroll(event);}, false);

The onScroll simply checks if event.attrName is “curpos” and if it’s true the tree has been scrolled by user

onLeftScroll : function(event) { if (event.attrName == “curpos”) {
rightTreeView.treebox.scrollToRow(leftTreeView.treebox.getFirstVisibleRow());
}
}

This solution works fine but maybe exists a better way…

Blog at WordPress.com.