forked from phcode-dev/staging.phcode.dev
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathQuickViewManager.js
More file actions
1 lines (1 loc) · 11.5 KB
/
QuickViewManager.js
File metadata and controls
1 lines (1 loc) · 11.5 KB
1
define(function(require,exports,module){const CommandManager=require("command/CommandManager"),Commands=require("command/Commands"),EditorManager=require("editor/EditorManager"),Menus=require("command/Menus"),PreferencesManager=require("preferences/PreferencesManager"),Strings=require("strings"),ViewUtils=require("utils/ViewUtils"),AppInit=require("utils/AppInit"),WorkspaceManager=require("view/WorkspaceManager"),EventDispatcher=require("utils/EventDispatcher"),ProviderRegistrationHandler=require("features/PriorityBasedRegistration").RegistrationHandler;EventDispatcher.makeEventDispatcher(exports);const _EVENT_POPUP_CONTENT_MUTATED="_popupContentMutated",observer=new MutationObserver(mutations=>{for(let mutation of mutations)if("childList"===mutation.type||"subtree"===mutation.type){exports.trigger(_EVENT_POPUP_CONTENT_MUTATED,mutations);break}}),previewContainerHTML='<div id="quick-view-container">\n <div class="preview-content">\n </div>\n</div>',_providerRegistrationHandler=new ProviderRegistrationHandler,registerQuickViewProvider=_providerRegistrationHandler.registerProvider.bind(_providerRegistrationHandler),removeQuickViewProvider=_providerRegistrationHandler.removeProvider.bind(_providerRegistrationHandler);function _getQuickViewProviders(editor,pos){let language=editor.getLanguageForPosition(pos);return _providerRegistrationHandler.getProvidersForLanguageId(language.getId())}let enabled,prefs=null,$previewContainer,$previewContent,_currentMousePos,animationRequest,quickViewLocked=!1;const CMD_ENABLE_QUICK_VIEW="view.enableQuickView",QUICK_VIEW_EDITOR_MARKER="quickViewMark",HOVER_DELAY=350,POINTER_HEIGHT=10,POPOVER_HORZ_MARGIN=5;(prefs=PreferencesManager.getExtensionPrefs("quickview")).definePreference("enabled","boolean",!0,{description:Strings.DESCRIPTION_QUICK_VIEW_ENABLED});let popoverState=null;function hidePreview(){popoverState&&(popoverState.visible&&(popoverState.marker.clear(),$previewContent.empty(),$previewContainer.hide(),$previewContainer.removeClass("active"),EditorManager.getActiveEditor()&&EditorManager.getActiveEditor().focus()),mouseInPreviewContainer=!1,unlockQuickView(),window.clearTimeout(popoverState.hoverTimer),popoverState=null)}function positionPreview(editor,xpos,ypos,ybot){if($previewContent.find("#quick-view-popover-root").is(":empty"))return void hidePreview();let previewWidth=$previewContainer.outerWidth(),top=ypos-$previewContainer.outerHeight()-POINTER_HEIGHT,left=xpos-previewWidth/2,elementRect={top:top,left:left-POPOVER_HORZ_MARGIN,height:$previewContainer.outerHeight()+POINTER_HEIGHT,width:previewWidth+2*POPOVER_HORZ_MARGIN},clip=ViewUtils.getElementClipSize($(editor.getRootElement()),elementRect);clip.left>0?left+=clip.left:clip.right>0&&(left-=clip.right),clip.top>0?(top=ybot+POINTER_HEIGHT,$previewContainer.removeClass("preview-bubble-above").addClass("preview-bubble-below")):$previewContainer.removeClass("preview-bubble-below").addClass("preview-bubble-above"),$previewContainer.css({left:left,top:top}).addClass("active")}function _isResultBeforePopoverStart(editor,popover,result){return!popover.start||editor.indexFromPos(result.start)<editor.indexFromPos(popover.start)}function _isResultAfterPopoverEnd(editor,popover,result){return!popover.end||editor.indexFromPos(popover.start)>editor.indexFromPos(result.end)}function _createPopoverState(editor,popoverResults){if(popoverResults&&popoverResults.length){let popover={content:$("<div id='quick-view-popover-root'></div>")};for(let i=0;i<popoverResults.length;i++){const result=popoverResults[i];_isResultBeforePopoverStart(editor,popover,result)&&(popover.start=result.start),_isResultAfterPopoverEnd(editor,popover,result)&&(popover.end=result.end),result.editsDoc&&(popover.editsDoc=!0);let cssClass="class='quick-view-partition quick-view-item'";i===popoverResults.length-1&&(cssClass="class='quick-view-item'"),popover.content.append($(`<div ${cssClass} ></div>`).append(result.content))}let startCoord=editor.charCoords(popover.start),endCoord=editor.charCoords(popover.end);return popover.xpos=(endCoord.left-startCoord.left)/2+startCoord.left,endCoord.left<startCoord.left&&(popover.xpos=startCoord.left),popover.ytop=startCoord.top,popover.ybot=startCoord.bottom,popover.visible=!1,popover.editor=editor,popover}return null}function _getPopover(results,providerInfos){let popovers=[],fulfilledProviderInfos=[];for(let i=0;i<results.length;i++){let result=results[i];if("fulfilled"===result.status&&result.value){let popoverResult=result.value;popoverResult.providerInfo=providerInfos[i],fulfilledProviderInfos.push(providerInfos[i]),popovers.push(popoverResult)}}for(let providerInfo of fulfilledProviderInfos){let provider=providerInfo.provider;provider.filterQuickView&&(popovers=provider.filterQuickView(popovers)||popovers)}return popovers}async function queryPreviewProviders(editor,pos,token){let line=editor.document.getLine(pos.line),providerInfos=_getQuickViewProviders(editor,pos),providerPromises=[],activeProviderInfos=[],results;for(let providerInfo of providerInfos){let provider=providerInfo.provider;provider.getQuickView?(providerPromises.push(provider.getQuickView(editor,pos,token,line)),activeProviderInfos.push(providerInfo)):console.error("Quickview provider does not implement the required getQuickView function",provider)}return _createPopoverState(editor,_getPopover(await Promise.allSettled(providerPromises),activeProviderInfos))}function _renderPreview(editor){if(popoverState&&popoverState.start&&popoverState.end){popoverState.marker=editor.markText(QUICK_VIEW_EDITOR_MARKER,popoverState.start,popoverState.end,{className:"quick-view-highlight"});let $popoverContent=$(popoverState.content);$previewContent.append($popoverContent),$previewContainer.show(),popoverState.visible=!0,positionPreview(editor,popoverState.xpos,popoverState.ytop,popoverState.ybot),exports.off(_EVENT_POPUP_CONTENT_MUTATED),exports.on(_EVENT_POPUP_CONTENT_MUTATED,()=>{popoverState&&editor&&positionPreview(editor,popoverState.xpos,popoverState.ytop,popoverState.ybot)})}}let currentQueryID=0;async function showPreview(editor){let token;if(editor||(editor=EditorManager.getHoveredEditor(_currentMousePos)),!editor)return void hidePreview();let pos=editor.coordsChar({left:_currentMousePos.clientX,top:_currentMousePos.clientY});if(pos.ch>=editor.document.getLine(pos.line).length)return;token=editor.getToken(pos);let savedQueryId=++currentQueryID;popoverState=await queryPreviewProviders(editor,pos,token),savedQueryId===currentQueryID&&_renderPreview(editor)}function _isMouseFarFromPopup(){const previewRect=$previewContainer[0].getBoundingClientRect(),docRect={height:$(document).height(),width:$(document).width()},thresholdPercent=5;function _isDistanceExceedThreshold(smaller,larger,total,threshold){return(larger-smaller)/total*100>threshold}let x=_currentMousePos.clientX,y=_currentMousePos.clientY;return!!(x<previewRect.left&&_isDistanceExceedThreshold(x,previewRect.left,docRect.width,5)||x>previewRect.right&&_isDistanceExceedThreshold(previewRect.right,x,docRect.width,5)||y<previewRect.top&&_isDistanceExceedThreshold(y,previewRect.top,docRect.height,5)||y>previewRect.bottom&&_isDistanceExceedThreshold(previewRect.bottom,y,docRect.height,5))}function processMouseMove(){if(animationRequest=null,mouseInPreviewContainer||quickViewLocked)return;let editor=null;if(popoverState&&popoverState.visible&&(editor=EditorManager.getHoveredEditor(_currentMousePos))){let pos=editor.coordsChar({left:_currentMousePos.clientX,top:_currentMousePos.clientY});if(popoverState.start&&popoverState.end&&editor.posWithinRange(pos,popoverState.start,popoverState.end,!0)&&pos.ch<editor.document.getLine(pos.line).length)return;if(_isMouseFarFromPopup())return void hidePreview()}popoverState=popoverState||{},clearTimeout(popoverState.hoverTimer),popoverState.hoverTimer=window.setTimeout(function(){mouseInPreviewContainer||quickViewLocked||(hidePreview(),popoverState={},showPreview(editor))},HOVER_DELAY)}function handleMouseMove(event){_currentMousePos={clientX:event.clientX,clientY:event.clientY},!enabled||quickViewLocked||$previewContainer[0].contains(window.document.activeElement)||(0===event.buttons||mouseInPreviewContainer?animationRequest||(animationRequest=window.requestAnimationFrame(processMouseMove)):hidePreview())}function docChanged(){popoverState&&!popoverState.editsDoc&&hidePreview()}function onActiveEditorChange(event,current,previous){hidePreview(),previous&&previous.document&&previous.document.off("change",docChanged),current&¤t.document&¤t.document.on("change",docChanged)}function updateMenuItemCheckmark(){CommandManager.get(CMD_ENABLE_QUICK_VIEW).setChecked(enabled)}let mouseInPreviewContainer=!1;function mouseOut(_evt){setTimeout(()=>{mouseInPreviewContainer||$previewContainer[0].contains(_evt.toElement)||quickViewLocked||hidePreview()},HOVER_DELAY)}function _mouseEnteredPreviewContainer(){mouseInPreviewContainer=!0}function _mouseExitedPreviewContainer(){mouseInPreviewContainer=!1}function setEnabled(_enabled,doNotSave){if(enabled!==_enabled){enabled=_enabled;let editorHolder=$("#editor-holder")[0],previewContainer=$previewContainer[0];enabled?(editorHolder.addEventListener("mousemove",handleMouseMove,!0),editorHolder.addEventListener("scroll",hidePreview,!0),editorHolder.addEventListener("mouseout",mouseOut,!0),previewContainer.addEventListener("mouseover",_mouseEnteredPreviewContainer,!0),previewContainer.addEventListener("mouseout",_mouseExitedPreviewContainer,!0),onActiveEditorChange(null,EditorManager.getActiveEditor(),null),EditorManager.on("activeEditorChange",onActiveEditorChange)):(editorHolder.removeEventListener("mousemove",handleMouseMove,!0),editorHolder.removeEventListener("scroll",hidePreview,!0),editorHolder.removeEventListener("mouseout",mouseOut,!0),previewContainer.removeEventListener("mouseover",_mouseEnteredPreviewContainer,!0),previewContainer.removeEventListener("mouseout",_mouseExitedPreviewContainer,!0),onActiveEditorChange(null,null,EditorManager.getActiveEditor()),EditorManager.off("activeEditorChange",onActiveEditorChange),hidePreview()),doNotSave||(prefs.set("enabled",enabled),prefs.save())}updateMenuItemCheckmark()}function toggleEnableQuickView(){let enableQuickView=!enabled;enableQuickView||unlockQuickView(),setEnabled(enableQuickView)}function _forceShow(popover){hidePreview(),_currentMousePos={clientX:popover.xpos,clientY:Math.floor((popover.ybot+popover.ytop)/2)},popoverState=popover,_renderPreview(popover.editor)}function _handleEscapeKeyEvent(event){return!!isQuickViewShown()&&(hidePreview(),event.preventDefault(),event.stopPropagation(),!0)}function isQuickViewShown(){return popoverState&&popoverState.visible||!1}function lockQuickView(){isQuickViewShown()&&(quickViewLocked=!0)}function unlockQuickView(){quickViewLocked=!1}AppInit.appReady(function(){$previewContainer=$(previewContainerHTML).appendTo($("body")),$previewContent=$previewContainer.find(".preview-content"),observer.observe($previewContent[0],{childList:!0,subtree:!0}),CommandManager.register(Strings.CMD_ENABLE_QUICK_VIEW,CMD_ENABLE_QUICK_VIEW,toggleEnableQuickView),Menus.getMenu(Menus.AppMenuBar.VIEW_MENU).addMenuItem(CMD_ENABLE_QUICK_VIEW,null,Menus.AFTER,Commands.VIEW_TOGGLE_INSPECTION),setEnabled(prefs.get("enabled"),!0),prefs.on("change","enabled",function(){setEnabled(prefs.get("enabled"),!0)}),WorkspaceManager.addEscapeKeyEventHandler("quickView",_handleEscapeKeyEvent)}),exports._queryPreviewProviders=queryPreviewProviders,exports._forceShow=_forceShow,exports.registerQuickViewProvider=registerQuickViewProvider,exports.removeQuickViewProvider=removeQuickViewProvider,exports.isQuickViewShown=isQuickViewShown,exports.lockQuickView=lockQuickView,exports.unlockQuickView=unlockQuickView});