Backnumber

June, 2006
May, 2006
April, 2006
March, 2006
February, 2006
January, 2006
December, 2005
November, 2005
October, 2005
September, 2005
August, 2005
July, 2005
June, 2005
May, 2005
April, 2005
March, 2005
Feburary, 2005
January, 2005
December, 2004
November, 2004
October, 2004
September, 2004
Augsut, 2004
July, 2004
June, 2004
May, 2004
April, 2004
March, 2004
February, 2004
January, 2004
December, 2003
November, 2003
October, 2003
September, 2003
August, 2003

- HMDT archive-
February, 2004

Feburary 28

またまたはじめてのブラウザのつくり方 10.3を更新。クッキーを表示するです。

はじめてのブラウザのトピックは、後は、ダウンロード、戻る進むリスト、認証、検索ぐらいかな。

Feburary 24

はじめてのブラウザのつくり方 10.3を更新。ステータステキストを Cocoa バインディングを使って表示するだ。

Cocoa バインディングを使うと、ほんとアプリケーションの作り方が、がらっと変わるね。

追記:プロジェクトのイメージから、一部ファイルが抜けているという、どうしようもない致命的なミスを犯していたので、アップし直しました。ごめんなさい。

Feburary 20

XO さんの、Cocoa バインディングが分かりにくいワケに突っ込んでみる。長いので、こちらで。

KVO (Key Value Observing) で、確かにこれはドキュメント化されてるけど、Observing、という名前とは裏腹に、実際は値を「監視」してるわけじゃない。

どっちかというと、中身の動きはNotification、つまり「通知」だよね。Notificationってのがすでに使われてるからObservingになったんじゃないかと思うぐらい。

「監視」という名前から、ポーリングのような処理を想像する?おっしゃるとおり、中身は「通知」です。Apple の KVO のドキュメントでも、真っ先に NSNotification との比較がされてるしね(What is Key-Value Observing)。NSNotification との違いは、NSNotificationCenter を経由するか、一対一の関係か、というところでしょう。

分かりにくいのが、ViewからControllerに向かってのびるKVCの矢印。 これが分かりにくい原因は、Interface BuilderのInfoパネルの「Bindings」ペインにある「Controller Key」と「Model Key Path」のせいじゃないかと。

「Controller Key」は分かるか?んー、Controllerのキー?なんかよく分からない。

Controller Key っていうのは、ビューからコントローラに KVC でアクセスするための、プロパティです。つまり、このキーを使って、コントローラに valueForKey: でアクセスするわけ。KVC の名前規約(Accessor Search Implementations Details)によれば、始めはインスタンス変数にトライして、そこになければアクセッサメソッドを探す。コントローラで使われることになるキーの多くは、インスタンス変数に対応していない。つまりこれは、名前を指定したメソッドの呼び出しです。Interface Builder の Controller Key コンボボックスに出てくるのは、NSObjectController や NSArrayController のメソッドの名前です。

では、このメソッドを呼ぶと何が返ってくるか?モデルが返ってくるんですよ。Controller Key ってのは、コントローラからモデルを取得するためのキーです。ただし、コントローラが管理しているモデルは 1 つではない。動的に変わることもある。さらに、コントローラはモデルの「選択」もサポートしている。これらのどれを取得するかを決定するのが、Controller Key です。

ちなみに、Controller の状態を取得するためのキーもある。canAdd とか。これはモデルは返さないっす。

「Controllerのメンバ変数」は「Controller Key」に設定するのであって、「Model Key Path」には「ModelのKeyへのPath」じゃなくて「ModelのKey(=メンバ変数)」を指定する。Pathが余分。

いや、そうでもないのか。Controllerのが指すのは直接関連するオブジェクトだけで、何もModelが単一のオブジェクトでできてるとは限らないからか。つまりModelのKeyにたどり着くのに、いくつものリレーションをたどる場合もあると。

Model Key Path の場合は、valueForKeyPath: を使って、モデルのプロパティにアクセスするんですな。キー・パスの利点は、関連をたどることができること。たとえば、バインディングの Bind to には、コントローラ以外にも File's Owner を指定することもできる。この場合、Controller Key は使えなくなるんで、Model Key Path を使って、モデルを指定する。たとえば、File's Owner が NSApplication で、そのデリゲートが WebView を持っていて、WebView から WebPreferences を取り出して、その defaultFontSize にバインディングするには、Model Key Path に、delegate.webView.preferences.defaultFontSize って指定してやればいい。ま、これは、極端な例だけど。この場合、File's Owner をかますので、nib でインスタンス化していないオブジェクトも、モデルとして指定できる。

また、キー・パスには演算子を指定することもできる(Array Operators)。オブジェクトの数や、値の平均、最小値、最大値とかが得られる。これを使うと、対多関連のプロパティを表示するときに、選択しているものが全体の何番目かを示す「2 of 200」って感じのを、コーディングなしで実現できたりする。

で、最後、全体のまとめである、KVB (Key Value Binding)。これは全然仕組みが分からない。リファレンスに一部のヒントはあるんだけど、全体像は公開されてない。

これ分からんよね。1 つは、おっしゃってるように、bind:toObject:withKeyPath:options: で何をやればいいのか分からない。あと、現在バインディングしている、またはバインディングされているものを知る方法が無い。だから、動的にバインディングを変更できないし、バインディングしているキー・パスを知ることもできない。これ、けっこう嫌だ。

いちおう、NSObject の observationInfo がそれらしいんだけど、void* 型のデータが返ってきて、中身公開されていないし。この中身が分からんと、不便だなー。

さらに、ツッコミ返し

この、「プロパティ」ってのが実際のところ一体何なんだというのが分かりにくい原因? 「属性(attributes)と関連(relationship)はプロパティ(property)と呼ばれることもあります」っていうことなんだけど、じゃattributesとrelationshipって何?

属性と関連はきちんと定義(Terminology)がありまして、端的に言うと、属性はプロパティを持たないもの、関連はプロパティを持つものです。さらに踏み込んでいってしまえば、属性はバインディングの対象になるもの、関連はならないもの、です。関連から属性を取り出して、それをバインディングすることになります。たぶん、こう言い切っていいと思うんだけど。

具体的にいえば、属性は NSNumber だったり NSString だったり NSColor だったり。NSNumber や NSString はテキストフィールドの value にバインディングできるし、NSColor はカラー・ウェルの value や、テキストフィールドの textColor にバインディングできる。

それに対して、関連は自分で定義したモデルクラスだったり NSMutableDictionary だったり。これを直接バインディングすることはなくて、そっから属性を取り出します。

関連の概念では特に対多関連が大事です。たとえば、テーブルにデータを表示するときのことを考えてください。テーブルの 1 行分のデータが 1 つのモデルクラスに納められている。そのモデルクラスは Music っていうクラスで、titleartisttime っていう属性を持っているとする。それを、テーブルのそれぞれの列に表示するとする。

こういう場合は、テーブルとコントローラの間を「対多関連」で関連づけます。これには、arrangedObjects コントローラキーを使うでしょう。そして、コントローラとモデルの間は、「属性」を指定する。title とか artist ですね。

というわけで、属性と関連の違いは、Cocoa バインディングの肝です。少なくとも、NSArrayController を使うときは、かなり意識します。個人的には、NSHierarchyController みたいのが欲しいっすね。で、それを NSOutlineView や NSBrowser にバインディングできれば、とっても嬉しいんだけど。

Feburary 19

前に、iBook に不具合があるから、ロジックボードの交換を行う、っていう告知があったでしょう(iBook - Logic Board Repair Extension Program)。

うちにも iBook があるんだけど、そういや 1 年ほど前に修理に持っていったんだよね。なんか、ふたの開け閉めをすると、画面がちらついて。そのうち映らなくなった。修理の対応をしてくれた兄ちゃんは、「あぁ、これね」っていう感じの受け答えで、あっさりロジックボード交換とあいなった。

あれって、この交換プログラムに含まれんのかなー、と思っていたら、Apple から手紙が来た。いわく、「お前にやってやった修理はいまただでやってるから、リファンドしてやる」だって。おぉ、金返ってくるのか。当たり前の対応だけど、Apple がそんな当たり前のことをできるようになったんだ、と思って、ちょっとびっくり。

この修理って、Apple Store に持ち込んでやってもらったんだよね。だから、スムーズだったりするのかも。直営店は、やっぱり便利というか、安心感がある。

Feburary 18

Safari のさ、戻る、進むボタンって、長押しするとメニューが出てくるじゃない。コントロール + クリックでも出てくるんだけど。あのボタンを作ってみようと思ったんだよ。

そのために、まずボタンをクリックしたときの挙動を調べてみた。ボタンである NSButton をクリックすると、mouseDown: が呼ばれる。その次に、NSCell の trackMouse:inRect:ofView:untilMouseUp: が呼ばれる。その中からは、きちんと設定すれば、startTracking:inView:continueTracking:at:inView:stopTracking:at:inView:mouseIsUp: が呼ばれて、ドラッグの状態を知ることができる。

えーと、ということは、trackMouse:inRect:ofView:untilMouseUp: をオーバーライドして、NSApplication の nextEventMatchingMask:untilDate:inMode:deque: でも呼んでよればいいのか。ということで、NSButtonCell を継承したクラスで、次のような実装をしてみた。

(sample)
- (BOOL)trackMouse:(NSEvent*)theEvent 
        inRect:(NSRect)cellFrame 
        ofView:(NSView *)controlView 
        untilMouseUp:(BOOL)untilMouseUp
{
    NSEvent*	event;
    event = [NSApp nextEventMatchingMask:
                (NSLeftMouseUpMask | NSLeftMouseDraggedMask) 
            untilDate:[NSDate dateWithTimeIntervalSinceNow:1.0] 
            inMode:NSEventTrackingRunLoopMode 
            dequeue:NO];
    if (event) {
        return [super trackMouse:theEvent 
                inRect:cellFrame 
                ofView:controlView 
                untilMouseUp:untilMouseUp];
    }
    else {
        [NSMenu popUpContextMenu:[controlView menu] 
                withEvent:event 
                forView:controlView];
        return NO;
    }
}

まず、NSApplication の nextEventMatchingMask:untilDate:inMode:dequeue: を、NSLeftMouseUpMaskNSLeftMouseDraggedMask を指定して呼んで、ユーザのドラッグを 1 秒間待つ。その間にドラッグかマウスアップが発生したら、NSButtonCell のメソッドを呼ぶ。ドラッグしなかったら、NSMenu を使ってコンテキストメニューを表示する。

これで、とりあえずは動く。ちゃんと、長押しでメニューが表示される。でも、問題もある。

  • あるボタンでメニューを表示させた後、別のボタンを押してもクリックが反応しない。
  • マウスを動かさないで、メニューを表示させた後ボタンを離すと、メニューが表示されたままになる。(Safari では消える)

うーむ。どうしたもんだろう。もう少し対策をつめれば、ちゃんと動きそうな気もするけど。でも、今日はワインを飲んで酔っぱらっているので、続きはまた後日。

ソースコードダウンロード
MenuButtonTest.dmg

void GraphicWizardsLair(void); 経由、「火星でいったい何が起きたのか?」この間の、NASA の探査機が火星で再起動を繰り返したときの、原因と解決法。

まず、発生した問題を、無意味に隠さずにきちんと公表するのは正しいよね。隠したって、ぜんぜん意味ないし。この記事で、何が起きたかを理解するには十分な量の情報がある。

個人的な印象は、優先度逆転での問題って実際に起こるんだ、ってこと。そりゃ確かに、起こりうることは周知のことだけど、そこまで突き詰めなくても、たぶん大丈夫だよね、って感覚があった。そうか、ほんとうに起こるんだ。

ただ、VxWorks のプログラム書くなら、pipe() や select() 使わない方がいいんじゃない?ネイティブで用意されている、セマフォやメッセージキューを使えよ、という気はする。それが直接の原因ではないにせよ、UNIX 的な皮を使うよりは、ネイティブ API を呼ぶ方がいいって。この場合は、移植性を気にしなくていいし。火星探査機用プログラムを移植するか?

Feburary 17

ひさしぶりに、はじめてのブラウザのつくり方を更新!ジャカジャン!

今回は、WebPreferences を Cocoa バインディングで設定するだ。あの、WebView 用の初期設定パネルを、Cocoa バインディングを使って実装しよう、という話だぜ。ポイントは、NSObjectController のsetContent: を動的に使うところ。詳しくは、読んでみて。

