+ You can now click-n-drag in empty space to create a group. If the group is too small, it will animate away (the cancel action) and if they group contains orphaned tabs, lo', it pulls those tabs into itself.

+ Changed the behavior of removing the penultimate tab from a group. The group no longer goes away until the very last tab is removed.
+ Added some new rect utilities for finding if a point/rect is inside another rect
This commit is contained in:
Aza Raskin 2010-05-06 16:28:10 -07:00
parent 68a5fc8948
commit 67dc79f22c
3 changed files with 104 additions and 1 deletions

View File

@ -924,10 +924,14 @@ DragInfo.prototype = {
stop: function() {
this.$el.data('isDragging', false);
// I'm commenting this out for a while as I believe it feels uncomfortable
// 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
&& this.parent._children.length == 1 && !this.parent.getTitle()) {
this.parent.remove(this.parent._children[0]);
}
}*/
if(this.item && !this.$el.hasClass('willGroup') && !this.item.parent) {
this.item.setZ(drag.zIndex);

View File

@ -129,6 +129,14 @@ window.Page = {
init: function() {
Utils.homeTab.raw.maxWidth = 60;
Utils.homeTab.raw.minWidth = 60;
// When you click on the background/empty part of TabCandy
// we create a new group.
$(Utils.homeTab.contentDocument).mousedown(function(e){
if( e.originalTarget.nodeName == "HTML" )
Page.createGroupOnDrag(e)
})
Tabs.onClose(function(){
// Only go back to the TabCandy tab when there you close the last
@ -179,6 +187,69 @@ window.Page = {
});
},
// ----------
createGroupOnDrag: function(e){
e.preventDefault();
const minSize = 60;
var startPos = {x:e.clientX, y:e.clientY}
var phantom = $("<div class='group'>").css({
position: "absolute",
top: startPos.y,
left: startPos.x,
width: 0,
height: 0,
opacity: .7,
zIndex: -1,
cursor: "default"
}).appendTo("body");
function updateSize(e){
var css = {width: e.clientX-startPos.x, height:e.clientY-startPos.y}
if( css.width > minSize || css.height > minSize ) css.opacity = 1;
else css.opacity = .7
phantom.css(css);
e.preventDefault();
}
function collapse(){
phantom.animate({
width: 0,
height: 0,
top: phantom.position().top + phantom.height()/2,
left: phantom.position().left + phantom.width()/2
}, 300, function(){
phantom.remove();
})
}
function finalize(e){
$("html").unbind("mousemove");
if( phantom.css("opacity") != 1 ) collapse();
else{
var bounds = new Rect(startPos.x, startPos.y, phantom.width(), phantom.height())
// Add all of the orphaned tabs that are contained inside the new group
// to that group.
var tabs = Groups.getOrphanedTabs();
var insideTabs = [];
for each( tab in tabs ){
if( bounds.contains( tab.bounds ) ){
insideTabs.push(tab);
}
}
var group = new Group(insideTabs,{bounds:bounds});
phantom.remove();
}
}
$("html").mousemove(updateSize)
$("html").one('mouseup',finalize);
return false;
},
// ----------
findOpenSpaceFor: function($div) {
var w = window.innerWidth;

View File

@ -102,6 +102,34 @@ window.Rect.prototype = {
&& rect.top < this.bottom);
},
// ----------
// Function: containsPoint
// Returns a boolean denoting if the <Point> is inside of
// the bounding rect.
//
// Paramaters
// - A point
containsPoint: function(point){
return( point.x > this.left
&& point.x < this.right
&& point.y > this.top
&& point.y < this.bottom )
},
// ----------
// Function: contains
// Returns a boolean denoting if the <Rect> is contained inside
// of the bounding rect.
//
// Paramaters
// - A rect
contains: function(rect){
return( rect.left > this.left
&& rect.right < this.right
&& rect.top > this.top
&& rect.bottom < this.bottom )
},
// ----------
center: function() {
return new Point(this.left + (this.width / 2), this.top + (this.height / 2));