Bug 919978 - Make StyleEditor use CodeMirror, r=anton, msucan

This commit is contained in:
Girish Sharma 2013-10-24 10:31:02 +05:30
parent f8ceba11c2
commit d23a69252d
13 changed files with 278 additions and 147 deletions

View File

@ -862,7 +862,7 @@ FilterView.prototype = {
_performLineSearch: function(aLine) {
// Make sure we're actually searching for a valid line.
if (aLine) {
DebuggerView.editor.setCursor({ line: aLine - 1, ch: 0 });
DebuggerView.editor.setCursor({ line: aLine - 1, ch: 0 }, "center");
}
},
@ -1497,6 +1497,7 @@ FilteredFunctionsView.prototype = Heritage.extend(ResultsPanelContainer.prototyp
DebuggerView.setEditorLocation(sourceUrl, actualLocation.start.line, {
charOffset: scriptOffset,
columnOffset: actualLocation.start.column,
align: "center",
noDebug: true
});
}

View File

@ -457,7 +457,8 @@ let DebuggerView = {
}
if (!aFlags.noCaret) {
this.editor.setCursor({ line: aLine -1, ch: aFlags.columnOffset || 0 });
this.editor.setCursor({ line: aLine -1, ch: aFlags.columnOffset || 0 },
aFlags.align);
}
if (!aFlags.noDebug) {

View File

@ -37,6 +37,7 @@ browser.jar:
content/browser/devtools/codemirror/htmlmixed.js (sourceeditor/codemirror/htmlmixed.js)
content/browser/devtools/codemirror/activeline.js (sourceeditor/codemirror/activeline.js)
content/browser/devtools/codemirror/matchbrackets.js (sourceeditor/codemirror/matchbrackets.js)
content/browser/devtools/codemirror/closebrackets.js (sourceeditor/codemirror/closebrackets.js)
content/browser/devtools/codemirror/comment.js (sourceeditor/codemirror/comment.js)
content/browser/devtools/codemirror/searchcursor.js (sourceeditor/codemirror/search/searchcursor.js)
content/browser/devtools/codemirror/search.js (sourceeditor/codemirror/search/search.js)

View File

@ -40,6 +40,7 @@ in the LICENSE file:
* dialog/dialog.js
* javascript.js
* matchbrackets.js
* closebrackets.js
* search/match-highlighter.js
* search/search.js
* search/searchcursor.js

View File

@ -0,0 +1,82 @@
(function() {
var DEFAULT_BRACKETS = "()[]{}''\"\"";
var DEFAULT_EXPLODE_ON_ENTER = "[]{}";
var SPACE_CHAR_REGEX = /\s/;
CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
if (old != CodeMirror.Init && old)
cm.removeKeyMap("autoCloseBrackets");
if (!val) return;
var pairs = DEFAULT_BRACKETS, explode = DEFAULT_EXPLODE_ON_ENTER;
if (typeof val == "string") pairs = val;
else if (typeof val == "object") {
if (val.pairs != null) pairs = val.pairs;
if (val.explode != null) explode = val.explode;
}
var map = buildKeymap(pairs);
if (explode) map.Enter = buildExplodeHandler(explode);
cm.addKeyMap(map);
});
function charsAround(cm, pos) {
var str = cm.getRange(CodeMirror.Pos(pos.line, pos.ch - 1),
CodeMirror.Pos(pos.line, pos.ch + 1));
return str.length == 2 ? str : null;
}
function buildKeymap(pairs) {
var map = {
name : "autoCloseBrackets",
Backspace: function(cm) {
if (cm.somethingSelected()) return CodeMirror.Pass;
var cur = cm.getCursor(), around = charsAround(cm, cur);
if (around && pairs.indexOf(around) % 2 == 0)
cm.replaceRange("", CodeMirror.Pos(cur.line, cur.ch - 1), CodeMirror.Pos(cur.line, cur.ch + 1));
else
return CodeMirror.Pass;
}
};
var closingBrackets = "";
for (var i = 0; i < pairs.length; i += 2) (function(left, right) {
if (left != right) closingBrackets += right;
function surround(cm) {
var selection = cm.getSelection();
cm.replaceSelection(left + selection + right);
}
function maybeOverwrite(cm) {
var cur = cm.getCursor(), ahead = cm.getRange(cur, CodeMirror.Pos(cur.line, cur.ch + 1));
if (ahead != right || cm.somethingSelected()) return CodeMirror.Pass;
else cm.execCommand("goCharRight");
}
map["'" + left + "'"] = function(cm) {
if (left == "'" && cm.getTokenAt(cm.getCursor()).type == "comment")
return CodeMirror.Pass;
if (cm.somethingSelected()) return surround(cm);
if (left == right && maybeOverwrite(cm) != CodeMirror.Pass) return;
var cur = cm.getCursor(), ahead = CodeMirror.Pos(cur.line, cur.ch + 1);
var line = cm.getLine(cur.line), nextChar = line.charAt(cur.ch), curChar = cur.ch > 0 ? line.charAt(cur.ch - 1) : "";
if (left == right && CodeMirror.isWordChar(curChar))
return CodeMirror.Pass;
if (line.length == cur.ch || closingBrackets.indexOf(nextChar) >= 0 || SPACE_CHAR_REGEX.test(nextChar))
cm.replaceSelection(left + right, {head: ahead, anchor: ahead});
else
return CodeMirror.Pass;
};
if (left != right) map["'" + right + "'"] = maybeOverwrite;
})(pairs.charAt(i), pairs.charAt(i + 1));
return map;
}
function buildExplodeHandler(pairs) {
return function(cm) {
var cur = cm.getCursor(), around = charsAround(cm, cur);
if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
cm.operation(function() {
var newPos = CodeMirror.Pos(cur.line + 1, 0);
cm.replaceSelection("\n\n", {anchor: newPos, head: newPos}, "+input");
cm.indentLine(cur.line + 1, null, true);
cm.indentLine(cur.line + 2, null, true);
});
};
}
})();

