Takuro Ashie
ashie****@homa*****
2003年 3月 10日 (月) 19:32:14 JST
遅くなりましたが,Actionについて少し説明します. Actionというのは,ユーザー操作一つ(例えば「戻る」とか「再読み込み」など )に対してオブジェクト一つを割り当てて,それに対してプログラムで識別する ための名前を付け,そのオブジェクトを中心にUIを統合的に管理するための仕組 みです. 例えば,「戻る」というアクションについて考えてみます. タブを開いた直後は戻るページなんて物は存在しないので,多くのブラウザでは 「戻る」ボタンを灰色にして操作を奪うという処理をしています. しかし,一方で,多くのブラウザではメニューバー,ツールバー,ポップアップ ウィンドウの3箇所で「戻る」という操作を提供していると思います(場合によっ てはジェスチャでも提供しているでしょう).ですから,「戻る」という操作を 奪う為に,いちいちこの3箇所についてgtk_widget_set_sensitive(widget, FALSE)という操作をしなければなりません.(それも,メニューバーやポップアッ プメニューから一々メニューアイテムを取り出す操作も加える必要があるでしょ う).プログラムサイズが小さいときはそれでもまあ構わないと言えば構わない のですが,ある程度の規模になると,すぐにコードがぐちゃぐちゃになってしま います.(実際,Gtk/GNOMEアプリは,Widgetの表示と実際の状態がsyncしていな いというバグが結構多いです.一方で,KDEアプリではこのようなバグはあまり 目にした事がありません) それに考えても見れば,我々は戻るページが無いから「戻る」というユーザー操 作そのものを殺したいのであって,ツールバーのボタンやメニュー項目を灰色に して使えなくするというのは,その結果に過ぎないわけです. ならば,「戻る」というアクションその物に対して「動くな」と命令するだけで, それに連動して「戻る」というアクションを提供しているWidget全てが灰色にな るという仕組みにしておいたほうが,プログラム的にはずっと楽になるというわ けです.例えるならば,スロットルをロックすると,アクセルペダルがロックさ れるという感じでしょうか.アクセルペダルが複数あっても,この仕組みによっ て全てのペダルが安全にロックされるというわけです. これは,Widgetを隠す(gtk_widget_hide())場合についても同様の事が言えます. 多くの場合は,Widgetというよりはアクションその物を(ユーザーから)隠蔽した いのだと思います. また,個々のアクションについて(プログラムで識別するための)名前が付くとい うのも,実は非常に重要な事です. 例えば設定ファイルでジェスチャを自在にカスタマイズできるようにしたいとし ます.このとき,個々のアクションに対して名前が付いていないと,設定を保存 しようがありません. 今までのように個々のメニューアイテムやツールバーアイテム等に対してコール バック関数をconnectするというやり方は,アクションに対して名前がついてい るようで,実はついていないという状態です. 今回導入したegg-menu-mergeによってXMLで自在にメニューバーやツールバーを カスタマイズできるようになりましたが,これができるようになったのも,個々 のアクションに対して(プログラム的な)名前が付いた事が大きな要因です. 以前私が日記で「ツールバーのカスタマイズ用のUIが作りやすくなる」と言った 理由はここにあります. また,少し利口なプログラマならば,実際の処理は一つの関数で提供して,コー ルバック関数ではそれを呼び出すだけ,というコーディングをしていると思いま すなぜならば,UIは複数あっても,実際の処理はほとんど同じだから.すなわち 「少し利口なプログラマ」氏は,アクセルペダルとスロットルが別物であること に,なんとなく気が付いてるんですね.ならば,「なんとなく気が付いてる」状 態を脱して,しっかりと定義を定めてやった方が,事が整然と整理されて,万事 うまくいくというわけです.その定義がActionという概念です. Actionオブジェクトでは,以下のプロパティを管理します. * アクションの名前 * アイコン(正確には,アイコンストックでの識別名) * 実際の処理(コールバック関数) * 機能の説明文(ツールチップ等で使用) * アクセルキー メニューやツールバーで使う「ラベル」(「アクションの名前」とは似て非なる 物)はこのActionオブジェクトで管理するかどうかは,少し微妙な所です.現在 のEggActionクラスではラベルも管理しているのですが,例えばショートカット キー(戻る(_R)のRの部分)の指定は,ツールバーでは必要無いからです.英語の ままであればアンダースコアを消すだけで良いのですが,日本語ではそうはいき ません.それに,同じアクションであっても,Widgetを置く場所によって微妙に ラベルを変化させたいという事はよくある事です(好ましい事だとは思いません が...).以上の理由から,私は「ラベル」はActionオブジェクトでは管理すべき ではないと考えています(KDEでも多分そうなっているはずです). 現在のEggActionクラスには他にも問題があって,アクセルキーも管理するよう にはなっているものの,実際にはメニューアイテムを作成しないとアクセルキー が有効にならないという問題を抱えています(アクセルキーの機能をアクセルラ ベルで実現しているため). 全てのユーザー操作はこの「Action」という概念で管理したほうがスマートに行 くので,検索エリアにフォーカスを当てるという操作もActionオブジェクトにし てしまおうと思ったのですが,この問題でひっかかってしまったので,まだやっ ていません.近日中にこの問題を修正して,フォーカスを当てる動作等,全ての ユーザー操作をActionオブジェクトにしてしまうつもりです. こうする事で,アクセルキーのカスタマイズの仕組みも楽に作れるようになりま す.というか,今回追加したlibeggの中には,アクセルキーのカスタマイズのた めのUIも含まれています(src/libegg/egg-accel-dialog.[ch]).ただ,使いやす いとは言えないので,作り直すつもりですが.まあGtk+標準でもすこし設定を変 えればメニューバー等で設定を変更できるようになりますが,メニューに加えな いアイテムについてもGUIで設定できるようにしたいので. 余談ですが,Gtk+ではaccelキーの設定をインポート,エクスポートする仕組み が標準で備わっています.これを利用すれば,キーテーマ等と称してvi風, Emacs風,w3m風,Mozilla風といった設定を用意する事が可能だと思います.全 てのユーザー操作がActionによって統一的に管理される事で,こういうこともや りやすくなる,というわけです. また,以前言っていた抽象化ブックマークのUIも,このActionオブジェクトを経 由する事で実現するつもりです.EggActionを継承したEggBookmarkActionという クラスを作成し,ブックマークアイテムオブジェクトを引数に渡してActionオブ ジェクトを作成する事で,メニューアイテムにもツールバーアイテムにも(はた またまったく別の何か)にもなれるというわけです. 一つのブックマークアイテム用UIを作るのに2つのオブジェクトを作る事になる ので,メモリ消費がやや心配ではありますが...