Fix bug 392194 - Incorrect time and shadow is shown when draging an event in week/day view. r=philipp
authorDecathlon <bv1578@gmail.com>
Mon, 02 Nov 2009 10:14:02 +0100
changeset 4285 3d69701584653c3176e788498647c1e5864403e5
parent 4284 6f99bf71b1f6107177974e81ad75d1006d3dbf86
child 4286 7c25972181652c1321812f1906e9007147adc192
push id3348
push usermozilla@kewis.ch
push dateMon, 02 Nov 2009 09:14:27 +0000
treeherdercomm-central@3d6970158465 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersphilipp
bugs392194
Fix bug 392194 - Incorrect time and shadow is shown when draging an event in week/day view. 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
@@ -580,19 +580,20 @@
            if (stdate.compare(this.mDate) == -1) {
                startHour = 0;
                startMinute = 0;
            }
            if (enddate.compare(this.mDate) == 1) {
                endHour = 24;
                endMinute = 0;
            }
-
-           return { start: startHour * 60 + startMinute,
-                    end:   endHour   * 60 + endMinute };
+           let dur = aOccurrence.duration;
+           return { start:        startHour * 60 + startMinute,
+                    end:          endHour   * 60 + endMinute,
+                    realDuration: (dur.days * 24 + dur.hours) * 60 + dur.minutes};
         ]]></body>
       </method>
 
       <method name="createChunk">
         <parameter name="aOccurrence"/>
         <body><![CDATA[
            var mins = this.getStartEndMinutesForOccurrence(aOccurrence);
 
@@ -820,17 +821,17 @@
                           innerColumn.appendChild(chunkBox);
                           chunkBox.calendarView = this.calendarView;
                           chunkBox.occurrence = chunk.event;
                           chunkBox.parentColumn = this;
                           if (chunk.event.hashId in this.mSelectedItemIds) {
                               chunkBox.selected = true;
                               this.mSelectedChunks.push(chunkBox);
                           }
-                          
+
                           this.mEventBoxes.push(chunkBox);
 
                           if (this.mEventToEdit &&
                               chunkBox.occurrence.hashId == this.mEventToEdit.hashId) {
                               boxToEdit = chunkBox;
                           }
                       } else {
                           var chunkBox = createXULElement("spacer");
@@ -1240,25 +1241,25 @@
       </method>
 
       <!--
          - Event sweep handlers
         -->
       <method name="onEventSweepMouseMove">
         <parameter name="event"/>
         <body><![CDATA[
-          var col = document.calendarEventColumnDragging;
+          let col = document.calendarEventColumnDragging;
           if (!col) return;
 
           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)) {
 
-              var dragState = col.mDragState;
+              let dragState = col.mDragState;
               col.fgboxes.dragbox.removeAttribute("dragging");
               col.fgboxes.box.removeAttribute("dragging");
               window.removeEventListener("mousemove", col.onEventSweepMouseMove, false);
               window.removeEventListener("mouseup", col.onEventSweepMouseUp, false);
               document.calendarEventColumnDragging = null;
               col.mDragState = null;
 
 
@@ -1276,17 +1277,17 @@
                   })) {
                   col.calendarView.setSelectedItems(1,
                       [event.ctrlKey ? item.parentItem : item]);
               }
               invokeEventDragSession(dragState.dragOccurrence, col);
               return;
           }
 
-          var dragState = col.mDragState;
+          let dragState = col.mDragState;
 
           col.fgboxes.box.setAttribute("dragging", "true");
           col.fgboxes.dragbox.setAttribute("dragging", "true");
 
           // check if we need to jump a column
           if (dragState.dragType == "move") {
               let newcol = col.calendarView.findColumnForClientPoint(event.screenX, event.screenY);
               if (newcol && newcol != col) {
@@ -1299,46 +1300,49 @@
 
                   // restart event handling
                   col.onEventSweepMouseMove(event);
 
                   return;
               }
           }
 
