Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'origin/master' into pflynn/live-css-syn…
Browse files Browse the repository at this point in the history
…c-from-disk

* origin/master:
  Fix html extension check.
  Make clicks in dead space in inline CSS widget set focus back to the actual editor and set the selection to the beginning/end
  Update CodeMirror SHA
  Correctly handle scenario where no document is active.
  Make sure in-memory changes to CSS docs are pushed when starting live development connection.
  Fail silently when trying to connect to stale connection.
  Reverted close() back to onClosed() since close() already means something
  Code review cleanup: changed onClosed() to close(), other minor fixes.
  Made Editor.setInlineWidgetHeight() also take a widget instead of an ID
  Get rid of EditorManager._addInlineWidget, an dmake it so Editor.addInlineWidget just takes an actual inlineWidget and stores the widget itself in the _inlineWidgets list.
  • Loading branch information
peterflynn committed Apr 5, 2012
2 parents 5cd730e + bbf4dbf commit a4b0c76
Show file tree
Hide file tree
Showing 11 changed files with 139 additions and 122 deletions.
5 changes: 5 additions & 0 deletions src/LiveDevelopment/Documents/CSSDocument.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ define(function CSSDocumentModule(require, exports, module) {
// res = {styleSheet}
this.rules = res.styleSheet.rules;
}.bind(this));

// If the CSS document is dirty, push the changes into the browser now
if (doc.isDirty) {
CSSAgent.reloadDocument(this.doc);
}
};

