2011年3月31日木曜日

Excel VBAを書く準備

本日は残念ながら、新学期に向けた仕事を自宅でした。Excelのワークシート作り。
毎週水曜日に「学年打ち合わせ」をして次週の時間割や学習内容を決めている。

話し合うたたき台の「打ち合わせ資料」はExcelで作った表をプリントアウトして使っていたが、今年のように5学級もあるとプリントアウトするのがなんだかもったいない。できればひとつのドキュメントを共有して、パソコンだけで打ち合わせをできるようにしたい。

その土台作りをしてみた。とりあえず1週間分の時間割と予定などを記入するシート、それをもとに各学級別の時間割を作るVBA、という感じで考えている。本日はシートを作った。

あとはシートから必要な部分だけをコピーして、学級別にファイルを作ってシートを追加するようにVBAを書く、と。

cocoaプログラミングしたいなあ、と思いつつ1年に1回くらいしか書かないVBAを再勉強した。ただ、私が作るようなCocoaプログラムは誰も使いたいと思わないけれど、この手のExcelVBAは少なくても4人には喜んでもらえる。何よりも仕事で自分が楽をできる。楽するためならどんな苦労も厭わない、がハッカー気質でしたっけ?

2011年3月30日水曜日

PDFkit 検索(6)

やっとNSTableViewを使って検索結果を表示することができた。ついでにTableViewの上に、操作用のViewをつけてみた。


しかし・・・サムネイルビューと切り替えるのにremoveFromSuperViewしようとするとうまくいかない。subViewが2つになった関係か。

むー、カスタムビューの上にNSTableViewと操作用パネルを配置してもう1回やり直すか。明日以降だなあ。

PDFkitをいじりはじめて早2週間。結局ドキュメントベースアプリケーションを初めて作っていることになるので、いろいろ調べなければならないことが多い。

NSTableViewにしても、NSArrayControllerを使ってcocoaバインドを利用するとdelgateメソッドがいらないみたいだ、とか、調べていくうちにわかってくるわけだが、実験しないといけないことが多いのでまだ試していない。

おもしろいなあ、プログラミングは。

2011年3月29日火曜日

PDFkit NSTableViewをプログラマブルにリサイズ わかった!!

Skimのソースを追っているうちにわかった。

addSubViewする時にTableViewを直接渡していたのが敗因。

[placeHolderView addSubview:[tableView enclosingScrollView]];

これが正解だった。期待した通りの動作をしたので思わずiMacの前でガッツポーズをしてしまった。ちなみにガッツポースという言葉、ガッツ石松がチャンピオンになって勝利の雄叫びをしたポーズにちなんで名づけられたというのは喜びのあまりにふりまく薀蓄。

PDFkit NSTableViewをプログラマブルにリサイズ

プログラマブルにリサイズができないよ、という話で情けない。

初めからSplitViewにはりつけた状態だと、期待通りの動作をする。


しかしAddSubViewすると、こうならない。どーしてだろう。さらに勉強が必要ということで本日は終了。がっくり。

2011年3月28日月曜日

PDFkit 検索(5) NSTableView

というわけで平日のほうが時間が限られている分、集中できるかも。因果な性格だなー。

NSTableViewをサイドパネルに表示できるようにした。

データソース関係はこんな感じ。
-(NSUInteger)numberOfRowsInTableView:(NSTableView*)aTableView{
    
    return ([searchResults count]);
}
-(id)tableView:(NSTableView*)aTableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{
    
    if([[tableColumn identifier] isEqualToString:@"page"])
        return ([[[[searchResults objectAtIndex:row]pages] objectAtIndex:0] label]);
    else if ([[tableColumn identifier] isEqualToString:@"selection"]){
        NSString *label=[[[pdfView document] outlineItemForSelection:[searchResults objectAtIndex:row]] label];
        return label;
    }
    else 
        return NULL;
}

デリゲートメソッドはこうなった。

- (void) tableViewSelectionDidChange: (NSNotification *) notification{
    NSInteger rowIndex;
    
    // What was selected.  Skip out if the row has not changed.
    rowIndex = [(NSTableView *)[notification object] selectedRow];// 1
    if (rowIndex >= 0)
    {
        [pdfView setCurrentSelection: // 2
        [searchResults objectAtIndex: rowIndex] animate:YES];
        [pdfView scrollSelectionToVisible: self];// 3
    }

}

ほとんどデベロッパドキュメントの「Introduction to PDF Kit Programming Guide」にあった通りというかコピペというか。

これで無事にNSTableViewに検索結果を表示できるわけだが・・・


なぜスクロールバーが出てこないんだろう(^^;)ヘッダ行も表示されていない。表示はされていないけれど、↑キーとかを押すとちゃんと動作するので、

[[pdfView document] findString:[sender stringValue] withOptions:NSCaseInsensitiveSearch];

とやっているのが悪いのかも。デベロッパドキュメントの通り、beginFindString:withOptions:を使ったほうがいいのかな。これは明日以降だな。

2011年3月27日日曜日

JetBrains CIDR

サイダーと読め、と公式サイトに書いてありますな。



JetBrains CIDR is Juicing Up!

RubyMineを出している会社がつくる、ObjC用IDEだそうです。もうすぐβ版ができあがる、と。

さっそくMLに登録して吉報を待つことにする。

PDFkit 検索(4)

プレビュー.appで検索を始めると出てくるこのパネル・・・、


カスタムToolbarかと思っていたら、カスタムViewなのかしらん。
Selectionを移動していくのにこういうUIは必要なわけで、あちらのアプリこちらのアプリと動作を調べたりしているうちに本日は終了。相変わらずTableViewまで行き着かなかった。

というか、TableViewを使うのにViewControllerを作るのをやめにして、メインのnibにTableViewを放り込むことにした、と。ViewControllerを使うとオブジェクト間のデータの受け渡しをどうするのかわからないかったので(^^;)、とりあえず安易な方法をとった。うーん、この辺はコードを書いて覚えていくしかないだろうな。

