Lower Decks:dockling覚え書き

docklingの開発中に気がついたことを、覚え書きとしてまとめてみました。

開発中に書いたメモをまとめ直したのですが、まだあんまり整理されていません。 わかりにくい点は、どうかご容赦ください。 なお、間違いなどありましたら、ぜひ、ご指摘およびご教授をお願いいたします。


docklingの外部インターフェース 2001年7月5日

docklingは、下記のようなC言語形式の関数をエクスポートした共有ライブラリとして実装します。 この共有ライブラリは、DocklingServer.appというアプリケーションによってロード/実行されます。

2001年7月5日現在、アップルからdocklingのインターフェースや作成方法は公表されていません。 下記の情報は、Riley Lynch 氏が開発した “Space.dock”(http://space.sourceforge.net/) のソース・コードを元に、私がまとめなおしたものです。
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ファイルの作成とロード
  1. Interface Builderを起動し、パネルのオーナー(コントローラ)となるオブジェクトのクラス (ここでは“PanelControler”とします)を定義します。
  2. PanelControlerクラスにアウトレット(ここでは“panel”とします)を追加します。
  3. Interface Builderの“Instances”タブを選択し、“File's Owner”アイコンをクリックします。 インスペクタ・パネルにて、“File's Owner”のクラスをPanelControlerに設定します。
  4. Interface Builderで、パネルをデザインします。 デザインができたら、パネルのウインドウから、File's Ownerのpanelアウトレットへとコネクションを設定します。
  5. 作成したデザインをnibファイル(ここでは“panel.nib”というファイル名とします)へと保存します。
  6. Interface Builderで、PanelControlerクラスのソース・コードを生成します。 次に、生成したソース・コードをProject Bulderで編集し、PanelControler クラスの初期化メソッドを以下のように定義します。
  7. -(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ファイルのロードに失敗してしまうことがあるようです。

パネルの表示

ロードしたパネルを表示する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ライブラリへ明示的に通知しなくてはなりません。

作成:2001年7月5日, © 2001 raktajino,All rights reserved. raktajino@mac.com