Merge pull request #270 from jviereck/folding
Add support for unfolding folds using the mouse. Add hints on the gutter for wrapped lines.
This commit is contained in:
commit
a41092adff
4 changed files with 95 additions and 39 deletions
52
demo/demo.js
52
demo/demo.js
|
|
@ -496,14 +496,34 @@ exports.launch = function(env) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function isCommentRow(row) {
|
||||||
|
var session = env.editor.session;
|
||||||
|
var token;
|
||||||
|
var tokens = session.getTokens(row, row)[0].tokens;
|
||||||
|
var c = 0;
|
||||||
|
for (var i = 0; i < tokens.length; i++) {
|
||||||
|
token = tokens[i];
|
||||||
|
if (/^comment/.test(token.type)) {
|
||||||
|
return c;
|
||||||
|
} else if (!/^text/.test(token.type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
c += token.value.length;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
function toggleFold(env, tryToUnfold) {
|
function toggleFold(env, tryToUnfold) {
|
||||||
var session = env.editor.session,
|
var session = env.editor.session;
|
||||||
selection = env.editor.selection,
|
var selection = env.editor.selection;
|
||||||
range = selection.getRange(), addFold;
|
var range = selection.getRange();
|
||||||
|
var addFold;
|
||||||
|
|
||||||
if(range.isEmpty()) {
|
if(range.isEmpty()) {
|
||||||
var br = session.findMatchingBracket(range.start);
|
var br = session.findMatchingBracket(range.start);
|
||||||
var fold = session.getFoldAt(range.start.row, range.start.column)
|
var fold = session.getFoldAt(range.start.row, range.start.column);
|
||||||
|
var column;
|
||||||
|
|
||||||
if(fold) {
|
if(fold) {
|
||||||
session.expandFold(fold);
|
session.expandFold(fold);
|
||||||
selection.setSelectionRange(fold.range)
|
selection.setSelectionRange(fold.range)
|
||||||
|
|
@ -513,15 +533,25 @@ exports.launch = function(env) {
|
||||||
else
|
else
|
||||||
range.start = br;
|
range.start = br;
|
||||||
addFold = true;
|
addFold = true;
|
||||||
|
} else if ((column = isCommentRow(range.start.row)) !== false) {
|
||||||
|
var firstCommentRow = range.start.row;
|
||||||
|
var lastCommentRow = range.start.row;
|
||||||
|
var t;
|
||||||
|
while ((t = isCommentRow(firstCommentRow - 1)) !== false) {
|
||||||
|
firstCommentRow --;
|
||||||
|
column = t;
|
||||||
|
}
|
||||||
|
while (isCommentRow(lastCommentRow + 1) !== false) {
|
||||||
|
lastCommentRow ++;
|
||||||
|
}
|
||||||
|
range.start.row = firstCommentRow;
|
||||||
|
range.start.column = column + 2;
|
||||||
|
range.end.row = lastCommentRow;
|
||||||
|
range.end.column = session.getLine(lastCommentRow).length - 1;
|
||||||
|
addFold = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var folds = session.getFoldsInRange(range);
|
addFold = true;
|
||||||
if(tryToUnfold && folds.length)
|
|
||||||
session.expandFolds(folds);
|
|
||||||
else if(folds.length == 1 && folds[0].range.compare(range) == 0)
|
|
||||||
session.expandFolds(folds);
|
|
||||||
else
|
|
||||||
addFold = true;
|
|
||||||
}
|
}
|
||||||
if(addFold) {
|
if(addFold) {
|
||||||
var placeHolder = session.getTextRange(range);
|
var placeHolder = session.getTextRange(range);
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,13 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
font-family: "Menlo", "Monaco", "Courier New", monospace;
|
font-family: "Menlo", "Monaco", "Courier New", monospace;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_scroller {
|
.ace_scroller {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
overflow-x: scroll;
|
overflow-x: scroll;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ace_content {
|
.ace_content {
|
||||||
|
|
@ -90,7 +90,7 @@
|
||||||
.ace_layer {
|
.ace_layer {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
@ -154,6 +154,10 @@
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ace_line .ace_fold {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
.ace_dragging .ace_marker-layer, .ace_dragging .ace_text-layer {
|
.ace_dragging .ace_marker-layer, .ace_dragging .ace_text-layer {
|
||||||
cursor: move;
|
cursor: move;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,7 @@ var Gutter = function(parentEl) {
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if(i > foldStart) {
|
if(i > foldStart) {
|
||||||
i = fold.end.row+1;
|
i = fold.end.row + 1;
|
||||||
fold = this.session.getNextFold(i);
|
fold = this.session.getNextFold(i);
|
||||||
foldStart = fold ?fold.start.row :Infinity;
|
foldStart = fold ?fold.start.row :Infinity;
|
||||||
}
|
}
|
||||||
|
|
@ -121,7 +121,14 @@ var Gutter = function(parentEl) {
|
||||||
this.$breakpoints[i] ? " ace_breakpoint " : " ",
|
this.$breakpoints[i] ? " ace_breakpoint " : " ",
|
||||||
annotation.className,
|
annotation.className,
|
||||||
"' title='", annotation.text.join("\n"),
|
"' title='", annotation.text.join("\n"),
|
||||||
"' style='height:", this.session.getRowHeight(config, i), "px;'>", (i+1), "</div>");
|
"' style='height:", config.lineHeight, "px;'>", (i+1));
|
||||||
|
|
||||||
|
var wrappedRowLength = this.session.getRowLength(i) - 1;
|
||||||
|
while (wrappedRowLength--) {
|
||||||
|
html.push("</div><div class='ace_gutter-cell' style='height:", config.lineHeight, "px'>¦</div>");
|
||||||
|
}
|
||||||
|
|
||||||
|
html.push("</div>");
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ var MouseHandler = function(editor) {
|
||||||
event.addListener(editor.container, "selectstart", function(e) {
|
event.addListener(editor.container, "selectstart", function(e) {
|
||||||
return event.preventDefault(e);
|
return event.preventDefault(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
var mouseTarget = editor.renderer.getMouseEventTarget();
|
var mouseTarget = editor.renderer.getMouseEventTarget();
|
||||||
event.addListener(mouseTarget, "mousedown", this.onMouseDown.bind(this));
|
event.addListener(mouseTarget, "mousedown", this.onMouseDown.bind(this));
|
||||||
event.addMultiMouseDownListener(mouseTarget, 0, 2, 500, this.onMouseDoubleClick.bind(this));
|
event.addMultiMouseDownListener(mouseTarget, 0, 2, 500, this.onMouseDoubleClick.bind(this));
|
||||||
|
|
@ -73,7 +73,7 @@ var MouseHandler = function(editor) {
|
||||||
this.setScrollSpeed = function(speed) {
|
this.setScrollSpeed = function(speed) {
|
||||||
this.$scrollSpeed = speed;
|
this.$scrollSpeed = speed;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getScrollSpeed = function() {
|
this.getScrollSpeed = function() {
|
||||||
return this.$scrollSpeed;
|
return this.$scrollSpeed;
|
||||||
};
|
};
|
||||||
|
|
@ -100,7 +100,7 @@ var MouseHandler = function(editor) {
|
||||||
var selectionEmpty = selectionRange.isEmpty();
|
var selectionEmpty = selectionRange.isEmpty();
|
||||||
var state = STATE_UNKNOWN;
|
var state = STATE_UNKNOWN;
|
||||||
var inSelection = false;
|
var inSelection = false;
|
||||||
|
|
||||||
var button = event.getButton(e);
|
var button = event.getButton(e);
|
||||||
if (button !== 0) {
|
if (button !== 0) {
|
||||||
if (selectionEmpty) {
|
if (selectionEmpty) {
|
||||||
|
|
@ -112,6 +112,13 @@ var MouseHandler = function(editor) {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
// Select the fold as the user clicks it.
|
||||||
|
var fold = editor.session.getFoldAt(pos.row, pos.column, 1);
|
||||||
|
if (fold) {
|
||||||
|
editor.selection.setSelectionRange(fold.range);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
inSelection = !editor.getReadOnly()
|
inSelection = !editor.getReadOnly()
|
||||||
&& !selectionEmpty
|
&& !selectionEmpty
|
||||||
&& selectionRange.contains(pos.row, pos.column);
|
&& selectionRange.contains(pos.row, pos.column);
|
||||||
|
|
@ -127,19 +134,19 @@ var MouseHandler = function(editor) {
|
||||||
var overwrite = editor.getOverwrite();
|
var overwrite = editor.getOverwrite();
|
||||||
var mousedownTime = (new Date()).getTime();
|
var mousedownTime = (new Date()).getTime();
|
||||||
var dragCursor, dragRange;
|
var dragCursor, dragRange;
|
||||||
|
|
||||||
var onMouseSelection = function(e) {
|
var onMouseSelection = function(e) {
|
||||||
mousePageX = event.getDocumentX(e);
|
mousePageX = event.getDocumentX(e);
|
||||||
mousePageY = event.getDocumentY(e);
|
mousePageY = event.getDocumentY(e);
|
||||||
};
|
};
|
||||||
|
|
||||||
var onMouseSelectionEnd = function() {
|
var onMouseSelectionEnd = function() {
|
||||||
clearInterval(timerId);
|
clearInterval(timerId);
|
||||||
if (state == STATE_UNKNOWN)
|
if (state == STATE_UNKNOWN)
|
||||||
onStartSelect(pos);
|
onStartSelect(pos);
|
||||||
else if (state == STATE_DRAG)
|
else if (state == STATE_DRAG)
|
||||||
onMouseDragSelectionEnd();
|
onMouseDragSelectionEnd();
|
||||||
|
|
||||||
self.$clickSelection = null;
|
self.$clickSelection = null;
|
||||||
state = STATE_UNKNOWN;
|
state = STATE_UNKNOWN;
|
||||||
};
|
};
|
||||||
|
|
@ -172,7 +179,7 @@ var MouseHandler = function(editor) {
|
||||||
|
|
||||||
editor.selection.setSelectionRange(newRange);
|
editor.selection.setSelectionRange(newRange);
|
||||||
};
|
};
|
||||||
|
|
||||||
var onSelectionInterval = function() {
|
var onSelectionInterval = function() {
|
||||||
if (mousePageX === undefined || mousePageY === undefined)
|
if (mousePageX === undefined || mousePageY === undefined)
|
||||||
return;
|
return;
|
||||||
|
|
@ -181,7 +188,7 @@ var MouseHandler = function(editor) {
|
||||||
var distance = self.$distance(pageX, pageY, mousePageX, mousePageY);
|
var distance = self.$distance(pageX, pageY, mousePageX, mousePageY);
|
||||||
var time = (new Date()).getTime();
|
var time = (new Date()).getTime();
|
||||||
|
|
||||||
|
|
||||||
if (distance > DRAG_OFFSET) {
|
if (distance > DRAG_OFFSET) {
|
||||||
state = STATE_SELECT;
|
state = STATE_SELECT;
|
||||||
var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
|
var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
|
||||||
|
|
@ -197,13 +204,13 @@ var MouseHandler = function(editor) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == STATE_DRAG)
|
if (state == STATE_DRAG)
|
||||||
onDragSelectionInterval();
|
onDragSelectionInterval();
|
||||||
else if (state == STATE_SELECT)
|
else if (state == STATE_SELECT)
|
||||||
onUpdateSelectionInterval();
|
onUpdateSelectionInterval();
|
||||||
};
|
};
|
||||||
|
|
||||||
function onStartSelect(pos) {
|
function onStartSelect(pos) {
|
||||||
if (e.shiftKey)
|
if (e.shiftKey)
|
||||||
editor.selection.selectToPosition(pos)
|
editor.selection.selectToPosition(pos)
|
||||||
|
|
@ -215,12 +222,12 @@ var MouseHandler = function(editor) {
|
||||||
}
|
}
|
||||||
state = STATE_SELECT;
|
state = STATE_SELECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
var onUpdateSelectionInterval = function() {
|
var onUpdateSelectionInterval = function() {
|
||||||
var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
|
var cursor = editor.renderer.screenToTextCoordinates(mousePageX, mousePageY);
|
||||||
cursor.row = Math.max(0, Math.min(cursor.row, editor.session.getLength()-1));
|
cursor.row = Math.max(0, Math.min(cursor.row, editor.session.getLength()-1));
|
||||||
|
|
||||||
if (self.$clickSelection) {
|
if (self.$clickSelection) {
|
||||||
if (self.$clickSelection.contains(cursor.row, cursor.column)) {
|
if (self.$clickSelection.contains(cursor.row, cursor.column)) {
|
||||||
editor.selection.setSelectionRange(self.$clickSelection);
|
editor.selection.setSelectionRange(self.$clickSelection);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -236,7 +243,7 @@ var MouseHandler = function(editor) {
|
||||||
else {
|
else {
|
||||||
editor.selection.selectToPosition(cursor);
|
editor.selection.selectToPosition(cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.renderer.scrollCursorIntoView();
|
editor.renderer.scrollCursorIntoView();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -250,32 +257,40 @@ var MouseHandler = function(editor) {
|
||||||
|
|
||||||
event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);
|
event.capture(editor.container, onMouseSelection, onMouseSelectionEnd);
|
||||||
var timerId = setInterval(onSelectionInterval, 20);
|
var timerId = setInterval(onSelectionInterval, 20);
|
||||||
|
|
||||||
return event.preventDefault(e);
|
return event.preventDefault(e);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onMouseDoubleClick = function(e) {
|
this.onMouseDoubleClick = function(e) {
|
||||||
|
var editor = this.editor;
|
||||||
var pos = this.$getEventPosition(e);
|
var pos = this.$getEventPosition(e);
|
||||||
this.editor.moveCursorToPosition(pos);
|
|
||||||
this.editor.selection.selectWord();
|
// If the user dclicked on a fold, then expand it.
|
||||||
this.$clickSelection = this.editor.getSelectionRange();
|
var fold = editor.session.getFoldAt(pos.row, pos.column, 1);
|
||||||
|
if (fold) {
|
||||||
|
editor.session.expandFold(fold);
|
||||||
|
} else {
|
||||||
|
editor.moveCursorToPosition(pos);
|
||||||
|
editor.selection.selectWord();
|
||||||
|
this.$clickSelection = editor.getSelectionRange();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onMouseTripleClick = function(e) {
|
this.onMouseTripleClick = function(e) {
|
||||||
var pos = this.$getEventPosition(e);
|
var pos = this.$getEventPosition(e);
|
||||||
this.editor.moveCursorToPosition(pos);
|
this.editor.moveCursorToPosition(pos);
|
||||||
this.editor.selection.selectLine();
|
this.editor.selection.selectLine();
|
||||||
this.$clickSelection = this.editor.getSelectionRange();
|
this.$clickSelection = this.editor.getSelectionRange();
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onMouseQuadClick = function(e) {
|
this.onMouseQuadClick = function(e) {
|
||||||
this.editor.selectAll();
|
this.editor.selectAll();
|
||||||
this.$clickSelection = this.editor.getSelectionRange();
|
this.$clickSelection = this.editor.getSelectionRange();
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onMouseWheel = function(e) {
|
this.onMouseWheel = function(e) {
|
||||||
var speed = this.$scrollSpeed * 2;
|
var speed = this.$scrollSpeed * 2;
|
||||||
|
|
||||||
this.editor.renderer.scrollBy(e.wheelX * speed, e.wheelY * speed);
|
this.editor.renderer.scrollBy(e.wheelX * speed, e.wheelY * speed);
|
||||||
return event.preventDefault(e);
|
return event.preventDefault(e);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue