Bug 729480 - Link to rule in Style Editor should show the relevant line at the top of the editor's viewport; r=msucan f=msucan

This commit is contained in:
Girish Sharma 2012-03-11 11:50:01 +02:00
parent 8ad767dea2
commit 7a55e54453
4 changed files with 168 additions and 2 deletions

View File

@ -24,6 +24,7 @@
* Kenny Heaton <kennyheaton@gmail.com>
* Spyros Livathinos <livathinos.spyros@gmail.com>
* Allen Eubank <adeubank@gmail.com>
* Girish Sharma <scrapmachines@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -63,6 +64,14 @@ const ORION_IFRAME = "data:text/html;charset=utf8,<!DOCTYPE html>" +
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
/**
* Maximum allowed vertical offset for the line index when you call
* SourceEditor.setCaretPosition().
*
* @type number
*/
const VERTICAL_OFFSET = 3;
/**
* The primary selection update delay. On Linux, the X11 primary selection is
* updated to hold the currently selected text.
@ -1325,10 +1334,56 @@ SourceEditor.prototype = {
* The new caret line location. Line numbers start from 0.
* @param number [aColumn=0]
* Optional. The new caret column location. Columns start from 0.
* @param number [aAlign=0]
* Optional. Position of the line with respect to viewport.
* Allowed values are:
* SourceEditor.VERTICAL_ALIGN.TOP target line at top of view.
* SourceEditor.VERTICAL_ALIGN.CENTER target line at center of view.
* SourceEditor.VERTICAL_ALIGN.BOTTOM target line at bottom of view.
*/
setCaretPosition: function SE_setCaretPosition(aLine, aColumn)
setCaretPosition: function SE_setCaretPosition(aLine, aColumn, aAlign)
{
this.setCaretOffset(this._model.getLineStart(aLine) + (aColumn || 0));
let editorHeight = this._view.getClientArea().height;
let lineHeight = this._view.getLineHeight();
let linesVisible = Math.floor(editorHeight/lineHeight);
let halfVisible = Math.round(linesVisible/2);
let firstVisible = this.getTopIndex();
let lastVisible = this._view.getBottomIndex();
let caretOffset = this._model.getLineStart(aLine) + (aColumn || 0);
this._view.setSelection(caretOffset, caretOffset, false);
// If the target line is in view, skip the vertical alignment part.
if (aLine <= lastVisible && aLine >= firstVisible) {
this._view.showSelection();
return;
}
// Setting the offset so that the line always falls in the upper half
// of visible lines (lower half for BOTTOM aligned).
// VERTICAL_OFFSET is the maximum allowed value.
let offset = Math.min(halfVisible, VERTICAL_OFFSET);
let topIndex;
switch (aAlign) {
case this.VERTICAL_ALIGN.CENTER:
topIndex = Math.max(aLine - halfVisible, 0);
break;
case this.VERTICAL_ALIGN.BOTTOM:
topIndex = Math.max(aLine - linesVisible + offset, 0);
break;
default: // this.VERTICAL_ALIGN.TOP.
topIndex = Math.max(aLine - offset, 0);
break;
}
// Bringing down the topIndex to total lines in the editor if exceeding.
topIndex = Math.min(topIndex, this.getLineCount());
this.setTopIndex(topIndex);
let location = this._view.getLocationAtOffset(caretOffset);
this._view.setHorizontalPixel(location.x);
},
/**

View File

@ -312,6 +312,16 @@ SourceEditor.EVENTS = {
DIRTY_CHANGED: "DirtyChanged",
};
/**
* Allowed vertical alignment options for the line index
* when you call SourceEditor.setCaretPosition().
*/
SourceEditor.VERTICAL_ALIGN = {
TOP: 0,
CENTER: 1,
BOTTOM: 2,
};
/**
* Extend a destination object with properties from a source object.
*
@ -336,6 +346,7 @@ extend(SourceEditor.prototype, {
MODES: SourceEditor.MODES,
THEMES: SourceEditor.THEMES,
DEFAULTS: SourceEditor.DEFAULTS,
VERTICAL_ALIGN: SourceEditor.VERTICAL_ALIGN,
_lastFind: null,

View File

@ -60,6 +60,7 @@ _BROWSER_TEST_FILES = \
browser_bug712982_line_ruler_click.js \
browser_bug725618_moveLines_shortcut.js \
browser_bug700893_dirty_state.js \
browser_bug729480_line_vertical_align.js \
head.js \
libs:: $(_BROWSER_TEST_FILES)

View File

@ -0,0 +1,99 @@
/* 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";
let tempScope = {};
Cu.import("resource:///modules/source-editor.jsm", tempScope);
let SourceEditor = tempScope.SourceEditor;
let testWin;
let editor;
const VERTICAL_OFFSET = 3;
function test()
{
waitForExplicitFinish();
const windowUrl = "data:application/vnd.mozilla.xul+xml,<?xml version='1.0'?>" +
"<window xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul'" +
" title='test for bug 729480 - allow setCaretPosition align the target line" +
" vertically in view according to a third argument'" +
" width='300' height='300'><box flex='1'/></window>";
const windowFeatures = "chrome,titlebar,toolbar,centerscreen,dialog=no";
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 box = testWin.document.querySelector("box");
editor = new SourceEditor();
editor.init(box, {showLineNumbers: true}, editorLoaded);
}
function editorLoaded()
{
editor.focus();
// setting 3 pages of lines containing the line number.
let view = editor._view;
let lineHeight = view.getLineHeight();
let editorHeight = view.getClientArea().height;
let linesPerPage = Math.floor(editorHeight / lineHeight);
let totalLines = 3 * linesPerPage;
let text = "";
for (let i = 0; i < totalLines; i++) {
text += "Line " + i + "\n";
}
editor.setText(text);
editor.setCaretOffset(0);
let offset = Math.min(Math.round(linesPerPage/2), VERTICAL_OFFSET);
// Building the iterator array.
// [line, alignment, topIndex_check]
let iterateOn = [
[0, "TOP", 0],
[25, "TOP", 25 - offset],
// Case when the target line is already in view.
[27, "TOP", 25 - offset],
[0, "BOTTOM", 0],
[5, "BOTTOM", 0],
[38, "BOTTOM", 38 - linesPerPage + offset],
[0, "CENTER", 0],
[4, "CENTER", 0],
[34, "CENTER", 34 - Math.round(linesPerPage/2)]
];
function testEnd() {
editor.destroy();
testWin.close();
testWin = editor = null;
waitForFocus(finish, window);
}
function testPosition(pos) {
is(editor.getTopIndex(), iterateOn[pos][2], "scroll is correct for test #" + pos);
iterator(++pos);
}
function iterator(i) {
if (i == iterateOn.length) {
testEnd();
} else {
editor.setCaretPosition(iterateOn[i][0], 0,
editor.VERTICAL_ALIGN[iterateOn[i][1]]);
executeSoon(testPosition.bind(this, i));
}
}
iterator(0);
}