Home > Latest topics

Latest topics 近況報告

たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。

萌えるふぉくす子さんだば子本制作プロジェクトの動向はもえじら組ブログで。

宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

Page 10/248: « 6 7 8 9 10 11 12 13 14 »

ツリー型タブとVimperatorが衝突する - Apr 14, 2009

という報告を受けて調べてみて、解決策が見えなくて頭を抱えてる。

原因はFirefox 3以降でタブの拡張性が深刻なまでに低下したことに起因している。現在、Firefox 3でタブの中に独自の要素(ツリー型タブの「ツリーの開閉状態を示すアイコン」「折り畳まれたタブの数を表示するラベル」など)を追加しようとすると、バインディングを上書きしてやらないといけない。でも複数のアドオンでバインディングを上書き上書きとやってると、最後にバインディングを適用した誰かの物だけが生き残って、他のアドオンが追加したバインディングは全滅してしまう。今回の問題も、ツリー型タブがFirefox自身の提供するバインディングを上書きした後から、Vimperatorがさらにバインディングを上書きしているために、タブの要素構造がツリー型タブが想定する構造から変化して、初期化に失敗するようになってしまっている。

ツリー型タブマルチプルタブハンドラ情報化タブの3つを開発するにあたっては、この問題に対処するために、以下のような方針をとることにした。

  • それぞれが別個にバインディングを適用したら、お互いに主導権の奪い合いになる。
    • だから、適用するバインディングは「タブの中に要素を追加できる状態」を整えるためだけの物にする(三者でそれを共有する)。
      • その時の「タブの中に要素を追加できる状態」は、Firefox 2以前のバインディングと互換性がある物にする。
  • タブの中への要素の追加は、タブが追加された時のTabOpenイベントを拾って、スクリプトで動的に行う。

これを実現するために作ったのがこちらのライブラリ。3つのファイルで構成されてる。

3つを同じ所に置いてXULファイルだけをオーバーレイで読み込ませると、バインディングを上書きする。他のアドオンで同じライブラリが読み込まれてる時は、最新の物が使われる。

これをVimperatorの作者の人にも使ってもらえればいいんだけど……誰にコンタクトすればいいか分からないし、そもそも向こうにはわざわざこれを使う動機がない。Vimperatorユーザは基本的にVimperatorのカスタマイズですべてを解決する傾向にあるようだから、他のアドオンとの互換性が低くても問題にならないだろうし。

ていうか僕自身Vimperator使ってないから、わざわざ上記のような交渉をしようというモチベーションがない。というわけで、上に名前が出てる3つのアドオンのどれかとVimperatorとを共存させたいVimperatorユーザの人は、自分で作者にコンタクト取ってください。(丸投げ)

アニメーション効果を有効にしたツリー型タブの新版とデモ動画を公開したよ - Apr 09, 2009

Tree Style Tab 0.7.2009040901公開した。アニメーション効果の実装の他に、細かいバグ修正も色々。

あと、実際どんな感じかというのをわかりやすく示せるかなと思って、デモ動画も作ってみた。CamStudioもNiVEも使うの久しぶり(っていうかVistaにしてからは初)だから、やり方思い出すのに苦労したよ……

<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/M9dUfyoHz3E&hl=ja&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/M9dUfyoHz3E&hl=ja&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object>

ヌルヌル動いてるのは倍速再生してるわけではなく、これで等倍速です(一応)。タブの影はbox-shadowで描画してるので、Firefox 3.0.xだと影無しになります。

しかしYouTubeはアップロードが簡単になってるわ画質が上がってるわで、いつの間にかすんげーパワーアップしてますね。Stage6とかあった頃とは隔世の感があります。

以下余談。

実装の最後の段階になって困った点として、画面外にタブが開かれた時にそこまで自動スクロールしてくれないという問題が起こってた。スクロールしても、新しく開かれたタブの一個前のタブの位置にスクロールしちゃったりして。上の動画で言うと、0:57あたりで画面下の方でサブツリーを展開した時に、子タブが画面内におさまるように自動でスクロールしてるけど、これがちゃんと動かなくなってた。

なんでこんな問題が起こってたかというと、「そのタブが画面外にあるのかどうかを判定する」「そのタブの位置までスクロールする」といった処理が全部「タブの座標」を基準にしてたせいで、アニメーション開始時点やアニメーション中の中途半端な座標を元に処理を行ってしまい、もうシッチャカメッチャカになってた、という……

