зеркало из https://github.com/mozilla/gecko-dev.git
Bug 852088 - Add drag caret to select text support. r-fryn
This commit is contained in:
Родитель
4f28fff593
Коммит
9fcdd4aa4c
|
@ -10,9 +10,9 @@
|
|||
<html:div flex="1" class="selection-overlay-inner window-width window-height" anonid="selection-overlay-inner">
|
||||
<xul:stack>
|
||||
<html:div anonid="selection-overlay-debug" class="window-width window-height"/>
|
||||
<xul:toolbarbutton id="selectionhandle-start" label="^" left="10" top="10" hidden="true"/>
|
||||
<xul:toolbarbutton id="selectionhandle-end" label="^" left="10" top="10" hidden="true"/>
|
||||
<xul:toolbarbutton id="selectionhandle-caret" label="^" left="10" top="10" hidden="true"/>
|
||||
<xul:toolbarbutton id="selectionhandle-mark1" label="^" left="10" top="10" hidden="true"/>
|
||||
<xul:toolbarbutton id="selectionhandle-mark2" label="^" left="10" top="10" hidden="true"/>
|
||||
<xul:toolbarbutton id="selectionhandle-mark3" label="^" left="10" top="10" hidden="true"/>
|
||||
</xul:stack>
|
||||
</html:div>
|
||||
</content>
|
||||
|
|
|
@ -411,8 +411,15 @@ var SelectionHandler = {
|
|||
}
|
||||
|
||||
// Updates this._cache content selection position data which we send over
|
||||
// to SelectionHelperUI.
|
||||
this._updateUIMarkerRects(selection);
|
||||
// to SelectionHelperUI. Note updateUIMarkerRects will fail if there isn't
|
||||
// any selection in the page. This can happen when we start a monocle drag
|
||||
// but haven't dragged enough to create selection. Just return.
|
||||
try {
|
||||
this._updateUIMarkerRects(selection);
|
||||
} catch (ex) {
|
||||
Util.dumpLn(ex.message);
|
||||
return;
|
||||
}
|
||||
|
||||
this._cache.updateStart = aUpdateStart;
|
||||
this._cache.updateEnd = aUpdateEnd;
|
||||
|
|
|
@ -76,6 +76,7 @@ function Marker(aParent, aTag, aElementId, xPos, yPos) {
|
|||
this._yPos = yPos;
|
||||
this._selectionHelperUI = aParent;
|
||||
this._element = document.getElementById(aElementId);
|
||||
this._elementId = aElementId;
|
||||
// These get picked in input.js and receives drag input
|
||||
this._element.customDragger = new MarkerDragger(this);
|
||||
this.tag = aTag;
|
||||
|
@ -83,6 +84,7 @@ function Marker(aParent, aTag, aElementId, xPos, yPos) {
|
|||
|
||||
Marker.prototype = {
|
||||
_element: null,
|
||||
_elementId: "",
|
||||
_selectionHelperUI: null,
|
||||
_xPos: 0,
|
||||
_yPos: 0,
|
||||
|
@ -171,8 +173,12 @@ Marker.prototype = {
|
|||
moveBy: function moveBy(aDx, aDy, aClientX, aClientY) {
|
||||
this._xPos -= aDx;
|
||||
this._yPos -= aDy;
|
||||
this._selectionHelperUI.markerDragMove(this);
|
||||
this._setPosition();
|
||||
let direction = (aDx < 0 || aDy < 0 ? "end" : "start");
|
||||
// We may swap markers in markerDragMove. If markerDragMove
|
||||
// returns true keep processing, otherwise get out of here.
|
||||
if (this._selectionHelperUI.markerDragMove(this, direction)) {
|
||||
this._setPosition();
|
||||
}
|
||||
},
|
||||
|
||||
hitTest: function hitTest(aX, aY) {
|
||||
|
@ -187,6 +193,23 @@ Marker.prototype = {
|
|||
return true;
|
||||
return false;
|
||||
},
|
||||
|
||||
swapMonocle: function swapMonocle(aCaret) {
|
||||
let targetElement = aCaret._element;
|
||||
let targetElementId = aCaret._elementId;
|
||||
|
||||
aCaret._element = this._element;
|
||||
aCaret._element.customDragger._marker = aCaret;
|
||||
aCaret._elementId = this._elementId;
|
||||
|
||||
this._xPos = aCaret._xPos;
|
||||
this._yPos = aCaret._yPos;
|
||||
this._element = targetElement;
|
||||
this._element.customDragger._marker = this;
|
||||
this._elementId = targetElementId;
|
||||
this._element.visible = true;
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -203,24 +226,29 @@ var SelectionHelperUI = {
|
|||
_movement: { active: false, x:0, y: 0 },
|
||||
_activeSelectionRect: null,
|
||||
_selectionHandlerActive: false,
|
||||
_selectionMarkIds: [],
|
||||
|
||||
/*
|
||||
* Properties
|
||||
*/
|
||||
|
||||
get startMark() {
|
||||
if (this._startMark == null) {
|
||||
this._startMark = new Marker(this, "start", "selectionhandle-start", 0, 0);
|
||||
this._startMark = new Marker(this, "start", this._selectionMarkIds.pop(), 0, 0);
|
||||
}
|
||||
return this._startMark;
|
||||
},
|
||||
|
||||
get endMark() {
|
||||
if (this._endMark == null) {
|
||||
this._endMark = new Marker(this, "end", "selectionhandle-end", 0, 0);
|
||||
this._endMark = new Marker(this, "end", this._selectionMarkIds.pop(), 0, 0);
|
||||
}
|
||||
return this._endMark;
|
||||
},
|
||||
|
||||
get caretMark() {
|
||||
if (this._caretMark == null) {
|
||||
this._caretMark = new Marker(this, "caret", "selectionhandle-caret", 0, 0);
|
||||
this._caretMark = new Marker(this, "caret", this._selectionMarkIds.pop(), 0, 0);
|
||||
}
|
||||
return this._caretMark;
|
||||
},
|
||||
|
@ -229,6 +257,20 @@ var SelectionHelperUI = {
|
|||
return document.getElementById("selection-overlay");
|
||||
},
|
||||
|
||||
/*
|
||||
* isActive (prop)
|
||||
*
|
||||
* Determines if an edit session is currently active.
|
||||
*/
|
||||
get isActive() {
|
||||
return (this._msgTarget &&
|
||||
this._selectionHandlerActive);
|
||||
},
|
||||
|
||||
/*
|
||||
* Public apis
|
||||
*/
|
||||
|
||||
/*
|
||||
* openEditSession
|
||||
*
|
||||
|
@ -241,10 +283,6 @@ var SelectionHelperUI = {
|
|||
this._init(aContent);
|
||||
this._setupDebugOptions();
|
||||
|
||||
// Set the track bounds for each marker NIY
|
||||
this.startMark.setTrackBounds(aClientX, aClientY);
|
||||
this.endMark.setTrackBounds(aClientX, aClientY);
|
||||
|
||||
// Send this over to SelectionHandler in content, they'll message us
|
||||
// back with information on the current selection. SelectionStart
|
||||
// takes client coordinates.
|
||||
|
@ -266,10 +304,6 @@ var SelectionHelperUI = {
|
|||
this._init(aContent);
|
||||
this._setupDebugOptions();
|
||||
|
||||
// Set the track bounds for each marker NIY
|
||||
this.startMark.setTrackBounds(aClientX, aClientY);
|
||||
this.endMark.setTrackBounds(aClientX, aClientY);
|
||||
|
||||
// Send this over to SelectionHandler in content, they'll message us
|
||||
// back with information on the current selection. SelectionAttach
|
||||
// takes client coordinates.
|
||||
|
@ -289,7 +323,7 @@ var SelectionHelperUI = {
|
|||
* Note the caret marker is pretty limited in functionality. The
|
||||
* only thing is can do is be displayed at the caret position.
|
||||
* Once the user starts a drag, the caret marker is hidden, and
|
||||
* the start and end markers take over. (TBD)
|
||||
* the start and end markers take over.
|
||||
*
|
||||
* @param aClientX, aClientY client coordiates of the tap that
|
||||
* initiated the session.
|
||||
|
@ -319,16 +353,6 @@ var SelectionHelperUI = {
|
|||
return false;
|
||||
},
|
||||
|
||||
/*
|
||||
* isActive (prop)
|
||||
*
|
||||
* Determines if an edit session is currently active.
|
||||
*/
|
||||
get isActive() {
|
||||
return (this._msgTarget &&
|
||||
this._selectionHandlerActive);
|
||||
},
|
||||
|
||||
/*
|
||||
* closeEditSession
|
||||
*
|
||||
|
@ -359,6 +383,11 @@ var SelectionHelperUI = {
|
|||
// store the target message manager
|
||||
this._msgTarget = aMsgTarget;
|
||||
|
||||
// Init our list of available monocle ids
|
||||
this._selectionMarkIds = ["selectionhandle-mark1",
|
||||
"selectionhandle-mark2",
|
||||
"selectionhandle-mark3"];
|
||||
|
||||
// SelectionHandler messages
|
||||
messageManager.addMessageListener("Content:SelectionRange", this);
|
||||
messageManager.addMessageListener("Content:SelectionCopied", this);
|
||||
|
@ -419,10 +448,11 @@ var SelectionHelperUI = {
|
|||
if (this._caretMark != null)
|
||||
this._caretMark.shutdown();
|
||||
|
||||
delete this._startMark;
|
||||
delete this._endMark;
|
||||
delete this._caretMark;
|
||||
this._startMark = null;
|
||||
this._endMark = null;
|
||||
this._caretMark = null;
|
||||
|
||||
this._selectionMarkIds = [];
|
||||
this._msgTarget = null;
|
||||
this._activeSelectionRect = null;
|
||||
this._selectionHandlerActive = false;
|
||||
|
@ -435,6 +465,54 @@ var SelectionHelperUI = {
|
|||
* Utilities
|
||||
*/
|
||||
|
||||
/*
|
||||
* _swapCaretMarker
|
||||
*
|
||||
* Swap two drag markers - used when transitioning from caret mode
|
||||
* to selection mode. We take the current caret marker (which is in a
|
||||
* drag state) and swap it out with one of the selection markers.
|
||||
*/
|
||||
_swapCaretMarker: function _swapCaretMarker(aDirection) {
|
||||
let targetMark = null;
|
||||
if (aDirection == "start")
|
||||
targetMark = this.startMark;
|
||||
else
|
||||
targetMark = this.endMark;
|
||||
let caret = this.caretMark;
|
||||
targetMark.swapMonocle(caret);
|
||||
let id = caret._elementId;
|
||||
caret.shutdown();
|
||||
this._caretMark = null;
|
||||
this._selectionMarkIds.push(id);
|
||||
},
|
||||
|
||||
/*
|
||||
* _transitionFromCaretToSelection
|
||||
*
|
||||
* Transitions from caret mode to text selection mode.
|
||||
*/
|
||||
_transitionFromCaretToSelection: function _transitionFromCaretToSelection(aDirection) {
|
||||
// Get selection markers initialized if they aren't already
|
||||
{ let mark = this.startMark; mark = this.endMark; }
|
||||
|
||||
// Swap the caret marker out for the start or end marker depending
|
||||
// on direction.
|
||||
this._swapCaretMarker(aDirection);
|
||||
|
||||
let targetMark = null;
|
||||
if (aDirection == "start")
|
||||
targetMark = this.startMark;
|
||||
else
|
||||
targetMark = this.endMark;
|
||||
// Start the selection monocle drag. SelectionHandler relies on this
|
||||
// for getting initialized. This will also trigger a message back for
|
||||
// monocle positioning. Note, markerDragMove is still on the stack in
|
||||
// this call!
|
||||
targetMark._setPosition();
|
||||
this.markerDragStart(targetMark);
|
||||
this.markerDragMove(targetMark, aDirection);
|
||||
},
|
||||
|
||||
/*
|
||||
* _setupDebugOptions
|
||||
*
|
||||
|
@ -731,13 +809,17 @@ var SelectionHelperUI = {
|
|||
this._sendAsyncMessage("Browser:SelectionMoveEnd", json);
|
||||
},
|
||||
|
||||
markerDragMove: function markerDragMove(aMarker) {
|
||||
markerDragMove: function markerDragMove(aMarker, aDirection) {
|
||||
let json = this._getMarkerBaseMessage();
|
||||
json.change = aMarker.tag;
|
||||
if (aMarker.tag == "caret") {
|
||||
this._sendAsyncMessage("Browser:CaretMove", json);
|
||||
return;
|
||||
// We are going to transition from caret browsing mode to selection mode
|
||||
// on a drag. So swap the caret monocle for a start or end monocle
|
||||
// depending on the direction of the drag, and start selecting text.
|
||||
this._transitionFromCaretToSelection(aDirection);
|
||||
return false;
|
||||
}
|
||||
this._sendAsyncMessage("Browser:SelectionMove", json);
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -146,10 +146,12 @@ var TouchModule = {
|
|||
// once we get omtc and the apzc. Currently though dblclick is delivered to
|
||||
// content and triggers selection of text, so fire up the SelectionHelperUI
|
||||
// once selection is present.
|
||||
setTimeout(function () {
|
||||
SelectionHelperUI.attachEditSession(Browser.selectedTab.browser,
|
||||
aEvent.clientX, aEvent.clientY);
|
||||
}, 50);
|
||||
if (!SelectionHelperUI.isActive) {
|
||||
setTimeout(function () {
|
||||
SelectionHelperUI.attachEditSession(Browser.selectedTab.browser,
|
||||
aEvent.clientX, aEvent.clientY);
|
||||
}, 50);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -934,18 +934,18 @@ setting[type="directory"] > .preferences-alignment {
|
|||
|
||||
/* Text selection handles */
|
||||
|
||||
#selectionhandle-start,
|
||||
#selectionhandle-end,
|
||||
#selectionhandle-caret {
|
||||
#selectionhandle-mark1,
|
||||
#selectionhandle-mark2,
|
||||
#selectionhandle-mark3 {
|
||||
border: 0px solid gray;
|
||||
padding: 0px;
|
||||
margin-top: -30px;
|
||||
margin-left: -18px;
|
||||
}
|
||||
|
||||
#selectionhandle-start,
|
||||
#selectionhandle-end,
|
||||
#selectionhandle-caret {
|
||||
#selectionhandle-mark1,
|
||||
#selectionhandle-mark2,
|
||||
#selectionhandle-mark3 {
|
||||
list-style-image: url("chrome://browser/skin/images/selection-monocle.png");
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче