MOSA Multi-OS Software Artists

MOSAはソフトウェア開発者を支援します

  • iPhone/iPod touch アプリ紹介
  • MOSA掲示板
  • 活動履歴
  • About MOSA(English)

MOSA Developer News[MOSADeN=モサ伝]第170号

2005-08-02

目次

  • 「WebObjects Dev Report」    第16回  田畑 英和
  • 小池邦人の「Carbon API 徒然草」
  • SqueakではじめるSmalltalk入門  第44回  鷲見 正人
  • ニュース・解説               木下 誠

「WebObjects Dev Report」  第16回  田畑 英和

 モデルファイルの説明で1つ解説し忘れていたところがありましたので、今回はその補足からおこなっていきたいと思います。モデルの生成方法は以前説明したのですが、モデルはデータベースとオブジェクトのマッピング情報を保持しています。データを保存するのはデータベースですので、データベースの構築も別途おこなっておく必要があります。
 そのために、まずはデータベースの新規作成が必要になってきますが、こちらはデータベースの管理ソフト上であらかじめおこなっておくのがよいでしょう。OpenBaseを用いる場合は、データベースのエンコーディング指定や、システム起動時の自動起動などが管理ツール上(OpenBaseManager)で設定できます。
 データベースを作成した次は、モデルで定義したEntityやAttributeに対応するテーブルを追加していきます。モデル上にはデータベース上でのカラム名やデータ型を定義してありますので、これらの情報に基づいてテーブルを作成していけばよいわけですが、EOModelerにモデルの情報に基づいてSQLを自動生成し、データベース上にテーブルを作成する機能があります。

 ツールバーの「SQL」ボタンか「Property」メニューの「Generate SQL…」を実行しますと自動生成されたSQLを確認することができます。新規にテーブルを作成する場合は「Create Tables」にチェックをいれ「Execute SQL」ボタンをクリックすることにより、あらかじめモデルの接続情報で設定しておいた接続先のデータベースにSQLを発行することができます。また、EOFは自動的にプライマリーキーを管理しますが、この機能を利用するには「Create Primary Key Support」のチェックも入れておく必要があります。OpenBaseの場合データベースに”EO_PK_TABLE”という名前のテーブルが作成され、このテーブルで他のテーブルのプライマリーキーの管理がおこなわれます。
 モデルを変更し、テーブルの再作成が必要になった場合は、「Drop Table」にもチェックをいれておくことで、テーブルの削除と作成を同時におこなうことができますが、この場合当然古いテーブル上に保存してあったデータは削除されてしまいますので注意が必要です。
 あと注意しなければならないこととしては、データベースのチューニングがあります。EOModelerから自動的に作成したテーブルをそのまま利用しますと、データ件数によってはパフォーマンス上問題があるかもしれません。そのためインデックスの作成などは別途対応する必要が出てきます。データベースに関しては、その他にもテスト用のデータをどのように用意するかや、データベースのバックアップをどうするのかなど、検討しなければならないことは色々とあります。

 さて、これでデータベースとモデル(フレームワーク)の基本的な説明が終わりましたので、今後必要になってくる作業の概要を簡単にまとめておきたいと思います。

・プロジェクトの作成
 まずはアプリケーション本体のプロジェクトを作成しましょう。アプリケーションを開発するさいには、前回説明しましたフレームワークを利用するような場合もあるでしょうし、なんらかのライブラリを利用する場合もあるでしょう。フレームワークやライブラリはプロジェクトに登録して利用しますが、開発環境と運用環境でそれぞれ管理をおこなう必要があります。

・Webページの作成
 動的に生成するWebページのテンプレートを作成します。標準で付属するツール「WebObjects Builder」を用いてテンプレートを作成します。WebObjectsでは再利用可能なコンポーネントを作成することもできますので、複数のページで共通するような部品(メニューなど)は積極的に共通化しておくことで開発効率を高めることができます。

・カスタムEOの作成
 EOFにより、強力なデータベースアクセス機能を利用することができますが、実際にアプリケーションを作成するとなると、アプリケーション固有の機能を追加する必要が出てきます。例えば、データの初期化をおこなったり、ユーザが入力したデータの正当性を検証したりする必要があります。こういった処理を実現するための機能として、EOModelerにはクラスファイルを自動生成する機能があります。この機能を利用しますと各Entityのデータを操作するためのクラスファイルが自動生成されますので、そのクラスを利用して、データの初期化や正当性の検証処理など独自の処理を組み込んでいくことができます。

 他にもテストなど、開発に関する様々な作業がありますが、まずは主な作業の概要をまとめてみました。これらはけっして順番にやっていかなければならないというものではなく、WebObjectsの開発効率のよさを利用して必要な部分から少しずつ動作を確認しながら着手していくことがポイントになります。

小池邦人のCarbon API 徒然草(2005/07/29)

ドラッグ&ドロップの活用(その7)

今回は、前回のファイル複製処理の続きです。startMyDrag()ルーチンの中で登録しているsendDataMyDrag()ルーチンについて詳しく解説します。ドラッグアイテムとして追加されたPromiseHFSFlavor構造体やその他の情報は、このルーチンの中で解析されてファイル複製のために用いられます。

以下が、「ドラッグ&ドロップの活用(その4)」で解説したstartMyDrag()ルーチンです。ここで再掲載しておきます。実際にファイルの複製を行うsendDataMyDrag()ルーチンは、SetDragSendProc()でシステムに登録しておきます。これにより、sendDataMyDrag()は、ドラッグ開始時ではなくドラッグ終了時(ドロップ時)に、Drag Managerにより呼び出されます。最初に、startMyDrag()の処理内容について、もう少し追加の解説をしておきます。

short startMyDrag( WindowRef window,ControlRef chd,EventRecord *event )
{
    short                    chk1,chk2,ret=eventNotHandledErr;
    RgnHandle                rgn1,rgn2;
    GWorldPtr                gptr=NULL;
    DragReference            dref;
    DragSendDataUPP          fptr;
    DragAttributes           att;
    StandardDropLocation     loc;

    if( WaitMouseMoved( event->where ) )  // マウスが範囲外へ動くまで待つ
    {
        if( NewDrag( &dref ) ) // 新規のDragReferenceを得る(セッション開始)
            return( 1 );

        if( createDataMyDrag( window,chd,dref ) ) // ドラッグ用データを設定する
        {
            DisposeMyDrag( dref );
            return( 1 );
        }
        chk1=chk2=1;
        if( rgn1=NewRgn() )
            chk1=createRegionMyDrag( window,chd,rgn1 ); // ドロップ枠を作成
        if( rgn2=NewRgn() )
            chk2=createImageMyDrag( window,chd,dref,rgn2,&gptr );
                                                        // 半透明画像を作成
        if( chk1==noErr && chk2==noErr )
        {
            fptr=NewDragSendDataUPP( (DragSendDataProcPtr)sendDataMyDrag );
            ret=SetDragSendProc( dref,fptr,0 ) );
                                    // データ受け渡し用のコールバックUPPを実装
            if( ret==noErr )
                TrackDrag( dref,event,rgn1 );   // ドラッグ&ドロップの開始
            DisposeDragSendDataUPP( fptr );     // コールバックUPPを削除
            if( ret==noErr )
            {
                GetDragAttributes( dref,&att ); // ドラッグアトリビュートを得る
                if( (att&kDragInsideSenderApplication)==0 )
                                                // 別アプリへドロップされたか?
                {
                    if( ! GetStandardDropLocation( dref,&loc ) )
                    {
                        if( loc==kDragStandardDropLocationTrash )
                            deleteDataMyDrag( window,chd );
                    }   // オブジェクトがゴミ箱へドロップされた場合の処理
                }
            }
        }
        if( rgn1 )
            DisposeRgn( rgn1 );     // ドロップ枠用のRegionを削除
        if( rgn2 )
            DisposeRgn( rgn2 );     // ドロップ画像用のRegionを削除
        if( gptr )
            DisposeGWorld( gptr );  // ドロップ画像用のGworldを削除
        DisposeDrag( dref );
    }
    return( ret );
}