WindowControllerの支配下に全部のViewを置けば、subViewの切替や操作も楽なのは確か。

素人プログラミングはなかなか進まない。

2011年3月26日土曜日

久しぶりに読書

ゆっくり朝寝して、犬の散歩をしたあとiMacでニュースチェックしたあとにXcode4のアップデートをしたので、なんとなく手持ち無沙汰になったので久しぶりに読書をした。

巡査の休日
巡査の休日
posted with amazlet at 11.03.26
佐々木 譲
角川春樹事務所
売り上げランキング: 150689

フィクションは図書館で借りることに決めたのはいいけど、人気のある作品は2年たたないと読めないのね。

このシリーズはちゃんと頭から続けて読んだほうがいいだろうなあ、と思いつつゆっくり読み進めている。

redcar0.11

Xcodeの中にいるだけで自由時間のほとんどが過ぎてしまうため、redcarとかあまり使っていない。けれど「2バイト文字のシンタックスハイライト直したよ」とあったのでredcarのアップグレードをした。


日本語入力したとたんに画面がモノクロームなるbugが見事にfixされているようだ。ついでに起動もかなり速くなっている。体感3倍(^^;)。

PDFkit 検索(3)


本日はあまりXcodeに触っていない。Xcode4.01にアップグレードはしてけれど。

書き加えたコードは以下の3行。

    NSRect rect=[placeHolderView bounds];
    [pdfThumbView setFrame:rect];
    [placeHolderView addSubview:pdfThumbView];

InterfaceBuilderでちょちょいと作業して、これでまたまたサムネイル表示ができるようになった。


placeHolderViewはいわゆるコンテンツビューへのOutlet。このViewにsubViewをaddしたりremoveしたりすることでサイドパネルを切り替える予定。

今日はTableViewをいじろうと思っていたがなかなか予定通りにはいかない。明日も仕事やら家族の用事やらでどうなるかなー。

2011年3月25日金曜日

年度終了

本日で2010年度が終了。

例年なら華々しく大送別会を開くところだが、今年は被災者のみなさんが苦しい思いをしていることを考えて、飲めや歌えやの宴席は開かないことになった。

子どもたちが帰ったあとの学校で、会食会を開いて終了。

転勤は教員の仕事の一部である。あまり感傷にひたっている暇もない。

何かが終わるということは、何かが始まることでもある。来週からは新年度準備。忙しくなるなあ。

さすがに年度に終わりを迎えて疲れがどっと出た感じ。プログラミングがあまり進まないのもそのせいですな。

PDFkit ViewController

SplitViewに検索結果を表示するTableViewを表示したい。そこで2つ、NSViewControllerクラスを作る。

ひとつにはTableView、もうひとつはOutlineViewを配置してみた。

実はもうひとつ、PDFThumbnaillViewをもつControllerを作ってみたが、これはpdfViewというOutletをメインのPDFViewにつなぐだけのものなので、わざわざControllerを作るまでもない、と判断してメインのnibファイルにViewのインスタンスを置くことにする。

ADCのサンプルなどを調べながらの作業なので、本日はこんなところで終了。手探りだなあ。

2011年3月24日木曜日

MacRuby0.10

0.10がリリースされた。

Xcode4で使えるテンプレート、も重要なアップデートみたいなのでさっそく試す。


ちゃんと使えますな。
⌘+Nで出てくる新規ファイル用のダイアログでも.rbが選択できる。


かといって、MacRubyであれこれ試すだけの元気はさすがにない。今はとにかくObjCでCocoaに集中。

PDFkit 検索(2)

検索そのものはPDFDocumentクラスのfindStringで行う。で、見つかった検索結果はPDFSelectionの配列で戻ってくる。

これをどうやってViewで表示するか・・・当然Viewにそういうメソッドがあるだろう、ということでデベロッパドキュメントを探す。PDFViewのselection関連のメソッドは

– currentSelection
– setCurrentSelection:
– selectAll:
– clearSelection
– copy:
– scrollSelectionToVisible:
– setCurrentSelection:animate:
– setHighlightedSelections:
– highlightedSelections

・・・そのものずばり、– setHighlightedSelections:が求めるメソッドだった。引数はPDFSelectionの配列だから、findStringの戻り値をそのまま渡せばいい、という簡単さ。

    NSArray* seledted=[[pdfView document] findString:[sender stringValue] withOptions:NSCaseInsensitiveSearch];

    [pdfView setHighlightedSelections:seledted];
これだけでPDFドキュメント内の検索ヒット文字列が全て選択状態になる。便利じゃのお。しかしここままだと、最初の検索ヒット文字列にまでViewが勝手に動いてくれるわけではない。そこで、最初の検索ヒット文字列をcurrentSelectionに指定して、そこまでスクロールするコードを加える。

    [pdfView setCurrentSelection:[seledted objectAtIndex:0] ];
    [pdfView scrollSelectionToVisible:self];

というわけで「検索→すべての検索結果を選択状態→最初の検索ヒット文字列を表示」が実現できた。

さらにsetHighlightedSelections:のドキュメントには「通常の選択文字列とは違う背景色で表示することを勧める」とあるので、選択文字列の背景色を変えてみる。