ほんとは、これにフォントウェルを使いたかったんだけど、今回は断念。きちんと nib パレット用に書き出さないと、あまり恩恵が受けられないから。そのうち、きちんとやるぞ、これも。

Feburary 16

使っている PowerBook G4 のバッテリが、だめだめになってしまった。充電しても 10 分も持たない。これじゃ、ぜんぜんバッテリ駆動できねーよ。というわけで、新しいバッテリを買ってきてしまいました。そうしたら、駆動時間が 3:30 にのびた。すばらしい。

PowerBook G4 の、初代をほぼすぐに買ったんだよな。たしか、2001 年の 1 月か 2 月だったような。丸 3 年使っているのかぁ。バッテリもそろそろへたりますか。

Xcode の CVS サポートを、いろいろと弄んでみた。いやー、使いにくいね、これ。とりあえず、まとめてみるよ。

始めにいっておきますと、mkino は会社では Perforce と VSS (Visual Source Safe) を主に使っていて、CVS はほとんど使ったこと無いです。つまり、バージョン管理の概念は知ってますけど、CVS 自体はよく知らないです。というわけで、CVS 入門も兼ねながらまとめるよ。

まずは、Xcode の CVS サポートを手っ取り早く体験してみよう。そのために、ローカルで CVS リポジトリを作る。つまり、ローカルのマシンを、CVS サーバとして使うということね。

ローカルで使うには、適当な箇所に、CVS のリポジトリを作る。たとえば、/usr/local/newrepos に作ってみよう。それには、コマンドラインから以下のように打ち込む。

% setenv CVSROOT /usr/local/newrepos
% sudo cvs init

CVS の init コマンドっていうのが、新しいリポジトリを作るためのもの。これで、ローカルマシンに、CVS のモジュールを作ることができるようになる。

次に、CVS に入れる、Xcode のプロジェクトを作る。Xcode を起動して、適当なプロジェクトを作ってくれ。仮に、TestProject っていう名前にしよう。

そうしたら、このプロジェクトを CVS に入れる。それには、コマンドラインで TestProject のディレクトリに移動して、次のコマンドを入れるんだ。

% cd TestProject
% cvs import -m "Inital project" TestProject vendor release

import コマンドが、CVS に新しいモジュールを作るためのコマンド。-m の後に来るのは、コメント、モジュール名、ベンダータグ、リリースタグ。とりあえず、モジュール名が大事。このコマンドを実行すると、追加されたファイル名がずらずらと出てくると思う。

これで、CVS にファイルが入った。ただし、この状態では Xcode は自分が CVS に入れられたことを知らない。そこで、いったんファイルをすべて CVS から取り直す必要がある。まず、Xcode を終了する。そして、TestProject ディレクトリの名前を他の名前に変更してくれ。そして、CVS からファイルを取り直す。次のコマンドを実行してくれ。

% cvs co TestProject

cocheckout の意味。これで、TestProject のファイルを CVS から取得できる。新しい TestProject ディレクトリをのぞくと、CVS っていうディレクトリができていると思う。ここに、CVS の情報が入る。そして、このディレクトリによって、Xcode は CVS を利用していることを知ることができる。

で、Xcode を起動し直す。そうすると、SCM メニューが使えるようになる。ファイルを変更して diff を取ったり、変更をコミットしてみてくれ。

ここまでで分かるのは、Xcode からは、リポジトリの作成、新規モジュールの作成、ファイルのチェックアウトはできない。これらはコマンドラインから実行する必要がある。CVS から取得した Xcode のプロジェクトファイルを使うと、コミット、diff、アップデートなどができるようになる。

といったところで、次回へ続く。

Feburary 14

掲示板の方で要請(ってほどじゃないけど)があったので、試しにコメント機能をつけてみたよ。HaloScan を使っています。

前から、やらんといけないなー、と思っていたので、ちょうどいい機会なので。そろそろ、サイト全体をオーバーホールしないといけないなぁ。

Feburary 13

Matz にっきや、mput の日記から。あなたのあこがれのプログラマって誰だ?

そら、あんた、簡単な話で、ビル・アトキンスンだし、アンディ・ハーツフィールドだし、アビー・テバニアンでしょう。まぁ、Mac ユーザって単純。