GetDragAttributes()で得られたアトリビュート値を調べることで、自分自身のウィンドウ上へのドロップか、別アプリケーションのウィンドウ上へのドロップかを区別することができます。また、もしドラッグアイテムのドロップ先が「Dock」のゴミ箱の中であれば(Mac OS 9ならデスクトップ上のゴミ箱)、GetStandardDropLocation()により返されたStandardDropLocationがkDragStandardDropLocationTrashとなります。よって、もし必要であれば、ドロップしたデータ(ファイルやPICT画像)を削除する処理を追加しておくことも可能です。ここでは、自作のdeleteDataMyDrag()ルーチンがその役割を担っていますが、処理内容はケースバイケースですので、詳細な解説は省略しておきます。

以下が、ドロップ時にファイルの複製を行うsendDataMyDrag()ルーチンです。まずは、GetFlavorData()でドラッグアイテムとして、PromiseHFSFlavor構造体が送られて来ているかどうかを調べます。もし送られて来ていれば、同様にGetFlavorData()を使い、複製元ファイルのFSSpec構造体(タイプは’fsc ‘)と複製先ファイル名のパスカル文字列(タイプは’str ‘)を得ます。そして、getDropDirectory()ルーチンを使うことで、ドロップ先のフォルダ(ディレクトリ)のFSSpec構造体を得ます。

pascal short sendDataMyDrag( FlavorType type,long *refcon,ItemReference item,
                                                           DragReference dref )
{
    FSSpec              fsc0,fsc1,fsc2;
    short               ret=noErr;
    Str255              name;
    long                size;
    PromiseHFSFlavor    ff1;

    size=sizeof(PromiseHFSFlavor);
    if( ! GetFlavorData( dref,item,flavorTypePromiseHFS,&ff1,&size,0 ) )
    {                             // PromiseHFSFlavor構造体を受け取る
        if( size==sizeof( PromiseHFSFlavor ) && type==ff1.promisedFlavor )
        {                        // PromiseHFSFlavor構造体かどうかを厳密に確認
            size=sizeof( FSSpec );
            if( ! GetFlavorData( dref,item,'fsc ',&fsc0,&size,0 ) )
            {                   // 複製元ファイルのFSSpec構造体を得る
                size=sizeof( Str255 );
                if( ! GetFlavorData( dref,item,'str ',&name,&size,0 ) )
                {               // 名称変更用のパスカル文字列を得る
                    if( ! getDropDirectory( dref,&fsc1 ) )
                    {           // ドロップ先のフォルダのFSSpecを得る
                        getFolderFSSpec( &fsc1,&fsc2 ); // 複製先DirIDを得る
                        copyString( name,fsc2.name );   // 複製先FSSpecを作成
                        FSpDelete( &fsc2 );             // 重ね書きを行う
                        duplicateFile( &fsc0,&fsc2 );   // ファイルの複製
                        ret=SetDragItemFlavorData( dref,item,ff1.promisedFlavor,
                                                  (Ptr)&fsc2,sizeof(FSSpec),0 );
                                // Finderにアイコン表示位置を調整させる
                    }
                }
            }
        }
    }
    return( ret );
}


以下が、ドロップ先のフォルダ(ディレクトリ)のFSSpecを返すgetDropDirectory()ルーチンです。そのFSSpecをgetFolderFSSpec()ルーチンに渡すことで、そのフォルダ自身のDirIDを得て、そこに新規のファイル名を組み合わせることで、複製先ファイルの完全なFSSpec構造体を作成しています。それを自作のduplicateFile()ルーチンに渡して、ファイルの複製を実行します。