上記の処理を行う時に、アニメーション中の座標とアニメーション終了後の座標とのズレをきちんと考慮して計算してやればいいってだけの話なんだけど、普通に考えるとこれがめんどくさい。それぞれのタブがちょっとずつズレて表示されてるわけだから、座標を調べたいタブだけじゃなくてそれより前(上)にあるタブ全部について、そのタブはアニメーション中か?とか、そのタブは非表示か?とかを判別しながらオフセット値を調べないといけないわけで……いちいちそんな計算するのはめんどくさすぎる。メンテナンスし辛そうだし、コードの量が多くなりそうだし、真面目に書く気しないです(大学生の頃だったらやってたかもだけどね……時間は有り余ってたから)。

で、代わりに以下のようなやり方を思いついた。

  • アニメーション開始時点やアニメーション実行中は、個々のタブの属性値として本来の座標からのオフセット値を持たせておく。
  • タブの座標が必要になった時には、「特定の条件にマッチするタブの当該属性値を収集して合計した値」をXPathで取得して、それを現在の座標に足してやる。

コードにするとこんな感じ。

getYOffsetOfTab : function(aTab)
{
  return document.evaluate(
    'sum((self::* | preceding-sibling::*[not(@tab-collapsed="true")])'+
         '/attribute::tab-y-offset)',
    aTab,
    null,
    XPathResult.NUMBER_TYPE,
    null
  ).numberValue;
},

sum()は、渡されたノードセットの値を数値として合計したものを返すXPathの関数。受け取る結果の型をXPathResult.NUMBER_TYPEと指定すれば、計算結果の数値を直接得られる。XPathはうまく使えばこんな風に、処理対象のノードの絞り込みだけじゃなくその後の処理(ここでは計算)まで一発で済ませられるので面白い。

ツリー型タブにアニメーション処理(トゥイーン)を加えつつある - Apr 08, 2009

以前、ツリーの折りたたみでアニメーションするようにしてみた事があった。

この界隈には、GUI要素のアニメーションは嫌いで片っ端から無効にしてて、Web上でもアニメーション効果が使われてると「ウザッ」と思う、というタイプの人が多そうだと思う。でも、アニメーション効果ってのはインターフェースの見た目を考える上で結構バカにできない。

現状のように一気にすべての子タブが出たり消えたりすると、「最初の状態」と「最後の状態」の差が大きすぎて、今自分がどのタブを見ているのか見失ってしまう事がある。でもアニメーションで少しずつ折りたたんだり少しずつ展開したりする事で、「最初の状態」と「最後の状態」の間を段階的に変化させてやると、それほど戸惑わなくて済むようになる。こういう、2つの状態の間を埋めるアニメーションのことを一般にトゥイーンと呼ぶ。使い所を間違えなければ、アニメーションするインターフェースは人にやさしいものとなる。

問題は、再描画が頻繁にかかるのでPCの性能次第では激重になってしまうということ。以前試した時も、自分の環境でとんでもなく重い結果になってしまったので、導入を諦めてた。

で、今日ふと思い立ってもう一度試してみたところ、VistaのAeroが快適に動くような環境ではさすがに快適に動作してくれることが分かった。上記のような小難しい理屈を抜きにしてもヌルヌル動きまくりなのが単純にスゲー面白い。今回はかつて諦めた時のようなフレーム数固定(何回描画したら終わり、というやり方)ではなくフレームレート可変(何秒以内にできる限りの回数だけ描画する、というやり方)で処理するように実装してみたので、貧弱な環境でもそれほど重くはならないと思うんだけど……一応会社のマシンとかで試してみて、問題なさそうなら次版でデフォルト有効にしてみようと思う。

ここでは折りたたみのトゥイーンについてだけ書いてるけど、今回最初に取り組んでたのは元々はインデント幅の変更部分のトゥイーンだった。インデント幅の調整くらいだったらそれほど負荷は高くないだろう、という考えでやり始めたんだけど、最終的には折りたたみまで含めてアニメーション化しても結構気持ちよく動いてくれたということで、上のような話になっている。