Feburary 12

かりやん日記さんの、Cocoa バインディングの件の件。

その通りでして、もちろんモデルを setValue:forKey: で更新するのが正しいと思います。それができるのならば。問題は、ビューの値を更新しようとするオブジェクトが、ビューのことしか知らない場合です。バインディングの Controller Key と Model Key Path は、通常 Interface Builder で設定するので、そのオブジェクトは知らないです。

では、ビューから、現在持っているバインディングの設定を取り出すことができるか?唯一それらしいことができるメソッドは、NSObject の observationInfo でしょうか。でも、これ返ってくるのが void* 型で、どんなデータか分かんねー。

ということで、ユーザの挙動のトレースしか手が無いのです。

とはいうものの、挙動トレースをしようとしても、やっぱりうまく動かん。冷静になると、たしかに無駄な努力の気もするし。この問題の箇所は、Cocoa バインディングを使わない方向でいきます。ぷしゅ〜ぅ。

Feburary 11

NSTextField の value を、あるモデルのプロパティとバインディングしたとしよう。たとえば、Album っていうモデルクラスの title プロパティとバインディングしたとする。このとき、他のオブジェクトが title プロパティを変更すると、NSTextField の値が更新される。これはオッケー。また、ユーザがテキストフィールドの値を手で変更すると、今度はモデルの title プロパティが変わる。これもオッケー。でも、プログラム上で NSTextField に setStringValue: を使って値を変更すると、モデルの title プロパティは変更されない。これはよくない。

察するに、setStringValue: でモデルのプロパティも変更してしまうと、ループのような状況に陥ってしまうのではないか。だから、わざと更新しないようにしている。そうだとしたら、それはしょうがない。じゃあ、どうするか?プログラム上で、ユーザが手で編集したのと同じような処理を行ってやればよい。NSControl やら NSCell のメソッドを眺めていると、editWithFrame:inView:editor:delegate:event:endEdting: あたりが怪しいのではないかと。これをコードから呼んでやれば、ユーザが手で編集したのと同じことになるのでは?と、予測をたててみた。後で実験してみる。

でも、このへんは Cocoa バインディング側でケアしてほしいなぁ。

Feburary 10

Surfin' Safari で、Safari 1.2 の修正箇所が紹介されているぜ。ざっと抜き出すと、
  • Java アプレットのための LiveConnect のサポート
  • Personal Certificate のサポート
  • keygen の実装。これで VeriSign とかでキーペアを作れるんだそうな
  • タブキーなどによる、すべてのコントローラへのキーボードアクセス
  • ダウンロードの改良。ダウンロードの再開、ダウンロードマネージャでのコンテキストメニュー、最大接続数 4 つまでの制限の撤廃、など
  • でかい空白ができる問題の解決などを含む、印刷の改良
  • 国際ドメイン名サポート
  • ページのフォントサイズを調べて、ページ上のコントロールのサイズを自動的に Small や Mini にする
  • XMLHTTPRequestObject のサポート。これで、Orkut が使えるんだそうな
  • CSS2 のテーブルのサポートの改良
  • DHTML のパフォーマンスの改良。1.1 と比べると、すごく速くなったらしい
  • hover/active の改良
  • CSS2.1 にあるような、generated content に対するポジショニングとフローティングのサポート(?)
    追記:ねこめしにっきに解説があります
  • marquee のサポート
  • フォントの small-caps のサポート
  • 安定性が増した
  • パフォーマンスの改良。たとえば、ページを移動するときのスクロールバーの位置が改良されたとか。他にもいろいろ
  • キャッシュの改良。いままでは、タイムアウトが無視されていたんだそうな
  • HTTPS のスピードの改良。バグがあったんだそうな
  • CSS 読み込みの改良。CSS ファイルで画像が指定してあっても、実際に Web ページで使われるまで読み込まないそうだ。これで、CSS ファイルがクロスサイトで置いてあったときとかに、読み込み時間が短くなるときもあるって。

よく分かんないところもあるけど、こんな感じ。詳しくは Surfin' Safari のページでどうぞ。

Cocoa 1001 の更新。Cocoa バインディングでエンコーディングメニューを作る。こんな感じのエンコーディングメニューを、Cocoa バインディングで作ってみた。

