たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。
の動向はもえじら組ブログで。
宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能!
Page 1/1: 1
英語で書かれた障害報告のメールに返信する時にルーラーがひどくずれていたのが気になってたけど放置してた件について、ルーラーバー 0.3.2008120101で修正した。
今まで、ルーラーの表示サイズの基準には編集領域のdocument.documentElement
のfont-size
を使ってたけど、こちらはエンコーディングが変わっても値が変化しない。それに対して、document.body
のfont-size
は、エンコーディングごとのフォントサイズの違いの影響を受ける。ということでbodyの方の値を参照するようにしたら、ルーラーの間隔はおおむね正しいものになるようになった。
ただ、これでもカーソル位置の強調表示のずれは残る。フォントサイズだけでなくフォント自体もエンコーディングによって変わる可能性があり、フォントサイズだけ合わせても、実際の編集領域とカーソル位置検出用の非表示のフレームとでフォントが違ったら、ピクセル単位で位置を拾った時に微妙にずれが発生する可能性がある。そこで、非表示のフレームの方にもエンコーディングの変化を適用させるために、SetDocumentCharacterSet()
のタイミングで非表示のフレームの方のエンコーディングも変更するようにした。エンコーディングの動的な変更の方法はこんな感じ。
// this.calculator は非表示のフレームのbrowser要素
var docCharset = this.calculator.docShell
.QueryInterface(Components.interfaces.nsIDocCharset);
docCharset.charset = aCharset;
var webNav = this.calculator.webNavigation;
webNav.reload(webNav.LOAD_FLAGS_CHARSET_CHANGE);
var self = this;
this.calculator.addEventListener('DOMContentLoaded', function() {
self.calculator.removeEventListener('DOMContentLoaded', arguments.callee, false);
// 読み込みが終わった段階でルーラーの表示を更新する(カーソル位置の検出をやり直す)
self.updateRulerAppearance();
}, false);
最後にリロードしないと表示が変わらない、のかな?(リロードしなかった場合の挙動については未検証)
Ruler Bar更新した。結局、今までのやり方はほとんど全部うっちゃって、ピクセル単位で位置合わせするようにした。
ピクセル単位で現在のカーソル位置を取得するには、カーソル位置=長さ0の選択範囲の位置に何かダミーの要素を挿入して、その要素の画面上でのX座標を取得すればいい。ただ、メール本文の編集中にこれをやると、場合によっては再描画とかノードがブツ切りにされまくるとかでかなり怖いことになるんじゃないだろうかという心配があったり、そもそもテキストノードの切断を伴うような処理をやると選択範囲が失われる(=カーソルが一時的に消える)のでその復活のための処理が面倒だったり、といくつかの理由があってこの方法を採るのをずっとためらってた。
でも上手い解決方法を思いついたので、今回この方法に切り替えることにした。
種を明かすと、非表示のフレームを一つ用意しておいて、編集中のメール本文のうちカーソルがある段落の箇所だけをその隠しフレームに複製して、そっちでテキストノードの切断を伴うような処理をやってる。フォントや文字の大きさ、body要素の幅などを合わせてやれば、そこで起こる折り返しは基本的に本物と全く同じ結果になるはずなので。編集されるのは複製の方で、しかもカーソル前後の段落だけ抜き出したものだから、ノードを切り刻んでも再描画のコストは最低限で済んでる……と思う。
ルーラバーだとやっぱり行ったことのある場所に行くあの呪文しか思い浮かばないという声があったので、日本語名をルーラーバーに変えた。
そのルーラーバーなんだけど、Rulerrrrrでもあった「折り返された次の行の先頭にカーソルがある時や行末にカーソルがある時にルーラー上の現在位置表示がおかしくなる(カーソル位置の計算に失敗する)問題」に真面目に取り組んで、0.2.2008101101でだいぶ改善した。
ルーラーバーもRulerrrrrも、現在のカーソルの位置を計算するのには選択範囲を使っている。FirefoxやThunderbirdではカーソル位置をJavaScriptから直接取得することはできないんだけど、現在カーソルがある位置は長さ0の選択範囲として取得できるので、選択範囲が含まれているノードとか選択範囲の開始・終了位置などからどうにかこうにかして「カーソルより前に何文字あるか」を数えて、カーソル位置を割り出している。
行末にカーソルがある時にカーソル位置が0(行頭)と判定されてしまっていたのは、この選択範囲から選択範囲が含まれているノードを取得できないせい。どういう事かというと、行末にカーソルがある状態というのは「テキストノード」「改行のBR要素」「テキストノード」という順番にノードが並んでいてBR要素の直前に長さ0のRangeがあるという状態で、「選択範囲が含まれているノード」は前後の要素やテキストノードではなくいきなりBODY要素になってしまう、ということでカーソル位置の求めようがなくなっていた。
そこで、TreeWalkerを使って各行のテキストノードやBR要素を走査し、compareBoundaryPoints()
でそのノードがカーソルに隣接しているかどうかを調べる、という風な処理を入れてみた。これにより、行末にカーソルがある時でもカーソルより前にある文字を数えられるようになった。
折り返された行の処理はもうちょっと厄介だった。普通に考えたら、「カーソル位置より前の文字数÷折り返し文字数 の余り」でカーソルの現在位置が分かるはずなんだけど、実際にはこれだけじゃダメだった。FirefoxやThunderbirdのエディタ機能では、折り返された行の行末にカーソルがある時に右キーを押すと、次の文字(折り返された次の行の先頭文字)の後の位置にカーソルが移動するのではなく、次の文字の前・仮想的な改行文字の後にカーソルが移動してしまう。折り返された後の行頭で左キーを押した時も同様。なので、いくら文字数ベースで計算しても、今「折り返された行の折り返し直前にカーソルがある」のか「折り返された後の行の先頭にカーソルがある」のかは分からない。
幸い、選択範囲の変更(=カーソルの移動)を監視する時にはその選択範囲の変更が発生したユーザの操作の種類がある程度分かる。なので、マウス操作でのカーソル移動については、行の左の方でのクリックでカーソルが移動した時は行頭、そうでなければ行末と判定するようにした。また、キー操作でのカーソル移動については、「直前にいた位置が行頭・行の中程・行末のどれだったか」と「どのキーが押されたか」の組み合わせを元に、今カーソルがどの位置にあるかを推測するようにした。
英単語等があるせいで予定の文字数より前で折り返しが発生した時や、HTMLでプロポーショナルフォントが使用されている時、画像がある時などについてはもう完全にお手上げです。カーソルの位置をピクセル単位で取れるようなAPIが付いてくれないことには、もうどうにもなりません。
このサイトの方にまだ配布ページ作ってないのでとりあえずMozilla Add-onsに置いてみました。「ルーラ」と書くか「ルーラー」と書くか迷って「ルーラ」にしてしまいました。知ってる土地まで戻る魔法ではありません。→0.2で「ルーラーバー」に名前を変更したのでこのエントリの表記も「ルーラー」に統一しました。
見ての通り、Rulerrrrrのクローンです。公開終了しちゃってる上に特にオープンソースなライセンスが設定されていたわけでもないので、Rulerrrrrの改造ではなく一応フルスクラッチです。以下の点がちょっとだけRulerrrrrよりパワーアップしてます。
空行から左キーを押して一つ前の行の末尾に移動する時に、ルーラー上の強調表示がちゃんと追従してくれないとか、右キーを押して行末→行頭に移動しても強調表示は行末側に残ってしまうとか、Rulerrrrrでも見られた問題がこいつにもあります。そのうちなんとかしたいですね。→0.2.2008101101で改善しました
ていうか誰かすでにクローンを作ってるんじゃないかと思ったら案外誰もやってなかったみたいで驚いた。
Page 1/1: 1