面白い副作用として、インデント幅の調整と「折り畳まれたタブを元の状態に戻す」処理とが同時に走ると、まるで画面の左上からその位置にタブが落ちてきて填り込むようなエフェクトになる事に気がついた。どこにタブが増えたかを見失いにくくなる、という効果があるんじゃないかと思う。また、Vista+Aeroだと割となんでもアニメーションするので、その中に結構馴染んでる気もする。

追記。Let's note W7のUbuntuだと、Shiretokoだとわりかしヌルヌル、Firefox 3.0.xだとフレーム落ちで単純にアニメーションしてないように見えるだけという感じ。ドスパラのWindows XPマシンでも同じような感じだった。コマ落ちした場合でも最低1回は再描画があるので、ワンテンポ遅れる感じはあるんだけど、アニメーションしてる間反応がなくなるという風なことはないので、とりあえず次版から有効にしようと思う。(無効にする設定はもちろん付ける)

Mac OS Xのデフォルトテーマに合わせた新スタイルをツリー型タブに加えたよ - Mar 26, 2009

Tree Style Tabで選択可能な組み込みのスタイル指定の一つとして、Mac OS X上のデフォルトテーマ風の物を、cho45さんのStylish用スタイル定義を参考にして作ってみた。 (Metalスタイルを適用した状態のスクリーンショット) スクリーンショットはVista上での物だけど、OS X上でも確認はしてるのでご安心を。

Firefox 3以前の環境ではcho45さんのスタイル定義ほぼそのまんまを適用するようになってて、その場合はタブの高さが26ピクセル固定になってしまうのでタブの中に何か追加する系のアドオン(具体的にはInformational Tab)との相性が非常に悪い。

で、それをなんとかする方法として、Firefox 3.5以降ではborder-imageが使えるということを思い出したので、その実験というか練習も兼ねて使ってみる事にした。

普通に考えると、tab要素自体に-moz-border-imageを指定すればそれでおしまいという事になるんだけど……ツリー型タブの場合はドロップ位置のマーカーを表示するためにborderを多用してるので、-moz-border-imageをtabに指定すると都合が悪い(普通のborderと同時に指定した場合、-moz-border-imageの方が優先されるようだ)。かといって、内側や外側にもう一つタブ全体を囲うXUL要素を増やそうとすると、他のスタイル指定と激しく競合して見た目がグチャグチャになるし……

で、色々試行錯誤して、Firefox 3以前でタブの右・左・中央のそれぞれに異なる背景画像を表示するために使っていたボックスを流用して解決する方法を思いついた。

(図) この拡大図で言うと、9個に分けられた各領域を普通だったら一つのボックスのborder-imageでカバーするところを、今回は1~3・4~6・7~9の3つのボックスに分けている。-webkit-border-imageや-moz-border-imageの例として紹介されているコードでは4つの辺の幅を同じにしてる例が多いけど、実は4つの辺はそれぞれバラバラに幅を指定できる。なので、

  • 図の赤のボックスはurl("共通の画像") 10 10 10 10 / 10px 0 10px 10pxで右の辺の幅を0に。
  • 緑のボックスはurl("共通の画像") 10 10 10 10 / 10px 0 10px 0で左右の辺の幅を0に。
  • 青のボックスはurl("共通の画像") 10 10 10 10 / 10px 10px 10px 0で左の辺の幅を0に。

という風にしてやる事で、1枚の画像で3つのボックスそれぞれに異なる部分を切り出して適用するような効果を得られる。

また、このままだとタブの高さがborder-imageの幅の分だけ高くなってしまう(border-imageの上辺+タブのラベルの高さ+border-imageの下辺=タブの高さ)ので、タブのラベルやアイコンなどに対して上下にネガティブマージンを設定して、強制的にタブの高さを小さくするようにしてみた。上の図は切り出し位置を示すためにわざと高さを広げた状態だけど、ネガティブマージンを効かせれば、冒頭のスクリーンショットのようなスリムなタブになる。

タブの縦置き、タブのグループ化 - Mar 19, 2009

ツリー型タブに似たアドオン2つを新たに知った。

VertTabbarは、タブバーをウィンドウの右または左に移動して縦列タブにするアドオン。Vertigoはずいぶん昔に更新が止まってるようなので、その代替と言えるだろうか。カスタマイズ機能も色々あるみたい。