OSErr getDropDirectory( DragReference dragRef,FSSpecPtr fssOut )
{
    AEDesc    dropLocAlias={ typeNull, nil };
    AEDesc    dropLocFSS={ typeNull, nil };
    OSErr     err1,err=noErr;
    FSSpecPtr fss;

    if( ! ( err=GetDropLocation( dragRef,&dropLocAlias ) ) )
    {                                                // ドロップされた場所を得る
        if( dropLocAlias.descriptorType!=typeAlias ) // Aliasタイプか?
            err=paramErr;
        else
        {
            if( ! ( err=AECoerceDesc( &dropLocAlias,typeFSS,&dropLocFSS ) ) )
            {                                       // FSSpec構造体へ変換
                fss=(FSSpecPtr) *(dropLocFSS.dataHandle );
                BlockMoveData( fss,fssOut,minimumBytesForFSSpec(fss) );
                                                   // 得られたFSSpecを引数で返す
                err=AEDisposeDesc( &dropLocFSS );  // FSSpec用のAEDescを削除
            }
        }
        if( dropLocAlias.dataHandle )              // Handleは確保されているか?
        {
            err1=AEDisposeDesc( &dropLocAlias );   // Alias用のAEDescを削除
            if( ! err )
                err=err1;
        }
    }
    return( err );
}

short getFolderFSSpec(FSSpec *sfsc, FSSpec *dfsc)
{
    CInfoPBRec   crec;
    short        ret;

    crec.hFileInfo.ioCompletion=0L;
    crec.hFileInfo.ioNamePtr=(StringPtr)sfsc->name;
    crec.hFileInfo.ioVRefNum=sfsc->vRefNum;
    crec.hFileInfo.ioFDirIndex=0;
    crec.dirInfo.ioDrDirID=sfsc->parID;
    ret=PBGetCatInfo( &crec,0 );        // 指定フォルダのカタログ情報を得る
    if( ! ret && ( crec.hFileInfo.ioFlAttrib&0x10 ) )  // フォルダである
    {
        *dfsc=*sfsc;
        dfsc->parID=crec.dirInfo.ioDrDirID; //そのフォルダ自身のDirIDを得る
    }
    return( ret );
}


それでは、処理の最後のSetDragItemFlavorData()は、いったい何をしているのでしょうか? 実はこの処理を追加することで、複製が完了したファイルのFSSpecをFinderに教えることができます。結果として、Finderは複製済みのファイルのアイコンをドロップした位置にちゃんと移動して表示してくれます。この処理を行わないと、複製されたファイルはウィンドウ上のドロップされた位置ではなく、ディフォルト位置に表示されてしまいます。
sendDataMyDrag()の最後の1ラインを削除すると、ドロップ終了後のアイコン表示がどうなるのかを、ぜひ試してみてください。

次回は、いよいよ「ドラッグ&ドロップの活用」の最終回です。ドラッグを実行中にテンポラリ表示される半透明の画像の作成と登録方法を解説します。例えばQuickTime PlayerからMovieをドラッグすると、ドラッグ中に小ぶりの半透明画像が表示されますが、そうした画像の作り方を紹介します。

つづく

SqueakではじめるSmalltalk入門   第44回  鷲見正人

 本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。今回は、簡易ファイラであるファイル・リストに備え付けのテキストエディタ機能についてです。

 ファイル・リストは、Finderなどの一般的なファイラが持つディレクトリ・ブラウザ機能の他に、テキストエディタの機能を備えています。下の大きめのペインはそのためのもので、選択したファイルの内容は即座にこのペインに表示されます。選択したファイルがテキストファイルなら、その内容の確認はもちろん、編集して保存することも可能です。編集後の内容を保存するには、下のペインの黄ボタンメニューから「了解」(英語メニューではaccept)を選択します。キーボードショートカットはcmd-Sです。

 Macのアプリと違い、ファイル・リストは保存の際、常に重ね書きの確認をとりにきます。重ね書きでよいときは、ポップアップから「overwrite that file」を選びます。名前を変えて保存したいときは「choose another name」のほうを選びます。改めて、a FillInTheBlank(入力欄オブジェクト)を使って保存先を訊ねてくるので、そこで適当なファイル名を入力して「了解」します。