フォントウェルに対する反応がいくつかあったよ!

まずは site-aro さん。パネルが出っぱなしになるのはいやなので、メニューみたい終わったらひっこむといいのかではないかと。うーむ、出っぱなしがよくないのは賛成ですけど、パネルをそのままメニューにするのはどうかと。下のボタン、隠れちゃうし。

ヘチマコンピュータさんは、最近使った項目と、よく使う項目のメニューを追加した HTFontWell を。これは使いやすいかも。NSSegmentedControl のほうが、たしかにかっこいいし。

両方とも、メニュー形式を採用しているんだよ。やっぱり、ワンアクションで選択できるポップアップメニューは、パネルよりも便利ですな。でも、項目が 40 とか 50 もずらずら続くのは勘弁。5 から 10 ぐらいのメニューから選択できるのが、いちばん楽なのかなぁ。

Feburary 9

たいへんひさしぶりに、Cocoa 1001 を更新。ツールバーを使って、タブを選択するっす。初期設定パネルのように、ツールバーとタブがくっついたインタフェースの作り方の話。

ちなみに、Mac OS X 10.3 からは、NSToolbar のデリゲートで toolbarSelectableItemIdentifiers: を実装することで、ツールバーのアイテムを選択表示することが可能。この手の初期設定パネルでは、これを使おう。

いま、あるアプリケーションをちょびちょび書いていて、そのとき気づいたものを書き留めいているのが、最近の更新なのでした。

Cocoa Bindings Examples and Hints。おぉっ、まだほとんどみかけることのない、Cocoa バインディングの例が。

NSPopUpButton の Bindings では、文字列しか表示させることができないのか?NSMenuItem 渡したら、その description を表示しやがった。これじゃ、セパレータを表示できないじゃないか。うーむ。

Feburary 6

きのうカラーウェルの話を書いたけど、実は、始めはフォントを設定するときのユーザインタフェースを考えていたんだ。

たとえば、Mac OS X の標準でついてくるテキストエディタは、フォントを設定するために、右のようなインタフェースを使っている。フォントの名前を表示するテキストフィールドと、フォントパネルを表示するための「設定」ボタンから構成されるんだ。「設定」ボタンを押すと、フォントパネルが表示されて、そこで選択されたフォントがテキストフィールドに反映される。

Safari のも、似たような感じだね。ただし、こちらはテキストフィールドのフォントに、選択されたフォントを使うようになっている。

個人的に、このインタフェースはあんまり好きになれない。ポイントは 2 つ。1 つは、ボタンとテキストフィールドという、2 つの部品を使っていること。1 つにまとまっていた方が、すっきりして好き。もう 1 つは、どれが設定中のフォントか分からないこと。一応、最後に「設定」ボタンを押した方のフォントを設定することになっているんだけど、インタフェースにその情報が表示されていないから、ぱっと見分からんよね。

これとは別に、ポップアップメニューを使うという手もある。でもこれは、フォントの数が 40 とか 50 になると、かなり使いづらい。それに、せっかくなら、システムが用意しているフォントパネルを使いたいよね。

そんなことを考えていたら、カラーウェルがよいヒントを与えてくれた!というわけで、フォントでも似たようなことを実現する、フォントウェルと呼ぶようなインタフェースを作ってみた。左の図がそれ。

フォントウェルは、フォントを選択、表示するためのインタフェースだ。使い方は、

  • フォントウェルをクリックすると、フォントパネルが表示される
  • フォントパネルで選択したフォントが、フォントウェルに反映される

フォントウェルには、アクティブ状態と、非アクティブ状態があるんだ。

  • フォントウェルをクリックすることで、アクティブと非アクティブを切り替えることができる
  • アクティブ状態のフォントウェルが、フォントパネルでの選択を反映する

さらに、排他制御も行う。

  • あるフォントウェルをアクティブ状態にすると、他のフォントウェルを非アクティブにする

といった仕様にして、実装してみた。とりあえず手っ取り早く行うために、NSButton のサブクラスにしてみた。だから、Cocoa バインディングにも対応できるぜ。使ってみた感じはけっこういいと思うんだけど、どんなもんでしょ。ソースコードをダウンロードしておくようにするんで、興味のある人はどうぞ。

