Merge mozilla-central to mozilla-inbound

This commit is contained in:
Ed Morley 2012-02-23 01:03:16 +00:00
Родитель d5c1663550 1fff1817f2
Коммит f0f12f21cd
50 изменённых файлов: 3504 добавлений и 1970 удалений

Просмотреть файл

@ -55,8 +55,9 @@
this.check = function switchTab_check(aEvent)
{
var title = getAccessible(browserDocument()).name;
ok(title.indexOf(aEvent.accessible.name) != -1,
"Window title contains the name of active tab document");
isnot(title.indexOf(aEvent.accessible.name), -1,
"Window title contains the name of active tab document" +
" (Is '" + aEvent.accessible.name + "' in '" + title + "'?)");
}
this.getID = function switchTab_getID() { return "switch tab"; }

Просмотреть файл

@ -44,9 +44,6 @@ let gBrowserThumbnails = {
this._tabEvents.forEach(function (aEvent) {
gBrowser.tabContainer.removeEventListener(aEvent, this, false);
}, this);
this._timeouts = null;
this._pageThumbs = null;
},
handleEvent: function Thumbnails_handleEvent(aEvent) {

Просмотреть файл

@ -169,6 +169,7 @@ _BROWSER_FILES = \
browser_tabview_bug706430.js \
browser_tabview_bug706736.js \
browser_tabview_bug707466.js \
browser_tabview_bug728887.js \
browser_tabview_click_group.js \
browser_tabview_dragdrop.js \
browser_tabview_exit_button.js \

Просмотреть файл

@ -0,0 +1,15 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
function test() {
waitForExplicitFinish();
showTabView(function () {
let cw = TabView.getContentWindow();
let target = cw.GroupItems.groupItems[0].container;
EventUtils.sendMouseEvent({type: "dblclick", button: 0}, target, cw);
is(cw.GroupItems.groupItems.length, 1, "one groupItem after double clicking");
hideTabView(finish);
});
}

Просмотреть файл

@ -205,6 +205,9 @@ let UI = {
});
iQ(gTabViewFrame.contentDocument).dblclick(function(e) {
if (e.originalTarget.id != "content")
return;
// Create a group with one tab on double click
let box =
new Rect(e.clientX - Math.floor(TabItems.tabWidth/2),

Просмотреть файл

@ -10,7 +10,6 @@ browser.jar:
content/browser/devtools/cssruleview.xul (styleinspector/cssruleview.xul)
content/browser/devtools/styleinspector.css (styleinspector/styleinspector.css)
content/browser/orion.js (sourceeditor/orion/orion.js)
content/browser/orion.css (sourceeditor/orion/orion.css)
content/browser/source-editor-overlay.xul (sourceeditor/source-editor-overlay.xul)
* content/browser/debugger.xul (debugger/debugger.xul)
content/browser/debugger.css (debugger/debugger.css)

Просмотреть файл

@ -806,7 +806,7 @@ var Scratchpad = {
let config = {
mode: SourceEditor.MODES.JAVASCRIPT,
showLineNumbers: true,
placeholderText: initialText
initialText: initialText,
};
let editorPlaceholder = document.getElementById("scratchpad-editor");
@ -1068,7 +1068,15 @@ var Scratchpad = {
handler.apply(observer, aArgs);
}
}
}
},
openDocumentationPage: function SP_openDocumentationPage()
{
let url = this.strings.GetStringFromName("help.openDocumentationPage");
let newTab = this.gBrowser.addTab(url);
this.browserWindow.focus();
this.gBrowser.selectedTab = newTab;
},
};
XPCOMUtils.defineLazyGetter(Scratchpad, "strings", function () {

Просмотреть файл

@ -83,6 +83,7 @@
<command id="sp-cmd-webConsole" oncommand="Scratchpad.openWebConsole();"/>
<command id="sp-cmd-undo" oncommand="Scratchpad.undo();" disabled="true"/>
<command id="sp-cmd-redo" oncommand="Scratchpad.redo();" disabled="true"/>
<command id="sp-cmd-documentationLink" oncommand="Scratchpad.openDocumentationPage();"/>
</commandset>
<keyset id="sp-keyset">
@ -171,6 +172,9 @@
key="&gotoLineCmd.key;"
command="cmd_gotoLine"
modifiers="accel"/>
<key id="key_openHelp"
keycode="VK_F1"
command="sp-cmd-documentationLink"/>
</keyset>
@ -316,6 +320,24 @@
type="radio"/>
</menupopup>
</menu>
#ifdef XP_WIN
<menu id="sp-help-menu"
label="&helpMenu.label;"
accesskey="&helpMenuWin.accesskey;">
#else
<menu id="sp-help-menu"
label="&helpMenu.label;"
accesskey="&helpMenu.accesskey;">
#endif
<menupopup id="sp-menu-help">
<menuitem id="sp-menu-documentation"
label="&documentationLink.label;"
accesskey="&documentationLink.accesskey;"
command="sp-cmd-documentationLink"
key="key_openHelp"/>
</menupopup>
</menu>
</menubar>
<popupset id="scratchpad-popups">

Просмотреть файл

@ -63,6 +63,7 @@ _BROWSER_TEST_FILES = \
browser_scratchpad_bug690552_display_outputs_errors.js \
browser_scratchpad_bug650345_find_ui.js \
browser_scratchpad_bug714942_goto_line_ui.js \
browser_scratchpad_bug_650760_help_key.js \
head.js \
libs:: $(_BROWSER_TEST_FILES)

Просмотреть файл

@ -0,0 +1,60 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function test()
{
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
content.location = "data:text/html,Test keybindings for opening Scratchpad MDN Documentation, bug 650760";
gBrowser.selectedBrowser.addEventListener("load", function onTabLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onTabLoad, true);
ok(window.Scratchpad, "Scratchpad variable exists");
openScratchpad(runTest);
}, true);
}
function runTest()
{
let sp = gScratchpadWindow.Scratchpad;
ok(sp, "Scratchpad object exists in new window");
ok(sp.editor.hasFocus(), "the editor has focus");
let keyid = gScratchpadWindow.document.getElementById("key_openHelp");
let modifiers = keyid.getAttribute("modifiers");
let key = null;
if (keyid.getAttribute("keycode"))
key = keyid.getAttribute("keycode");
else if (keyid.getAttribute("key"))
key = keyid.getAttribute("key");
isnot(key, null, "Successfully retrieved keycode/key");
var aEvent = {
shiftKey: modifiers.match("shift"),
ctrlKey: modifiers.match("ctrl"),
altKey: modifiers.match("alt"),
metaKey: modifiers.match("meta"),
accelKey: modifiers.match("accel")
}
info("check that the MDN page is opened on \"F1\"");
let linkClicked = false;
sp.openDocumentationPage = function(event) { linkClicked = true; };
EventUtils.synthesizeKey(key, aEvent, gScratchpadWindow);
is(linkClicked, true, "MDN page will open");
finishTest();
}
function finishTest()
{
gScratchpadWindow.close();
finish();
}

Просмотреть файл

