2010-02-24 01:47:55 -08:00
|
|
|
(function(){
|
|
|
|
|
|
|
|
const Cc = Components.classes;
|
|
|
|
const Ci = Components.interfaces;
|
|
|
|
const Cu = Components.utils;
|
|
|
|
const Cr = Components.results;
|
|
|
|
|
|
|
|
// Get this in a way where we can load the page automatically
|
|
|
|
// where it doesn't need to be focused...
|
|
|
|
var homeWindow = Cc["@mozilla.org/embedcomp/window-watcher;1"]
|
2010-03-03 17:21:44 -08:00
|
|
|
.getService(Ci.nsIWindowWatcher)
|
|
|
|
.activeWindow;
|
|
|
|
|
|
|
|
var consoleService = Cc["@mozilla.org/consoleservice;1"]
|
|
|
|
.getService(Components.interfaces.nsIConsoleService);
|
2010-02-24 01:47:55 -08:00
|
|
|
|
2010-03-05 15:14:10 -08:00
|
|
|
var extensionManager = Cc["@mozilla.org/extensions/manager;1"]
|
|
|
|
.getService(Ci.nsIExtensionManager);
|
|
|
|
|
2010-03-26 11:34:09 -07:00
|
|
|
// ##########
|
2010-03-25 17:22:45 -07:00
|
|
|
window.Point = function(x, y) {
|
|
|
|
this.x = (typeof(x) == 'undefined' ? 0 : x);
|
|
|
|
this.y = (typeof(y) == 'undefined' ? 0 : y);
|
|
|
|
}
|
|
|
|
|
2010-03-26 11:34:09 -07:00
|
|
|
// ##########
|
|
|
|
window.Rect = function(a, top, width, height) {
|
|
|
|
if(typeof(a.left) != 'undefined' && typeof(a.top) != 'undefined'
|
|
|
|
&& typeof(a.right) != 'undefined' && typeof(a.bottom) != 'undefined') {
|
|
|
|
this.left = a.left;
|
|
|
|
this.top = a.top;
|
|
|
|
this.width = a.width;
|
|
|
|
this.height = a.height;
|
|
|
|
} else {
|
|
|
|
this.left = a;
|
|
|
|
this.top = top;
|
|
|
|
this.width = width;
|
|
|
|
this.height = height;
|
|
|
|
}
|
2010-03-24 16:54:48 -07:00
|
|
|
}
|
|
|
|
|
2010-03-25 17:22:45 -07:00
|
|
|
window.Rect.prototype = {
|
2010-03-26 11:34:09 -07:00
|
|
|
// ----------
|
2010-03-24 16:54:48 -07:00
|
|
|
get right() {
|
|
|
|
return this.left + this.width;
|
|
|
|
},
|
|
|
|
|
2010-03-26 11:34:09 -07:00
|
|
|
// ----------
|
2010-03-24 16:54:48 -07:00
|
|
|
set right(value) {
|
|
|
|
this.width = value - this.left;
|
|
|
|
},
|
|
|
|
|
2010-03-26 11:34:09 -07:00
|
|
|
// ----------
|
2010-03-24 16:54:48 -07:00
|
|
|
get bottom() {
|
|
|
|
return this.top + this.height;
|
|
|
|
},
|
|
|
|
|
2010-03-26 11:34:09 -07:00
|
|
|
// ----------
|
2010-03-24 16:54:48 -07:00
|
|
|
set bottom(value) {
|
|
|
|
this.height = value - this.top;
|
|
|
|
},
|
|
|
|
|
2010-03-26 11:34:09 -07:00
|
|
|
// ----------
|
2010-03-24 16:54:48 -07:00
|
|
|
intersects: function(rect) {
|
|
|
|
return (rect.right > this.left
|
|
|
|
&& rect.left < this.right
|
|
|
|
&& rect.bottom > this.top
|
|
|
|
&& rect.top < this.bottom);
|
2010-03-25 17:22:45 -07:00
|
|
|
},
|
|
|
|
|
2010-03-26 11:34:09 -07:00
|
|
|
// ----------
|
2010-03-25 17:22:45 -07:00
|
|
|
center: function() {
|
|
|
|
return new Point(this.left + (this.width / 2), this.top + (this.height / 2));
|
|
|
|
},
|
|
|
|
|
2010-03-26 11:34:09 -07:00
|
|
|
// ----------
|
|
|
|
inset: function(a, b) {
|
|
|
|
if(typeof(a.x) != 'undefined' && typeof(a.y) != 'undefined') {
|
|
|
|
b = a.y;
|
|
|
|
a = a.x;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.left += a;
|
|
|
|
this.width -= a * 2;
|
|
|
|
this.top += b;
|
|
|
|
this.height -= b * 2;
|
|
|
|
},
|
|
|
|
|
|
|
|
// ----------
|
|
|
|
offset: function(a, b) {
|
|
|
|
if(typeof(a.x) != 'undefined' && typeof(a.y) != 'undefined') {
|
|
|
|
this.left += a.x;
|
|
|
|
this.top += a.y;
|
|
|
|
} else {
|
|
|
|
this.left += a;
|
|
|
|
this.top += b;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
// ----------
|
|
|
|
equals: function(a) {
|
|
|
|
return (a.left == this.left
|
|
|
|
&& a.top == this.top
|
|
|
|
&& a.right == this.right
|
|
|
|
&& a.bottom == this.bottom);
|
2010-03-31 17:24:16 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// ##########
|
|
|
|
// TODO generalize for any number of events
|
|
|
|
window.Subscribable = function() {
|
|
|
|
this.onCloseSubscribers = [];
|
|
|
|
};
|
|
|
|
|
|
|
|
window.Subscribable.prototype = {
|
|
|
|
// ----------
|
|
|
|
addOnClose: function(referenceElement, callback) {
|
|
|
|
var existing = jQuery.grep(this.onCloseSubscribers, function(element) {
|
|
|
|
return element.referenceElement == referenceElement;
|
|
|
|
});
|
|
|
|
|
|
|
|
if(existing.size) {
|
|
|
|
Utils.assert('should only ever be one', existing.size == 1);
|
|
|
|
existing[0].callback = callback;
|
|
|
|
} else {
|
|
|
|
this.onCloseSubscribers.push({
|
|
|
|
referenceElement: referenceElement,
|
|
|
|
callback: callback
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
// ----------
|
|
|
|
removeOnClose: function(referenceElement) {
|
|
|
|
this.onCloseSubscribers = jQuery.grep(this.onCloseSubscribers, function(element) {
|
|
|
|
return element.referenceElement == referenceElement;
|
|
|
|
}, true);
|
|
|
|
},
|
|
|
|
|
|
|
|
// ----------
|
|
|
|
_sendOnClose: function() {
|
|
|
|
jQuery.each(this.onCloseSubscribers, function(index, object) {
|
|
|
|
object.callback(this);
|
|
|
|
});
|
2010-03-24 16:54:48 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-03-26 11:34:09 -07:00
|
|
|
// ##########
|
2010-02-24 01:47:55 -08:00
|
|
|
var Utils = {
|
2010-03-05 15:14:10 -08:00
|
|
|
// ___ Windows and Tabs
|
2010-02-24 01:47:55 -08:00
|
|
|
get activeWindow(){
|
|
|
|
var win = Cc["@mozilla.org/embedcomp/window-watcher;1"]
|
|
|
|
.getService(Ci.nsIWindowWatcher)
|
|
|
|
.activeWindow;
|
|
|
|
|
|
|
|
if( win != null ) return win;
|
|
|
|
else return homeWindow;
|
|
|
|
},
|
|
|
|
|
|
|
|
get activeTab(){
|
|
|
|
var tabBrowser = this.activeWindow.gBrowser;
|
|
|
|
return tabBrowser.selectedTab;
|
|
|
|
},
|
|
|
|
|
|
|
|
get homeTab(){
|
|
|
|
for( var i=0; i<Tabs.length; i++){
|
|
|
|
if(Tabs[i].contentWindow.location.host == "tabcandy"){
|
|
|
|
return Tabs[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
},
|
2010-03-05 15:14:10 -08:00
|
|
|
|
|
|
|
// ___ Files
|
|
|
|
getInstallDirectory: function(id) {
|
|
|
|
var file = extensionManager.getInstallLocation(id).getItemFile(id, "install.rdf");
|
|
|
|
return file.parent;
|
|
|
|
},
|
|
|
|
|
|
|
|
getFiles: function(dir) {
|
|
|
|
var files = [];
|
|
|
|
if(dir.isReadable() && dir.isDirectory) {
|
|
|
|
var entries = dir.directoryEntries;
|
|
|
|
while(entries.hasMoreElements()) {
|
|
|
|
var entry = entries.getNext();
|
|
|
|
entry.QueryInterface(Ci.nsIFile);
|
|
|
|
files.push(entry);
|
|
|
|
}
|
|
|
|
}
|
2010-03-03 17:21:44 -08:00
|
|
|
|
2010-03-05 15:14:10 -08:00
|
|
|
return files;
|
|
|
|
},
|
|
|
|
|
|
|
|
getVisualizationNames: function() {
|
|
|
|
var names = [];
|
|
|
|
var dir = this.getInstallDirectory('tabcandy@aza.raskin');
|
|
|
|
dir.append('content');
|
|
|
|
dir.append('candies');
|
|
|
|
var files = this.getFiles(dir);
|
|
|
|
var count = files.length;
|
|
|
|
var a;
|
|
|
|
for(a = 0; a < count; a++) {
|
|
|
|
var file = files[a];
|
|
|
|
if(file.isDirectory())
|
|
|
|
names.push(file.leafName);
|
|
|
|
}
|
|
|
|
|
|
|
|
return names;
|
|
|
|
},
|
2010-03-03 17:21:44 -08:00
|
|
|
|
2010-03-05 15:14:10 -08:00
|
|
|
// ___ Logging
|
2010-03-16 22:25:00 -07:00
|
|
|
|
|
|
|
// Interactive logging!
|
|
|
|
ilog: function(){ // pass as many arguments as you want, it'll print them all
|
|
|
|
// If Firebug lite already exists, print to the console.
|
|
|
|
if( window.firebug ){
|
|
|
|
window.firebug.d.console.cmd.log.apply(null, arguments);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Else, embed it.
|
|
|
|
$('<link rel="stylesheet" href="../../js/firebuglite/firebug-lite.css"/>')
|
|
|
|
.appendTo("head");
|
|
|
|
|
|
|
|
$('<script src="../../js/firebuglite/firebug-lite.js"></script>')
|
|
|
|
.appendTo("body");
|
|
|
|
|
|
|
|
var args = arguments;
|
|
|
|
|
|
|
|
(function(){
|
|
|
|
var fb = window.firebug;
|
|
|
|
if(fb && fb.version){
|
|
|
|
fb.init();
|
|
|
|
fb.win.setHeight(100);
|
|
|
|
fb.d.console.cmd.log.apply(null, args);
|
|
|
|
}
|
|
|
|
else{setTimeout(arguments.callee);}
|
|
|
|
})();
|
|
|
|
},
|
|
|
|
|
2010-03-05 15:14:10 -08:00
|
|
|
log: function() { // pass as many arguments as you want, it'll print them all
|
|
|
|
var text = this.expandArgumentsForLog(arguments);
|
|
|
|
consoleService.logStringMessage(text);
|
2010-03-03 17:21:44 -08:00
|
|
|
},
|
2010-02-24 01:47:55 -08:00
|
|
|
|
2010-03-15 17:15:27 -07:00
|
|
|
error: function() { // pass as many arguments as you want, it'll print them all
|
2010-03-05 15:14:10 -08:00
|
|
|
var text = this.expandArgumentsForLog(arguments);
|
2010-03-15 17:15:27 -07:00
|
|
|
Cu.reportError('tabcandy error: ' + text);
|
2010-03-03 17:21:44 -08:00
|
|
|
},
|
|
|
|
|
2010-03-15 17:15:27 -07:00
|
|
|
trace: function() { // pass as many arguments as you want, it'll print them all
|
2010-03-05 15:14:10 -08:00
|
|
|
var text = this.expandArgumentsForLog(arguments);
|
2010-03-03 17:21:44 -08:00
|
|
|
if(typeof(printStackTrace) != 'function')
|
|
|
|
this.log(text + ' trace: you need to include stacktrace.js');
|
|
|
|
else {
|
|
|
|
var calls = printStackTrace();
|
|
|
|
calls.splice(0, 3); // Remove this call and the printStackTrace calls
|
2010-03-05 17:21:38 -08:00
|
|
|
this.log('trace: ' + text + '\n' + calls.join('\n'));
|
2010-03-03 17:21:44 -08:00
|
|
|
}
|
|
|
|
},
|
2010-03-15 17:15:27 -07:00
|
|
|
|
|
|
|
assert: function(label, condition) {
|
|
|
|
if(!condition) {
|
|
|
|
var text = 'tabcandy assert: ' + label;
|
|
|
|
if(typeof(printStackTrace) == 'function') {
|
|
|
|
var calls = printStackTrace();
|
|
|
|
text += '\n' + calls[3];
|
|
|
|
}
|
|
|
|
|
|
|
|
Cu.reportError(text);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2010-03-03 17:21:44 -08:00
|
|
|
expandObject: function(obj) {
|
|
|
|
var s = obj + ' = {';
|
|
|
|
for(prop in obj) {
|
|
|
|
var value = obj[prop];
|
2010-03-24 16:54:48 -07:00
|
|
|
s += prop + ': ';
|
|
|
|
if(typeof(value) == 'string')
|
|
|
|
s += '\'' + value + '\'';
|
|
|
|
else if(typeof(value) == 'function')
|
|
|
|
s += 'function';
|
|
|
|
else
|
|
|
|
s += value;
|
|
|
|
|
|
|
|
s += ", ";
|
2010-03-03 17:21:44 -08:00
|
|
|
}
|
|
|
|
return s + '}';
|
2010-03-05 15:14:10 -08:00
|
|
|
},
|
|
|
|
|
|
|
|
expandArgumentsForLog: function(args) {
|
|
|
|
var s = '';
|
|
|
|
var count = args.length;
|
|
|
|
var a;
|
|
|
|
for(a = 0; a < count; a++) {
|
|
|
|
var arg = args[a];
|
|
|
|
if(typeof(arg) == 'object')
|
|
|
|
arg = this.expandObject(arg);
|
|
|
|
|
|
|
|
s += arg;
|
|
|
|
if(a < count - 1)
|
|
|
|
s += '; ';
|
|
|
|
}
|
|
|
|
|
|
|
|
return s;
|
|
|
|
},
|
|
|
|
|
|
|
|
testLogging: function() {
|
|
|
|
this.log('beginning logging test');
|
|
|
|
this.error('this is an error');
|
|
|
|
this.trace('this is a trace');
|
|
|
|
this.log(1, null, {'foo': 'hello', 'bar': 2}, 'whatever');
|
|
|
|
this.log('ending logging test');
|
2010-03-09 14:21:08 -08:00
|
|
|
},
|
|
|
|
|
|
|
|
// ___ Event
|
|
|
|
isRightClick: function(event) {
|
|
|
|
if(event.which)
|
|
|
|
return (event.which == 3);
|
|
|
|
else if(event.button)
|
|
|
|
return (event.button == 2);
|
|
|
|
|
|
|
|
return false;
|
2010-03-11 16:14:50 -08:00
|
|
|
},
|
|
|
|
|
|
|
|
// ___ Time
|
|
|
|
getMilliseconds: function() {
|
|
|
|
var date = new Date();
|
|
|
|
return date.getTime();
|
2010-03-24 14:38:23 -07:00
|
|
|
},
|
|
|
|
|
2010-03-24 16:54:48 -07:00
|
|
|
// ___ Geometry
|
|
|
|
getBounds: function(el) {
|
|
|
|
var $el = $(el);
|
|
|
|
return new Rect(
|
|
|
|
parseInt($el.css('left')),
|
|
|
|
parseInt($el.css('top')),
|
|
|
|
$el.width(),
|
|
|
|
$el.height()
|
|
|
|
);
|
|
|
|
},
|
|
|
|
|
2010-03-24 14:38:23 -07:00
|
|
|
// ___ Misc
|
|
|
|
isJQuery: function(object) {
|
|
|
|
// TODO: need more robust way
|
|
|
|
return (object && typeof(object.fadeIn) == 'function' ? true : false);
|
|
|
|
}
|
2010-03-05 15:14:10 -08:00
|
|
|
};
|
2010-02-24 01:47:55 -08:00
|
|
|
|
|
|
|
window.Utils = Utils;
|
|
|
|
|
|
|
|
})();
|