これはPDFSelectionに「setColor」というメソッドがあったことを覚えていたのでそれを使う。
しかし[[seledted objectAtIndex:0] setColor:[NSColor yellowColor]としてみたら、最初の選択文字列だけ背景色が黄色くなってしまった。全部のPDFSelectionオブジェクトでsetColorする必要があるのか。

ま、

for (PDFSelection* selection in seledted) {
        [selection setColor:[NSColor yellowColor]];
    }
と書き加えるだけだから簡単なんだけど。

これで次のように表示できるようになった。


ふむふむ、次はサイドビューを表示できるようにして、そこで検索がヒットしたページを並べる、という処理かなあ。プレビュー.appに準ずるくらいの機能をつけられたいいな、と思っている。できるかな。

2011年3月23日水曜日

Firefox4

firefox4はbetaをしばらく前から試していたが、アドオンが使えなくなることが多いので常用はしていなかった。

本日、職場のPCも家のiMacもFirefox4にアップグレードした。最高6倍速の表示、ということだけど、それほど速くなったとは思えない。

それでもメインのブラウザをChromeに移行しないでいるのは、Chromeのマウスジェスチャが今イチ信頼感に欠けることが一番大きな原因か。

なんせマウス派なので、ブラウザを触っているときにキーボード入力するのはblogを書くときと検索語を入力するときだけ、ってくらいマウスで操作している。マウスでちゃかちゃか履歴をたどったり検索したりできないのはつらい。そんなわけで私はFirefox派。

Tabの場所が変わったけど、なんか意義があるのかな。

PDFkit 検索

Toolbarに検索用のテキストボックスを配置できたので、今度は実際の検索について調べる。

文書内の検索は主にPDFDocumentクラスの仕事。メソッドはこんな感じ。

– findString:withOptions:
– beginFindString:withOptions:
– beginFindStrings:withOptions:
– findString:fromSelection:withOptions:
– isFinding
– cancelFindString

findString以外は「検索ボックスで逐次マッチした部分を表示する」タイプの検索用らしい。まずはTableViewにHitしたページを表示するような検索から始めたいので、findStringの挙動から調べることにする。

Toolbarに配置したSearchFieldで検索語が入力されると、beginSearch:が呼ばれる。ここでいちおう注釈をたれておけば、InterfaceBuilderで「SendsWholeSearchString」(リターンキーが入力されてから初めてactionが呼ばれる、という設定)にチェックを入れておいても今のところちゃんと働かないようだ。Xcode4のbugかしらん。ソース上でawakeFromNibあたりで明示的に

[[searchFieldOutlet cell] setSendsWholeSearchString:YES];

としておくのが吉・・・って今これを書いていて気づいたけど、InterfaceBuilder上でちゃんとsearchFieldのcellを選択してたかな。cellを選択してないとだめな気がする。(^^;)

actionは今のところこれしか書いていない。
-(void)beginSearch:(id)sender{
    NSArray* seledted=[[pdfView document] findString:[sender stringValue] withOptions:NSCaseInsensitiveSearch];
}
実はこの後ろに、渡されたNSArrayの中がどうなっているかNSLogで調べているコードが続くんだけどそれは割愛。

NSArrayはPDFSelectionの配列。というわけでこいつをどうやって利用するのか、明日の勉強でございますな。デベロッパドキュメントのあちこちを調べている時間が長い。Xcode4になって、デベロッパドキュメントがちょっと読みにくくなった気がするなあ。こっちもTabインターフェイスにしてくれたら並行していろいろなクラスを参照できるのに。

PDFkitについて日本語の情報があまり(ほとんど?)ないのがこれまたつらい原因。全て手探りしていくしかないけれど、ま、それがおもしろいんだな。

2011年3月22日火曜日

Xcode4・苦言

Xcodeを使い始めて日が浅いので、3から4になってもそれほど困ったところはない。ウィンドウがたくさん開かない点で大変重宝している。ついでにTabインターフェイス大好きだし。

今のところ不満はただひとつ。Dock上のアイコンを右クリックして表示されるメニューが困る。


3の時は「Openしているproject」と「開いているウィンドウ」が全部表示されていたので、たくさんウィンドウがあってもDockからウィンドウを探すことができた。ところが4ではプロジェクトさえ表示されない。Exposeを使ってウィンドウを探すことになるが、今イチ、視認性が高くないと思うのは私だけか。ぱっと見てすぐわからないことが多いんだな、Expose。

Spaces.appやExpose.aapからはいろいろなアプリのウィンドウを自由自在に動かせるんだから、その辺のAPIをユーザに開放してほしいなあApple。

NSToolbar(3)

めんどくせ、などとネガティブな発言をしてしまって反省。(^^;)Menuと同じでそれほど面倒ではなさそうだ。カスタムViewを簡単にToolbarにのっけてしまえるところは激しく良。

昨日骨組みだけ書いてあったNSToolbarのdelegateメソッド、本日少し書いてみた。といってもADCのサンプルからコピペしたコードが多い。ま、コピペするにもそれなりの取捨選択と事前作業が必要なので、それほど悲観することもないだろう。

- (NSToolbarItem *) toolbar: (NSToolbar *)toolbar itemForItemIdentifier: (NSString *) itemIdent willBeInsertedIntoToolbar:(BOOL) willBeInserted {
     NSToolbarItem *toolbarItem = nil;
    if([itemIdent isEqual: SearchDocToolbarItemIdentifier]) {
        // NSToolbarItem doens't normally autovalidate items that hold custom views, but we want this guy to be disabled when there is no text to search.
        toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdent] autorelease];

        // Set up the standard properties 
        [toolbarItem setLabel: @"Search"];
        [toolbarItem setPaletteLabel: @"Search"];
        [toolbarItem setToolTip: @"Search Your Document"];
        
        searchFieldOutlet = [[NSSearchField alloc] initWithFrame:[searchFieldOutlet frame]];
        // Use a custom view, a text field, for the search item 
        [toolbarItem setView: searchFieldOutlet];
        [toolbarItem setMinSize:NSMakeSize(30, NSHeight([searchFieldOutlet frame]))];
        [toolbarItem setMaxSize:NSMakeSize(200,NSHeight([searchFieldOutlet frame]))];
        [toolbarItem setTarget:self];
        [toolbarItem setAction:@selector(beginSearch:)];
 }
    return toolbarItem;
}
- (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar {
    return [NSArray arrayWithObjects:NSToolbarFlexibleSpaceItemIdentifier, SearchDocToolbarItemIdentifier, nil];
}
- (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar {
    return [NSArray arrayWithObjects:NSToolbarFlexibleSpaceItemIdentifier,SearchDocToolbarItemIdentifier, nil];

}

これだけでサーチフィールドが表示できた。


あとはactionを実装していくわけだが、InterfaceBuilderでNSSearchFieldのSendsWholeSearchStringを有効にしても、キーボードから1文字入力するたびにいちいちactionが呼ばれているのはなぜだろう。この辺は実際に作ってみればわかるか。

NSToolbarはけっこう重要なUIクラスらしい、とだんだんわかってきた。OSXのアプリってWinアプリのようなToolbarの使われ方(MenuのショートカットUI版、とでも言うか)をしていない、という印象が強いのだが、

[toolbar setDisplayMode: NSToolbarDisplayModeLabelOnly]

で使われていることがけっこうあるみたい、と気づいた。早い話、Xcode4で⌘+Fを押したら出てくる検索バー、


ついでにそのすぐ上の「ファイル・クラス・メソッドのセレクタ」も同じく NSToolbarDisplayModeLabelOnly、と思われる。使い方を勉強する価値が十分にある、ということね。

2011年3月21日月曜日

無線LAN親機

いきなり無線LANの親機がこわれた。
リセットしても電源を入れなおしても、DIAGランプ(Buffalo製品)がつきっぱなしで、Wifiランプがつかない。無線LAN機能だけがお亡くなりになった模様。ちなみに取説ではDIAGランプがつきっぱなしになったら修理センターに送れ、と記述されていた。送る手間とお金より、ネットにつながらない時間の長さが耐えられない、ということで、さっそく大型電器店で新しい親機を仕入れてきた。

本体のみなら7500円程度だった。仕方ない。

しかしどーして無線LANって、すんなり設定できないんだろう。インストールCDの中にMac用の「AOSS設定アプリ」があるってんで試してみたら、AirMacが無効です、と言い張って全然働かない。なんじゃこりゃ。

結局自分で暗号化Keyを入力して接続はできたけど、安定した動作になるまでけっこう時間がかかった。

さらに。

今まではイーサネットを無線に変換する子機を使っていたが、どーも調子がわるいのでAirMacを使うことにしたら、スリープからの復帰がけっこうまだるっこしいことが判明。無線LANがすぐに復帰しないみたい。

うむむ。やはりイーサネットでつなぐ子機を使うことにしようかなあ。

Expose

Spinを実際に毎日使っている。自分用に作ったのだからあたりまえだけど、けっこう便利でございますよ。デスクトップでマウスホイール回したらSpacesが切り替わるのは快感。

本日なんとなく、TaskSwitcher上でマウスクリックしたらExposeが起動するようにしよう、と思いついてソースをいじる。

-(void)mouseDown:(NSEvent *)theEvent{
    NSWorkspace* ws=[NSWorkspace sharedWorkspace];
    [ws launchApplication:@"Expose.app"];
    
}
と書くだけだからえらく簡単なわけだけど、Exposeがどこにあるのかしばらく探しまわってしまった。(^^;)Spaces.appと同じ場所だった。

ググったりターミナルであれこれ探しているうちに、こんなことがわかった。

Expose 1

でいわゆる「デスクトップを表示」になる。

Expose 2

で「アプリケーションウィンドウを表示」。

なるほど。

ググっているうちに
Secrets

というサイトに行き着く。OSXの様々なシークレット設定を集めた、というサイトで、設定をあれこれいじれる環境設定アプリまで配布していたのでさっそくインストールしてみた。


設定の項目はたくさんあって、全然試せていないけれどこんな感じだった。


世の中にはたくさんのハッカーがいるもんだなあ。ありがたやありがたや。

NSToolbar(2)

NSToolbarをつけようとしてあれこれ調べる。

ADCのサンプルやら先達のみなさんのサイトで調べて、

- (NSToolbarItem *) toolbar: (NSToolbar *)toolbar itemForItemIdentifier: (NSString *) itemIdent willBeInsertedIntoToolbar:(BOOL) willBeInserted

- (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar

- (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar


この3つのメソッドをdelegateになるクラスで実装すればいいことがわかった。しかし初心者の悲しいところは、どのクラスをdelegateにすればいいかわかんない、というところ。(^^;)

サンプルコードなんかではDocumentクラスで実装していることが多いけど、どう考えてもそれは「簡便な」方法でしょう、ということで、ここはWindowControllerで実装するのがいいのではないか、と考えた、のだが、実際にWindowControllerに書いていみるとビルドする前から「WindowControllerはdelegateになれないよ」と警告がでる。

うーん、うーん、と唸りながらあちこち調べる。そうすると、どうもクラスのヘッダにというプロトコル宣言(?)を入れればいいらしいことが判明。で、WindowControllerのヘッダに入れたら警告は消えた。うーむ。しかしまだメソッドの中身を何も記述していないのでビルドはできていない。だから実際にWindowControllerがDelegateでいいのかどうかはまだわからない、という。

お休みで時間があったために、プログラミング以外のことをやっている時間が長かったため、今日もこんなところ。

しかしADCのサンプルをたくさん眺めて、NSViewControllerを使って複数のViewを切り替える方法もなんとなくわかってきたからいいとするか。

2011年3月20日日曜日

NSToolBar

休日は家族の用事やらなにやらであっという間に過ぎる。今日もあまりXcodeを触らずに終わった。

検索をできるようにしようと思ってToolBarに検索Boxをつけるか、と考えてNSToolBarを調べる。

・・・めんどうだなあ、これ。(^^;)Cocoaは今のところ大変使いやすいフレームワークだと思っているけど、ToolBarに関してはかなり面倒。

絵をずらずらっと並べてイベントハンドラと結びつける、みたいにならないのか。

というわけでADCのサンプルやらSkimのソースやらを眺めて本日は終了。

2011年3月19日土曜日

Cocoa NSWindowController

本日は連休初日でほとんど寝ていた感じ。ちょっと疲れがたまっていて、プログラミングに向かう気力がわかない。珍しいこともあるもんだ。

簡易PDFビューワを作っている。PDFドキュメントの単語をクリックすると辞書.appがパネル表示される、というのがメイン。いちおうそこまでは簡単にできて、その後どうしようか、というところ。

朝、寝床でごろごろしていると、どこからか「検索機能くらいは勉強のためにつけておけ」という声が聞こえてきた。(^^;)何かのお告げらしい。

そんなわけでちょろちょろとPDFViewの検索関係のメソッドを調べる。PDFkitには便利なクラスやメソッドが山盛りなので、やりたいことはすぐにできそうだけれど・・・問題はUI。検索文字列を入力して、検索結果を表示するためにどんなUIにするか、非常に一般的なことではあるけれども、こういうcocoaプログラミングの基礎的な部分を非常におろそかにしているため、何をどうやってやるか全然わからない。(がっくり)

とりあえずプレビュー.appとSkimの検索関連のUIを調べる。

プレビュー.app

PDFThumbnailViewをカスタム化しているようだ。

こっちはSkim

上の画像は検索結果をtableViewに表示しているが、もう一つこんな表示もある。


当面はSkimの最初の画像、TableViewに表示することを目標にしてみる。

そうすると、SplitViewのsubViewを切り替える必要があるなあ。まずはWindowContrillerを作ってそこからViewを操作するようにしてみよう。

というわけでNSWindowControllerについても調べ始める。Skimなんかは全部のViewとWindowにControllerが用意されているので、そういうお作法を学ぶいい機会かも。

コードを書きながら勉強、勉強しながらコードを書く、ということがしばらく続きそうだ。疲れてさえいなければ、それがサイコーの娯楽なんだけど。

2011年3月18日金曜日

サブタイトルを変えてみた

「50近い小学校教員でも、Railsは楽しめるよ」というサブタイトルを「素人のおっさん、Cocoa Programingの海をゆく」にしてみた。

Rails関係の話題には当面もどりそうにもない、ということで。

どーでもいいな、こんなことは。
このblog全体がどーでもいいなこんなことは、なのだが。

ついでにメインタイトルも変えようかなと一瞬思ったが、あと半年もすれば50歳になっちゃうおやぢにしてみると「日暮れて道遠し」は毎日の実感なので変えないことにした。

元ネタは中野重治のエッセイの題名で(いやもともとは故事成語か)・・・といっても、中野重治そのものがすでにほとんど知られていない過去の作家になっているかも。ちょっと悲しい。「中野重治詩集」、今読んでもすごーくいいんだけどな。「私の心は悲しいのに」とか。

PDFkit(その5)辞書.appで辞書を引く(その3)

PDFView上の、現在のマウスカーソル下にある単語を取得する。
PDFSelection* sel=[page selectionForWordAtPoint:[self convertPoint:point toPage:page]];
pageは
PDFPage* page=[self currentPage];
pointは
NSPoint point=[self convertPointFromBase:[theEvent locationInWindow ]];

取得した単語の、page上の位置と大きさ(rect)を取得する。
NSRect selRect=[sel boundsForPage:page];

さて。ここから、selRectのoriginをscreen座標系に変換しないと辞書パネルが正しい位置に表示されない。泥臭く変換してみる。

まずpage上の座標をViewの座標へ。
NSPoint vPoint=[self convertPoint:selRect.origin fromPage:page];

さらにPDFViewのsuperViewであるNSSCrollViewの座標へ。
NSPoint p1=[[self superview] convertPoint:vPoint fromView:self];
それをさらにWindowの座標へ。
NSPoint p2=[[self superview] convertPointToBase:p1];
そしてやっとScreen座標へ。
NSPoint p3=[[self window] convertBaseToScreen:p2];

これでやっと、ほぼ望む位置に辞書パネルが表示されるようになった。

まず右クリックから「辞書で調べる」を選択した場合の画像。

次が現在作っているappで出した辞書パネル。

y方向に若干のずれがある・・・。どうしてそうなるのかよくわからない。ここまできたらもういいか、という素人独特の判断で、

point2.y=rect.size.height- screenPoint.y-3.0;

とやったらそれらしい表示ができたので満足とする。
なおscreenPointは上記の処理をいっぺんにやってみた結果。

NSPoint screenPoint=[[self window] convertBaseToScreen:[[self superview] convertPointToBase:[[self superview] convertPoint:vPoint fromView:self]]];

なんかむちゃ長い1行だ。(^^;)ま、いいか。

いちおう初期の目標はこれで達成。このままPDFビューワを作りこんでいくかどうか、ちょっと考えている。自分用のアプリとしても、しおり機能くらいはつけたい。でもそうすると、「読み込んだPDFごとのデータ保存」が必要になるからすごくめんどうな予感がする。どーしよー。

検索機能とかもいるよなあ。

Document Base のいい勉強になる気もするけど、どうしても作りたい、ということでもないので迷い中。

2011年3月17日木曜日

PDFkit(その4)辞書.appで辞書を引く(その2)

HIDictionaryWindowShowの引数は次のようになっている。

void HIDictionaryWindowShow( DCSDictionaryRef dictionary,
CFTypeRef textString,
CFRange selectionRange,
CTFontRef textFont,
CGPoint textOrigin,
Boolean verticalText,
const CGAffineTransform *viewTransform );
DCSDictionaryRef dictionaryはNULL指定、CFTypeRef textStringは検索する文字列(検索して結果が0だと何も表示されません)、 CFRange selectionRangeはDCSGetTermRangeInStringの戻り値で選択文字が何文字か、という数値が入っている模様、CTFontRef textFontはパネル表示した時のタイトルFont、検索文字列をCFStringで指定した場合は必須(指定しないとアプリが落ちますな)、CGPoint textOriginが要は辞書パネルの表示開始位置。

辞書パネルの表示がずれているのはどう考えてもtextOriginのせいなわけで、ここに[NSEvent mouseLocation]を入れてみたらうまくいった。

コードは相変わらずとりあえず動けばいい状態の恥ずかしいものだけどこうなっている。

-(void)mouseDown:(NSEvent *)theEvent{
   
        PDFPage* page=[self currentPage];
        NSPoint point=[self convertPointFromBase:[theEvent locationInWindow ]];
                    
        PDFSelection* sel=[page selectionForWordAtPoint:[self convertPoint:point toPage:page]];
    if ([[sel string] length]>0 ) {
        CFRange rang=DCSGetTermRangeInString(NULL, (CFStringRef)[sel string], 0);
        NSPoint p=[NSEvent mouseLocation];
        CGPoint point2;
        point2.x=p.x;
        NSRect rect= [[NSScreen mainScreen] frame];
        point2.y=rect.size.height- p.y;
        CTFontRef font = CTFontCreateWithName(CFSTR("Helvetica"), 0.0, NULL);
        HIDictionaryWindowShow(NULL, [sel string], rang, font, point2 , FALSE, NULL);
    }

}

辞書パネルの表示位置はスクリーン座標が必要、ということらしい。


しかしまだうまくいかないというか、すっきりしないところがある。「mouseDownイベントが起きたスクリーン座標」だけだと、たとえば単語の途中をクリックするとこうなってしまう。


かなり単語の先頭からずれた場所に辞書パネルがでる、と。
これは「選択された文字列のPDFview内のRect」をなんとかスクリーン座標まで変換しないと解決できないようだ。

PDFPage→View→Window→Screenという段階で変換しないといけないようで、こんがらがってしまう。焼酎をちびちびやりながらコーディング、というわけにはいかないので明日以降調べる、と。

2011年3月16日水曜日

Spin β版 公開

一応完成版ですが、自分の環境でしか使ったことがないのでβ版としておきます。

右のサイドバーの「Spin β公開中」からダウンロードできますので、よければ使ってやってください。bugなどはコメントしてもらえればうれしいです。

PDFkit(その3)辞書.appで辞書を引く

昨日の続き。PDFファイルを表示して、マウスクリックで単語を拾って辞書.appで辞書を引く。
昨日はここまでできた。


mouseDownの中で
    [pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
    [pb setString:[sel string] forType:NSPasteboardTypeString];

    NSPerformService(@"Look Up in Dictionary" , pb);
 
とすると上の画像のように辞書.appが起動する。うーん、こうじゃなくて、Ctrl+Command+Dした時のように、パネルで辞書.appを表示したいんだけど・・・。

もう一つ、プログラム内から辞書.appを使う方法が
dict://
だということは知っていたので使い方を調べる。そして書いたのが次のコード。

    NSString *str=[[NSString alloc] initWithFormat:@"dict://%@",[sel string]];
    [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:str]];

しかしこれも


辞書.appのウィンドウが開いてしまう。なぜウィンドウが開くとだめかというと、いちいちウィンドウのフォーカスが変わってしまうのが不便だから。辞書がパネル表示されるとその辺が便利。

上の方法を調べているうちに、デベロッパドキュメント内で

Dictionary Services Reference
に行き当たった。苦労して英文を読んでみると、
HIDictionaryWindowShow
がまさに希望する機能を実現するメソッドらしい。

というわけで、Carbonなので生なCの関数にびくびくしながら次のような、いい加減なコードを書いてみる。

    CFRange rang=DCSGetTermRangeInString(NULL, (CFStringRef)[sel string], 0);
    CGPoint point2;
    point2.x=point.x;
    NSRect rect= [[NSScreen mainScreen] frame];
    point2.y=rect.size.height- point.y;
    CTFontRef font = CTFontCreateWithName(CFSTR("Helvetica"), 0.0, NULL);
    HIDictionaryWindowShow(NULL, [sel string], rang, font, point2 , FALSE, NULL);
NSScreen系とCGWindow系の座標変換、とか、CTFontRefの作り方、とか、そりゃもうググリまくりですよ。

これで実行してみると


出た。パネル表示の辞書。しかし位置がずれている。うーん、座標系の変換でまだやることがあるみたい。

でもいちおう、考えていたことができるとわかったのでうれしい。

2011年3月15日火曜日

PDFkit(その2)

PDFkitについて調べながらコードを少し書く。

本日書いたのはこれだけ。

-(void)mouseDown:(NSEvent *)theEvent{
 
    PDFPage* page=[self currentPage];
    NSPoint point=[self convertPointFromBase:[theEvent locationInWindow]];
                   
    PDFSelection* sel=[page selectionForWordAtPoint:[self convertPoint:point toPage:page]];
    //NSLog(@"%@",[sel string]);
    NSPasteboard* pb=[NSPasteboard generalPasteboard];
    [pb setString:[sel string] forType:NSPasteboardTypeString];
    //NSLog(@"%@",[pb stringForType:NSPasteboardTypeString]);
    NSPerformService(@"Look Up in Dictionary" , pb);
}

カスタムPDFViewの中のmouseDown。
PDFSelection* sel=[page selectionForWordAtPoint:[self convertPoint:point toPage:page]];
こいつでマウスクリックした場所にある単語を拾うことはできる。しかしそれをPasteboardに書きこむことができないみたい。NSPasteboardの使い方がよくわからないや。明日以降勉強。

上記のコードで、一応辞書.appが起動するところまでは確認できた。ただし渡している単語はNSPasteboardTypeString、というかNSだけという不思議。しかも辞書.appはウィンドウを開いちゃうし。

PDFView、右クリックすると単語を選択してサービスメニューを開くところまで実装されているなあ。空白部分で右クリックすれば、PDF用のサービスメニューが開く。よくできているクラスだ。

追記:
[pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
をsetString前に書くと無事動作する。10.6以降でもやはり必要なのね。

2011年3月14日月曜日

PDFView(PDFkit)

PDFkitをさわり始めている。これがなかなかおもしろい。ぶっ飛びで簡単にPDFを表示できる、と、とあるblogに書いてあったけれど本当にぶっ飛びに簡単だった。

ADCのPDFkit関係のサンプルは
・PDFKitLinker2
・Link Snoop
・PDF Annotation Editor
・PDF Calendar
という4つが現在のところ主なものらしい。このうち、昨日あたりからPDF Annotation Editorのソースを読んでいる。Annotationはプレビュー.appでいうところの「注釈」で、PDFにあれこれ上から書き込める機能。自分としてはそんな機能は全然必要としていないので、空のプロジェクトから自分で作っていく方法を選んだ。

本日の成果。


わずか1時間程度で、見た目だけはプレビュー.appと変わらない(というのは言い過ぎか)PDFビューワができてしまう。いちおう、プレビュー.appではないよ、という証拠?画像も。


本日やったこと。

ドキュメントタイプの指定

プロジェクトを作るときにドキュメントの拡張子を「pdf」にする。

Quatrz.frameworkをプロジェクトに追加

プロジェクトのプロパティで追加できる。

コード追加
本日書いた、というかほとんどコピペだけど、とりあえず追加したコードはこれだけ。

- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
    [super windowControllerDidLoadNib:aController];
    PDFDocument *pdfDoc;
    
    pdfDoc = [[[PDFDocument alloc] initWithURL:[self fileURL]] autorelease];
    [pdfView setDocument: pdfDoc];
    // Add any code here that needs to be executed once the windowController has loaded the document's window.
}
[super window...]までがあらかじめ書かれている部分で、それ以下のpdfDoc云々の2行だけ。これはデベロッパドキュメントの「PDF Kit Programming Guide」からほぼコピペ。

ドキュメントウィンドウ
contentViewだけのwindowに、以下のようにSplitViewをはり、その上にPDFViewとPDFThumbnailViewを配置する。


で、PDFThumbnailViewから右クリックで例の矢印をPDFViewに伸ばしていくと


あらかじめ設定されているpdfViewというOutletが現れるので、それで接続する。


この接続をするだけで、PDFのThumnailが全自動でできあがる。これにはびっくりした。Thumbの大きさは128x128にしてある。

AppDelegate
ただしこのままだと、アプリ起動時に空のウィンドウが表示されてしまって気持ちが悪い。
PDF Annotation EditorではAppDelegate.mで
- (BOOL) applicationShouldOpenUntitledFile: (NSApplication *) application
{
    return NO;
}

とすることでこれを抑止している。

しかし・・・Xcode4で新たしいプロジェクトをつくると、3の時のようにこのAppdelegateを自動で作ってくれなくなった。(そのかわりというかなんというか、git init が全自動で行われる)

Delegateってどうやって作るのよ?と調べて自分でやってみるのにけっこう時間がかかってしまった。(^^;)MainMenu.xibのほうにNSObjectを作って、そのclassをAppDelegateにする、ということでいいようだ。

本当にわずかなコードでPDFビューワができてしまった。ただし、WindowControllerは作っていない。検索とかの機能をつけるなら、WiodowControllerをはさんだほうがいいようだ。以下は明日。

2011年3月13日日曜日

Cocoa ObjC 備忘録 NSPerformService

NSPerformService
デベロッパドキュメントから引用。すぐ忘れるからな。

NSPerformService
Programmatically invokes a Services menu service.

BOOL NSPerformService (
NSString *itemName,
NSPasteboard *pboard
);
Parameters
itemName
Specifies a Services menu item, in any language. If the requested service is from a submenu of the Services menu, the value must contain a slash (for example, “Mail/Selection”).
pboard
The pasteboard containing the data required by the service. This data must be present for the service to succeed. On output, this pasteboard contains the data returned by the service provider.
Return Value
YES if the service was successfully performed or NO if it was not.

Discussion
Use this function to programmatically invoke a service found in the application’s Services menu.

Availability
Available in Mac OS X v10.0 and later.
Related Sample Code
PhotoSearch
Declared In
NSApplication.h

NSPasteboard* pb=[NSPasteboard generalPasteboard];
へ?このあとどうやって書くんだろ。明日以降。
Spinにめどがついたので次の小物ツールを計画中。こんどは「辞書引き専用PDFビューワ」はできるかな、と考えている。幸いADCにPDFビューワの原型がサンプルであがっているので、それに手を入れる方向でいけばなんとかなるかな、と。

NSPerformServiceを使えば、選択した文字列を辞書.appに渡せるようだ。
しかしPDFkitは手に余るかもなあ。

Spin Spaces.appが無効の時はどうなるか

Spaces.appの寄生虫のようなtoolなわけで、Spaces.appが無効だったらどうなるか一応試す。今まで試してないほうが間違っておるな。(^^;)

基本設定
1行4桁、横に4枚のワークスペースというのが普段の私の設定。
ワークスペース1にfirefoxと夜フクロウ、ワークスペース2にXcode、って感じで割り振っている。

Spaces.appを無効にする
当然、起動中のアプリは全てワークスペース1に集まってくる。Spaces.appの設定は残っているので、ここでSpinを起動するといつもどおりの画面になる。ワンパターンだけどこれね。

Spaces.app無効時のSpinの動作
起動はするけれど、ワークスペース切替はできなくなっているに違いない、と思っていた。ところが、無効なはずのワークスペースに切り替えてしまえる。

さらに、アプリも普通に起動できる。これにはびっくり。

しかし、タスクスイッチャで他のワークスペースにあるアプリに切り替えようとしても、さすがにそれはできない。

なるほど、おもしろ。

Cocoa ObjC Spin開発いちおう終了

ほぼ出来上がった、と自分では思うので公開の準備を始める。

どこにサイト作っておこうか、という話ですな。bloggerの「ページ」機能を使えばいいようなんだけど、問題は.zipファイルの置き場所。googleサイトをまたまた使わせてもらおうか。(このblogのsyntaxhighliter用ファイルをすでに置かせてもらっている。申し訳ないことだ)

Coolなサイトを作る技術も気力もないので適当につくるしかあるまい。

ダウンロード用のリンクを記述すればいいわけだが、右クリックをする場所によって微妙に機能がちがったりするので、少しだけ説明が必要だなあ。

2011年3月12日土曜日

Cocoa ObjC Xcode4でローカライズ

Xcode4からの機能なのか、3の時からできたのか、すでに3はHDD上にないので確認できないが、Xcode4に統合されたInterfaceBuilderで簡単にローカライズができた。nibファイル関連だけだが。


こんな形でUIを作ったら、インスペクターでローカライズファイルを追加する。


そうするとローカライズ用のxlbファイルが作られる。


あとは日本語を直接UIに記述していく、と。


これでメニューやらnibに埋め込むウィンドウやViewを日本語化することが可能。


ソース内のメッセージなどは従来のローカライズが必要なのかな。埋め込んであるテキストは右クリックメニューくらいなのであまり試す気なし。(^^;)

Cocoa ObjC 環境設定パネル(6)

結局環境設定パネルはこんなふうになった。


表示系を整えて、TaskSwitcherに右クリックメニューをつけて


だいたい完成。いくつか細かい動作でデリゲートの機能とかを確認していくつもり。

2011年3月11日金曜日

本日はお休み

なるべく毎日更新、が基本方針。その日の勉強の成果を書き留めておくために。

しかし本日はお休み。地震の被災地のみなさんのことを思うと胸が痛む。

2011年3月10日木曜日

引き続きアップデートもやってしまう

iTunesとSafariとあとも一つはなんだろう、とにかく3項目をアップデート中。

もうひとつはJavaだった。

Xcode 4

600円が惜しいわけではない。さすがにそこまでケチではない。AppStoreのカスタマレビューに「なぜ日本なら3割増なんだ?」という書き込みがあったけれど、ま、1ドル=120円というアップルレートなんでしょう。

ここで疑問なのはいきなりの有償化ですね。今後Lionには今まのでように無償でXcodeは付属しないのだろうなあ。

AppStore経由でアップデートも自動でできるようにするからテラ銭払いなさい、ということなのか、それとも無償でXcodeが使えるとあほらしいアプリが(きっとiOSで)多くなりすぎるから、たとえ600円といえどお金を払ってまでXcodeを使おう、というユーザだけに絞ろうとしているのか。

でも600円ならアホアプリを作るユーザへの対抗策になり難い気もする。

MSでさえVisualStudioをほぼ無償で提供している現在、appleが逆行する意味がエンドユーザとしては理解不能だ。ただでつけておけば「さすがapple、太っ腹」と言われ続けたろうに。

少しだけ、デベロッパープログラムに登録するか悩んだ。約1万円でLionも使えるようになるし、と。とりあえず600円で済ませたけど(^^;)。

Xcode4のUIは3からかなり変更されている。


少しだけ触った限りでは、以下の点で私は4のほうが好き。(結局UIって好みと慣れの問題ですね)

1,ウィンドウがたくさん開かない
2,tabでviewを管理できる
3,1とかぶるけれど、InterfaceBuilderと統合された
4,Gitが使える(GUIで)

特に私には2が大きい。シングルウィンドウアプリならtabのあるなしは使い勝手をかなり左右する。あとはtabのAPIをちゃんと公開してくれれば最高ですな。

4も地味に重要かも。Githubと同期できたのにはびっくり。(あらかじめリポジトリは作ってあって、それとちゃんと同期出来ました)

Cocoa ObjC 環境設定パネル(5)

subViewの表示順を入れ替える。

縁起物なのでXcode4のウィンドウをキャプチャしちゃおう。


なにか幽霊のようにうっすらと見えているコントロールは、現在Hideしているもの。TaskSwitcherの表示関係ですな。

それはともかく。Top Viewを入れ替えることができるようにしてみた。とんでもない力業なのでとてもではないがソースは公開しない。(^^;)いわゆるリファクタリングってのをしないといけませんなー。おそらく、全部書きなおすのが一番いいだろうなあ。


とりあえず表示するだけ、なので明日以降、もう少しコードに手を入れて環境設定がすぐに表示に反映されるようにしてみる。

力業でやるならすぐにでもできるけれど・・・。

2011年3月9日水曜日

Cocoa ObjC Spin SpaceView縦表示

ソースを眺めているうちに、Spaces関連の縦表示は簡単にできそうな感じがしたので、危険だけど飲酒プログラミング。(^^;)

行と桁を入れ替えるだけなら簡単だな、やっぱり。

あとはSpacesViewとTaskSwitcherの表示の順番を入れ替えられるようにする、と。

iPad2は買うぞ

と宣言してみる。

appleからのお知らせメールを楽しみに待っている現状です。ふところ具合からいうとWifi16Gしか買えないけど。

Cocoa ObjC 環境設定パネル(4)

現在の環境設定パネル。


縦横表示の切替をやってみた。
チェックボックスをON/OFFするたびに、うまいこと縦・横表示に切り替わるが・・・。よく見ると、なにやら残像が。


明らかに、縦表示の時のsubViewの表示がうっすら見えている。ウィンドウのリサイズをするときれいになる。うー、メインのViewがおかしな挙動をしているらしい。あるいは必要な設定がちゃんとできていないのか。

対症療法として、メインのViewの透明度を下げて0.6にしたら残像が見えなくなった。
透明度付きのプログラミングなんてしたことなかったからなあ。まだまだ勉強することがたくさんありすぎてめまいがする。(^^;)

2011年3月8日火曜日

Cocoa ObjC Spin 縦表示

subViewの表示方法を縦・横どちらでもできるようにする。

ま、これはsubViewのframeのorigin.xとorigin.yを指定するだけなので、意外と簡単だった。

縦表示にしてみた。


SpacesのWorkspace表示は、Spacesの設定をそのまま使っている。上の画像なら2行×2桁。
しかしこれが1行×4桁(実は普段は私はこの設定)にすると、縦表示だとこうなってしまう。


かっこわるー。(^^;)うーん、どうしよう。Spacesの設定とは別に、独自に表示する方法もとれるようにするか、あるいは「行と桁を入れ替える」という表示設定を追加するか・・・。

ただ、デスクトップでホイールころころ→Workspace切り替わる、が実現できちゃったところで、けっこう本体の表示については興味を失いつつある。デスクトップのホイールができるならあまりWorkspace切替器の必要性がないからなあ。

TaskSwitcherもICON_ONLYな表示でいいじゃん、と思ってるし。(なんかネガティブ(^^;))