タブグループマネージャーは、名前から見ても機能的にもTabGroupsの後継っぽい。でも多分中身は全然別物なんだろう。今見てないグループのタブ全部をメモリから追い出して省メモリにする機能とか、検索バーからの検索結果を自動的にグループにする(セカンドサーチとも連携できるらしい)とか、色々高機能だ。

ツリー型タブ on Vista - Mar 05, 2009

そういえばbox-shadow(-moz-box-shadow)が使えるんだったなと思って、Firefox 3.1……じゃなくて3.5以降ではツリー表示したタブに影を付けるようにしてみた。 (スクリーンショット)

「新しいタブ」ボタンの影だけは背景画像です。

ツリー型タブの自動テスト - Feb 12, 2009

書き始めた。

最近、恐怖症っていうか神経症っていうか……自動テストで検証されてない事が怖くて仕方ない。一通りテストを書き終えるまで、次をリリースするのが怖い。リリース工程をとても億劫に感じてしまって、どうにかしてそれを乗り越えてやっとリリースしたと思ったら、しょうもないregressionがあることに気がついて、またあの面倒なリリース工程をやらないといけないのかと思うと気が重くなって。

追記。とかなんとか言いながら結局テスト未完のままリリースしてしまった。

テストがあるからってバグがない訳ではない……XUL/Migemoもまだまだモロモロと障害が見つかってる。ただ、自動化のプロセスがほぼできあがってるので、新たに問題がおこるケースが見つかったら、それをテストケースに追加して、コードを修正して、全体のテストが完遂すること(=regressionが無いこと)を確認して、過去に自分が把握してた範囲についてはある程度の自信を持ってリリースできる。自動化ができてないと、その自信を持てない。直したと思った物がすぐ後ろから崩れてるかもしれないという恐怖に駆られる。

Firefox 3.1に向けてまたタブ回りが色々変わったのと、XUL要素のdisplayプロパティの値 - Jan 24, 2009

タブのドラッグ&ドロップに関する色んなバグを一挙に解決するパッチ最後のタブの右に「新しいタブ」ボタンを表示するようにするパッチの両方が入って、タブ回りが色々変わった。何はともあれ、タブをクリックしようとしただけなのにうっかりドラッグになってしまって別ウィンドウが開かれてムキー、という事がなくなってよかった。

