2008-02-12
目次
りんご味Ruby 第18回 藤本 尚邦
前回から、Xcode ToolsのサンプルアプリケーションSketchに、RubyCocoaフレームワークをリンクして、Rubyプログラムで機能を追加していく様子を示しています。
今回は、角が丸みを持つ四角形(rounded corner rectangle)を表現するクラスをRubyで実装します。その前に、簡単に前回のおさらいをしておきましょう:
・Sketchのプロジェクトフォルダをコピー。Sketchは
/Developer/Examples/AppKit/Sketchにあります
・コピーしたXcodeプロジェクトを開いてRubyCocoa.frameworkを追加
・SKTMain.mのmain関数にRubyCocoaを初期化するコードを追加。Sketchが起
動したら、RubyCocoaのAPI関数である RBApplicationInit が呼び出される
ようにしました。RBApplicationInit の引数として渡した “main.rb” が最
初に実行されるRubyプログラムとなります。
・main.rbを追加。新規ファイル追加で「Ruby application init」を選択し
ます。main.rbに、標準出力にRubyやRubyCocoaのバージョンを出力する
コードを追加しました。
これで、Rubyプログラムで機能を追加するための準備ができました。
■ Sketchのグラフィックオブジェクト
画像や図形などグラフィカルなドキュメントを編集するアプリケーションは、ペイント系(MacPaintを源流とする)とドロー系(MacDrawを源流とする)に分類されることがありますね。ペイント系では、キャンバス(描画空間)上の各点の色を直接変更します。ドロー系では、キャンバス上に各種図形などのグラフィックオブジェクトを配置していきます。
私は、”Sketch”という名前からペイント系アプリケーションを連想したのですが、実際のSketchは、キャンバス上にグラフィックオブジェクトを順に置いていくタイプの、典型的なドロー系のアプリケーションです。
Sketchのソースをざっと見ると、楕円形・画像・線分・四角形・テキストと5種類のグラフィックオブジェクトを扱えるらしきことがわかります。それぞれ、SKTCircle, SKTImage, SKTLine, SKTRectangle, SKTText という名前が付けられています。みな、SKTGraphicクラスの派生クラスとしてObjective-Cにより定義されています。
NSObject
+- SKTGraphic
+- SKTCircle
+- SKTImage
+- SKTLine
+- SKTRectangle
+- SKTText
■ SKTRoundedRectangleの実装
では6番目のグラフィックオブジェクトとして、角丸四角形を表現するクラスSKTRoundedRectangle をRubyで実装しましょう。
「新規ファイル」コマンドで SKTRoundedRectangle.rb を追加します。テンプレートには「Ruby NSObject subclass」を選んでください。SKTRoundedRectangle は SKTGraphic の派生クラスなので、親クラスをNSObjectからSKTGraphicに書き換えます。
-------------------------- SKTRoundedRectangle.rb #0 --
require 'osx/cocoa'
class SKTRoundedRectangle < OSX::SKTGraphic
include OSX
end
--------------------------
それでは角丸四角形の特徴を定義していきましょう。
手がかりとして SKTRectangle.m を見てみます。bezierPathForDrawing というメソッドが定義されているのみですね。bezierPathForDrawingはグラフィックオブジェクトの形状を返すメソッドのようです。これだけ定義しておけば、その他のことは親クラスの SKTGraphic がやってくれるのでしょう。
ということで、SKTRoundedRectangle に角丸四角形のパスを返すbezierPathForDrawing を実装します。SKTRectangleのbezierPathForDrawingをRubyで書き換えて、パスの形状を変えるだけでよいでしょう。以下のようになります。
-------------------------- SKTRoundedRectangle#bezierPathForDrawing --
def bezierPathForDrawing
path = NSBezierPath.bezierPathWithRoundedRect_xRadius_yRadius(
self.bounds, 24.0, 24.0)
path.setLineWidth(self.strokeWidth)
path
end
-------------------------------------------
これだけで十分そうですが、念のため SKTCircle.m を見てみます。するとSKTRectangle にはなかった isContentsUnderPoint というメソッドが定義されていました。名前と引数から、指定された点がグラフィックオブジェクトの中にあるかどうかを示す真偽値を返すメソッドということになるでしょう。
SKTGraphic.mでの定義を見ると、NSPointInRectを使って、指定された点がboundsのなかにあるかどうか調べています。 SKTRoundedRectangle の場合、角の削れた部分で偽を返す必要があるので実装することにします。SKTRectangleのisContentsUnderPointと同じく、NSBezierPath#containsPoint を使います。
ということで SKTRoundedRectangle.rb ができあがりました:
-------------------------- SKTRoundedRectangle.rb --
require 'osx/cocoa'
class SKTRoundedRectangle < OSX::SKTGraphic
include OSX
def bezierPathForDrawing
path = NSBezierPath.bezierPathWithRoundedRect_xRadius_yRadius(
self.bounds, 24.0, 24.0)
path.setLineWidth(self.strokeWidth)
path
end
def isContentsUnderPoint(point)
self.bezierPathForDrawing.containsPoint(point)
end
end
--------------------------
しかし、SKTRoundedRectangle を定義しただけでは、まだSketchアプリケーションで角丸四角形のオブジェクトを作ることはできません。ということで次回に続きます。
(おまけ) ペイント系、ドロー系のことを書いていたら...昔のMac 用の開発ツールThink C や Think Pascal には、Think Class Ligraryというアプリケーションフレームワークが付属していたのですが、そのサンプルのひとつとして、Art Class という素敵なペイント系アプリケーションのソースがまるまる入っていたことを思い出しました。
「Wonderful Server Life」 第64回 田畑 英和
〜Open Directory編〜
今回はLeopard ServerのディレクトリサービスであるOpen Directoryについて解説します。これまで説明してきましたように、Leopard Serverには標準/ワークグループ/詳細の3つのサーバ構成があります。LDAPベースのディレクトリサービスであるということは共通していますが、サーバ構成によって細かな違いがありますので、それぞれの違いを詳しくみていきたいと思います。
◇詳細構成
まず詳細構成から説明します。詳細構成の場合はTiger Serverとよく似ており、Open Directoryを使用するには手動で設定を行う必要があります。つまりデフォルトの状態ではローカルユーザの管理しかできず、ネットワークユーザを管理するにはOpen Directoryのマスターを手動で構築する必要があります。
Tiger ServerのころはOSの初期セットアップ中にOpen Directoryのマスターを構築することができましたが、Leopard Serverではセットアップ後でないとマスターが構築できなくなりました。ただし、Open Directoryのマスターをきちんと構築するにはDNS関連の設定が正しく行われている事が前提になるため、セットアップ後に確実に動作確認を行ってから構築したほうが安全です。
このように、詳細構成では必要に応じて管理者がOpen Directoryの設定を行うことになります。
◇標準構成
次は標準構成です。実はOpen Directoryを使用するのであればこの構成を選択することにより、自動的にOpen Directoryのマスターが構築できます。ですので手っ取り早くOpen Directoryのマスターを構築したい場合には、まずは標準構成で始めてみるのもよいものです。標準構成であればあとから詳細構成に変更(「サーバ管理」で変更可能)できますので、最初はシンプルに始めて、必要に応じて詳細構成に移行することも可能です。
ところで標準構成の場合、セットアップ中に登録した管理者アカウントは、どのように管理されているのでしょうか。詳細構成の場合は、Tiger Serverと同様にローカルアカウントとして登録されます。標準構成の場合は、第61回の連載でも解説したように、セットアップ中に登録した管理者アカウントはネットワークアカウントとして登録され、同時に「localadmin」という名前のローカルアカウントも登録されます。
選択したサーバ構成によって、セットアップ中に登録した管理者アカウントの扱いが変わってきますので注意が必要です。
◇ワークグループ構成
ワークグループ構成でも標準構成と同様に、Open Directoryのマスターが自動的に構築されます。管理者アカウントがネットワークアカウントとして登録されることも同様です。
標準構成との違いは、ワークグループは他のディレクトリサーバに接続することにあります。そして接続先のディレクトリサーバ上のユーザアカウントをワークグループ上に読み込むことができます。
読み込むといっても、ワークグループ上に新たなアカウントとして再登録するのではなく、アカウントの実体はあくまでも接続先のディレクトリサーバ上で管理し、ワークグループ上では読み込んだアカウントに対して追加の属性が管理できるようになります。このようなユーザのことをAugmented Userと呼びます。
この仕組みを利用することで、ユーザアカウントの実体は直接編集せずに、追加の属性を管理できるようになります。
なお、セットアップ時に標準構成を選択していても、あとから他のディレクトリサーバに接続すれば、サーバ構成はワークグループになります。
◇アカウントの管理ツール
Open Directoryの主な役割にアカウント管理がありますが、ここでアカウント管理に使用するツールをおさらいしておきましょう。アカウントの種類に応じて次のようなツールが使用できます。
「システム環境設定」
ローカルアカウント
「ワークグループマネージャ」
ローカルアカウント、ネットワークアカウント
「ターミナル」を使ってコマンドライン上でアカウント管理を行う事も可能です。Tigerまでは「NetInfoマネージャ」でローカルアカウントの管理も可能でしたが、LeopardではNetInfoは廃止されました。
これらのツールに加え、Leopard Serverには新しい管理ツール「サーバ環境設定」が加わり、このツールからもアカウント管理が可能です。「サーバ環境設定」ではユーザおよびグループの管理が可能ですが、管理対象となるアカウントはネットワークアカウントです。また、「システム環境設定」と同じくら簡単にアカウントの管理ができます。
それでは次回は「サーバ環境設定」を使ったアカウント管理について解説します。
次回へつづく
小池邦人のCarbon視点でCocoa探求(2008/02/08)
〜 モデル・オブジェクトを考察する 〜
今回は、「しんぶんし 3」で必要とされるだろうデータ構造(モデル・オブジェクト)について考えてみます。基本的には、複数の画像ファイルを管理するのに必要とされるデータ構造を用意します。
その前に、前回はウィンドウに表示させたいJPEG画像ファイルを用意し、プロジェクトの「Resources」グループに登録しておけば、これらの画像アイコンがInterface Builderのライブラリの「Media」タブに表示されると解説しました。しかし、Carbonプロジェクトの場合、表示用のPICT画像やアイコンがリソースファイルとして保存されているケースが多々あります。旧バージョンのInterface Builderでは、リソースファイルに登録した画像も、InterfaceBuilder上でその内容を確認しながら編集作業(ボタンに貼付けるとか)が出来ました。
ところが、最新バージョンでは、それが表示されなくなってしまいました(ボタン上に画像が何も出てこない)。加えて、テキストフィールドへの文字入力がインスペクタ上でしかできないようになっていたりと、引き続きCarbonプロジェクトをメンテしなければいけない開発者にとっては不便きわまりない状態です。「ユーザインターフェースの処理はCocoaでやりなさい!」という話は分かるのですが、前に可能だったことを出来なくするのだけは止めていただきたいと思います。実作業に支障が出るのは大変に困ります。
さて、アプリケーションのメイン・データ構造を決定する場合には、そのアプリケーションが「何をするのか?」を考えれば良いことになります。「しんぶんし 3」の場合には、画像ファイルをオープンし、そのシンメトリ(対称)画像を作成して保存するという一連の作業を行います。一枚一枚画像ファイルをオープンしていては面倒ですので、画像ファイルを含むフォルダを選び、中の画像をすべて得るという処理も必要です。カット&ペーストやドラッグ&ドロップによる画像やフォルダの登録も必要でしょう。
例えば、複数の画像ファイルを管理するなら、とりあえずファイルの「パス名」リストとその「個数」を保存しておけばOKです。まあ、実際のシンメトリ処理には、その機能に付随する幾つかのアトリビュート(パラメータ)も必要となりますので、パス名だけという訳には行きませんが、今回のアプリケーションでは、それほど多くのパラメータは必要ないでしょう。Carbonで作成していた前バージョンは、画像ファイルの管理用としてパス名の代わりにFSSpec構造体を利用していました(これもパス名みたいなものですが...)。
すべての管理用データは以下のようなImageFile構造体にまとめられています。
typedef struct {
FSSpec sys_fsc; // 画像ファルの保存場所を示すFSSpec構造体
Rect sys_srt; // 画像選択用の矩形枠情報
OSType sys_type; // 画像ファイルのタイプ
short sys_flag; // 状態の管理用フラグ
short sys_kind; // シンメトリ(対称)方向
short sys_para; // オプション用パラメータ
} ImageFile,*ImageFilePtr;
この構造体を予想される最大個数(前回は2000個に定義していました)確保し、画像ファイルの管理に利用します。ソースコードで書けば...
#define MAX_FILE 2000 // 最大が像ファイル管理個数
ImageFilePtr sys_image; // 構造体配列の先頭アドレス
sys_image=(ImageFilePtr)NewPtrClear( MAX_FILE*sizeof(ImageFile) );
if( sys_image==NULL )
// 確保できなかった場合のエラー処理
といった感じです。その後の処理で「n個目」の構造体を参照する場合には、
sys_imageを起点として以下のようにアクセスします。
ImageFilePtr nowImagePtr;
nowImagePtr=sys_image+n;
構造体データをすべてコピーしたければ、最近のコンパイラでは以下の書式でOKです。
この方法、構造体用メモリを一度に全部確保してしまいますので、必要となるメモリ容量の予想がしやすく(エラー処理も簡単)全体的な管理が楽です。また、逐次確保の手続きが不要な分だけデータアクセス処理が高速となります。欠点は、余分な(未使用)メモリ領域が確保されてしまっている点と、どうあがいても2000個以上登録できないと言うことです(笑)。しかし、今となっては2000を20000に変更したところで、消費されるメモリは2MByte程度ですので「どおってことない」という感じはします。
これをObjective-Cの「オブジェクト」として実装してみると、以下のような感じになります。上記の構造体のメンバーは、インスタンス変数として定義されます。今後の展開からして、CGRectはNSRectの方が良いかもしれません(内部構造的には同じ)。
@interface ImageFile : NSObject
{
NSString *_name;
NSString *_type;
CGRect _srt;
unsigned int _flag;
int _kind;
int _para;
}
@end
そして、モデルのコントロール・オブジェクトの方にNSMutableArrayのインスタンス変数を定義しておいて、その配列要素に、[[ImageFile alloc] init];で確保したImageFileオブジェクトを登録して管理します。
@interface ImageList : NSObject
{
NSMutableArray *_list;
}
@end
こちらの方法の利点は、登録個数に制限がない点です(Mac OS Xが管理できるメモリ容量最大までOK)。それに特定オブジェクトを削除したり順番を入れ替えたりする仕事は、NSMutableArrayのメソッドが引き受けてくれますので、リスト管理が大変楽です。先に説明した構造体一括管理の場合には、そうした処理が必要であれば自分で処理ルーチンを実装する必要があります(そんなに難しくはないですが...)。旧「しんぶんし」でも、そうした処理(削除のみで順番変更はなし)を独自で実装していました。
さて、旧バージョンのデータ構造では、ドラッグ&ドロップで登録した画像ファイルはOKなのですが、カット&ペーストで登録したい画像(ファイルではなく画像データ)の情報を保存できません。だとすると、画像データ自体を保存しておくインスタンス変数も用意しておいた方が良いかもしれません。旧バージョンでは、画像ファイル一覧(台帳)をファイルへ保存して再利用するという機能はありませんでした。しかし、今回はCocoaの練習の意味もあるので「台帳」のファイルへの保存も考えることにします。
であれば、パス名の管理だけでは、登録後にその画像が別の場所に移されてしまった時に台帳に登録したファイルが見つからない場合があります。Carbonアプリでは、構造体内にファイルの「AliasHandle」を保存しておくことで、Aliasマネージャがファイルを探し出してくれました。Cocoaではどうしたものでしょうか? また、台帳ファイルを保存するという機能を追加するとなれば、Cocoaのアプリケーション形式を「Cocoa Document-based Application」へと切り替えた方が良さそうです。色々と課題が山積しています。
次回は、「しんぶんし 3」プロジェクトを「Cocoa Document-basedApplication」に切り替えてみます。こちらのアプリケーションタイプで注意すべき点を調べながら、モデル・オブジェクトの実装を試みたいと思います。
つづく
ターミナルの向こうから 第19回 海上 忍
〜 スプレッドシートとの共存を考える (1)〜
今回は、スプレッドシート、特に「Excel」という存在感の大きいアプリケーション、およびそのファイルフォーマットについて考えてみます。
・Excelという巨大な存在
Microsoft Excelというアプリケーションは、PCの世界のみならず、実社会にも大きな影響力を持っています。Windows 95ブーム以降、"PCを使える"ことすなわちExcelを一通り操作できること、といった風潮がありましたが、それは今なお健在です。Excelの使い方を授業に取り入れている学校、新入社員教育にExcelを使う会社は、かなり多いはずです。
しかしExcelが普及すること、誰もが使い方を覚えることは、問題にならないと思います。むしろ問題は、Excelがあまりに機能豊富で文書処理の広範囲に応用可能なため、なんでもかんでもExcelで済ませてしまおうという層が出現することです。
実例を挙げてみましょう。顧客の住所録をExcelでつくる、これはよく耳にする話ですね。巨大なワークシートを顧客管理DB代わりに使う、これもなんとなく想像できると思います。ここまでは、想定の範囲内です。では、ワープロ文書のようにきちんとレイアウトされた送達状の作成に使われているとしたら……プレゼンで使うグラフのみならず本文までが、しかもセルではなくテキストボックスに入力されていたとしたら……そして、そのExcelブックを「相手の事情を考えずに」送りつけてきたとしたら……Excel依存が進みすぎることの弊害はご理解いただけたでしょうか?
・過度なExcel依存にどう対処するか
MOSA伝の主旨からは外れてしまうかもしれませんが、この話題をもう少し続けましょう。今はメールやWebで他プラットフォームとも密接に連係している時代、Macでも無関係ではないからです。
対策の1つには、フォーマットの誘導を図ることが挙げられます。最新の
Office Open XML(.xlsx)形式は、すべての項目を忠実に開こうとすれば最新のExcel 2008が必要になりますから、Excel 97-2000(.xls)で保存してもらいます。そうすれば、OpenOffice.orgなどのフリーなソフトで開けますから、少なくとも開けなくて困ることはなくなります。ユーザを無理に慣れた操作体系から離れさせる必要もありません。
もう1つは、Excelブックを自動変換する処理系をつくりあげること。メールにExcelブックが添付されていた場合、自動的にCSVなどの汎用的なフォーマットに変換してしまう、というものです。こちらは費用も時間もかかりますから、おいそれとは着手できないでしょうが、1つの方向であろうとは思います。
Office Open XMLの普及を待つ、という消極的な方法もアリだと思います。このフォーマットはオープンですから、いずれはExcelブックのコンバートに使えそうな実装系が登場することでしょう。実際、OpenXML4J(http://www.openxml4j.org/)などのオープンな開発プロジェクトもスタートしています。
・Excelブックの処理系
プログラミングで解決を図るという方向性を、もう少し角度を変えて考えてみましょう。Excelはプロプライエタリなアプリケーションですが、データの取得/追加や保存などの作業を行えるオープンな処理系がいくつか存在するからです。
1つは、Rubyの拡張ライブラリ「win32ole」。Windowsで用いられるComponent Object Model(COM)にRubyからアクセス、Excelブックのデータハンドリングを可能にするというものです。バージョン1.8以降のRubyに標準装備されていますから、ある程度ポピュラーな方法といえますが、Win32環境専用ですので、Mac OS Xでは利用できません。
もう1つは、Perlの「Spreadsheet::WriteExcel」および「Spreadsheet::ParseExcel」モジュール。こちらはクロスプラットフォームですから、Mac OS Xでも利用できます。CPAN(http://www.cpan.org/)からいくつかモジュールをダウンロードする必要がありますが、作業自体はとてもかんたんです。
・Spreadsheet::WriteExcelを入手する
Perlモジュールは、cpanコマンドでダウンロードできます。紙幅が残り少ないので、細かい環境設定は抜きで参りましょう。まずはTerminalから以下のコマンドを実行してください(はじめて実行したときは色々と質問されますが、基本的にデフォルト値でOK)。
- - - - -
$ sudo -H cpan
cpan> force install Spreadsheet::WriteExcel
cpan> exit
- - - - -
これで、以下のリストが動作するようになります。適当なファイル名で保存したあと、「perl filename」として実行してください。数値と数式が入力されたExcelブック「sample.xls」が、カレントディレクトリに作成されたはずです。次週に続きます!
- - - - -
#!/usr/bin/perl -w
use strict;
use Spreadsheet::WriteExcel;
my $mybook = Spreadsheet::WriteExcel->new('sample.xls');
my $mysheet = $mybook->add_worksheet();
$mysheet->write(1, 0, 123453);
$mysheet->write(2, 0, 4.34567);
$mysheet->write(4, 0, '=A2 + A3');
- - - - -
ニュース解説 MOSAic
★★★ 開発関連のニュースはwebに掲載中 ★★★
http://www.mosa.gr.jp/?page_id=1017
・1月のニュース
http://www.mosa.gr.jp/?p=1515
◇MOSAからのお知らせと編集後記は割愛します◇