diff --git a/src/editor/Editor.js b/src/editor/Editor.js index 2736197bff6..a47ab23da6b 100644 --- a/src/editor/Editor.js +++ b/src/editor/Editor.js @@ -986,8 +986,13 @@ define(function (require, exports, module) { * Set the editor size in pixels or percentage * @param {(number|string)} width * @param {(number|string)} height + * @param {boolean=} revealCursor whether or not to reveal the cursor after resize */ - Editor.prototype.setSize = function (width, height) { + Editor.prototype.setSize = function (width, height, revealCursor) { + if (revealCursor) { + var delta = height - $(this.getScrollerElement()).height(); + this.showCursorAfterResize(delta); + } this._codeMirror.setSize(width, height); }; @@ -1030,6 +1035,26 @@ define(function (require, exports, module) { this.setScrollPos(null, pos); } }; + + /** + * Determines if the cursor will be hidden, and if it will scrolls the + * editor viewport restoring the distance between the cursor and the bottom + * of the editor prior to editor resize, or centering the cursor vertically + * in the editor if that requires less scrolling. + * + * @param {number} delta The change in editor height + */ + Editor.prototype.showCursorAfterResize = function (delta) { + var $scrollerElement = $(this.getScrollerElement()), + editorHeight = $scrollerElement.height(), + cursorToTop = this._codeMirror.cursorCoords(null, "page").bottom - $scrollerElement.offset().top, + cursorToBottom = editorHeight - cursorToTop; + + if (delta < 0 && -delta > cursorToBottom) { + var scrollTarget = this.getScrollPos().y + Math.min(cursorToTop - (editorHeight + delta) / 2, -delta); + this.setScrollPos(null, scrollTarget); + } + }; /** * Given a position, returns its index within the text (assuming \n newlines) diff --git a/src/editor/EditorManager.js b/src/editor/EditorManager.js index 4536e270e9c..d090475987a 100644 --- a/src/editor/EditorManager.js +++ b/src/editor/EditorManager.js @@ -501,29 +501,32 @@ define(function (require, exports, module) { * some other cases are handled by external code calling `resizeEditor()` (e.g. ModalBar hide/show). * * @param {number} editorAreaHt - * @param {string=} refreshFlag For internal use. Set to "force" to ensure the editor will refresh, - * "skip" to ensure the editor does not refresh, or leave undefined to let `_onEditorAreaResize()` - * determine whether it needs to refresh. + * @param {{refresh:string=, revealCursor:boolean=}} options For internal use. + * Set to "force" to ensure the editor will refresh, "skip" to ensure the editor does not refresh, or + * leave undefined to let `_onEditorAreaResize()` determine whether it needs to refresh. + * Set revealCursor to true to reveal cursor. */ - function _onEditorAreaResize(event, editorAreaHt, refreshFlag) { + function _onEditorAreaResize(event, editorAreaHt, options) { if (_currentEditor) { var curRoot = _currentEditor.getRootElement(), - curWidth = $(curRoot).width(); - if (!curRoot.style.height || $(curRoot).height() !== editorAreaHt) { + curWidth = $(curRoot).width(), + curHeight = $(curRoot).height(); + + if (!curRoot.style.height || curHeight !== editorAreaHt) { // Call setSize() instead of $.height() to allow CodeMirror to // check for options like line wrapping - _currentEditor.setSize(null, editorAreaHt); - if (refreshFlag === undefined) { - refreshFlag = REFRESH_FORCE; + _currentEditor.setSize(null, editorAreaHt, options.revealCursor); + if (options.refresh === undefined) { + options.refresh = REFRESH_FORCE; } } else if (curWidth !== _lastEditorWidth) { - if (refreshFlag === undefined) { - refreshFlag = REFRESH_FORCE; + if (options.refresh === undefined) { + options.refresh = REFRESH_FORCE; } } _lastEditorWidth = curWidth; - if (refreshFlag === REFRESH_FORCE) { + if (options.refresh === REFRESH_FORCE) { _currentEditor.refreshAll(true); } } diff --git a/src/view/PanelManager.js b/src/view/PanelManager.js index 86024026ede..40111c285fd 100644 --- a/src/view/PanelManager.js +++ b/src/view/PanelManager.js @@ -101,16 +101,16 @@ define(function (require, exports, module) { * Calculates a new size for editor-holder and resizes it accordingly, then and dispatches the "editorAreaResize" * event. (The editors within are resized by EditorManager, in response to that event). * - * @param {string=} refreshHint One of "skip", "force", or undefined. See EditorManager docs. + * @param {{refresh:string=, revealCursor:boolean=}} options See EditorManager._onEditorAreaResize docs. */ - function triggerEditorResize(refreshHint) { + function triggerEditorResize(options) { // Find how much space is left for the editor var editorAreaHeight = calcEditorHeight(); $editorHolder.height(editorAreaHeight); // affects size of "not-editor" placeholder as well // Resize editor to fill the space - $(exports).trigger("editorAreaResize", [editorAreaHeight, refreshHint]); + $(exports).trigger("editorAreaResize", [editorAreaHeight, options || {}]); } @@ -144,14 +144,18 @@ define(function (require, exports, module) { /** Trigger editor area resize whenever the given panel is shown/hidden/resized */ function listenToResize($panel) { - // Update editor height when shown/hidden, & continuously as panel is resized - $panel.on("panelCollapsed panelExpanded panelResizeUpdate", function () { + // Update editor height when hidden, & continuously as panel is resized + $panel.on("panelCollapsed panelResizeUpdate", function () { triggerEditorResize(); }); // Update max size of sibling panels when shown/hidden, & at *end* of resize gesture $panel.on("panelCollapsed panelExpanded panelResizeEnd", function () { updateResizeLimits(); }); + // Update editor height when shown, & scroll to show cursor above panel if necessary + $panel.on("panelExpanded", function () { + triggerEditorResize({revealCursor: true}); + }); }