たまに18歳未満の人や心臓の弱い人にはお勧めできない情報が含まれることもあるかもしれない、甘くなくて酸っぱくてしょっぱいチラシの裏。RSSによる簡単な更新情報を利用したりすると、ハッピーになるかも知れませんしそうでないかも知れません。
の動向はもえじら組ブログで。
宣伝。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。
以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能!
という報告を受けて調べてみて、解決策が見えなくて頭を抱えてる。
原因はFirefox 3以降でタブの拡張性が深刻なまでに低下したことに起因している。現在、Firefox 3でタブの中に独自の要素(ツリー型タブの「ツリーの開閉状態を示すアイコン」「折り畳まれたタブの数を表示するラベル」など)を追加しようとすると、バインディングを上書きしてやらないといけない。でも複数のアドオンでバインディングを上書き上書きとやってると、最後にバインディングを適用した誰かの物だけが生き残って、他のアドオンが追加したバインディングは全滅してしまう。今回の問題も、ツリー型タブがFirefox自身の提供するバインディングを上書きした後から、Vimperatorがさらにバインディングを上書きしているために、タブの要素構造がツリー型タブが想定する構造から変化して、初期化に失敗するようになってしまっている。
ツリー型タブ、マルチプルタブハンドラ、情報化タブの3つを開発するにあたっては、この問題に対処するために、以下のような方針をとることにした。
これを実現するために作ったのがこちらのライブラリ。3つのファイルで構成されてる。
3つを同じ所に置いてXULファイルだけをオーバーレイで読み込ませると、バインディングを上書きする。他のアドオンで同じライブラリが読み込まれてる時は、最新の物が使われる。
これをVimperatorの作者の人にも使ってもらえればいいんだけど……誰にコンタクトすればいいか分からないし、そもそも向こうにはわざわざこれを使う動機がない。Vimperatorユーザは基本的にVimperatorのカスタマイズですべてを解決する傾向にあるようだから、他のアドオンとの互換性が低くても問題にならないだろうし。
ていうか僕自身Vimperator使ってないから、わざわざ上記のような交渉をしようというモチベーションがない。というわけで、上に名前が出てる3つのアドオンのどれかとVimperatorとを共存させたいVimperatorユーザの人は、自分で作者にコンタクト取ってください。(丸投げ)
と、面と向かって聞かれると答えに窮する。はっきり「ハイ、面食いです。かわいくないのは絶対嫌です、お断りです。」って言えるかどうか、という話。
僕は「面食い」を、顔の造形を指してだけ言うんじゃなくて、「雰囲気イケメンも含むイケメン」と同様の広い意味合いで、「服装とかも含めてかわいい人が好み」という感じのニュアンスで捉えてるんだけど。その上で考えると、自分自身が身なりに気を遣えてない、気を遣ったとしてもトンチンカンなことにしかなってないくせに、他人には高いレベルを要求するんですか、って話になるわけです。見合う物持ってんの? 持ってないでしょ? じゃああんた選り好みする資格無いよ。と、自分で思う。(※だから前彼女はブサイクでした、という話ではないですよ?共通の友人各位)
にもかかわらず「ハイ、面食いです。かわいくないのはお断りです。」って言い放ったら、もう、お前何様だよって話になるわけじゃないすか。人によっては「顔で差別するとはけしからん!!!」と憤慨するかもしれない。憤慨しなくても「ふーん、顔しか見てないんだね。哀れな人だね。」って思われることうけあい。
かといって「いや、性格がよければ全然気にしないよ!」とかそれっぽいことを言ったって、嘘っぽいっていうかぶっちゃけ嘘だし。「かわいくないよりはかわいい方が……」とか「まぁ好きになったらその人がタイプになる感じかな……」とかの煮え切らない答えというのも、無難な落とし所に逃げてる感アリアリだし。「そうだね、まずは『面食い』の定義によるかな。そもそも……」とかマジに語り出したら空気読めてなさ過ぎだし。もうね、どう答えろと。
……はっ、もしかして、そういう負の視線をものともせず自分の意志を強く貫ける人間かどうかってことを試されたのか?(考えすぎ)
とかなんとかそんな風にぐるぐる考えてしまうから、いつも、そういう事は考えないようにしてる。評価しない。判断しない。判断しても口にしない。口に出すのは、それで傷付く人がいなさそうな時だけ(評価対象が無生物であるとか、はいはいノロケノロケとはなから相手にされないような場合であるとか)。
以前急性胃腸炎でダウンした時に助けてくれた従妹の子がオーケストラで参加するオペラが今なら身内割引でお値打ち価格!!みたいな次第で、いってきた。なんという戦略的宣伝……お礼もまだしてないのに断れるわけなかろう……!
ミュージカルは観たことあるけどオペラは見たことなかったので、興味本位というのもあった。
始まるまで知らなかったんだけど、オペラって地の「セリフ」がないんですね。全部歌詞なのか。しかも原語ときたもんだ(日本語字幕が舞台の横に出てた。フランス語なんか分からんから、字幕と人の間を視線が行ったり来たりで忙しかった)。仕事上のミスで朝帰り後にちょっと寝てそれから行ったので、聞いてても意味が分からない未知の言葉がいい具合に子守歌になって、だいぶ寝てしまった。だからこれは「カルメン」の感想じゃなくて「初めてオペラに行ってみました」レポートでしかない気がする。
一応、事前にあらすじは調べておいてから行ったんだけど、こう、今このタイミングで見に行くのはなかなか辛いものがありましたよ……ホセを振ったカルメンがエスカミーリョとラブラブいちゃいちゃしてて、ホセがストーカー化してキショい言動まくり、とか、もうね。(って、ホセはホセでミカエラを捨てたんだからこれもまた酷い話ですが……)
終わった後に挨拶していけばよかったんだけど、オーケストラピットそばまで行ってみたものの、怖くて逃げ帰ってしまった。←これはひどい。
ごろたんから、このサイトのアドオン関係のページに書いてあるプログラミングのド素人が下手の横好きで作ったもの。
という部分にツッコミを受けてしまった。素人じゃねーじゃん!!と。
いつでも初心を忘れないPiroですヨロシク。
いや、確かあの文って大学1年とかそのくらいの時に書いたはずで、それまでプログラミングといったら中学の時のN88BASICのお遊びと、ページ左のメニューをどうにかして自動生成したいってことで訳わかんないまま書いてたJavaScriptくらいしか、経験がなかったんですよね。専門の教育を受けたわけでもないし、きちんとしたプロダクトを作った事もなかったし……「大阪電気通信大学」っていうとじゃあ理系か工学系なのかって思われそうだけど、僕のいたメディア学科は入試に数学が無くて、カリキュラムにもプログラミングをテーマにした物は入ってなかった、そういうとこですから。
でも確かに今となっては、プログラマなのかエンジニアなのかとにかくコードを書くことが仕事の一環になってはいるので、素人とは言えないでしょうね。ってか、言ってたらマズイ。ということで上記のフレーズは消しておくことにします。
でも自分の感覚では、相変わらず、素人に毛が生えた程度という認識でいるんですよね。この1年くらいで技術的に進歩したと言えそうな事といえば、せいぜい、自動テストを書くようになったくらいで……ごろたんの記事読むまでeasing関数って単語すらも知らなかったし。使える言語も、Mozilla語のJavaScript方言とRails語をカタコトくらいですよ(JavaScriptとRuby、と胸を張っては言いづらいレベルの知識の偏り方なので)。論文読むとか本を読むとかそういう学習意欲の高いプロフェッショナルな人達を見てると、なんかすごく見劣りする気がする。
いや、ひょっとしたらそういう事じゃないのかもしれない。もっと形式的なところにこだわってるのかもしれない。
なんかねえ……例えば、入社1年目で何かプロジェクトにアサインされて、リーダーの下で指示を受けてあれこれ学びながら作業をこなして、納品してリーダーから「よくやった、お疲れ!」とかねぎらいの言葉をもらう、みたいな感じの、社会人としておそらくは常識的な<ruby><rb>通過儀礼</rb><rp>(</rp><rt>イニシエーション</rt><rp>)</rp></ruby>を経てない状態で、自分は技術者ですみたいな認識を持つことに、自分で抵抗があるということなんじゃないかって思う。
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あたりで画面下の方でサブツリーを展開した時に、子タブが画面内におさまるように自動でスクロールしてるけど、これがちゃんと動かなくなってた。
なんでこんな問題が起こってたかというと、「そのタブが画面外にあるのかどうかを判定する」「そのタブの位置までスクロールする」といった処理が全部「タブの座標」を基準にしてたせいで、アニメーション開始時点やアニメーション中の中途半端な座標を元に処理を行ってしまい、もうシッチャカメッチャカになってた、という……
上記の処理を行う時に、アニメーション中の座標とアニメーション終了後の座標とのズレをきちんと考慮して計算してやればいいってだけの話なんだけど、普通に考えるとこれがめんどくさい。それぞれのタブがちょっとずつズレて表示されてるわけだから、座標を調べたいタブだけじゃなくてそれより前(上)にあるタブ全部について、そのタブはアニメーション中か?とか、そのタブは非表示か?とかを判別しながらオフセット値を調べないといけないわけで……いちいちそんな計算するのはめんどくさすぎる。メンテナンスし辛そうだし、コードの量が多くなりそうだし、真面目に書く気しないです(大学生の頃だったらやってたかもだけどね……時間は有り余ってたから)。
で、代わりに以下のようなやり方を思いついた。
コードにするとこんな感じ。
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はうまく使えばこんな風に、処理対象のノードの絞り込みだけじゃなくその後の処理(ここでは計算)まで一発で済ませられるので面白い。
トゥイーンの話を受けてごろたんがさらに発展的な話を書いてくれた。で、「ほうほう、こういうのをeasingと言うのか……」と自分の無知っぷり&何も知らんくせに偉そうなことを語る厚顔さに恥じ入りながら先のエントリを少し手直しした。
で、JSTweener という Tweener (as3 のモーショントィーンライブラリ) 互換のライブラリを使うと、標準で様々な easing 関数が利用できたり、タイマーが一つなので、数百, 数千オブジェクトをモーションさせるときにはだいぶ高速になる。
というのを読んで、確かに先のエントリに書いた物はいっこいっこのタブごとにタイマー走らせるから効率悪いよなあ、と思い、1個のタイマーだけで複数のアニメーションを走らせるための簡単なライブラリを作ってみた。ツリー型タブの開発版にも早速組み込んでる。
window['piro.sakura.ne.jp'].animationManager.addTask(
)
にアニメーション用の関数その他の引数を渡してやると、それを共通のタイマーで処理する、というごく単純なもの。window['piro.sakura.ne.jp'].animationManager.removeTask(
)
で関数の登録を解除してやる。クロージャ使って書くこと前提の不親切なAPIですんません……
クリアコード カレー部部長(部員0名)としてだいたい週2回くらいのペースで同じインドカレー屋でカレー食ってるわけですが、この間のお得意さん認定に続いて、今度は注文する前からメニューを読まれてる&名前を聞かれるというイベントが発生してしまいました。
着実にフラグが立っていっているようですが、その店員さんは男の人なわけで。
つい先日お別れした元彼女に「きっともっといい人が見つかる」的なことを言われましたが、僕の身の回りで立つフラグといったらこんなんだけですよ……
1つ前のエントリに書いた、可変フレームなトゥイーン効果の実装の話。
今時は便利なJavaScriptのアニメーション用ライブラリが色々あるからわざわざ自分で書くような必要はないんだろうけど、自分はほんの一箇所だけのためにライブラリ全部突っ込むというのは気が引けるタイプなので、ピンポイントな実装とその理屈を(雑学として)書いておこう。
先に、タブのインデント幅変更の処理の完成したものを貼っておく。説明を簡単にするためにちょっと省略してる。
indentDuration : 200,
updateTabIndent : function(aTab, aProp, aIndent)
{
this.stopTabIndentAnimation(aTab);
var startIndent = this.getPropertyPixelValue(aTab, aProp);
var delta = aIndent - startIndent;
var duration = this.indentDuration;
var startTime = Date.now();
aTab.__treestyletab__updateTabIndentTimer = window.setInterval(function(aSelf) {
var progress = Math.min(1, (Date.now() - startTime) / duration);
var powerForStyle = Math.sin(90 * power * Math.PI / 180);
var indent = (progress == 1) ?
aIndent :
startIndent + (delta * powerForStyle);
aTab.setAttribute(
'style',
aTab.getAttribute('style')+';'+
aProp+':'+indent+'px !important;'
);
if (progress == 1) aSelf.stopTabIndentAnimation(aTab);
}, 10, this);
},
stopTabIndentAnimation : function(aTab)
{
if (!aTab.__treestyletab__updateTabIndentTimer) return;
window.clearInterval(aTab.__treestyletab__updateTabIndentTimer);
aTab.__treestyletab__updateTabIndentTimer = null;
},
getPropertyPixelValue : function(aElement, aProp)
{
var style = window.getComputedStyle(aElement, null);
return Number(style.getPropertyValue(aProp).replace(/px$/, ''));
},
なんでCSSOM使ってないの、って所にはツッコまないように。
アニメーションというと、つまりはちょっとずつ値を変えて再描画するということで、単純に考えたら多分こうなる。
function doAnimation(aElement, aStart, aEnd)
{
for (var i = aStart; i < aEnd; i++)
{
aElement.style.marginLeft = i+'px';
}
}
でもこれはダメ。CSSのプロパティを変更しても、その状態が描画されるより前に次の値がセットされてしまうので、間のアニメーションがアニメーションにならない。(CSSのプロパティが変更された瞬間に再描画する実装だったらこれでもいいかもだけど、少なくともGeckoではダメ。)
もうちょっと改良すると、こう。
function doAnimation(aElement, aStart, aEnd)
{
var margin = aStart;
var timer = window.setInterval(function() {
aElement.style.marginLeft = (margin++)+'px';
if (margin == aEnd) {
window.clearInterval(timer);
}
}, 10);
}
こういう風にタイマーを使ってやれば、きちんと各コマが描画されるようになる。
しかしこのやり方だと、最初の値から最後の値までの全コマが必ず描画される(=フレームレート固定)ので、貧弱な環境だとものすごい遅いアニメーションになってしまう。上の例だと、10ミリ秒ごとに1ピクセルずらして、というのを移動距離の分だけ繰り返すことになってしまう。
「高速な環境ではたくさん描画していいけど、低速な環境だと再描画を減らしてほしい。とにかく、1回のアニメーションは決まった時間の中できちんと終わらせたい。」これが可変フレームレートの基本的な考え方。
可変フレームレートにする場合、描画と描画の間にどれだけ時間がかかったか、というのが鍵になる。
JavaScriptのsetIntervalのタイマーは、(少なくともGecko/SpiderMonkeyでは、)仮に実行間隔を10ミリ秒にした場合、実際には「1回目の処理の時間」+「10ミリ秒のインターバル」+「2回目の処理の時間」+「10ミリ秒のインターバル」……という風な感じで時間が過ぎていく。アニメーションにかける全体の時間が分かっているなら、「n回目の描画開始時の時点で、アニメーションにかける時間全体の何%が過ぎたか」をまず計算して、移動量をそのパーセンテージから求めてやればいい。
function doAnimation(aElement, aStart, aEnd)
{
var delta = aEnd - aStart;
var duration = 200; // アニメーション効果全体を200ミリ秒で終わらせる
var startTime = Date.now(); // (new Date()).getTime() と同等
var timer = window.setInterval(function() {
var progress = Math.min(
1,
(Date.now() - startTime) / duration
);
var margin = (progress == 1) ?
aEnd :
aStart + (delta * progress) ;
aElement.style.marginLeft = margin+'px';
if (progress == 1) {
window.clearInterval(timer);
}
}, 10);
}
これで、可変フレームレートのアニメーションになった。progress
はアニメーションの進行状況を示していて、0(開始時点=0%)から1(終了時点=100%)の間の値を取る。開始時の値と終了時の値の差にこれをかけてやれば、「今の時点ではこれだけ移動してるはず(その位置に描画すればよい)」ということが分かるワケ。(ちなみにこの時点で、値が増加していくのか減少していくのかどっちなんだ、ということも気にせずに済むようになっている。)
この時点では、値の変化率は一定なので、理科の時間に習う「等速直線運動」ってやつになっている。実際のUIでこれをそのまま使うとちょっと味気ないので、もうちょっとかっこよくしてやりたくなるところだ。可変フレームレートならそれも簡単にできる。
よくあるのは、「最初はすごい速度で飛んできて、最後はフワッと着地する」みたいな効果だろう。これは三角関数のsin()やcos()を使えば簡単に計算できる。
円と複素数平面の勉強をしたことがあれば、0°から90°の間を1°ずつ動く間に、Xの値は「最初はゆっくりと、最後は急速に」Yの値は「最初は速く、最後はゆっくり」増加していくことが分かるだろう。sin(θ)やcos(θ)を使えば、この「XやYの値の変化率」を取り出して利用できる。
例えば「最初は速く、最後はゆっくり」のアニメーションなら、上の例の(delta * progress)
の所を(delta * Math.sin( (progress * 90) * Math.PI / 180 ))
にすればいい。これで、0°から90°までの間のYの値の変化率に応じた移動量になる。(Math.sin()
やMath.cos()
は角度をラジアンで指定しないといけないので、θ×π÷180で度数をラジアンに変換している。)
以上、中学や高校で勉強する数学って案外無駄にならないんだよ、というお話でした。
ちなみに、aStart + (delta * progress)
の所あたりを任意の式に置き換えれば、動き方を等速直線運動や等加速度運動やはね回る等の色んな形に変えることができる。これを、「<ruby><rb>最初の値</rb><rp>(</rp><rt>Start</rt><rp>)</rp></ruby>・<ruby><rb>値の最終的な変化量</rb><rp>(</rp><rt>total Change</rt><rp>)</rp></ruby>・<ruby><rb>アニメーションにかけたい時間</rb><rp>(</rp><rt>Duration</rt><rp>)</rp></ruby>・<ruby><rb>現在までに過ぎた時間</rb><rp>(</rp><rt>Time</rt><rp>)</rp></ruby>(最後の2つから現在の進度が分かる)という4つのパラメータを受け取り現在の値を返す関数」として定義した物をeasing関数と呼ぶそうで、世にある多くのアニメーションライブラリは、このeasing関数を入れ替えることで色んなエフェクトを得られるようにしたもの、と言うことができる。
……という風に読み解いてみると、普段使ってるライブラリが一体何をどのように処理しているのか分かっておもしろいんじゃないでしょうか。僕はライブラリ使ってませんが。
追記。Norahさんのこれって yield 使ったらダメなんだろうか?
というコメントを見た。べつに使っちゃダメってことはないし、むしろ自分も一瞬「あれ、これyieldで書けるんじゃね?」と思ったんだけど、どっちにしろタイマーでループ回すという事には変わりないし、そうなるとここで書いてるくらいの規模だとコードの量が無駄に増えるだけって気がしたので、そのままタイマーだけで書いた次第です。
追記。easing関数の説明を間違えてたので修正しました……
以前、ツリーの折りたたみでアニメーションするようにしてみた事があった。
この界隈には、GUI要素のアニメーションは嫌いで片っ端から無効にしてて、Web上でもアニメーション効果が使われてると「ウザッ」と思う、というタイプの人が多そうだと思う。でも、アニメーション効果ってのはインターフェースの見た目を考える上で結構バカにできない。
現状のように一気にすべての子タブが出たり消えたりすると、「最初の状態」と「最後の状態」の差が大きすぎて、今自分がどのタブを見ているのか見失ってしまう事がある。でもアニメーションで少しずつ折りたたんだり少しずつ展開したりする事で、「最初の状態」と「最後の状態」の間を段階的に変化させてやると、それほど戸惑わなくて済むようになる。こういう、2つの状態の間を埋めるアニメーションのことを一般にトゥイーンと呼ぶ。使い所を間違えなければ、アニメーションするインターフェースは人にやさしいものとなる。
問題は、再描画が頻繁にかかるのでPCの性能次第では激重になってしまうということ。以前試した時も、自分の環境でとんでもなく重い結果になってしまったので、導入を諦めてた。
で、今日ふと思い立ってもう一度試してみたところ、VistaのAeroが快適に動くような環境ではさすがに快適に動作してくれることが分かった。上記のような小難しい理屈を抜きにしてもヌルヌル動きまくりなのが単純にスゲー面白い。今回はかつて諦めた時のようなフレーム数固定(何回描画したら終わり、というやり方)ではなくフレームレート可変(何秒以内にできる限りの回数だけ描画する、というやり方)で処理するように実装してみたので、貧弱な環境でもそれほど重くはならないと思うんだけど……一応会社のマシンとかで試してみて、問題なさそうなら次版でデフォルト有効にしてみようと思う。
ここでは折りたたみのトゥイーンについてだけ書いてるけど、今回最初に取り組んでたのは元々はインデント幅の変更部分のトゥイーンだった。インデント幅の調整くらいだったらそれほど負荷は高くないだろう、という考えでやり始めたんだけど、最終的には折りたたみまで含めてアニメーション化しても結構気持ちよく動いてくれたということで、上のような話になっている。
面白い副作用として、インデント幅の調整と「折り畳まれたタブを元の状態に戻す」処理とが同時に走ると、まるで画面の左上からその位置にタブが落ちてきて填り込むようなエフェクトになる事に気がついた。どこにタブが増えたかを見失いにくくなる、という効果があるんじゃないかと思う。また、Vista+Aeroだと割となんでもアニメーションするので、その中に結構馴染んでる気もする。
追記。Let's note W7のUbuntuだと、Shiretokoだとわりかしヌルヌル、Firefox 3.0.xだとフレーム落ちで単純にアニメーションしてないように見えるだけという感じ。ドスパラのWindows XPマシンでも同じような感じだった。コマ落ちした場合でも最低1回は再描画があるので、ワンテンポ遅れる感じはあるんだけど、アニメーションしてる間反応がなくなるという風なことはないので、とりあえず次版から有効にしようと思う。(無効にする設定はもちろん付ける)
こんなメールが@google.comなアドレスから来たわけですが。(以下、適当訳は僕による物)
We are working on developing extensions for Chrome and are interested in exploring an opportunity to bring Tree Style Tab to Chrome. The initial design documents may be found here:
今私達はChrome用の拡張機能の開発のために働いており、Tree Style TabをChromeに移植する可能性について関心を持っています。最初の設計書は以下にあります:
http://dev.chromium.org/developers/design-documents/extensions
Further information on the API's that are up for consideration may also specifically be found here:
検討中のAPIについてのさらなる情報はこちら:
http://dev.chromium.org/developers/design-documents/extensions/apis As things further develop, the site will be updated and more information will become available."
将来的に、このサイトは更新され、より多くの情報が利用可能になる予定です。
で、この後にアンケートの案内が続く。アンケートはAPIの案に挙がってる物の中でどれが欲しいかというもので、自由回答欄もあったので、こう答えておいた。
Tree Style Tab totally restructures Firefox's tab bar. If I try to import it to Chrome, I'll need high flexibility not only Greasemonkey-like, but userChrome.js-like to control Chrome's UI from script.
Tree Style TabはFirefoxのタブバーを全体的に再構築します。もしChrome用に移植するなら、Greasemonkey風のものだけでなくuserChrome.js的な、ChromeのUIをスクリプトから制御する高い柔軟性が必要です。
どんなアドオンなのか中身を見ないでとりあえずAMOのおすすめリストから適当に選んでコンタクトしてきてんじゃないか?という気もする(速度重視の設計思想のChromeには、ツリー型タブを移植可能にするような高いカスタマイズ性はそぐわないと思う)。とはいえ、アドオン作者の積極的な取り込みのために動いてるとは、Google本気だな。
とりあえず僕個人に関しては、
という感じなので、僕がChromeにツリー型タブを移植するか?というと、可能になったとしてもやらないんじゃないかって気がする。リポジトリは公開してるから、やりたい人はどうぞお好きにってことで……