IMMウィンドウ制御
地方巡業の移動車中でがんばって作業し、なんとか動くところまでこぎつけました。お試し版は関係者に送付。ここでは、ポイントをメモしておきます。
compositionManagerへの要求を出すのは誰か?(revisited)
http://d.hatena.ne.jp/korakurider/20050602/p1では、コスチュームのさらに外側のテキスト管理アスペクト(CCostumeTextHolder)の周辺で処理をする方針を検討しました。委譲を積み重ねるTweakのフレームワークの中では魅力的な案なのですが、以下の問題点が見つかりました。
- テキストWidgetが置かれているコンテナが移動した場合(#frameChanged)、末端のコスチュームにイベントは伝播されない。無理やり伝播させるのは影響が大きすぎる。
- スクロールバーつきWidget(CTextEditor)の場合、スクロール対象の CTextEditorPane上で座標計算した場合、Widgetの可視領域外の座標となっている可能性がある。
これらの課題をクリアするには、プレイヤー側でハンドリングする必要があります。
Tweakの場合、プレイヤが纏うコスチュームを自由に入れ替えられるという設計思想があるので、一般化して動作するコードを書くのは、結構大変という印象を持ちました。今回は、リリースされているイメージに含まれる CWorkspace, CTextBox, CInputBoxの内部の階層構造を調べた結果、CTextBoxに処理を集約すれば一般化できそうだったのでそうしました。
!CTextEditor methodsFor: 'events' stamp: 'KR 6/7/2005 21:05'! onInputPointMoved | inputPt | <on: inputPointMoved> inputPt := (self inputPoint) + (self root ownerMorph topLeft). "Transcript show: inputPt; cr." ImmManager compositionWindowManager setCompositionWindowPositionX: (inputPt x) y: (inputPt y). ! ! !CTextEditor methodsFor: 'events' stamp: 'KR 6/7/2005 20:50'! onKeyboardFocusEnter "only accept input while having the keyboard focus" <on: keyboardFocusEnter> self resumeScript: #onKeyStroke:. self resumeScript: #onKeyDown:. self resumeScript: #onInputPointMoved. self signal: #inputPointMoved.! ! !CTextEditor methodsFor: 'events' stamp: 'KR 6/7/2005 20:49'! onKeyboardFocusLeave "only accept input while having the keyboard focus" <on: keyboardFocusLeave> self pauseScript: #onKeyStroke:. self pauseScript: #onKeyDown:. self pauseScript: #onInputPointMoved.! ! !CTextEditor methodsFor: 'events' stamp: 'KR 6/7/2005 21:13'! onTargetFrameChanged <on: frameChanged in: target> self signal: #inputPointMoved.! ! !CTextEditor methodsFor: 'events' stamp: 'KR 6/7/2005 21:08'! onTargetGeometryChanged <on: geometryChanged in: target> self signal: #inputPointMoved.! ! !CTextEditor methodsFor: 'events' stamp: 'KR 6/7/2005 21:04'! onTextSelectionChanged <on: textSelectionChanged in: target> self signal: #textSelectionChanged. self signal: #inputPointMoved.! !
Imm*シングルトンの管理
従来は、HandMorphのクラス変数・クラスメソッドとして管理されていましたが、これを独立したクラスに抜き出しました。HandMorph側も自分で抱え込まないようリファクタリングするほうがよいと思います。
Object subclass: #ImmManager instanceVariableNames: '' classVariableNames: 'Imm' poolDictionaries: '' category: 'Multilingual-ImmPlugin'! !ImmManager class methodsFor: 'as yet unclassified' stamp: 'KR 6/6/2005 23:30'! compositionWindowManager Imm ifNotNil: [^Imm]. SmalltalkImage current platformName = 'Win32' ifTrue: [^Imm := ImmWin32 new]. (SmalltalkImage current platformName = 'unix' and: [(SmalltalkImage current getSystemAttribute: 1005) = 'X11']) ifTrue: [^Imm := ImmX11 new]. ^Imm := ImmAbstractPlatform new! !
ウィンドウ位置の計算
CParagrpahEditor>>selectionRectを流用する方針は変えていませんが、位置がずれていたのを無理やり合わすため、マジックナンバーが入ってしまっています。ですが、CParagraphEditor>>selectionRectの中にもマジックナンバーが入っているので、当面は見逃してやってください。
!CTextEditor methodsFor: 'accessing' stamp: 'KR 6/7/2005 21:06'! inputPoint | ptLocal ptGlobal | ptLocal := (self textHolder editor selectionRect topLeft) + (Point x: 12 y: 12). ptGlobal := self textHolder costume localToGlobal: ptLocal. ^ptGlobal.! !