-          var pos;
-          var sizeattr;
+          let mousePos;
+          let sizeattr;
           if (col.getAttribute("orient") == "vertical") {
-              pos = event.screenY - col.parentNode.boxObject.screenY - dragState.mouseOffset;
+              mousePos = event.screenY - col.parentNode.boxObject.screenY;
               sizeattr = "height";
           } else {
-              pos = event.screenX - col.parentNode.boxObject.screenX - dragState.mouseOffset;
+              mousePos = event.screenX - col.parentNode.boxObject.screenX;
               sizeattr = "width";
           }
-          // don't let pos go outside the window edges
-          if (pos < 0)
-              pos = 0;
+          // don't let mouse position go outside the window edges
+          let pos = Math.max(0, mousePos) - dragState.mouseOffset;
 
           // snap to 15 minute intervals
-          var interval = col.mPixPerMin * 15;
-          var curmin = Math.floor(pos/interval) * 15;
-          var deltamin = curmin - dragState.origMin;
+          let interval = col.mPixPerMin * 15;
+          let curmin = Math.floor(pos/interval) * 15;
+          let deltamin = curmin - dragState.origMin;
 
           if (dragState.dragType == "new") {
               if (deltamin < 0) {
                   dragState.startMin = dragState.origMin + deltamin;
                   dragState.endMin = dragState.origMin;
               } else {
                   dragState.startMin = dragState.origMin;
                   dragState.endMin = dragState.origMin + deltamin;
               }
           } else if (dragState.dragType == "move") {
-              // if we're moving, we can only move the start, and the end has to be exactly start+duration
-              dragState.startMin = dragState.origMin + deltamin;
-              dragState.endMin = dragState.startMin + dragState.limitDurationMin;
+              // if we're moving, we modify startMin and endMin. When startMin
+              // is negative, the event start is in the previous day. We keep
+              // track to calculate the event's final position but then we set
+              // startMin to zero to show the shadow box with the right size
+              dragState.lastStart = dragState.origMinStart + deltamin;
+              dragState.endMin = Math.min(1440, dragState.origMinEnd + deltamin);
+              dragState.startMin = Math.max(0, dragState.origMinStart + deltamin);
           } else if (dragState.dragType == "modify-start") {
               // if we're modifying the start, the end time is fixed.
               dragState.startMin = dragState.origMin + deltamin;
               dragState.endMin = dragState.limitEndMin;
 
               // but we need to not go past the end; if we hit
               // the end, then we'll clamp to the previous 15-min interval
               if (dragState.endMin <= dragState.startMin)
@@ -1398,21 +1402,22 @@
                   return;
               }
           }
 
           var newStart;
           var newEnd;
           var startTZ;
           var endTZ;
+          let dragDay = col.mDate;
 
           if (dragState.dragType == "new") {
-              newStart = col.mDate.clone();
+              newStart = dragDay.clone();
               newStart.isDate = false;
-              newEnd = col.mDate.clone();
+              newEnd = dragDay.clone();
               newEnd.isDate = false;
           } else {
               var oldStart = dragState.dragOccurrence.startDate || dragState.dragOccurrence.entryDate;
               var oldEnd = dragState.dragOccurrence.endDate || dragState.dragOccurrence.dueDate;
               newStart = oldStart.clone();
               newEnd = oldEnd.clone();
 
               // Our views are pegged to the default timezone.  If the event
@@ -1424,36 +1429,34 @@
                   this.mTimezone != newEnd.timezone) {
                   startTZ = newStart.timezone;
                   endTZ = newEnd.timezone;
                   newStart = newStart.getInTimezone(col.calendarView.mTimezone);
                   newEnd = newEnd.getInTimezone(col.calendarView.mTimezone);
               }
           }
 
