guide trenches now originally start at their minRange range and then extend after a second
authorMichael Yoshitaka Erlewine <mitcho@mitcho.com>
Wed, 30 Jun 2010 00:46:15 -0400
changeset 50055 fcf9398b7c92ac1306c2587b83b98ebea634b52d
parent 50054 943639aadf8511adb41583f8715a894d800e472f
child 50056 ae8ed0a14a61dcf8de6b95007f62063f1278cc5c
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.3a6pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
guide trenches now originally start at their minRange range and then extend after a second
browser/base/content/tabcandy/app/drag.js
browser/base/content/tabcandy/app/trench.js
--- a/browser/base/content/tabcandy/app/drag.js
+++ b/browser/base/content/tabcandy/app/drag.js
@@ -112,28 +112,28 @@ Drag.prototype = {
         ) { 
       newRect = Trenches.snap(bounds,assumeConstantSize,keepProportional);
       if (newRect) { // might be false if no changes were made
         update = true;
         snappedTrenches = newRect.snappedTrenches || {};
         bounds = newRect;
       }
     } else {
-      Trenches.hideGuides();
+      Trenches.hideGuides( true );
     }
 
     // make sure the bounds are in the window.
     newRect = this.snapToEdge(bounds,assumeConstantSize,keepProportional);
     if (newRect) {
       update = true;
       bounds = newRect;
       iQ.extend(snappedTrenches,newRect.snappedTrenches);
     }
 