View File

@ -62,25 +62,27 @@ function getSearchCursor(cm, query, pos) {
* Otherwise, creates a new search and selects the first
* result.
*/
function doSearch(cm, rev, query) {
function doSearch(ctx, rev, query) {
let { cm } = ctx;
let state = getSearchState(cm);
if (state.query)
return searchNext(cm, rev);
return searchNext(ctx, rev);
cm.operation(function () {
if (state.query) return;
state.query = query;
state.posFrom = state.posTo = { line: 0, ch: 0 };
searchNext(cm, rev);
searchNext(ctx, rev);
});
}
/**
* Selects the next result of a saved search.
*/
function searchNext(cm, rev) {
function searchNext(ctx, rev) {
let { cm, ed } = ctx;
cm.operation(function () {
let state = getSearchState(cm)
let cursor = getSearchCursor(cm, state.query, rev ? state.posFrom : state.posTo);
@ -92,6 +94,7 @@ function searchNext(cm, rev) {
return;
}
ed.alignLine(cursor.from().line, "center");
cm.setSelection(cursor.from(), cursor.to());
state.posFrom = cursor.from();
state.posTo = cursor.to();
@ -236,25 +239,22 @@ function clearDebugLocation(ctx) {
* Starts a new search.
*/
function find(ctx, query) {
let { cm } = ctx;
clearSearch(cm);
doSearch(cm, false, query);
clearSearch(ctx.cm);
doSearch(ctx, false, query);
}
/**
* Finds the next item based on the currently saved search.
*/
function findNext(ctx, query) {
let { cm } = ctx;
doSearch(cm, false, query);
doSearch(ctx, false, query);
}
/**
* Finds the previous item based on the currently saved search.
*/
function findPrev(ctx, query) {
let { cm } = ctx;
doSearch(cm, true, query);
doSearch(ctx, true, query);
}

View File

@ -12,6 +12,10 @@ const EXPAND_TAB = "devtools.editor.expandtab";
const L10N_BUNDLE = "chrome://browser/locale/devtools/sourceeditor.properties";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
// Maximum allowed margin (in number of lines) from top or bottom of the editor
// while shifting to a line which was initially out of view.
const MAX_VERTICAL_OFFSET = 3;
const promise = require("sdk/core/promise");
const events = require("devtools/shared/event-emitter");
@ -34,6 +38,7 @@ const CM_SCRIPTS = [
"chrome://browser/content/devtools/codemirror/searchcursor.js",
"chrome://browser/content/devtools/codemirror/search.js",
"chrome://browser/content/devtools/codemirror/matchbrackets.js",
"chrome://browser/content/devtools/codemirror/closebrackets.js",
"chrome://browser/content/devtools/codemirror/comment.js",
"chrome://browser/content/devtools/codemirror/javascript.js",
"chrome://browser/content/devtools/codemirror/xml.js",
@ -59,7 +64,6 @@ const CM_IFRAME =
const CM_MAPPING = [
"focus",
"hasFocus",
"setCursor",
"getCursor",
"somethingSelected",
"setSelection",
@ -78,6 +82,8 @@ const CM_JUMP_DIALOG = [
+ " <input type=text style='width: 10em'/>"
];
const { cssProperties, cssValues, cssColors } = getCSSKeywords();
const editors = new WeakMap();
Editor.modes = {
@ -192,7 +198,21 @@ Editor.prototype = {
CM_SCRIPTS.forEach((url) =>
Services.scriptloader.loadSubScript(url, win, "utf8"));
// Create a CodeMirror instance add support for context menus and
// Replace the propertyKeywords, colorKeywords and valueKeywords
// properties of the CSS MIME type with the values provided by Gecko.
let cssSpec = win.CodeMirror.resolveMode("text/css");
cssSpec.propertyKeywords = cssProperties;
cssSpec.colorKeywords = cssColors;
cssSpec.valueKeywords = cssValues;
win.CodeMirror.defineMIME("text/css", cssSpec);
let scssSpec = win.CodeMirror.resolveMode("text/x-scss");
scssSpec.propertyKeywords = cssProperties;
scssSpec.colorKeywords = cssColors;
scssSpec.valueKeywords = cssValues;
win.CodeMirror.defineMIME("text/x-scss", scssSpec);
// Create a CodeMirror instance add support for context menus,
// overwrite the default controller (otherwise items in the top and
// context menus won't work).
@ -434,6 +454,67 @@ Editor.prototype = {
});
},
/**
* Gets the first visible line number in the editor.
*/
getFirstVisibleLine: function () {
let cm = editors.get(this);
return cm.lineAtHeight(0, "local");
},
/**
* Scrolls the view such that the given line number is the first visible line.
*/
setFirstVisibleLine: function (line) {
let cm = editors.get(this);
let { top } = cm.charCoords({line: line, ch: 0}, "local");
cm.scrollTo(0, top);
},
/**
* Sets the cursor to the specified {line, ch} position with an additional
* option to align the line at the "top", "center" or "bottom" of the editor
* with "top" being default value.
*/
setCursor: function ({line, ch}, align) {
let cm = editors.get(this);
this.alignLine(line, align);
cm.setCursor({line: line, ch: ch});
},
/**
* Aligns the provided line to either "top", "center" or "bottom" of the
* editor view with a maximum margin of MAX_VERTICAL_OFFSET lines from top or
* bottom.
*/
alignLine: function(line, align) {
let cm = editors.get(this);
let from = cm.lineAtHeight(0, "page");
let to = cm.lineAtHeight(cm.getWrapperElement().clientHeight, "page");
let linesVisible = to - from;
let halfVisible = Math.round(linesVisible/2);
// If the target line is in view, skip the vertical alignment part.
if (line <= to && line >= from) {
return;
}
// Setting the offset so that the line always falls in the upper half
// of visible lines (lower half for bottom aligned).
// MAX_VERTICAL_OFFSET is the maximum allowed value.
let offset = Math.min(halfVisible, MAX_VERTICAL_OFFSET);
let topLine = {
"center": Math.max(line - halfVisible, 0),
"bottom": Math.max(line - linesVisible + offset, 0),
"top": Math.max(line - offset, 0)
}[align || "top"] || offset;
// Bringing down the topLine to total lines in the editor if exceeding.
topLine = Math.min(topLine, this.lineCount());
this.setFirstVisibleLine(topLine);
},
destroy: function () {
this.container = null;
this.config = null;
@ -452,6 +533,44 @@ CM_MAPPING.forEach(function (name) {
};
});
// Since Gecko already provide complete and up to date list of CSS property
// names, values and color names, we compute them so that they can replace
// the ones used in CodeMirror while initiating an editor object. This is done
// here instead of the file codemirror/css.js so as to leave that file untouched
// and easily upgradable.
function getCSSKeywords() {
function keySet(array) {
var keys = {};
for (var i = 0; i < array.length; ++i) {
keys[array[i]] = true;
}
return keys;
}
let domUtils = Cc["@mozilla.org/inspector/dom-utils;1"]
.getService(Ci.inIDOMUtils);
let cssProperties = domUtils.getCSSPropertyNames(domUtils.INCLUDE_ALIASES);
let cssColors = {};
let cssValues = {};
cssProperties.forEach(property => {
if (property.contains("color")) {
domUtils.getCSSValuesForProperty(property).forEach(value => {
cssColors[value] = true;
});
}
else {
domUtils.getCSSValuesForProperty(property).forEach(value => {
cssValues[value] = true;
});
}
});
return {
cssProperties: keySet(cssProperties),
cssValues: cssValues,
cssColors: cssColors
};
}
/**
* Returns a controller object that can be used for
* editor-specific commands such as find, jump to line,

View File

@ -73,7 +73,7 @@ StyleEditorUI.prototype = {
return true;
}
return this.editors.some((editor) => {
return editor.sourceEditor && editor.sourceEditor.dirty;
return editor.sourceEditor && !editor.sourceEditor.isClean();
});
},
@ -151,8 +151,8 @@ StyleEditorUI.prototype = {
// remember selected sheet and line number for next load
if (this.selectedEditor && this.selectedEditor.sourceEditor) {
let href = this.selectedEditor.styleSheet.href;
let {line, col} = this.selectedEditor.sourceEditor.getCaretPosition();
this.selectStyleSheet(href, line, col);
let {line, ch} = this.selectedEditor.sourceEditor.getCursor();
this.selectStyleSheet(href, line, ch);
}
this._clearStyleSheetEditors();
@ -365,7 +365,7 @@ StyleEditorUI.prototype = {
col = col || 0;
editor.getSourceEditor().then(() => {
editor.sourceEditor.setCaretPosition(line, col);
editor.sourceEditor.setCursor({line: line, ch: col});
});
this._view.activeSummary = editor.summary;

View File

@ -11,21 +11,26 @@ const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js").Promise;
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
const Editor = require("devtools/sourceeditor/editor");
const promise = require("sdk/core/promise");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource:///modules/devtools/shared/event-emitter.js");
Cu.import("resource:///modules/devtools/sourceeditor/source-editor.jsm");
Cu.import("resource:///modules/devtools/StyleEditorUtil.jsm");
const SAVE_ERROR = "error-save";
// max update frequency in ms (avoid potential typing lag and/or flicker)
// @see StyleEditor.updateStylesheet
const UPDATE_STYLESHEET_THROTTLE_DELAY = 500;
function ctrl(k) {
return (Services.appinfo.OS == "Darwin" ? "Cmd-" : "Ctrl-") + k;
}
/**
* StyleSheetEditor controls the editor linked to a particular StyleSheet
* object.
@ -58,7 +63,10 @@ function StyleSheetEditor(styleSheet, win, file, isNew) {
this._state = { // state to use when inputElement attaches
text: "",
selection: {start: 0, end: 0},
selection: {
start: {line: 0, ch: 0},
end: {line: 0, ch: 0}
},
readOnly: false,
topIndex: 0, // the first visible line
};
@ -92,7 +100,7 @@ StyleSheetEditor.prototype = {
* Whether there are unsaved changes in the editor
*/
get unsaved() {
return this._sourceEditor && this._sourceEditor.dirty;
return this._sourceEditor && !this._sourceEditor.isClean();
},
/**
@ -200,21 +208,20 @@ StyleSheetEditor.prototype = {
load: function(inputElement) {
this._inputElement = inputElement;
let sourceEditor = new SourceEditor();
let config = {
initialText: this._state.text,
showLineNumbers: true,
mode: SourceEditor.MODES.CSS,
value: this._state.text,
lineNumbers: true,
mode: Editor.modes.css,
readOnly: this._state.readOnly,
keys: this._getKeyBindings()
autoCloseBrackets: "{}()[]",
extraKeys: this._getKeyBindings()
};
let sourceEditor = new Editor(config);
sourceEditor.init(inputElement, config, function onSourceEditorReady() {
setupBracketCompletion(sourceEditor);
sourceEditor.addEventListener(SourceEditor.EVENTS.TEXT_CHANGED,
function onTextChanged(event) {
sourceEditor.appendTo(inputElement).then(() => {
sourceEditor.on("change", () => {
this.updateStyleSheet();
}.bind(this));
});
this._sourceEditor = sourceEditor;
@ -223,15 +230,14 @@ StyleSheetEditor.prototype = {
sourceEditor.focus();
}
sourceEditor.setTopIndex(this._state.topIndex);
sourceEditor.setFirstVisibleLine(this._state.topIndex);
sourceEditor.setSelection(this._state.selection.start,
this._state.selection.end);
this.emit("source-editor-load");
}.bind(this));
});
sourceEditor.addEventListener(SourceEditor.EVENTS.DIRTY_CHANGED,
this._onPropertyChange);
sourceEditor.on("change", this._onPropertyChange);
},
/**
@ -246,7 +252,7 @@ StyleSheetEditor.prototype = {
if (this.sourceEditor) {
return promise.resolve(this);
}
this.on("source-editor-load", (event) => {
this.on("source-editor-load", () => {
deferred.resolve(this);
});
return deferred.promise;
@ -268,7 +274,7 @@ StyleSheetEditor.prototype = {
*/
onShow: function() {
if (this._sourceEditor) {
this._sourceEditor.setTopIndex(this._state.topIndex);
this._sourceEditor.setFirstVisibleLine(this._state.topIndex);
}
this.focus();
},
@ -370,7 +376,7 @@ StyleSheetEditor.prototype = {
if (callback) {
callback(returnFile);
}
this.sourceEditor.dirty = false;
this.sourceEditor.markClean();
}.bind(this));
};
@ -384,28 +390,15 @@ StyleSheetEditor.prototype = {
* @return {array} key binding objects for the source editor
*/
_getKeyBindings: function() {
let bindings = [];
let bindings = {};
bindings.push({
action: "StyleEditor.save",
code: _("saveStyleSheet.commandkey"),
accel: true,
callback: function save() {
bindings[ctrl(_("saveStyleSheet.commandkey"))] = () => {
this.saveToFile(this.savedFile);
return true;
}.bind(this)
});
};
bindings.push({
action: "StyleEditor.saveAs",
code: _("saveStyleSheet.commandkey"),
accel: true,
shift: true,
callback: function saveAs() {
bindings["Shift-" + ctrl(_("saveStyleSheet.commandkey"))] = () => {
this.saveToFile();
return true;
}.bind(this)
});
};
return bindings;
},
@ -426,18 +419,6 @@ const TAB_CHARS = "\t";
const OS = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
const LINE_SEPARATOR = OS === "WINNT" ? "\r\n" : "\n";
/**
* Return string that repeats text for aCount times.
*
* @param string text
* @param number aCount
* @return string
*/
function repeat(text, aCount)
{
return (new Array(aCount + 1)).join(text);
}
/**
* Prettify minified CSS text.
* This prettifies CSS code where there is no indentation in usual places while
@ -469,7 +450,7 @@ function prettifyCSS(text)
parts.push(indent + text.substring(partStart, i));
partStart = i;
}
indent = repeat(TAB_CHARS, --indentLevel);
indent = TAB_CHARS.repeat(--indentLevel);
/* fallthrough */
case ";":
case "{":
@ -493,58 +474,9 @@ function prettifyCSS(text)
}
if (c == "{") {
indent = repeat(TAB_CHARS, ++indentLevel);
indent = TAB_CHARS.repeat(++indentLevel);
}
}
return parts.join(LINE_SEPARATOR);
}
/**
* Set up bracket completion on a given SourceEditor.
* This automatically closes the following CSS brackets: "{", "(", "["
*
* @param SourceEditor sourceEditor
*/
function setupBracketCompletion(sourceEditor)
{
let editorElement = sourceEditor.editorElement;
let pairs = {
123: { // {
closeString: "}",
closeKeyCode: Ci.nsIDOMKeyEvent.DOM_VK_CLOSE_BRACKET
},
40: { // (
closeString: ")",
closeKeyCode: Ci.nsIDOMKeyEvent.DOM_VK_0
},
91: { // [
closeString: "]",
closeKeyCode: Ci.nsIDOMKeyEvent.DOM_VK_CLOSE_BRACKET
},
};
editorElement.addEventListener("keypress", function onKeyPress(event) {
let pair = pairs[event.charCode];
if (!pair || event.ctrlKey || event.metaKey ||
event.accelKey || event.altKey) {
return true;
}
// We detected an open bracket, sending closing character
let keyCode = pair.closeKeyCode;
let charCode = pair.closeString.charCodeAt(0);
let modifiers = 0;
let utils = editorElement.ownerDocument.defaultView.
QueryInterface(Ci.nsIInterfaceRequestor).
getInterface(Ci.nsIDOMWindowUtils);
if (utils.sendKeyEvent("keydown", keyCode, 0, modifiers)) {
utils.sendKeyEvent("keypress", 0, charCode, modifiers);
}
utils.sendKeyEvent("keyup", keyCode, 0, modifiers);
// and rewind caret
sourceEditor.setCaretOffset(sourceEditor.getCaretOffset() - 1);
}, false);
}

View File

@ -96,21 +96,10 @@ function testEditor(aEditor) {
is(computedStyle.backgroundColor, "rgb(255, 255, 255)",
"content's background color is initially white");
EventUtils.synthesizeKey("[", {accelKey: true}, gPanelWindow);
is(aEditor.sourceEditor.getText(), "",
"Nothing happened as it is a known shortcut in source editor");
EventUtils.synthesizeKey("]", {accelKey: true}, gPanelWindow);
is(aEditor.sourceEditor.getText(), "",
"Nothing happened as it is a known shortcut in source editor");
for each (let c in TESTCASE_CSS_SOURCE) {
EventUtils.synthesizeKey(c, {}, gPanelWindow);
}
is(aEditor.sourceEditor.getText(), TESTCASE_CSS_SOURCE + "}",
"rule bracket has been auto-closed");
ok(aEditor.unsaved,
"new editor has unsaved flag");
@ -122,6 +111,9 @@ function testEditor(aEditor) {
function onTransitionEnd() {
content.removeEventListener("transitionend", onTransitionEnd, false);
is(gNewEditor.sourceEditor.getText(), TESTCASE_CSS_SOURCE + "}",
"rule bracket has been auto-closed");
let computedStyle = content.getComputedStyle(content.document.body, null);
is(computedStyle.backgroundColor, "rgb(255, 0, 0)",
"content's background color has been updated to red");

View File

@ -54,9 +54,9 @@ function testRemembered()
{
is(gUI.selectedEditor, gUI.editors[1], "second editor is selected");
let {line, col} = gUI.selectedEditor.sourceEditor.getCaretPosition();
let {line, ch} = gUI.selectedEditor.sourceEditor.getCursor();
is(line, LINE_NO, "correct line selected");
is(col, COL_NO, "correct column selected");
is(ch, COL_NO, "correct column selected");
testNewPage();
}
@ -80,9 +80,9 @@ function testNotRemembered()
{
is(gUI.selectedEditor, gUI.editors[0], "first editor is selected");
let {line, col} = gUI.selectedEditor.sourceEditor.getCaretPosition();
let {line, ch} = gUI.selectedEditor.sourceEditor.getCursor();
is(line, 0, "first line is selected");
is(col, 0, "first column is selected");
is(ch, 0, "first column is selected");
gUI = null;
finish();

View File

@ -29,13 +29,14 @@ function runTests(aUI)
is(aUI.editors.length, 2,
"there is 2 stylesheets initially");
aUI.editors[0].getSourceEditor().then(function onEditorAttached(aEditor) {
aUI.editors[0].getSourceEditor().then(aEditor => {
executeSoon(function () {
waitForFocus(function () {
// queue a resize to inverse aspect ratio
// this will trigger a detach and reattach (to workaround bug 254144)
let originalSourceEditor = aEditor.sourceEditor;
aEditor.sourceEditor.setCaretOffset(4); // to check the caret is preserved
let editor = aEditor.sourceEditor;
editor.setCursor(editor.getPosition(4)); // to check the caret is preserved
gOriginalWidth = gPanelWindow.outerWidth;
gOriginalHeight = gPanelWindow.outerHeight;
@ -44,7 +45,8 @@ function runTests(aUI)
executeSoon(function () {
is(aEditor.sourceEditor, originalSourceEditor,
"the editor still references the same SourceEditor instance");
is(aEditor.sourceEditor.getCaretOffset(), 4,
let editor = aEditor.sourceEditor;
is(editor.getOffset(editor.getCursor()), 4,
"the caret position has been preserved");
// queue a resize to original aspect ratio

View File

@ -131,7 +131,7 @@ function performLineCheck(aEditor, aLine, aCallback)
{
function checkForCorrectState()
{
is(aEditor.sourceEditor.getCaretPosition().line, aLine,
is(aEditor.sourceEditor.getCursor().line, aLine,
"correct line is selected");
is(StyleEditorUI.selectedStyleSheetIndex, aEditor.styleSheet.styleSheetIndex,
"correct stylesheet is selected in the editor");