Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: ajaxorg/ace
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: liuzho/ace
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Able to merge. These branches can be automatically merged.
  • 3 commits
  • 14 files changed
  • 1 contributor

Commits on Sep 13, 2024

  1. Copy the full SHA
    a4e1e1e View commit details

Commits on Dec 25, 2024

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    68f5ff5 View commit details

Commits on Dec 26, 2024

  1. Copy the full SHA
    0dbfd03 View commit details
3 changes: 2 additions & 1 deletion demo/kitchen-sink/demo.js
Original file line number Diff line number Diff line change
@@ -614,7 +614,8 @@ require("ace/ext/inline_autocomplete");
env.editor.setOptions({
enableBasicAutocompletion: true,
enableInlineAutocompletion: true,
enableSnippets: true
enableSnippets: true,
enableMobileMenu: false,
});

var beautify = require("ace/ext/beautify");
Binary file added img/text_select_handle_left.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/text_select_handle_middle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/text_select_handle_right.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 27 additions & 2 deletions src/css/editor-css.js
Original file line number Diff line number Diff line change
@@ -643,7 +643,7 @@ module.exports = `
color: #ccc;
box-shadow: 1px 3px 2px grey;
border: 1px solid #444;
display: none;
}
.ace_mobile-button {
padding: 2px;
@@ -698,4 +698,29 @@ module.exports = `
.ace_hidden_token {
display: none;
}`;
}
.ace_select_handle {
z-index: 99;
position: absolute;
cursor: default;
pointer-events: auto;
}
.ace_mid_select_handle {
margin-left: -10px;
width: 20px;
opacity: 0.8;
}
.ace_l_select_handle {
margin-left: -33px;
width: 44px;
opacity: 0.8;
}
.ace_r_select_handle {
margin-left: -11px;
width: 44px;
opacity: 0.8;
}`;
2 changes: 1 addition & 1 deletion src/layer/cursor.js
Original file line number Diff line number Diff line change
@@ -4,7 +4,6 @@
*/
var dom = require("../lib/dom");


