MOSA Multi-OS Software Artists

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

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

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

MOSADenバックナンバー 2005年9月発行分

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

    2005-09-27

    目次

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

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

     前回は「単一テーブル」型の継承を用いて親クラスとサブクラス用のEntityをモデル上に作成する方法を解説しましたが、今回は継承を用いた場合のカスタムEOのソースコード作成方法について解説いたします。

     「単一テーブル」を用いた場合、継承関係にあるすべてのEntityのデータが1つのテーブルに格納されます。そこで、複数のEntityが混在するテーブルの中から各レコードのEntityを識別するための、”type”という名前の属性を追加しました。カスタムEOのソースコードでは、この”type”属性に適切な値を入力する処理が必要になってきます。

    ◇ソースコードの作成
     まずは、EOModelerを用いて親クラスとサブクラス用の全てのEntityから、ソースコードを自動生成します。このとき、モデル上で継承関係にあるEntityは、自動的に適切な継承がおこなわれたクラスとしてソースコードの生成がおこなわれます。つまり、サブクラス用EntityであるMOSAMember,MOSANonMember, MOSAAdminは、それぞれMOSAUserから継承されたクラスのソースコードが生成されます。親クラス用EntityのMOSAUserは、通常どおりEOGenericRecordクラスから継承したクラスが生成されます。

    ・各クラスの継承関係
    EOGenericRecord <- MOSAUser
    MOSAUser <- MOSAMember
    MOSAUser <- MOSANonMember
    MOSAUser <- MOSAAdmin

     これで継承関係をもったクラスのソースコードが準備できましたので、次はそれぞれのクラスで、"type"属性に適切な値を入力する処理が必要になってきます。
     どのタイミングで"type"属性に値を入力するかですが、これはEOを新しく生成するときにおこないます。つまりEOの新規作成時に"type"属性を初期化してあげるわけです。こういった新規作成時の初期化処理をおこなうためのメソッドとしてawakeFromInsertion()が用意されています。

    public void awakeFromInsertion(EOEditingContext ec)

     このawakeFromInsertion()をオーバーライドし、クラスごとに"type"属性に適切な値を入力してあげればよいわけですが、すべてのクラスでこのメソッドをオーバーライドする必要はなく、親クラス(MOSAUser)で一括して処理をおこなうことができます。例えば次のようなコードを記述します。

    public void awakeFromInsertion (EOEditingContext editingContext) {
         super.awakeFromInsertion(context);
         setType(_userType());
    }

     まずはsuperで親クラスのawakeFromInsertion()を呼び出し、次に"type"属性のセッターsetType()で値を入力します。次に_userType()を実装するわけですが、このメソッドで各クラスごとのユニークな値を取得するようにします。このメソッドはクラスごとに異なった値を返す必要がありますので、すべてのサブクラス上での実装が必要になってきます。例えばMOSAMemberの場合には次のようなコードになります。

    public Integer _userType() {
         return new Integer(10);
    }

     このときMOSAMemberで使用している"10"という値は、MOSAMemberであることを識別するための値ですので、あとは他のサブクラスでも同様なメソッドを値を変えて実装すれば、各クラスごとにユニークな値をEOの新規作成時に設定できるようになります。
     各クラスを識別する値ですが、次のように親クラスのMOSAUserで定数として宣言しておけば、値を一カ所にまとめておくことができます。

    public static final Integer TYPE_MOSAMember = new Integer(10);
    public static final Integer TYPE_MOSANonMember = new Integer(20);
    public static final Integer TYPE_MOSAAdmin = new Integer(30);

     このとき各サブクラスの_userType()は次のようになります。

    ・MOSAMember
    public Integer _userType() { return TYPE_MOSAMember; }
    ・MOSANonMember
    public Integer _userType() { return TYPE_MOSANonMember; }
    ・MOSAAdmin
    public Integer _userType() { return TYPE_MOSAAdmin; }

     これで、各サブクラスのインスタンス(EO)を生成(new)したとき、自動的に"type"属性には各サブクラスごとにユニークな値が入力されます。
     このとき入力した値は、前回解説した各サブクラス用Entityにモデル上で設定したQualifierの値と一致しています。つまり、"type"の値が"10"のレコードを全件取得すればMOSAMemberの全件が取得できることになります。

     今回は"type"属性に入力する値をIntegerの定数としてソースコード上で宣言していますが、ようするにクラスごとにユニークな値が入力できればよいので、例えば文字列を用いてもよいですし、値の入力方法は色々と工夫ができるところでもあります。

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

     やれやれようやく新シリーズである。……新シリーズというのも変か。でもなんかわくわくする言葉なんだよね。ブラディ・ファイト・シリーズとかMSGシリーズとか……。これらはみな、かつての新日本プロレスのシリーズ名。開幕戦はたいてい後楽園ホールで、あそこは狭いからたいがい満員になるんだけど、たまに玄関脇でダフ屋の親父が「今回は外人がしょぼいからなー」とかボヤイてたりとか……。まごうことなき昭和の風景だったなぁ、あれも。
     と、妙な方向に連想を突っ走らせて感慨にふけっている場合ではなかった。NSWindowの話だ。まずはふだんあんまり使うことのないこのクラスの初期化メッセージ、すなわちこれ……

    -(id) initWithContentRect:(NSRect)contentRect
                  styleMask:(unsigned int)aStyle
                    backing:(NSBackingStoreType)bufferingType
                      defer:(BOOL)flag;

    の話からはじめよう(他に、これの最後に「screen」が追加されたものと、Carbon の WindowRef から NSWindow を生成するのがあるんだけど、ここでの説明の骨子には関係ないので割愛する)。
     なぜこいつは「ふだんあんまり使うことがない」のだろうか。それは、通常、アプリケーションで使われるNSWindowのインスタンスはInterfaceBuilderを使って定義され、起動時にNibファイルから読み込まれて生成されてしまうからである。逆に言えば、その方法ではちと困る事情のあるインスタンスだけ、われわれがわざわざこいつを使って作らなければならない、のである。
     ……それはどんなモノか、と考える前に、ちょっとこれらのメッセージのパラメータを詳しくみておこうか。最初の contentRect は簡単だよね(パラメータとして)。これから作る ウィンドウ の「中身の部分」を指定する矩形である。次の aStyle というのは文字通りウィンドウのスタイルを指定するスイッチで、StyleMaskとある通りビット列で指定する。各ビットは「NSWindow.h」に以下のように定義されている。

    enum {
        NSBorderlessWindowMask = 0,
        NSTitledWindowMask = 1 << 0,
        NSClosableWindowMask = 1 << 1,
        NSMiniaturizableWindowMask = 1 << 2,
        NSResizableWindowMask = 1 << 3
    };

     次の bufferingType は、指定できる値が NSGraphics.h の中に次のように定義されていて、これはつまりウィンドウの描画のしかたである。普通はNSBackingStoreBuffered を指定しておくもんだと思うが、頻繁に高速な描き替えが必要な場合はバッファリングをしない(NSBackingStoreNonretained)とか、隠されてる部分にだけバッファを使う(NSBackingStoreRetained)を指定する……んだと思う。実際のところ、あんまりその効果を実感できたことはないんだよね。やってる処理によるのかな。……もしかして、オレだけ?

    typedef enum _NSBackingStoreType {
        NSBackingStoreRetained     = 0,
        NSBackingStoreNonretained  = 1,
        NSBackingStoreBuffered     = 2
    } NSBackingStoreType;
    


     最後の flag には、簡単に言うとウィンドウの描画に関わる命令の実行を、実際にウィンドウがスクリーンに持って来られるまで(まぁ「開くまで」と言ってもいいが)延期するというか、サボるかどうかを指定する。これが YESだと、ウィンドウの描画に関わる命令はすべて保留され、「さぁそのウィンドウを前面に持って来い」と言われた時に一気に実行される。そんなソバ屋の出前みたいなことになんの効用があるかというと……あ、ちと長くなってしまったな。次回はその効用から。
    (2005_09_21)

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

    UNIXとしてのMac OS X

    〜Perlについて(21)〜

     こんにちは、高橋真人です。
     前回紹介した「言明」(Assertion)は、少し分かりにくかったかもしれません。実際、私が日常的に正規表現を使う中でも、^ や $ は頻繁に使いますが、?b に関しては、ほとんど出番がないというのが実際のところです。
     その代わりというわけでもないのですが、言明に似たようなものとして今回は ? にアルファベットを組み合わせることで表現できるもの(これらを総称して「メタ文字」と表現している文献もあります)をいくつか紹介します。
     これらは以前紹介した文字クラスの代用として用いることができます。代表的なものを紹介します。参考までに、文字クラスで書いた場合にどうなるかを併せて記しておきます。

    ¥d ... 数字を表す [0-9]と同じ
    ¥D ... 数字以外を表す [^0-9]と同じ
    ¥w ... 単語を構成する文字を表す [a-zA-Z0-9_]と同じ
    ¥W ... 単語を構成する文字以外を表す [^a-zA-Z0-9_]と同じ
    ¥s ... 空白文字を表す [ ¥t¥r¥n¥f]と同じ
    ¥S ... 空白文字以外を表す [^ ¥t¥r¥n¥f]と同じ

     ¥sのところで出てくる¥fは、フォームフィードすなわち改ページ文字です。
     前回登場した?bにせよ、今回の¥wや¥sにせよ、あくまで単語が空白によって区切られる「分かち書き」の表記が前提となっていることは明白で、その意味で日本語を正規表現で処理するには多少の追加措置が必要になってくることは、まあプログラマの皆さんならばご承知の通りです(笑)

     さて、今回紹介した表記法を使うとどういうことができるのかという例を2つ紹介します。
     まず、前回も登場した、以下のようなテキスト。

    orange, banana, peach, apple and cherry

     ここから単語を拾い出すような場合には、/¥w+/という表現で一発です。ただし、'and'も単語として拾い出しますので、さすがに「名詞だけ」というよいな抽出の仕方は無理ですがね。これだけではナンなので、きちんと走るPerlスクリプトにしておきます。

    $_ = 'orange, banana, peach, apple and cherry';
    
    while (/¥w+/g) {
        print $&, "¥n";
    }
    


     これで各単語を順番に行として出力するようになります。以前触れたm//演算子のgオプションが使われていることに注意してください。これが指定されないと、このループは永久ループになってしまいます。(何度繰り返しても'orange'にしかマッチしない)

     もう一つの例は、やはり前回触れた「各行の末尾の空白(不可視文字)を消し去る」方法です。前回は半角スペースとタブのみを対象としましたが、今回は、/¥s+$/という表現で処理してみます。
     スクリプトとして仕立ててもよいのですが、このケースはエディタなどで使う方が重宝するはずなので、正規表現対応のエディタで試してみました。(miとJedit Xで検証)
     前回の、半角空白とタブのみの指定に対して、今回のように¥sを使った場合には、他の「空白文字」も対象となります。ちょっと興味深いのは、$という末尾指定の言明指示子と改行文字との絡みがどのようになるのかということです。(通常、$は改行文字を表すものとして考えるケースが多いのです)
     早速実験してみたところ、末尾の空白文字のみならず、いわゆる空白行(改行のみの行)や、加えて空白文字を一つ以上含んだ行もきれいに取り去ることができました。
     ちなみに、全角空白が含まれた行に関してはこの限りでないことは言うまでもありません(泣)

    ニュース・解説

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

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

    【開発環境】

    Mac OS X 10.4になり、Carbon関連のヘッダーファイルに定義されているAPIのコメントに「*** DEPRECATED *** 」という表記が追加されている場合があります。DEPRECATEDを訳すと、非難する、反対を唱える、軽視するとかになるのですが、どうも「廃止予定」と言う意味のようです。この「DEPRECATED」で、色々なヘッダーファイルを検索してみると、QuickDraw.hだけではなく、Files.hとかPMApplication.hなどでも数多くのAPIが廃止予定であることが分かります。

    Xcode 2.1のインストール時に、Developer/SDKsフォルダ内にMacOSX10.4u.sdkもインストールし、それを利用可に設定しておくと、Make時にDEPRECATEDが付いたAPIの使用にはWarningが表示されます。なんだかとても気分が悪いのですが(笑)、筆者が以前作成した湘南ミーティング用の簡単なサンプルでも、160以上のWarningが表示されてしまいました(涙)。しかし、GetWindowBounds()はOKなのに、SetRect()やOffsetRect()はダメなのは納得できませんねぇ。もう少し廃止対象APIの選定をちゃんとした方が良いような気がします...。

    ところで、「廃止予定」は理解できるのですが、Apple社はいったい「いつ」廃止するのでしょうか?時期Mac OS X 10.5(Leopard)投入時でしょうか?今すぐ、これらのAPIを廃止したら、起動しなくなるソフトが大量に出現してしまいます。また、ヘッダーファイルから消してしまうと(APIは残すとして)、古いソフトは再リンクできなくなり、メンテナンスは不可能となります。多分、最終的には、SDKを10.4用と10.5用に切り替え可能にするのでしょうね(10.4用にはDEPRECATED APIを残す)。兎にも角にも、サヨナラするのはQuickDrawだけではなさそうです。

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

    前回から9月23日の期間中、Apple社のDocumentationサイトには新規ドキュメントがひとつも登録されませんでしたが、新規リリースノートの方は4つ登録されました。また、デベロッパー向け読み物もひとつ登録されています。Javaに関連するリリースノートについては、前号の木下さんの記事も参照してみてください。

    リリースノート

    「Java 1.3.1 and 1.4.2 Release 2 Release Notes」(PDFあり)
    「J2SE 5.0 Release 1 for Mac OS X Release Notes」(PDFあり)
    「Java 1.4.2 for Mac OS X v10.4 Release Notes」(PDFあり)
    「WebObjects 5.3 Release Notes」(PDFあり)

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

    「SolidWorks Brings eDrawings to Mac OS X」(読み物)

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

    前回から9月23日の期間中、新規テクニカルノートは2つ登録されました。また、新規テクニカルQ&Aの方は3つ登録されています。TN2026では、MLTE(Multilingual Text Engine )の処理に関する「よくある質問と回答」がまとめられています。いつもいつも、MLTEの処理で苦労させられているCarbonデベロッパーの方は必読でしょう(笑)。テクニカルQ&Aについては、前号の木下さんの記事も参照してみてください。

    TN2139「Debugging Dashboard Widgets」
    TN2026「Multilingual Text Engine Frequently Asked Questions」

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

    QA1412「How can I add the ability to read and write Keynote 2 documents to my application?」
    QA1441「UpdateMovieResource causes my movie file to grow bigger」
    QA1443「Using QTPixelBufferContext- Create with NewMovieFromProperties」

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

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

    前回から9月23日の期間中、Apple社のSample Codeサイトには、新しいサンプルソースコードがひとつだけ登録されました。テクニカルQ&Aの「Using QTPixelBufferContext- Create with NewMovieFromProperties」と連動したサンプルとなっています。

    「QTPixelBufferVCToCGImage」(QuickTime関連)

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

    【デベロップメント SDK】

    前回から9月23日の期間中、Apple社のSDKサイトには新しいSDKがひとつだけ登録されました。Windows用のQuickTime 7.02 SDKです。 実際に確認はしていませんが、聞いたところでは、Core VideoやCore FoundationなどMac独自のAPIが使えるそうです。

    「QuickTime Windows SDK」

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

    また、以下のサイトからCHUDの最新版である4.2.2がダウンロード可能です。これをインストールすると、「システム環境設定」のハードウェアのカラムに「Processor」環境設定がインストールされます。以前、この環境設定のリソースには「x4」マークの画像ファイルが存在しており、色々と憶測を呼びましたが、今回はどうも「x6」マーク(?)の画像までもあるようです(笑)。さて、どうなることやら?

    「Computer Hardware Understanding Development Tools (CHUD )4.2.2」

    http://developer.apple.com/tools/download/

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

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

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

    2005-09-20

    目次

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

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

     今回は「単一テーブル」型の継承を用いたユーザ情報のモデル化方法について解説いたします。まず大まかな手順ですが、次のようになります。

    1. 親クラス用Entityの作成
       継承元のEntityを作成します。
    2. サブクラス用Entityの作成
       親クラス用Entityから継承したEntityを作成します。
    3. ソースコードの作成
       Entityからソースコードを生成し、継承のためのコードを追加します。

     今回作成するEntityですが、「MOSA会員」「非会員」「事務局」の3種類のユーザタイプ用のEntityに加え、各ユーザタイプに共通した属性をまとめた親クラス用Entityの計4つを作成します。それぞれのEntity名は次のようにします。

    MOSAUser:親クラス用Entity
    MOSAMember:MOSA会員用Entity
    MOSANonMember:非会員用Entity
    MOSAAdmin:事務局用Entity

    ◇親クラス用Entityの作成
     全てのサブクラスに共通する属性を定義します。属性の追加方法は、通常のEntityと同様ですが、継承を行う場合は継承用の属性が1つ必要になります。継承を用いた場合、データベース上の1つのテーブルに複数のEntityのレコードが混在することになりますので、この属性を用いて各レコードがどのEntityのレコードかを識別します。識別用の属性は例えば次のように作成します。

    Name : type
    Column : TYPE
    Value Class(Java) : Number
    External Type : int

     レコードを追加するさいに、この属性(type)にレコードごとのユニークな数値をセットすることにより、Entityの識別をおこないます。どのように数値をセットするかについてはソースコードの作成の説明で取り上げます。この属性は、Entityを識別するために用いるだけですが、値をセットする必要がありますのでクラスプロパティとして設定します。またそれぞれのEntityの数値は次のようにします。

     MOSAMember:10, MOSANonMember : 20, MOSAAdmin:30

     今回は、親クラス用のEntityを実際にはインスタンス化せず、ユーザ用のインスタンスはいずれかのサブクラス用Entityから生成します。このような場合には、EOModelerのAdvanced Entity Inspectorを用いてEntityをAbstractとして設定することにより、そのEntityがインスタンス化されない継承のための親クラスであることを宣言できます。

    ◇サブクラス用Entityの作成
     サブクラス用のEntityを作成するには、まずEOModeler上で継承する親クラスを選択し、PropertyメニューからCreate Subclassを実行します。サブクラス用のEntityを作成したらEntity名を設定しますが、このときテーブル名は親クラス用Entityのテーブル名と同じままにしておきます。単一テーブルの場合は、継承関係にあるすべてのEntityを単一のテーブルで管理しますので、テーブル名を統一しておく必要があります。
     親クラス用Entityに含まれる属性は、サブクラスを作成した時点でサブクラス用Entityにも自動的に継承されているため、あとはサブクラス固有の属性を追加していきます。

     次に単一のテーブルから特定のEntityに対応するレコードを取り出す設定をおこないます。EOModeler上でサブクラス用Entityを選択し、Advanced Entity Inspectorを用いてQualifierの設定をおこないます。このときQualifierはそれぞれのサブクラス用Entityで次のように設定します。

    MOSAMember:(type = 10)
    MOSANonMember : (type = 20)
    MOSAAdmin:(type = 30)

     このようなQualifierを設定することにより単一のテーブルから特定のEntityのレコードのみを取り出すことが可能になります。これらの操作をすべてのサブクラスごとに実行していきます。
     これで親クラスとサブクラス用のEntityの設定ができましたので、次回は継承を用いた場合のカスタムEOのソースコードの作成方法について解説いたします。

    小池邦人のCarbon API 徒然草(2005/09/16)

    画像ファイルをウィンドウに表示する(その2)

    今回は、openViwerWindow()から呼ばれているimageFileToImage()ルーチンについて解説します。基本的には、画像ファイルからCore Graphics Imageを作る処理なのですが、Mac OS Xのバージョンにより、その解決方法が大きく異なります。

    通常、画像ファイルから画像データを読み込む場合には、QuickTimeのGraphicsImporter APIを利用します。実際には、GetGraphicsImporterForFile()に画像ファイルのFSSpec構造体を渡し、GraphicsImportComponentを得ます。それを関連APIに渡すことで、各種画像情報や画像データを得ることや、指定CGrafPortへの描画などが可能となります。この場合、対象がどんな種類の画像ファイル(JPEGとかTIFF)なのかは、ほとんど気にする必要はありません。QuickTimeが読み込んで表示可能な画像種類であれば、すべて同様な処理を実行することができます。もし、QuickTimeが未対応の画像ファイルを処理しようとすると、GetGraphicsImporterForFile()でエラーが返りますので注意してください。

    以下のimageFileToPicture()ルーチンは、GraphicsImporter APIを利用して画像ファイルからPicture(PICT)データを得る簡単な例です。

    short imageFileToPicture( Rect *frt,FSSpec *fsc,PicHandle *pict,Rect *srt )
    {
        short                      ret=1;
        Rect                       drt;
        GraphicsImportComponent    gi;
    
        if( ! GetGraphicsImporterForFile( fsc,&gi ) ) // GraphicsImporterを開く
        {
            if( ! GraphicsImportGetNaturalBounds( gi,srt ) ) // 画像矩形枠を得る
            {
                OffsetRect( srt,-srt->left,-srt->top ); // 矩形枠を原点基準にする
                if( frt ) // frtが渡されていればその矩形枠内に拡大縮小する
                {
                    OffsetRect( frt,-frt->left,-frt->top );
                    fitBounds( 1,frt,srt,&drt );  // 矩形枠フィット用の自作ルーチン
                    OffsetRect( &drt,-drt.left,-drt.top );
                }
                else     // frtとしてNULLが渡された場合
                    drt=*srt; // PICT枠にはオリジナル画像枠を利用する
               GraphicsImportSetBoundsRect( gi,&drt );   // 画像矩形枠をセットし直す
               ret=GraphicsImportGetAsPicture( gi,pict );// 画像からPICTデータを得る
            }
            CloseComponent( gi ); // GraphicsImporterを閉じる
        }
        return( ret );
    }
    


    続いて、imageFileToImage()を調べてみます。今回、画像ファイルから得る必要があるのは、Core Graphics ImageのCGImageRefです。そのため、まず最初にimageFileToGworld()ルーチンを用いて、画像ファイルをオフスクリーン用に確保したGWorldへ描画してやります。そのGWorldのPixMapデータ(メモリ領域)から、Core Graphics(Quartz 2D)APIを駆使してCGImageRefを作成しています。

    short imageFileToImage( FSSpec *fsc,CGImageRef *image,GWorldPtr *off,Rect *srt )
    {
        long                 size,ww,hh;
        short                row,ret=1;
        CGColorSpaceRef      color;
        Ptr                  addr;
        CGDataProviderRef    prov;
        PixMapHandle         phd;
        Rect                 drt;
    
        if( ! imageFileToGworld( fsc,off,srt ) ) // 画像を描画したGWorldを得る
        {
            GetPortBounds( *off,&drt );  // 画像の矩形枠を得る
            phd=GetGWorldPixMap( *off ); // GWorldのPixMap(メモリ領域)を得る
            addr=GetPixBaseAddr( phd );  // PixMapの先頭アドレスを得る
            row=GetPixRowBytes( phd );   // PixMapのRowBytesを得る(横幅バイト数)
            ww=drt.right;
            hh=drt.bottom;
            size=hh*row;
            if( prov=CGDataProviderCreateWithData( NULL,(void *)addr,size,NULL ) )
            {               // GWorldのPixMapを対象としたCGDataProviderRefを得る
                color=CGColorSpaceCreateDeviceRGB(); // RGBのCGColorSpaceRefを得る
                if( *image=CGImageCreate( ww,hh,8,32,row,color,
                                              kCGImageAlphaNoneSkipFirst,prov,
                                              NULL,0,kCGRenderingIntentDefault ) )
                                 // CGDataProviderRefよりCore Graphics Imageを得る
                    ret=noErr;
                CGColorSpaceRelease( color );  // 用済みCGColorSpaceRefをリリース
                CGDataProviderRelease( prov ); // 用済みCGDataProviderRefをリリース
            }
            if( ret )
                DisposeGWorld( *off );  // エラーが発生した場合にはGWorldを削除
        }
        return( ret );
    }
    


    imageFileToGworld()ルーチンは、FSSpecから画像ファイルのGraphicsImportComponentを得て、それをオフスクリーン用に確保したGWorld(CGrafPort)へと描画します。描画先のGWorldをGraphicsImporterに知らせるにはGraphicsImportSetGWorld()を使い、実際の描画はGraphicsImportDraw()が担当します。

    short imageFileToGworld( FSSpec *fsc,GWorldPtr *off,Rect *srt )
    {
        short                      ret=1;
        GraphicsImportComponent    gi;
    
        if( ! GetGraphicsImporterForFile( fsc,&gi ) ) // GraphicsImporterを開く
        {
            if( ! GraphicsImportGetNaturalBounds( gi,srt ) ) // 画像矩形枠を得る
            {
                OffsetRect( srt,-srt->left,-srt->top ); // 矩形枠を原点基準にする
                if( ! NewGWorld( off,32,srt,NULL,NULL,0 ) ) // GWorldを作成する
                {
                    LockPixels( GetGWorldPixMap( *off ) ); // GWorldのPixMapをロック
                    GraphicsImportSetGWorld( gi,*off,0L ); // 描画先のGWorldを設定
                    GraphicsImportSetBoundsRect( gi,srt ); // 画像矩形枠を設定
                    GraphicsImportDraw( gi );              // GWorldに画像を描画する
                    ret=noErr;
                }
            }
            CloseComponent( gi );// GraphicsImporterを閉じる
        }
        return( ret );
    }
    


    上記方法では、オフスクリーン用のGWorldを確保してからCGImageRefを得ています。しかし、Mac OS X 10.4以降ではQuickDrawやGWorldといったレガシーな仕組みを極力用いないようにと、Apple社は提言しています。そのため、QuickTimeも徐々に改良が進められており、Mac OS Xのモダンな環境に対応した新APIがいくつも追加されています。例えば、Mac OS X 10.3とQuickTime 6.4以降からは、GraphicsImportCreateCGImage()という新APIが利用できます。このAPIを使えば、GraphicsImportComponentから直接Core Graphics Imageを得ることが可能です。以下に、このAPIを用いた場合のopenViwerWindow()を紹介しておきます。非常にスマートな処理となりますが、Mac OS X 10.2をアプリケーション・ターゲットに加えるとなると、この方法は採用できませんので注意してください。

    short openViwerWindow( WindowRef window,FSSpec *fsc,WindowRef *wptr )
    {
        short                    ret=1;
        CGImageRef               image;
        WindowClass              wcls;
        WindowAttributes         watt;
        Rect                     drt;
        GraphicsImportComponent  gi;
    
        if( ! GetGraphicsImporterForFile( fsc,&gi ) )
        {        // FSSPecで指定された画像ファイル用GraphicsImporterを開く
            if( ! GraphicsImportGetNaturalBounds( gi,&drt ) )
            {    // 画像ファイルのオリジナル矩形枠を得る
                if( ! GraphicsImportCreateCGImage( gi,&image,
                              kGraphicsImportCreateCGImageUsingCurrentSettings ) )
                    // Core Graphics Imageを得る...Mac OS X 10.3 & QT 6.4以降のみ可能
                {
                    wcls=kDocumentWindowClass; // ウィンドウクラスはドキュメント
                                               // ウィンドウアトリビュートをセット
                    watt=kWindowStandardDocumentAttributes|
                          kWindowLiveResizeAttribute|kWindowStandardHandlerAttribute|
                          kWindowCompositingAttribute;
                    if( ! createMyWindow(fsc->name,'VIEW',wcls,watt,&drt,fsc,wptr) )
                    {                          // 画像表示用ウィンドウの作成
                        if( ! setupViwerWindow( *wptr,image ) ) // ウィンドウ初期化
                        {
                            setupViwerWindowEvent( *wptr ); // Event Handlerの登録
                            setWParent( *wptr ,window );     // 親ウィンドウのセット
                            ShowWindow( *wptr  );            // ウィンドウを表示する
                            ret=0;
                        }
                        else
                            DisposeWindow( *wptr );          // エラーであれば削除
                    }
                    CGImageRelease( image );    // Core Graphics Imageをリリース
                }
            }
        }
        return( ret );
    }
    


    次回も、openViwerWindow()内部で実行されている色々なルーチンを追跡します。実際には、画像表示用ウィンドウを作成しているcreateMyWindow()ルーチンの解説が中心となる予定です。

    つづく

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

     本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。今回は、ファイルリストの文字化けをフィックスする作業を完了し、新しいメソッドの定義を他の仮想イメージでも利用できるようにするためのファイル出力の方法に触れます。

    ▼文字化け解消を.txtに限って機能するようにする
     前回、FileList >> #defaultEncoderFor:でa Latin1TextConverterに設定されていたコンバータをa ShiftJISTextConverterに変更することで、文字化けを解消できることがわかりました。ただ、このままではファイルリストでの文字コードコンバータがa Latin1TextConverterであることを想定している機構があった場合に、ちょっと困ったことになりますね。そこで、今回の改変による影響を最小限にとどめるために、拡張子が.txtのファイルに限ってa ShiftJISTextConverterを使うようにしておきましょう。

     このメソッドのコードをよく見ると、冒頭でテンポラリ変数「l」にファイル名を束縛しています。

    | l |
    l _ aFileName asLowercase.

     文字列の最後の文字が’.txt’であるかどうかをチェックするために送るメッセージは「endsWith: ‘.txt’」です。 したがって、lに束縛されたファイル名を示す文字列の最後が’.txt’ならa ShiftJISTextConverterを返す式を追加すれば目的は簡単に達成できそうです。そのための式は次のようになります。

    (l endsWith: '.txt') ifTrue: [^ ShiftJISTextConverter new].

     「endsWith: …」を「ifTrue: [...]」に優先して送信しなければならないので、括弧が必要です。この括弧がないと、「endsWith: … ifTrue:[...]」というひとつながりのメッセージと解釈されてしまいますので注意してください。また、生成したコンバータ(a ShiftJISTextConverter)をこのメソッドの返値として返すために「^」が必要です。まだ式が続くので、行末のピリオドも忘れないように。

     この式を途中に挿入し、あとは前回、ShiftJISTextConverterに変えてしまった最後のデフォルトのコンバータクラスをLatin1TextConverterに戻せば完成です。

    [fig.A]加筆、修正後のFileList >> #defaultEncoderFor:メソッド
    http://squab.no-ip.com:8080/mosaren/uploads/47a.png

     これで日本語ファイルの文字化けを解消する細工はOK。以後、ファイルリストで呼び出すシフトJISエンコードの.txtファイルは文字化けせずに表示されるようになります。デスクトップメニューから「保存」を選んで使用中の仮想イメージを上書きすれば再起動後もこの修正は機能し続けます。

    ▼修正したメソッドの定義をファイル出力する
     この改変を他の仮想イメージにも適用したい場合、いったん当該メソッドの定義をSmalltalkシステムの外へ持ち出さなければいけません。このようなときは、メソッドのソースをファイルとして出力し、別の仮想イメージ内でそれを読込む作業を行ないます。Smalltalkでは、システム内のリソース(主にソースコード)のファイル出力のことをファイルアウト(file out)、リソース(主にソースコード)のファイルからの読み込みのことをファイルイン(file in)と言います。

     言うまでもなく、メソッドのソースのファイルアウトもメッセージ送信で指示できます。

    FileList fileOutMethod: #defaultEncoderFor:

     が、こうした式をいちいちタイプしたり、do itするのも面倒な話ですよね。当然、ブラウザには同等の操作を行なうGUIが用意されているので、普段はこちらを使います。今、FileList >> #defaultEncoderFor:の編集に使っている変形ブラウザの上のペイン(通常のブラウザなら上段右端のペインに相当)の黄ボタンメニューからfileOutを選んでください。

    [fig.B]FileList >> #defaultEncoderFor:メソッドのソースをファイルアウト
    http://squab.no-ip.com:8080/mosaren/uploads/47b.png

     すると、FileList-defaultEncoderFor.stという名前のテキストファイルが使用中の仮想イメージと同じフォルダに作成されます。このファイルの中身はメソッドの定義とほぼ同じ内容です。“ほぼ”なのは、このファイルに含まれるコードがどんな素性のものかを示すメタ情報が追加され含まれているからです。具体的には、冒頭に仮想イメージのバージョンやファイルアウトされた日時が、また、メソッドの定義の直前には、クラス名、カテゴリ名、オーサー名とタイムスタンプが付記されます。なお多数挿入されている「!」は、これらメタ情報の区切りを示します。

     別の仮想イメージで、このファイルをファイルインすれば、機能の追加が可能です。次回は、いくつかあるファイルインの方法と、関連した便利なツールを紹介します。

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

    ニュース・解説

    今週の解説担当:木下 誠

    ———————————————————————-
    Java 1.3.1と1.4.2 Release 2がリリース
    ———————————————————————-

    Java 1.3.1と1.4.2 Release 2がリリースされました。それに合わせて、リリースノート「Java 1.3.1 and 1.4.2 Release 2 Release Notes」も公開されました。

    このリリースは、バグフィックスが中心となっているようです。細かいフィックスの内容は、リリースノートから調べることができます。主に、描画周りの修正が行われているようです。

    業務でJavaを利用している方は、要チェックでしょう。

    Java 1.3.1 and 1.4.2 Release 2
    http://www.apple.com/support/downloads/java131and142release2.html

    Java 1.3.1 and 1.4.2 Release 2 Release Notes
    http://developer.apple.com/releasenotes/Java/Java142RNTigerR2/index.html

    ———————————————————————-
    WindowsからのQuickTimeプログラミング
    ———————————————————————-

    WindowsプログラムからQuickTime 7を利用する方法を解説したドキュメント、「Scripting the COM/ActiveX Control in QuickTime 7 for Windows」が公開されています。Windows環境では、QuickTimeはCOMまたはActiveXを使って利用することになります。これにより、C、C++、C#、Visual Basicから透過的にアクセスできることになっています。

    実際にCOM/ActiveXインタフェースを眺めてみると、結構充実しています。Cocoa用のQTKitよりも高機能であり、ちょっとうらやましかったりもします。

    Scripting the COM/ActiveX Control in QuickTime 7 for Windows
    http://developer.apple.com/quicktime/activexcontrol.html

    ———————————————————————-
    QuickTimeのQAとサンプル
    ———————————————————————-

    Technical Q&A「QA1443: Using QTPixelBufferContextCreate with NewMovieFromProperties」と「QA1441: UpdateMovieResource causes my movie file to grow bigger」が公開されています。どちらも、QuickTimeプログラミングに関するものです。

    さらに、QuickTimeに関するサンプルコード「QTPixelBufferVCToCGImage」も公開されています。これは、QuickTimeのピクセルバッファを、CGImageとして書き出すサンプルです。

    最近、QuickTimeやCore Imageなど、グラフィック系のドキュメントやサンプルが、頻繁にアップデートされていますね。

    QA1443: Using QTPixelBufferContextCreate with NewMovieFromProperties
    http://developer.apple.com/qa/qa2005/qa1443.html

    QA1441: UpdateMovieResource causes my movie file to grow bigger
    http://developer.apple.com/qa/qa2005/qa1441.html

    QTPixelBufferVCToCGImage
    http://developer.apple.com/samplecode/QTPixelBufferVCToCGImage/QTPixelBufferVCToCGImage.html

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

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

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

    2005-09-13

    目次

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

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

     今回からユーザ情報をどのようにモデル化するかを解説したいと思います。前回ご紹介しましたようにユーザには「MOSA会員」「非会員」「事務局」の3種類のタイプがあります。これらのタイプをEOFの継承を用いて表現していきたいと思います。

     継承とはオブジェクト指向を用いた開発でよく使われる手法ですが、あるクラス(親クラス)を継承してサブクラスを作ることにより、親クラスの機能を引き継いだ新しいクラスを作成することができます。つまり、関連のあるクラスを作成するときはそれぞれ個別に作成するのではなく、親となるクラスから派生させてクラスを作成することにより、効率よく体系だてて開発ができることになります。
     この考えをデータのモデリングに応用しているのがEOFの継承です。共通した属性をもつ複数のEntityを、親Entityから継承することにより作成することができます。このとき共通する属性は親Entityで定義します。そもそも、EOFはオブジェクトをデータベースに永続化(マッピング)するためのテクノロジーですので、オブジェクト指向の世界で頻繁に使用される継承関係をもったオブジェクトであっても、データベースにマッピングできるというのは自然な考え方とも言えます。

     EOFの継承には「水平」「垂直」「単一テーブル」の3種類の方法があり、それぞれ次のような特長を持っています。

    ◇垂直
     ・Entityごとにテーブルを作成
     ・各テーブルには対応するEntity固有の属性のみが含まれる
     ・パフォーマンスは悪い
    ◇水平
     ・各テーブルは親Entityの属性も含む
     ・垂直よりもパフォーマンスがよい
    ◇単一テーブル
     ・1つのテーブルがすべてのEntityの属性を含む
     ・パフォーマンスがよい

     「垂直」の場合、テーブルへのマッピングは継承したクラスの実装とよく似ています。つまり、親Entityに対応するテーブルには親Entityの属性のみが含まれ、継承したEntityに対応するテーブルには、そのEntity固有の属性しか含まれません。このように、クラスの実装がそのままテーブルの定義にも対応していますので、分かりやすくはあるのですが、継承したEntityの1レコードを取得する場合、親Entityのテーブルが必ず必要になってきますので、パフォーマンスはよくありません。
     一方「水平」の場合、「垂直」では親Entity用のテーブルに含まれていた属性を、継承したEntity用のテーブルに含めてしまいます。つまり1つのテーブル内にすべての属性を含むことができますので、よりよいパフォーマンスを得ることができます。
     さらに「単一テーブル」の場合は、継承関係をもったすべてのEntityを1つのテーブルで管理します。この場合、Entityによっては使用しない属性が発生してしまいますが、「水平」と同様に1つのテーブルにレコードを構成するすべての属性を含むことができます。「単一テーブル」の場合、テーブル内の全件をFetchすれば、Entityにかかわらず、継承関係をもったすべてのレコードを取得することができます。

     EOFの継承はこのような特長をもっており、パフォーマンスを重視するのであれば「単一テーブル」あるいは「水平」を用いるのがよいでしょう。ただし継承の種類によってメンテナンスの手間が異なってきますので、まずはEntityの属性がどのようにテーブルとマッピングされるかを理解しておくことが重要になります。
     今回のシステムでは「単一テーブル」を用いてユーザ情報をモデル化してみたいと思います。継承の方法については次回解説したいと思いますが、参考になるドキュメントとサンプルを紹介しておきます。

    ・ドキュメント
    http://developer.apple.com/documentation/WebObjects/UsingEOModeler/
    「Modeling Inheritance」の章
    ・サンプル
    /Developer/Examples/JavaWebObjects/WOInheritanceExample

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

     承前(と、この言葉ばかり使ってるけど他にかっこいい言葉って無いのかな)、例えば編集メニューの「カット」に初期値でターゲットとして結びつけられているのはNibファイルを作ると自動的にできる「First Responder」というアイコンで、その意味するところは「レスポンダ・チェイン」であった。そして、このレスポンダ・チェインの先頭は、その時点のキー・ウィンドウ(キーボード・イベントを受け取るウィンドウ)のfirstResponderになっているのだった。よね?

     ここでちょっと老婆心。念のため語句の意味するところを確認しておきたい。
     ワタシが「レスポンダ・チェイン」と呼んでいるのは「NSResponderのサブクラスのインスタンス(面倒なので正確ではなくなるが以降「NSResponder」と略させてちょうだい)が、そのインスタンス変数nextResponderによってつながっているもの」である。特定のモノを指しているのではなくて、一般名詞として使ってるわけ。
     編集メニューの「カット」からのメッセージを受け取るのは、前にmouseDown: を受け取った時に辿ったレスポンダ・チェインとは別の流れだけど、これもレスポンダ・チェインであることに変わりはない。一つのNSResponderが持てるnextResponderは一つだけだが、複数のNSResponderが同じオブジェクトをnextResponderとして保持することはあり得るので、いくつものサブビューを持つウィンドウにおけるレスポンダ・チェインの全体像は、何本もの川が合流して大河になり海に流れ込むような感じになってる。いいかな?

     「カット」とか「コピー」とかの編集関係メニューアイテムからのアクションは、まぁたいていの場合キー・ウィンドウで処理される。でもNibファイルの「First Responder」アイコンに接続されているのは編集関係のメニューばかりではない。
     このテの「ターゲットが動的に変わるアクションがどんな順番でオブジェクトに実行を打診(てのもおかしいが言わんとするトコロは解るでしょ?)していくのかを以下にちと細かく追ってみる。
     最初は上で見たようにキー・ウィンドウのfirstResponderを先頭とするレスポンダ・チェインを辿る。このチェインの最後はご存知の通りキー・ウィンドウ自身になる。そこまで辿っても応答できるオブジェクトが見つからないと、このウィンドウのdelegateに打診する。
     テキストエディタのような、ドキュメント・ベースのアプリでは、次がキー・ウィンドウのNSWindowController、そしてNSDocumentへ進む。お気づきだろうか、「ファイル」メニューの「保存」だの「復帰」「印刷」だのは、こうしてめでたくNSDocumentに到達するのである。もしキー・ウィンドウとメイン・ウィンドウが違ってる場合には、次にメイン・ウィンドウのfirstResponderからのレスポンダ・チェインを辿ってそのNSDocumentまで以下同文。
     それでも応答されなければ、NSApplication(例えば「……を隠す」など)、そしてそのdelegate、おしまいにはNSDocumentControllerが控えていて、こいつが「新規(New Documentのこと、ただ「新規」とだけ書くとわかりにくいな)」や「開く…」を担当してるわけである。やぁ長い長い道のりでした天竺取経の旅ご苦労様(違うな)。

     これで、とにもかくにもNSViewのNSResponderのサブクラスとしての機能についてもあらかたの説明を終えたわけである。隔週のキレギレ話なのでまとめて読むと同じことを繰り返してたりするかもしれないけどそこはご勘弁(一応直前の原稿だけは必ず読み返して書いてるんだけどね)。次回からはNSWindowを取り上げたい。NSWindowもNSResponderのサブクラスである部分は同じだから、NSViewみたいな長丁場にはならないと思うんだが……。
     あ、そうそう。申し込みが始まってると思うけど、今年も湘南ミーティングで講師やります。今回のお題は「Spotlight importerプラグインの作成」。あ、これ簡単なので予習をやったりしないように。講師の存在意義がなくなっちまうので(笑)。
    (2005_09_07)

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

    UNIXとしてのMac OS X

    〜Perlについて(20)〜

     こんにちは、高橋真人です。
     量指定子の次は、「言明」というものについて説明します。
     実は白状しますと、この原稿を書くためにLarry WallのプログラミングPerlを参照するまで、私はこれから説明する一連のものに「言明」なる名前が付いているのを知りませんでした。
     もっとも、他の文献もいくつか当たってみた限りでは、この「言明」という表現を使っているものはひとつも見つけられませんでしたから、正規表現使いの中でも、この言い方に馴染んでいる人は多くないでしょう。

     具体的な例を出さずに話を続けても、読んでいる人には何のことか分からないでしょうから、先に例を挙げます。
     今回説明する言明というものには以下のようなものがあります。

    ^
    $
    ¥b

     まだ他にもあるのですが、よく使われるものに限定しておきます。

     ^は行の先頭を表すために使われます。これは前回の最後の説明でも使ったように、「全ての空白を除去したいわけではないが、先頭のものだけは取り除きたい」などという時に使うのに便利です。
     以前説明した否定文字クラスでもこの記号が使われていますが、意味も役割も全く違うことに注意してください。正規表現にはこのように「使われる場所によって全く別のものになる」記号が他にもいくつか存在します。

     $は^とは逆に行末を表現します。
     テキストデータ、特に人間が手打ちしたものであるとか、Webページをブラウザのウインドウからコピーしたようなデータには、とかくムダな空白文字が入りますが、こんなとき、この記号を使って、/[ ¥t]*$/としてマッチさせた文字列を空白に置き換えれば、きれいに取り去ることができます。
     ちなみに全角空白も考慮しようとすると、Perlではちょっと話が複雑になりますが、日本語対応エディタで、正規表現での検索置換ができるものでしたら、上記文字クラスに全角空白を加えてうまく行くケースも多いので、試してみる価値はあるでしょう。ここでも以前紹介したmiではうまく行くようです。

     さて¥bですが、これは単語の区切りを表現します。よく単語境界とかアンカー文字などと呼ばれます。ただ単語の区切りといっても、普通の考え方とは少し異なるので注意が必要です。
     たとえば、以下のようなテキストがあるとします。

    orange, banana, peach, apple and cherry

     ここから、eで終わる単語を抽出したいとしましょう。いろんな正規表現が考えられますが、今回は以下のような表現を使います。

    /¥b.+?e¥b/

     まずドットですが、何とまだこの連載では説明していませんでしたが、正規表現においては「改行以外の任意の文字にマッチする」役割を持ち、極めて頻繁に使われます。
     このドットに前回説明した + 記号を組み合わせて、「単語境界、任意の文字の1つ以上の連続、e、そして単語境界」という表現になります。+ のあとに? が一つ付いていますが、これは正規表現には「最長マッチ規則」というのがあって、「可能な限り長い部分にマッチする」のが決まりです。これを抑制するために、+ や * のあとに ? を付けるのです。
     さて、このようにしてマッチさせると、「orange」と「apple」を取り出すことができます。重要なのは、「apple」の a の直前のスペースはマッチ範囲に含まれていないということです。正規表現における単語境界というのは、いわゆる「区切り文字」のことではなく、単語を構成する文字(アルファベットなど)とそれ以外の文字(空白文字など)との間の部分そのものを意味します。
     冒頭で言明(英語で言うとassertion)と言いましたが、これは「ここ(¥b)に単語とその他の境界がある」と言明しているということなのです。

    ニュース・解説

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

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

    【開発環境】

    前号で木下さんも紹介されていますが、Apple社のサイトに「Developer Transition Resource Center」というWebページが登場しました。「Performance Optimization Development Mailing List」といメーリングリストへの参加もできるようですね。

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

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

    前回から9月9日の期間中、Apple社のDocumentationサイトには数多くのドキュメントが登録されました。ただし、ほとんどは内容のマイナーチェンジです。今回も、その中で初版と内容が大幅変更になったドキュメントだけをピックアップして記載しておきます。注目は「AltiVec/SSE Migration Guide」ですが、さて、これによりどこまでAltiVecユニットが失われてしまった状況をカバーできるのでしょうか(笑)。また、新規のデベロッパー向け読み物が2つ登録されました。「Working with Xcode: Building Applications for the Future」については、前号の木下さんの記事を参照してみてください。

    「AltiVec/SSE Migration Guide」(PDFあり)(初版)
    「FireWire Device Interface Guide」(PDFあり)
    「HIToolbar Reference」(PDFあり)
    「HIView Reference」(PDFあり)
    「Internationalization Programming Topics」(PDFあり)
    「iWork Programming Guide」(PDFあり)(初版)
    「Kernel Extension Concepts」(PDFあり)
    「Message Framework API Reference」
    「QuickTime 7 for Windows Update Guide」(PDFあり)(初版)
    「Spotlight Reference」(初版)
    「Universal Binary Programming Guidelines」(PDFあり)
    「vDSP Library」(PDFあり)
    「vecLib Framework Reference」(PDFあり)(初版)
    「What’s New In QuickTime」
    「Window Manager Reference」

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

    「Adopting Universal Binaries on Mac OS X」(読み物)

    http://developer.apple.com/macosx/adoptinguniversalbinaries.html

    「Working with Xcode: Building Applications for the Future」(読み物)

    http://developer.apple.com/tools/xcode/xcodefuture.html

    前回から9月9日の期間中、新規テクニカルノートはひとつも登録されませんでしたが、新規テクニカルQ&Aの方は3つ登録されています。

    QA1400「Adding Unicode characters to Text Media in a Text Track」
    QA1440「Implementing a CVFillExtendedPixels- CallBack」
    QA1401「Registering custom pixel formats with QuickTime and Core Video」

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

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

    前回から9月9日の期間中、Apple社のSample Codeサイトには、新しいサンプルソースコードが2つ登録されました。両方ともQuickTime関連なのですが、「QTKitPlayer」の方は、CocoaのQTKit Frameworkの使い方の総合的なお手本となっています。

    「CaptureAndCompress- IPBMovie」(QuickTime関連)
    「QTKitPlayer」(QTKit関連)(初版)

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

    【デベロップメント SDK】

    前回から9月9日の期間中、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
    Copyright (C)2005 MOSA. All rights reserved.

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

    2005-09-06

    目次

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

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

     前回に引き続きシステムで扱うデータについて検討していきます。前回は登録者情報について検討してみましたが、今回はその他のデータについてみていきましょう。

    ユーザタイプ

     現在、以下の3種類のユーザタイプを想定しています。

    ・MOSA会員
    ・非会員
    ・事務局(管理者)

     登録したユーザは、それぞれユーザタイプを設定することになりますが、システムを利用するさいにユーザタイプによるアクセス制限をおこないます。例えば「MOSA会員」のみ閲覧可能なページといった制限をおこないます。つまり、アクセスのあったユーザを特定(ログイン認証が必要)して、そのユーザのタイプにより処理を振り分けるということになります。

     こういったユーザタイプの実装方法としては何通りか考えられます。まず、ユーザのEntityにユーザタイプ用のAttributeを用意するのがもっとも単純な実現方法でしょう。たとえばMOSA会員は「1」、非会員は「2」、事務局は「0」といったやり方です。たしかに実現方法は単純なのですが、これでは「1」というユーザタイプがなんであるのかといった情報を別途管理する必要があります。
     そこで2つ目の方法としては、ユーザタイプ用のEntityを別途用意しておき、ユーザEntityとのRelationを設定します。こうすればユーザタイプはユーザとは切り離して管理でき、ユーザタイプに関する属性を一元管理できるようになります。
     また、EOFを用いればオブジェクト指向的アプローチをとることもできます。まず、すべてのタイプのユーザに共通する項目を抽出して、基底ユーザEntityとして定義します。次にその基底ユーザEntityから、各タイプのユーザEntityを派生させ、派生したEntityにはそれぞれのタイプごとに依存する属性情報をAttributeとして追加していきます。このようにモデルを定義すれば、各ユーザタイプをそれぞれ異なったEntityとして表現することができます。

    開発者募集情報

     ビジネスマッチングには2種類のやり方があります。1つは登録されているユーザのProfile情報を検索/閲覧し、目的に該当する人材を探すというやり方。もう1つは案件情報を掲載して人材を募集するというやり方です。
     後者の人材を募集するやり方では、まず案件の内容をシステムに入力することになりますが、次のようなデータが考えられます。

    ・概要
    ・期間
    ・開発環境
    ・言語
    ・地域/条件等
    ・開発依頼内容
    ・備考

     人材を募集する場合は、案件ベースで一時的に募集する場合と、社員を募集する場合がありますが、上記の項目は一時的に募集する場合を想定しています。
     これらのデータですが、基本的には文字列情報として記録することになります。募集情報を検索するとなると、まとまりのあるデータのほうが扱いやすいのですが、募集情報によって様々な要求があるでしょうから、基本的には自由入力とします。言語などは、あらかじめ登録しておいた一覧から選択するような形式でもよいでしょうが、マイナーな言語をどこまで登録するのかといった問題もあります。

    評価情報

     マッチング結果として、マッチングの成立件数を記録します。成立の確認をどのようにするかという問題はありますが、マッチング結果はつまり実績になりますので、人材を探すさいに1つの評価基準にもなるでしょう。
     もっともネットオークションなどと違って、短期間で成立件数が増えるようなことはないでしょうが、成立件数の他に会員からの紹介推薦文の掲載もおこないます。こちらは会員同士がお互いに推薦をおこなうというものです。実際にビジネスマッチングをおこなった相手からの推薦があれば、よい評価材料にもなるでしょう。

     さて、ビジネスマッチングシステムとして扱うデータは以上です。他にも細かなデータや、管理用のデータなどが必要になってきますが、主要なデータとしては以上です。今後はこれらのデータをモデルとして定義してから、アプリケーションの開発を進めていきたいと思います。

    小池邦人のCarbon API 徒然草(2005/09/02)

    画像ファイルをウィンドウに表示する(その1)

    本サンプルアプリケーションでは、データブラウザに登録されたファイル一覧のダブルクリック(もしくは表示ボタンクリック)で、その画像をスクロールバー付きのウィンドウへ表示(オープン)することが可能です。今回からは、自作アプリケーションへの画像表示用ウィンドウの実装について解説していきたいと思います。

    Mac OS X 10.2から、Carbon Frameworkには「HIView」という仕組みが導入されました。その仕組みの一部として、「Image View」や「Scroll View」といった新しいユーザインターフェースユニット(旧コントロールの一種)が用意されています。これらと、Carbon Event Handlerををうまく利用することで、画像をスクロールバー付きのウィンドウに表示する機能を簡単に実現することが可能となりました。本サンプルは、このImage ViewとScroll Viewを使うことで、画像ファイルをウィンドウに表示させます。

    画像を独立したウィンドウに表示(オープン)させるには、データブラウザの画像ファイル一覧をダブルクリックするか、表示させたい画像ファイルを選択しておいてから、カタログウィンドウの「表示」ボタンをクリックします。後者の場合には、同時に複数の画像ファイルをオープンすることが可能です。前者は、「データブラウザ・コールバックルーチン」を解説した時に紹介した、myNotification()ルーチンが実行していますので、そちらを参照してみてください。後者の場合は、以下のopenSelectedImageFile()ルーチンが実行しています。

    #define    MAX_FILE  1000      // カタログに登録できる最大ファイル数
    
    void openSelectedImageFile( WindowRef window,short launch )
    {
        unsigned long    i,nb,ct,item[MAX_FILE]; // ファイル最大数は1000
        ControlRef       browser;
        WindowRef        wptr;
        ObjectPtr        optr;
    
        getMyControlRef( window,BROW_ID,&browser );  // ブラウザのControlRefを得る
        getSelectedDataBrowser( browser,item,&ct );  // 選択されているアイテムを得る
        for( i=0;io_fsc ); // 画像を作成したアプリを起動し
            else                                   // そちらにオープンしてもらう
                openViwerWindow( window,&optr->o_fsc,&wptr );
                                                   // 画像表示用ウィンドウをオープン
        }
    }
    


    まず最初に、以下のgetSelectedDataBrowser()を使い、データブラウザで選択されている画像ファイルのアイテム番号と、その個数を得ます。

    void getSelectedDataBrowser( ControlRef browser,unsigned long item[],
                                                           unsigned long *ct )
    {
        long    size;
        Handle  hd;
    
        *ct=0;
        if( hd=NewHandle( 0 ) ) //アイテム番号を保存するためのHandleを確保
        {
            GetDataBrowserItems( browser,kDataBrowserNoItem,0,
                                                  kDataBrowserItemIsSelected,hd );
                                            // 選択されているアイテム番号を得る
            if( size=GetHandleSize( hd ) )  // Handleのサイズを得る
            {
                HLock( hd );                      // Handleをロックする
                BlockMoveData( *hd,item,size );   // 引数のitem[]へコピーする
                *ct=size/sizeof( unsigned long ); // アイテム番号の個数を計算する
            }
            DisposeHandle( hd ); // 確保したHandleを削除
        }
    }
    


    アイテム番号から1を引いた値は、カタログウィンドウのプロパティとして保存されているWInfo構造体(以下参照)のw_optr配列の引数と一致します。そこで、getWObject()ルーチンを使い、その番号に対応するObject構造体のポインタを得ておきます。

    typedef struct {
                        WindowRef       w_pref;           // 親ウィンドウのWindowRef
                        unsigned long   w_count;          // ObjectPtrの個数
                        ObjectPtr       w_optr[MAX_FILE]; // ObjectPtrのリスト
    
                    }   WInfo,*WInfoPtr,**WInfoHandle;
    
    short getWObject( WindowRef window,unsigned long nb,ObjectPtr *optr )
    {
        WInfo    winf;
    
        if( ! getWInfo( window,&winf ) ) // ウィンドウのプロパティとして
        {                                // 保存されているWInfo構造体を得る
            *optr=winf.w_optr[nb];       // 指定番号のObjectPtrを返す
            return( noErr );
        }
        return( 1 );
    }
    


    続いて紹介するのは、openSelectedImageFile()で呼ばれているopenViwerWindow()ルーチンです。最初にimageFileToImage()ルーチンで、画像ファイルからCore Graphics Imageを作り、それを、createMyWindow()ルーチンで作成したウィンドウに表示させます。ウィンドウにImage ViewやScroll Viewを配置するのは、setupViwerWindow()ルーチンの役割です。そして最後に、setupViwerWindowEvent()で必要とされるCarbon Event Handlerが登録されています。

    short openViwerWindow( WindowRef window,FSSpec *fsc,WindowRef *wptr )
    {
        short               ret=1;
        CGImageRef          image;
        WindowClass         wcls;
        WindowAttributes    watt;
        GWorldPtr           off;
        Rect                drt;
    
        if( ! imageFileToImage( fsc,&image,&off,&drt ) )
        {                              // 画像ファイルからCore Graphics Imageを作る
            wcls=kDocumentWindowClass; // ウィンドウクラスはドキュメントにセット
            watt=kWindowStandardDocumentAttributes|kWindowLiveResizeAttribute|
                 kWindowStandardHandlerAttribute|kWindowCompositingAttribute;
                                       // ウィンドウアトリビュートをセット
            if( ! createMyWindow( fsc->name,'VIEW',wcls,watt,&drt,fsc,wptr ) )
            {                          // 画像表示用ウィンドウの作成
                if( ! setupViwerWindow( *wptr,image ) ) // ウィンドウの各種初期化
                {
                    setupViwerWindowEvent( *wptr ); // Carbon Event Handlerの登録
                    setWParent( *wptr ,window );    // 親ウィンドウのセット
                    ShowWindow( *wptr  );           // ウィンドウを表示する
                    ret=0;
                }
                else
                    DisposeWindow( *wptr );         // エラーであれば削除する
            }
            CGImageRelease( image );    // 得られたCore Graphics Imageをリリース
            DisposeGWorld( off );       // オフスクリーン用GWorldを削除
        }
        return( ret );
    }
    


    画像ファイルを選択し、「表示」の代わりに「起動」ボタンが押された場合には、アプリ起動オプションがONで(引数のlaunchが1)openSelectedImageFile()が実行されます。その時、画像を作成したアプリケーションを起動しているのが、launchApplication()ルーチンです。この処理にはシステムのLaunch Servicesが提供するAPIが利用されています。各APIの詳しい内容については、LSInfo.hやLSOpen.hを参照してみてください。

    short launchApplication( FSSpec *fsc )
    {
    short ret=1;
    FSRef ref;

    if( ! FSpMakeFSRef( fsc,&ref ) ) // FSSpecからFSRefを作成する
    ret=LSOpenFSRef( &ref,NULL ); // 作成したアプリをオープンしそれに渡す
    return( ret );
    }

    次回は、openViwerWindow()から呼ばれているimageFileToImage()ルーチンについて解説します。基本的には、画像ファイルからCore Graphics Imageを作る処理なのですが、Mac OS Xのバージョンにより、その方法が大きく異なることを紹介したいと思います。

    つづく

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

     本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。引き続き、ファイルリストの文字化けをフィックスする作業を通じて、Smalltalkならではの便利機能に触れてゆきます。

    ▼メソッドのバージョンをもとに戻す(バージョン管理システム)
     前回、「FileList >> #readContentsBrief:」というメソッドを改変することで、ファイルリストをテキストエディタモードで呼び出したとき、このメソッドが呼び出されていることを確認しました。もはやこの細工は必要ないので、忘れないうちに元に戻しておくことにします。

     もちろん追加した行を削除して再コンパイルすれば済むことですが、ここではあえて、Smalltalkシステムのバージョン管理機構を使用して、元のバージョンを復活させてみましょう。

     Smalltalkでは、メソッド単位でコンパイルが完結することは、前回すでに体験していただいているとおりです。したがって、バージョン、つまり、改変の履歴も、各メソッドごとに個別に管理されています。注目するメソッドの過去のバージョンを見るには、ブラウザでそのメソッドを閲覧中にウインドウ中段のボタン群の中にある「versions」ボタンをクリックします。

    [fig.A]「versions」ボタン
    http://squab.no-ip.com:8080/mosaren/uploads/46a.png

     バージョンブラウザの上のペインには、そのメソッドの改変履歴がリストで表示されます。リストには、改変者のイニシャル(最初のメソッド改変のときに尋ねられたり、Utilities setAuthorInitialsでセットされたものです)、改変の日時、クラス名、メソッド名の順に表示されています。リストの上に行くほど最近の改変で、一番上のものが現行バージョンです。ためしに現行バージョンをクリックしてみてください。

    [fig.B]バージョンブラウザ
    http://squab.no-ip.com:8080/mosaren/uploads/46b.png

     ウインドウ中段、右端の「diff」(差分表示)オプションがオンになっているので、加えられた行は赤く、また、この差分にはありませんが、削除された行は青い色で、さらに取消線が付いた状態で表示されます。

     では、改変を加える前のバージョンに戻してみましょう。上のペインの2行目をクリックして選択します(この時点で、差分の青い取消線表示も確認できるはずです)。選択したバージョンに戻すには、ウインドウ中段のボタン「revert」をクリックします。これだけです。

     ウインドウを切り換え、元のブラウザに戻って確認してみると分かりますが、ちゃんとメソッドは手を加える前のバージョンに戻っています。

    ▼原因メソッドの呼び出し
     前回の解析の結果、FileList >> #readContentsBrief:の定義中、

    f converter: (self defaultEncoderFor: self fullName).

    とあるところで正しくコンバータが設定されていないのが、どうやら文字化けの原因であることが分かりました(簡単のため、そういうことにしてください)。ここでコンバータを生成している、#defaultEncoderFor:というメソッドがなにをしているのかを覗いてみることにしましょう。

     Smalltalkのメソッドは、やはりそれ自体がオブジェクトで、自分の定義の中で、どんなメソッドを呼び出しているのか(正確には、呼び出すためのメッセージを送信しているか)を把握しています。たとえば、今、注目している「FileList >> #readContentsBrief:」というメソッドなら、これにmessagesというメッセージを送ることで、自分の定義の中で呼び出しているメソッドの名前の一覧を返してきます。

    (FileList >> #readContentsBrief:) messages
    
    =>  a Set(#oldFileOrNoneNamed: #defaultEncoderFor: #not #braceWith:with:with: 
    #translated #contentsOfEntireFile #'<=' #next: #readServerBrief #fullName #close 
    #converter: #size #format: #isRemoteDirectory #'==')
    


     この性質を利用して、定義の中で送信されているメッセージに関係した情報をたやすく引き出せるように用意されたUIが、ブラウザ中段やや右寄りに並んでいるボタン「senders」と「implementors」です。これらのボタンをクリックすると、現在ブラウズ中のメソッド名に続いて、メソッドにmessgesメッセージを送信したときに得られるメソッド名の一覧がポップアップします。

    [fig.C]「implementors」をクリックしたときポップアップするメニュー
    http://squab.no-ip.com:8080/mosaren/uploads/46c.png

     このポップアップから適当なメソッド名を選ぶと、クリックしたのがたとえば「senders」ならsenders of it、つまり、選択した項目と同名のメソッドを呼び出しているメソッドの一覧がブラウズできます。これは、メソッド名をタイプして入力後、選択してcmd-Nとしたのと同じです。同様に「implementors」ならimplementors of it、つまり、選択した項目と同名のメソッドの定義をブラウズできます(cmd-B、もしくはcmd-Mと同じ)。

     今回は、指定したメソッドの定義を見たいので、implementorsボタンをクリックしてdefaultEncoderFor:を選びます。さいわい、この名前を持つメソッドはFileListに定義されたひとつだけです。

    [fig.D]FileList >> defaultEncoderFor:の定義
    http://squab.no-ip.com:8080/mosaren/uploads/46d.png

     最後の行で、a Latin1TextConverterを返していますが、どうやらこれが文字化けの元凶のようです。試しに、文字化けの起こらないa ShiftJISTextConverterを返すように差し替えて動きを見てみましょう。

     まず、Latin1TextConverterを選択して、Shiftjまでタイプしたあと、cmd-Qとします(クラス名やメソッド名の補完サービス)。すると、ShiftJISTextConverterと完全なクラス名が挿入されるので、そのままaccept(cmd-S)してコンパイルします。

    [fig.E]暫定的なFileList >> defaultEncoderFor:の定義
    http://squab.no-ip.com:8080/mosaren/uploads/46e.png

     あらためて、どこか適当な場所で、次の式をdo it (cmd-D)してみてください。

    (FileStream fileNamed: 'ShiftJisExample.txt') edit

     どうでしょう。文字化けは解消されましたね。次回は、この改変の影響を最小限にするため、ファイルの拡張子が.txtか.textの場合だけa ShiftJISTextConverterを返すような仕組みを設けて、このハックを終わりにしようと思います。

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

    ニュース・解説

    今週の解説担当:木下 誠

    ----------------------------------------------------------------------
    Developer Transition Resource Centerがオープン
    ----------------------------------------------------------------------

    ADCに、Intelチップへのアプリケーションの移行を促進するためのWebページ、「Developer Transition Resource Center」がオープンしました。基本的に、あちこちに分散していたIntel移行に関するドキュメントの、リンク集となっています。

    特に目新しい情報はありませんが、今後追加される情報は、要チェックでしょう。WWDCでの関連するセッションのビデオへのリンクがあるのが、うれしいところです。(視聴にはADCへの登録が必要)

    また、Universal Binaryへの移行をまとめた記事、「Adopting Universal Binaries」も公開されていました。Universal Binaryの必要性と、そのために必要なリソースを、まとめて紹介する内容になっています。

    Developer Transition Resource Center
    http://developer.apple.com/transition/index.html

    Adopting Universal Binaries
    http://developer.apple.com/macosx/adoptinguniversalbinaries.html

    ----------------------------------------------------------------------
    Xcode 2.1の紹介
    ----------------------------------------------------------------------

    Xcode 2.1の機能を紹介する記事、「Working with Xcode: Building Applications for the Future」が公開されていました。Xcodeが持つ機能を、初めて使う人に紹介するような内容になっています。

    事実上、Mac OS Xでの開発環境は、Xcodeただ一つになってしまいました。今後は、Intel対応などのような機能の拡張に加え、他の環境からの移行者を受け入れるための、ユーザインタフェースの拡充が求められるでしょう。

    Working with Xcode: Building Applications for the Future
    http://developer.apple.com/tools/xcode/xcodefuture.html

    ----------------------------------------------------------------------
    Technical Q&A
    ----------------------------------------------------------------------

    新規Technical Q&Aが、4つ公開されていました。

    Core Videoに関するもの(QA1440、QA1401)、QuickTimeのテキストトラックに関するもの(QA1400)、IntelマシンでのJavaアプリケーションに関するもの(QA1295)です。

    QA1440: Implementing a CVFillExtendedPixelsCallback
    http://developer.apple.com/qa/qa2005/qa1440.html

    QA1401: Registering custom pixel formats with QuickTime and Core Video
    http://developer.apple.com/qa/qa2005/qa1401.html

    QA1400: Adding Unicode characters to Text Media in a Text Track
    http://developer.apple.com/qa/qa2005/qa1400.html

    QA1295: Java on Intel-based Macintosh Computers
    http://developer.apple.com/qa/qa2005/qa1295.html

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

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