Bug 712982 - can't select line by clicking the line number in scratchpad; r=rcampbell
authorMihai Sucan <mihai.sucan@gmail.com>
Mon, 20 Feb 2012 19:13:19 +0200
changeset 87417 fc23d6e176c85499fb27836a0d789fef539dd1f1
parent 87416 aa44ffe9db743478cadd542c4d596eb001df62dd
child 87418 ac5158b80fdfc08a9a4c0c323ccd77eee75b3a82
push id22115
push userrcampbell@mozilla.com
push dateWed, 22 Feb 2012 16:47:35 +0000
treeherdermozilla-central@4f425ab85667 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrcampbell
bugs712982
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 712982 - can't select line by clicking the line number in scratchpad; r=rcampbell
browser/devtools/sourceeditor/source-editor-orion.jsm
browser/devtools/sourceeditor/test/Makefile.in
browser/devtools/sourceeditor/test/browser_bug712982_line_ruler_click.js
--- a/browser/devtools/sourceeditor/source-editor-orion.jsm
+++ b/browser/devtools/sourceeditor/source-editor-orion.jsm
@@ -302,16 +302,18 @@ SourceEditor.prototype = {
       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);
     }
 
     if (config.showOverviewRuler) {
       this._overviewRuler = new OverviewRuler(this._annotationModel, "right",
         {styleClass: "ruler overview"});
       this._overviewRuler.onClick = this._overviewRulerClick.bind(this);
 
@@ -615,16 +617,69 @@ SourceEditor.prototype = {
       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();
--- a/browser/devtools/sourceeditor/test/Makefile.in
+++ b/browser/devtools/sourceeditor/test/Makefile.in
@@ -52,12 +52,13 @@ include $(topsrcdir)/config/rules.mk
 		browser_bug687580_drag_and_drop.js \
 		browser_bug684546_reset_undo.js \
 		browser_bug695035_middle_click_paste.js \
 		browser_bug687160_line_api.js \
 		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)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/devtools/sourceeditor/test/browser_bug712982_line_ruler_click.js
@@ -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);
+  }
+}