-          var dragDay = col.mDate;
-
           if (dragState.dragType == "modify-start" ||
               dragState.dragType == "new") {
               newStart.resetTo(dragDay.year, dragDay.month, dragDay.day,
                                0, dragState.startMin + col.mStartMin, 0,
                                newStart.timezone);
           }
 
           if (dragState.dragType == "modify-end" ||
               dragState.dragType == "new") {
               newEnd.resetTo(dragDay.year, dragDay.month, dragDay.day,
                              0, dragState.endMin + col.mStartMin, 0,
                              newEnd.timezone);
           }
 
           if (dragState.dragType == "move") {
               // Figure out how much the event moved.
-              var duration = col.mDate.subtractDate(dragState.origDate);
-              var minutes = dragState.startMin - dragState.origMin;
+              let duration = dragDay.subtractDate(dragState.origDate);
+              let minutes = dragState.lastStart - dragState.origMinStart;
 
               // Since both boxDate and beginMove are dates (note datetimes),
               // subtractDate will only give us a non-zero number of hours on
               // DST changes. While strictly speaking, subtractDate's behavior
               // is correct, we need to move the event a discrete number of
               // days here. There is no need for normalization here, since
               // addDuration does the job for us. Also note, the duration used
               // here is only used to move over multiple days. Moving on the
@@ -1573,23 +1576,36 @@
               this.mDragState.limitStartMin = mins.start;
 
               // snap end
               this.mDragState.origMin = Math.floor(mins.end/15) * 15;
               this.fgboxes.dragspacer.setAttribute(sizeattr, mins.start * this.mPixPerMin);
               this.fgboxes.dragbox.setAttribute(sizeattr, (this.mDragState.origMin - mins.start) * this.mPixPerMin);
           } else if (aGrabbedElement == "middle") {
               this.mDragState.dragType = "move";
-              this.mDragState.limitDurationMin = mins.end - mins.start;
+              this.mDragState.limitDurationMin = mins.realDuration;
 
               // in a move, origMin will be the min of the start element;
-              // so we snap start again, but we keep the duration the same
-              // (we move the end based on the duration of the event,
-              // not including our snap)
+              // but we also use the min of start and end separately because
+              // we snap to one or the other according to the event start.
               this.mDragState.origMin = Math.floor(mins.start/15) * 15;
+              if (this.mDragState.origMin == 0) {
+                  // event starts on 0:00 or the day before. We drag the final
+                  // part so we snap the end and subtract duration to set
+                  // origMinStart to the real event duration (if negative the
+                  // event starts in the previous day)
+                  this.mDragState.origMinEnd = Math.floor(mins.end/15) * 15;
+                  this.mDragState.origMinStart = this.mDragState.origMinEnd - this.mDragState.limitDurationMin;
+              } else {
+                  // event starts the day on which we are moving. We snap the
+                  // start and add duration to set origMinEnd to the real end
+                  // of the event
+                  this.mDragState.origMinStart = Math.floor(mins.start/15) * 15;
+                  this.mDragState.origMinEnd = this.mDragState.origMinStart + this.mDragState.limitDurationMin;
+              }
 
               // Because we can pass this event to other columns, we also need
               // to track the original column's date too, to get the correct offset
               this.mDragState.origDate = this.mDate;
               this.fgboxes.dragspacer.setAttribute(sizeattr, this.mDragState.origMin * this.mPixPerMin);
               this.fgboxes.dragbox.setAttribute(sizeattr, (mins.end - mins.start) * this.mPixPerMin);
 
               // we need to set a mouse offset, since we're not dragging from
@@ -1636,20 +1652,17 @@
 
       <method name="updateDragLabels">
         <body><![CDATA[
           if (!this.mDragState) return;
 
           var realstartmin = this.mDragState.startMin + this.mStartMin;
           var realendmin = this.mDragState.endMin + this.mStartMin;
 
-
-          if (this.mDragState.dragType == "move") {
-              realendmin = realstartmin + this.mDragState.limitDurationMin;
-          } else if (this.mDragState.dragType == "start") {
+          if (this.mDragState.dragType == "start") {
               realendmin = this.mDragState.limitEndMin;
           } else if (this.mDragState.dragType == "end") {
               realstartmin = this.mDragSTate.limitStartMin;
           }
 
           var starthr = Math.floor(realstartmin / 60);
           var startmin = realstartmin % 60;