mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 09:45:41 +00:00
Bug 1197192 - Allow dragging the scrubber not just from the timeline header; r=ochameau
This adds a new invisible element centered around the scrubber and thick enough for users to drag from. --HG-- extra : commitid : 8T6UnzIMd35 extra : rebase_source : 4076198dae2bd3cf9fce7ad68f5f5615d98ef5bf extra : histedit_source : e1b038a2dc1f9a6bca504c207886d67e75636e8f%2C26ac318b25a7abd516fedfbced3ced3359af58c4
This commit is contained in:
parent
c77bb5f29b
commit
0b132638a2
@ -459,10 +459,10 @@ function AnimationsTimeline(inspector) {
|
|||||||
this.inspector = inspector;
|
this.inspector = inspector;
|
||||||
|
|
||||||
this.onAnimationStateChanged = this.onAnimationStateChanged.bind(this);
|
this.onAnimationStateChanged = this.onAnimationStateChanged.bind(this);
|
||||||
this.onTimeHeaderMouseDown = this.onTimeHeaderMouseDown.bind(this);
|
this.onScrubberMouseDown = this.onScrubberMouseDown.bind(this);
|
||||||
this.onTimeHeaderMouseUp = this.onTimeHeaderMouseUp.bind(this);
|
this.onScrubberMouseUp = this.onScrubberMouseUp.bind(this);
|
||||||
this.onTimeHeaderMouseOut = this.onTimeHeaderMouseOut.bind(this);
|
this.onScrubberMouseOut = this.onScrubberMouseOut.bind(this);
|
||||||
this.onTimeHeaderMouseMove = this.onTimeHeaderMouseMove.bind(this);
|
this.onScrubberMouseMove = this.onScrubberMouseMove.bind(this);
|
||||||
|
|
||||||
EventEmitter.decorate(this);
|
EventEmitter.decorate(this);
|
||||||
}
|
}
|
||||||
@ -487,13 +487,21 @@ AnimationsTimeline.prototype = {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.scrubberHandleEl = createNode({
|
||||||
|
parent: this.scrubberEl,
|
||||||
|
attributes: {
|
||||||
|
"class": "scrubber-handle"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.scrubberHandleEl.addEventListener("mousedown", this.onScrubberMouseDown);
|
||||||
|
|
||||||
this.timeHeaderEl = createNode({
|
this.timeHeaderEl = createNode({
|
||||||
parent: this.rootWrapperEl,
|
parent: this.rootWrapperEl,
|
||||||
attributes: {
|
attributes: {
|
||||||
"class": "time-header"
|
"class": "time-header"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.timeHeaderEl.addEventListener("mousedown", this.onTimeHeaderMouseDown);
|
this.timeHeaderEl.addEventListener("mousedown", this.onScrubberMouseDown);
|
||||||
|
|
||||||
this.animationsEl = createNode({
|
this.animationsEl = createNode({
|
||||||
parent: this.rootWrapperEl,
|
parent: this.rootWrapperEl,
|
||||||
@ -509,7 +517,9 @@ AnimationsTimeline.prototype = {
|
|||||||
this.unrender();
|
this.unrender();
|
||||||
|
|
||||||
this.timeHeaderEl.removeEventListener("mousedown",
|
this.timeHeaderEl.removeEventListener("mousedown",
|
||||||
this.onTimeHeaderMouseDown);
|
this.onScrubberMouseDown);
|
||||||
|
this.scrubberHandleEl.removeEventListener("mousedown",
|
||||||
|
this.onScrubberMouseDown);
|
||||||
|
|
||||||
this.rootWrapperEl.remove();
|
this.rootWrapperEl.remove();
|
||||||
this.animations = [];
|
this.animations = [];
|
||||||
@ -518,6 +528,7 @@ AnimationsTimeline.prototype = {
|
|||||||
this.timeHeaderEl = null;
|
this.timeHeaderEl = null;
|
||||||
this.animationsEl = null;
|
this.animationsEl = null;
|
||||||
this.scrubberEl = null;
|
this.scrubberEl = null;
|
||||||
|
this.scrubberHandleEl = null;
|
||||||
this.win = null;
|
this.win = null;
|
||||||
this.inspector = null;
|
this.inspector = null;
|
||||||
},
|
},
|
||||||
@ -539,18 +550,21 @@ AnimationsTimeline.prototype = {
|
|||||||
this.animationsEl.innerHTML = "";
|
this.animationsEl.innerHTML = "";
|
||||||
},
|
},
|
||||||
|
|
||||||
onTimeHeaderMouseDown: function(e) {
|
onScrubberMouseDown: function(e) {
|
||||||
this.moveScrubberTo(e.pageX);
|
this.moveScrubberTo(e.pageX);
|
||||||
this.win.addEventListener("mouseup", this.onTimeHeaderMouseUp);
|
this.win.addEventListener("mouseup", this.onScrubberMouseUp);
|
||||||
this.win.addEventListener("mouseout", this.onTimeHeaderMouseOut);
|
this.win.addEventListener("mouseout", this.onScrubberMouseOut);
|
||||||
this.win.addEventListener("mousemove", this.onTimeHeaderMouseMove);
|
this.win.addEventListener("mousemove", this.onScrubberMouseMove);
|
||||||
|
|
||||||
|
// Prevent text selection while dragging.
|
||||||
|
e.preventDefault();
|
||||||
},
|
},
|
||||||
|
|
||||||
onTimeHeaderMouseUp: function() {
|
onScrubberMouseUp: function() {
|
||||||
this.cancelTimeHeaderDragging();
|
this.cancelTimeHeaderDragging();
|
||||||
},
|
},
|
||||||
|
|
||||||
onTimeHeaderMouseOut: function(e) {
|
onScrubberMouseOut: function(e) {
|
||||||
// Check that mouseout happened on the window itself, and if yes, cancel
|
// Check that mouseout happened on the window itself, and if yes, cancel
|
||||||
// the dragging.
|
// the dragging.
|
||||||
if (!this.win.document.contains(e.relatedTarget)) {
|
if (!this.win.document.contains(e.relatedTarget)) {
|
||||||
@ -559,12 +573,12 @@ AnimationsTimeline.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
cancelTimeHeaderDragging: function() {
|
cancelTimeHeaderDragging: function() {
|
||||||
this.win.removeEventListener("mouseup", this.onTimeHeaderMouseUp);
|
this.win.removeEventListener("mouseup", this.onScrubberMouseUp);
|
||||||
this.win.removeEventListener("mouseout", this.onTimeHeaderMouseOut);
|
this.win.removeEventListener("mouseout", this.onScrubberMouseOut);
|
||||||
this.win.removeEventListener("mousemove", this.onTimeHeaderMouseMove);
|
this.win.removeEventListener("mousemove", this.onScrubberMouseMove);
|
||||||
},
|
},
|
||||||
|
|
||||||
onTimeHeaderMouseMove: function(e) {
|
onScrubberMouseMove: function(e) {
|
||||||
this.moveScrubberTo(e.pageX);
|
this.moveScrubberTo(e.pageX);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -8,23 +8,21 @@
|
|||||||
// in the header area.
|
// in the header area.
|
||||||
// Also check that doing so changes the timeline's play/pause button to paused
|
// Also check that doing so changes the timeline's play/pause button to paused
|
||||||
// state.
|
// state.
|
||||||
|
// Finally, also check that the scrubber can be moved using the scrubber handle.
|
||||||
|
|
||||||
add_task(function*() {
|
add_task(function*() {
|
||||||
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
|
yield addTab(TEST_URL_ROOT + "doc_simple_animation.html");
|
||||||
|
|
||||||
let {panel} = yield openAnimationInspector();
|
let {panel} = yield openAnimationInspector();
|
||||||
|
|
||||||
let timeline = panel.animationsTimelineComponent;
|
let timeline = panel.animationsTimelineComponent;
|
||||||
let win = timeline.win;
|
let {win, timeHeaderEl, scrubberEl, scrubberHandleEl} = timeline;
|
||||||
let timeHeaderEl = timeline.timeHeaderEl;
|
|
||||||
let scrubberEl = timeline.scrubberEl;
|
|
||||||
let playTimelineButtonEl = panel.playTimelineButtonEl;
|
let playTimelineButtonEl = panel.playTimelineButtonEl;
|
||||||
|
|
||||||
ok(!playTimelineButtonEl.classList.contains("paused"),
|
ok(!playTimelineButtonEl.classList.contains("paused"),
|
||||||
"The timeline play button is in its playing state by default");
|
"The timeline play button is in its playing state by default");
|
||||||
|
|
||||||
info("Mousedown in the header to move the scrubber");
|
info("Mousedown in the header to move the scrubber");
|
||||||
yield synthesizeMouseAndWaitForTimelineChange(timeline, 50, 1, "mousedown");
|
yield synthesizeInHeaderAndWaitForChange(timeline, 50, 1, "mousedown");
|
||||||
let newPos = parseInt(scrubberEl.style.left, 10);
|
let newPos = parseInt(scrubberEl.style.left, 10);
|
||||||
is(newPos, 50, "The scrubber moved on mousedown");
|
is(newPos, 50, "The scrubber moved on mousedown");
|
||||||
|
|
||||||
@ -32,7 +30,7 @@ add_task(function*() {
|
|||||||
"The timeline play button is in its paused state after mousedown");
|
"The timeline play button is in its paused state after mousedown");
|
||||||
|
|
||||||
info("Continue moving the mouse and verify that the scrubber tracks it");
|
info("Continue moving the mouse and verify that the scrubber tracks it");
|
||||||
yield synthesizeMouseAndWaitForTimelineChange(timeline, 100, 1, "mousemove");
|
yield synthesizeInHeaderAndWaitForChange(timeline, 100, 1, "mousemove");
|
||||||
newPos = parseInt(scrubberEl.style.left, 10);
|
newPos = parseInt(scrubberEl.style.left, 10);
|
||||||
is(newPos, 100, "The scrubber followed the mouse");
|
is(newPos, 100, "The scrubber followed the mouse");
|
||||||
|
|
||||||
@ -44,9 +42,19 @@ add_task(function*() {
|
|||||||
EventUtils.synthesizeMouse(timeHeaderEl, 200, 1, {type: "mousemove"}, win);
|
EventUtils.synthesizeMouse(timeHeaderEl, 200, 1, {type: "mousemove"}, win);
|
||||||
newPos = parseInt(scrubberEl.style.left, 10);
|
newPos = parseInt(scrubberEl.style.left, 10);
|
||||||
is(newPos, 100, "The scrubber stopped following the mouse");
|
is(newPos, 100, "The scrubber stopped following the mouse");
|
||||||
|
|
||||||
|
info("Try to drag the scrubber handle and check that the scrubber moves");
|
||||||
|
let onDataChanged = timeline.once("timeline-data-changed");
|
||||||
|
EventUtils.synthesizeMouse(scrubberHandleEl, 1, 20, {type: "mousedown"}, win);
|
||||||
|
EventUtils.synthesizeMouse(timeHeaderEl, 0, 0, {type: "mousemove"}, win);
|
||||||
|
EventUtils.synthesizeMouse(timeHeaderEl, 0, 0, {type: "mouseup"}, win);
|
||||||
|
yield onDataChanged;
|
||||||
|
|
||||||
|
newPos = parseInt(scrubberEl.style.left, 10);
|
||||||
|
is(newPos, 0, "The scrubber stopped following the mouse");
|
||||||
});
|
});
|
||||||
|
|
||||||
function* synthesizeMouseAndWaitForTimelineChange(timeline, x, y, type) {
|
function* synthesizeInHeaderAndWaitForChange(timeline, x, y, type) {
|
||||||
let onDataChanged = timeline.once("timeline-data-changed");
|
let onDataChanged = timeline.once("timeline-data-changed");
|
||||||
EventUtils.synthesizeMouse(timeline.timeHeaderEl, x, y, {type}, timeline.win);
|
EventUtils.synthesizeMouse(timeline.timeHeaderEl, x, y, {type}, timeline.win);
|
||||||
yield onDataChanged;
|
yield onDataChanged;
|
||||||
|
@ -201,6 +201,19 @@ body {
|
|||||||
border-right: 5px solid transparent;
|
border-right: 5px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The scrubber handle is a transparent element displayed on top of the scrubber
|
||||||
|
line that allows users to drag it */
|
||||||
|
.animation-timeline .scrubber .scrubber-handle {
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
/* Make it thick enough for easy dragging */
|
||||||
|
width: 6px;
|
||||||
|
right: -3px;
|
||||||
|
cursor: col-resize;
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
|
||||||
.animation-timeline .time-header {
|
.animation-timeline .time-header {
|
||||||
margin-left: var(--timeline-sidebar-width);
|
margin-left: var(--timeline-sidebar-width);
|
||||||
min-height: var(--toolbar-height);
|
min-height: var(--toolbar-height);
|
||||||
|
Loading…
Reference in New Issue
Block a user