[fig.A]重ね書きの確認ポップアップ
http://squab.no-ip.com:8080/mosaren/uploads/44a.png

 なお、ポップアップの「cancel」やファイル名入力欄の「取消」を選んだとき、エラー(ノーティファイア)が表示されますがこれは無視して(閉じてしまって)構いません。

 大きなファイルは、とりあえず最初の5000バイトだけが表示されます。下のペインの黄ボタンメニューから「get entire file」を選択することで、強制的に全体を読み込むことが可能です。ただ、ファイル・リストのテキストエディタ機能はあまり凝ったしくみにはなっていません。むやみに巨大なファイルを読み込もうとすると、なにかと支障をきたすことがあるので注意してください。もっとも、このファイル・リストに限らず、Squeakシステム自体、大きなサイズの情報を扱うことは苦手なのですが…。

 開こうとするファイルがテキストではなくバイナリ形式の場合は、ちょうど、Macでテキストエディタを使ってバイナリファイルを強制的に開いたときと同じ状態になります。その内容は意味をなしませんが、黄ボタンメニューから「view as hex」を選んで表示モードを十六進表記に切り替えることで、ある程度の対応は可能です。ただ、モード切り換え後は編集結果を保存できないなどの制約がありますから、あくまでオマケ的な機能だと割り切ったほうがよいでしょう。

 ファイル・リストは、上のペインにあるディレクトリブラウザの機能を切り離して、下のペインだけ、つまりテキストエディタとしてのみ機能させることも可能です。じつは、これまで何度か出てきた

(FileList fileNamed: ‘test.txt’) edit

という式は、test.txtというファイルを、このテキストエディタ“モード”のファイル・リストで開くためのものでした。ファイルストリームへのeditの送信によって起動するメソッドの定義は次のようになっています。

FileStream >> edit
   FileList openEditorOn: self editString: nil.

 これと同じことは、デスクトップメニューの「開く…」→「ファイル…」でポップアップからファイル名でファイルを選んで開く作業でもできます。

 テキストエディタモードで動くファイル・リストのウインドウの見た目は、ワークスペースのそれにたいへんよく似ています。これは、両者がまったく同じクラスに属するGUIオブジェクト(ウインドウ、テキスト編集枠)により構成されているためで、まあ当然といえばそれまでです。ただ、それぞれの“中核”にある(つまりMVCでいうところの「モデル」として働く)オブジェクトが別物であるため、その振る舞いには違いが生じるカラクリになっています。目に付きやすい所では、たとえば、両者では黄ボタンメニューの内容が異なります。

[fig.B]同じGUIオブジェクトでもモデルが違えば振る舞いも違ってくる
http://squab.no-ip.com:8080/mosaren/uploads/44b.png

 さて。最後に、もともとの話題であった日本語ファイルについて。残念ながらNihongo7では、日本語ファイルのファイル・リストでの扱いにはちょっとした問題があります。普通に開いただけでは、ファイルの内容が文字化けしてしまうのです。たとえば、第42回で作ったシフトJISのファイル「ShiftJisExample.txt」(もしくは、Macのテキストエディタで作成した適当な日本語テキストファイル)を「開く…」→「ファイル…」や次の式で開こうとしても文字化けしてしまい、その内容は正しく表示されません。

(FileStream fileNamed: ‘ShiftJisExample.txt’) edit

 Nihongo6まではきちんと表示されていたのですが、多言語化機構の公式英語版への取り込みに際して行なわれた仕様見直しの影響で、ファイル・リストの表示には常にa Latin1TextConverterが使われるようになってしまったのがこの文字化けの原因です。黄ボタンメニューの表示モードの切り換え「view as encoded text」で適切な文字コードを選択することで、とりあえずこの問題は回避できます。

[fig.C]文字コードの切り換え
http://squab.no-ip.com:8080/mosaren/uploads/44c.png

 ただ、ファイルを開くたび、文字コードをいちいち切り換えるのは面倒ですし、十六進表示モードへの切り換え時同様、編集後の保存ができないなど、使い勝手の面での不満も残ります。そこで次回は、.txtまたは.textという拡張子のファイルを開いたときだけは、デフォルトのa Latin1TextConverterの代わりにa ShiftJISTextConverterを使用してくれるように、ファイル・リストの機能をちょっとだけいじってみることにします。

バックナンバー:
http://squab.no-ip.com:8080/mosaren/

ニュース・解説

今週の解説担当:木下 誠

———————————————————————-
CodeWarrior 10が秋に登場、
PowerPlantおよびPowerPlant Xがオープンソース化
———————————————————————-

