+ The "new tabs" group can now not be renamed or closed, but it can be moved and resized. Updated how item locking works to accommodate this.

+ Groups now have some extra space at the bottom to accommodate for the "new tab" button
+ Items now unsquish after another item is closed, and on resize. This should cut down on random-seeming unsquishes later.
This commit is contained in:
Ian Gilman 2010-05-07 15:49:54 -07:00
parent e962f638a4
commit 5690ae628a
5 changed files with 173 additions and 89 deletions

View File

@ -36,13 +36,15 @@ window.Group = function(listOfEls, options) {
this._children = []; // an array of Items
this.defaultSize = new Point(TabItems.tabWidth * 1.5, TabItems.tabHeight * 1.5);
this.locked = options.locked || false;
this.isAGroup = true;
this.id = options.id || Groups.getNextID();
this.userSize = options.userSize || null;
this._isStacked = false;
this._stackAngles = [0];
this.expanded = null;
if(typeof(options.locked) == 'object')
this.locked = $.extend({}, options.locked);
var self = this;
@ -132,7 +134,7 @@ window.Group = function(listOfEls, options) {
.css({backgroundRepeat: 'no-repeat'})
.blur(titleUnfocus)
.focus(function() {
if(self.locked) {
if(self.locked.title) {
self.$title.blur();
return;
}
@ -147,7 +149,7 @@ window.Group = function(listOfEls, options) {
titleUnfocus();
if(this.locked)
if(this.locked.title)
this.$title.addClass('name-locked');
// ___ Content
@ -160,10 +162,11 @@ window.Group = function(listOfEls, options) {
.appendTo($container);
// ___ locking
if(this.locked) {
if(this.locked.bounds)
$container.css({cursor: 'default'});
/* $close.hide(); */
}
// if(this.locked.close)
// $close.hide();
// ___ Superclass initialization
this._init($container.get(0));
@ -179,7 +182,7 @@ window.Group = function(listOfEls, options) {
// ___ Finish Up
this._addHandlers($container);
if(!this.locked)
if(!this.locked.bounds)
this.setResizable(true);
Groups.register(this);
@ -200,8 +203,8 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
getStorageData: function() {
var data = {
bounds: this.getBounds(),
userSize: this.userSize,
locked: this.locked,
userSize: $.extend({}, this.userSize),
locked: $.extend({}, this.locked),
title: this.getTitle(),
id: this.id
};
@ -250,7 +253,7 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
box.top += titleHeight;
box.height -= titleHeight;
box.inset(6, 6);
box.height -= 15; // For new tab button
box.height -= 33; // For new tab button
return box;
},
@ -353,6 +356,7 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
Groups.unregister(this);
$(this.container).fadeOut(function() {
$(this).remove();
Items.unsquish();
});
},
@ -363,7 +367,7 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
$.each(toClose, function(index, child) {
child.close();
});
} else if(!this.locked)
} else if(!this.locked.close)
this.close();
},
@ -387,7 +391,7 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
item = Items.item($el);
}
Utils.assert('shouldn\'t already be in a group', !item.parent || item.parent == this);
Utils.assert('shouldn\'t already be in another group', !item.parent || item.parent == this);
if(!dropPos)
dropPos = {top:window.innerWidth, left:window.innerHeight};
@ -510,7 +514,7 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
if(typeof(item.setResizable) == 'function')
item.setResizable(true);
if(this._children.length == 0 && !this.locked && !this.getTitle()){
if(this._children.length == 0 && !this.locked.close && !this.getTitle()){
this.close();
} else if(!options.dontArrange) {
this.arrange();
@ -590,7 +594,7 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
var self = this;
$.each(this._children, function(index, child) {
if(!child.locked) {
if(!child.locked.bounds) {
child.setZ(zIndex);
zIndex--;
@ -731,7 +735,7 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
_addHandlers: function(container) {
var self = this;
if(!this.locked) {
if(!this.locked.bounds) {
$(container).draggable({
scroll: false,
cancel: '.close, .name',
@ -746,6 +750,12 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
drag.info = null;
}
});
/*
this.$title.mousedown(function() {
Utils.log('wtf');
});
*/
}
$(container).droppable({
@ -925,9 +935,9 @@ DragInfo.prototype = {
var now = Utils.getMilliseconds();
var distance = this.startPosition.distance(new Point(event.clientX, event.clientY));
if(now - this.startTime > 500 && distance > 100) {
this.item.locked = true;
this.item.locked.bounds = true;
this.parent.collapse();
this.item.locked = false;
this.item.locked.bounds = false;
}
}
},
@ -940,7 +950,7 @@ DragInfo.prototype = {
// that groups go away when there is still a tab in them. I do this at
// the cost of symmetry. -- Aza
/*
if(this.parent && !this.parent.locked && this.parent != this.item.parent
if(this.parent && !this.parent.locked.close && this.parent != this.item.parent
&& this.parent._children.length == 1 && !this.parent.getTitle()) {
this.parent.remove(this.parent._children[0]);
}*/
@ -1060,14 +1070,33 @@ window.Groups = {
if(data && data.groups) {
$.each(data.groups, function(index, group) {
new Group([], $.extend({}, group, {locked: false, dontPush: true}));
var isNewTabsGroup = (group.title == 'New Tabs');
var options = {
locked: {
close: isNewTabsGroup,
title: isNewTabsGroup
},
dontPush: true
};
new Group([], $.extend({}, group, options));
});
}
var group = this.getNewTabGroup();
if(!group) {
var box = this.getBoundsForNewTabGroup();
new Group([], {bounds: box, title: 'New Tabs', dontPush: true});
var options = {
locked: {
close: true,
title: true
},
dontPush: true,
bounds: box,
title: 'New Tabs'
};
new Group([], options);
}
},

View File

@ -38,7 +38,11 @@ window.Item = function() {
// Variable: locked
// Affects whether an item can be pushed, closed, renamed, etc
this.locked = false;
// The object may have properties to specify what can't be changed:
// .bounds is true if it can't be pushed, dragged, resized, etc
// .close is true if it can't be closed
// .title is true if it can't be renamed
this.locked = {};
// Variable: parent
// The group that this item is a child of
@ -48,10 +52,6 @@ window.Item = function() {
// A <Point> that describes the last size specifically chosen by the user.
// Used by unsquish.
this.userSize = null;
// Variable: locked
// True if the item should not be changed.
this.locked = false;
};
window.Item.prototype = {
@ -169,7 +169,7 @@ window.Item.prototype = {
var bbc = bb.center();
$.each(items, function(index, item) {
if(item == baseItem || item.locked)
if(item == baseItem || item.locked.bounds)
return;
var data = item.pushAwayData;
@ -212,7 +212,7 @@ window.Item.prototype = {
if(Items.squishMode == 'squish') {
$.each(items, function(index, item) {
var data = item.pushAwayData;
if(data.generation == 0 || item.locked)
if(data.generation == 0 || item.locked.bounds)
return;
function apply(item, posStep, posStep2, sizeStep) {
@ -276,7 +276,7 @@ window.Item.prototype = {
} else if(Items.squishMode == 'all') {
var newPageBounds = null;
$.each(items, function(index, item) {
if(item.locked)
if(item.locked.bounds)
return;
var data = item.pushAwayData;
@ -288,7 +288,7 @@ window.Item.prototype = {
var hScale = pageBounds.height / newPageBounds.height;
var scale = Math.min(hScale, wScale);
$.each(items, function(index, item) {
if(item.locked)
if(item.locked.bounds)
return;
var data = item.pushAwayData;
@ -305,65 +305,16 @@ window.Item.prototype = {
}
// ___ Unsquish
var pairs = [];
$.each(items, function(index, item) {
if(item.locked)
return;
var data = item.pushAwayData;
var bounds = data.bounds;
var newBounds = new Rect(bounds);
var newSize;
if(item.userSize)
newSize = new Point(item.userSize);
else
newSize = new Point(TabItems.tabWidth, TabItems.tabHeight);
if(item.isAGroup) {
newBounds.width = Math.max(newBounds.width, newSize.x);
newBounds.height = Math.max(newBounds.height, newSize.y);
} else {
if(bounds.width < newSize.x) {
newBounds.width = newSize.x;
newBounds.height = newSize.y;
}
}
newBounds.left -= (newBounds.width - bounds.width) / 2;
newBounds.top -= (newBounds.height - bounds.height) / 2;
var offset = new Point();
if(newBounds.left < pageBounds.left)
offset.x = pageBounds.left - newBounds.left;
else if(newBounds.right > pageBounds.right)
offset.x = pageBounds.right - newBounds.right;
if(newBounds.top < pageBounds.top)
offset.y = pageBounds.top - newBounds.top;
else if(newBounds.bottom > pageBounds.bottom)
offset.y = pageBounds.bottom - newBounds.bottom;
newBounds.offset(offset);
if(!bounds.equals(newBounds)) {
var blocked = false;
$.each(items, function(index, item2) {
if(item2 == item)
return;
var data2 = item2.pushAwayData;
var bounds2 = data2.bounds;
if(bounds2.intersects(newBounds)) {
blocked = true;
return false;
}
});
if(!blocked) {
data.bounds = newBounds;
}
}
pairs.push({
item: item,
bounds: data.bounds
});
});
Items.unsquish(pairs);
// ___ Apply changes
$.each(items, function(index, item) {
@ -521,7 +472,7 @@ window.Items = {
rects.push(new Rect(box));
else if(items && a < items.length) {
var item = items[a];
if(!item.locked) {
if(!item.locked.bounds) {
item.setBounds(box, immediately);
item.setRotation(0);
if(options.z)
@ -545,6 +496,95 @@ window.Items = {
}
return rects;
},
// ----------
// Function: unsquish
// Checks to see which items can now be unsquished.
//
// Parameters:
// pairs - an array of objects, each with two properties: item and bounds. The bounds are
// modified as appropriate, but the items are not changed. If pairs is null, the
// operation is performed directly on all of the top level items.
// ignore - an <Item> to not include in calculations (because it's about to be closed, for instance)
unsquish: function(pairs, ignore) {
var pairsProvided = (pairs ? true : false);
if(!pairsProvided) {
var items = Items.getTopLevelItems();
pairs = [];
$.each(items, function(index, item) {
pairs.push({
item: item,
bounds: item.getBounds()
});
});
}
var pageBounds = Items.getPageBounds();
$.each(pairs, function(index, pair) {
var item = pair.item;
if(item.locked.bounds || item == ignore)
return;
var bounds = pair.bounds;
var newBounds = new Rect(bounds);
var newSize;
if(item.userSize)
newSize = new Point(item.userSize);
else
newSize = new Point(TabItems.tabWidth, TabItems.tabHeight);
if(item.isAGroup) {
newBounds.width = Math.max(newBounds.width, newSize.x);
newBounds.height = Math.max(newBounds.height, newSize.y);
} else {
if(bounds.width < newSize.x) {
newBounds.width = newSize.x;
newBounds.height = newSize.y;
}
}
newBounds.left -= (newBounds.width - bounds.width) / 2;
newBounds.top -= (newBounds.height - bounds.height) / 2;
var offset = new Point();
if(newBounds.left < pageBounds.left)
offset.x = pageBounds.left - newBounds.left;
else if(newBounds.right > pageBounds.right)
offset.x = pageBounds.right - newBounds.right;
if(newBounds.top < pageBounds.top)
offset.y = pageBounds.top - newBounds.top;
else if(newBounds.bottom > pageBounds.bottom)
offset.y = pageBounds.bottom - newBounds.bottom;
newBounds.offset(offset);
if(!bounds.equals(newBounds)) {
var blocked = false;
$.each(pairs, function(index, pair2) {
if(pair2 == pair || pair2.item == ignore)
return;
var bounds2 = pair2.bounds;
if(bounds2.intersects(newBounds)) {
blocked = true;
return false;
}
});
if(!blocked) {
pair.bounds.copy(newBounds);
}
}
});
if(!pairsProvided) {
$.each(pairs, function(index, pair) {
pair.item.setBounds(pair.bounds);
});
}
}
};

View File

@ -292,6 +292,10 @@ window.TabItems = {
var item = new TabItem(this, tab);
$(this).data('tabItem', item);
item.addOnClose(self, function() {
Items.unsquish(null, item);
});
if(TabItems.reconnect(item))
reconnected = true;
else if(!tab.url || tab.url == 'about:blank') {

View File

@ -363,7 +363,7 @@ UIClass.prototype = {
itemBounds.width = 1;
itemBounds.height = 1;
$.each(items, function(index, item) {
if(item.locked)
if(item.locked.bounds)
return;
var bounds = item.getBounds();
@ -392,8 +392,9 @@ UIClass.prototype = {
var scale = Math.min(hScale, wScale);
var self = this;
var pairs = [];
$.each(items, function(index, item) {
if(item.locked)
if(item.locked.bounds)
return;
var bounds = item.getBounds();
@ -406,9 +407,18 @@ UIClass.prototype = {
bounds.top *= scale;
bounds.height *= scale;
item.setBounds(bounds, true);
pairs.push({
item: item,
bounds: bounds
});
});
Items.unsquish(pairs);
$.each(pairs, function(index, pair) {
pair.item.setBounds(pair.bounds, true);
});
this.pageBounds = Items.getPageBounds();
},

View File

@ -167,6 +167,7 @@ window.Rect.prototype = {
&& a.bottom == this.bottom);
},
// ----------
union: function(a){
var newLeft = Math.min(a.left, this.left);
var newTop = Math.min(a.top, this.top);