-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: markers with tooltips * refactor: rename TooltipMarkerGroup to MarkerGroup * unify diagnostic and occurrence markers * cleanup --------- Co-authored-by: Zakhar Kozlov <[email protected]> Co-authored-by: nightwing <[email protected]>
- Loading branch information
1 parent
23d4df6
commit 01d4605
Showing
9 changed files
with
346 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
"use strict"; | ||
|
||
/* | ||
Potential improvements: | ||
- use binary search when looking for hover match | ||
*/ | ||
|
||
class MarkerGroup { | ||
constructor(session) { | ||
this.markers = []; | ||
this.session = session; | ||
session.addDynamicMarker(this); | ||
} | ||
|
||
/** | ||
* Finds the first marker containing pos | ||
* @param {Position} pos | ||
* @returns Ace.MarkerGroupItem | ||
*/ | ||
getMarkerAtPosition(pos) { | ||
return this.markers.find(function(marker) { | ||
return marker.range.contains(pos.row, pos.column); | ||
}); | ||
} | ||
|
||
/** | ||
* Comparator for Array.sort function, which sorts marker definitions by their positions | ||
* | ||
* @param {Ace.MarkerGroupItem} a first marker. | ||
* @param {Ace.MarkerGroupItem} b second marker. | ||
* @returns {number} negative number if a should be before b, positive number if b should be before a, 0 otherwise. | ||
*/ | ||
markersComparator(a, b) { | ||
return a.range.start.row - b.range.start.row; | ||
} | ||
|
||
/** | ||
* Sets marker definitions to be rendered. Limits the number of markers at MAX_MARKERS. | ||
* @param {Ace.MarkerGroupItem[]} markers an array of marker definitions. | ||
*/ | ||
setMarkers(markers) { | ||
this.markers = markers.sort(this.markersComparator).slice(0, this.MAX_MARKERS); | ||
this.session._signal("changeBackMarker"); | ||
} | ||
|
||
update(html, markerLayer, session, config) { | ||
if (!this.markers || !this.markers.length) | ||
return; | ||
var visibleRangeStartRow = config.firstRow, visibleRangeEndRow = config.lastRow; | ||
var foldLine; | ||
var markersOnOneLine = 0; | ||
var lastRow = 0; | ||
|
||
for (var i = 0; i < this.markers.length; i++) { | ||
var marker = this.markers[i]; | ||
|
||
if (marker.range.end.row < visibleRangeStartRow) continue; | ||
if (marker.range.start.row > visibleRangeEndRow) continue; | ||
|
||
if (marker.range.start.row === lastRow) { | ||
markersOnOneLine++; | ||
} else { | ||
lastRow = marker.range.start.row; | ||
markersOnOneLine = 0; | ||
} | ||
// do not render too many markers on one line | ||
// because we do not have virtual scroll for horizontal direction | ||
if (markersOnOneLine > 200) { | ||
continue; | ||
} | ||
|
||
var markerVisibleRange = marker.range.clipRows(visibleRangeStartRow, visibleRangeEndRow); | ||
if (markerVisibleRange.start.row === markerVisibleRange.end.row | ||
&& markerVisibleRange.start.column === markerVisibleRange.end.column) { | ||
continue; // visible range is empty | ||
} | ||
|
||
var screenRange = markerVisibleRange.toScreenRange(session); | ||
if (screenRange.isEmpty()) { | ||
// we are inside a fold | ||
foldLine = session.getNextFoldLine(markerVisibleRange.end.row, foldLine); | ||
if (foldLine && foldLine.end.row > markerVisibleRange.end.row) { | ||
visibleRangeStartRow = foldLine.end.row; | ||
} | ||
continue; | ||
} | ||
|
||
if (screenRange.isMultiLine()) { | ||
markerLayer.drawTextMarker(html, screenRange, marker.className, config); | ||
} else { | ||
markerLayer.drawSingleLineMarker(html, screenRange, marker.className, config); | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
// this caps total amount of markers at 10K | ||
MarkerGroup.prototype.MAX_MARKERS = 10000; | ||
|
||
exports.MarkerGroup = MarkerGroup; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
if (typeof process !== "undefined") { | ||
require("./test/mockdom"); | ||
} | ||
|
||
"use strict"; | ||
|
||
var ace = require("./ace"); | ||
var dom = require("./lib/dom"); | ||
var assert = require("./test/assertions"); | ||
var EditSession = require("./edit_session").EditSession; | ||
var Range = require("./range").Range; | ||
var MarkerGroup = require("./marker_group").MarkerGroup; | ||
var editor; | ||
var session1, session2; | ||
|
||
module.exports = { | ||
setUp: function(next) { | ||
var value = "Hello empty world\n" | ||
+ "This is a second line" | ||
+ "\n".repeat(100) | ||
+ "line number 100"; | ||
session1 = new EditSession(value); | ||
session2 = new EditSession("2 " + value); | ||
editor = ace.edit(null, { | ||
session: session1 | ||
}); | ||
document.body.appendChild(editor.container); | ||
editor.container.style.height = "200px"; | ||
editor.container.style.width = "300px"; | ||
dom.importCssString('.ace_tooltip-marker_test { position: absolute; }'); | ||
|
||
next(); | ||
}, | ||
"test: show markers": function() { | ||
editor.resize(true); | ||
editor.renderer.$loop._flush(); | ||
var markerGroup = new MarkerGroup(session1); | ||
|
||
markerGroup.setMarkers([{ | ||
range: new Range(0, 0, 0, 5), | ||
className: "ace_tooltip-marker_test m2" | ||
}, { | ||
range: new Range(0, 12, 1, 4), | ||
className: "ace_tooltip-marker_test m1", | ||
isSecond: true | ||
}]); | ||
assert.ok(markerGroup.getMarkerAtPosition({row: 1, column: 1}).isSecond); | ||
assert.ok(!markerGroup.getMarkerAtPosition({row: 3, column: 1})); | ||
editor.renderer.$loop._flush(); | ||
assert.equal(editor.container.querySelectorAll(".m1").length, 2); | ||
assert.equal(editor.container.querySelectorAll(".m2").length, 1); | ||
editor.setSession(session2); | ||
editor.renderer.$loop._flush(); | ||
assert.equal(editor.container.querySelectorAll(".m1").length, 0); | ||
editor.setSession(session1); | ||
editor.renderer.$loop._flush(); | ||
assert.equal(editor.container.querySelectorAll(".m1").length, 2); | ||
editor.execCommand("gotoend"); | ||
editor.renderer.$loop._flush(); | ||
assert.equal(editor.container.querySelectorAll(".m1").length, 0); | ||
editor.execCommand("gotostart"); | ||
editor.renderer.$loop._flush(); | ||
assert.equal(editor.container.querySelectorAll(".m1").length, 2); | ||
markerGroup.setMarkers([]); | ||
editor.renderer.$loop._flush(); | ||
assert.equal(editor.container.querySelectorAll(".m1").length, 0); | ||
}, | ||
tearDown: function() { | ||
editor.destroy(); | ||
} | ||
}; | ||
|
||
if (typeof module !== "undefined" && module === require.main) { | ||
require("asyncjs").test.testcase(module.exports).exec(); | ||
} |
Oops, something went wrong.