diff --git a/browser/base/content/tabcandy/app/groups.js b/browser/base/content/tabcandy/app/groups.js
index c61429da1490..406d6a161f3b 100644
--- a/browser/base/content/tabcandy/app/groups.js
+++ b/browser/base/content/tabcandy/app/groups.js
@@ -936,10 +936,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);
diff --git a/browser/base/content/tabcandy/app/ui.js b/browser/base/content/tabcandy/app/ui.js
index 6809dadf0a0e..91f594231cb1 100644
--- a/browser/base/content/tabcandy/app/ui.js
+++ b/browser/base/content/tabcandy/app/ui.js
@@ -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
@@ -177,7 +185,70 @@ window.Page = {
}
lastTab = this;
});
- }
+ },
+
+ // ----------
+ createGroupOnDrag: function(e){
+ e.preventDefault();
+ const minSize = 60;
+
+ var startPos = {x:e.clientX, y:e.clientY}
+ var phantom = $("
").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;
+ }
}
// ##########
diff --git a/browser/base/content/tabcandy/core/utils.js b/browser/base/content/tabcandy/core/utils.js
index fe165deb04c5..16572aa123b0 100644
--- a/browser/base/content/tabcandy/core/utils.js
+++ b/browser/base/content/tabcandy/core/utils.js
@@ -102,6 +102,34 @@ window.Rect.prototype = {
&& rect.top < this.bottom);
},
+ // ----------
+ // Function: containsPoint
+ // Returns a boolean denoting if the
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 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));