class Cursor {
/**
* @param {HTMLElement} parentEl
@@ -23,6 +22,7 @@ class Cursor {
this.cursor = this.addCursor();
dom.addCssClass(this.element, "ace_hidden-cursors");
this.$updateCursors = this.$updateOpacity.bind(this);

}

/**
166 changes: 166 additions & 0 deletions src/layer/select_handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
"use strict";

const { EditSession } = require("../edit_session");
var dom = require("../lib/dom");

class SelectHandleDrawables {
constructor(cursor) {
this.isMidVisible = false;
this.isLRVisible = false;
this.element = cursor.element;
this.cursor = cursor;

this.hideMidTimeout = undefined;

this.addSelectHandle();
};

onSelectionChange(e) {
if (this.config) {
this.update(this.config);
}
}

/**
* @param {EditSession} session
*/
setSession(session) {
if (this.session) {
this.session.selection.off("changeSelection", this.onSelectionChange.bind(this));
}
this.session = session;
this.session.selection.on("changeSelection", this.onSelectionChange.bind(this));
}

setAceEditor(editor) {
this.editor = editor;
}


addSelectHandle() {
this.selectHandleLeft = dom.createElement("img");
this.selectHandleLeft.className = "ace_select_handle ace_l_select_handle";
this.selectHandleLeft.style.display = "none";
this.selectHandleLeft.style.zIndex = "999";
this.selectHandleLeft.src = "img/text_select_handle_left.png";
this.element.appendChild(this.selectHandleLeft);

this.selectHandleMid = dom.createElement("img");
this.selectHandleMid.className = "ace_select_handle ace_mid_select_handle";
this.selectHandleMid.style.display = "none";
this.selectHandleMid.src = "img/text_select_handle_middle.png";
this.element.appendChild(this.selectHandleMid);

this.selectHandleRight = dom.createElement("img");
this.selectHandleRight.className = "ace_select_handle ace_r_select_handle";
this.selectHandleRight.style.display = "none";
this.selectHandleRight.src = "img/text_select_handle_right.png";
this.element.appendChild(this.selectHandleRight);

};

showMidSelectHandle() {
this.cancelMidTimeout();
this.isMidVisible = true;
this.selectHandleMid.style.display = "";
this.hideLeftRightSelectHandle();
this.hideMidSelectHandleTimeout();
};

showLeftRightSelectHandle() {
this.isLRVisible = true;
this.selectHandleLeft.style.display = "";
this.selectHandleRight.style.display = "";
this.hideMidSelectHandle();
};

hideMidSelectHandle() {
this.selectHandleMid.style.display = "none";
this.isMidVisible = false;
};

hideMidSelectHandleTimeout() {
this.cancelMidTimeout();
this.hideMidTimeout = setTimeout(() => {
this.hideMidSelectHandle();
}, 2000);
}

cancelMidTimeout() {
if (this.hideMidTimeout != undefined) {
clearTimeout(this.hideMidTimeout);
this.hideMidTimeout = undefined;
}
}

hideLeftRightSelectHandle() {
this.selectHandleLeft.style.display = "none";
this.selectHandleRight.style.display = "none";
this.isLRVisible = false;
};

ignoreUpdate = false;

update(config) {

if (this.ignoreUpdate) {
return;
}
this.config = config;
// console.trace("update drawable");
if (!this.cursor.isVisible) {
if (this.isMidVisible) this.hideMidSelectHandle();
if (this.isLRVisible) this.hideLeftRightSelectHandle();
return;
}

var selection = this.cursor.session.selection;

var lead = selection.getSelectionLead();
var anchor = selection.getSelectionAnchor();

var start, end;
if (anchor.row < lead.row || (anchor.row == lead.row && anchor.column < lead.column)) {
start = anchor;
end = lead;
} else {
start = lead;
end = anchor;
}
var startPos = this.cursor.session.documentToScreenPosition(start);
var startCursorLeft = this.cursor.$padding + startPos.column * config.characterWidth;
var startCursorTop = (startPos.row - config.firstRowScreen) * config.lineHeight + config.lineHeight;

var style;
var transX = 0;// dom.getElemLeft(this.element);
var transY = 0;// dom.getElemTop(this.element);
if (anchor.row == lead.row &&
anchor.column == lead.column) {
//no selection
style = this.selectHandleMid.style;
style.left = (transX + startCursorLeft) + "px";
style.top = (transY + startCursorTop) + "px";
this.hideLeftRightSelectHandle();
} else {
style = this.selectHandleLeft.style;
style.left = (transX + startCursorLeft) + "px";
style.top = (transY + startCursorTop) + "px";

var endPos = this.cursor.session.documentToScreenPosition(end);
var endCursorLeft = this.cursor.$padding + endPos.column * config.characterWidth;
var endCursorTop = (endPos.row - config.firstRowScreen) * config.lineHeight + config.lineHeight;

style = this.selectHandleRight.style;
style.left = (transX + endCursorLeft) + "px";
style.top = (transY + endCursorTop) + "px";

if (!this.isLRVisible) this.showLeftRightSelectHandle();
}
};

destroy() {

};
}

exports.SelectHandleDrawables = SelectHandleDrawables;
34 changes: 34 additions & 0 deletions src/lib/dom.js
Original file line number Diff line number Diff line change
@@ -3,6 +3,40 @@
var useragent = require("./useragent");
var XHTML_NS = "http://www.w3.org/1999/xhtml";


/**
* @param {HTMLElement} element
* @returns {number}
*/
exports.getElemLeft = function(element) {
var actualLeft = element.offsetLeft;
var current = element.offsetParent;

while (current !== null && current != undefined) {
actualLeft += current.offsetLeft;
current = current.offsetParent;
}

return actualLeft;
}

/**
* @param {HTMLElement} element
* @returns {number}
*/
exports.getElemTop = function(element) {
var actualTop = element.offsetTop;
var current = element.offsetParent;

while (current !== null && current != undefined) {
actualTop += current.offsetTop;
current = current.offsetParent;
}

return actualTop;
}


