+ First working draft of tabs and groups getting pushed out of the way by the creation of a new group

+ The grid feature now removes all the tabs from their groups beforehand; it doesn't restore tab sizes properly yet
+ You can now rearrange tabs inside a group
+ More geometry:
++ The Rect constructor now accepts either coordinates or another Rect
++ Rect.inset now accepts either coordinates or a Point
++ New functions: Rect.offset and Rect.equals
This commit is contained in:
Ian Gilman 2010-03-26 11:34:09 -07:00
parent a78be22cf5
commit f2426297ad
3 changed files with 132 additions and 50 deletions

View File

@ -63,8 +63,7 @@ Group.prototype = {
},
// ----------
create: function(listOfEls, manager) {
this.manager = manager;
create: function(listOfEls, options) {
var self = this;
this._children = $(listOfEls).toArray();
@ -142,31 +141,40 @@ Group.prototype = {
}
// ___ Push other objects away
this.pushAway();
if(!options || !options.suppressPush)
this.pushAway();
},
// ----------
pushAway: function() {
return; // TODO: not ready yet.
var buffer = 10;
var items = this.manager.getTopLevelItems();
var items = Items.getTopLevelItems();
$.each(items, function(index, item) {
item.pushAwayData = {};
var data = {};
data.bounds = item.getBounds();
data.startBounds = new Rect(data.bounds);
item.pushAwayData = data;
});
var itemsToPush = [this];
this.pushAwayData.anchored = true;
var pushOne = function(baseItem) {
baseItem.pushAwayData.anchored = true;
var bb = baseItem.getBounds();
var bb = new Rect(baseItem.pushAwayData.bounds);
bb.inset(-buffer, -buffer);
var bbc = bb.center();
$.each(items, function(index, item) {
if(item.pushAwayData.anchored)
if(item == baseItem)
return;
var box = item.getBounds();
var data = item.pushAwayData;
if(data.anchored)
return;
var bounds = data.bounds;
var box = new Rect(bounds);
box.inset(-buffer, -buffer);
if(box.intersects(bb)) {
var offset = new Point();
@ -182,15 +190,22 @@ Group.prototype = {
else
offset.x = bb.left - box.right;
}
/* Utils.log(offset); */
item.setPosition(box.left + offset.x, box.top + offset.y);
/* pushOne(item); */
bounds.offset(offset);
itemsToPush.push(item);
}
});
};
pushOne(this);
};
var a;
for(a = 0; a < 500 && itemsToPush.length; a++)
pushOne(itemsToPush.shift());
$.each(items, function(index, item) {
var data = item.pushAwayData;
if(!data.bounds.equals(data.startBounds))
item.setPosition(data.bounds.left, data.bounds.top);
});
},
// ----------
@ -207,13 +222,15 @@ Group.prototype = {
setPosition: function(left, top) {
var box = this.getBounds();
var offset = new Point(left - box.left, top - box.top);
$.each(this._children, function(index, value) {
var $el = $(this);
box = Utils.getBounds(this);
$el.animate({left: box.left + offset.x, top: box.top + offset.y});
});
$(this._container).animate({left: left, top: top});
var bb = Utils.getBounds(this._container);
$(this._container).animate({left: bb.left + offset.x, top: bb.top + offset.y});
},
// ----------
@ -224,6 +241,8 @@ Group.prototype = {
if( typeof(dropPos) == "undefined" ) dropPos = {top:window.innerWidth, left:window.innerHeight};
var self = this;
// TODO: You should be allowed to drop in the white space at the bottom and have it go to the end
// (right now it can match the thumbnail above it and go there)
function findInsertionPoint(dropPos){
var best = {dist: Infinity, el: null};
var index = 0;
@ -231,7 +250,7 @@ Group.prototype = {
var pos = $(child).position();
var [w, h] = [$(child).width(), $(child).height()];
var dist = Math.sqrt( Math.pow((pos.top+h/2)-dropPos.top,2) + Math.pow((pos.left+w/2)-dropPos.left,2) );
Utils.log( index, dist );
/* Utils.log( index, dist ); */
if( dist <= best.dist ){
best.el = child;
best.dist = dist;
@ -249,12 +268,12 @@ Group.prototype = {
}
var oldIndex = $.inArray(el, this._children);
if(oldIndex != -1)
this._children.splice(oldIndex, 1);
var index = findInsertionPoint(dropPos);
if($.inArray(el, this._children) == -1){
this._children.splice( index, 0, el );
}
this._children.splice( index, 0, el );
$(el).droppable("disable");
@ -297,6 +316,15 @@ Group.prototype = {
},
// ----------
// TODO: could be a lot more efficient by unwrapping the remove routine
removeAll: function() {
var self = this;
$.each(this._children, function(index, child) {
self.remove(child);
});
},
// ----------
_updateGroup: function(){
var self = this;
@ -474,7 +502,7 @@ window.Groups = {
var group = $(target).data("group");
if( group == null ){
var group = new Group();
group.create([target, dragged], Groups);
group.create([target, dragged]);
} else {
group.add( dragged );
}
@ -522,8 +550,20 @@ window.Groups = {
y += h + padding;
}
});
},
},
// ----------
removeAll: function() {
var $groups = $('.group');
$groups.each(function() {
var group = $(this).data('group');
group.removeAll();
});
}
};
// ##########
window.Items = {
// ----------
getTopLevelItems: function() {
var items = [];

View File

@ -302,6 +302,9 @@ ArrangeClass.prototype = {
//----------------------------------------------------------
var grid = new ArrangeClass("Grid", function(value) {
if(typeof(Groups) != 'undefined')
Groups.removeAll();
var immediately = false;
if(typeof(value) == 'boolean')
immediately = value;
@ -331,6 +334,8 @@ var grid = new ArrangeClass("Grid", function(value) {
//----------------------------------------------------------
var site = new ArrangeClass("Site", function() {
Groups.removeAll();
var startX = 30;
var startY = 100;
var x = startX;
@ -342,34 +347,32 @@ var site = new ArrangeClass("Site", function() {
$el = $(this);
var tab = Tabs.tab(this);
var group = $el.data('group');
if(group)
group.remove(this);
var url = tab.url;
var domain = url.split('/')[2];
var domainParts = domain.split('.');
var mainDomain = domainParts[domainParts.length - 2];
if(groups[mainDomain])
groups[mainDomain].push(this);
groups[mainDomain].push($(this));
else
groups[mainDomain] = [this];
groups[mainDomain] = [$(this)];
});
var createOptions = {suppressPush: true};
var leftovers = [];
for(key in groups) {
var set = groups[key];
if(set.length > 1) {
group = new Groups.Group();
group.create(set);
group.create(set, createOptions);
} else
leftovers.push(set[0]);
}
if(leftovers.length > 1) {
/* if(leftovers.length > 1) { */
group = new Groups.Group();
group.create(leftovers);
}
group.create(leftovers, createOptions);
/* } */
Groups.arrange();
});

View File

@ -17,37 +17,50 @@ var consoleService = Cc["@mozilla.org/consoleservice;1"]
var extensionManager = Cc["@mozilla.org/extensions/manager;1"]
.getService(Ci.nsIExtensionManager);
// ----------
// ##########
window.Point = function(x, y) {
this.x = (typeof(x) == 'undefined' ? 0 : x);
this.y = (typeof(y) == 'undefined' ? 0 : y);
}
// ----------
window.Rect = function(left, top, width, height) {
this.left = left;
this.top = top;
this.width = width;
this.height = height;
// ##########
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;
}
}
window.Rect.prototype = {
// ----------
get right() {
return this.left + this.width;
},
// ----------
set right(value) {
this.width = value - this.left;
},
// ----------
get bottom() {
return this.top + this.height;
},
// ----------
set bottom(value) {
this.height = value - this.top;
},
// ----------
intersects: function(rect) {
return (rect.right > this.left
&& rect.left < this.right
@ -55,19 +68,45 @@ window.Rect.prototype = {
&& rect.top < this.bottom);
},
// ----------
center: function() {
return new Point(this.left + (this.width / 2), this.top + (this.height / 2));
},
inset: function(x, y) {
this.left += x;
this.width -= x * 2;
this.top += y;
this.height -= y * 2;
// ----------
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);
}
};
// ----------
// ##########
var Utils = {
// ___ Windows and Tabs
get activeWindow(){