/** Close the document */
Expand Down
10 changes: 10 additions & 0 deletions src/LiveDevelopment/Inspector/Inspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,16 @@ define(function Inspector(require, exports, module) {
* @param {object} the method signature
*/
function _send(method, signature, varargs) {
if (!_socket) {
// FUTURE: Our current implementation closes and re-opens an inspector connection whenever
// a new HTML file is selected. If done quickly enough, pending requests from the previous
// connection could come in before the new socket connection is established. For now we
// simply ignore this condition.
// This race condition will go away once we support multiple inspector connections and turn
// off auto re-opening when a new HTML file is selected.
return;
}

console.assert(_socket, "You must connect to the WebSocket before sending messages.");
var id, callback, args, i, params = {};

Expand Down
12 changes: 7 additions & 5 deletions src/LiveDevelopment/LiveDevelopment.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ define(function LiveDevelopment(require, exports, module) {
// For Sprint 6, we only open live development connections for HTML files
// FUTURE: Remove this test when we support opening connections for different
// file types.
if (doc.extension.indexOf('htm') !== 0) {
if (!doc.extension || doc.extension.indexOf('htm') !== 0) {
return;
}

Expand Down Expand Up @@ -348,16 +348,18 @@ define(function LiveDevelopment(require, exports, module) {
/** Triggered by a document change from the DocumentManager */
function _onDocumentChange() {
var doc = _getCurrentDocument();
if (!doc) {
return;
}

if (Inspector.connected()) {
if (!doc) {
close();
} else if (agents.network && agents.network.wasURLRequested(doc.url)) {
if (agents.network && agents.network.wasURLRequested(doc.url)) {
_closeDocument();
var editor = EditorManager.getCurrentFullEditor();
_openDocument(doc, editor);
} else {
/* FUTURE: support live connections for docments other than html */
if (doc.extension.indexOf('htm') === 0) {
if (doc.extension && doc.extension.indexOf('htm') === 0) {
close();
setTimeout(open);
}
Expand Down
28 changes: 25 additions & 3 deletions src/editor/CSSInlineEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

define(function (require, exports, module) {
'use strict';

// Load dependent modules
var DocumentManager = require("document/DocumentManager"),
HTMLUtils = require("language/HTMLUtils"),
Expand Down Expand Up @@ -56,6 +56,7 @@ define(function (require, exports, module) {

// Bind event handlers
this._updateRelatedContainer = this._updateRelatedContainer.bind(this);
this._onClick = this._onClick.bind(this);

// Create DOM to hold editors and related list
this.$editorsDiv = $(document.createElement('div')).addClass("inlineEditorHolder");
Expand Down Expand Up @@ -108,6 +109,9 @@ define(function (require, exports, module) {

// Listen to the editor's scroll event to reposition the relatedContainer.
$(this.hostEditor).on("scroll", this._updateRelatedContainer);

// Listen for clicks directly on us, so we can set focus back to the editor
this.$htmlContent.on("click", this._onClick);

return (new $.Deferred()).resolve();
};
Expand Down Expand Up @@ -182,7 +186,7 @@ define(function (require, exports, module) {
};

/**
* Called any time inline was closed, whether manually (via closeThisInline()) or automatically
* Called any time inline is closed, whether manually (via closeThisInline()) or automatically
*/
CSSInlineEditor.prototype.onClosed = function () {
this.parentClass.onClosed.call(this); // super.onClosed()
Expand All @@ -193,6 +197,24 @@ define(function (require, exports, module) {
$(this.hostEditor).off("scroll", this._updateRelatedContainer);
};

/**
* Handle a click outside our child editor by setting focus back to it.
*/
CSSInlineEditor.prototype._onClick = function (event) {
var childEditor = this.editors[0],
editorRoot = childEditor.getRootElement(),
editorPos = $(editorRoot).offset();
if (!$.contains(editorRoot, event.target)) {
childEditor.focus();
if (event.pageY < editorPos.top) {
childEditor.setCursorPos(0, 0);
} else if (event.pageY > editorPos.top + $(editorRoot).height()) {
var lastLine = childEditor.getLastVisibleLine();
childEditor.setCursorPos(lastLine, childEditor.getLineText(lastLine).length);
}
}
};

/**
*
*
Expand Down Expand Up @@ -257,7 +279,7 @@ define(function (require, exports, module) {
this.parentClass.sizeInlineWidgetToContents.call(this, force);
// Size the widget height to the max between the editor content and the related rules list
var widgetHeight = Math.max(this.$relatedContainer.find(".related").height(), this.$editorsDiv.height());
this.hostEditor.setInlineWidgetHeight(this.inlineId, widgetHeight, true);
this.hostEditor.setInlineWidgetHeight(this, widgetHeight, true);

// The related rules container size itself based on htmlContent which is set by setInlineWidgetHeight above.
this._updateRelatedContainer();
Expand Down
85 changes: 45 additions & 40 deletions src/editor/Editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,8 @@ define(function (require, exports, module) {

// Destroying us destroys any inline widgets we're hosting. Make sure their closeCallbacks
// run, at least, since they may also need to release Document refs
this._inlineWidgets.forEach(function (inlineInfo) {
inlineInfo.closeCallback();
this._inlineWidgets.forEach(function (inlineWidget) {
inlineWidget.onClosed();
});
};

Expand All @@ -357,14 +357,8 @@ define(function (require, exports, module) {
* bugs in CodeMirror when lines are hidden.
*/
Editor.prototype._selectAllVisible = function () {
var startLine, endLine;
if (this._visibleRange) {
startLine = this._visibleRange.startLine;
endLine = this._visibleRange.endLine;
} else {
startLine = 0;
endLine = this.lineCount() - 1;
}
var startLine = this.getFirstVisibleLine(),
endLine = this.getLastVisibleLine();
this.setSelection({line: startLine, ch: 0},
{line: endLine, ch: this.getLineText(endLine).length});
};
Expand Down Expand Up @@ -664,6 +658,22 @@ define(function (require, exports, module) {
Editor.prototype.lineCount = function () {
return this._codeMirror.lineCount();
};

/**
* Gets the number of the first visible line in the editor.
* @returns {number} The 0-based index of the first visible line.
*/
Editor.prototype.getFirstVisibleLine = function () {
return (this._visibleRange ? this._visibleRange.startLine : 0);
};

/**
* Gets the number of the last visible line in the editor.
* @returns {number} The 0-based index of the last visible line.
*/
Editor.prototype.getLastVisibleLine = function () {
return (this._visibleRange ? this._visibleRange.endLine : this.lineCount() - 1);
};

/* Hides the specified line number in the editor
* @param {!number}
Expand All @@ -689,40 +699,37 @@ define(function (require, exports, module) {
return this._codeMirror.getScrollerElement();
};

/**
* Gets the root DOM node of the editor.
* @returns {Object} The editor's root DOM node.
*/
Editor.prototype.getRootElement = function () {
return this._codeMirror.getWrapperElement();
};

/**
* Adds an inline widget below the given line. If any inline widget was already open for that
* line, it is closed without warning.
* @param {!{line:number, ch:number}} pos Position in text to anchor the inline.
* @param {!DOMElement} domContent DOM node of widget UI to insert.
* @param {number} initialHeight Initial height to accomodate.
* @param {function()} parentShowCallback Function called when the host editor is shown
* (via Editor.setVisible()).
* @param {function()} closeCallback Function called when inline is closed, either automatically
* by CodeMirror, or by this host Editor closing, or manually via removeInlineWidget().
* @param {Object} data Extra data to track along with the widget. Accessible later via
* {@link #getInlineWidgets()}.
* @return {number} id for this inline widget instance; unique to this Editor
*/
Editor.prototype.addInlineWidget = function (pos, domContent, initialHeight, parentShowCallback, closeCallback, data) {
// Now add the new widget
* @param {!InlineWidget} inlineWidget The widget to add.
*/
Editor.prototype.addInlineWidget = function (pos, inlineWidget) {
var self = this;
var inlineId = this._codeMirror.addInlineWidget(pos, domContent, initialHeight, function (id) {
inlineWidget.id = this._codeMirror.addInlineWidget(pos, inlineWidget.htmlContent, inlineWidget.height, function (id) {
self._removeInlineWidgetInternal(id);
closeCallback();
inlineWidget.onClosed();
});
this._inlineWidgets.push({ id: inlineId, data: data, parentShowCallback: parentShowCallback, closeCallback: closeCallback });

return inlineId;
this._inlineWidgets.push(inlineWidget);
inlineWidget.onAdded();
};

/**
* Removes the given inline widget.
* @param {number} inlineId id returned by addInlineWidget().
* @param {number} inlineWidget The widget to remove.
*/
Editor.prototype.removeInlineWidget = function (inlineId) {
Editor.prototype.removeInlineWidget = function (inlineWidget) {
// _removeInlineWidgetInternal will get called from the destroy callback in CodeMirror.
this._codeMirror.removeInlineWidget(inlineId);
this._codeMirror.removeInlineWidget(inlineWidget.id);
};

/**
Expand All @@ -749,13 +756,13 @@ define(function (require, exports, module) {
};

/**
* Sets the height of the inline widget for this editor. The inline editor is identified by id.
* @param {!number} id
* @param {!height} height
* @param {boolean} ensureVisible
* Sets the height of an inline widget in this editor.
* @param {!InlineWidget} inlineWidget The widget whose height should be set.
* @param {!height} height The height of the widget.
* @param {boolean} ensureVisible Whether to scroll the entire widget into view.
*/
Editor.prototype.setInlineWidgetHeight = function (id, height, ensureVisible) {
this._codeMirror.setInlineWidgetHeight(id, height, ensureVisible);
Editor.prototype.setInlineWidgetHeight = function (inlineWidget, height, ensureVisible) {
this._codeMirror.setInlineWidgetHeight(inlineWidget.id, height, ensureVisible);
};


Expand Down Expand Up @@ -786,10 +793,8 @@ define(function (require, exports, module) {
$(this._codeMirror.getWrapperElement()).css("display", (show ? "" : "none"));
this._codeMirror.refresh();
if (show) {
this._inlineWidgets.forEach(function (widget) {
if (widget.parentShowCallback) {
widget.parentShowCallback();
}
this._inlineWidgets.forEach(function (inlineWidget) {
inlineWidget.onParentShown();
});
}
};
Expand Down
49 changes: 11 additions & 38 deletions src/editor/EditorManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,30 +108,6 @@ define(function (require, exports, module) {
return new Editor(doc, makeMasterEditor, mode, container, extraKeys, range);
}

/**
* @private
* Adds a new widget to the host Editor.
* @param {!Editor} editor the candidate host editor
* @param !{line:number, ch:number} pos
* @param {!InlineWidget} inlineWidget
*/
function _addInlineWidget(editor, pos, inlineWidget) {
$(inlineWidget.htmlContent).append('<div class="shadow top"/>')
.append('<div class="shadow bottom"/>');

var closeCallback = function () {
inlineWidget.onClosed();
};
var parentShowCallback = function () {
inlineWidget.onParentShown();
};

var inlineId = editor.addInlineWidget(pos, inlineWidget.htmlContent, inlineWidget.height,
parentShowCallback, closeCallback, inlineWidget);

inlineWidget.onAdded(inlineId);
}

/**
* @private
* Bound to Ctrl+E on outermost editors.
Expand All @@ -154,7 +130,7 @@ define(function (require, exports, module) {
// If one of them will provide a widget, show it inline once ready
if (inlinePromise) {
inlinePromise.done(function (inlineWidget) {
_addInlineWidget(editor, pos, inlineWidget);
editor.addInlineWidget(pos, inlineWidget);
result.resolve();
}).fail(function () {
result.reject();
Expand All @@ -167,18 +143,18 @@ define(function (require, exports, module) {
}

/**
* Removes the given widget UI from the given hostEdtior (agnostic of what the widget's content
* Removes the given widget UI from the given hostEditor (agnostic of what the widget's content
* is). The widget's onClosed() callback will be run as a result.
* @param {!Editor} hostEditor
* @param {!number} inlineId
* @param {!Editor} hostEditor The editor containing the widget.
* @param {!InlineWidget} inlineWidget The inline widget to close.
* @param {!boolean} moveFocus If true, focuses hostEditor and ensures the cursor position lies
* near the inline's location.
*/
function closeInlineWidget(hostEditor, inlineId, moveFocus) {
function closeInlineWidget(hostEditor, inlineWidget, moveFocus) {
if (moveFocus) {
// Place cursor back on the line just above the inline (the line from which it was opened)
// If cursor's already on that line, leave it be to preserve column position
var widgetLine = hostEditor._codeMirror.getInlineWidgetInfo(inlineId).line;
var widgetLine = hostEditor._codeMirror.getInlineWidgetInfo(inlineWidget.id).line;
var cursorLine = hostEditor.getCursorPos().line;
if (cursorLine !== widgetLine) {
hostEditor.setCursorPos({ line: widgetLine, pos: 0 });
Expand All @@ -187,10 +163,8 @@ define(function (require, exports, module) {
hostEditor.focus();
}

hostEditor.removeInlineWidget(inlineId);

hostEditor.removeInlineWidget(inlineWidget);
}


/**
* Registers a new inline provider. When _openInlineWidget() is called each registered inline
Expand Down Expand Up @@ -219,8 +193,8 @@ define(function (require, exports, module) {
function getInlineEditors(hostEditor) {
var inlineEditors = [];
hostEditor.getInlineWidgets().forEach(function (widget) {
if (widget.data instanceof InlineTextEditor) {
inlineEditors.concat(widget.data.editors);
if (widget instanceof InlineTextEditor) {
inlineEditors.concat(widget.editors);
}
});
return inlineEditors;
Expand Down Expand Up @@ -449,8 +423,8 @@ define(function (require, exports, module) {

// See if any inlines have focus
_currentEditor.getInlineWidgets().forEach(function (widget) {
if (widget.data instanceof InlineTextEditor) {
widget.data.editors.forEach(function (editor) {
if (widget instanceof InlineTextEditor) {
widget.editors.forEach(function (editor) {
if (editor.hasFocus()) {
focusedInline = editor;
}
Expand Down Expand Up @@ -480,7 +454,6 @@ define(function (require, exports, module) {

// For unit tests
exports._openInlineWidget = _openInlineWidget;
exports._addInlineWidget = _addInlineWidget;

// Define public API
exports.setEditorHolder = setEditorHolder;
Expand Down
Loading

0 comments on commit a4b0c76

Please sign in to comment.