これはSmalltalk Advent Calendar 2019の記事です。
Spec2は、Pharo Smalltalk で採用されているUIフレームワークであるSpec の新しいバージョンです。Pharo 7.0 では Spec が使われていましたが、Pharo 8 では(ほぼ?)全てのUIが Spec2 で書き直されるようです。この記事では Spec2 を使った UI の実装方法について簡単に紹介します。
Squeak/Pharo Smalltalk では、UIの実現のために長らく Morphic を用いてきました。Morphic はシンプルで強力なフレームワークですが、複数のコンポーネントを組み合わせていくとアナーキーな実装をしがちで、リファクタリングや再利用の際に泣きたくなるような状況に陥りがちです。Spec/Spec2 はUIの構築に秩序をもたらし、コンポーネントの再利用がしやすく設計されています。
前回の記事から、Scratch 1.4風のファイル選択ダイアログを作っています。
今回は前回のファイル選択ダイアログに、ディレクトリ移動の機能を付けます。具体的にはファイル一覧でディレクトリ名をダブルクリックしたらサブディレクトリに移動する機能を加えます。
一覧でのダブルクリックに反応する
ファイル一覧は self newList で生成されるリストウィジェットで表示しています。リストウィジェットは、一覧を操作するための様々な機能を備えています。
デフォルトで生成されるリストウィジェットは項目を複数選択できるものですが、今回の例には合わないので項目を1つだけ選択できる(beSingleSelection)ようにします。また、ダブルクリックに反応できる(activateOnDoubleClick)よう、 initializePresenters を太字のように変更します。
initializePresenters listCurrent := self newDropList. listEntries := self newList beSingleSelection; activateOnDoubleClick; items: self getEntries.
項目をダブルクリックされたときに反応するには、ブロックを引数にしてリストウィジェットへ whenActivatedDo: メッセージを送って設定します。これは connectPresenters で行います。
connectPresenters listEntries display: [ :m | self showEntry: m ]; whenActivatedDo: [ :selection | self entriesChanged: selection ].
これで、項目がダブルクリックされたときに entriesChanged: メッセージが送られるようになるので、次は entriesChanged: メソッドを定義します。
entriesChanged: aSelectionMode | dir | dir := aSelectionMode selectedItem. dir isDirectory ifFalse: [ ^ self ]. self directory: dir asFileReference
entriesChanged: の引数は、SpSingleSelectionMode のインスタンスで、ダブルクリックされた項目に関する情報を保持しています。このオブジェクトに対して selectedItem を送れば、項目のオブジェクトが得られるので、ダイアログの新たなディレクトリとして設定します。
最後に directory: メソッドを定義して、作成しているダイアログのディレクトリを変更し、リストウィジェットの内容を再構築します。
directory: aFileReference directory := aFileReference. listEntries unselectAll; items: #(); items: self getEntries
以上で、リストウィジェットのディレクトリ(カッコで囲まれたエントリ)をダブルクリックすると、サブディレクトリが表示されるようになりました。