ダウンロード

FontWell.tar.gz

Apple が .Mac メンバに配布していた、スーパージグゾーパズルにどっぷりとはまる。好きなんだよ、こういうの。500 ピースぐらいにしてやってみたら、すげー難しい。でも、ピースがはまったときの快感が病み付きになって、やめられなくなる。5 時間が飛んでいった。あぅぅ。

Feburary 5

カラーウェルの謎

Mac OS X には、カラーウェルっていうユーザインタフェースがある。色を選択したり、表示したりするものだね。Classic な Mac OS にはなかったんで、OPENSTEP 由来のものなのかな?Cocoa では、NSColorWell っていうクラスが、このユーザインタフェースを受け持っている。

カラーウェルってあんまり使ったことがなかったので、どういう動作をするか調べてみた。まず、当然のことながら、

  • 色を、NSColor として、持っている
  • その色を表示する

ということができる。これは、見れば分かるね。さらに、

  • (ボーダーを持った状態ならば、)クリックすると、カラーパネル(NSColorPanel)を表示する

ことができる。そして、カラーパネルで色を変更するために、

  • アクティブか非アクティブか、という状態を持っている
  • クリックすると、状態がトグルする
  • アクティブの状態になると、カラーパネルと色が同期する。つまり、カラーウェルがアクティブになると、その色がカラーパネルで選択される。カラーパネルの色を変更すると、カラーウェルの色も変わる

うーむ、なるほど。で、さらにアクティブ状態のことについて調べてみると、こんな特性もある。

  • カラーウェルをクリックしてアクティブ状態にすると、他のすべてのカラーウェルが非アクティブになる
  • シフトキーを押しながらクリックすると、複数のカラーウェルをアクティブにできる。その場合、色はすべてのカラーウェルで同一になる

アクティブ状態は、ラジオボタンみたいに、排他的にできるんだ。だけど、普通排他的な制御をするには、お互いのことをしらないといけないよね。たとえばラジオボタンだと、NSMatrix の中に入れられて管理されている。しかし、カラーウェルは、そういう明示的な設定がいらない。さらに、実験してみたら、異なるウィンドウ上にあるカラーウェルの間でも、排他的に制御されてる!

なんでー?どうやってんのー?と思って、調べてみた。デバッガ立ち上げていろいろ見てみると、どうも NSColorWell は、インスタンスが作られると、どこかで一元的に管理されているみたい。で、あるカラーウェルがアクティブになると、他のインスタンスに非アクティブにしろ、という通知が行くみたい。

なるほどー。そういうことですか。将来役に立つかもしれないから、いちおう覚えておくことにする。

Feburary 3

Safari 1.2 が公開されたよー。

今回のアップデートでは、WebCore と JavaScriptCore のソースコードも、速攻で公開された。毎回、こうしてくれよー。バージョンは v125 になったらしい。中身は、まだ見てない。

Omni Web の 5.0 beta も出たよー。

Omni Web も、Safari と同じく WebCore をベースにしている Web ブラウザ。ほうほう、どれどれ、とパッケージを開いて、WebCore と JavaScriptCore のバージョンを確認してみると、v85。あれー?古いじゃん。これって、WWDC 2003 のときのバージョンだね。つまり、Web Kit が公開されたときのもので、もう半年ぐらい前のかな。Omni のサイトで公開されているソースコードも変わっていないし。5.0 は、ユーザインタフェースの変更だけで、レンダリングエンジンは変更ないのか?

なんか、とにかく、えらいこと忙しくてですね。やらなくてはいけないことが、やってもやっても終わらなくてですね。HMDT の方が、ぜんぜん更新できなかったのです。

そのうちに、忘れた頃に、成果をお見せできる、かも。


[Home] [Download] [Archives] [BBS] [Cocoa Programming Tips 1001] [Core Foundation の秘密] [Safari Developer Center] [はじめてのブラウザのつくり方] [Sketch BP] [スクリーンセイバーを作ろう] [Objective-C 最適化] [Authorization API 完全理解] [Mac OS X Programming Books Review] [オブジェクト指向の言語比較論] [panther-dev]

mailto: mkino@xd5.so-net.ne.jp