とりあえず自分が把握してる限りでは、ツリー型タブ等でscrollbox内の方の「新しいタブ」ボタン(今回追加された奴)をdisplay: none;で消してるせいか、ボタンを再表示させた時や新しいタブを追加した時などにタブやボタンの並び順が盛大にぶっ壊れるようになった。display: -moz-box; visibility: collapse;にしておくとこの問題は起こらないっぽいので、次版ではそうする予定。(コードはもうコミットしてある

あと、gBrowser.mTabContainer.childNodesが返す内容がタブとは限らなくなった(どんな要素でもタブバー内に置けるようになったので)ということで、タブを取得するのにこのプロパティを使ってる人は一応気をつけといた方がいいと思う。てかtabbrowser要素のmTabs自体がこれを参照してるし、現実的にはタブ以外を置いたら色んな所がぶっ壊れる事が予想されるから「置くなよ! 絶対置くなよ!!」って言ってるのと同じだよなあ。まあ一応対応しとくけどさ……

またさらに気付いたけど、タブのnextSiblingpreviousSiblingタブでない値を返す可能性がある状態になってる。XBLのソースに埋め込まれてるコメントノードの位置もタブの間に何故か移動してしまったりする事があるようで、前後のタブをこのプロパティで参照してる場合には被害を受ける事になる。ここも注意が必要だ。

全然話は変わるけど。

アドオンで要素の表示・非表示をCSSのdisplayプロパティで制御するにあたって、display: none;で非表示にするのはセオリー通りで別にいいんだけど、表示させる時にdisplay: inline;とかdisplay: block;とかにしてる人がたまにいてもにょる。Web上のCSSではそれで正解なんだけど、XULでこれをやるとボックスの並び順がぶっ壊れたりレイアウトがおかしくなったりする事があるので、よっぽどの事情(タブバーを多段表示させる時とか)がない限りはあくまでdisplay: -moz-box;の方を使って欲しい。最近見かけたものではPathtraqがそうだった。

XUL要素の表示・非表示を制御するには大別して3つ、細かく分けると7つの方法がある。

  • 要素を完全に消す(レイアウトのフローから完全に除外する)
    • node.hidden = truenode.hidden = false
    • node.setAttribute('hidden', true)node.removeAttribute('hidden')
    • node.style.display = 'none'node.style.display = '-moz-box'
  • 表示上見えなくする(レイアウト上は幅・高さ0でその位置にある物として扱う)
    • node.collapsed = truenode.collapsed = false
    • node.setAttribute('collapsed', true)node.removeAttribute('collapsed')
    • node.style.visibility = 'collapse'node.style.visibility = 'visible'
  • 表示上見えなくする(レイアウト上もその位置に本来の幅・高さで要素がある物として扱うが、その領域には何も描画しない)
    • node.style.visibility = 'hidden'node.style.visibility = 'visible'

いくつかのXUL要素では、hiddenプロパティやcollapsedプロパティに真偽値を代入しても何も起こらないので、setAttribute()removeAttribute()とした方がより確実ではある。プロパティでの代入にせよDOMの属性値での指定にせよ、最終的にはCSSでの指定と同じ物として扱われる。xul.cssの頭の方を見れば、どういう事かよく分かると思う。

上の例でnode.setAttribute('hidden', false)ではなくnode.removeAttribute('hidden')と書いているのにも理由がある。テーマやアドオンの中には「要素のhidden属性の値がtrueであるかどうか」ではなく「hidden属性に何らかの値がセットされているかどうか」しか考えてない場合があって、falseを設定したのに非表示のままになってしまう、というような事がたまにあるから。collapsedにも同じ注意が必要。

XULの世界的には物凄く基本的な事なんだけど、HTML+CSSの世界から入ってきたばっかりの人はこの辺の事を知らないままでいるかもしれないので、一応書いてみた。

こういう事(why:何故そう書かねばならないか)って、アドオンの実際のコード(how:どう書いたらよいか)をいくら見てても分からないんだよなあ……ほんとXULは地獄だぜ。

リンクから開かれた新しいタブでも「戻る」を使えるようにするTab Historyがイイ - Dec 03, 2008

Firefoxタブ常用者のための最新エクステンションガイド - SourceForge.JP Magazine で「ツリー型タブを入れてるとTab History が無効になる」と書かれてたので「なに!」と思って入れてみたんだけど今の所特に不具合無く動いてるように見える。一応ソースも見てみたけど、特に衝突する点も無いような……一カ所「もしかして、ここか?」と思う所は無くもないんだけど。そこだけ次版で手を入れておくか……(追記:ツリー型タブ 0.7.2008120401で一応手を入れてみた)

その問題はさておき、Tab Historyは確かに良い。万人にお勧めできると思う。よくある「初心者ユーザがリンクをクリックした時に勝手に新しいウィンドウが開かれて、それが全画面表示になっているせいで、『元のページに戻りたいのに戻るボタンを押しても何も起こらないムキー!!!』となってしまう」という現象、のタブ版を防ぐ物だと言えるだろう。自分はよく、あるタブから子タブを開く→子タブを見ている間に親タブを閉じる→やっぱり親タブをもう一度見たくなる→閉じたタブを開き直す という操作をやるのだけれども、Tab Historyが入っていれば、子タブしか残っていない状態でも「戻る」ボタンで親タブで見てたページに戻れる。

ていうかソース覗いてみて思ったけど、これ作った人頭いいなー。タブが開かれる時に引数でリファラが指定されていたら現在アクティブなタブから開かれたタブであると見なしてセッションヒストリを引き継ぐ、という判定をしていて、最小限の変更で適切な動作になるようにしてる。まあリファラを偽装する系の他のアドオンと組み合わせた時には問題が起こるかもしれないけど。僕にもこういうピンポイントで問題を解決する力が欲しい。

あとPrint All Tabsにちょっと興味を引かれたので、マルチプルタブハンドラのタブ選択時のメニューに「選択したタブを印刷」を加えるようにしてみてる(Print All Tabsをバックエンドに使うので、Print All Tabsが入っていない場合は使えない機能となる)。

Page 10/248: « 6 7 8 9 10 11 12 13 14 »

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のコメント

最近のつぶやき