/**
*
* @param {any} arr
10 changes: 10 additions & 0 deletions src/lib/event.js
Original file line number Diff line number Diff line change
@@ -103,6 +103,16 @@ exports.capture = function(el, eventHandler, releaseCaptureHandler) {
return onMouseUp;
};


exports.getEvent = function(e) {
if (e instanceof TouchEvent) {
var touch = e.touches[0] || e.changedTouches[0];
return touch;
} else {
return e;
}
}

/**
* @param el
* @param callback
8 changes: 8 additions & 0 deletions src/mouse/default_handlers.js
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@
* @typedef {import("./mouse_event").MouseEvent} MouseEvent
*/
var useragent = require("../lib/useragent");
var SelectDrawableEventHandler = require("./select_drawables_handler").SelectDrawableEventHandler;
var SelectHandleDrawables = require("../layer/select_handler").SelectHandleDrawables;

var DRAG_OFFSET = 0; // pixels
var SCROLL_COOLDOWN_T = 550; // milliseconds
@@ -31,6 +33,9 @@ class DefaultHandlers {

mouseHandler["selectByLines"] = this.extendSelectionBy.bind(mouseHandler, "getLineRange");
mouseHandler["selectByWords"] = this.extendSelectionBy.bind(mouseHandler, "getWordRange");

new SelectDrawableEventHandler(this, mouseHandler, editor.renderer.$selectorLayer);

}

