Skip to content

Commit

Permalink
New extension example: how to create panel splitter
Browse files Browse the repository at this point in the history
  • Loading branch information
janodvarko committed Aug 20, 2013
1 parent 67af3c9 commit f200d49
Show file tree
Hide file tree
Showing 9 changed files with 407 additions and 0 deletions.
152 changes: 152 additions & 0 deletions PanelSplitter/bootstrap.js
@@ -0,0 +1,152 @@
/* See license.txt for terms of usage */

// ********************************************************************************************* //
// XPCOM

var {classes: Cc, interfaces: Ci, utils: Cu} = Components;

// ********************************************************************************************* //
// Constants

// Extension installation path. Set within startup callback.
var installPath;

// ********************************************************************************************* //
// Firefox Bootstrap API

function install(data, reason) {}
function uninstall(data, reason) {}

function startup(data, reason)
{
// Remember so, we can use later within firebugStartup callback.
installPath = data.installPath;

// Firebug extension start-up callback. Since extension load order isn't guaranteed
// the code needs to be ready for two alternatives:
// 1) Firebug is already loaded - good, let's just execute firebugStartup() callback
// that will ensure proper Firebug related initialization for this extension.
// 2) Firebug is not loaded yet - as soon as Firebug is loaded it'll execute this
// method automatically.
firebugStartup();
}

function shutdown(data, reason)
{
firebugShutdown();
}

function isFirebugLoaded()
{
try
{
// Import Firebug modules into this scope. It fails if Firebug isn't loaded yet.
Cu.import("resource://firebug/loader.js");
Cu.import("resource://firebug/prefLoader.js");

return true;
}
catch (e)
{
// Report the error only if you want to track cases where this extension
// is loaded before Firebug.
//Cu.reportError(e);
}

return false;
}

// ********************************************************************************************* //
// Firebug Bootstrap API

/**
* Executed by Firebug framework when Firebug is started. Since the order of Firebug
* and its bootstrapped extensions is not guaranteed this function is executed twice.
* 1) When Firebug is loaded
* 2) When this extension is loaded
*/
function firebugStartup()
{
// If Firebug isn't loaded just bail out, Firebug will execute this method
// as soon as it loads.
if (!isFirebugLoaded())
return;

// At this point, Firebug is loaded and we can use its API.
FirebugLoader.registerBootstrapScope(this);

// Load default preferences
PrefLoader.loadDefaultPrefs(installPath, "prefs.js");
}

/**
* Executed by Firefox when this extension shutdowns.
*/
function firebugShutdown()
{
try
{
FirebugLoader.unregisterBootstrapScope(this);
}
catch (e)
{
Cu.reportError(e);
}
}

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

/**
* Executed by Firebug framework for every browser window. Use this function to append
* any new elements into the browser window (browser.xul). Don't forget to remove
* these elements in topWindowUnload.
*
* @param {Window} win The browser window
*/
function topWindowLoad(win)
{
// TODO: overlay global browser window
}

/**
* Executed by Firebug framework when this extension
* @param {Object} win
*/
function topWindowUnload(win)
{
// TODO: remove global browser window overlays
}

/**
* Entire Firebug UI is running inside an iframe (firebugFrame.xul). This function
* is executed by Firebug framework when the frame is loaded. This happens when
* the user requires Firebug for the first time (doesn't have to happen during the
* Firefox session at all)
*
* @param {Window} win The Firebug window
*/
function firebugFrameLoad(Firebug)
{
// Register trace listener the customizes trace logs coming from this extension
// * panelSplitter; is unique prefix of all messages that should be customized.
// * DBG_PANELSPLITTER is a class name with style defined in the specified stylesheet.
Firebug.registerTracePrefix("panelSplitter;", "DBG_PANELSPLITTER", true,
"chrome://panelsplitter/skin/panelsplitter.css");

// The registration process will automatically look for 'main' module and load it.
// The is the same what happens in a XUL overlay applied on:
// chrome://firebug/content/firebugOverlay.xul
var config = {id: "panelsplitter@janodvarko.cz"};
Firebug.registerExtension("panelsplitter", config);
}

function firebugFrameUnload(Firebug)
{
if (!Firebug.isInitialized)
return;

Firebug.unregisterExtension("panelsplitter");
Firebug.unregisterTracePrefix("panelSplitter;");
}

// ********************************************************************************************* //
3 changes: 3 additions & 0 deletions PanelSplitter/chrome.manifest
@@ -0,0 +1,3 @@
content panelsplitter chrome/content/
skin panelsplitter classic/1.0 chrome/skin/classic/
locale panelsplitter en-US chrome/locale/en-US/
41 changes: 41 additions & 0 deletions PanelSplitter/chrome/content/main.js
@@ -0,0 +1,41 @@
/* See license.txt for terms of usage */

define([
"firebug/lib/trace",
"panelsplitter/myPanel",
],
function(FBTrace, MyPanel) {

// ********************************************************************************************* //
// The Application Object

var theApp =
{
initialize: function()
{
if (FBTrace.DBG_PANELSPLITTER)
FBTrace.sysout("panelSplitter; initialize");

// TODO: Extension initialization
},

shutdown: function()
{
if (FBTrace.DBG_PANELSPLITTER)
FBTrace.sysout("panelSplitter; shutdown");

// Unregister all registered Firebug components
Firebug.unregisterPanel(MyPanel);
Firebug.unregisterStylesheet("chrome://panelsplitter/skin/panelsplitter.css");
Firebug.unregisterStringBundle("chrome://panelsplitter/locale/panelsplitter.properties");

// TODO: Extension shutdown
}
}

// ********************************************************************************************* //

return theApp;

// ********************************************************************************************* //
});
116 changes: 116 additions & 0 deletions PanelSplitter/chrome/content/myPanel.js
@@ -0,0 +1,116 @@
/* See license.txt for terms of usage */

