docklingの開発中に気がついたことを、覚え書きとしてまとめてみました。
開発中に書いたメモをまとめ直したのですが、まだあんまり整理されていません。 わかりにくい点は、どうかご容赦ください。 なお、間違いなどありましたら、ぜひ、ご指摘およびご教授をお願いいたします。
docklingの外部インターフェース 2001年7月5日
docklingは、下記のようなC言語形式の関数をエクスポートした共有ライブラリとして実装します。
この共有ライブラリは、DocklingServer.app
というアプリケーションによってロード/実行されます。
int DocklingInit()
- docklingの初期化処理を行います。正常に初期化できた場合には、
0
を返します。 CFMutableArrayRef DocklingGetMenu()
-
メニューを返します。 返り値は、辞書(
CFMutableDictionary
)を要素とする配列(CFMutableArray
)です。 メニューのアイテム毎に辞書を作成して、配列へと格納します。
辞書には、それぞれ次のような要素を格納します。
キー データの型 意味 name
CFString
メニュー・アイテムの表示名 command
CFNumber
メニュー・アイテムが選択された場合に、 DocklingDoMenuCommand
へ渡されるコマンド番号mark
CFNumber
メニュー・アイテムに付加するマークの文字コード enabled
CFBoolean
この値が kCFBooleanTrue
の時、メニュー・アイテムはイネーブルとなるseparator
CFBoolean
この値が kCFBooleanTrue
の時、メニュー・アイテムはセパレータとなる (メニュー・アイテムがセパレータの場合には、辞書にseparator
以外のキーは不要) void DocklingDoMenuCommand(int command)
- メニュー・アイテムが選択された場合の処理を行います。
void DocklingTerminate()
- docklingの終了処理を行います。
void DocklingToggle()
- 不明です。(Mac OS X 10.0〜10.0.4までのバージョンでは、このルーチンが呼び出されることはないようです)
Docklingクラスとlibdockling_glue.aライブラリ 2001年7月5日
docklingのネイティブ・インターフェースはC言語形式であり、Cocoaのフレームワークを意識したものとはなっていません。 高い開発効率を誇るCocoaなのですから、dockilingについてもCocoaを利用して効率的に作成したいものです。
そこで、Brian Webster 氏の作成したlibdockling_glue.a
というグルー・ライブラリを使用します。
このグルー・ライブラリは、前述のC言語形式のインターフェースをDockling
というクラスでラップしたものです。
Dockling
クラスは、次のようなメソッドを持っています。
libdockling_glue.a
ライブラリの入手と、それを利用したdocklingの開発の詳細については、
Brian Webster 氏の“Creating docklings on Mac OS X 10.0.4”(
http://www.stepwise.com/Articles/Technical/2001-03-30.01.html
)をご参照ください。
-(id)initWithBundle:(NSBundle*)bundle window:(NSWindow*)window
- docklingの初期化処理を行います。
-(NSMenu*)menu
- docklingのメニューを返します。
-(void)setMenu:(NSMenu*)menu
- docklingにメニューを設定します。
-(BOOL)isMenuChanged
- メニューの内容が更新された場合、
YES
を返します。 -(void)setMenuChanged:(BOOL)newState
- メニューの内容を更新したことを設定します。
-(NSBundle*)bundle
- docklingのバンドルを取得します。
-(NSWindow*)window
- ドック内に描画する際に使用するウインドウを取得します。
docklingを作成する場合には、Dockling
クラスのサブクラスを作成します。
そのサブクラスのなかで、必要に応じて上記のメソッドをオーバーライドして、docklingの振る舞いを記述します。
Interface Builderでデザインしたパネルを使う 2001年7月5日
- nibファイルの作成とロード
-
- Interface Builderを起動し、パネルのオーナー(コントローラ)となるオブジェクトのクラス
(ここでは“
PanelControler
”とします)を定義します。 PanelControler
クラスにアウトレット(ここでは“panel
”とします)を追加します。- Interface Builderの“Instances”タブを選択し、“File's Owner”アイコンをクリックします。
インスペクタ・パネルにて、“File's Owner”のクラスを
PanelControler
に設定します。 - Interface Builderで、パネルをデザインします。 デザインができたら、パネルのウインドウから、File's Ownerのpanelアウトレットへとコネクションを設定します。
- 作成したデザインをnibファイル(ここでは“
panel.nib
”というファイル名とします)へと保存します。 - Interface Builderで、
PanelControler
クラスのソース・コードを生成します。 次に、生成したソース・コードをProject Bulderで編集し、PanelControler
クラスの初期化メソッドを以下のように定義します。
-(id)initWithBundle:(NSBundle*)bundle { self = [super init]; if(self != nil) { NSDictionary *context = [NSDictionary dictionaryWithObject:self forKey:@"NSOwner"]; [bundle loadNibFile:@"panel" externalNameTable:context withZone:nil]; } return self; }
普通のアプリケーションにおいてnibファイルをロードする場合には、
NSBundle
クラスのファクトリ・メソッドであるloadNibNamed:owner:
を使用します。 でも、docklingでは、上記のソース・コードのようにloadNibFile:externalNameTable:withZone:
メソッドを使用し、docklingのバンドルを明示的に指定してnibファイルをロードします。 そうしないと、Mac OS X 10.0.4でdocklingを動かした時に、nibファイルのロードに失敗してしまうことがあるようです。 - Interface Builderを起動し、パネルのオーナー(コントローラ)となるオブジェクトのクラス
(ここでは“
- パネルの表示
-
ロードしたパネルを表示する
showPanel
メソッドを、PanelControler
クラスへ追加します。-(void)showPanel { [panel center]; [panel setLevel:NSModalPanelWindowLevel]; [[NSApplication sharedApplication] activateIgnoringOtherApps:YES]; [panel makeKeyAndOrderFront:nil]; }
ここで、
NSApplication
のインスタンスに対してactivateIgnoringOtherApps:
メッセージを送信するのがポイントです。 docklingの場合、この処理を行わないと、パネルが他のウインドウの背面に隠れて表示されてしまうことがあるようです。
メニューの更新 2001年7月5日
libdockling_glue.a
ライブラリを利用する場合、isMenuChanged
メソッドの返り値としてYES
を返すことで、ライブラリにメニューの更新が必要であることを伝えなくてはなりません。
メニュー・アイテムの個数や内容が変化した場合はもちろんですが、setState:
メソッドによってメニュー・アイテムのチェック・マークの状態が変化した場合にも、isMenuChanged
メソッドは
YES
を返さなくてはなりません。
これには、以下のような理由があります。
DocklingServer.app
は、CFMutableArray
としてメニューを受け取ります。
一方、Dockling
クラスのmenu
メソッドは、メニューをNSMenu
クラスのオブジェクトとして返す仕様となっています。
そこで、libdockling_glue.a
ライブラリの内部で、menu
メソッドから返されたNSMenu
オブジェクトをCFMutableArray
に変換し、DocklingServer.app
へと渡しています。
こうした構造になっているため、NSMenu
オブジェクトを変更しただけでは、DocklingServer.app
へ渡される
CFMutableArray
は更新されません。
CFMutableArray
の値を更新するためには、isMenuChanged
メソッドからYES
を返して、メニューの変更が行われたことをlibdockling_glue.a
ライブラリへ明示的に通知しなくてはなりません。