/**
@@ -43,6 +48,9 @@ class DefaultHandlers {
this.mousedownEvent = ev;
var editor = this.editor;

var selectors = this.editor.renderer.$selectorLayer;
selectors.showMidSelectHandle();

var button = ev.getButton();
if (button !== 0) {
var selectionRange = editor.getSelectionRange();
265 changes: 265 additions & 0 deletions src/mouse/select_drawables_handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
"use strict";


var dom = require("../lib/dom");
var event = require("../lib/event");
var MouseEvent = require("./mouse_event").MouseEvent;

var auchorRow, auchorColumn;


// function getPointer(editor) {
// var point = document.getElementById("bdfm-touch-pointer");
// if (point == undefined) {
// point = dom.createElement("div");
// point.id = "bdfm-touch-pointer";
// point.style.width = "8px";
// point.style.height = "8px";
// point.style.backgroundColor = "#ff0000";
// point.style.position = "absolute";
// // for debug
// document.body.appendChild(point);
// }
// return point;
// }

class SelectDrawableEventHandler {

constructor(defaultHandler, mouseHandler, selectors) {
this.editor = mouseHandler.editor;

var _self = this;


var midDownX = 0;
var midDownY = 0;

var midDownY2Pointer = 0;
var midDownX2Pointer = 0;


var onMidTouchStart = function (e) {
selectors.cancelMidTimeout();
event.stopEvent(e);

try {
//@ts-ignore
AndroidEditor.hideContextMenu();
} catch (e) { }

e = _self.getEvent(e);
midDownX = e.clientX;
midDownY = e.clientY;

// console.log("liuzh: handler.start.mid: x="+e.clientX+", y="+e.clientY);


var target = _self.editor.renderer.getMouseEventTarget();

var mouseEvent = new MouseEvent(e, _self.editor);
mouseEvent.x = mouseEvent.clientX = dom.getElemLeft(this) + this.clientWidth / 2 - _self.editor.renderer.scrollLeft;
// console.log("me.x=" + mouseEvent.x + ", me.clentX=" + mouseEvent.clientX);
mouseEvent.y = mouseEvent.clientY = e.clientY - _self.editor.renderer.layerConfig.lineHeight / 3 - (e.clientY - dom.getElemTop(this)) - _self.editor.renderer.layerConfig.offset;
// console.log("me.y=" + mouseEvent.y + ", me.clentY=" + mouseEvent.clientY);
// console.log("liuzh: midTop="+dom.getElemTop(this)+", diff="+(e.clientY - dom.getElemTop(this)));

midDownY2Pointer = midDownY - mouseEvent.y;
midDownX2Pointer = midDownX - mouseEvent.x;

// var p = getPointer(_self.editor);
// p.style.left = mouseEvent.x+"px";
// p.style.top = mouseEvent.y+"px";

defaultHandler.onMouseDown.call(mouseHandler, mouseEvent);
}

event.addListener(selectors.selectHandleMid, "touchstart", onMidTouchStart);

event.addListener(selectors.selectHandleMid, "touchmove", function (e) {
selectors.cancelMidTimeout();
event.stopEvent(e);
e = _self.getEvent(e);
var mouseEvent = new MouseEvent(e, _self.editor);

mouseEvent.x = mouseEvent.clientX = e.clientX - midDownX2Pointer;
// console.log("me.x=" + mouseEvent.x + ", me.clentX=" + mouseEvent.clientX);
mouseEvent.y = mouseEvent.clientY = e.clientY - midDownY2Pointer;

defaultHandler.onMouseDown.call(mouseHandler, mouseEvent);
});

var onMidTouchEnd = function (e) {
selectors.hideMidSelectHandleTimeout();
}

event.addListener(selectors.selectHandleMid, "touchend", onMidTouchEnd);
event.addListener(selectors.selectHandleMid, "touchcancel", onMidTouchEnd);


var onTouchStart = this.onTouchStart.bind(this);
var onTouchMove = this.onTouchMove.bind(this);

var onTouchEnd = function (e) {
selectors.ignoreUpdate = false;
var cursor = _self.editor.renderer.$cursorLayer;
var config = _self.editor.renderer.layerConfig;
// reset handlers position
selectors.update(config);
var start = _self.editor.selection.getSelectionLead();
var startPos = cursor.session.documentToScreenPosition(start);
var startCursorLeft = cursor.$padding + startPos.column * config.characterWidth;
var startCursorTop = (startPos.row - config.firstRowScreen) * config.lineHeight;
var transX = dom.getElemLeft(cursor.element) - _self.editor.renderer.scrollLeft;
var transY = dom.getElemTop(cursor.element) - _self.editor.renderer.layerConfig.offset;
var setMode = require("./touch_handler").setMode;
setMode("");

try {
// @ts-ignore p1:x p2:y
AndroidEditor.showContextMenu(transX + startCursorLeft, transY + startCursorTop);
var hideMenu = function () {
try{
// @ts-ignore
AndroidEditor.hideContextMenu();
}catch(e){}
_self.editor.off("input", hideMenu);
}
_self.editor.on("input", hideMenu);
return;
}catch(e){}
}

event.addListener(selectors.selectHandleLeft, "touchstart", onTouchStart);
event.addListener(selectors.selectHandleLeft, "touchmove", onTouchMove);
event.addListener(selectors.selectHandleLeft, "touchend", onTouchEnd);
event.addListener(selectors.selectHandleLeft, "touchcancel", onTouchEnd);

event.addListener(selectors.selectHandleRight, "touchstart", onTouchStart);
event.addListener(selectors.selectHandleRight, "touchmove", onTouchMove);
event.addListener(selectors.selectHandleRight, "touchend", onTouchEnd);
event.addListener(selectors.selectHandleRight, "touchcancel", onTouchEnd);
}

getEvent(e) {
if (e instanceof TouchEvent) {
var touch = e.touches[0] || e.changedTouches[0];
return touch;
} else
return e;
}

leftDownX = 0;
leftDownY = 0;
leftDownXOffset = 0;
leftDownYOffset = 0;

onTouchStart(e) {
// console.log("liuzh: onTouchStart.");

event.stopEvent(e);
e = this.getEvent(e);

try {
//@ts-ignore
AndroidEditor.hideContextMenu();
} catch (e) { }

var selectors = this.editor.renderer.$selectorLayer;
selectors.ignoreUpdate = true;

var cursorLayerLeft = dom.getElemLeft(this.editor.renderer.$cursorLayer.element);

var elem = e.target || e.srcElement;

this.leftDownX = e.clientX;
this.leftDownY = e.clientY;
this.leftDownXOffset = e.clientX - dom.getElemLeft(elem);
this.leftDownYOffset = e.clientY - dom.getElemTop(elem);

// console.log("liuzh: downX=" + this.leftDownX + ", elemLeft=" + dom.getElemLeft(elem) + ", offX=" + this.leftDownXOffset + ", offY=" + this.leftDownYOffset);


var selection = this.editor.selection;

var isRightHandler = dom.hasCssClass(elem, "ace_r_select_handle");

var anchor = selection.getSelectionAnchor();
var lead = selection.getSelectionLead();

var x;
if (isRightHandler) {
x = dom.getElemLeft(elem) - cursorLayerLeft + 11;
} else {
x = dom.getElemLeft(elem) - cursorLayerLeft + elem.clientWidth + -11/*margin in css*/;
}
x -= this.editor.renderer.scrollLeft;
var y = dom.getElemTop(elem) - this.editor.renderer.layerConfig.lineHeight / 2 - this.editor.renderer.layerConfig.offset;