ADHOC (The Advanced Developers Hands On Conference)にて、Metrowerksのセッション「Bash Metrowerks」が行われ、その中でCodeWarrior 10の登場、PowerPlant、PowerPlant X、Constructorのオープンソース化が発表されたそうです。

セッションに参加された方のノートによると、

・CodeWarrior 10は、秋に登場。ターゲットはMac OS X 10.2
・Intelチップ用のコンパイルは行なわれない。PowerPlantは、Intelホスト上では、少しの作業で動く
・PowerPlant、PowerPlant X、Constructorはオープンソース化、IDEはオープンソース化されない
・CodeWarrior 10でおそらく最後、サポートは今年の終わりまで
・x86関連は、Nokiaが買収

などが明らかになったそうです。

事実上、CodeWarriorは終焉、Intel対応は行われない、ということになりました。ただし、PowerPlantとPowerPlant Xがオープンソース化されるので、有志によるIntel対応の道が開けた、と言えるでしょう。

The Advanced Developers Hands On Conference
http://www.adhocconference.com/
Driss-A-Blog: The CodeWarrior roadmap
http://www.drissman.com/blog/archives/2005/07/29/the_codewarrior_roadmap.html

———————————————————————-
Core Dataプログラミングガイド日本語訳
———————————————————————-

アップルジャパンのサイトに、Core Dataプログラミングガイドの日本語訳が登場していました。Tigerから搭載されている、Cocoaのモデルレイヤーを受け持つCore Dataですが、データベースを由来とする技術なので、そちらの分野で使われる用語が多く見られます。日本語訳の登場は、理解の助けになるでしょう。

ここ数ヶ月、アップルジャパンはいままでとは比べ物にならない勢いで、ドキュメントの日本語訳を公開しています。まだまだごくわずかなドキュメントしか翻訳されていませんが、この傾向が維持されることを期待したいところです。

Core Dataプログラミングガイド
http://developer.apple.com/ja/documentation/cocoa/Conceptual/CoreData/index.html

———————————————————————-
Xsan 1.1への移行ガイド
———————————————————————-

6月に発表されたXsan 1.1への、移行ガイド「Xsan Migration Guide」が公開されました。Xsan 1.0から1.1への移行の説明になります。

PantherおよびTiger上でXsanを動作させている場合の、移行手順が説明されています。

Xsan Migraion Guide
http://images.apple.com/server/pdfs/20050725_Xsan_Migration_Guide.pdf

———————————————————————-
Comic Lifeの開発チームの紹介
———————————————————————-

最近、ADCで中小のソフトウェアベンダーがよく紹介されていますが、今回はComic Lifeを開発したplasqが紹介されています(plasq Shows What a Small Team Can Do: Comic Life Is Media-Rich and Fun to Use)。Comic Lifeは、今年のWWDCでApple Design Awardを受賞した、グラフィックソフトです。

記事では、plasqがCocoa、Core Image、.Mac、iPhotoといった技術を使って、小さいチームでアプリケーションを作り上げた事例が紹介されています。

plasq Shows What a Small Team Can Do: Comic Life Is Media-Rich and Fun to Use
http://developer.apple.com/business/macmarket/plasq.html

———————————————————————-
サンプル、Technical NoteのUniversal Binary化続く
———————————————————————-

7月の初めから、ADCのサンプルが多数更改され続けています。この多くは、Universal Binary化を行うためのものです。今週も、この更改が多く行われました。

また、QuickTimeコンポーネントの作成を解説したTechnical Note、「TN2012: Building QuickTime Components for Mac OS X」も更新されました。これも、Universal Binaryに対応するためのものです。

TN2012: Building QuickTime Components for Mac OS X
http://developer.apple.com/technotes/tn/tn2012.html

MOSAからのお知らせと編集後記は割愛します

MOSA Developer News   略称[MOSADeN=モサ伝]
Apple、Mac OSは米国アップルコンピュータ社の登録商標です。またそのほかの各製品名等はそれぞれ各社の商標ならびに登録商標です。
このメールの再配信、および掲載された記事の無断転載を禁じます。
特定非営利活動法人MOSA
Copyright (C)2005 MOSA. All rights reserved.