@ -49,10 +49,10 @@ copy({
ORION_EDITOR + "/orion/textview/eventTarget.js",
ORION_EDITOR + "/orion/editor/regex.js",
ORION_EDITOR + "/orion/textview/keyBinding.js",
ORION_EDITOR + "/orion/textview/annotations.js",
ORION_EDITOR + "/orion/textview/rulers.js",
ORION_EDITOR + "/orion/textview/undoStack.js",
ORION_EDITOR + "/orion/textview/textModel.js",
ORION_EDITOR + "/orion/textview/annotations.js",
ORION_EDITOR + "/orion/textview/tooltip.js",
ORION_EDITOR + "/orion/textview/textView.js",
ORION_EDITOR + "/orion/textview/textDND.js",

Просмотреть файл

@ -8,15 +8,19 @@ The Orion editor web site: http://www.eclipse.org/orion
To upgrade Orion to a newer version see the UPGRADE file.
Orion version: git clone from 2011-12-09
commit hash d8a6dc01d9c561d6eb99f03b64c8c78ce785c59d
+ patch for Eclipse Bug 366312 - right-clicking outside of the selection causes the caret to move
https://github.com/mihaisucan/orion.client/tree/bug-366312
see https://bugs.eclipse.org/bugs/show_bug.cgi?id=366312
+ patch for Mozilla Bug 711737 - Orion should support all the CSS properties from CSS1, CSS2, CSS2.1 and CSS3
https://bugzilla.mozilla.org/show_bug.cgi?id=711737
+ patch for Mozilla Bug 719028 - Style Editor does not highlight a few CSS2.0 and CSS3 properties
https://bugzilla.mozilla.org/show_bug.cgi?id=719028
Orion version: git clone from 2012-01-26
commit hash 1d1150131dacecc9f4d9eb3cdda9103ea1819045
+ patch for Eclipse Bug 370584 - [Firefox] Edit menu items in context menus
http://git.eclipse.org/c/orion/org.eclipse.orion.client.git/commit/?id=137d5a8e9bbc0fa204caae74ebd25a7d9d4729bd
see https://bugs.eclipse.org/bugs/show_bug.cgi?id=370584
+ patches for Eclipse Bug 370606 - Problems with UndoStack and deletions at
the beginning of the document
http://git.eclipse.org/c/orion/org.eclipse.orion.client.git/commit/?id=cec71bddaf32251c34d3728df5da13c130d14f33
http://git.eclipse.org/c/orion/org.eclipse.orion.client.git/commit/?id=3ce24b94f1d8103b16b9cf16f2f50a6302d43b18
http://git.eclipse.org/c/orion/org.eclipse.orion.client.git/commit/?id=27177e9a3dc70c20b4877e3eab3adfff1d56e342
see https://bugs.eclipse.org/bugs/show_bug.cgi?id=370606
# License
@ -25,3 +29,11 @@ file:
orion.js
orion.css
# Theming
The syntax highlighting and the editor UI are themed using a style sheet. The
default theme file is browser/themes/*/devtools/orion.css - this is based on the
orion.css found in this folder.
Please note that the orion.css file from this folder is not used. It is kept
here only as reference.

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -54,12 +54,22 @@ XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
const ORION_SCRIPT = "chrome://browser/content/orion.js";
const ORION_IFRAME = "data:text/html;charset=utf8,<!DOCTYPE html>" +
"<html style='height:100%' dir='ltr'>" +
"<head><link rel='stylesheet'" +
" href='chrome://browser/skin/devtools/orion-container.css'></head>" +
"<body style='height:100%;margin:0;overflow:hidden'>" +
"<div id='editor' style='height:100%'></div>" +
"</body></html>";
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
/**
* The primary selection update delay. On Linux, the X11 primary selection is
* updated to hold the currently selected text.
*
* @type number
*/
const PRIMARY_SELECTION_DELAY = 100;
/**
* Predefined themes for syntax highlighting. This objects maps
* SourceEditor.THEMES to Orion CSS files.
@ -69,8 +79,8 @@ const ORION_THEMES = {
};
/**
* Known editor events you can listen for. This object maps SourceEditor.EVENTS
* to Orion events.
* Known Orion editor events you can listen for. This object maps several of the
* SourceEditor.EVENTS to Orion events.
*/
const ORION_EVENTS = {
ContextMenu: "ContextMenu",
@ -89,6 +99,9 @@ const ORION_EVENTS = {
const ORION_ANNOTATION_TYPES = {
currentBracket: "orion.annotation.currentBracket",
matchingBracket: "orion.annotation.matchingBracket",
breakpoint: "orion.annotation.breakpoint",
task: "orion.annotation.task",
currentLine: "orion.annotation.currentLine",
};
/**
@ -127,13 +140,15 @@ var EXPORTED_SYMBOLS = ["SourceEditor"];
function SourceEditor() {
// Update the SourceEditor defaults from user preferences.
SourceEditor.DEFAULTS.TAB_SIZE =
SourceEditor.DEFAULTS.tabSize =
Services.prefs.getIntPref(SourceEditor.PREFS.TAB_SIZE);
SourceEditor.DEFAULTS.EXPAND_TAB =
SourceEditor.DEFAULTS.expandTab =
Services.prefs.getBoolPref(SourceEditor.PREFS.EXPAND_TAB);
this._onOrionSelection = this._onOrionSelection.bind(this);
this._eventTarget = {};
this._eventListenersQueue = [];
this.ui = new SourceEditorUI(this);
}
@ -143,14 +158,20 @@ SourceEditor.prototype = {
_model: null,
_undoStack: null,
_linesRuler: null,
_annotationRuler: null,
_overviewRuler: null,
_styler: null,
_annotationStyler: null,
_annotationModel: null,
_dragAndDrop: null,
_currentLineAnnotation: null,
_primarySelectionTimeout: null,
_mode: null,
_expandTab: null,
_tabSize: null,
_iframeWindow: null,
_eventTarget: null,
_eventListenersQueue: null,
/**
* The Source Editor user interface manager.
@ -171,30 +192,12 @@ SourceEditor.prototype = {
* @param nsIDOMElement aElement
* The DOM element where you want the editor to show.
* @param object aConfig
* Editor configuration object. Properties:
* - placeholderText - the text you want to be shown by default.
* - theme - the syntax highlighting theme you want. You can use one
* of the predefined themes, or you can point to your CSS file.
* - mode - the editor mode, based on the file type you want to edit.
* You can use one of the predefined modes.
* - tabSize - define how many spaces to use for a tab character.
* - expandTab - tells if you want tab characters to be expanded to
* spaces.
* - readOnly - make the editor read only.
* - showLineNumbers - display the line numbers gutter.
* - undoLimit - how many steps should the undo stack hold.
* - keys - is an array of objects that allows you to define custom
* editor keyboard bindings. Each object can have:
* - action - name of the editor action to invoke.
* - code - keyCode for the shortcut.
* - accel - boolean for the Accel key (cmd/ctrl).
* - shift - boolean for the Shift key.
* - alt - boolean for the Alt key.
* - callback - optional function to invoke, if the action is not
* predefined in the editor.
* Editor configuration object. See SourceEditor.DEFAULTS for the
* available configuration options.
* @param function [aCallback]
* Function you want to execute once the editor is loaded and
* initialized.
* @see SourceEditor.DEFAULTS
*/
init: function SE_init(aElement, aConfig, aCallback)
{
@ -218,7 +221,21 @@ SourceEditor.prototype = {
aElement.appendChild(this._iframe);
this.parentElement = aElement;
this._config = aConfig;
this._config = {};
for (let key in SourceEditor.DEFAULTS) {
this._config[key] = key in aConfig ?
aConfig[key] :
SourceEditor.DEFAULTS[key];
}
// TODO: Bug 725677 - Remove the deprecated placeholderText option from the
// Source Editor initialization.
if (aConfig.placeholderText) {
this._config.initialText = aConfig.placeholderText;
Services.console.logStringMessage("SourceEditor.init() was called with the placeholderText option which is deprecated, please use initialText.");
}
this._onReadyCallback = aCallback;
this.ui.init();
},
@ -238,14 +255,13 @@ SourceEditor.prototype = {
let TextModel = window.require("orion/textview/textModel").TextModel;
let TextView = window.require("orion/textview/textView").TextView;
this._expandTab = typeof config.expandTab != "undefined" ?
config.expandTab : SourceEditor.DEFAULTS.EXPAND_TAB;
this._tabSize = config.tabSize || SourceEditor.DEFAULTS.TAB_SIZE;
this._expandTab = config.expandTab;
this._tabSize = config.tabSize;
let theme = config.theme || SourceEditor.DEFAULTS.THEME;
let theme = config.theme;
let stylesheet = theme in ORION_THEMES ? ORION_THEMES[theme] : theme;
this._model = new TextModel(config.placeholderText);
this._model = new TextModel(config.initialText);
this._view = new TextView({
model: this._model,
parent: "editor",
@ -262,30 +278,64 @@ SourceEditor.prototype = {
}.bind(this);
this._view.addEventListener("Load", onOrionLoad);
if (Services.appinfo.OS == "Linux") {
if (config.highlightCurrentLine || Services.appinfo.OS == "Linux") {
this._view.addEventListener("Selection", this._onOrionSelection);
}
let KeyBinding = window.require("orion/textview/keyBinding").KeyBinding;
let TextDND = window.require("orion/textview/textDND").TextDND;
let LineNumberRuler = window.require("orion/textview/rulers").LineNumberRuler;
let Rulers = window.require("orion/textview/rulers");
let LineNumberRuler = Rulers.LineNumberRuler;
let AnnotationRuler = Rulers.AnnotationRuler;
let OverviewRuler = Rulers.OverviewRuler;
let UndoStack = window.require("orion/textview/undoStack").UndoStack;
let AnnotationModel = window.require("orion/textview/annotations").AnnotationModel;
this._annotationModel = new AnnotationModel(this._model);
if (config.showLineNumbers) {
this._linesRuler = new LineNumberRuler(this._annotationModel, "left",
{styleClass: "rulerLines"}, {styleClass: "rulerLine odd"},
{styleClass: "rulerLine even"});
if (config.showAnnotationRuler) {
this._annotationRuler = new AnnotationRuler(this._annotationModel, "left",
{styleClass: "ruler annotations"});
this._annotationRuler.onClick = this._annotationRulerClick.bind(this);
this._annotationRuler.addAnnotationType(ORION_ANNOTATION_TYPES.breakpoint);
this._annotationRuler.setMultiAnnotation({
html: "<div class='annotationHTML multiple'></div>"
});
this._annotationRuler.setMultiAnnotationOverlay({
html: "<div class='annotationHTML overlay'></div>"
});
this._view.addRuler(this._annotationRuler);
}
if (config.showLineNumbers) {
let rulerClass = this._annotationRuler ?
"ruler lines linesWithAnnotations" :
"ruler lines";
this._linesRuler = new LineNumberRuler(this._annotationModel, "left",
{styleClass: rulerClass}, {styleClass: "rulerLines odd"},
{styleClass: "rulerLines even"});
this._linesRuler.onClick = this._linesRulerClick.bind(this);
this._linesRuler.onDblClick = this._linesRulerDblClick.bind(this);
this._view.addRuler(this._linesRuler);
}
this.setMode(config.mode || SourceEditor.DEFAULTS.MODE);
if (config.showOverviewRuler) {
this._overviewRuler = new OverviewRuler(this._annotationModel, "right",
{styleClass: "ruler overview"});
this._overviewRuler.onClick = this._overviewRulerClick.bind(this);
this._undoStack = new UndoStack(this._view,
config.undoLimit || SourceEditor.DEFAULTS.UNDO_LIMIT);
this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.matchingBracket);
this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.currentBracket);
this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.breakpoint);
this._overviewRuler.addAnnotationType(ORION_ANNOTATION_TYPES.task);
this._view.addRuler(this._overviewRuler);
}
this.setMode(config.mode);
this._undoStack = new UndoStack(this._view, config.undoLimit);
this._dragAndDrop = new TextDND(this._view, this._undoStack);
@ -315,6 +365,43 @@ SourceEditor.prototype = {
this._view.setAction(aKey.action, aKey.callback);
}
}, this);
this._initEventTarget();
},
/**
* Initialize the private Orion EventTarget object. This is used for tracking
* our own event listeners for events outside of Orion's scope.
* @private
*/
_initEventTarget: function SE__initEventTarget()
{
let EventTarget =
this._iframeWindow.require("orion/textview/eventTarget").EventTarget;
EventTarget.addMixin(this._eventTarget);
this._eventListenersQueue.forEach(function(aRequest) {
if (aRequest[0] == "add") {
this.addEventListener(aRequest[1], aRequest[2]);
} else {
this.removeEventListener(aRequest[1], aRequest[2]);
}
}, this);
this._eventListenersQueue = [];
},
/**
* Dispatch an event to the SourceEditor event listeners. This covers only the
* SourceEditor-specific events.
*
* @private
* @param object aEvent
* The event object to dispatch to all listeners.
*/
_dispatchEvent: function SE__dispatchEvent(aEvent)
{
this._eventTarget.dispatchEvent(aEvent);
},
/**
@ -474,8 +561,9 @@ SourceEditor.prototype = {
},
/**
* Orion Selection event handler for the X Window System users. This allows
* one to select text and have it copied into the X11 PRIMARY.
* The Orion Selection event handler. The current caret line is
* highlighted and for Linux users the selected text is copied into the X11
* PRIMARY buffer.
*
* @private
* @param object aEvent
@ -483,7 +571,31 @@ SourceEditor.prototype = {
*/
_onOrionSelection: function SE__onOrionSelection(aEvent)
{
let text = this.getText(aEvent.newValue.start, aEvent.newValue.end);
if (this._config.highlightCurrentLine) {
this._highlightCurrentLine(aEvent);
}
if (Services.appinfo.OS == "Linux") {
let window = this.parentElement.ownerDocument.defaultView;
if (this._primarySelectionTimeout) {
window.clearTimeout(this._primarySelectionTimeout);
}
this._primarySelectionTimeout =
window.setTimeout(this._updatePrimarySelection.bind(this),
PRIMARY_SELECTION_DELAY);
}
},
/**
* Update the X11 PRIMARY buffer to hold the current selection.
* @private
*/
_updatePrimarySelection: function SE__updatePrimarySelection()
{
this._primarySelectionTimeout = null;
let text = this.getSelectedText();
if (!text) {
return;
}
@ -492,6 +604,213 @@ SourceEditor.prototype = {
Ci.nsIClipboard.kSelectionClipboard);
},
/**
* Highlight the current line using the Orion annotation model.
*
* @private
* @param object aEvent
* The Selection event object.
*/
_highlightCurrentLine: function SE__highlightCurrentLine(aEvent)
{
let annotationModel = this._annotationModel;
let model = this._model;
let oldAnnotation = this._currentLineAnnotation;
let newSelection = aEvent.newValue;
let collapsed = newSelection.start == newSelection.end;
if (!collapsed) {
if (oldAnnotation) {
annotationModel.removeAnnotation(oldAnnotation);
this._currentLineAnnotation = null;
}
return;
}
let line = model.getLineAtOffset(newSelection.start);
let lineStart = model.getLineStart(line);
let lineEnd = model.getLineEnd(line);
let title = oldAnnotation ? oldAnnotation.title :
SourceEditorUI.strings.GetStringFromName("annotation.currentLine");
this._currentLineAnnotation = {
start: lineStart,
end: lineEnd,
type: ORION_ANNOTATION_TYPES.currentLine,
title: title,
html: "<div class='annotationHTML currentLine'></div>",
overviewStyle: {styleClass: "annotationOverview currentLine"},
lineStyle: {styleClass: "annotationLine currentLine"},
};
annotationModel.replaceAnnotations(oldAnnotation ? [oldAnnotation] : null,
[this._currentLineAnnotation]);
},
/**
* The click event handler for the lines gutter. This function allows the user
* to jump to a line or to perform line selection while holding the Shift key
* down.
*
* @private
* @param number aLineIndex
* The line index where the click event occurred.
* @param object aEvent
* The DOM click event object.
*/
_linesRulerClick: function SE__linesRulerClick(aLineIndex, aEvent)
{
if (aLineIndex === undefined) {
return;
}
if (aEvent.shiftKey) {
let model = this._model;
let selection = this.getSelection();
let selectionLineStart = model.getLineAtOffset(selection.start);
let selectionLineEnd = model.getLineAtOffset(selection.end);
let newStart = aLineIndex <= selectionLineStart ?
model.getLineStart(aLineIndex) : selection.start;
let newEnd = aLineIndex <= selectionLineStart ?
selection.end : model.getLineEnd(aLineIndex);
this.setSelection(newStart, newEnd);
} else {
this.setCaretPosition(aLineIndex);
}
},
/**
* The dblclick event handler for the lines gutter. This function selects the
* whole line where the event occurred.
*
* @private
* @param number aLineIndex
* The line index where the double click event occurred.
* @param object aEvent
* The DOM dblclick event object.
*/
_linesRulerDblClick: function SE__linesRulerDblClick(aLineIndex)
{
if (aLineIndex === undefined) {
return;
}
let newStart = this._model.getLineStart(aLineIndex);
let newEnd = this._model.getLineEnd(aLineIndex);
this.setSelection(newStart, newEnd);
},
/**
* Highlight the Orion annotations. This updates the annotation styler as
* needed.
* @private
*/
_highlightAnnotations: function SE__highlightAnnotations()
{
if (this._annotationStyler) {
this._annotationStyler.destroy();
this._annotationStyler = null;
}
let AnnotationStyler =
this._iframeWindow.require("orion/textview/annotations").AnnotationStyler;
let styler = new AnnotationStyler(this._view, this._annotationModel);
this._annotationStyler = styler;
styler.addAnnotationType(ORION_ANNOTATION_TYPES.matchingBracket);
styler.addAnnotationType(ORION_ANNOTATION_TYPES.currentBracket);
styler.addAnnotationType(ORION_ANNOTATION_TYPES.task);
if (this._config.highlightCurrentLine) {
styler.addAnnotationType(ORION_ANNOTATION_TYPES.currentLine);
}
},
/**
* Retrieve the list of Orion Annotations filtered by type for the given text range.
*
* @private
* @param string aType
* The annotation type to filter annotations for.
* @param number aStart
* Offset from where to start finding the annotations.
* @param number aEnd
* End offset for retrieving the annotations.
* @return array
* The array of annotations, filtered by type, within the given text
* range.
*/
_getAnnotationsByType: function SE__getAnnotationsByType(aType, aStart, aEnd)
{
let annotations = this._annotationModel.getAnnotations(aStart, aEnd);
let annotation, result = [];
while (annotation = annotations.next()) {
if (annotation.type == ORION_ANNOTATION_TYPES[aType]) {
result.push(annotation);
}
}
return result;
},
/**
* The click event handler for the annotation ruler.
*
* @private
* @param number aLineIndex
* The line index where the click event occurred.
* @param object aEvent
* The DOM click event object.
*/
_annotationRulerClick: function SE__annotationRulerClick(aLineIndex, aEvent)
{
if (aLineIndex === undefined || aLineIndex == -1) {
return;
}
let lineStart = this._model.getLineStart(aLineIndex);
let lineEnd = this._model.getLineEnd(aLineIndex);
let annotations = this._getAnnotationsByType("breakpoint", lineStart, lineEnd);
if (annotations.length > 0) {
this.removeBreakpoint(aLineIndex);
} else {
this.addBreakpoint(aLineIndex);
}
},
/**
* The click event handler for the overview ruler. When the user clicks on an
* annotation the editor jumps to the associated line.
*
* @private
* @param number aLineIndex
* The line index where the click event occurred.
* @param object aEvent
* The DOM click event object.
*/
_overviewRulerClick: function SE__overviewRulerClick(aLineIndex, aEvent)
{
if (aLineIndex === undefined || aLineIndex == -1) {
return;
}
let model = this._model;
let lineStart = model.getLineStart(aLineIndex);
let lineEnd = model.getLineEnd(aLineIndex);
let annotations = this._annotationModel.getAnnotations(lineStart, lineEnd);
let annotation = annotations.next();
// Jump to the line where annotation is. If the annotation is specific to
// a substring part of the line, then select the substring.
if (!annotation || lineStart == annotation.start && lineEnd == annotation.end) {
this.setSelection(lineStart, lineStart);
} else {
this.setSelection(annotation.start, annotation.end);
}
},
/**
* Get the editor element.
*
@ -512,14 +831,14 @@ SourceEditor.prototype = {
* @param function aCallback
* The function you want executed when the event is triggered.
*/
addEventListener:
function SE_addEventListener(aEventType, aCallback)
addEventListener: function SE_addEventListener(aEventType, aCallback)
{
if (aEventType in ORION_EVENTS) {
if (this._view && aEventType in ORION_EVENTS) {
this._view.addEventListener(ORION_EVENTS[aEventType], aCallback);
} else if (this._eventTarget.addEventListener) {
this._eventTarget.addEventListener(aEventType, aCallback);
} else {
throw new Error("SourceEditor.addEventListener() unknown event " +
"type " + aEventType);
this._eventListenersQueue.push(["add", aEventType, aCallback]);
}
},
@ -534,14 +853,14 @@ SourceEditor.prototype = {
* @param function aCallback
* The function you have as the event handler.
*/
removeEventListener:
function SE_removeEventListener(aEventType, aCallback)
removeEventListener: function SE_removeEventListener(aEventType, aCallback)
{
if (aEventType in ORION_EVENTS) {
if (this._view && aEventType in ORION_EVENTS) {
this._view.removeEventListener(ORION_EVENTS[aEventType], aCallback);
} else if (this._eventTarget.removeEventListener) {
this._eventTarget.removeEventListener(aEventType, aCallback);
} else {
throw new Error("SourceEditor.removeEventListener() unknown event " +
"type " + aEventType);
this._eventListenersQueue.push(["remove", aEventType, aCallback]);
}
},
@ -550,7 +869,7 @@ SourceEditor.prototype = {
*/
undo: function SE_undo()
{
this._undoStack.undo();
return this._undoStack.undo();
},
/**
@ -558,7 +877,7 @@ SourceEditor.prototype = {
*/
redo: function SE_redo()
{
this._undoStack.redo();
return this._undoStack.redo();
},
/**
@ -841,10 +1160,6 @@ SourceEditor.prototype = {
this._styler.destroy();
this._styler = null;
}
if (this._annotationStyler) {
this._annotationStyler.destroy();
this._annotationStyler = null;
}
let window = this._iframeWindow;
@ -856,17 +1171,6 @@ SourceEditor.prototype = {
this._styler = new TextStyler(this._view, aMode, this._annotationModel);
this._styler.setFoldingEnabled(false);
this._styler.setHighlightCaretLine(true);
let AnnotationStyler =
window.require("orion/textview/annotations").AnnotationStyler;
this._annotationStyler =
new AnnotationStyler(this._view, this._annotationModel);
this._annotationStyler.
addAnnotationType(ORION_ANNOTATION_TYPES.matchingBracket);
this._annotationStyler.
addAnnotationType(ORION_ANNOTATION_TYPES.currentBracket);
break;
case SourceEditor.MODES.HTML:
@ -875,10 +1179,11 @@ SourceEditor.prototype = {
window.require("orion/editor/textMateStyler").TextMateStyler;
let HtmlGrammar =
window.require("orion/editor/htmlGrammar").HtmlGrammar;
this._styler = new TextMateStyler(this._view, new HtmlGrammar().grammar);
this._styler = new TextMateStyler(this._view, new HtmlGrammar());
break;
}
this._highlightAnnotations();
this._mode = aMode;
},
@ -915,16 +1220,122 @@ SourceEditor.prototype = {
return this._view.getOptions("readonly");
},
/**
* Add a breakpoint at the given line index.
*
* @param number aLineIndex
* Line index where to add the breakpoint (starts from 0).
* @param string [aCondition]
* Optional breakpoint condition.
*/
addBreakpoint: function SE_addBreakpoint(aLineIndex, aCondition)
{
let lineStart = this._model.getLineStart(aLineIndex);
let lineEnd = this._model.getLineEnd(aLineIndex);
let annotations = this._getAnnotationsByType("breakpoint", lineStart, lineEnd);
if (annotations.length > 0) {
return;
}
let lineText = this._model.getLine(aLineIndex);
let title = SourceEditorUI.strings.
formatStringFromName("annotation.breakpoint.title",
[lineText], 1);
let annotation = {
type: ORION_ANNOTATION_TYPES.breakpoint,
start: lineStart,
end: lineEnd,
breakpointCondition: aCondition,
title: title,
style: {styleClass: "annotation breakpoint"},
html: "<div class='annotationHTML breakpoint'></div>",
overviewStyle: {styleClass: "annotationOverview breakpoint"},
rangeStyle: {styleClass: "annotationRange breakpoint"}
};
this._annotationModel.addAnnotation(annotation);
let event = {
type: SourceEditor.EVENTS.BREAKPOINT_CHANGE,
added: [{line: aLineIndex, condition: aCondition}],
removed: [],
};
this._dispatchEvent(event);
},
/**
* Remove the current breakpoint from the given line index.
*
* @param number aLineIndex
* Line index from where to remove the breakpoint (starts from 0).
* @return boolean
* True if a breakpoint was removed, false otherwise.
*/
removeBreakpoint: function SE_removeBreakpoint(aLineIndex)
{
let lineStart = this._model.getLineStart(aLineIndex);
let lineEnd = this._model.getLineEnd(aLineIndex);
let event = {
type: SourceEditor.EVENTS.BREAKPOINT_CHANGE,
added: [],
removed: [],
};
let annotations = this._getAnnotationsByType("breakpoint", lineStart, lineEnd);
annotations.forEach(function(annotation) {
this._annotationModel.removeAnnotation(annotation);
event.removed.push({line: aLineIndex,
condition: annotation.breakpointCondition});
}, this);
if (event.removed.length > 0) {
this._dispatchEvent(event);
}
return event.removed.length > 0;
},
/**
* Get the list of breakpoints in the Source Editor instance.
*
* @return array
* The array of breakpoints. Each item is an object with two
* properties: line and condition.
*/
getBreakpoints: function SE_getBreakpoints()
{
let annotations = this._getAnnotationsByType("breakpoint", 0,
this.getCharCount());
let breakpoints = [];
annotations.forEach(function(annotation) {
breakpoints.push({line: this._model.getLineAtOffset(annotation.start),
condition: annotation.breakpointCondition});
}, this);
return breakpoints;
},
/**
* Destroy/uninitialize the editor.
*/
destroy: function SE_destroy()
{
if (Services.appinfo.OS == "Linux") {
if (this._config.highlightCurrentLine || Services.appinfo.OS == "Linux") {
this._view.removeEventListener("Selection", this._onOrionSelection);
}
this._onOrionSelection = null;
if (this._primarySelectionTimeout) {
let window = this.parentElement.ownerDocument.defaultView;
window.clearTimeout(this._primarySelectionTimeout);
this._primarySelectionTimeout = null;
}
this._view.destroy();
this.ui.destroy();
this.ui = null;
@ -936,9 +1347,14 @@ SourceEditor.prototype = {
this._undoStack = null;
this._styler = null;
this._linesRuler = null;
this._annotationRuler = null;
this._overviewRuler = null;
this._dragAndDrop = null;
this._annotationModel = null;
this._annotationStyler = null;
this._currentLineAnnotation = null;
this._eventTarget = null;
this._eventListenersQueue = null;
this._view = null;
this._model = null;
this._config = null;

Просмотреть файл

@ -106,13 +106,99 @@ SourceEditor.THEMES = {
/**
* Source editor configuration defaults.
* @see SourceEditor.init
*/
SourceEditor.DEFAULTS = {
MODE: SourceEditor.MODES.TEXT,
THEME: SourceEditor.THEMES.MOZILLA,
UNDO_LIMIT: 200,
TAB_SIZE: 4, // overriden by pref
EXPAND_TAB: true, // overriden by pref
/**
* The text you want shown when the editor opens up.
* @type string
*/
initialText: "",
/**
* The editor mode, based on the file type you want to edit. You can use one of
* the predefined modes.
*
* @see SourceEditor.MODES
* @type string
*/
mode: SourceEditor.MODES.TEXT,
/**
* The syntax highlighting theme you want. You can use one of the predefined
* themes, or you can point to your CSS file.
*
* @see SourceEditor.THEMES.
* @type string
*/
theme: SourceEditor.THEMES.MOZILLA,
/**
* How many steps should the undo stack hold.
* @type number
*/
undoLimit: 200,
/**
* Define how many spaces to use for a tab character. This value is overridden
* by a user preference, see SourceEditor.PREFS.TAB_SIZE.
*
* @type number
*/
tabSize: 4,
/**
* Tells if you want tab characters to be expanded to spaces. This value is
* overridden by a user preference, see SourceEditor.PREFS.EXPAND_TAB.
* @type boolean
*/
expandTab: true,
/**
* Tells if you want the editor to be read only or not.
* @type boolean
*/
readOnly: false,
/**
* Display the line numbers gutter.
* @type boolean
*/
showLineNumbers: false,
/**
* Display the annotations gutter/ruler. This gutter currently supports
* annotations of breakpoint type.
* @type boolean
*/
showAnnotationRuler: false,
/**
* Display the overview gutter/ruler. This gutter presents an overview of the
* current annotations in the editor, for example the breakpoints.
* @type boolean
*/
showOverviewRuler: false,
/**
* Highlight the current line.
* @type boolean
*/
highlightCurrentLine: true,
/**
* An array of objects that allows you to define custom editor keyboard
* bindings. Each object can have:
* - action - name of the editor action to invoke.
* - code - keyCode for the shortcut.
* - accel - boolean for the Accel key (Cmd on Macs, Ctrl on Linux/Windows).
* - shift - boolean for the Shift key.
* - alt - boolean for the Alt key.
* - callback - optional function to invoke, if the action is not predefined
* in the editor.
* @type array
*/
keys: null,
};
/**
@ -185,6 +271,17 @@ SourceEditor.EVENTS = {
* - x and y - the mouse coordinates relative to the document being edited.
*/
MOUSE_OUT: "MouseOut",
/**
* The BreakpointChange event is fired when a new breakpoint is added or when
* a breakpoint is removed - either through API use or through the editor UI.
* Event object properties:
* - added - array that holds the new breakpoints.
* - removed - array that holds the breakpoints that have been removed.
* Each object in the added/removed arrays holds two properties: line and
* condition.
*/
BREAKPOINT_CHANGE: "BreakpointChange",
};
/**

Просмотреть файл

@ -56,6 +56,8 @@ _BROWSER_TEST_FILES = \
browser_bug650345_find.js \
browser_bug703692_focus_blur.js \
browser_bug725388_mouse_events.js \
browser_bug707987_debugger_breakpoints.js \
browser_bug712982_line_ruler_click.js \
head.js \
libs:: $(_BROWSER_TEST_FILES)

Просмотреть файл

@ -48,7 +48,7 @@ function initEditor()
let config = {
showLineNumbers: true,
placeholderText: text,
initialText: text,
};
editor = new SourceEditor();

Просмотреть файл

@ -0,0 +1,169 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
function test() {
let temp = {};
Cu.import("resource:///modules/source-editor.jsm", temp);
let SourceEditor = temp.SourceEditor;
let component = Services.prefs.getCharPref(SourceEditor.PREFS.COMPONENT);
if (component == "textarea") {
ok(true, "skip test for bug 707987: only applicable for non-textarea components");
return;
}
waitForExplicitFinish();
let editor;
const windowUrl = "data:text/xml,<?xml version='1.0'?>" +
"<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
" title='test for bug 707987' width='600' height='500'><hbox flex='1'/></window>";
const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
let testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null);
testWin.addEventListener("load", function onWindowLoad() {
testWin.removeEventListener("load", onWindowLoad, false);
waitForFocus(initEditor, testWin);
}, false);
function initEditor()
{
let hbox = testWin.document.querySelector("hbox");
editor = new SourceEditor();
editor.init(hbox, {showAnnotationRuler: true}, editorLoaded);
}
function editorLoaded()
{
editor.focus();
editor.setText("line1\nline2\nline3\nline4");
is(editor.getBreakpoints().length, 0, "no breakpoints");
let event = null;
let eventHandler = function(aEvent) {
event = aEvent;
};
editor.addEventListener(SourceEditor.EVENTS.BREAKPOINT_CHANGE, eventHandler);
// Add breakpoint at line 0
editor.addBreakpoint(0);
let breakpoints = editor.getBreakpoints();
is(breakpoints.length, 1, "one breakpoint added");
is(breakpoints[0].line, 0, "breakpoint[0].line is correct");
ok(!breakpoints[0].condition, "breakpoint[0].condition is correct");
ok(event, "breakpoint event fired");
is(event.added.length, 1, "one breakpoint added (confirmed)");
is(event.removed.length, 0, "no breakpoint removed");
is(event.added[0].line, 0, "event added[0].line is correct");
ok(!event.added[0].condition, "event added[0].condition is correct");
// Add breakpoint at line 3
event = null;
editor.addBreakpoint(3, "foo == 'bar'");
breakpoints = editor.getBreakpoints();
is(breakpoints.length, 2, "another breakpoint added");
is(breakpoints[0].line, 0, "breakpoint[0].line is correct");
ok(!breakpoints[0].condition, "breakpoint[0].condition is correct");
is(breakpoints[1].line, 3, "breakpoint[1].line is correct");
is(breakpoints[1].condition, "foo == 'bar'",
"breakpoint[1].condition is correct");
ok(event, "breakpoint event fired");
is(event.added.length, 1, "another breakpoint added (confirmed)");
is(event.removed.length, 0, "no breakpoint removed");
is(event.added[0].line, 3, "event added[0].line is correct");
is(event.added[0].condition, "foo == 'bar'",
"event added[0].condition is correct");
// Try to add another breakpoint at line 0
event = null;
editor.addBreakpoint(0);
is(editor.getBreakpoints().length, 2, "no breakpoint added");
is(event, null, "no breakpoint event fired");
// Try to remove a breakpoint from line 1
is(editor.removeBreakpoint(1), false, "removeBreakpoint(1) returns false");
is(editor.getBreakpoints().length, 2, "no breakpoint removed");
is(event, null, "no breakpoint event fired");
// Remove the breakpoint from line 0
is(editor.removeBreakpoint(0), true, "removeBreakpoint(0) returns true");
breakpoints = editor.getBreakpoints();
is(breakpoints[0].line, 3, "breakpoint[0].line is correct");
is(breakpoints[0].condition, "foo == 'bar'",
"breakpoint[0].condition is correct");
ok(event, "breakpoint event fired");
is(event.added.length, 0, "no breakpoint added");
is(event.removed.length, 1, "one breakpoint removed");
is(event.removed[0].line, 0, "event removed[0].line is correct");
ok(!event.removed[0].condition, "event removed[0].condition is correct");
// Remove the breakpoint from line 3
event = null;
is(editor.removeBreakpoint(3), true, "removeBreakpoint(3) returns true");
is(editor.getBreakpoints().length, 0, "no breakpoints");
ok(event, "breakpoint event fired");
is(event.added.length, 0, "no breakpoint added");
is(event.removed.length, 1, "one breakpoint removed");
is(event.removed[0].line, 3, "event removed[0].line is correct");
is(event.removed[0].condition, "foo == 'bar'",
"event removed[0].condition is correct");
// Add a breakpoint with the mouse
event = null;
EventUtils.synthesizeMouse(editor.editorElement, 10, 10, {}, testWin);
breakpoints = editor.getBreakpoints();
is(breakpoints.length, 1, "one breakpoint added");
is(breakpoints[0].line, 0, "breakpoint[0].line is correct");
ok(!breakpoints[0].condition, "breakpoint[0].condition is correct");
ok(event, "breakpoint event fired");
is(event.added.length, 1, "one breakpoint added (confirmed)");
is(event.removed.length, 0, "no breakpoint removed");
is(event.added[0].line, 0, "event added[0].line is correct");
ok(!event.added[0].condition, "event added[0].condition is correct");
// Remove a breakpoint with the mouse
event = null;
EventUtils.synthesizeMouse(editor.editorElement, 10, 10, {}, testWin);
breakpoints = editor.getBreakpoints();
is(breakpoints.length, 0, "one breakpoint removed");
ok(event, "breakpoint event fired");
is(event.added.length, 0, "no breakpoint added");
is(event.removed.length, 1, "one breakpoint removed (confirmed)");
is(event.removed[0].line, 0, "event removed[0].line is correct");
ok(!event.removed[0].condition, "event removed[0].condition is correct");
editor.destroy();
testWin.close();
testWin = editor = null;
waitForFocus(finish, window);
}
}

Просмотреть файл

@ -0,0 +1,74 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
function test() {
let temp = {};
Cu.import("resource:///modules/source-editor.jsm", temp);
let SourceEditor = temp.SourceEditor;
let component = Services.prefs.getCharPref(SourceEditor.PREFS.COMPONENT);
if (component == "textarea") {
ok(true, "skip test for bug 712982: only applicable for non-textarea components");
return;
}
waitForExplicitFinish();
let editor;
const windowUrl = "data:text/xml,<?xml version='1.0'?>" +
"<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
" title='test for bug 712982' width='600' height='500'><hbox flex='1'/></window>";
const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
let testWin = Services.ww.openWindow(null, windowUrl, "_blank", windowFeatures, null);
testWin.addEventListener("load", function onWindowLoad() {
testWin.removeEventListener("load", onWindowLoad, false);
waitForFocus(initEditor, testWin);
}, false);
function initEditor()
{
let hbox = testWin.document.querySelector("hbox");
editor = new SourceEditor();
editor.init(hbox, {showLineNumbers: true}, editorLoaded);
}
function editorLoaded()
{
editor.focus();
editor.setText("line1\nline2\nline3\nline4");
editor.setCaretPosition(3);
let pos = editor.getCaretPosition();
ok(pos.line == 3 && pos.col == 0, "initial caret location is correct");
EventUtils.synthesizeMouse(editor.editorElement, 10, 10, {}, testWin);
is(editor.getCaretOffset(), 0, "click on line 0 worked");
editor.setCaretPosition(2);
EventUtils.synthesizeMouse(editor.editorElement, 11, 11,
{shiftKey: true}, testWin);
is(editor.getSelectedText().trim(), "line1\nline2", "shift+click works");
editor.setCaretOffset(0);
EventUtils.synthesizeMouse(editor.editorElement, 10, 10,
{clickCount: 2}, testWin);
is(editor.getSelectedText().trim(), "line1", "double click works");
editor.destroy();
testWin.close();
testWin = editor = null;
waitForFocus(finish, window);
}
}

Просмотреть файл

@ -37,22 +37,30 @@ function initEditor()
function editorLoaded()
{
editor.focus();
testWin.resizeBy(1, 2);
let text = "BrowserBug - 725388";
editor.setText(text);
let target = editor.editorElement;
let targetWin = target.ownerDocument.defaultView;
let eventsFired = 0;
let done = function() {
eventsFired++;
if (eventsFired == 3) {
executeSoon(testEnd);
}
};
let mMoveHandler = function(aEvent) {
editor.removeEventListener(SourceEditor.EVENTS.MOUSE_MOVE, mMoveHandler);
is(aEvent.event.type, "mousemove", "MouseMove event fired.");
editor.addEventListener(SourceEditor.EVENTS.MOUSE_OVER, mOverHandler);
waitForFocus(function() {
EventUtils.synthesizeMouse(target, 10, 10, {type: "mouseover"},
targetWin);
});
executeSoon(done);
};
let mOverHandler = function(aEvent) {
@ -60,26 +68,28 @@ function editorLoaded()
is(aEvent.event.type, "mouseover", "MouseOver event fired.");
editor.addEventListener(SourceEditor.EVENTS.MOUSE_OUT, mOutHandler);
waitForFocus(function() {
EventUtils.synthesizeMouse(target, -10, -10, {type: "mouseout"},
targetWin);
}, targetWin);
executeSoon(done);
};
let mOutHandler = function(aEvent) {
editor.removeEventListener(SourceEditor.EVENTS.MOUSE_OUT, mOutHandler);
is(aEvent.event.type, "mouseout", "MouseOut event fired.");
executeSoon(testEnd);
executeSoon(done);
};
editor.addEventListener(SourceEditor.EVENTS.MOUSE_OVER, mOverHandler);
editor.addEventListener(SourceEditor.EVENTS.MOUSE_MOVE, mMoveHandler);
editor.addEventListener(SourceEditor.EVENTS.MOUSE_OUT, mOutHandler);
editor.focus();
waitForFocus(function() {
EventUtils.synthesizeMouse(target, 1, 1, {type: "mousemove"},
targetWin);
EventUtils.synthesizeMouse(target, 10, 10, {type: "mouseover"},
targetWin);
EventUtils.synthesizeMouse(target, 15, 17, {type: "mousemove"},
targetWin);
EventUtils.synthesizeMouse(target, -10, -10, {type: "mouseout"},
targetWin);
}, targetWin);
}

Просмотреть файл

@ -37,7 +37,7 @@ function initEditor()
editor = new SourceEditor();
let config = {
showLineNumbers: true,
placeholderText: "foobarbaz",
initialText: "foobarbaz",
tabSize: 7,
expandTab: true,
};
@ -54,7 +54,7 @@ function editorLoaded()
editor.focus();
is(editor.getMode(), SourceEditor.DEFAULTS.MODE, "default editor mode");
is(editor.getMode(), SourceEditor.DEFAULTS.mode, "default editor mode");
// Test general editing methods.

Просмотреть файл

@ -222,7 +222,7 @@ StyleEditor.prototype = {
let sourceEditor = new SourceEditor();
let config = {
placeholderText: this._state.text, //! this is initialText (bug 680371)
initialText: this._state.text,
showLineNumbers: true,
mode: SourceEditor.MODES.CSS,
readOnly: this._state.readOnly,

Просмотреть файл

@ -121,6 +121,18 @@
<!ENTITY browserContext.label "Browser">
<!ENTITY browserContext.accesskey "B">
<!-- LOCALIZATION NOTE some localizations of Windows (ex:french, german) use "?"
- for the help button in the menubar but Gnome does not.
-->
<!ENTITY helpMenu.label "Help">
<!ENTITY helpMenu.accesskey "H">
<!ENTITY helpMenuWin.label "Help">
<!ENTITY helpMenuWin.accesskey "H">
<!ENTITY documentationLink.label "Scratchpad Help on MDN">
<!ENTITY documentationLink.accesskey "D">
<!-- LOCALIZATION NOTE (resetContext2.label): This command allows the developer
- to reset/clear the global object of the environment where the code executes.
-->

Просмотреть файл

@ -54,3 +54,7 @@ scratchpadIntro=/*\n * This is a JavaScript Scratchpad.\n *\n * Enter some JavaS
# LOCALIZATION NOTE (notification.browserContext): This is the message displayed
# over the top of the editor when the user has switched to browser context.
browserContext.notification=This scratchpad executes in the Browser context.
# LOCALIZATION NOTE (help.openDocumentationPage): This returns a localized link with
# documentation for Scratchpad on MDN.
help.openDocumentationPage=https://developer.mozilla.org/en/Tools/Scratchpad

Просмотреть файл

@ -28,3 +28,13 @@ gotoLineCmd.promptTitle=Go to line…
# the user wants to jump to a specific line number in the code. You can
# access this feature by pressing Ctrl-J on Windows/Linux or Cmd-J on Mac.
gotoLineCmd.promptMessage=Jump to line number:
# LOCALIZATION NOTE (annotation.breakpoint.title): This is the text shown in
# front of any breakpoint annotation when it is displayed as a tooltip in one of
# the editor gutters. This feature is used in the JavaScript Debugger.
annotation.breakpoint.title=Breakpoint: %S
# LOCALIZATION NOTE (annotation.currentLine): This is the text shown in
# a tooltip displayed in any of the editor gutters when the user hovers the
# current line.
annotation.currentLine=Current line

Двоичные данные
browser/themes/gnomestripe/devtools/orion-breakpoint.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 626 B

Просмотреть файл

@ -0,0 +1,39 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
.viewTooltip {
display: none; /* TODO: add tooltips support, see bug 721752 */
font-family: monospace;
font-size: 13px;
background-color: InfoBackground;
color: InfoText;
padding: 2px;
border-radius: 4px;
border: 1px solid black;
z-index: 100;
position: fixed;
overflow: hidden;
white-space: pre;
}
.viewTooltip em {
font-style: normal;
font-weight: bold;
}
.annotationHTML {
cursor: pointer;
width: 16px;
height: 16px;
display: inline-block;
vertical-align: middle;
background-position: center;
background-repeat: no-repeat;
}
.annotationHTML.task {
background-image: url("chrome://browser/skin/devtools/orion-task.png");
}
.annotationHTML.breakpoint {
background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
}

Двоичные данные
browser/themes/gnomestripe/devtools/orion-task.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 413 B

Просмотреть файл

@ -11,28 +11,93 @@
.view {
color: black; /* Default text color */
background: #f0f0ff; /* Background of the editor */
padding-left: 0;
padding-left: 4px;
}
.readonly > .view {
background: #f0f0ff;
}
/* One line */
.viewContent > div {
padding-left: 4px; /* Margin between the ruler and the editor */
}
/* Styles for the line number ruler */
.rulerLines {
border-right: 1px solid #b4c4d3;
.ruler {
background: #cddae5;
color: #7a8a99;
}
.ruler.annotations {
width: 16px;
padding-left: 4px;
}
.ruler.lines {
border-right: 1px solid #b4c4d3;
min-width: 1.4em;
padding-left: 4px;
padding-right: 4px;
text-align: end;
}
.ruler.linesWithAnnotations {
min-width: 0;
padding-left: 0;
}
.ruler.overview {
border-left: 1px solid #b4c4d3;
width: 14px;
text-align: start;
}
/* Styles for the annotation ruler (first line) */
.annotationHTML {
cursor: pointer;
width: 16px;
height: 16px;
display: inline-block;
vertical-align: middle;
background-position: center;
background-repeat: no-repeat;
}
.annotationHTML.task {
background-image: url("chrome://browser/skin/devtools/orion-task.png");
}
.annotationHTML.breakpoint {
background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
}
/* Styles for the overview ruler */
.annotationOverview {
cursor: pointer;
border-radius: 2px;
left: 2px;
width: 8px;
}
.annotationOverview.task {
background-color: lightgreen;
border: 1px solid green;
}
.annotationOverview.breakpoint {
background-color: lightblue;
border: 1px solid blue;
}
.annotationOverview.currentBracket {
background-color: lightgray;
border: 1px solid red;
}
.annotationOverview.matchingBracket {
background-color: lightgray;
border: 1px solid red;
}
/* Styles for text range */
.annotationRange {
background-repeat: repeat-x;
background-position: left bottom;
}
.annotationRange.task {
outline: 1px dashed rgba(0, 255, 0, 0.5);
}
.annotationRange.matchingBracket {
outline: 1px solid grey;
}
.token_singleline_comment {
color: #45a946; /* green */
}
@ -81,11 +146,13 @@
background-position: left center;
}
.line_caret { /* Current line */
.line_caret,
.annotationLine.currentLine { /* Current line */
background: #dae2ee; /* lighter than the background */
}
.readonly .line_caret {
.readonly .line_caret,
.readonly .annotationLine.currentLine {
background: #cddae5; /* a bit darker than the background */
}
@ -115,7 +182,3 @@
color: red;
font-weight: bold;
}
.annotationRange.matchingBracket {
outline: 1px solid grey;
}

Просмотреть файл

@ -95,6 +95,9 @@ browser.jar:
skin/classic/browser/devtools/webconsole.png (devtools/webconsole.png)
skin/classic/browser/devtools/gcli.css (devtools/gcli.css)
skin/classic/browser/devtools/orion.css (devtools/orion.css)
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
skin/classic/browser/devtools/breadcrumbs/ltr-end-pressed.png (devtools/breadcrumbs/ltr-end-pressed.png)
skin/classic/browser/devtools/breadcrumbs/ltr-end-selected-pressed.png (devtools/breadcrumbs/ltr-end-selected-pressed.png)
skin/classic/browser/devtools/breadcrumbs/ltr-end-selected.png (devtools/breadcrumbs/ltr-end-selected.png)

Двоичные данные
browser/themes/pinstripe/devtools/orion-breakpoint.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 626 B

Просмотреть файл

@ -0,0 +1,39 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
.viewTooltip {
display: none; /* TODO: add tooltips support, see bug 721752 */
font-family: monospace;
font-size: 13px;
background-color: InfoBackground;
color: InfoText;
padding: 2px;
border-radius: 4px;
border: 1px solid black;
z-index: 100;
position: fixed;
overflow: hidden;
white-space: pre;
}
.viewTooltip em {
font-style: normal;
font-weight: bold;
}
.annotationHTML {
cursor: pointer;
width: 16px;
height: 16px;
display: inline-block;
vertical-align: middle;
background-position: center;
background-repeat: no-repeat;
}
.annotationHTML.task {
background-image: url("chrome://browser/skin/devtools/orion-task.png");
}
.annotationHTML.breakpoint {
background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
}

Двоичные данные
browser/themes/pinstripe/devtools/orion-task.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 413 B

Просмотреть файл

@ -11,28 +11,93 @@
.view {
color: black; /* Default text color */
background: #f0f0ff; /* Background of the editor */
padding-left: 0;
padding-left: 4px;
}
.readonly > .view {
background: #f0f0ff;
}
/* One line */
.viewContent > div {
padding-left: 4px; /* Margin between the ruler and the editor */
}
/* Styles for the line number ruler */
.rulerLines {
border-right: 1px solid #b4c4d3;
.ruler {
background: #cddae5;
color: #7a8a99;
}
.ruler.annotations {
width: 16px;
padding-left: 4px;
}
.ruler.lines {
border-right: 1px solid #b4c4d3;
min-width: 1.4em;
padding-left: 4px;
padding-right: 4px;
text-align: end;
}
.ruler.linesWithAnnotations {
min-width: 0;
padding-left: 0;
}
.ruler.overview {
border-left: 1px solid #b4c4d3;
width: 14px;
text-align: start;
}
/* Styles for the annotation ruler (first line) */
.annotationHTML {
cursor: pointer;
width: 16px;
height: 16px;
display: inline-block;
vertical-align: middle;
background-position: center;
background-repeat: no-repeat;
}
.annotationHTML.task {
background-image: url("chrome://browser/skin/devtools/orion-task.png");
}
.annotationHTML.breakpoint {
background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
}
/* Styles for the overview ruler */
.annotationOverview {
cursor: pointer;
border-radius: 2px;
left: 2px;
width: 8px;
}
.annotationOverview.task {
background-color: lightgreen;
border: 1px solid green;
}
.annotationOverview.breakpoint {
background-color: lightblue;
border: 1px solid blue;
}
.annotationOverview.currentBracket {
background-color: lightgray;
border: 1px solid red;
}
.annotationOverview.matchingBracket {
background-color: lightgray;
border: 1px solid red;
}
/* Styles for text range */
.annotationRange {
background-repeat: repeat-x;
background-position: left bottom;
}
.annotationRange.task {
outline: 1px dashed rgba(0, 255, 0, 0.5);
}
.annotationRange.matchingBracket {
outline: 1px solid grey;
}
.token_singleline_comment {
color: #45a946; /* green */
}
@ -81,11 +146,13 @@
background-position: left center;
}
.line_caret { /* Current line */
.line_caret,
.annotationLine.currentLine { /* Current line */
background: #dae2ee; /* lighter than the background */
}
.readonly .line_caret {
.readonly .line_caret,
.readonly .annotationLine.currentLine {
background: #cddae5; /* a bit darker than the background */
}
@ -115,7 +182,3 @@
color: red;
font-weight: bold;
}
.annotationRange.matchingBracket {
outline: 1px solid grey;
}

Просмотреть файл

@ -131,6 +131,9 @@ browser.jar:
skin/classic/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
skin/classic/browser/devtools/gcli.css (devtools/gcli.css)
skin/classic/browser/devtools/orion.css (devtools/orion.css)
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
skin/classic/browser/devtools/toolbarbutton-close.png (devtools/toolbarbutton-close.png)
* skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
skin/classic/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)

Двоичные данные
browser/themes/winstripe/devtools/orion-breakpoint.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 626 B

Просмотреть файл

@ -0,0 +1,39 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
.viewTooltip {
display: none; /* TODO: add tooltips support, see bug 721752 */
font-family: monospace;
font-size: 13px;
background-color: InfoBackground;
color: InfoText;
padding: 2px;
border-radius: 4px;
border: 1px solid black;
z-index: 100;
position: fixed;
overflow: hidden;
white-space: pre;
}
.viewTooltip em {
font-style: normal;
font-weight: bold;
}
.annotationHTML {
cursor: pointer;
width: 16px;
height: 16px;
display: inline-block;
vertical-align: middle;
background-position: center;
background-repeat: no-repeat;
}
.annotationHTML.task {
background-image: url("chrome://browser/skin/devtools/orion-task.png");
}
.annotationHTML.breakpoint {
background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
}

Двоичные данные
browser/themes/winstripe/devtools/orion-task.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 413 B

Просмотреть файл

@ -11,28 +11,93 @@
.view {
color: black; /* Default text color */
background: #f0f0ff; /* Background of the editor */
padding-left: 0;
padding-left: 4px;
}
.readonly > .view {
background: #f0f0ff;
}
/* One line */
.viewContent > div {
padding-left: 4px; /* Margin between the ruler and the editor */
}
/* Styles for the line number ruler */
.rulerLines {
border-right: 1px solid #b4c4d3;
.ruler {
background: #cddae5;
color: #7a8a99;
}
.ruler.annotations {
width: 16px;
padding-left: 4px;
}
.ruler.lines {
border-right: 1px solid #b4c4d3;
min-width: 1.4em;
padding-left: 4px;
padding-right: 4px;
text-align: end;
}
.ruler.linesWithAnnotations {
min-width: 0;
padding-left: 0;
}
.ruler.overview {
border-left: 1px solid #b4c4d3;
width: 14px;
text-align: start;
}
/* Styles for the annotation ruler (first line) */
.annotationHTML {
cursor: pointer;
width: 16px;
height: 16px;
display: inline-block;
vertical-align: middle;
background-position: center;
background-repeat: no-repeat;
}
.annotationHTML.task {
background-image: url("chrome://browser/skin/devtools/orion-task.png");
}
.annotationHTML.breakpoint {
background-image: url("chrome://browser/skin/devtools/orion-breakpoint.png");
}
/* Styles for the overview ruler */
.annotationOverview {
cursor: pointer;
border-radius: 2px;
left: 2px;
width: 8px;
}
.annotationOverview.task {
background-color: lightgreen;
border: 1px solid green;
}
.annotationOverview.breakpoint {
background-color: lightblue;
border: 1px solid blue;
}
.annotationOverview.currentBracket {
background-color: lightgray;
border: 1px solid red;
}
.annotationOverview.matchingBracket {
background-color: lightgray;
border: 1px solid red;
}
/* Styles for text range */
.annotationRange {
background-repeat: repeat-x;
background-position: left bottom;
}
.annotationRange.task {
outline: 1px dashed rgba(0, 255, 0, 0.5);
}
.annotationRange.matchingBracket {
outline: 1px solid grey;
}
.token_singleline_comment {
color: #45a946; /* green */
}
@ -81,11 +146,13 @@
background-position: left center;
}
.line_caret { /* Current line */
.line_caret,
.annotationLine.currentLine { /* Current line */
background: #dae2ee; /* lighter than the background */
}
.readonly .line_caret {
.readonly .line_caret,
.readonly .annotationLine.currentLine {
background: #cddae5; /* a bit darker than the background */
}
@ -115,7 +182,3 @@
color: red;
font-weight: bold;
}
.annotationRange.matchingBracket {
outline: 1px solid grey;
}

Просмотреть файл

@ -116,6 +116,9 @@ browser.jar:
skin/classic/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
skin/classic/browser/devtools/gcli.css (devtools/gcli.css)
skin/classic/browser/devtools/orion.css (devtools/orion.css)
skin/classic/browser/devtools/orion-container.css (devtools/orion-container.css)
skin/classic/browser/devtools/orion-task.png (devtools/orion-task.png)
skin/classic/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
skin/classic/browser/devtools/toolbarbutton-close.png (devtools/toolbarbutton-close.png)
skin/classic/browser/devtools/webconsole.css (devtools/webconsole.css)
skin/classic/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)
@ -282,6 +285,9 @@ browser.jar:
skin/classic/aero/browser/devtools/csshtmltree.css (devtools/csshtmltree.css)
skin/classic/aero/browser/devtools/gcli.css (devtools/gcli.css)
skin/classic/aero/browser/devtools/orion.css (devtools/orion.css)
skin/classic/aero/browser/devtools/orion-container.css (devtools/orion-container.css)
skin/classic/aero/browser/devtools/orion-task.png (devtools/orion-task.png)
skin/classic/aero/browser/devtools/orion-breakpoint.png (devtools/orion-breakpoint.png)
skin/classic/aero/browser/devtools/toolbarbutton-close.png (devtools/toolbarbutton-close.png)
skin/classic/aero/browser/devtools/webconsole.css (devtools/webconsole.css)
skin/classic/aero/browser/devtools/webconsole_networkpanel.css (devtools/webconsole_networkpanel.css)

Просмотреть файл

@ -63,7 +63,7 @@ var step1 =function() {
// Navigate down and up.
is(testWindow.document.body.scrollTop, 0,
"Page1: Ensure we scrollpane is at the top before we start scrolling.");
"Page1: Ensure the scrollpane is at the top before we start scrolling.");
testWindow.addEventListener("scroll", function () {
testWindow.removeEventListener("scroll", arguments.callee, true);
isnot(testWindow.document.body.scrollTop, 0,
@ -91,11 +91,11 @@ var step2 =function() {
// Scroll around a bit.
is(testWindow.document.body.scrollTop, 0,
"Page2: Ensure we scrollpane is at the top before we start scrolling.");
"Page2: Ensure the scrollpane is at the top before we start scrolling.");
var count = 0;
testWindow.addEventListener("scroll", function () {
if (++count < 4) {
if (++count < 2) {
SimpleTest.executeSoon(function () { sendKey('DOWN', testWindow); });
} else {
testWindow.removeEventListener("scroll", arguments.callee, true);

Просмотреть файл

@ -1321,6 +1321,7 @@ nsGlobalWindow::FreeInnerObjects(bool aClearScope)
// Remove our reference to the document and the document principal.
mDocument = nsnull;
mDoc = nsnull;
mFocusedNode = nsnull;
if (mApplicationCache) {
static_cast<nsDOMOfflineResourceList*>(mApplicationCache.get())->Disconnect();
@ -2389,6 +2390,7 @@ nsGlobalWindow::InnerSetNewDocument(nsIDocument* aDocument)
mDocument = do_QueryInterface(aDocument);
mDoc = aDocument;
mFocusedNode = nsnull;
mLocalStorage = nsnull;
mSessionStorage = nsnull;
@ -2450,6 +2452,7 @@ nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
// Release our document reference
mDocument = nsnull;
mDoc = nsnull;
mFocusedNode = nsnull;
}
if (mContext) {
@ -7751,9 +7754,16 @@ nsGlobalWindow::SetFocusedNode(nsIContent* aNode,
{
FORWARD_TO_INNER_VOID(SetFocusedNode, (aNode, aFocusMethod, aNeedsFocus));
NS_ASSERTION(!aNode || aNode->GetCurrentDoc() == mDoc,
"setting focus to a node from the wrong document");
if (aNode && aNode->GetCurrentDoc() != mDoc) {
NS_WARNING("Trying to set focus to a node from a wrong document");
return;
}
if (mCleanedUp) {
NS_ASSERTION(!aNode, "Trying to focus cleaned up window!");
aNode = nsnull;
aNeedsFocus = false;
}
if (mFocusedNode != aNode) {
UpdateCanvasFocus(false, aNode);
mFocusedNode = aNode;
@ -7857,6 +7867,10 @@ nsGlobalWindow::TakeFocus(bool aFocus, PRUint32 aFocusMethod)
{
FORWARD_TO_INNER(TakeFocus, (aFocus, aFocusMethod), false);
if (mCleanedUp) {
return false;
}
if (aFocus)
mFocusMethod = aFocusMethod & FOCUSMETHOD_MASK;

Просмотреть файл

@ -241,7 +241,7 @@ var WifiManager = (function() {
}
function setScanModeCommand(setActive, callback) {
sScanModeActive = setActive;
scanModeActive = setActive;
doSetScanModeCommand(setActive, callback);
}
@ -737,7 +737,7 @@ var WifiManager = (function() {
manager.getNetworkConfiguration = function(config, callback) {
var netId = config.netId;
var done = 0;
for (var n = 0; n < networkConfigurationFields; ++n) {
for (var n = 0; n < networkConfigurationFields.length; ++n) {
var fieldName = networkConfigurationFields[n];
getNetworkVariableCommand(netId, fieldName, function(value) {
config[fieldName] = value;
@ -833,6 +833,10 @@ var WifiManager = (function() {
}
manager.getMacAddress = getMacAddressCommand;
manager.getScanResults = scanResultsCommand;
manager.setScanMode = function(mode, callback) {
setScanModeCommand(mode === "active", callback);
}
manager.scan = scanCommand;
return manager;
})();
@ -865,22 +869,18 @@ function nsWifiWorker() {
self.state = this.state;
// TODO Worth adding a more generic API for this?
if (self.state === "INACTIVE" && connectToMozilla.waiting)
if (self.state === "INACTIVE")
connectToMozilla();
}
function connectToMozilla() {
if (self.state !== "INACTIVE") {
connectToMozilla.waiting = true;
return;
}
// We're not trying to connect so try to find an open Mozilla network.
// TODO Don't do this for pre-existing networks.
// TODO Remove me in favor of UI and a way to select a network.
debug("Haven't connected to a network, trying a default (for now)");
var configs = [
{ "ssid": '"mozilla demo"', "key_mgmt": "NONE", "disabled": 0 },
{ "ssid": '"mozilla demo"', "key_mgmt": "NONE", "scan_ssid": 1, "disabled": 0 },
{ "ssid": '"Mozilla"', "key_mgmt": "NONE", "disabled": 0 },
{ "ssid": '"Mozilla Guest"', "key_mgmt": "NONE", "scan_ssid": 1, "disabled": 0 },
];
@ -897,15 +897,21 @@ function nsWifiWorker() {
addThem();
return;
}
// Some drivers might not automatically start scanning. In that case,
// we need to give them a hint.
WifiManager.scan(false, function(){});
});
}
addThem();
}
this.waitForScan(connectToMozilla);
WifiManager.onscanresultsavailable = function() {
debug("Scan results are available! Asking for them.");
WifiManager.getScanResults(function(r) {
// Now that we have scan results, there's no more need to continue
// scanning. Ignore any errors from this command.
WifiManager.setScanMode("inactive", function() {});
let lines = r.split("\n");
// NB: Skip the header line.
for (let i = 1; i < lines.length; ++i) {

Просмотреть файл

@ -2469,8 +2469,8 @@ PresShell::ScrollLine(bool aForward)
nsIScrollableFrame* scrollFrame =
GetFrameToScrollAsScrollable(nsIPresShell::eVertical);
if (scrollFrame) {
// Scroll 2 lines at a time to improve scrolling speed.
PRInt32 lineCount = 2;
PRInt32 lineCount = Preferences::GetInt("toolkit.scrollbox.verticalScrollDistance",
NS_DEFAULT_VERTICAL_SCROLL_DISTANCE);
scrollFrame->ScrollBy(nsIntPoint(0, aForward ? lineCount : -lineCount),
nsIScrollableFrame::LINES,
nsIScrollableFrame::SMOOTH);

Просмотреть файл

@ -3255,7 +3255,8 @@ nsGfxScrollFrameInner::ReflowFinished()
nsPoint scrollPos = GetScrollPosition();
// XXX shouldn't we use GetPageScrollAmount/GetLineScrollAmount here?
if (vScroll) {
const double kScrollMultiplier = 3;
const double kScrollMultiplier = Preferences::GetInt("toolkit.scrollbox.verticalScrollDistance",
NS_DEFAULT_VERTICAL_SCROLL_DISTANCE);
nscoord fontHeight = GetLineScrollAmount().height * kScrollMultiplier;
// We normally use (scrollArea.height - fontHeight) for height
// of page scrolling. However, it is too small when

Просмотреть файл

@ -47,6 +47,8 @@
#include "nsPresContext.h"
#include "nsIFrame.h" // to get nsIBox, which is a typedef
#define NS_DEFAULT_VERTICAL_SCROLL_DISTANCE 3
class nsBoxLayoutState;
class nsIScrollPositionListener;

Просмотреть файл

@ -297,6 +297,8 @@ pref("toolkit.autocomplete.richBoundaryCutoff", 200);
pref("toolkit.scrollbox.smoothScroll", true);
pref("toolkit.scrollbox.scrollIncrement", 20);
// Make sure to update NS_DEFAULT_VERTICAL_SCROLL_DISTANCE if changing this default.
pref("toolkit.scrollbox.verticalScrollDistance", 3);
pref("toolkit.scrollbox.clickToScroll.scrollDelay", 150);
// Telemetry

Просмотреть файл

@ -1 +1 @@
http://hg.mozilla.org/projects/addon-sdk/archive/c4a695618bf8.tar.bz2
http://hg.mozilla.org/projects/addon-sdk/archive/0aef86102e9d.tar.bz2

Просмотреть файл

@ -81,6 +81,9 @@ NS_IMPL_ISUPPORTS5(nsFormFillController,
nsIMutationObserver)
nsFormFillController::nsFormFillController() :
mFocusedInput(nsnull),
mFocusedInputNode(nsnull),
mListNode(nsnull),
mTimeout(50),
mMinResultsForPopup(1),
mMaxRows(0),
@ -96,8 +99,28 @@ nsFormFillController::nsFormFillController() :
mPwmgrInputs.Init();
}
struct PwmgrInputsEnumData
{
PwmgrInputsEnumData(nsIMutationObserver* aMutationObserver, nsIDocument* aDoc)
: mMutationObserver(aMutationObserver), mDoc(aDoc) {}
nsIMutationObserver* mMutationObserver;
nsCOMPtr<nsIDocument> mDoc;
};
nsFormFillController::~nsFormFillController()
{
PwmgrInputsEnumData ed(this, nsnull);
mPwmgrInputs.Enumerate(RemoveForDocumentEnumerator, &ed);
if (mListNode) {
mListNode->RemoveMutationObserver(this);
mListNode = nsnull;
}
if (mFocusedInputNode) {
mFocusedInputNode->RemoveMutationObserver(this);
mFocusedInputNode = nsnull;
mFocusedInput = nsnull;
}
// Remove ourselves as a focus listener from all cached docShells
PRUint32 count;
mDocShells->Count(&count);
@ -119,7 +142,9 @@ nsFormFillController::AttributeChanged(nsIDocument* aDocument,
PRInt32 aNameSpaceID,
nsIAtom* aAttribute, PRInt32 aModType)
{
RevalidateDataList();
if (mListNode && mListNode->Contains(aElement)) {
RevalidateDataList();
}
}
void
@ -128,7 +153,9 @@ nsFormFillController::ContentAppended(nsIDocument* aDocument,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
RevalidateDataList();
if (mListNode && mListNode->Contains(aContainer)) {
RevalidateDataList();
}
}
void
@ -137,7 +164,9 @@ nsFormFillController::ContentInserted(nsIDocument* aDocument,
nsIContent* aChild,
PRInt32 aIndexInContainer)
{
RevalidateDataList();
if (mListNode && mListNode->Contains(aContainer)) {
RevalidateDataList();
}
}
void
@ -147,7 +176,9 @@ nsFormFillController::ContentRemoved(nsIDocument* aDocument,
PRInt32 aIndexInContainer,
nsIContent* aPreviousSibling)
{
RevalidateDataList();
if (mListNode && mListNode->Contains(aContainer)) {
RevalidateDataList();
}
}
void
@ -180,6 +211,14 @@ nsFormFillController::ParentChainChanged(nsIContent* aContent)
void
nsFormFillController::NodeWillBeDestroyed(const nsINode* aNode)
{
mPwmgrInputs.Remove(aNode);
if (aNode == mListNode) {
mListNode = nsnull;
RevalidateDataList();
} else if (aNode == mFocusedInputNode) {
mFocusedInputNode = nsnull;
mFocusedInput = nsnull;
}
}
////////////////////////////////////////////////////////////////////////
@ -229,7 +268,10 @@ nsFormFillController::MarkAsLoginManagerField(nsIDOMHTMLInputElement *aInput)
* autocomplete. The form manager also checks for this tag when saving
* form history (so it doesn't save usernames).
*/
mPwmgrInputs.Put(aInput, 1);
nsCOMPtr<nsINode> node = do_QueryInterface(aInput);
NS_ENSURE_STATE(node);
mPwmgrInputs.Put(node, true);
node->AddMutationObserverUnlessExists(this);
if (!mLoginManager)
mLoginManager = do_GetService("@mozilla.org/login-manager;1");
@ -564,8 +606,8 @@ nsFormFillController::StartSearch(const nsAString &aSearchString, const nsAStrin
// If the login manager has indicated it's responsible for this field, let it
// handle the autocomplete. Otherwise, handle with form history.
PRInt32 dummy;
if (mPwmgrInputs.Get(mFocusedInput, &dummy)) {
bool dummy;
if (mPwmgrInputs.Get(mFocusedInputNode, &dummy)) {
// XXX aPreviousResult shouldn't ever be a historyResult type, since we're not letting
// satchel manage the field?
rv = mLoginManager->AutoCompleteSearch(aSearchString,
@ -609,8 +651,15 @@ nsFormFillController::StartSearch(const nsAString &aSearchString, const nsAStrin
mFocusedInput->GetList(getter_AddRefs(list));
nsCOMPtr<nsINode> node = do_QueryInterface(list);
if(node) {
node->AddMutationObserverUnlessExists(this);
if (mListNode != node) {
if (mListNode) {
mListNode->RemoveMutationObserver(this);
mListNode = nsnull;
}
if (node) {
node->AddMutationObserverUnlessExists(this);
mListNode = node;
}
}
}
}
@ -647,6 +696,9 @@ private:
void nsFormFillController::RevalidateDataList()
{
if (!mLastListener) {
return;
}
nsresult rv;
nsCOMPtr <nsIInputListAutoComplete> inputListAutoComplete =
do_GetService("@mozilla.org/satchel/inputlist-autocomplete;1", &rv);
@ -728,7 +780,9 @@ nsFormFillController::HandleEvent(nsIDOMEvent* aEvent)
StopControllingInput();
}
mPwmgrInputs.Enumerate(RemoveForDOMDocumentEnumerator, domDoc);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
PwmgrInputsEnumData ed(this, doc);
mPwmgrInputs.Enumerate(RemoveForDocumentEnumerator, &ed);
}
return NS_OK;
@ -736,17 +790,15 @@ nsFormFillController::HandleEvent(nsIDOMEvent* aEvent)
/* static */ PLDHashOperator
nsFormFillController::RemoveForDOMDocumentEnumerator(nsISupports* aKey,
PRInt32& aEntry,
nsFormFillController::RemoveForDocumentEnumerator(const nsINode* aKey,
bool& aEntry,
void* aUserData)
{
nsIDOMDocument* domDoc = static_cast<nsIDOMDocument*>(aUserData);
nsCOMPtr<nsIDOMHTMLInputElement> element = do_QueryInterface(aKey);
nsCOMPtr<nsIDOMDocument> elementDoc;
element->GetOwnerDocument(getter_AddRefs(elementDoc));
if (elementDoc == domDoc)
PwmgrInputsEnumData* ed = static_cast<PwmgrInputsEnumData*>(aUserData);
if (aKey && (!ed->mDoc || aKey->OwnerDoc() == ed->mDoc)) {
const_cast<nsINode*>(aKey)->RemoveMutationObserver(ed->mMutationObserver);
return PL_DHASH_REMOVE;
}
return PL_DHASH_NEXT;
}
@ -757,7 +809,8 @@ nsFormFillController::Focus(nsIDOMEvent* aEvent)
aEvent->GetTarget(getter_AddRefs(target));
nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(target);
if (!input)
nsCOMPtr<nsINode> inputNode = do_QueryInterface(input);
if (!inputNode)
return NS_OK;
bool isReadOnly = false;
@ -769,9 +822,9 @@ nsFormFillController::Focus(nsIDOMEvent* aEvent)
input->GetList(getter_AddRefs(datalist));
bool hasList = datalist != nsnull;
PRInt32 dummy;
bool dummy;
bool isPwmgrInput = false;
if (mPwmgrInputs.Get(input, &dummy))
if (mPwmgrInputs.Get(inputNode, &dummy))
isPwmgrInput = true;
nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(input);
@ -949,7 +1002,9 @@ nsFormFillController::RemoveWindowListeners(nsIDOMWindow *aWindow)
nsCOMPtr<nsIDOMDocument> domDoc;
aWindow->GetDocument(getter_AddRefs(domDoc));
mPwmgrInputs.Enumerate(RemoveForDOMDocumentEnumerator, domDoc);
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
PwmgrInputsEnumData ed(this, doc);
mPwmgrInputs.Enumerate(RemoveForDocumentEnumerator, &ed);
nsCOMPtr<nsPIDOMWindow> privateDOMWindow(do_QueryInterface(aWindow));
nsIDOMEventTarget* target = nsnull;
@ -1008,9 +1063,25 @@ nsFormFillController::StartControllingInput(nsIDOMHTMLInputElement *aInput)
// Cache the popup for the focused docShell
mPopups->GetElementAt(index, getter_AddRefs(mFocusedPopup));
nsCOMPtr<nsINode> node = do_QueryInterface(aInput);
if (!node) {
return;
}
AddKeyListener(aInput);
node->AddMutationObserverUnlessExists(this);
mFocusedInputNode = node;
mFocusedInput = aInput;
nsCOMPtr<nsIDOMHTMLElement> list;
mFocusedInput->GetList(getter_AddRefs(list));
nsCOMPtr<nsINode> listNode = do_QueryInterface(list);
if (listNode) {
listNode->AddMutationObserverUnlessExists(this);
mListNode = listNode;
}
// Now we are the autocomplete controller's bitch
mController->SetInput(this);
}
@ -1020,14 +1091,9 @@ nsFormFillController::StopControllingInput()
{
RemoveKeyListener();
if(mFocusedInput) {
nsCOMPtr<nsIDOMHTMLElement> list;
mFocusedInput->GetList(getter_AddRefs(list));
nsCOMPtr<nsINode> node = do_QueryInterface(list);
if (node) {
node->RemoveMutationObserver(this);
}
if (mListNode) {
mListNode->RemoveMutationObserver(this);
mListNode = nsnull;
}
// Reset the controller's input, but not if it has been switched
@ -1038,7 +1104,11 @@ nsFormFillController::StopControllingInput()
if (input == this)
mController->SetInput(nsnull);
mFocusedInput = nsnull;
if (mFocusedInputNode) {
mFocusedInputNode->RemoveMutationObserver(this);
mFocusedInputNode = nsnull;
mFocusedInput = nsnull;
}
mFocusedPopup = nsnull;
}

Просмотреть файл

@ -61,6 +61,7 @@
#endif
class nsFormHistory;
class nsINode;
class nsFormFillController : public nsIFormFillController,
public nsIAutoCompleteInput,
@ -100,15 +101,17 @@ protected:
inline nsIDOMWindow *GetWindowForDocShell(nsIDocShell *aDocShell);
inline PRInt32 GetIndexOfDocShell(nsIDocShell *aDocShell);
static PLDHashOperator RemoveForDOMDocumentEnumerator(nsISupports* aKey,
PRInt32& aEntry,
void* aUserData);
static PLDHashOperator RemoveForDocumentEnumerator(const nsINode* aKey,
bool& aEntry,
void* aUserData);
bool IsEventTrusted(nsIDOMEvent *aEvent);
// members //////////////////////////////////////////
nsCOMPtr<nsIAutoCompleteController> mController;
nsCOMPtr<nsILoginManager> mLoginManager;
nsCOMPtr<nsIDOMHTMLInputElement> mFocusedInput;
nsIDOMHTMLInputElement* mFocusedInput;
nsINode* mFocusedInputNode;
nsINode* mListNode;
nsCOMPtr<nsIAutoCompletePopup> mFocusedPopup;
nsCOMPtr<nsISupportsArray> mDocShells;
@ -119,7 +122,7 @@ protected:
nsCOMPtr<nsIAutoCompleteObserver> mLastListener;
nsString mLastSearchString;
nsDataHashtable<nsISupportsHashKey,PRInt32> mPwmgrInputs;
nsDataHashtable<nsPtrHashKey<const nsINode>, bool> mPwmgrInputs;
PRUint32 mTimeout;
PRUint32 mMinResultsForPopup;