-    Trenches.hideGuides();
+    Trenches.hideGuides( true );
     for (let edge in snappedTrenches) {
       let trench = snappedTrenches[edge];
       if (typeof trench == 'object') {
         trench.showGuide = true;
         trench.show();
       } else if (trench === 'edge') {
         // show the edge.
       }
@@ -226,16 +226,17 @@ Drag.prototype = {
       }
     }
   },
 
   // ----------  
   // Function: stop
   // Called in response to an <Item> draggable "stop" event.
   stop: function() {
+		Trenches.hideGuides();
     this.item.isDragging = false;
 
     if(this.parent && !this.parent.locked.close && this.parent != this.item.parent 
         && this.parent._children.length == 0 && !this.parent.getTitle()) {
       this.parent.close();
     }
      
     if(this.parent && this.parent.expanded)
--- a/browser/base/content/tabcandy/app/trench.js
+++ b/browser/base/content/tabcandy/app/trench.js
@@ -104,16 +104,24 @@ var Trench = function(element, xory, typ
   //----------
   // Variables: some Ranges
   //   range - (<Range>) explicit range; this is along the transverse axis
   //   minRange - (<Range>) the minimum active range
   //   activeRange - (<Range>) the currently active range
   this.range = new Range(0,10000);
   this.minRange = new Range(0,0);
   this.activeRange = new Range(0,10000);
+  
+  //----------
+  // Variable: extending guide trench variables
+  // only makes sense for guide trenches
+  //   extended - (bool) whether this trench has been extended or not.
+  //   
+  this.extended = false;
+  this.snapBeginTime = false;
 };
 Trench.prototype = {
   //----------
   // Function: setPosition
   // set the trench's position.
   // 
   // Parameters:
   //   position - (integer) px center position of the trench
@@ -206,29 +214,40 @@ Trench.prototype = {
   //----------
   // Function: show
   // 
   // Show guide (dotted line), if <showGuide> is true.
   // 
   // If <Trenches.showDebug> is true, we will draw the trench. Active portions are drawn with 0.5
   // opacity. If <active> is false, the entire trench will be
   // very translucent.
-  show: function Trench_show() { // DEBUG
+  show: function Trench_show( animateExtend ) { // DEBUG
 
-    if (this.active && this.showGuide) {
-      if (!this.dom.guideTrench)
-        this.dom.guideTrench = iQ("<div/>").addClass('guideTrench').css({id: 'guideTrench'+this.id});
-      var guideTrench = this.dom.guideTrench;
-      guideTrench.css(this.guideRect);
-      iQ("body").append(guideTrench);
+    if (this.active && (this.showGuide || this.extended)) {
+      if (!this.dom.guideTrench) {
+        var guideTrench = this.dom.guideTrench = iQ("<div/>").addClass('guideTrench').css({id: 'guideTrench'+this.id});
+//        if (!this.animatingExtend)
+          guideTrench.css(this.guideRect);
+        iQ("body").append(guideTrench);
+      }
+      if (animateExtend) {
+        this.animatingExtend = true;
+        var self = this;
+        this.dom.guideTrench.animate( this.guideRect, {
+          complete: function () { self.animatingExtend = false; },
+          duration: 500,
+        } );
+      }
     } else {
-      if (this.dom.guideTrench)
+      if (this.dom.guideTrench) {
         this.dom.guideTrench.remove();
+        delete this.dom.guideTrench;
+      }
     }
-
+    
     if (!Trenches.showDebug) {
       this.hide( true ); // true for dontHideGuides
       return;
     }
 
     if (!this.dom.visibleTrench)
       this.dom.visibleTrench = iQ("<div/>")
         .addClass('visibleTrench')
@@ -259,16 +278,18 @@ Trench.prototype = {
   // Hide the trench.
   hide: function Trench_hide( dontHideGuides ) {
     if (this.dom.visibleTrench)
       this.dom.visibleTrench.remove();
     if (this.dom.activeVisibleTrench)
       this.dom.activeVisibleTrench.remove();
     if (!dontHideGuides && this.dom.guideTrench)
       this.dom.guideTrench.remove();
+    if (!dontHideGuides && this.extended)
+      this.unextend();
   },
 
   //----------
   // Function: rectOverlaps
   // Given a <Rect>, compute whether it overlaps with this trench. If it does, return an
   // adjusted ("snapped") <Rect>; if it does not overlap, simply return false.
   //
   // Note that simply overlapping is not all that is required to be affected by this function.
@@ -398,16 +419,22 @@ Trench.prototype = {
   calculateActiveRange: function Trench_calculateActiveRange() {
 
     // set it to the default: just the range itself.
     this.setActiveRange(this.range);
 
     // only guide-type trenches need to set a separate active range
     if (this.type != 'guide')
       return;
+    
+    // if it's not extended yet, let's just add a little 
+    if (!this.extended) {
+      this.setActiveRange(new Range(this.minRange.min - 30, this.minRange.max + 30));
+      return;
+    }
 
     var groups = Groups.groups;
     var trench = this;
     groups.forEach(function( group ) {
       if (group.isDragging) // floating groups don't block trenches
         return;
       if (group.isNewTabsGroup())
         return;
@@ -426,31 +453,48 @@ Trench.prototype = {
         activeRange = trench.adjustRangeIfIntercept(bounds.top, bounds.xRange);
         if (activeRange)
           trench.setActiveRange(activeRange);
         activeRange = trench.adjustRangeIfIntercept(bounds.bottom, bounds.xRange);
         if (activeRange)
           trench.setActiveRange(activeRange);
       }
     });
+  },
+  
+  extend: function Trench_extend() {
+    this.extended = true;
+    this.calculateActiveRange();
+    this.show( true );
+  },
+  
+  unextend: function Trench_unextend() {
+    this.snapBeginTime = false;
+    if (this.extended) {
+      this.extended = false;
+      this.calculateActiveRange();
+      this.show();
+    }
   }
 };
 
 // ##########
 // Class: Trenches
 // Singelton for managing all <Trench>es. 
 var Trenches = {
   // ---------
   // Variables:
   //   nextId - (integer) a counter for the next <Trench>'s <Trench.id> value.
   //   showDebug - (boolean) whether to draw the <Trench>es or not.
   //   defaultRadius - (integer) the default radius for new <Trench>es.
+  //   extendTime - (integer) the number of milliseconds before a <Trench> is extended.
   nextId: 0,
   showDebug: false,
   defaultRadius: 10,
+  extendTime: 1000, // in milliseconds
 
   // ---------
   // Variables: snapping preferences; used to break ties in snapping.
   //   preferTop - (boolean) prefer snapping to the top to the bottom
   //   preferLeft - (boolean) prefer snapping to the left to the right
   preferTop: true,
   preferLeft: true,
   
@@ -523,18 +567,20 @@ var Trenches = {
       t.showGuide = false;
       t.show();
     });
   },
 
   // ---------
   // Function: hideGuides
   // Hide all guides (dotted lines) en masse.
-  hideGuides: function Trenches_hideGuides() {
+  hideGuides: function Trenches_hideGuides( dontHideExtendedGuides ) {
     this.trenches.forEach(function(t) {
+      if (!dontHideExtendedGuides)
+        t.unextend();
       t.showGuide = false;
       t.show();
     });    
   },
 
   // ---------
   // Function: snap
   // Used to "snap" an object's bounds to active trenches and to the edge of the window.
@@ -578,46 +624,71 @@ var Trenches = {
           break;
         if (assumeConstantSize && updatedX && (newRect.adjustedEdge == "left"||newRect.adjustedEdge == "right"))
           continue;
         if (assumeConstantSize && updatedY && (newRect.adjustedEdge == "top"||newRect.adjustedEdge == "bottom"))
           continue;
 
         rect = newRect;
         updated = true;
-//        // turn on the guide
-//        t.showGuide = true;
-//        t.show();
   
         // register this trench as the "snapped trench" for the appropriate edge.
         snappedTrenches[newRect.adjustedEdge] = t;
   
         // if updatedX, we don't need to update x any more.
         if (newRect.adjustedEdge == "left" && this.preferLeft)
           updatedX = true;
         if (newRect.adjustedEdge == "right" && !this.preferLeft)
           updatedX = true;
   
         // if updatedY, we don't need to update x any more.
         if (newRect.adjustedEdge == "top" && this.preferTop)
           updatedY = true;
         if (newRect.adjustedEdge == "bottom" && !this.preferTop)
           updatedY = true;
 
-      } else if (t.showGuide) { // make sure to turn it off
+      }
+    }
+    
+    let stamp = Date.now();
+    if (updated) {
+      for (let i in snappedTrenches) {
+        let t = snappedTrenches[i];
+        t.showGuide = true;
+        t.show();
+        if (t.type == 'guide' && !t.snapBeginTime) {
+          t.snapBeginTime = stamp;
+          iQ.timeout(function(){
+            // if the timestamp is still the same...
+            // that means that this is a continuation of the same drag instance.
+            if (stamp == t.snapBeginTime)
+              t.extend();
+          }, Trenches.extendTime);
+        }
+      }
+    }
+    // clear the snapBeginTime for the other trenches
+    let snappedIds = [ snappedTrenches[j].id for (j in snappedTrenches) ];
+    for (let i in this.trenches) {
+      let t = this.trenches[i];
+      // make sure to turn the guide off if we're no longer snapping to it
+      if (t.showGuide && snappedIds.indexOf(t.id) == -1) {
         t.showGuide = false;
         t.show();
       }
+      if (t.snapBeginTime && snappedIds.indexOf(t.id) == -1 ) {
+//        t.unextend();
+      }
     }
-    
+
     if (updated) {
       rect.snappedTrenches = snappedTrenches;
       return rect;
     } else {
-      Trenches.hideGuides();
+      Trenches.hideGuides( true );
       return false;
     }
   },
 
   // ---------
   // Function: show
   // <Trench.show> all <Trench>es.
   show: function Trenches_show() {