// var pointer = getPointer(this.editor);
// pointer.style.left = (x - pointer.clientWidth / 2) + "px";
// pointer.style.top = (y - pointer.clientHeight / 2) + "px";

var screenX = x + cursorLayerLeft;
var screenY = y;
var pos = this.editor.renderer.screenToTextCoordinates(screenX, screenY);
// console.log("liuzh: downPos=("+pos.row+","+pos.column+")");

if (pos.row == lead.row && lead.column == pos.column) {
auchorRow = anchor.row;
auchorColumn = anchor.column;
} else {
auchorRow = lead.row;
auchorColumn = lead.column;
}
// console.log("onTouchStart: auchorRow=" + auchorRow + ", auchorColumn=" + auchorColumn);
};

onTouchMove(e) {
event.stopEvent(e);
e = this.getEvent(e);

var selectors = this.editor.renderer.$selectorLayer;


var elem = e.target || e.srcElement;
var isRightHandler = dom.hasCssClass(elem, "ace_r_select_handle");
// marginLeft in css
var marginLeft = isRightHandler ? 11 : 33;

var cursorLeft = dom.getElemLeft(this.editor.renderer.$cursorLayer.element);
var left = e.clientX - this.leftDownXOffset - cursorLeft + marginLeft;
var top = e.clientY - this.leftDownYOffset;

var x = left + cursorLeft - this.editor.renderer.scrollLeft;
var y = top - this.editor.renderer.layerConfig.lineHeight / 2 - this.editor.renderer.layerConfig.offset;

// console.log("liuzh: lr.move: cursorLeft="+cursorLeft+", offX="+this.leftDownXOffset+", scrollLeft="+this.editor.renderer.scrollLeft);


var pos = this.editor.renderer.screenToTextCoordinates(x, y);
var selection = this.editor.selection;


elem.style.left = left + "px";
elem.style.top = top + "px";

// var pointer = getPointer(this.editor);
// pointer.style.left = (x - pointer.clientWidth / 2) + "px";
// pointer.style.top = (y - pointer.clientHeight / 2) + "px";


var auchor = selection.getSelectionAnchor();
var lead = selection.getSelectionLead();
// console.log("row=" + auchorRow + " col=" + auchorColumn + " -> row=" + pos.row + " col=" + pos.column);
if (pos.row == auchorRow && pos.column == auchorColumn) {
return;
}

this.editor.selection.setSelectionAnchor(auchorRow, auchorColumn);
this.editor.selection.selectToPosition(pos);
this.editor.renderer.scrollCursorIntoView();
};

}

exports.SelectDrawableEventHandler = SelectDrawableEventHandler;
102 changes: 98 additions & 4 deletions src/mouse/touch_handler.js
Original file line number Diff line number Diff line change
@@ -4,8 +4,13 @@ var MouseEvent = require("./mouse_event").MouseEvent;
var event = require("../lib/event");
var dom = require("../lib/dom");

