MOSA Multi-OS Software Artists

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

プログラマーに興味がある方なら誰でも入会いただけます。
MOSA Multi-OS Software Artists
===SINCE 1995===

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

MOSADenバックナンバー 2006年4月発行分

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

    2006-04-25
     

    目次

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

    「WebObjects Dev Report」  最終回  田畑 英和

     さて、今回で「WebObjects Dev Report」は最終回となります。今回はアプリケーションをデータの登録用と閲覧用に分割し、2つのアプリケーションの共通分をフレームワーク化した結果を解説します。
     まずは、これまで開発したアプリケーションを実際にInternet上でアクセスできるようにしてありますので、こちらのURLをご紹介します。

    ・単体アプリケーション版
    http://210.175.246.197/cgi-bin/WebObjects/MOSAJobMatchTest.woa
    ・分割フレームワーク版
    http://210.175.246.197/MOSAJobMatchTest.html

     どちらのバージョンも同じコードに基づいていますが、それぞれプロジェクトの構造が異なります。また分割フレームワーク版では2つのアプリケーションを使用するためトップページは通常のHTMLファイルとして作成し、それぞれのアプリケーションへのリンクを作成してあります。

    ◇プロジェクトの構造
     それではプロジェクトの構造を解説しましょう。分割フレームワーク版では次のように3つのプロジェクトからシステム全体が構成されています。

    ・データ登録用アプリケーション
    MOSABusinessRegister
    ・データ閲覧用アプリケーション
    MOSABusinessFinder
    ・フレームワーク
    MOSABusiness

    ◇フレームワーク(MOSABusiness)
     フレームワーク用プロジェクトでは2つのアプリケーションで共通する各種ファイルを管理しています。フレームワークでは次のようなファイルを管理しています。

    ・アプリケーション、セッションクラス
     Application.java、Session.javaで共通する処理をまとめたクラスをフレームワークにMOSABusinessApplication.javaとMOSABusinessSession.javaとして実装しました(クラス名は前回紹介したものから変更しています)。
    ・カスタムEOクラス
     ジェネレーションギャップパターンを利用して作成したカスタムEOのクラスファイルです。分割前のプロジェクトで使用していたファイルを、そのままフレームワークに移動しました。
    ・Webコンポーネント
     2つのアプリケーションで共通して利用するReusable Componentです。ページのレイアウトを実装したPageTemplateと各ページのヘッダーおよびフッター(Header、Footer)をフレームワークに移動しました。またコンポーネント用の親クラスも移動してあります。
    ・モデルファイル
     両方のアプリケーションから共通のデータベースへアクセスするため、フレームワークにモデルを移動しました。
    ・Webサーバリソース
     画像ファイルおよびCSSファイルをフレームワークに移動しました。画像ファイルは数が多いため、すべてフレームワークに移動してあります。

    ◇データ登録用アプリケーション(MOSABusinessRegister)
    ◇データ閲覧用アプリケーション(MOSABusinessFinder)
     フレームワークに共通部分を移動したために、アプリケーション本体には、アプリケーションに依存したファイルのみを登録しました。

    ・アプリケーション、セッションクラス
     アプリケーションのApplication.javaとSession.javaは、フレームワークのMOSABusinessApplication.javaとMOSABusinessSession.javaを継承して実装しました。
    ・Webコンポーネント
     アプリケーションではフレームワークに実装したReusable Componentを使用しています。また画像ファイルもフレームワークのものを使用していますが、WOImageのframeworkプロパティを”MOSABusiness”と指定して、フレームワークを明示的に設定しています。
    ・モデルファイル、Webサーバリソース
     アプリケーション側にモデルファイルやWebサーバリソースは存在しません。
    ・フレームワーク
     MOSABusiness.frameworkを参照しています。

     このように共通部分をフレームワークに集約したために、各プロジェクトでのファイル数は分割前の1/3程度に減らすことができました。アプリケーションは2つに分割しましたが、フレームワーク部分を改良すれば、両方のアプリケーションに反映されることになります。
     なお今回解説しましたプロジェクトは下記のURLでダウンロードすることができます。

    ・プロジェクトダウンロード
    http://210.175.246.197/WebObjects/mosa/MOSABusiness_Framework.zip

    ◇課題
     これにて連載は終わりになりますが、最後に今後アプリケーションを改良する場合の課題を上げておきましょう。
     まず、アプリケーション間でのデータの同期に関する問題があります。アプリケーションを2つに分割したため、それぞれのアプリケーションでデータをキャッシュすることになります。よって登録用アプリケーションで登録したデータが、閲覧用アプリケーションですぐに確認できないことも考えられます。
     また機能的な強化も考えられます。現在のアプリケーションではユーザ登録の機能やデータを登録するさいの質問項目を管理する機能がありません。

    さて、約1年間にわたってWebObjectsでアプリケーションを開発する過程をレポートしてきましたが、いかがでしたでしょうか。皆さんの開発に少しでもお役にたてたなら幸いです。次回からはテーマを変えてMac OS X Serverに関する連載を新たにスタートさせます。ご期待ください。

    小池邦人のCarbon API 徒然草(2006/04/21)

    〜 アプリケーションのUniversal Binary化(その7) 〜

    今回は、前回に引き続いてもう少しリソースデータについての例題を調べてみます。また、効率の良いエンディアンの反転方法についても考察してみます。

    以下のaddIconResources()は、FSpOpenResFile()などでオープンされたカレントのリソースファイルに、48×48ピクセルのフルカラー画像アイコンリソースを付加するルーチンです。何故だか、現在のCarbon APIやQuickTime APIにはファイル(JPEGやTIFF)に画像アイコンを手軽に付加するAPIが存在しないために、こうした自作ルーチンが必要となります。アイコン用の画像は、引数で渡されたCGrafPtr(GWorldオフスクリーン)に先んじて描画されていることが条件です。

    ここでは、リソースタイプが’icns’でリソースIDが-16455のリソースをAddResource()を用いて付加しています。’icns’リソースは、マスク画像、白黒画像、フルカラー画像など複数のアイコン情報を含むデータ構造を取っています。そのため、データの先頭に各データのタイプ(’icns’と’ich#’と’ih32′)とそのサイズ(容量)を保存します。これらの情報(数値)は、すべてビッグエンディアンフォーマットでリソースフォークへ保存されていますので、Intel CPU版のアプリケーションでは保存前にエンディアンを反転する必要があります。

    short addIconResources( CGrafPtr off )
    {
        long            size1=9216L+576L+24L;  // リソース全体のサイズ(容量)
        long            size2=576L+8L;         // "ich#"データのサイズ
        long            size3=9216L+8L;        // 'ih32'データのサイズ
        OSType          type1,type2,type3;
        Ptr             addr,optr,dptr;
        Rect            srt,drt,frt;
        GWorldPtr       off1,gptr;
        short           row,i;
        GDHandle        ghd;
        PixMapHandle    phd;
        Handle          hd;
    
        type1='icns';
        type2='ich#';
        type3='ih32';
        hd=NewHandleClear( size1 );  //  アイコン保存用メモリ領域をHandleとして確保
        if( ! hd )
            return( 1 );
        HLock( hd );
        dptr=*hd;
    
        #if __LITTLE_ENDIAN__      // Intel CPU版のみ#endifまでコンパイルされる
    
        type1=Endian32_Swap( type1 );  // 利用するOSTypeを反転する
        type2=Endian32_Swap( type2 );
        type3=Endian32_Swap( type3 );
        size1=Endian32_Swap( size1 );  // 利用するデータサイズ(long値)を反転する
        size2=Endian32_Swap( size2 );
        size3=Endian32_Swap( size3 );
    
        #endif
    
        BlockMoveData( &type1,dptr,4L );  // OSType 'icns'
        dptr+=4;
        BlockMoveData( &size1,dptr,4L );  // リソースデータ全体のサイズ(容量)
        dptr+=4;
        BlockMoveData( &type2,dptr,4L );  // OSType 'ich#'
        dptr+=4;
        BlockMoveData( &size2,dptr,4L );  // 'ich#'データのサイズ
        dptr+=4;
    
        GetGWorld( &gptr,&ghd );
        SetRect( &srt,0,0,48,48 );      // アイコンの矩形サイズは48x48ピクセル
        GetPortBounds( off,&frt );      // ソース画像の矩形枠
        OffsetRect( &frt,-frt.left,-frt.top );
        fitRect( 1,&srt,&frt,&drt );   // ソース画像の矩形枠を合わせる自作ルーチン
        if( ! NewGWorld( &off1,1,&srt,0L,0L,0 ) ) // 白黒画像とマスク用1bit GWorld
        {
            phd=GetGWorldPixMap( off1 );
            LockPixels( phd );
            addr=GetPixBaseAddr( phd ); // GWorldメモリ領域の先頭アドレスを得る
            row=GetPixRowBytes( phd );  // GWorldメモリ領域のRow Bytesを得る
            SetGWorld( off1,ghd );
            EraseRect( &srt );
            CopyBits(GetPortBitMapForCopyBits(off),GetPortBitMapForCopyBits(off1),
                                                                &frt,&drt,0,NULL );
            FrameRect( &drt );
            optr=addr;
            for( i=0;i<48;i++ )  // 白黒アイコン画像データを転送
            {
                BlockMoveData( optr,dptr,6L );
                optr+=row;
                dptr+=6;
            }
            PaintRect( &drt );
            optr=addr;
            for( i=0;i<48;i++ )  // 白黒アイコンマスクデータを転送
            {
                BlockMoveData( optr,dptr,6L );
                optr+=row;
                dptr+=6;
            }
            DisposeGWorld( off1 ); // GWorldを削除
    
            BlockMoveData( &type3,dptr,4L );  // OSType 'ih32'
            dptr+=4;
            BlockMoveData( &size3,dptr,4L );  // 'ih32'データのサイズ
            dptr+=4;
    
            SetGWorld( gptr,ghd );
            if( ! NewGWorld( &off1,32,&srt,NULL,NULL,0 ) )
            {                           // フルカラーアイコン画像用321bit GWorld
                                        // 画像フォーマットはビッグエンディアン
                phd=GetGWorldPixMap( off1 );
                LockPixels( phd );
                addr=GetPixBaseAddr( phd ); // GWorldメモリ領域の先頭アドレスを得る
                row=GetPixRowBytes( phd );  // GWorldメモリ領域のRow Bytesを得る
                SetGWorld( off1,ghd );
                EraseRect( &srt );
                CopyBits(GetPortBitMapForCopyBits(off),
                                  GetPortBitMapForCopyBits(off1),&frt,&drt,0,NULL );
                FrameRect( &drt );
                optr=addr;
                for( i=0;i<48;i++ )  // フルカラーアイコン画像データを転送
                {
                    BlockMoveData( optr,dptr,192L );
                    optr+=row;
                    dptr+=192;
                }
                DisposeGWorld( off1 ); // GWorldを削除
                SetGWorld( gptr,ghd );
                AddResource( hd,'icns',-16455,"\p" ); // 'icns'リソースを付加
                return( 0 );
            }
        }
        DisposeHandle( hd ); // メモリ領域を開放
        return( 1 );
    }
    


    こうして見てくると、エンディアンの反転は、データをファイルに保存する直前かファイルから読み込んだ直後に行うことが多いようです。しかし、こうした処理をファイルI/Oが発生する度にいちいち追加していては面倒ですし、必要な処理を見落としてしまう危険性もあります。そこで、以下の様にFSWriteFork()やFSReadFork()と自作フリッパーを組み合わせた上位ファイルI/Oルーチンを用意しておくと便利です。ファイルへ読み書きするフォーマット(構造体)の種類をOSTypeで指示してやることで、エンディアンの反転処理を一元管理することが可能です。ちょうどApple社が用意したカスタムリソースデータのフリッパーと同じ仕組みです。

    OSErr writeFile( OSType type,short fref,ByteCount size,Ptr buf )
    {
        OSErr        err;
        ByteCount    ss;
    
        flipFile( type,size,buf );    //  構造体のエンディアンをひっくり返す
        err=FSWriteFork( fref,fsAtMark,0,size,buf,&ss ); // ファイルへの書き込み
        flipFile( type,size,buf );    //  構造体のエンディアンを元に戻す
        return( err );
    }
    
    OSErr readFile( OSType type,short fref,ByteCount size,Ptr buf )
    {
        OSErr        err;
        ByteCount    ss;
    
        err=FSReadFork( fref,fsAtMark,0,size,buf,&ss ); // ファイルからの読み込み
        if( err==noErr )
            flipFile( type,size,buf );   //  構造体のエンディアンをひっくり返す
        return( err );
    }
    
    void flipFile( OSType type,long size,Ptr buf )
    {
        #if __LITTLE_ENDIAN__  // Intel CPU版のみ#endifまでコンパイルされる
        switch( type )
        {
            case 'pref':
    
                flipPref( (PrefPtr)buf );  // Pref構造体反転の自作ルーチン
                break;
    
            case 'list':
    
                flipLst( (LstPtr)buf );  // List構造体反転の自作ルーチン
                break;
    
            case 'head':
    
                flipHeader( (HeaderPtr)buf ); // Header構造体反転の自作ルーチン
                break;
    
            case 'indx':
    
                flipIndex( (IndexPtr)buf ); // Index構造体反転の自作ルーチン
                break;
        }
        #endif
    }
    


    こうした処理が必要なのは、ファイル保存されているデータフォーマットがエンディアンの違いに影響を受ける場合に限られます。つまり、shortやlongの整数値、floatやdoubleの浮動小数点値が、そのままファイルへ保存されている場合です。保存フォーマットがリトルエンディアンであれば、PowerPC用アプリケーションのファイルI/Oで反転する必要がありますし、逆にビッグエンディアンであればIntel CPU用アプリケーションで反転する必要があります。ちなみに、保存形式がテキストデータやXMLデータなどエンディアンの違いに影響されないフォーマットであれば、その必要はありません。

    次回は、画像(ビットフィールド)を処理するアプリケーションにおけるエンディアンの違いの影響について調べてみます。例題として、OpenGLのテクスチャ画像を作成する場合などについて解説する予定です。

    つづく

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

     本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。前回は少々寄り道をして、ジョブズやアトキンソンたちが1979年のPARC見学の際にかいま見たであろう、ALTO/Smalltalkシステム、つまり暫定ダイナブック環境の持つ動的性を、メニューのポップアップの挙動を変更する作業を通じて、プチ体験していただきました。今回は、再びポップアップメニューの“解剖”に戻りたいと思います。

    念のため、観察用のメニューをポップアップさせるスクリプトを再掲します。

    | menu |
    menu := MenuMorph new.
    menu defaultTarget: 1.
    menu add: 'default (one)' action: #inspect.
    menu addLine.
    menu add: 'two'   target: 2 selector: #inspect.
    menu add: 'three' target: 3 selector: #inspect.
    menu add: 'four'  target: 4 selector: #inspect.
    menu addLine.
    menu
       add: 'open workspace'
       target: Workspace
       selector: #openLabel:
       argument: 'My New Workspace'.
    menu invokeModal

     ワークスペースなど適当な場所にこのスクリプトを貼り付けて、全体を選択してからdo it(cmd + D)するとメニューを呼び出せます。前々回はこのメニューをモーフとして選択しインスペクト(検査)しました。今回は、メニューを構成するメニュー項目の中味をインスペクトしてみることにします。

    スクリプトの記述からも伺えるように、そして、#add:action:、#add:target:selector:などのメソッドをシステムブラウザを使って“上流”に遡ることで#addMorphBack:メソッドの起動を確認できることからも、メニュー項目モーフ(a MenuItemMorph)がメニューモーフ(a MenuMorph)のサブモーフとして登録されていることは、すでにご説明したとおりです。

    あるモーフに登録されたサブモーフをインスペクトするためには、コマンドクリックを繰り返す方法をすでに紹介済みですが、今回は、インスペクタの新たな操作法のレクチャーを兼ねて、サブモーフ群がオーナーのsubmorphsというインスタンス変数に束縛されていることを利用することにします。

    まず、オーナーモーフであるメニューをコマンドクリックでモーフとして選択。現れたハローのうち右手上から二番目のグレイのハロー(デバッグハロー)をshiftキーを押しながらクリックすると、そのメニューのインスペクタを開くことができます。この操作はすでにお馴染みですね。

    では次に、開いたインスペクタで、左手のリストペインのsubmorphsをダブルクリックしてみてください。するとsubmorphsに束縛されている配列(an Array)のインスペクタが現れます。Smalltalkシステムでは、このようにインスペクタを介して、オブジェクトのネットワークの海の深みに向かって次々に“ダイブ”してゆくことが可能となっています。

    [fig.A]submorphsのダブルクリックで現れた新しいインスペクタ

     さて。我々が興味を持つサブモーフとしてのメニュー項目は、今、インスペクト中の配列の要素として束縛されています。メニュー項目は五つなのに、この配列には七つの要素があることを不思議に思ったかたは、メニュー項目だけではなく、区切り線もモーフ(a MenuLineMorph)であり、サブモーフとして登録されていることを思い出してください。

    区切り線の二番目と六番目以外はメニュー項目なので、どれを選んでもかまわないのですが、ここでは最後の要素、つまり、選択するとワークスペースを開くメニュー項目を観察することにしましょう。

    インデックス「7」の要素をダブルクリックして改めてインスペクタを開いてみてください。このとき、すでに項目が選択されているとダブルクリックしてもうまくインスペクタが開かないことがあります。いったんクリックして選択を解除してから改めてダブルクリックするか、ダブルクリック操作ではなくinspect it(cmd + I)をタイプしてください。インスペクタが開いたら、内容を見やすくするために、右下付近にポインタを合わせ、すこしウインドウサイズを大きめにしましょう。

    [fig.B]配列のインスペクタから呼び出したメニュー項目のインスペクタ

     左手のリストペインに、メニュー項目モーフに用意されたインスタンス変数が列挙されています。最後のほうにあるtarget、selector、argumentsに注目してください。これらには、前述のスクリプトでこのメニュー項目を追加するときに指定した、ターゲットであるWorkspace、セレクタである#openLabel:、メッセージ送信に際して必要になるパラメータ(引数)として、'My New Workspace'を要素に持つ配列がそれぞれ束縛されているはずです。

    メニュー項目は自らが選択されると、指定されたターゲットに、セレクタとパラメータを組み合わせたメッセージ(このメニュー項目では、「openLabel:'My New Workspace'」というメッセージ)を送信することで、その役割を果たします。試しに、このインスペクタで別のターゲットにすげ替えて、メニュー項目を選んだときにどんな挙動を示すかを観察してみましょう。

    インスペクタの左手リストペインからtargetを選択します。右手のペインには今は束縛されているWorkspaceが表示されます。これを「Transcript」と書き換えてaccept(cmd + S)します。すると、ペインの内容は「a TranscriptStream ''」と変わります。これで、メッセージの送り先をクラスWorkspaceからトランスクリプト(TranscriptStreamのインスタンス。グローバル変数のTranscriptに束縛されている…)への、すげ替えが完了です。トランスクリプトも「openLabel: aLabelString」というメッセージを受けることができるので、問題はありません。

    では、おおもとのメニューに戻って「open workspace」を選択してみてください。もし、何らかの理由でメニューがすでに消えてしまっていたら、最初に開いたメニューのインスペクタで「self openInWorld」をdo it(cmd + D)することで再び呼び出すことができます。

    さて。メニュー項目を選択後に開いたウインドウは、一見、ワークスペースのように見えますが、さにあらず。これはれっきとしたトランスクリプト(標準出力もどき)ウインドウです。その証拠に、どこか適当な場所、たとえば、インスペクタの下部にあるペインで、

    Transcript show: 'Hello World'

    とタイプしてからdo it(cmd + D)すると、「Hello World」ときちんと表示されるはずです。

    バックナンバー:

    ニュース・解説

     今週の解説担当:木下 誠

    ----------------------------------------------------------------------
    WWDCにてLeopardをプレビューすることが告知
    ----------------------------------------------------------------------

    8月の7日から11日にかけて行われる、今年のWWDC (Worldwide Developers Conference)のページが更新されました。正式に、LeopardことMac OS X 10.5のプレビューを行う事を告知しています。

    また、セッションの紹介も公開されています。セッションは5つのトラック(Application Technologies、Development Tools、Graphics and Media、Information Technologies、OS Foundations)に分かれており、合計で120以上のセッションが予定されています。

    現在のところ、それぞれのトラックの紹介には、Leopardに関する新しい情報はないようです。もともと、ほとんどのセッションがNDAになるため、Webページで公開される情報は少ないのですが。

    WWDC 2006
    http://developer.apple.com/wwdc/

    ----------------------------------------------------------------------
    J2SE 5.0 Release 4がリリース
    ----------------------------------------------------------------------

    J2SE (Java 2 Standard Edition) 5.0がバージョンアップした、J2SE 5.0 Release 4がリリースされています。

    このリリースから、JavaはデフォルトでJ2SE 5.0、つまりjava 1.5、を使用するようになりました。ただし、以前のバージョンであるjava 1.4はそのまま残されているので、切り替えて利用することが可能です。

    同時に、J2SE 5.0 Release 4のリリースノートも公開されています。修正されたバグ、および認識されているバグが記述されていますので、Javaを利用している開発者の方は、要チェックです。EOModeler、JBuilder、OpenBase JDBCとの不具合などがあります。

    About Java 2 Standard Edition (J2SE) 5.0 Release 4
    http://docs.info.apple.com/article.html?artnum=302983

    J2SE 5.0 Release 4 Release Notes
    http://developer.apple.com/releasenotes/Java/Java50Release4RN/index.html

    ----------------------------------------------------------------------
    Javaに関するTNとQA
    ----------------------------------------------------------------------

    J2SE 5.0のバージョンアップに加えて、Javaに関するTechnical NoteとQ&Aが公開されています。

    「TN2147: JNI Development on Mac OS X」は、Mac OS XでのJNI (Java Native Interface)の開発方法について述べられています。単なるJNIの使い方だけではなく、CocoaやCore Foundationの間での、オブジェクトの変換、グラフィック環境へのアクセス、スレッドセーフの実現、Java仮想マシンの呼び出しなどが議論されています。

    「QA1474: UnsupportedClassVersionError With J2SE 5.0 Release 4」では、J2SE 5.0 Release 4をインストールしたときに、コンパイルで発生する問題について解説しています。XcodeのターゲットVMと、Javaコンパイラが作成するバイドコードのバージョンが異なる場合、問題が発生するようです。

    TN2147: JNI Development on Mac OS X
    http://developer.apple.com/technotes/tn2005/tn2147.html

    QA1474: UnsupportedClassVersionError With J2SE 5.0 Release 4
    http://developer.apple.com/qa/qa2006/qa1474.html

    ----------------------------------------------------------------------
    ATSによるフォント一覧の取得
    ----------------------------------------------------------------------

    ATS (Apple Type Services)を使って、インストールされているフォントの一覧を取得する方法を解説した、「QA1471: Enumerating fonts with ATS」が公開されています。

    ATSFontIteratorNextか、ATSFontFamilyIteratorNextを使って、一覧を取得します。ただし、取得には長い時間がかかる事、取得中にユーザがフォントの構成を変更するとエラーが発生する事、が注意点として挙げられています。

    QA1471: Enumerating fonts with ATS
    http://developer.apple.com/qa/qa2006/qa1471.html

     

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

     

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

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

    2006-04-18

    目次

    • 「WebObjects Dev Report」     第47回  田畑 英和
    • 藤本裕之のプログラミング夜話 #89
    • 高橋真人の「プログラミング指南」  第87回
    • ニュース・解説                小池 邦人

     

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

     前回はアプリケーションの利用方法を解説しましたが、今回はビジネスマッチングシステムのプロジェクトを実際にフレームワーク化する方法を紹介してみたいと思います。アプリケーション単体で起動するバージョンはすでに以下のURLでプロジェクトを公開していますが、こちらのプロジェクトをアプリケーション本体とフレームワークに分離してみたいと思います。

    ・プロジェクトのダウンロードURL
    http://210.175.246.197/WebObjects/mosa/MOSAJobMatch_0330.zip

    ◇プロジェクトの構造
     まず現状のプロジェクトの構造ですが、本プロジェクトは以下のようなファイルで構成されています。

    ・Javaソースコード
      -Application.java, Session.java, DirectAction.java
      -カスタムEO
    ・Webコンポーネント
      -Main.woなどのコンポーネント
      -Header.woやFootor.woなどのReusableコンポーネント
    ・リソース
      -Propertiesファイル
      -モデルファイル
    ・Webサーバリソース
      -CSSファイル
      -画像ファイル

     フレームワークに移行するファイルをまずは決めたいと思います。フレームワークに移行するかどうかは、アプリケーションに依存せず汎用性があるかどうかや、複数のアプリケーションから共有するかどうかがポイントになります。
     とはいいましても、本プロジェクトではアプリケーションを1つしか作成していません。そこでアプリケーションを機能別に2つに分離して、さらに共通部分をフレームワーク化してみたいと思います。
     アプリケーションの分離ですが、機能的には大きく分けてデータの登録と参照に分かれますので、データ登録用のアプリケーションと、データの参照用のアプリケーションに分けてみたいと思います。

    ◇Javaソースコード
     まず、JavaソースコードですがApplication、Session、DirectActionの各クラスファイルはアプリケーションに関する機能を実装しますので、これらはそのままアプリケーション本体に残します。
     ですが、アプリケーション間で共有できるような処理は、その部分を親クラス化してフレームワークで実装します。通常Applicationクラスは次のような階層関係を持っていますが、WOApplicationを継承したクラスをフレームワークに実装しておきます。

    ・通常のApplicationの継承関係
    WOApplication <- Application
    ・独自の親クラスを作成した場合の継承関係
    WOApplication <- MOSAApplication <- Application

     各アプリケーションのApplicationクラスでの共有処理をMOSAApplicationクラスに実装し、アプリケーション側のApplicationクラスはMyApplicationクラスを継承するように変更します。本プロジェクトではエンコーディング処理に関する部分が共有処理になります。
     カスタムEOのJavaソースコードに関してはデータベースにアクセスするアプリケーションであれば共通して利用することになりますので、これらはすべてフレームワークに移行します。

    ◇Webコンポーネント
     各画面を実装しているアプリケーション固有のコンポーネントはアプリケーション間で共有することもないでしょうから、そのままアプリケーション本体に残します。
     一方、再利用可能なReusableコンポーネントはフレームワークに移行して、アプリケーションから共有できるようにします。ただしReusableコンポーネントであってもアプリケーション内でしか再利用しないようなものは、フレームワークには移行しないでおきます。

    ◇リソース
     モデルファイルについては、カスタムEOのJavaクラスと同様に、アプリケーションから共通して利用することになりますので、フレームワークに移行します。

    ◇Webサーバリソース
     CSSファイルについては、今回のアプリケーションではフレームワークに移行して、共有するようにします。また、画像ファイルはアプリケーション間で共通して利用しないものもあるのですが、ファイルの数が多いために、管理しやすいようまとめてフレームワークに移行することにします。

    これでアプリケーションのどの部分をフレームワーク化するかが決まりました。あとは前回解説したようにフレームワーク用のプロジェクトを新規に作成してアプリケーションのプロジェクトからファイルを移行し、プロジェクトにビルド済のフレームワークを登録します。
     Webサーバリソースに関しては、アプリケーションに登録してあるのか、フレームワークに登録してあるのかで設定が少し違ってきます。アプリケーションに登録してある場合にはWOImageのframework属性は"app"となりますが、フレームワークに登録してある場合にはframework属性にフレームワーク名を指定します。

    さて、約1年間にわたって連載してきました「WebObjects Dev Report」ですが次回をもって最終回となります。次回はフレームワーク化の結果や今後の課題をまとめてみたいと思います。

    藤本裕之のプログラミング夜話 #89

     自分でこんなことを言うのもなんだが、NSWindowの説明だけで半年もかかってしまったことにいささか驚いている。もちろん、Cocoaの全てのオブジェクトを解説しようなどという、手塚治虫の「火の鳥」以上に無謀なライフワークを抱え込むつもりは毛頭ないんだが、NSWindowの最後の方で出てきたような「いかにもタコにも使用機会の少なそうなアトリビュートだのなんだの」を微に入り細をうがって説明していくのはいかにも効率が悪かろう。

    そういうわけなので、今回から今までのようなクラスオリエンティッドな話の進め方を改め、オブジェクティブオリエンティッドなやり方をしようと思う。オブジェクトオリエンティッドぢゃなくてオブジェクティブ(目的・目標)ね。具体的には「●●を▽▽したい」という風にまず目標を設定し、そのための手段ミチスジ最短距離や搦め手などをクラス横断的に考えていくというふうにしたい。これだと読者諸兄から「おれは■■を○○する方法が知りたい」とかいうリクエストも受けやすいし(オレにもさっぱり解んなくて知らないふりをすることはあるにしても、ね)。

    で、今回からその第1弾を始めるとして、初回だから勝手にこっちで目標を決めた。とりあえず簡単そうなところで、「プログラムからアプリケーションを起動したい」というあたりからやってみたい。Classic環境、あるいはCarbonでこれをやった経験のあるヒトは「そんなのLaunchApplicationを呼べばいいだけぢゃん」と言うと思う。こんな感じですかな(オレのCarbonの知識はちと古いのでちと不安だけど)。

    NSString*           aPath;         // これにアプリのフルパスが入ってる。
    FSRef               aRef;
    FSSpec              aSpec;
    LaunchParamBlockRec aParams;
    unsigned char*      aName = (unsigned char*)[aPath UTF8String];
    
    OSStatus status = FSPathMakeRef(aName, &aRef, FALSE);
    if(status == noErr){
         status = FSGetCatalogInfo(&aRef, kFSCatInfoNone, NULL, NULL, &aSpec, NULL);
         if(status == noErr){
              aParams.launchBlockID = extendedBlock;
              aParams.launchEPBLength = extendedBlockLen;
              aParams.launchFileFlags = 0;
              aParams.launchControlFlags = launchContinue + launchNoFileFlags;
              aParams.launchAppSpec = &aSpec;
              aParams.launchAppParameters = NULL;
              status = LaunchApplication(&aParams);
         }
    }
    


     ヒトは知らず、実を言うとオレは上に出てくる LaunchParamBlockRec というヤツが昔から嫌いだった。いちいち面倒くさいんだもん。これ、Cocoaでは以下のように書ける。オレがCocoaを好きなわけが解るでしょ(笑)?

    NSString*                aPath;         // 同じくこれにアプリのフルパス。
    [[NSWorkspace sharedWorkspace] launchApplication: aPath];
    


     とは言え、いくらなんでもこれで問題解決ではない。というか、それならこんな原稿は書かない。面倒くさいことにも利点はあってCarbonだといろいろと小技を使えるのだ。例えば上のaParams.launchControlFlags というパラメータ、これに渡す値にlaunchDontSwitch という定数を足してやれば、アプリケーションをバックグラウンドで起動できる。逆に言えば、CocoaにおけるNSWorkspaceのメソッド、launchApplication: でアプリを起動すると、そいつは必ずアクティブアプリケーションになってしまう。
     さぁここで問題。ではどうやったらCocoaでアプリケーションをアクティブにせずに起動できるでしょう? ……そういうときだけCarbonを使うってのももちろんアリだけど(そうするしか方法がない時も確かにあるけどね)、これはなんとかCocoaの中で解決できる。次回までにあれこれ考えてみてちょうだいな。
    (2006_04_14)

    高橋真人の「プログラミング指南」第87回

    UNIXとしてのMac OS X

    〜Perlについて(33)〜

     こんにちは、高橋真人です。早速続きを始めましょう。
     さて、Perlネタの最後のお話として解説している、map、grep、sortなどの演算子にリストデータを順に受け渡しながら処理していくやり方ですが、sortに続いて今回はgrepです。
     多少なりともUNIXに親しんでいる人であれば、grepというコマンドがあることはご存知でしょう。ご存じない方のために少し解説します。
     manコマンド(UNIXのオンラインリファレンス)によれば、「パターンにマッチする行を表示する」となっています。使い方としては

    grep pattern file

    のような形で、patternの部分にはおなじみの正規表現を、fileの部分には任意のファイルのパスを指定します。
     コマンドの名前のgrepは、時に正規表現の代名詞として使われるほど代表的なものですが、grepコマンドが持つパターンマッチング機能に関してはさほど高いものではなく、後発のPerlにすっかりお株を奪われてしまった感があります。
     とはいえ、UNIXのコマンドラインで作業する上においては必要欠くべからざる常用ツールでもあります。ただ、多くのUNIXユーザにとってgrepを使う局面というのは、ファイルを対象とするケースよりも他のコマンドの出力結果から必要な情報のみを取り出すというケースが圧倒的に多いでしょう。
     コマンドからコマンドへのデータの受け渡しなどの話についてはいずれまた詳しく取り上げてみたいと思いますが、今回は具体的な例で使い方を見てみます。

    Terminalを開いて、psと打ち込んでみてください(例によって末尾のリターンはいちいち記述しません)。
     数行のテキストが表示されたと思います。これはps(process status)コマンドによって現在実行中のプロセスのリストが表示された状態です。
     もちろん今表示されたものがあなたのマシンで動いているすべてのプロセスではありません。細かい説明は抜きにして、今度はps auxと打ってみてください。今度は一画面で表示し切れずに画面の彼方に多くの行が流れていったと思います。
     さて、ただ表示させてみただけではつまらないので、ここからドックのプロセスを探してみましょう。皆さんはドックを再起動させるにはどうしたらいいかをご存知ですか? Finderの再起動ならば、アップルメニューの強制終了を選んで「再度開く」を押せば行えますが、ドックのようにアプリケーションとしてユーザーから見えないプロセスの場合、標準で用意されたインターフェースでは強制終了や再起動は簡単に行えません。
     ではそれをやってみましょう。
     ps auxで表示された中からドックのプロセスを探し、あとはkillコマンドを使って強制的にプロセスを終了させるだけです。強制的にプロセスを終了させれば、システムがドックを再起動してくれます。
     killコマンドの使い方などは割愛しますが、ドックのプロセスIDの探し方を。
     まず、初期状態のTerminalのウインドウは横幅が狭いので、ドックのプロセスが表示し切れないはずです。そこで、さらにオプションを追加して、ps auxwwとします(wを2つ入れるところがミソ)。
     そうするとウインドウの幅に合わせて切れることなく、各プロセスが最後まで表示されます。でも、行が折り返されていて見にくいですね。ウインドウを広げて、折り返しを解消してもよいのですが、ここでは余計な情報を隠してしまいましょう。
     そこでgrepの登場です。UNIXにおける特徴であるパイプという仕組みを使って、psコマンドの出力をgrepにつなぎます。具体的には以下のようにします。

    ps auxww | grep Dock

     これでずっとすっきりとした表示になるはずです。ただし、ここでやっているのはあくまで文字列検索です。最初に説明したようにgrepコマンドは「パターンがマッチした行」を表示するだけなので、psコマンドから渡された複数の行の中から、Dockという文字列が含まれるもののみを取り出しているにすぎません。
     ですから、よく見ると今打ったコマンド自体も表示されているのが分かります。Dockという文字列を含んでいますからね。

     さて、ここまでの説明でUNIXにおけるgrepというコマンドがフィルタリングの仕組みを持ったものだということがお分かりいただけましたでしょうか?
     実は、今回の主題であるPerlのgrepも同様です。渡されたリストの中から、「条件に一致したもの」のみを取り出し、それをリストにして返す。これがgrep演算子の機能になります。
     もっとも、条件と言うのはもう少し込み入っていまして、文字列の一致のみに留まりません。以下のような例を見ていただければ、「条件に一致」の意味がお分かりいただけるでしょう。

    @list = grep { $_ % 2 == 0 } (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    print join(", ", @list);
    


     これは、1から10までの数値のリストを作って、grepコマンドで偶数のものを取り出しています。ブロックの中ではリストの各要素が特殊変数$_を使って渡されていることを読み取ってください。
     %はC言語でもおなじみのモジュロ演算子です。$_を2で割った時、余りが0であれば真となるわけですが、ブロック全体の値が評価される仕組みは前回のsort演算子と同様です。grepの場合には、ここが真になった要素が取り出され、新しいリストとして返されることになります。

    ニュース・解説

     今週の解説担当:小池邦人

    ● Carbon ドキュメント & サンプル & SDK ナビゲーション(2006/04/14)

    【開発環境】

    このところのMac業界は、Intel CPU版のMacintoshでWindows XPを起動するための「Boot Camp」の登場で盛り上がっていますが、 OS切り換えのもう一つの方向性として、Mac OS XからLinuxやWindowsを制御可能にする(Virtual PCライク)「Parallels Workstation 2.1」(Parallels, Inc.)というソフトが注目を集めています。

    http://www.parallels.com/

    サイトでβ版が公開されていますが、すごい勢いで改良されており、あっという間にβ3となりました。USBサポートももうすぐのようです。製品は$49 .99で販売されるそうですが、現時点でプリオーダーすると$39.99で購入できます。OSのデュアルブートと目的別に切り換えて使えば利用価値が高いでしょう。ただし、Apple社もMac OS X 10.5で同じことをやっているような気もするのですが(笑)…さて、どうなるでしょうか?

    以前ここでも紹介したMac OS X用のインテル版開発環境が正式に販売開始になりました。製品概要は以下のPDFを参照してみてください。C/C++コンパイラはXcodeに組み込んで利用します。

    http://jp.xlsoft.com/documents/intel/catalog/intel_brochure_mac.pdf

    MOSA会員は、MOSA特別販売で購入することが可能です。購入を考えている方は、以下のURLを参照してください。

    http://www.xlsoft.com/jp/products/intel/mosa_camp.html

    ライブラリとのセット価格が大変安いですね(6万円引き)。私もさっそく注文したので、次回のニュースでは、その使用感などについて報告したいと思います。

    【テクニカルドキュメント】

    前回から4月14日の期間中、Apple社のDocumentationサイトには数多くのドキュメントが登録されました。ただし、大部分は今までの内容のマイナーチェンジです。今回は、その中で初版と内容が大幅変更になったドキュメントだけをピックアップしました。新顔として「…Developer Note」という形態のドキュメントが多数登録されています。また、リリースノートとして「What’s New In Mac OS X 」も登録されましたが、こちらについては改訂版となっています。加えて、デベロッパ向け読み物も2つ登録されました。このうち「Delivering Content with RSS for Web Developers on Mac OS X」については、前号の木下さんの記事も参考にしてください。

    「Animation Programming Guide」(PDFあり)(初版)
    「Apple Filing Protocol Reference」(初版)
    「Darwin Notification API Referenc」
    「Open Directory Reference」(PDFあり)(初版)
    「Quartz 2D Reference」
    「Quartz Display Services Reference」(PDFあり)
    「Quartz Event Services Reference」(PDFあり)(初版)
    「Spotlight Reference」(初版)
    「Tree-Based XML Programming Guide for Cocoa」(PDFあり)
    「AirPort Developer Note」(初版)
    「Audio Developer Note」(初版)
    「Bluetooth Developer Note」(初版)
    「Ethernet Developer Note」(初版)
    「FireWire Developer Note」(初版)
    「Hardware Developer Note Terms and Abbreviations」(PDFあり)(初版)
    「iMac G5 Developer Note」(初版)
    「PCI Developer Note」(初版)
    「Power Mac G5 Developer Note」(初版)
    「RAM Expansion Developer Note」(初版)
    「Universal Serial Bus Developer Note」(初版)
    「Video Developer Note」(初版)

    http://developer.apple.com/documentation/index-rev-date.html

    リリースノート

    「What’s New In Mac OS X 」

    http://developer.apple.com/releasenotes/

    「Elluminate Live! on Mac OS X: Going to the Head of the Virtual Class」

    http://developer.apple.com/business/macmarket/elluminate.html

    「Delivering Content with RSS for Web Developers on Mac OS X」

    http://developer.apple.com/internet/deliveringcontentwithrss.html

    前回から4月14日の期間中、新規テクニカルノートはひとつ登録され、新規テクニカルQ&Aの方は3つ登録されました。

    TN2124「Mac OS X Debugging Magic」

    http://developer.apple.com/technicalnotes/index-rev-date.html

    QA1476「Using the kQTPropertyClass_DRM properties with QuickTime」(初版)
    QA1467「CoreAudio Overload Warnings 」(初版)
    QA1469「MovieAudioExtraction – Ensure a Movie is fully loaded before starting
    an extraction session」(初版)

    http://developer.apple.com/technicalqas/index-rev-date.html

    【サンプルソースコード】

    前回から4月14日の期間中、Apple社のSample Codeサイトには、新しいサンプルソースコードが3つ登録されました。「WcharDataFormatter 」のみが新規登録となります。

    「CFFTPSample」(Network関連)
    「ExtractMovieAudioToAIFF」(QuickTime関連)
    「WcharDataFormatter」(Tools関連)(初版)

    http://developer.apple.com/samplecode/index-rev-date.html

    【デベロップメント SDK】

    前回から4月14日の期間中、Apple社のSDKサイトには新しいSDKが2つ登録されました。Mac OS X 10.4.6対応「Kernel Debug Kit」(PowerPC版とIntel版あり)です。

    「Kernel Debug Kit 10.4.6 – Intel 」
    「Kernel Debug Kit 10.4.6 – PowerPC」

    http://developer.apple.com/sdk/

     

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

     

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

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

    2006-04-11
     

    目次

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

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

     Intel Mac上でWindows XPを利用可能にするBoot Campのパブリックベータがリリースされました。Webアプリケーションを開発していますと、動作確認のためにMacもWinも両方必要になったりしますが、1台のマシンで両方が使えるようになるのは便利ですね。また、ノートパソコンを持ち歩いている方でMacもWinも使いたかった方にとっては特に朗報なのではないでしょうか。ただ、デュアルブートですので、OSを切り替えながら使い分ける必要がありますね。

    さて、前回はこれまでこの連載で解説してきましたプロジェクトを実際に動かす手順を解説しました。アプリケーション単体として起動に必要なものはすべてご紹介しましたが、今回は今後アプリケーションを拡張するにあたっての改良について解説したいと思います。

    ◇プロジェクトの改良
     プロジェクトの規模が大きくなればなるほど、1つのプロジェクトが肥大化してきます。1つのプロジェクトの中にすべてのファイルがまとまっているとそれはそれで便利かもしれませんが、それでもアプリケーションの数が増えたりするとプロジェクト間での共通部分をどう扱うかという問題があります。
     たとえば一般ユーザが利用するアプリケーションと、管理者が利用する管理用のアプリケーションを個別に開発するとしましょう。このような場合、データベースは共通のものを利用するでしょうし、そうなるとモデルファイルも共通のものを利用するでしょう。アプリケーションごとに扱うEntityやAttributeは異なるかもしれませんが、共通する部分もある程度はあるはずです。さらにモデルファイルが共通であれば、カスタムEOのソースコードも共通化しておいたほうが効率的です。
     このようにアプリケーション(プロジェクト)間で共通する各種ファイルはフレームワークとしてまとめることができます。ここでまずフレームワークとはなにかですが、WebObjectsでアプリケーションを開発しているのであれば、すでにフレームワークは使用しています。プロジェクトのFrameworksグループの中には、プロジェクトを生成したときに自動的に追加された次のようなWebObjects標準のフレームワークが登録されているはずです。

    ・WebObjectsアプリケーションにデフォルトで登録されるフレームワーク
    -JavaFoundation.framework
    -JavaEOControl.framework
    -JavaEOAccess.framework
    -JavaWebObjects.framework
    -JavaWOExtensions.framework
    -JavaXML.framework
    -JavaJDBCAdaptor.framework

    ◇フレームワーク
     フレームワークには.frameworkという拡張子がついていますが、その実体はディレクトリであり、システムが提供するフレームワークは次のパスにインストールされています。

    ・システムが提供するフレームワークのパス
    /システム/ライブラリ/Frameworks/

     フレームワークの中身がどうなっているかですが、基本的にプロジェクト上で扱うことのできるファイルは、なんでもフレームワークの中に入れることができます。例えば、JavaライブラリやWOのコンポーネントやモデルファイルなどをフレームワークとしてまとめることができます。さらに、フレームワークから別のフレームワークを参照することもできます。
     フレームワークは異なるプロジェクトから自由に参照することができますので、フレームワークの中で管理しているファイルは複数のプロジェクトから共有することができるというわけです。

    ◇フレームワークの作り方
     フレームワークの開発方法は、アプリケーションの開発方法と似ています。まず最初にフレームワーク用のプロジェクトを新規作成しますが、このときプロジェクトのタイプとして、「WebObjects Framework」を選択します。
     あとはアプリケーションを開発していたときと同様に、プロジェクトの中にJavaのソースコードを実装したり、WOのコンポーネントやモデルファイルを追加していきます。ただし、アプリケーションとは違いフレームワークを起動することはできません。フレームワークはあくまでもアプリケーションから参照されるものです。
     完成したフレームワークを実際に使用するときにはアプリケーションと同様に、インストールを行ないます。独自に開発したフレームワークは、システムが提供するフレームワークとは異なるパスにインストールします。

    ・独自に開発したフレームワークをインストールするパス
    /ライブラリ/Frameworks/

    ◇フレームワークの使い方
     フレームワークは、プロジェクトに登録するだけで利用できるようになります。プロジェクトにフレームワークを追加するには、Frameworksグループを選択した状態でCtrl + クリックし「追加」メニューから「既存のフレームワーク…」メニューを選択して、プロジェクトに追加するフレームワークを指定します。
     フレームワークをプロジェクトに追加すれば、フレームワークに登録しておいたファイルをプロジェクトから利用できるようになります。

    小池邦人のCarbon API 徒然草(2006/03/17)

    〜 アプリケーションのUniversal Binary化(その6) 〜

    今回は、Macintosh独自のデータ保存方法「リソース」についてエンディアンの影響を調べてみます。例題として、長い間QuickDrawで利用されてきた画像フォーマットのPicture(PICT)構造体を取り上げます。

    まず頭に入れておかなければいけない点は、リソースデータはファイルのリソースフォークにビッグエンディアンとして保存されているということです。例えばリソースデータ内に何らかのサイズを示すlong値が含まれているとすると、その数値フォーマットは必ずビッグエンディアンです。リソースを取り扱う場合にResource ManagerのAPIを使えば、データのエンディアンの違いはシステムの内部処理が吸収しますので、x86環境においてもその違いを気にする必要はありません。ただし、APIを利用せず、直接リソースの内部データにアクセスするような場合には注意が必要です。

    以下にx86環境でコンパイルすると正常に動かない例を示します。ここでの処理の対象はGetPicture()で読み込んだPICTリソース(PicHandle)です。setMyControlWellPict()は、PICTリソースをWellコントロール(画像表示用コントロール)に表示するためのルーチンです。Wellコントロールでは、その表示枠としてPICT画像の矩形枠(picFrame)を利用します。よって、矩形枠が大きすぎるPICT画像を小さなWellコントロールに表示する場合には、その矩形枠の再調整が必要になるわけです。setMyControlWellPict()ルーチンの引数fitに1を代入すると、PICT画像の矩形枠をWellコントロールの表示枠から上下左右3ピクセル分小さく合わせて表示することができます。

    void setMyControlWellPict( ControlRef chd,short fit,PicHandle pict )
    {
        Rect                        brt,srt,frt;
        ControlButtonContentInfo    info;
    
        if( pict && fit )
        {
            srt=(*pict)->picFrame;                  // PICT画像枠を得る
            OffsetRect( &srt,-srt.left,-srt.top );  // 画像枠を左上原点へオフセット
            GetControlBounds( chd,&brt );           // Wellコントロールの表示枠
            InsetRect( &brt,3,3 );                  // 表示枠を3ピクセル小さめにする
            OffsetRect( &brt,-brt.left,-brt.top );  // 左上原点へオフセット
            fitBounds( 1,&brt,&srt,&frt );          // 矩形枠を調整する自作ルーチン
            OffsetRect( &frt,-frt.left,-frt.top );  // 左上原点へオフセット
            (*pict)->picFrame=frt;                  // 調整済み矩形枠をセットする
        }
        info.contentType=kControlContentPictHandle; // 表示対象をPictureに設定
        info.u.picture=pict;                        // PicHandleを代入
        SetImageWellContentInfo( chd,&info );       // Wellコントロールに表示指示
    }

    このルーチンがPowerPC用にコンパイルされれば正常動作しますが、x86用にコンパイルされると正常に動かず、画像は正しく表示されません。原因は、srt=(*pict)->picFrameと(*pict)->picFrame=srtの箇所です。(*pict)->picFrameは生のリソースデータですので、その構造体のメンバー(4つのshort値)はビッグエンディアンです。しかし、それ以降のAPIが取り扱うRect構造体のメンバーはリトルエンディアンである必要がありますので、srt=(*pict)->picFrameという処理によりエンディアンの不整合が発生するわけです。

    何らかのCarbon APIを用いれば、上記の問題はシステム側で解決してくれるはずです。そこで、PICT画像の矩形枠を得たり設定したりするAPIを探してみました。矩形枠を得るAPIとしては、QDGetPictureBounds()が見つかりましたが、どうもセットする方のAPIは存在しないようです。そこで、Rect構造体メンバーのエンディアンを反転するswapRect()と、PICT画像の矩形枠をセットするsetPictureBounds()という自作ルーチンを用意しました。

    void setPictureBounds( PicHandle pict,Rect *drt )
    {
        Rect    frt;
    
        frt=*drt;
    
        #if __LITTLE_ENDIAN__
            swapRect( &frt );         // x86ではRect構造体を反転させる
        #endif
        if( pict )
            (*pict)->picFrame=frt;    //
    }
    
    void swapRect( Rect *drt )
    {
        drt->left=Endian16_Swap( drt->left );     // Rect構造体の右の値を反転
        drt->right=Endian16_Swap( drt->right );   // Rect構造体の左の値を反転
        drt->top=Endian16_Swap( drt->top );       // Rect構造体の上の値を反転
        drt->bottom=Endian16_Swap( drt->bottom ); // Rect構造体の下の値を反転
    }
    
    void setMyControlWellPict( ControlRef chd,short fit,PicHandle pict )
    {
        Rect                        brt,srt,frt;
        ControlButtonContentInfo    info;
    
        if( pict && fit )
        {
            QDGetPictureBounds( pict,&srt );        // PICT矩形枠を得るAPI
            OffsetRect( &srt,-srt.left,-srt.top );
            GetControlBounds( chd,&brt );
            InsetRect( &brt,3,3 );
            OffsetRect( &brt,-brt.left,-brt.top );
            fitBounds( 1,&brt,&srt,&frt );
            OffsetRect( &frt,-frt.left,-frt.top );
            setPictureBounds( pict,&frt );         // 自作した矩形枠セットルーチン
        }
        info.contentType=kControlContentPictHandle;
        info.u.picture=pict;
        SetImageWellContentInfo( chd,&info );
    }
    


    これでOKかと思われたのですが、調べてみるとQDGetPictureBounds()はMac OS X 10.3以上でないと利用できません(涙)。x86環境は必ずMac OS X 10.4以上ですので問題はないのですが、このルーチンをPowerPC環境のMac OS X 10.2xで動かすとクラッシュしてしまいます。そこで、PICT画像の矩形枠を得る場合にも、以下のような自作ルーチンを用意してやっと問題は解決しました。

    void getPictureBounds( PicHandle pict,Rect *drt )
    {
        if( pict )
        {
            #if __LITTLE_ENDIAN__
                QDGetPictureBounds( pict,drt ); // x86環境ではAPIを利用する
            #else
                *drt=(*pict)->picFrame;         // PowerPC環境ではダイレクトに設定
            #endif
        }
    }
    
    void setMyControlWellPict( ControlRef chd,short fit,PicHandle pict )
    {
        Rect                        brt,srt,frt;
        ControlButtonContentInfo    info;
    
        if( pict && fit )
        {
            getPictureBounds( pict,&srt );       // 自作したルーチンに変更する
            OffsetRect( &srt,-srt.left,-srt.top );
            GetControlBounds( chd,&brt );
            InsetRect( &brt,3,3 );
            OffsetRect( &brt,-brt.left,-brt.top );
            fitBounds( 1,&brt,&srt,&frt );
            OffsetRect( &frt,-frt.left,-frt.top );
            setPictureBounds( pict,&frt );
        }
        info.contentType=kControlContentPictHandle;
        info.u.picture=pict;
        SetImageWellContentInfo( chd,&info );
    }
    


    とにかく、リソースデータを処理する場合には、そのために用意されているAPIを使うことが肝要です。ただし、Resource ManagerのAPI側でエンディアンを考慮してくれる対象は、Apple社が定義しているリソースタイプ(種類)だけですので注意してください。自分自身でデータフォーマット(構造体)を定義しているカスタムリソースについては、一般的なファイルを読み込む場合と同様、その入出力時にエンディアンの違いを考慮する必要があります。例えば、Metrowerks CodeWarrior付属のPowerPlant Frameworkで用いられているカスタムリソースなどがこれに当てはまります。

    カスタムリソースデータと同様なものには、カスタムペーストボードデータやカスタムアップルイベントデータがあります。こうしたカスタムデータのエンディアンを効率よく反転させるために、Apple社はフリッパーと呼ばれるバイトスワップ用コールバックルーチンを組み込めるようにしました。仕組みは簡単で、OSTypeでその種類を判別できるバイトスワップ用コールバックルーチンを定義し、それをCoreEndianInstallFlipper()で登録します(CoreServiceのEndian.hを参照)。

    フリッパーの仕組みやCoreEndianInstallFlipper()についての詳細は、以下のURLから参照できる「Universal Binaryプログラミングガイドライン(第2版)」の「データのバイトスワップを行うコールバックの作成とインストール」の章に詳しく解説されています。また、Metrowerks CodeWarriorの付属のPowerPlant Frameworkのソースコードに対して考慮すべき処理内容は「Appendix D: PowerPlantの使用」の章で参照できます。

    http://developer.apple.com/jp/transition/

    次回は、もう少しリソースについての例題を調べてみます。また、効率の良いエンディアンの反転方法についても考えてみます。

    つづく

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

     本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。

    前回は、メニューがポップアップするときに起動されるメソッドを“上流”にたどることで、ポップアップメニューにメニュー項目がサブモーフとして登録されるのと同じように、ポップアップメニュー自身もデスクトップにサブモーフとして登録される…という統一的な動作モデルで画面表示が構成されていることを確認しました。なお、システムには他に同名のメソッドがないので「popUpAt:forHand:in:allowKeyboard:」を(タイプ、あるいはコピー&ペーストして入力後…)選択してからcmd + B(browse it)すれば、再び前回と同じ操作を繰り返すことなしに、当該メソッドのソースコードを一発で再び呼び出せます。

    ところで、このメソッド#popUpAt:forHand:in:allowKeyboard:には、前回の内容に絡めてちょっと面白い情報も一緒に含まれています。1回分まるまる使ってしまう少々長めの余談となりますが、立ち寄りついでにそれをご紹介することにいたしましょう。

    前回、ポップアップメニューのデバッグハローを単にクリックして(つまりshiftキーを押さずに…)デバッグハローメニューを呼び出してしまうと、解析したいポップアップメニューが消えてしまったのを覚えておられるでしょうか。そこで、デバッグハローから直接、インスペクタをよびだすためにshift-クリックを使用したのでしたよね。

    [fig.A]デバッグハローメニューを出すと、元のメニューが消えてしまう

     これはメニューモーフ独特の挙動で、他のモーフはこんなことはありません。で、どうしてこんなことが起こるのかの答えが、実は今、ブラウズしていただいている#popUpAt:forHand:in:allowKeyboard:に書かれているのです。

     このメソッドの最初の部分がそれです。

    aWorld submorphs
       select: [:each |
          (each isKindOf: MenuMorph) and: [each stayUp not]]
       thenCollect: [:menu | menu delete]
    
     #select:#thenCollectという見慣れないメソッドを使っているので、すでに皆さんがご存じの#select:、#collect:に置き換えて、同じことをするコードに書き直してみます(#select:、#collectについは、第34回を参照)。と、申しましても、単に前半を括弧でくくって、thenCollect:以降を#collect:を起動する独立したメッセージにするだけです。
    
    (aWorld submorphs
       select: [:each |
          (each isKindOf: MenuMorph) and: [each stayUp not]])
       collect: [:menu | menu delete]

     ちなみに「select:thenCollect:」を入力して選択後、browse it(cmd +B)して見ることができる定義にも、実は同じことが書いてあります。単に括弧をひとつ省くためだけのメソッドの存在をいぶかしがる向きもあるかと思いますが、かのマーチン・ファウラーはこうした冗長さを称して“ヒューメイン(人道的)”な言語デザインなのだと言っています。

    http://capsctrl.que.jp/kdmsnr/wiki/bliki/?HumaneInterface

     さらに踏み込んで、このコードに限っては、次のように書いても同じことになります。

    (aWorld submorphs
       select: [:each |
          (each isKindOf: MenuMorph) and: [each stayUp not]])
       do: [:menu | menu delete]
    


     本来、#select:thenCollect:は、その定義どおり、#select:(パラメータブロックがtrueを返す要素を選別)したコレクションに対して#collect:(パラメータブロックの返値を改めて要素としたコレクションを新たに作成)するときに用いるメソッドなのですが、ここでは返値を捨てている(変数に束縛していない)ので、#do:(各要素についてパラメータブロックを評価)しているのと同じ…というわけです。

    察しのよい読者の皆様におかれましては、#select:thenCollect:の説明など見るまでもなく、このコードがデスクトップ(aWorld)に存在するメニューモーフを一掃するためのものであることをご推察いただけていることと思います。試しにこのコードをコメントアウトして、どうなるか確認してみましょう。コメントアウトするには、このコードの前後にダブルクオーテーション「”」を追加して、accept(cmd + S)します。

    ただちにコンパイルが終了し、システムはコメントアウトしたコード抜きで新たな挙動を示すようになります。改めて前々回のスクリプトでポップアップメニューを出してモーフとして選択後、デバッグハローメニューを呼び出してみてください。いかがですか? もう、元のメニューは消えませんよね。

    [fig.B]デバッグハローメニューを出しても、消えなくなったメニュー

     こんなふうに、システムの仕組みや動きがどんなふうになっているかを気軽に、かつ、安全に学べるようになっていることも、アラン・ケイが考えるダイナブックの備えるべき(そして、Mac のような“限定”ダイナブックでは削られて久しい…)特徴のひとつであり、暫定ダイナブックシステムとしてのSmalltalkは見事にそれを体現しているわけです。

    今回、手を加えたメソッドは、ブラウザのversionボタンで呼び出すことができるバージョンブラウザから一つ前のバージョンを選択して、revert、remove from changesの順にボタンを押して明示的に戻すか、システムを保存せずに終了して再起動することで変更自体をなかったことにできます(後者の場合は、起動後加えた他の変更もすべて失われるので注意してください)。

    バックナンバー:

    ニュース・解説

     今週の解説担当:木下 誠

    ———————————————————————-
    Boot Camp登場!
    ———————————————————————-

    もうみなさんご承知でしょうが、Intel MacでWindows XPを起動可能にする「Boot Camp」が、Appleより登場しました。MacintoshでWindowsが動くその姿は、正に、衝撃の一言です。

    Apple – Boot Camp
    http://www.apple.com/macosx/bootcamp/

    このBoot Campは、パブリックベータですが、将来、LeopardことMac OS X 10.5に組み込まれることが明言されています。現在はデュアルブートという形を取っていますが、同時起動が可能になるのか、Linuxなどの他のOSも起動可能になるのか、目が離せません。

    各種Webニュースメディアからも、速報および詳報が次々と公開されています。

    『Intel MacでWindowsが動く「Boot Camp」レポート【インストール編】』
    http://pc.watch.impress.co.jp/docs/2006/0406/apple2.htm
    『Intel MacでWindowsが動く「Boot Camp」レポート【ベンチマーク編】』
    http://pc.watch.impress.co.jp/docs/2006/0407/apple.htm
    『Intel MacでWin XPとのデュアル起動を実現、アップルの「Boot Camp」』
    http://pcweb.mycom.co.jp/news/2006/04/06/100.html
    『衝撃! Mac OS X+XPのデュアル環境を「Boot Camp」』
    http://pcweb.mycom.co.jp/column/osx/173/
    『パソコン史に残る一大事件! MacでWindowsが“快適”に動く『Boot Camp』の秘密に迫る』
    http://mac.ascii24.com/mac/news/misc/2006/04/06/661552-000.html
    『【Boot Camp】OS XとWindows XPのデュアルブートが可能なIntel Macの作り方』
    http://mac.ascii24.com/mac/news/software/2006/04/06/661554-000.html
    『もうみんなMacを買えばいいと思う――Apple純正「Boot Camp」をさっそく試した』
    http://plusd.itmedia.co.jp/pcupdate/articles/0604/06/news059.html

    わたしも実際にインストールしてみましたが、インストーラの完成度は高く、まったく問題なく進みました。

    Boot Campが、Macユーザ、およびPCユーザに、どのような影響を与えるかは、まだ未知数です。ですが、PC業界がWindows Vistaの発売延期により閉塞感が漂う中、次から次へと新しい矢を繰り出してくるAppleには驚かされます。

    ———————————————————————-
    「インテルソフトウェア開発製品Mac OS版」の販売開始
    ———————————————————————-

    前にも紹介したことのある、Intel製のIntel Mac向けコンパイラが、「インテルソフトウェア開発製品Mac OS版」として、正式に発売開始となりました。この開発ツールには、C++コンパイラ、Fortranコンパイラ、マス・カーネル・ライブラリ、インテグレーテッド・パフォーマンス・プリミティブが含まれます。

    特に、Intel Macに向けて、FortranおよびC++プログラムのパフォーマンスチューニングを行いたい方に、おすすめでしょう。

    MOSAでは、この製品の特別優待価格による購入の案内をするそうです。詳しい内容については、近日中に案内があるそうです。

    また、先週行われたインテル・デベロッパー・フォーラムで、「Apple Mac OSおよびマルチコア対応ソフトウェア開発ツール最新版のご紹介」と題したセミナーが開催されました。MYCOM PC WEBで、レポートが公開されています。

    IDF-J 2006 – Intel Mac向け開発ツールが提供開始、最適化による性能向上をアピール
    http://pcweb.mycom.co.jp/articles/2006/04/08/idf1/

    Development Support for Intel-based Macs
    http://www.intel.com/cd/ids/developer/asmo-na/eng/255716.htm

    販売店である、エクセルソフトによるプレスリリース
    http://www.xlsoft.com/jp/services/press/PressRelease_MacOSTools20060407.pdf

    ———————————————————————-
    RSS紹介のドキュメント
    ———————————————————————-

    Web開発者向けに、RSSを紹介したドキュメント、「Delivering Content with RSS for Web Developers on Mac OS X」が公開されています。RSSの仕組みと利用方法が、簡単に紹介されています。

    通常のRSSに加えて、Podcastのための仕組みも解説されているところが、Appleらしいです。

    Delivering Content with RSS for Web Developers on Mac OS X
    http://developer.apple.com/internet/deliveringcontentwithrss.html

    ———————————————————————-
    初出ドキュメント3つ
    ———————————————————————-

    ADCのリファレンスライブラリに、初出のドキュメントが3つ、追加されています。

    「Animation Programming Guide」は、Cocoaでのアニメーションプログラミングを解説したもの。NSAnimationおよびNSViewAnimationを使います。

    「Apple Filing Protocol Reference」は、AFP (Apple Filing Protocol)のためのコマンドのリファレンスです。”FP”で始まるAPIが含まれます。

    「Open Directory Reference」は、Open DirectoryのAPIリファレンスです。こちらは、”ds”で始まる関数になります。

    Animation Programming Guide
    http://developer.apple.com/documentation/Cocoa/Conceptual/AnimationGuide/index.html

    Apple Filing Protocol Reference
    http://developer.apple.com/documentation/Networking/Reference/AFP_Reference/index.html

    Open Directory Reference
    http://developer.apple.com/documentation/Networking/Reference/Open_Directory_Ref/index.html

     

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

     

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

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

    2006-04-04

    目次

    • 「WebObjects Dev Report」     第45回  田畑 英和
    • 藤本裕之のプログラミング夜話 #88
    • 高橋真人の「プログラミング指南」  第86回
    • ニュース・解説                小池 邦人

     

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

     今年の3/28でWebObjects 1.0がリリースされてから10周年のようです。10年の間に会社がNeXTからAppleへと変わり、言語がObjective-CからJavaへと変わり、値段もとても高価なものから今となっては無償(開発版のみ)に変わりました。コンピュータ業界で10年といえばとてつもなく長い時間になりますが、よくここまで生き残ったものです。はたして10年後はどうなっているのでしょうか。

    ・WebObjectsの歴史
    http://en.wikipedia.org/wiki/WebObjects

     さて、今回はこれまで紹介してきたプロジェクトを実際に動かす手順をご紹介しておきます。昨年の湘南ミーティングの時点で一度プロジェクト一式を公開していましたが、その後最低限のエラー処理などを少し加えてあります。まずはプロジェクトのダウンロード先から。

    □プロジェクトダウンロード
    ・プロジェクト
    http://210.175.246.197/WebObjects/mosa/MOSAJobMatch_0330.zip
    ・ビルド済アプリケーション本体
    http://210.175.246.197/WebObjects/mosa/0330.zip
    ・ビルド済WebServerResources
    http://210.175.246.197/WebObjects/mosa/MOSAJobMatch.woa.zip
    ・データベース(OpenBase ASCIIバックアップ)
    http://210.175.246.197/WebObjects/mosa/JobMatch_ASCIIBackup0330.bck.zip

     WebブラウザでダウンロードしやすいようにすべてFinder上でzip圧縮をかけてあります。ソースコードを確認したい方はプロジェクトをダウンロードしてください。運用環境で実際に動作させてみたいという方は、ビルド済のアプリケーション本体とWebServerResourcesをダウンロードしてください。ビルド済のアプリケーションのインストール先は以下のパスになります。zipファイルをこのパスで解凍してください。

    □インストールパス
    ・ビルド済アプリケーション本体(別のパスでも可)
    /Library/WebObjects/Applications/
    ・ビルド済WebServerResources
    /Library/WebServer/Documents/WebObjects/

     Xcodeから起動する場合も、アプリケーションをインストールして運用環境で起動する場合もデータベースが必要になります。すぐにアプリケーションを起動できるようにサンプルデータ入りのデータベースバックアップファイル(JobMatch_ASCIIBackup0330.bck.zip)を用意してあります。
     データベースにはOpenBaseを使用していますが、OpenBaseのセットアップはあらかじめ行っておく必要があります。OpenBaseがセットアップできましたらOpenBase Managerで新規にデータベースを作成して、バックアップファイルをリストアします。データベースをリストアするには、あらかじめデータベースを起動しておく必要があります。データベースを新規に作成するときは以下の条件で作成します。

    □新規データベースのパラメータ
    データベース名:JobMatch
    データベースエンコーディング:UNICODE UTF-8
    内部のソート基準:other(なにも指定せず)

     これでアプリケーションを起動する準備が整いました。このプロジェクトではWebObjects標準のフレームワークしか使用していませんので、ほかにインストールが必要なものはありません。
     アプリケーションを起動すると「閲覧」と「登録」メニューがありますが、「登録」を行うには、ユーザ情報を登録するアカウントでのユーザ認証が必要になります。ユーザ認証にはMOSA IDとメールアドレスが必要になります。サンプルデータベースにはあらかじめ4名分のアカウントが登録してあり、認証に必要な値はそれぞれ以下のようになっています。

    □サンプルユーザ(MOSA ID/メールアドレス)
    test1/test1@mosa.gr.jp
    test2/test2@mosa.gr.jp
    test3/test3@mosa.gr.jp
    test4/test4@mosa.gr.jp
    ※アプリケーションに新規ユーザを登録する機能はありません。

     本プロジェクトの開発環境ですが、次のように少し古い環境で作成してあります。動作確認はしてありませんが、これよりも新しいバージョンであれば問題なく動作するものと思われます。より新しいバージョンのXcodeでプロジェクトを開くと、プロジェクトファイルの形式を新しいものに変換することがあります。

    □開発環境
    ・Xcode 1.1
    ・WebObjects 5.2.3
    ・OpenBase 8.0.4(b20)
    ・Mac OS X 10.3.9

     最後に、運用中のアプリケーションを入れ替える方法について解説しておきます。まず新しいバージョンのアプリケーションをインストールする必要がありますが、インストールパスをバージョンごとにサブディレクトリに分けておけば、既存のバージョンを残したまま新しいバージョンをインストールすることができます。別のパス上にアプリケーションをインストールした場合には、Monitorで起動スクリプトのパスを変更する必要があります。
     パスの変更を行っておけば、あとは稼働中のインスタンスを停止してから起動すれば、新しいバージョンの運用を始めることができます。インスタンスを停止するときは、Monitor上でセッション数を確認してください。セッション数が0でなければ使用中のユーザが存在するというとになりますので、そのままインスタンスを停止するとメモリ上のデータは失われてしまいます。
     インスタンスが複数ある場合には、1つずつ停止&起動を繰り返して行けばシステム全体としては停止せずにアプリケーションの入れ替えを行うことができます。また、インスタンスが1つだけの場合でも、インスタンスを1つ追加して起動を確認してから、古いインスタンスを停止することでシステム全体を停止することなく入れ替えを行うことができます。
     ほかにも、場合によってはアプリケーションの入れ替え時にデータベースの更新や運用のパラメータ変更が必要になることも考えられます。

    藤本裕之のプログラミング夜話 #88

     こないだふと思いついてこの原稿のバックナンバーを読み返したら、このNSWindowの項目が始まったのは昨年の9月、なんだかんだでもう半年以上やっているのである。読者諸兄もそうかもしれないがなにより書いているオレが少々飽きてきた。ちうわけで、ここらでちょっとスピードアップし、今回でNSWindowの話を終えてしまいたいと思う。

     Interface Builderで設定できる属性、残るは4つ。まずは「Has shadow」というスイッチだがこれは説明不要だろう。メソッド setHasShadow に直結していてそのウインドウが影を持つか否かを指定する。普段あんまり影を持たないウインドウというのは見かけないが、またぞろそれを探し始めると長くなってしまうので「世の中には影を持ちたくないウインドウもある、ウインドウいろいろ、人生いろいろ」と為政者風に端折って次に行く。

    「Display tooltips when app is inactive」というスイッチは……あっとその前にここで言っている tooltips ってわかるよね? ウインドウそのものには指定できないが、その上に配置されるボタンやテキストフィールドなどの各種コントロールを選択してインスペクタ上部のポップアップメニューから「Help」を選ぶと1行分のヘルプメッセージを入力できる。ここに入力された文字列は、マウスカーソルがそのコントロールの上にとどまっていると黄色い(これ、色変更できるのかな?)小さなウインドウが出てきてそこに表示される。通常あれは、そのウインドウを出しているアプリケーションがアクティブなときしか表示されないんだが、このスイッチをオンにしておけば、それが表示されるようになる、と。この機能がどんなときに便利かというと、フォアグラウンドにあるファインダからファイルなんかのドラッグ&ドロップを待っているときとかですね。ドラッグ&ドロップを受け付けるNSViewのサブクラスが、アプリケーションがアクティブぢゃない時でも「ここにドロップしてちょうだい」というメッセージを出せれば親切でしょ?

    さて次が問題の(前回の最後の話、覚えてる? このスイッチが実はあれに絡んでいるのである)「Unified title toolbar look」、これもまた、Borderless や Textureと同様、ウインドウ作成のときに使われる StyleMaskで指定されるのでウインドウを作ってしまってからでは変更できない。で、その効果……というか、これをオンにするとどうなるかというと、読んで字のごとく、タイトルバーとツールバーの境目がなくなって一体化しちゃうのである。当然ながらツールバーの部分を「持って」ウインドウをドラッグすることも可能になる。

     ワタシの手持ちのアプリケーションでこれを使っているのは「Mail.app」「Xcode」のプロジェクトウインドウ(他のはなぜか違う)、「Jedit X」のバージョン1.33……。え? 効能はわかったがそのスイッチをオンにできないって? そうなのだ、オレもどうしてそうしてあるのかさっぱり解らないのだが、Interface Builderのインスペクタにあるスイッチ、インスタンスがNSPanel の時にしか有効にならない。別にパネルに限る理由もないように思えるし、前に出てきた2つと違って「panel only」とかいう断りもないので、もしかしたら単なるバグではないかと思っているのだがどうですか。まぁ、NSPanel は NSWindow のサブクラスであって逆ではないので、NSPanel としてインスタンスを作っておけば別に支障はないんだけどね(ほんのわずかメモリを余計に食うだけ)。

    そして、最後に残ったのが「Auto recalcurate key view loop」。プログラムの都合でウインドウ内にあるテキストフィールドを実行中に追加したり逆に減らしたりしたいことがある。以前のシステムではこういうことをやると、それらkeyViewの持つ nextKeyView の連鎖を自分でメンテナンスしてやらなければならなかった。が、Tigerではそれを一発でやってくれるメソッド、recalcurateKeyViewLoop と、それを使うのさえ面倒だというものぐさなひとのためにこの属性が用意された。つまりこれをオンにしておくと……どこをフックしてるのかな? とにかくkeyViewにあたるオブジェクトの追加・削除のおりに、自動的にその連鎖をチェックしてくれる、とこういうわけである。

    はぁはぁ、最後はちと急ぎ足になったが、これでNSWindowの話は一応終わりとしたい。次回から何をやろうかな。編集長と相談しよう(実はまだ何も決めてない)。
    (2006_03_31)

    高橋真人の「プログラミング指南」第86回

    UNIXとしてのMac OS X

    〜Perlについて(32)〜

     こんにちは、高橋真人です。早速続きを始めましょう。
     今回はPerlにおけるソートについてがテーマです。Perlでは他の演算子と同じようにデフォルトの挙動であれば記述は極めて単純です。前回に使用した

    print sort (5, 3, 7, 2, 6, 1);

    というコードは、リスト(カッコで囲まれた数値の羅列)がsort演算子に渡され、さらにprint演算子に渡された結果、

    1234567

    という出力結果が得られるわけです。
     蛇足ながら、この出力結果がなぜこのような形になるかを説明しましょう。
     print演算子は、意外にもリストコンテキストを要求しますので、sort演算子が返した値は数値のリストとして渡され、そのまま「結合されて」出力されます。(ちなみに、PerlではC言語とは違って、数値と文字列の区別が柔軟にできているため、print演算子に渡された数値のリストは、文字列のリストとして処理されます)
     こういうわけで、例えば以下のようなコード、

    print ;

    において、INに割り当てられているファイルの中身は、丸ごと標準出力に送られることになります。大切なのは、裏側ではリストのやり取りがなされていることを意識することです。漠然と「ファイルの中身が出力された」と考えていると、対象となるファイルが巨大な場合にメモリ不足に陥っても何が起こったか分からずに戸惑うことになります。
     また、リストの各要素が「改行も含んだ」状態であることを忘れると、print演算子に渡されたリストが自動的に改行で連結されると勘違いしたり、スカラーコンテキストでと使った場合、末尾に改行があることを忘れたりする結果にもつながります。
     ちなみに、printに渡したリストの各要素の結合の際に区切り文字を入れたい場合はjoin演算子を使うことも覚えておくといいでしょう。

    さて、本題のソートです。そもそもソートというものは、よほど単純なデータの集まりでもない限りデフォルトの並び順、つまり文字のコード順による並び替えで済むことはありませんから、ソートにはほとんどの場合比較ルーチンが付き物です。
     Perlではこんなときにブロックを使います。ブロックというのはおなじみの{}で囲まれた単文または複文です。デフォルトのソート処理をあえてブロックを使った形で表現すると、以下のようになります。

    @list = qw(s d w a f z);
    @list = sort { $a cmp $b } @list;
    


     cmpという演算子は、+ とか * と同じく二項演算子で、左側が右側より小さい場合には-1を、逆の場合には+1を、そして左右が同じ場合には0を返します。ANSI Cのライブラリ関数のstrcmp()と同じだと考えれば分かりやすいでしょう。
     また、以上のことから類推できるように、sort演算子におけるブロックの評価値はANSI Cライブラリのqsort()が要求する比較関数の場合と同じです。ブロックの評価値ということに関してですが、Perlではreturnなどを使って明示的に表記することなく、「最後の文の評価値」がそのままブロック全体の値として評価されます。
     ところで、上記のブロックにおいて突然出てきた$aと$bって何? と思われた方も少なくないことでしょう。これも私がPerlに対して感じる「違和感」の一つなのですが、何とこの変数は決め打ちです。つまり、sortの比較処理ブロックにおける比較対象を表す変数名は必ず$aと$bに「固定されて」います。任意の変数名を使うことは許されないのです。
     もっとも、このビックリな仕様のおかげで、いわゆる降順ソートを書く場合には、単に左右を入れ替えて以下のように書けばよいのです。

    sort { $b cmp $a } @list;
    
     もっとも、逆順ソートをするだけならば、以下のように書いた方がPerlらしいですが(笑)。
    
    reverse sort @list;
    
     ところでcmpという比較演算子ですが、これはあくまで「文字列比較のため」の演算子なので、今回の冒頭に出てきたような数値の比較では問題があります。たまたま今回の例ではすべての数値は一ケタなので、結果的に問題なしですが、二ケタになってくるとcmpではまずいのです。
    
    @list = sort { $a cmp $b } (5, 3, 7, 20, 6, 12);
    print join ', ', @list;
    
     このコードの出力結果は、12, 20, 3, 5, 6, 7となってしまいます。
     そこで、文字列比較のためのcmp演算子とは別に数値比較のために<=>という演算子が用意されています。この演算子を使うと、要素は意図した通りに(?)並んでくれます。
     さて、前回の最後の例の処理ですが、大文字と小文字を区別しない並び順をどうするかという答えは、以下のようになります。
    
    @list = qw(f D c N m L b s Z p);
    print sort { lc($a) cmp lc($b) } @list;
    
     lcという演算子は、lower caseつまり、文字列を「すべて小文字に」変換します。もちろんupper caseのuc演算子を使用しても構いません。
     ところで、sortで一つ注意する必要があることですが、$aと$bの値を変えてはいけません。これをやると並べ替えているデータそのものが変わってしまいます。例えば以下のようなやり方はダメです。
    
    ※やってはいけない例
    @list = qw(f D c N m L b s Z p);
    print sort {
         $a = lc $a;
         $b = lc $b;
         $a cmp $b
    } @list;

     どうしてもこのように変換した値を変数に一度格納したい場合には、必ず別の変数を使うようにしてください。

    ニュース・解説

     今週の解説担当:小池邦人

    ● Carbon ドキュメント & サンプル & SDK ナビゲーション(2005/03/31)

    【開発環境】

    Intel CPU版 iMacやMac mini、MacBook ProでWindows XPが起動したという話題に注目が集まる中、今度は、Apple社がWindowsのベンチマーク・テストを開発している標準化団体「BAPCo」(http://www.bapco.com/)に加盟したと言うニュースが飛び込んで来ました。この加盟は、いったい何を意味するのでしょうか?

    Mac OS X 10.5(Leopard)には、Intel CPUに搭載されている機能を用いたOSのバーチャライズソフトウェアが搭載されるという噂があります。まあ、あくまでも噂の段階なのですが、Mac OS X、Linux、Windows のトリプルブートだけではなく、Mac OS XからLinuxやWindowsの制御ができるようになれば(Virtual PCのように)、世の中大変面白いことになります。何せ、Mac OS Xを起動できるパソコンは世界で唯一Macintoshだけですから、Webアプリケーション開発者などには大受けするかもしれません。

    ところで、Apple社は4月1日に創業30年を迎えます。私のAppleとの付き合いも、なんと26年目に突入します。我ながら良く付き合ってきたものです(笑)。さて、4月1日には噂に上がっているような(Intel CPU版のiBookとか)発表があるのでしょうか? この日がエイプリールフールというのが若干気になりますが(笑)、技術的なトピックスについては8月のWWDCまで静かな日々が続きそうです…。

    【テクニカルドキュメント】

    前回から3月31日の期間中、Apple社のDocumentationサイトには新規ドキュメントがひとつも登録されませんでしたが、デベロッパ向け読み物が3つ登録されています。このうち「ADC Video Tutorial Series: Building a Sample Core Data Application」は、Cocoaから活用できるCore Dataの利用方法をQuickTime Movieの映像で解説しています(とても分かり易い)。こういう映像資料についても、ぜひ日本語吹き替えが欲しいところです。「Intuit Enhances QuickBooks for Mac: Leveraging Tiger Features and .Mac」については、前号の木下さんの記事も参考にしてみてください。

    「Intuit Enhances QuickBooks for Mac: Leveraging Tiger Features and .Mac」

    http://developer.apple.com/business/macmarket/quickbooks.html

    「Building a JNI Universal Application with Xcode」

    http://developer.apple.com/java/jniuniversal.html

    「ADC Video Tutorial Series: Building a Sample Core Data Application」

    http://developer.apple.com/cocoa/coredatatutorial/index.html

    前回から3月31日の期間中、新規テクニカルノートはひとつ登録され、新規テクニカルQ&Aの方は2つ登録されました。QA1464については、前号の木下さんの記事も参考にしてください。

    TN2065「do shell script in AppleScript 」

    http://developer.apple.com/technicalnotes/index-rev-date.html

    QA1464「ColorSync Color Matching on Intel-based Macs」(初版)
    QA1242「Developing for VFS 」

    http://developer.apple.com/technicalqas/index-rev-date.html

    【サンプルソースコード】

    前回から3月31日期間中、Apple社のSample Codeサイトには、新しいサンプルソースコードが2つ登録されました。どちらも新規登録となります。

    「DragItemAround」(Cocoa関連)(初版)
    「SpecialPictureProtocol」(Cocoa関連)(初版)

    http://developer.apple.com/samplecode/index-rev-date.html

    【デベロップメント SDK】

    前回から3月31日の期間中、Apple社のSDKサイトには新しいSDKがひとつも登録されませんでした。

    http://developer.apple.com/sdk/

     

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

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