docklingの開発中に気がついたことを、覚え書きとしてまとめてみました。
開発中に書いたメモをまとめ直したのですが、まだあんまり整理されていません。 わかりにくい点は、どうかご容赦ください。 なお、間違いなどありましたら、ぜひ、ご指摘およびご教授をお願いいたします。
docklingの外部インターフェース 2001年7月5日
docklingは、下記のようなC言語形式の関数をエクスポートした共有ライブラリとして実装します。
この共有ライブラリは、DocklingServer.appというアプリケーションによってロード/実行されます。
int DocklingInit()- docklingの初期化処理を行います。正常に初期化できた場合には、
0を返します。 CFMutableArrayRef DocklingGetMenu()-
メニューを返します。 返り値は、辞書(
CFMutableDictionary)を要素とする配列(CFMutableArray)です。 メニューのアイテム毎に辞書を作成して、配列へと格納します。辞書には、それぞれ次のような要素を格納します。
キー データの型 意味 nameCFStringメニュー・アイテムの表示名 commandCFNumberメニュー・アイテムが選択された場合に、 DocklingDoMenuCommandへ渡されるコマンド番号markCFNumberメニュー・アイテムに付加するマークの文字コード enabledCFBooleanこの値が kCFBooleanTrueの時、メニュー・アイテムはイネーブルとなるseparatorCFBooleanこの値が 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ライブラリへ明示的に通知しなくてはなりません。