forked from phcode-dev/staging.phcode.dev
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathScrollTrackMarkers.js
More file actions
1 lines (1 loc) · 7.64 KB
/
Copy pathScrollTrackMarkers.js
File metadata and controls
1 lines (1 loc) · 7.64 KB
1
define(function(require,exports,module){const _=require("thirdparty/lodash"),EditorManager=require("editor/EditorManager"),WorkspaceManager=require("view/WorkspaceManager"),TRACK_STYLES={LINE:"line",ON_LEFT:"left"};let scrollbarTrackOffset;switch(brackets.platform){case"win":scrollbarTrackOffset=0;break;case"mac":scrollbarTrackOffset=4;break;case"linux":scrollbarTrackOffset=2}const MARKER_HEIGHT_LINE=2,MARKER_HEIGHT_LEFT=5;function _getMarkerState(editor){return editor._scrollTrackMarker||(editor._scrollTrackMarker={trackOffset:0,trackHt:0,marks:[],$currentTick:null,visible:!1,resizeHandler:null}),editor._scrollTrackMarker}function _getScrollbar(editor){return $(editor.getRootElement()).children(".CodeMirror-vscrollbar")}function _calcScaling(editor){const markerState=_getMarkerState(editor),$sb=_getScrollbar(editor),trackHeight=$sb[0].offsetHeight;if(trackHeight>0)markerState.trackOffset=scrollbarTrackOffset,markerState.trackHt=trackHeight-2*markerState.trackOffset;else{const codeContainer=$(editor.getRootElement()).find("> .CodeMirror-scroll > .CodeMirror-sizer > div > .CodeMirror-lines > div")[0];markerState.trackHt=codeContainer.offsetHeight,markerState.trackOffset=codeContainer.offsetTop}}function _getTop(editor,pos){const cm=editor._codeMirror,markerState=_getMarkerState(editor),editorHt=cm.getScrollerElement().scrollHeight,wrapping=cm.getOption("lineWrapping");let cursorTop;const singleLineH=wrapping&&1.5*cm.defaultTextHeight(),lineObj=cm.getLineHandle(pos.line);cursorTop=wrapping&&lineObj&&lineObj.height>singleLineH?cm.charCoords(pos,"local").top:cm.heightAtLine(pos.line,"local");const ratio=editorHt?cursorTop/editorHt:0;return Math.round(ratio*markerState.trackHt)+markerState.trackOffset-1}function _renderMarks(editor,posArray){const cm=editor._codeMirror,markerState=_getMarkerState(editor),$track=$(".tickmark-track",editor.getRootElement()),editorHt=cm.getScrollerElement().scrollHeight,wrapping=cm.getOption("lineWrapping"),markPositions=[];posArray.forEach(function(pos){const trackStyle=pos.options.trackStyle||TRACK_STYLES.LINE,cssColorClass=pos.options.cssColorClass||"",isLineMarker=trackStyle===TRACK_STYLES.LINE,markerHeight=isLineMarker?MARKER_HEIGHT_LINE:MARKER_HEIGHT_LEFT,startPos=pos.start||pos,endPos=pos.end||pos,startY=_computeY(startPos),endY=_computeY(endPos),topY=Math.min(startY,endY),bottomY=Math.max(startY,endY)+markerHeight;markPositions.push({top:topY,bottom:bottomY,isLine:isLineMarker,cssColorClass:cssColorClass})}),markPositions.sort(function(a,b){return a.top-b.top});const mergedLineMarks=[],mergedLeftMarks=[];markPositions.forEach(function(mark){const mergedMarks=mark.isLine?mergedLineMarks:mergedLeftMarks;if(mergedMarks.length>0){const last=mergedMarks[mergedMarks.length-1];if(mark.top<=last.bottom+1)return last.bottom=Math.max(last.bottom,mark.bottom),void(last.height=last.bottom-last.top)}mark.height=mark.bottom-mark.top,mergedMarks.push(mark)});let html=mergedLineMarks.map(function(m){return`<div class='tickmark ${m.cssColorClass}'\n style='top: ${m.top}px; height: ${m.height}px;'></div>`}).join("");function _computeY(cmPos){if(wrapping)return cm.charCoords(cmPos,"local").top/editorHt*markerState.trackHt+markerState.trackOffset-1;const cursorTop=cm.heightAtLine(cmPos.line,"local"),ratio=editorHt?cursorTop/editorHt:0;return Math.round(ratio*markerState.trackHt)+markerState.trackOffset-1}$track.append($(html)),html=mergedLeftMarks.map(function(m){return`<div class='tickmark tickmark-side ${m.cssColorClass}'\n style='top: ${m.top}px; height: ${m.height}px;'></div>`}).join(""),$track.append($(html))}function _showTrack(editor){const markerState=_getMarkerState(editor);if(markerState.visible)return;markerState.visible=!0;const $scrollbar=_getScrollbar(editor),$overlay=$("<div class='tickmark-track'></div>");$scrollbar.parent().append($overlay),_calcScaling(editor),markerState.resizeHandler=_.debounce(function(){markerState.marks.length&&(_calcScaling(editor),$(".tickmark-track",editor.getRootElement()).empty(),_renderMarks(editor,markerState.marks))},300),WorkspaceManager.on("workspaceUpdateLayout.ScrollTrackMarkers",markerState.resizeHandler)}function _hideTrack(editor){const markerState=_getMarkerState(editor);markerState.visible&&(markerState.visible=!1,$(".tickmark-track",editor.getRootElement()).remove(),markerState.resizeHandler&&(WorkspaceManager.off("workspaceUpdateLayout.ScrollTrackMarkers",markerState.resizeHandler),markerState.resizeHandler=null),markerState.marks=[],markerState.$currentTick&&(markerState.$currentTick.remove(),markerState.$currentTick=null))}function clear(editor,markName){editor||(console.error("Calling ScrollTrackMarkers.clear without an editor instance is deprecated."),editor=EditorManager.getActiveEditor());const markerState=editor&&editor._scrollTrackMarker;markerState&&(markerState.marks=markName?markerState.marks.filter(mark=>mark.options&&mark.options.name!==markName):markerState.marks.filter(mark=>mark.options&&mark.options.name),0===markerState.marks.length?_hideTrack(editor):($(".tickmark-track",editor.getRootElement()).empty(),_renderMarks(editor,markerState.marks)),markerState.$currentTick&&!markName&&(markerState.$currentTick.remove(),markerState.$currentTick=null))}function clearAll(editor){if(!editor)throw new Error("Called ScrollTrackMarkers.clearAll without an editor!");const markerState=editor&&editor._scrollTrackMarker;markerState&&(markerState.marks=[],_hideTrack(editor))}function setVisible(){console.warn("DEPRECATED: ScrollTrackMarkers.setVisible() is no longer needed. Track visibility is now managed automatically.")}function _mergeMarks(markArray){markArray.sort((a,b)=>a.start.line!==b.start.line?a.start.line-b.start.line:a.start.ch-b.start.ch);const merged=[];let current=null;for(const mark of markArray)current?mark.start.line<=current.end.line+1?mark.end.line>current.end.line?(current.end.line=mark.end.line,current.end.ch=mark.end.ch):mark.end.line===current.end.line&&mark.end.ch>current.end.ch&&(current.end.ch=mark.end.ch):(merged.push(current),current={start:{...mark.start},end:{...mark.end},options:mark.options}):current={start:{...mark.start},end:{...mark.end},options:mark.options};return current&&merged.push(current),merged}function addTickmarks(editor,posArray,options={}){const markerState=_getMarkerState(editor);if(!markerState)return;const wasEmpty=0===markerState.marks.length,newMarks=posArray.map(pos=>pos.start&&pos.end?{start:pos.start,end:pos.end,options:options}:{start:pos,end:pos,options:options}),mergedMarks=options.dontMerge?newMarks:_mergeMarks(newMarks);markerState.marks=markerState.marks.concat(mergedMarks),wasEmpty&&markerState.marks.length>0&&_showTrack(editor),markerState.visible&&($(".tickmark-track",editor.getRootElement()).empty(),_renderMarks(editor,markerState.marks))}function _markCurrent(index,editor){if(!editor)throw new Error("Calling private API ScrollTrackMarkers._markCurrent without editor instance is deprecated.");const markerState=_getMarkerState(editor);if(markerState.$currentTick&&(markerState.$currentTick.remove(),markerState.$currentTick=null),-1===index||!markerState.marks[index])return;const top=_getTop(editor,markerState.marks[index].start),$currentTick=$(`<div class='tickmark tickmark-current' style='top: ${top}px; height: ${MARKER_HEIGHT_LINE}px;'></div>`);$(".tickmark-track",editor.getRootElement()).append($currentTick),markerState.$currentTick=$currentTick}function _getTickmarks(editorInstance){const markerState=editorInstance&&editorInstance._scrollTrackMarker;return markerState?markerState.marks:[]}exports._getTickmarks=_getTickmarks,exports._markCurrent=_markCurrent,exports.setVisible=setVisible,exports.addTickmarks=addTickmarks,exports.clear=clear,exports.clearAll=clearAll,exports.TRACK_STYLES=TRACK_STYLES});