Fix bug 389445 - The view doesn't scroll with the mouse if I drag start/end time to a hidden hour display. r=philipp
authorDecathlon <bv1578@gmail.com>
Thu, 21 Nov 2013 08:03:55 +0100
changeset 16915 eb971b974099082371fb9140979430e3267f36b7
parent 16914 ffe30ba8cd1bcc73b49e9b5bbcf8e47c7d7199de
child 16916 9b1106f87c8c1c38e2fea32aabc65957a4d95950
push id1074
push userbugzilla@standard8.plus.com
push dateMon, 03 Feb 2014 22:47:23 +0000
treeherdercomm-beta@6b791b5369ed [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersphilipp
bugs389445
Fix bug 389445 - The view doesn't scroll with the mouse if I drag start/end time to a hidden hour display. r=philipp
calendar/base/content/calendar-multiday-view.xml
--- a/calendar/base/content/calendar-multiday-view.xml
+++ b/calendar/base/content/calendar-multiday-view.xml
@@ -1358,30 +1358,91 @@
               }
 
               col.mDragState = null;
               document.calendarEventColumnDragging = null;
           }
         ]]></body>
       </method>
 
+      <method name="clearMagicScroll">
+        <body><![CDATA[
+          if (this.mMagicScrollTimer) {
+              clearTimeout(this.mMagicScrollTimer);
+              this.mMagicScrollTimer = null;
+          }
+        ]]></body>
+      </method>
+
+      <method name="setupMagicScroll">
+        <parameter name="event"/>
+        <body><![CDATA[
+          this.clearMagicScroll();
+
+          // If we are at the bottom or top of the view (or left/right when
+          // rotated), calculate the difference and start accelerating the
+          // scrollbar.
+          let diffStart, diffEnd;
+          let orient = event.target.getAttribute("orient");
+          let scrollbox = document.getAnonymousElementByAttribute(
+                         event.target, "anonid", "scrollbox");
+          if (orient == "vertical") {
+              diffStart = event.clientY - scrollbox.boxObject.y;
+              diffEnd = scrollbox.boxObject.y + scrollbox.boxObject.height - event.clientY;
+          } else {
+              diffStart = event.clientX - scrollbox.boxObject.x;
+              diffEnd = scrollbox.boxObject.x + scrollbox.boxObject.width - event.clientX;
+          }
+
+          const SCROLLZONE = 55;    // Size (pixels) of the top/bottom view where the scroll starts.
+          const MAXTIMEOUT = 250,   // Max and min time interval (ms) between
+                MINTIMEOUT = 30;    // two consecutive scrolls.
+          const SCROLLBYHOUR = .33; // Part of hour to move for each scroll.
+          let insideScrollZone = 0;
+          let pxPerHr = event.target.mPixPerMin * 60;
+          let scrollBy = Math.floor(pxPerHr * SCROLLBYHOUR);
+          if (diffStart < SCROLLZONE) {
+              insideScrollZone = SCROLLZONE - diffStart;
+              scrollBy *= -1;
+          } else if (diffEnd < SCROLLZONE) {
+              insideScrollZone = SCROLLZONE - diffEnd;
+          }
+
+          if (insideScrollZone) {
+              let sbo = scrollbox.boxObject.QueryInterface(Components.interfaces.nsIScrollBoxObject);
+              let timeout = MAXTIMEOUT - insideScrollZone * (MAXTIMEOUT - MINTIMEOUT) / SCROLLZONE;
+              this.mMagicScrollTimer = setTimeout(function() {
+                  sbo.scrollBy(orient == "horizontal" && scrollBy,
+                               orient == "vertical" && scrollBy);
+                  this.onEventSweepMouseMove(event);
+              }.bind(this), timeout);
+          }
+        ]]></body>
+      </method>
+
       <!--
          - Event sweep handlers
         -->
       <method name="onEventSweepMouseMove">
         <parameter name="event"/>
         <body><![CDATA[
           let col = document.calendarEventColumnDragging;
           if (!col) return;
 
+          col.setupMagicScroll(event);
+
           let dragState = col.mDragState;
 
           let lateralColumns = col.firstLastShadowColumns();
           let firstCol = lateralColumns.firstCol;
           let firstIndex = lateralColumns.firstIndex;
+
+          // If we leave the view, then stop our internal sweeping and start a
+          // real drag session. Someday we need to fix the sweep to soely be a
+          // drag session, no sweeping.
           if (event.clientX < (event.target.boxObject.x) ||
               event.clientX > (event.target.boxObject.x + event.target.boxObject.width) ||
               event.clientY < (event.target.boxObject.y) ||
               event.clientY > (event.target.boxObject.y + event.target.boxObject.height)) {
 
               // Remove the drag state
               for (let column = firstCol, i = firstIndex;
                    column && i < col.mDragState.shadows;
@@ -1563,16 +1624,18 @@
           let index = lateralColumns.firstIndex;
           while (column && index < dragState.shadows) {
               column.fgboxes.dragbox.removeAttribute("dragging");
               column.fgboxes.box.removeAttribute("dragging");
               column = column.nextSibling;
               index++;
           }
 
+          col.clearMagicScroll();
+
           window.removeEventListener("mousemove", col.onEventSweepMouseMove, false);
           window.removeEventListener("mouseup", col.onEventSweepMouseUp, false);
           window.removeEventListener("keypress", col.onEventSweepKeypress, false);
 
           document.calendarEventColumnDragging = null;
 
           // if the user didn't sweep out at least a few pixels, ignore
           // unless we're in a different column