define([
"firebug/lib/object",
"firebug/lib/trace",
"firebug/lib/locale",
"firebug/lib/domplate",
"firebug/lib/dom",
"firebug/lib/http",
"firebug/lib/wrapper",
"firebug/lib/array",
"firebug/lib/dragdrop",
],
function(Obj, FBTrace, Locale, Domplate, Dom, Http, Wrapper, Arr, DragDrop) {

"use strict";

// ********************************************************************************************* //
// Custom Panel Implementation

function MyPanel() {};
MyPanel.prototype = Obj.extend(Firebug.Panel,
{
name: "panelsplitter",
title: "Panel with a splitter",

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Initialization

initialize: function()
{
Firebug.Panel.initialize.apply(this, arguments);
this.refresh();
},

destroy: function(state)
{
Firebug.Panel.destroy.apply(this, arguments);
},

refresh: function()
{
this.MyTemplate.render(this.panelNode);

// Initialize panel splitter
var handler = this.panelNode.querySelector(".myResizer");
this.resizer = new DragDrop.Tracker(handler, {
onDragStart: Obj.bind(this.onDragStart, this),
onDragOver: Obj.bind(this.onDragOver, this),
onDrop: Obj.bind(this.onDrop, this)
});
},

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Splitter

onDragStart: function(tracker)
{
var body = Dom.getBody(this.document);
body.setAttribute("resizingHtmlPreview", "true");

var topPane = this.panelNode.querySelector(".topPane");
this.startHeight = topPane.clientHeight;
},

onDragOver: function(newPos, tracker)
{
var newHeight = (this.startHeight + newPos.y);
var topPane = this.panelNode.querySelector(".topPane");
topPane.style.height = newHeight + "px";
},

onDrop: function(tracker)
{
var body = Dom.getBody(this.document);
body.removeAttribute("resizingHtmlPreview");
},
});

// ********************************************************************************************* //
// Panel UI (Domplate)

// Register strings before the following template definition.
Firebug.registerStringBundle("chrome://panelsplitter/locale/panelsplitter.properties");

var {domplate, DIV} = Domplate;

MyPanel.prototype.MyTemplate = domplate(
{
tag:
DIV(
DIV({"class": "topPane"},
Locale.$STR("panelsplitter.panel.label1")
),
DIV({"class": "myResizer"}),
DIV({"class": "bottomPane"},
Locale.$STR("panelsplitter.panel.label2")
)
),

render: function(parentNode)
{
this.tag.replace({}, parentNode);
}
})

// ********************************************************************************************* //
// Registration

Firebug.registerPanel(MyPanel);
Firebug.registerStylesheet("chrome://panelsplitter/skin/panelsplitter.css");

return MyPanel;

// ********************************************************************************************* //
});
2 changes: 2 additions & 0 deletions PanelSplitter/chrome/locale/en-US/panelsplitter.properties
@@ -0,0 +1,2 @@
panelsplitter.panel.label1=Top panel. Min and max height of this panel is defined in panelsplitter.css
panelsplitter.panel.label2=Bottom panel
36 changes: 36 additions & 0 deletions PanelSplitter/chrome/skin/classic/panelsplitter.css
@@ -0,0 +1,36 @@
/* See license.txt for terms of usage */

/*************************************************************************************************/

/* Style applied on the panel node. Rule syntax: .panelNode-<extid> */
.panelNode-panelsplitter {
overflow: hidden;
padding: 0;
font-size: 12px;
}

/*************************************************************************************************/
/* Splitter */

.topPane {
height: 100px;
min-height: 25px;
max-height: 200px;
}

.myResizer {
width: 100%;
height: 5px;
background-color: lightgrey;
cursor: s-resize;
}

/*************************************************************************************************/

/* Firebug Tracing Console customization. All messages from this example use this color.
This helps to distinguish logs from those coming from Firebug
Rule syntax: .DBG_<ext-id>
See: http://getfirebug.com/wiki/index.php/FBTrace for more details */
.DBG_PANELSPLITTER {
color: rgb(101, 0, 114);
}
1 change: 1 addition & 0 deletions PanelSplitter/defaults/preferences/prefs.js
@@ -0,0 +1 @@
pref("extensions.firebug.DBG_PANELSPLITTER", true);
26 changes: 26 additions & 0 deletions PanelSplitter/install.rdf
@@ -0,0 +1,26 @@
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">

<Description about="urn:mozilla:install-manifest">
<em:id>panelsplitter@janodvarko.cz</em:id>
<em:version>0.5</em:version>
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>

<!-- Target Application this extension can install into,
with minimum and maximum supported versions. -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>10.0</em:minVersion>
<em:maxVersion>30.*</em:maxVersion>
</Description>
</em:targetApplication>

<!-- Front End MetaData -->
<em:name>PanelSplitter</em:name>
<em:description>Firebug extension example.</em:description>
<em:creator>Jan Odvarko</em:creator>
<em:homepageURL>http://getfirebug.com</em:homepageURL>
</Description>
</RDF>

0 comments on commit f200d49

Please sign in to comment.