var mode = "scroll";

exports.setMode = function (m) {
mode = m;
};

exports.addTouchListeners = function(el, editor) {
var mode = "scroll";
var startX;
var startY;
var touchStartT;
@@ -90,7 +95,79 @@ exports.addTouchListeners = function(el, editor) {
["span", { class: "ace_mobile-button", action: "more" }, "..."]
], editor.container);
}
function showContextMenu() {

// function getPointer() {
// var point = document.getElementById("bdfm-menus-position");
// if (point == undefined) {
// point = dom.createElement("div");
// point.id = "bdfm-menus-position";
// point.style.width = "118px";
// point.style.height = "28px";
// point.style.backgroundColor = "#ff0000";
// point.style.position = "absolute";
// point.style.zIndex = "99";
// point.style.opacity = "0.5";
// document.body.appendChild(point);
// }
// return point;
// }
// var pointerTimeout;

function showContextMenu(opts) {
// console.log("liuzh: showContextMenu: selection.isEmpty="+editor.selection.isEmpty());
var lead = editor.selection.getSelectionLead();
var anchor = editor.selection.getSelectionAnchor();
var start, end;
if (anchor.row < lead.row || (anchor.row == lead.row && anchor.column < lead.column)) {
start = anchor;
end = lead;
} else {
start = lead;
end = anchor;
}
var cursor = editor.renderer.$cursorLayer;
var config = editor.renderer.layerConfig;
var startPos = cursor.session.documentToScreenPosition(start);
var startCursorLeft = cursor.$padding + startPos.column * config.characterWidth;
var startCursorTop = (startPos.row - config.firstRowScreen) * config.lineHeight;

var transX = dom.getElemLeft(cursor.element) - editor.renderer.scrollLeft;
var transY = dom.getElemTop(cursor.element) - editor.renderer.layerConfig.offset;

if(editor.selection.isEmpty()) {

// var p = getPointer();
// p.style.left = (transX + startCursorLeft - p.clientWidth/2) + "px";
// p.style.top = (transY + startCursorTop - p.clientHeight) + "px";
// p.style.opacity = "0.5";
// if(pointerTimeout){
// clearTimeout(pointerTimeout);
// pointerTimeout = undefined;
// }

try {
// @ts-ignore p1:x p2:y
AndroidEditor.showContextMenu(transX + startCursorLeft, transY + startCursorTop);
editor.on("input", hideContextMenu);
return;
}catch(e){}

} else if(opts&&opts.longtap && pos) {
var startCursorLeft = cursor.$padding + pos.column * config.characterWidth;
var startCursorTop = (pos.row - config.firstRowScreen) * config.lineHeight;
// var p = getPointer();
// p.style.left = (transX + startCursorLeft - p.clientWidth/2) + "px";
// p.style.top = (transY + startCursorTop - p.clientHeight) + "px";
// p.style.opacity = "0.5";

try {
// @ts-ignore p1:x p2:y
AndroidEditor.showContextMenu(transX + startCursorLeft, transY + startCursorTop);
editor.on("input", hideContextMenu);
return;
}catch(e){}
return;
}
if (!editor.getOption("enableMobileMenu")) {
if (contextMenu) {
hideContextMenu();
@@ -116,6 +193,14 @@ exports.addTouchListeners = function(el, editor) {
editor.on("input", hideContextMenu);
}
function hideContextMenu(e) {
// console.log("liuzh: hideContextMenu");
try{
// @ts-ignore
AndroidEditor.hideContextMenu();
editor.off("input", hideContextMenu);
return;
}catch(e){}

if (contextMenu)
contextMenu.style.display = "none";
editor.off("input", hideContextMenu);
@@ -131,7 +216,7 @@ exports.addTouchListeners = function(el, editor) {
editor.selection.selectWord();
}
mode = "wait";
showContextMenu();
showContextMenu({longtap: true});
}
function switchToSelectionMode() {
longTouchTimer = null;
@@ -229,6 +314,8 @@ exports.addTouchListeners = function(el, editor) {
touchStartT = t;
}, editor);

var lastPos;

event.addListener(el, "touchend", function (e) {
pressed = editor.$mouseHandler.isMousePressed = false;
if (animationTimer) clearInterval(animationTimer);
@@ -238,9 +325,16 @@ exports.addTouchListeners = function(el, editor) {
} else if (longTouchTimer) {
editor.selection.moveToPosition(pos);
animationSteps = 0;
showContextMenu();
if(lastPos != undefined && pos.row == lastPos.row && pos.column == lastPos.column) {
showContextMenu();
} else {
// console.log("liuzh: touched-hideContextMenu-1, el="+el.id);
hideContextMenu();
}
lastPos = pos;
} else if (mode == "scroll") {
animate();
// console.log("liuzh: touched-hideContextMenu-2, el="+el.id);
hideContextMenu();
} else {
showContextMenu();
87 changes: 81 additions & 6 deletions src/scrollbar_custom.js
Original file line number Diff line number Diff line change
@@ -7,17 +7,16 @@ var EventEmitter = require("./lib/event_emitter").EventEmitter;

dom.importCssString(`.ace_editor>.ace_sb-v div, .ace_editor>.ace_sb-h div{
position: absolute;
background: rgba(128, 128, 128, 0.6);
background: rgba(76, 138, 255, 0.6);
-moz-box-sizing: border-box;
box-sizing: border-box;
border: 1px solid #bbb;
border-radius: 2px;
border-radius: 6px;
z-index: 8;
}
.ace_editor>.ace_sb-v, .ace_editor>.ace_sb-h {
position: absolute;
z-index: 6;
background: none;
background: rgba(128, 128, 128, 0.2);
overflow: hidden!important;
}
.ace_editor>.ace_sb-v {
@@ -35,6 +34,7 @@ dom.importCssString(`.ace_editor>.ace_sb-v div, .ace_editor>.ace_sb-h div{
bottom: 0;
left: 0;
height: 12px;
display: none;
}
.ace_editor>.ace_sb-h div {
bottom: 0;
@@ -99,8 +99,83 @@ class VScrollBar extends ScrollBar {
this.parent = parent;
this.width = this.VScrollWidth;
this.renderer = renderer;
this.inner.style.width = this.element.style.width = (this.width || 15) + "px";
this.inner.style.width = this.element.style.width = this.width + "px";
this.$minWidth = 0;

event.addListener(this.element, "touchstart", (e)=>{
// console.log("scrollbar: onTouchDown element");
event.stopEvent(e);
e = event.getEvent(e);
try {
//@ts-ignore
AndroidEditor.hideContextMenu();
} catch (e) { }
var top = e.clientY - this.element.getBoundingClientRect().top - this.thumbHeight / 2;
this._emit("scroll", {data: this.scrollTopFromThumbTop(top)});
return event.preventDefault(e);
});
event.addListener(this.inner, "touchstart", (e)=>{
this.onThumbTouchStart(e);
});
event.addListener(this.inner, "touchmove", (e)=>{
this.onThumbTouchMove(e);
});
event.addListener(this.inner, "touchcancel", (e)=>{
this.onThumbTouchEnd(e);
});
event.addListener(this.inner, "touchend", (e)=>{
this.onThumbTouchEnd(e);
});
}

onThumbTouchEnd(e) {
// console.log("scrollbar: onThumbTouchEnd");
this.isThumbTouching = false;
if (this.thumbTouchTimer != undefined) {
clearInterval(this.thumbTouchTimer);
}
try {
//@ts-ignore
AndroidEditor.scrollbarReleased();
} catch (e) { }
}

onThumbTouchMove(e) {
event.stopEvent(e);
e = event.getEvent(e);
this.thumbTouchPageY = e.clientY;
// console.log("scrollbar: thumb touchmove touchPageY="+this.thumbTouchPageY);
}

thumbTouchPageY = undefined;
thumbTouchTimer = undefined;
isThumbTouching = false;

onThumbTouchStart(e) {
// console.log("scrollbar: onThumbTouchStart");
this.isThumbTouching = true;
event.stopEvent(e);
e = event.getEvent(e);

try {
//@ts-ignore
AndroidEditor.hideContextMenu();
} catch (e) { }
try {
//@ts-ignore
AndroidEditor.scrollbarTouched();
} catch (e) { }
const startY = e.clientY;
const startTop = this.thumbTop;

const onScrollInterval = () => {
if (this.thumbTouchPageY === undefined) return;
const scrollTop = this.scrollTopFromThumbTop(startTop + this.thumbTouchPageY - startY);
if (scrollTop === this.scrollTop) return;
this._emit("scroll", {data: scrollTop});
};

this.thumbTouchTimer = setInterval(onScrollInterval, 20);
}

/**
@@ -194,7 +269,7 @@ class VScrollBar extends ScrollBar {
setScrollHeight(height, force) {
if (this.pageHeight === height && !force) return;
this.pageHeight = height;
this.thumbHeight = this.slideHeight * this.viewHeight / this.pageHeight;
this.thumbHeight = 60;

if (this.thumbHeight > this.slideHeight) this.thumbHeight = this.slideHeight;
if (this.thumbHeight < 15) this.thumbHeight = 15;
11 changes: 9 additions & 2 deletions src/virtual_renderer.js
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ var GutterLayer = require("./layer/gutter").Gutter;
var MarkerLayer = require("./layer/marker").Marker;
var TextLayer = require("./layer/text").Text;
var CursorLayer = require("./layer/cursor").Cursor;
var SelectorLayer = require("./layer/select_handler").SelectHandleDrawables;
var HScrollBar = require("./scrollbar").HScrollBar;
var VScrollBar = require("./scrollbar").VScrollBar;
var HScrollBarCustom = require("./scrollbar_custom").HScrollBar;
@@ -74,6 +75,8 @@ class VirtualRenderer {

this.$cursorLayer = new CursorLayer(this.content);

this.$selectorLayer = new SelectorLayer(this.$cursorLayer);

// Indicates whether the horizontal scrollbar is visible
this.$horizScroll = false;
this.$vScroll = false;
@@ -210,6 +213,7 @@ class VirtualRenderer {
session.setScrollTop(-this.scrollMargin.top);

this.$cursorLayer.setSession(session);
this.$selectorLayer.setSession(session);
this.$markerBack.setSession(session);
this.$markerFront.setSession(session);
this.$gutterLayer.setSession(session);
@@ -415,10 +419,10 @@ class VirtualRenderer {
size.scrollerWidth = Math.max(0, width - gutterWidth - this.scrollBarV.getWidth() - this.margin.h);
dom.setStyle(this.$gutter.style, "left", this.margin.left + "px");

var right = this.scrollBarV.getWidth() + "px";
var right = "0px";
dom.setStyle(this.scrollBarH.element.style, "right", right);
dom.setStyle(this.scroller.style, "right", right);
dom.setStyle(this.scroller.style, "bottom", this.scrollBarH.getHeight());
dom.setStyle(this.scroller.style, "bottom", "0px");

this.scrollBarH.setWidth(size.scrollerWidth);

@@ -973,6 +977,7 @@ class VirtualRenderer {
this.$markerBack.update(config);
this.$markerFront.update(config);
this.$cursorLayer.update(config);
this.$selectorLayer.update(config);
this.$moveTextAreaToCursor();
this._signal("afterRender", changes);
return;
@@ -998,6 +1003,7 @@ class VirtualRenderer {
this.$markerBack.update(config);
this.$markerFront.update(config);
this.$cursorLayer.update(config);
this.$selectorLayer.update(config);
this.$moveTextAreaToCursor();
this._signal("afterRender", changes);
return;
@@ -1037,6 +1043,7 @@ class VirtualRenderer {

if (changes & this.CHANGE_CURSOR) {
this.$cursorLayer.update(config);
this.$selectorLayer.update(config);
this.$moveTextAreaToCursor();
}