2011年5月31日火曜日

エネループ

iMacのキーボードにはエネループを2本いれている。
昨年9月にiMacを購入して、最初についてきた乾電池は約1か月で寿命となった。

それから満充電したエネループを入れて、以来およそ7か月・・・その間、充電したのは1回だけである。

本日、20%を切った、という警告が出た。いやー、何ヶ月もったのかしらん。すごいことだ。

実はこの充電というのが惑わしく感じられて、USBのフルキーボードの購入も考えていたのだが、いつの間にかそんなことも忘れてしまった。おそるべしエネループ。それともiMacのおかげ?

Cocoa NSTreeControllerを調べる(4)

FileManagerでOutlineViewにマウントされているデバイスのディレクトリを表示する。デベロッパドキュメントに載っていたサンプル通りのままだと、外付けHDDなどがマウントされた時にどうすればいいかわからない。そんなんでNSTreeControllerについて調べている。

NSTreeControllerでFileSystemを表示しようとする場合、NSTreeNodeを使わないで直接modelのArrayをNSTreeControllerのContentにしたほうがよいみたいだ、というのが昨日の結論。それなら、さらにNSTreeControllerも使わずにOutlineViewのdatasourceでコードを書いてしまえばいいのでは、となんとなく思ったが、bindingを使ったほうがやはり何かと便利そうだ。コードの量が少なければbugも少なくなるはずだし。

というわけで、本日は昨日の状態からさらに

1,[[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:nil options:NSVolumeEnumerationSkipHiddenVolumes]でマウントされたVolumesを取得する。(そうするとHide属性のVolumeを拾わないですむ)
2,volumesというNSMutableArrayをメンバにして、読み書き可能なプロバティにしてNSTreeControllerのcontentにbindingさせる
3,NSWorkspaceDidMountNotification、NSWorkspaceDidUnmountNotificationを使ってマウント時、アンマウント時の処理をしてみる

以上をやってみた。

この状態から外付けHDD「for_mac」をマウントすると、


最後尾に追加される。

コードはこうなった。
#import "Controller.h"
#import "FileSystemItem.h"

@implementation Controller
@synthesize volumes;
- (id)init
{
    self = [super init];
    if (self) {
        // Initialization code here.
        volumes=[NSMutableArray array];
    }
    
    return self;
}

- (void)dealloc
{
    [volumes release];
    [super dealloc];
}
-(void)setVolume{
    NSArray* mountedVols=[[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:nil options:NSVolumeEnumerationSkipHiddenVolumes];
    NSMutableArray *roots=[NSMutableArray array];
    if ([mountedVols count] > 0){
  for (NSURL *element in mountedVols){
            FileSystemItem* item,*parent;
            if([[element path ]isEqualToString:@"/"]){
                item=[[FileSystemItem alloc] initWithPath:[element path] parent:nil];
            }
            else{
                parent=[[FileSystemItem alloc]initWithPath:[[element path] stringByDeletingLastPathComponent] parent:nil];
                item=[[FileSystemItem alloc] initWithPath:[element path] parent:parent];
                [parent release];
                
            }
            [roots addObject:item];
            [item release];
            
        }
  [self setVolumes:roots]; 
 }

    
}
-(void)awakeFromNib{
    [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(didMount:) name:NSWorkspaceDidMountNotification object:nil];
    [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(didUnmount:) name:NSWorkspaceDidUnmountNotification object:nil];
    [self setVolume];

}
-(void)didMount:(id)sender{
    NSLog(@"Mount! %@",sender);
    NSDictionary* info=[sender userInfo];
    NSURL* url=[info objectForKey:NSWorkspaceVolumeURLKey];
    FileSystemItem* parent=[[FileSystemItem alloc]initWithPath:[[url path] stringByDeletingLastPathComponent] parent:nil];
    FileSystemItem* item=[[FileSystemItem alloc] initWithPath:[url path] parent:parent];
    [parent release];
    [volumes addObject:item];
    [item release];
    [treeController rearrangeObjects];
  
    
}
-(void)didUnmount:(id)sender{
    NSLog(@"UnMount! %@",sender);
    NSDictionary* info=[sender userInfo];
    NSURL* url=[info objectForKey:NSWorkspaceVolumeURLKey];
    NSUInteger deleteNo;
    for (NSInteger i=0; i<[volumes count]; i++) {
        FileSystemItem* item=[volumes objectAtIndex:i];
        if ([[item fullPath] isEqualToString:[url path]]) {
           deleteNo=i;
        }
    }
    [volumes removeObjectAtIndex:deleteNo];
    [treeController rearrangeObjects];

}
@end

treeControllerのbindingなどはこうなっている。

これでほぼ考えていた動作が実現できた。次はEseに組み込んでみる。これはちょっと苦労するところがあると予想している。@"/"を期待した動作、などを書いているので。

2011年5月30日月曜日

ダイナミックフィギュア 上巻読了


あまりにもおもしろくて読み終わるのが惜しい。ゆっくり読もう、プログラミングたくさんしよう、と思ってもページをめくる手が止まらない。
今日は上まで読んだんだからもうやめ、と思っても、その上巻の終わりが後をひく終わり方で下巻に突入せざるを得ない。

今日が振替休業で休みでよかった。たっぷり楽しめた。

Cocoa NSTreeControllerを調べる(3)

昨日の段階ではNSTreeControllerとファイルシステムの間にNSTreeNodeをはさんでみたが、どーも冗長なのでもう少し調べてみた。

InterfaceBuilderでNSTreeControllerのアトリビュートを表示すると

こうなっていて、実際にはこの「Children Key Path」をうそでもいいから入力しないと、ビルドには成功しても実行時にデバッグコンソールでエラーが出続ける。
で、ここでChildrenとかのKeyPathを入れるということは、Contentに子ノードを表現するArrayなり、Arrayを返すメソッドがあれば自動的にTree表示してくれそうな感じがする。Childrenの他に入力するKeyPathは画像の通り「Count」と「IsLeaf」・・・ふーむ、これはつまり、EseでOutlineView用に使っているクラスを流用すれば、簡単に行けるのでは?

と見当をつけてさっそく作業をしてみる。
EseのOutlineViewで使っているノード用のクラスはデベロッパドキュメントに載っていたFileSystem.mほぼそのまま。若干現在の実験プロジェクト用に書き換えて、さらにbindingも変えた。


「Model Key Path」に「representedObject」を入れるとNSTreeNodeが保持するObjectのKeyPathが要求されるようなので、ここはrepresentedObjectを削除して直接FileSystemクラスのKeyPathを指定した。

そうすると、とりあえずこれだけのコードで
-(void)awakeFromNib{
    NSArray *mountedVols = [[NSWorkspace sharedWorkspace] mountedLocalVolumePaths]; 
 NSMutableArray *roots=[NSMutableArray array];
    if ([mountedVols count] > 0)
        
 {
  for (NSString *element in mountedVols){
            NSLog(@"%@",element);
            FileSystemItem* item,*parent;
            if([element isEqualToString:@"/"]){
                item=[[FileSystemItem alloc] initWithPath:element parent:nil];
            }
            else{
                parent=[[FileSystemItem alloc]initWithPath:[element stringByDeletingLastPathComponent] parent:nil];
                item=[[FileSystemItem alloc] initWithPath:element parent:parent];
               
            }
                       [roots addObject:item];
            [item release];
          
        }
  [treeController setContent:roots]; 
 }
    

}

(parentをreleaseしてないの点は現在のところ無視(^^;))
こうなった。

ふむふむ、あとはOutlineViewではディレクトリ名しか必要としないから全部NSStringでPath名を取得しているところを、NSURLに入れ替えるかどうか、というあたりだな。removableなメディアのマウントについてはNotificationがあるので簡単だろうし。

2011年5月29日日曜日

ダイナミックフィギュア

図書館に本を返しに行ったら、上下並べておいてあったので早速借りる。


これはすごい。久しぶりに冒頭からわくわくしている。
エヴァンゲリオンそのものはあまりよく知らない(コミックス版を借りて読んだことがある程度。しかもあまり感心しなかったという)のだけれど、醸しだす雰囲気は「エヴァ・インスパイア」系なのでしょうか。

上巻100ページ読んで、「全ての謎に納得する解決」があることを祈っている自分を発見。この厚さだからきっと大丈夫だろう。

Cocoa NSTreeControllerを調べる(2)

昨日は運動会とその反省会のためプログラミングどころではなく、ビールをがぶ飲みして帰宅後即ベッドに倒れ込む。

本日もけっこう疲れていて気力が湧かず、目もしばしばしてあまり集中力がない状態で1日過ごす。しかし2,3日プログラミングから離れるとあっという間に多くのことを忘れるので多少無理してでもCocoaに触れておいた。

本日はNSTreeController、およびNSTreeNodeについて調べた。

書けたコードはこれだけ。
-(void)awakeFromNib{
    NSArray *mountedVols = [[NSWorkspace sharedWorkspace] mountedLocalVolumePaths]; 
 NSMutableArray *roots=[NSMutableArray array];
    if ([mountedVols count] > 0)
        
 {
  for (NSString *element in mountedVols){
            Node* node=[[Node alloc]init];
            NSString *volName=[[NSFileManager defaultManager] displayNameAtPath:element];
            [node setNodeTitle:volName];
            [node setNodeIcon:[[NSWorkspace sharedWorkspace] iconForFile:element]];
            NSTreeNode* treeNode=[NSTreeNode treeNodeWithRepresentedObject:node];
       
            [roots addObject:treeNode];
            [node release];
        }
  [treeController setContent:roots]; 
 }
}

コンテンツ用のNodeクラス(名前とiconだけ)を用意して、それをNSTreeNodeに格納、それをMutableArrayに追加して、NSTreeControllerにsetContentってなんだかすごく冗長なんだけど、いいのかなあこんなんで。
MutableArrayをクラスのメンバにして、InterfaceBuilderでContentに指定したほうがいいか。
とりあえずこれでこんな風な表示になる。


/homeと/netをどうやって消すのかな、とか、この後Childをどうやって指定していくのかな、とか、明日以降への疑問が山積み。

2011年5月27日金曜日

Cocoa NSTreeControllerを調べる

内蔵HDD以外のドライブがマウントされたら、それもちゃんとrootItemにしてNSOutlineViewに表示したい。しかし・・・NSOutlineViewで、rootItemが二つ以上ある場合はどうするの?と調べてみたら全然わからない。

ただ、NSTreeContorollerを使えば実現できることはわかったので、とりあえずそっちを調べてみた。しかしNSTreeControllerもよくわからないクラスだなあ。簡単なサンプルがないかググってみたところ、

Designed Recreations -Cocoa NSTreeController and NSTreeNode

というアーティクルと、ダウンロードできるサンプルが非常にわかりやすかった。サンプルプロジェクトを実行したらこんな感じだった。


ちょっと古いプロジェクトだとビルドできなくてがっくりすることがある。このプロジェクトの場合はTargetを64bitにしてやればビルドできた。

画像でわかるとおり、rootItemがたくさんある。nibでのbindingは、TreeControllerのNodeクラスのnameをOutlineViewにつなげているだけ。

ふむふむ、このコードを参考にして、少し実験してみることにしよう。運動会が終わったら。

2011年5月26日木曜日

運動会

生まれも育ちも北海道なので、この時期に運動会が開催されることに疑問をもったことがない。しかし最近、北海道新聞のコラムに載ったとある大学教授のエッセイを読んで驚愕した。

教授の育った東京では、運動会が秋に開催されるのはもちろんとして、応援といえば学校のそばの文房具屋のおじさんくらい、だったそうな。ところが北海道に来て、娘の小学校の運動会で席取りのために徹夜同然で席を確保し、妻が盛大なお弁当を作る、という文化に激しい違和感をもった、という内容。

ひえー、家族総出、まかり間違えば一族総出で運動会に出かけてきて、昼ごはんはドバーっとお弁当やらおやつやらフルーツやらを大量に並べてほとんど宴会状態になる、というのは北海道だけなのか?それとも日本全国の田舎の風習?

運動会の「席取り」は大変な騒ぎで、私の務める学校でも明日の夕方から1時間にわたって「席取り」が開催される。ちなみに運動会は明後日土曜日ね。
席取りに先立ち、まず子どもに「席取りの順番」を決めるくじを引かせる。くじには、1番から始まって、PTA戸数分の番号が書かれている。で、金曜の5時から、そのくじの順に並んで、順番に運動会を座って見るための場所を確保していく。1家庭畳1枚程度、という約束。
テント用のペグなどを地面に打ち込んで、ビニールテープなどで区分けしていく。中にはビニールシートを早々に引いていく人もいる。

運動会当日は、このシートの上にキャンプ用の保温シートやら座布団やらを敷いて、のんびりビールなどを飲みながら保護者のみなさんは子どもに声援を送りビデオを撮影し写真を撮る。

これって北海道だけ?そうだとしたらすごいカルチャーショックだ。(^^;)

Cocoa FileManager メニューから新しいPathを選択する

現在表示中のディレクトリを、いわゆる「パンくずリスト」で次のように表示している。


この状態から「Devleper」を押すとこんなメニューが出現する。

これは「/Developer/」以下のディレクトリを列挙して選択できるようにしている。

当然、「/」をクリックするとこうなる。

「/」以下のディレクトリを表示するのはいいとして、じゃあ例えば外付けのHDDをマウントしたらどうなるか。

この外付けHDD、今のところ残念ながら/Volumesにしか出現しない。
本来なら、「/」ではなくて「Macintosh HDD」とVolume名で表示して、他にマウントされているVolumeがあればそれも並べて表示できるのがふつうだろう。
まあ現在の仕様上仕方のないところだが、これはなんとかしていきたい。
デベロッパドキュメントの

Low-Level File Management Programming Topics
の「Information about Files and Volumes」をざっと読むと、mountedVolumeURLsIncludingResourceValuesForKeys: options:を使うらしい。

ふーむ、古目のデベロッパドキュメントのサンプルをもとにしたOutlineViewのファイルシステム表示はNSStringベースなのだが、NSURLベースに書き換えないとmountedVolumeURLsIncludingResourceValuesForKeysは使えないなあ。(戻り値がNSURLのArrayなので)

OutlineViewの表示も変更しないといけないが、アプリの根本的な部分に関わるので早めにやっておいたほうがいい感じ。とりあえず運動会が終わってからか。

2011年5月25日水曜日

Cocoa FileManager NSMenu popUpMenuPositioningItem: atLocation: inView:

考えていた機能がそれほど重要なものではないので、とりあえずpopupMenuで表示出来てるからいいか、と思いかけたけれど、ドキュメントにあったNSMenuクラスのpopUpMenuPositioningItem: atLocation: inView:をもう少しだけ研究してみることにした。

popUpContextMenu: withEvent: forView:がクラスメソッドなのに対し、popUpMenuPositioningItemはインスタンスメソッド。

第1引数がNSMenuItemなので、特定のItemだけpopupさせるのかと思ったのだけれど、よく読めばItemはnilでも構わないということなので試してみる。
NSPoint point= NSMakePoint([cell drawedRect].origin.x, [cell drawedRect].size.height);
NSMenuItem* activeitem=[menu itemAtIndex:1];
[menu popUpMenuPositioningItem:activeitem atLocation:point inView:self];

これでこうなった。

マウスカーソルがある場所でクリックしているので、これで期待通りの動作となった。なーんだ、できるんじゃん。ドキュメントをもっとしっかり読まないといかんなあ。

ただし初めはMenuが無効な状態で表示されていた。itemを生成するとき、setTargetしないと有効にならないのね。(^^;)

第1引数でNSMenuItemを指定すると、そのItemが指定したポジションのTopLeftにくるように描画されている。なるほど便利だなあ。

あとはMenuで選択されたディレクトリを表示できるようにすればいい、と。これは明日以降。

Cocoa FileManager NSPopUpButtonCell

NSPopUpButtonCellを使えば、Cellをクリックしたら出てくるPopupメニューを簡単に制御できるか実験してみた。結論からいうと、ちょっと手に余る。

別プロジェクトを作って、NSPopUpButtonCellを表示してみる。
コードはほとんど現在作っているFileManagerのプロジェクトから流用したのでそれほど手間はかかっていない。

ドキュメントを読んだ限りでは、オブジェクトを生成してNSMenuをsetしたら、あとは難しいことはNSPopUpButtonCellがやってくれる、ように思える。(大いなる誤解(^^;))

で、@"/Developer/Applications/Audio"みたいなpathを分解して、それぞれのサブディレクトリをMenuとして表示するPopUpをこの程度まで作ってみた。


各ボタンにMenuをセットして

[button drawWithFrame:rect inView:self];

としてみたら見事にPopUpButtonとして表示してくれるものの、見た目はこれじゃいかん、ということで

[button drawInteriorWithFrame:rect inView:self]

とボタン内部だけ描画してみたらこうなってしまった。

CellなのでEventは表示しているViewで管理しないといけないようだし、drawInteriorWithFrameをカスタマイズしていくのはかなり苦労がありそう。じゃあNSPopUpButtonそのものを使う、と言う手はどうかというと、見た目のカスタマイズはどちらにしろNSPopUpButtonCellの役目なので苦労は同じだろう、と判断した。

というわけでNSPopUpButtonCellをめぐる実験はこれだけで終了とあいなった。

2011年5月24日火曜日

Cocoa FileManager NavigateBar(3)の続き

ドキュメントを読んでから再びXcode4をいじってみたら、やはりNSPopUpButton、あるいはNSPopUpButtonCellを使っているようだ。

ふーむ、NSButtonCellとはかなり扱い方が違うようなので、おもしろそうではある。でもいろいろ苦労するして実装していくかどうかちょっと迷う。

そろそろFileManagerの肝である、「ファイルのコピー、移動、プレビュー」、「ドラッグアンドドロップ」といった濃いところに手をつけてみたいとも思うので。さらにTableViewでのソートとか、グリッドなViewとか。

コピーや移動はUIでユーザとのやりとりも必要だから、ToolBarにも手をつけたいし。ふむ、明日の気分で決めよう。(^^;)

Cocoa FileManager NavigateBar(3)

ディレクトリを表示したCellをクリックしたら、そのディレクトリ以下にあるディレクトリをメニューで表示してみる。


-(NSInteger)cellAtPoint:(NSPoint)point{
    NaviButtonCell* cell;
    for(NSUInteger i=0;i<[buttonArray count];i++){
        cell=[buttonArray objectAtIndex:i];
        NSRect rect=[cell drawedRect];
        if(NSPointInRect(point, rect)){
            return i;
        }
    }
    return -1;
    
}
-(void)mouseDown:(NSEvent *)theEvent{
    NSPoint point = [self convertPointFromBase:[theEvent locationInWindow]];
 NSInteger index = [self cellAtPoint:point];
    if(index!=-1){
        NaviButtonCell* cell=[buttonArray objectAtIndex:index];
        NSFileManager *fileManager = [NSFileManager defaultManager];
        BOOL isDir, valid;
        
        valid = [fileManager fileExistsAtPath:[cell fullPath] isDirectory:&isDir];
        if (valid && isDir) {
            NSArray *array = [fileManager contentsOfDirectoryAtPath:[cell fullPath] error:NULL];
            if(array){
                NSMenu* menu=[[NSMenu alloc]initWithTitle:@"Directory"];
                for (NSInteger i=0; i<[array count]; i++) {
                    NSString* testpath=[[cell fullPath] stringByAppendingPathComponent:[array objectAtIndex:i]];
                    valid = [fileManager fileExistsAtPath:testpath isDirectory:&isDir];
                    if(valid && isDir){
                        NSMenuItem* item=[[NSMenuItem alloc]initWithTitle:[array objectAtIndex:i] action:@selector(menuSelected:) keyEquivalent:@""];
                        [menu addItem:item];
                        [item release];
                    }
                    
                    
                }
                
                [NSMenu popUpContextMenu:menu withEvent:theEvent forView:self];
                [menu release];
            }
            
        }
    }


}

この程度で可能。ただ、popUpContextMenuだとmouseDownを拾ったロケーションでメニューがpopupしてしまうわけで、こういう事態も起こる。

うーん、Xcode4とはちょっと違う動作だなあ。もしかしてXcode4、popupButton使っているのかなあ。もう少し調査してみよう。

2011年5月23日月曜日

iPad2 iOSのUI

UIというか、ユーザーインターフェイスの入力デバイス、すなわち「指」インターフェイスはやはり画期的なUIだとつくづく思う。

娘がiPad2でSafariを使っているのを横目で見ていると、人差し指で軽くスクロールさせている。極めて直感的ですぐれた操作方法なので、それを見ていたおかあちゃんがすぐにまねできる。はじく、ひろげる、狭める、という動作が期待通りの結果を見せてくれるすごさ。

これをプログラミングではどうやって処理してるんだろう。ちょっと興味が湧きますなあ。
PalmやZaurusなど、いわゆるPDAでタッチパネルのデバイスを長らく触ったけれど、結局マウスのかわりに指やペンを使う、というところで留まっていたわけで、appleってこのあたりは発想がすごいんだなあ、と改めて感じた。

Cocoa FileManager NavigateBar(2)

本日は「ひとつ上のディレクトリへ」ボタンの実装。
-(IBAction)upButtonAction:(id)sender{
    if ([tabTitlePath isEqualToString:@"/"]) {
        return;
    }
    else{
        NSString* newPath=[tabTitlePath stringByDeletingLastPathComponent];
        [outLineView deselectRow:[outLineView selectedRow]];
        [self setDirectoryRowFromFullPath:newPath];
    }
    
}

rootなら何もせず(というか、rootの時はボタンがDisebleだから一応のエラー対策)、その他の時はもともと持っている「tabTitlepath」という名前の「現在のディレクトリのfullPath」からstringByDeletingLastPathComponentでひとつディレクトリを遡るパスをつくり、それをOutlineViewにセットする、と。
OutlineViewの選択行が変更されると連動してTableViewの中身やTabのタイトルなども変更されるので(KVOですな)、これだけでOKだった。

時間があったのでさらに「現在のディレクトリの場所のビジュアル表現」をやってみた。

モロXcode4のまね。(^^;)一番時間がかかったのが「区切り線」をドット絵で書くこと。
この手の小さなpngはもっぱら

このアプリを使わせてもらっている。慣れるとなかなか便利なアプリであります。

ここから「ディレクトリをクリックした時の処理」は明日以降。

2011年5月22日日曜日

Cocoa FileManager NavigateBar

結局SplitViewのスプリッタ位置復元はとりあえず放り出した。(^^;)ユーザーインターフェースとしては「ユーザーが使いやすくカスタマイズした状態の保持」はすごく大事なのでそのうち再挑戦しよう。

本日はTableViewの上に表示するNavigateBarをいじる。1つ上のディレクトリに移動する、ヒストリ上を進む、戻る、といった機能をつけたい。

本日はここまで。

ボタン3つは楽をしてNSButoonをnibにはりつけた。上矢印があんまり見た目がよくないなあ。(某サイトからいただいたものだから文句は言えないが)

その横のディレクトリの「パンくず表示」はNSButtonCellを使っている。iconとpath名を表示するだけなので、ButtonCellでなくてもいいかも。NavigateBar(NSView)側からイベントを処理するならNSCellのカスタムクラスでいいか。
- (void)drawInteriorWithFrame:はOutlineViewの表示用のCellから流用。というか、このCellそのまま使ってしまってもいいかな、と考えている。

Cell側にメニュー表示を任せようと考えていたが、NavigateBar側でマウスイベントを処理することにすれば、メニューもひとつで済むか。
Xcodeについているこの「ミニツールバー」のまねをしようとしている。

path名をクリックしたら「同じディレクトリの中の他のディレクトリ」をメニューで選択できるようにしてみる、と。OutlineViewで選択すればいいわけだからあまり必要ないといえば必要ないのだけれど・・・。

2011年5月21日土曜日

ipad2 1週間

iPad2が着いて明日で1週間。

劇的に生活を変える、ということはないけれど、ちょこちょこっと楽しくしてくれるデバイスなのかもしれない。

本日午前中は疲れのためプログラミングに手をつける気力が出なかったため、iPad2のアプリをちょろっと調べていくつかインストールしてみた。

iTunesのAppの画面はこんな感じ。

GarageBandも購入した他、極めて一般的なアプリが並んでいる感じがいたしますな。家族のためにインストールした「映画情報」がけっこう楽しくて予告編をたくさん見てしまった。北海道の田舎町の映画館の上映時間もちゃんと教えてくれるので感動しましたよ。

PaperTossとCardSharkは最高のひまつぶしゲーム。PaperTossのHD版はなんかすごくいい。(^^;)

Cocoa FileManager Tab削除の挙動 NSNotificationCenter removeObserver

Tabを削除したら当然Tabに乗っていたオブジェクトも削除される。ってことはいわゆるカウンタ方式のメモリ管理でなにかまちがいがあるのかしらん、といろいろ調べてみる。

しかし不用意なautoreleaseもないようだし、わざわざretainと書いてるところもない。

不具合の出現の仕方がこれまた不規則で、Tab削除後、TableViewの行をダブルクリックした時に発生するところまではわかっていたが、「このオブジェクトにこんなセレクタはないぞ」と怒られるだけの時や、いきなりアプリが落ちる時や、よくわからない挙動をする。

「そんなセレクタはない!」と怒るときのメッセージをよくよくみると、特定のNotificationのaddObserverで登録してあるセレクタだった。うーむ、ということは・・・addObserverしたNotificationを、オブジェクトが消えるときにちゃんとremoveしていない・・・。うおー、また単純なミスだった。

荻原本で確かめたところ、やはりちゃんとremoveObserverしないとセレクタへのポインタが残ってしまうみたい。そのポインタがたまたま他のオブジェクトを指していたときは「そんなセレクタはない!」となり、ポインタが空ならメモリエラーが発生していた、と。

コーディングを急いでいるときはこういうエラーを起こしてしまうんだなあ。もっとていねいにいかないと。

教訓:NotificationのObserverは必ず削除する

そんなんでエラーの原因がわかったところで、気分良くUserDefaultsにあれこれ記録する方法を勉強してみた。
NSRectをそのまま記録しようとして「そんなプロパティは記録できません」といわれて首をひねり、ググって
NSStringFromRect(NSRect)
に行き着く。そんなんでとりあえずこんな感じで記録できた。

そこでこれを復元するわけだが・・・NSSplitViewのスプリッタの位置、どうやって復元させるかまだわかっていない。もちろんひとつだけならInterfaceBuilderで「AutoSaveNmae」を付ければいいわけだけれど、Tabの分だけSplitViewもあるわけで、これはやっぱりSplitView上にあるSubViewの位置を全部記録する必要があるのかなあ。

明日はNavigateViewに掛かりたいけれど、果たしてそこまで行けるか。

2011年5月20日金曜日

Cocoa FileManager Tab削除の挙動

自分で作ったtabインターフェイス、要はNSTabViewをタブレスで表示して、TabViewItemの切り替えをTabでやっている。

よくある、PrefarenceでツールバーでTabViewItemを切り替えているのと同じ。違うところと言えば、動的にTabItemを付け加えたり削除するところ。

addTabするのは順調に動作するのだけれど、removeTabすると挙動がおかしくなるのを発見。今までTabとOutlineViewとTableViewをばらばらにつくってきて、いざ同調させて動かそうとしたとたんに不具合がどんどん出てくる。いささかげっそり。

本日は1週間分の疲れもあって集中力が続かない。明日以降がんばってみよう。

2011年5月19日木曜日

iPad2 あまり使っていない

私自身はあまりiPad2を使ってない。もっぱら娘たちが使っている。
「でかいiPhoneは使いやすい」というのが彼女たちの感想。

すき間時間のゲームってのが使う目的みたいですな。

私は朝、新聞がわりにざっとネット上のニュースを確認する、天気を確認する、予定をチェックする(GoogleカレンダーとMUJICalendarを同期させている)のが主な用途。

早くもう少し使いこなせるようになりたいなあ。

Cocoa FileManager NSOutlineView bug原因判明

OutlineViewのrootItemを取得するのに、autoreleaseをうかつにつけていたのがbugの原因だった。(^^;)
rootディレクトリにアクセスしようとした時だけメモリのエラーでこけるので、最近追加したコードでrootItemに触っていたのを思い出してよくよく見てみたらすぐにわかった。

うー、ちょっと慣れてくるとこういうエラーコードを書いてしまう。気をつけよう。
GC有効にしてもいいのだろうけれど、GC有効にしたとたんTabの中身のViewが全部同じになってしまう、というよくわからない動作をするので今のところパス。

iOSのプログラミングにも当然興味があるわけで、GCで楽するのはもう少し後、と考えている。

さて、これで

この状態から、rootの三角をクリックすると無事

こうなる、と。しかしこの状態でもう一度rootの三角を押すと

OutlineViewの選択行ハイライトは当然消えている。これはFinderでもXcodeでも同じ動作なので仕方のないところ。しかしこれだと「右側のペインはどのディレクトリの中身か」がわかりづらいので、NavigateViewを作っていく。つまりXcodeでいう

今日気づいたんだけれど、結局自分は「Xcode4と同じようなインターフェイスのファイルマネージャ」をつくろうとしているらしい。ふむ、それもおもしろいか。それならそれで目標がはっきりしていていいかも。

2011年5月18日水曜日

iPad2 無線LAN?

リセット云々の原因はどうも無線LANと繋がりづらくなることのようだ。iPad2そのものが固まってしまうわけではなさそう。

iMacでもスリープ解除後、無線ルータを探し出せず毎度毎度30秒くらい待たされるので、その辺りが原因かと。

無線ルータはbuffaloのWHR-HP-G300N、けっこう新しいブツなんだけど・・・。要調査、ということで。

Cocoa FileManager NSOutlineView調査中

OutlineViewのselectedRowは、選択行がない場合(たとえばディレクトリを閉じた場合は選択行なくなる)は-1を返す。

このチェックをしていなかったのがまず昨日のエラーの第一の原因。nibファイルのSelection項目から「Empty」のチェックをはずせば、「閉じたディレクトリ」が自動的に選択行になるためこれで対処してもいい。(1つ問題が残るけど)


問題というのはなぜか起動時にrootまで選択されてしまうこと。これはまあなんとかなりそうな予感はする。

それよりもなによりも、「/」を閉じようとすると相変わらずアプリが落ちる。これについてはまだ追跡中。OutlineViewのitemになるクラスに問題がある、みたい。

なかなかbugの原因がわからずいらついてしまう。さらに深く追求するぞ。意外とアホみたいな原因だったりするかなあ。

2011年5月17日火曜日

iPad2 けっこう頻繁にリセットする

今のところはっきりした原因はわからないものの、動作が不安定になることがけっこうある。

例えばネットがらみのアプリが新しいウィンドウ(ページ?)を開こうとして、いきなり落ちる。

MUJIのカレンダーが更新に失敗する。

天気予報アプリが更新できない。

こういった症状の時はリセットしないといけないようだ。

また、たくさんのアプリを起動しておくと、強制リセットがかかることもあるみたい。

こういう面ではiPhoneのほうが安定していると今のところ感じているが、私はiPhoneのヘビーユーザではないので、iOSに共通の症状なのかもしれない。

異常に快適な時と異常に不安定な時の症状の切り分けができないのがちょっと残念。とりあえずアプリはこまめに終了したほうがいいようだ。

Cocoa FileManager NSOutlineViewをさらに調べる

前回起動時の「Tabに表示していたディレクトリ」を、次回起動時に復元する、という作業をしている。

最後に表示していたTabの数は簡単に保存できるし復元もできる。Tabのタイトルから表示ディレクトリを復元するところであたふたしている。

私の場合は、ファイルマネージャなら前回終了した時と同じ状態で使い始めたい。この辺も好みだろうから、UserDefaultsで設定できるようにするべきだろうな。

とりあえずUserDefaultsから前回表示していたディレクトリ名を取得して、そのディレクトリをOutlineViewで選択状態にしたい。

NSOutlineViewは素人にとってはけっこう難物で、たとえば「/」だけを表示しているときは行番号0しか受け付けてくれない。「/」を展開した状態にしないと、例えば「/Applications」の行番号を取得しようとしても「-1」しか返してこない。現在表示している行数を常に意識しないといけないようだ。

そんなんで本日も短い時間ながらあれこれやって表示ディレクトの復元に挑戦中。

一応はできたのだけれど、

こういう状態から「/」を折りたたもうとするとエラーになって落ちてしまう。まだまだ研究しないといけないようだ。

2011年5月16日月曜日

iPad2 家族で共有する

リビング用ネット閲覧デバイスであるから、家族全員でiPad2を使い始めた。

要は、お母ちゃんがあまりにもパソコンとかネットとかに弱いので、少しは興味と関心と技能を持たせて、時代に取り残されないようにしよう、というねらい。娘たちはiPhoneユーザでもあるのでiPad2への抵抗感は全く無く、「液晶が大きくて使いやすい」と大喜びをしている。

実際、iPad2の大きい液晶、てきぱきとした動作を経験すると、初代iPhoneであれこれするのがアホらしくなりますわな。(私はあれこれしてないけど(^^;))

ただ、家族全員で使うとなると、twitterやらFaceBookはどうするか、とか、いろいろ問題も出てくる。safari以外のブラウザをいくつか入れて、自分専用のブラウザを決めちゃおうか、とか、twitterクライアントを切り分けようか、とか。

自分用に1台、家族用に1台、なんて話をよく見かけるけど、こういうことなのね。

私の場合はXcodeを使うという大目的があるのでiMacを使わなくなるということはありえないけど、iPad2があったらパソコンを起動している時間が短くなるというのもうなずける楽しさが、たしかにある。

Cocoa FileManager UserDefaultsを調べ始める

かなり順序が逆転しているような気もするが、「Tabで表示中のディレクトリをUserDefaultsに保存する」、「次回起動時にそれを復元してtabを開く」という機能を考える。

とりあえずtabは「rootディレクトリ」で開いておけばいいや、と気軽にやっていたので、ここにきて苦労している。

たいした機能もないくせに、いたずらにViewとかControllerとかをたくさん使っているため、OutlineViewで選択されたディレクトリをTabのタイトルとして表示したり、TabのタイトルからOutlineViewの選択行を復元したり、としようとした時、どのControllerにどんなオブジェクトを渡していくか、常に困っている気がする。

今のところのClass構成はこんな感じ。

ネーミングのセンスないなあ、とがっくりくるけれど仕方がない。各クラスの機能を持たせ方とか、やっぱり自分でコード書いたり、人のコード読んだりしていく中でバランス感覚を学ぶしかないのだろう。

本日は「現在表示中のTabの、ディレクトリ名をUserDefaultsに保存する」ことだけやってみた。
[[NSUserDefaults standardUserDefaults] setInteger:[tabBar tabsCount] forKey:@"TabsCount"];
[[NSUserDefaults standardUserDefaults] setObject:[tabBar tabsTitle] forKey:@"TabsTitle"];

これだけかい?という。(^^;)

tabsTitleはNSArrayで各Tabのタイトル(の元になっているディレクトリ名のフルパス)を返すメソッド。こんな感じ。
-(NSArray*)tabsTitle{
    NSMutableArray *titleArray=[NSMutableArray array];
    NSArray* tabs=[self subviews];
    for (NSInteger i=0; i<[tabs count]; i++) {
        Tab* tab=[tabs objectAtIndex:i];
        [titleArray addObject:[tab title]];
    }
    return [[[NSArray alloc]initWithArray:titleArray]autorelease];
}

NSArrayを保存するのは初めてなのでうまくいってちょっとうれしかった。
現在はNSStringをaddObjectしているが、これを様々な情報をつめこんだNSDictionaryにしていく、と。このあたり、ちゃんとやったことないのでなかなか勉強が進まない。荻原本を読んでいる時間が長くなっている。

UserDefaultsって、環境設定でしかいじったことなかったからなあ。

2011年5月15日日曜日

Cocoa FileManager Tabのタイトル文字列変更

iPad2が到着しても、Cocoaプログラミングは全く飽きていない。おもしろいなあ、とつくづく思う。

Tabのタイトル文字列をやっと変更できるようにした。現在選択しているディレクトリをタイトルとして表示できるのが当たり前だが、それをどうやってやるか1日あれこれ試していた。その成果。

これに手をつけていなかったのは、「OutlineViewでディレクトリを選択」→「TableViewにそのディレクトリの中身を表示」、「TableViewでディレクトリをダブルクリック」→「OutlineViewでそのディレクトリをアクティブなRowにする」という動作ができたら、と思っていたから。独自Viewで一度やっていたけれど、Tabに手を付ける前に独自Viewの描画の遅いことに気づいた、と。

そんなんでやっとTabのタイトルが表示できたので、それをUserDefaultで記録する方法を考えている。
保存したいのは、Tabごとに
1,選択ディレクトリ名
2,tabのindex・・・これはいらないかも
3,OutlineViewのRect
4,OutlineViewの展開状態(・・・いらない?)
5,SplitViewのスプリッタの位置(3があればいらないか?)
6,TableViewの各コラムの幅
7,TableViewの選択行

左側のペインは今後「お気に入り」を格納したOutlineViewを増やすかもしれず、右側のペインにはCollectionViewを増やすかもしれず、当然それらの選択状態も保存したい。

Tabがなければあまり悩まないところだが・・・。もう少し勉強が必要。ドキュメントベースアプリケーションだとWindow毎に保存しているのかなあ。

memo:iPad2に早速インストールしたapp

リビング用ネット閲覧デバイス、としてiPad2を購入した。
本日の午前中、ネットのあちこちでよさそうなアプリを探してみて、とりあえずインストールしたのは次の4つ。


EverNoteにはネットでみかけてよさそうなレシピとかたくさんいれているので。


新聞の天気予報より速報性が高くて便利そうなのでいれてみた。


iPad2はiTunesでアプリ入れるより、iPad2上でそのままインストールしたほうがいいみたい。だから(失礼ながら)このアプリ、予想していたよりずっと便利だということが、少し使ってみたわかった。


ネットで探しだしたレシピを確認するのにいちいちiMac起動していた。しかしこのアプリのおかげでレシピ関係はOKみたい。

あとは本体を起動してネットにつないで、AppStoreを起動したらiBookいる?と素直にインストールした。

買ったのは16G版。音楽やムービーは同期しないつもりなので、アプリだけなら容量は大丈夫かなあ。
ちょっとずつ使っていこう。

ざっと使った感じでは、
1,非常にサクサク動く(本当に気持よく動く)
2,きれいな液晶
3,テーブルに置いたり、カバーをスタンド替わりにして使っても見やすい

ただ、初回起動時から何度かリセットがかかっている。「ゲームセンター」はタップしたら必ずリセット。なんなんでしょ。

iPad2 届く

本日昼前に届いた。

2週間ちょい、かかったことになるが、人気商品ということなので仕方ないとしよう。
13日の夕方、東京を出発したiPad2は、2日後の15日早朝には私の住む街の営業所に届いていたみたい。震災の影響はもうないようだ。

営業所は自宅のすぐそばなので、昼休み直前に配送されたようだ。(^^;)

2011年5月14日土曜日

iPad2 東京に着いてそれから

14日夜の段階で、配送状況はこうなってますな。


昨日の午後6時近くに東京を出て、今はどこにあるのかな。
北海道なんで、これはひょっとすると月曜日になるかも。できれば明日だと時間の余裕があってありがたいんだけど。

FileManager NSTableViewのダブルクリック

ファイル表示をNSTableViwに切り替えた。今まで作っていた実験用プロジェクトがごちゃごちゃになってきたので、新たに実験用プロジェクトを作った・・・わけだが、今までつくってきたクラスを流用するのに「プロジェクトにファイルを追加」した時、今回に限って「ファイルをコピーする」チェックボックスにチェックを入れるのを忘れたため、元ファイルがそのままプロジェクトに追加されてしまった。

それを気づかずにあれこれいじって、変更したくないはずのファイルにまで変更を加えてしまった。で、さらに新しいプロジェクトを作ったりして余計な時間がかかってしまった。ま、お休みだからいいけど。

そんなんで現在の状態。

cocoa bindingは楽でいいなあ。本日初めて知ったのだが、propaty宣言はメソッドでも全然OKだった。こんなことも知らなかったなんて・・・。自分でがっかり。
後日の自分のために書いておくと、

-(NSString*)name
というメソッドは
@propaty NSString* name
と宣言できる、と。メンバ変数しかpropatyにできないのは不便だよなあ、と思って
詳解 Objective-C 2.0 改訂版
荻原 剛志
ソフトバンククリエイティブ
売り上げランキング: 5721
荻原本を読み返したらちゃんと書いてあった。がっくり。

本日はこの状態から、TableViewのダブルクリックを拾うところまで。デベロッパドキュメントを読むと

[tableView setDoubleAction:@selector(mouseDoubleClicked:)];

でいいみたいなんだけど、全然ダブルクリックが拾えず首をかしげるばかり。bindingのDouble click Targetをいじったら拾えるようになったけど、[tableView clickedRow]でクリックされた行が渡ってこない。

うーん、と腕組みしながらあちこちググったところ、

[tableView setTarget:self];

が必要だった。orzこれまたがっくり。基本的なことがまだまだわかっていないので苦労する。
そんなんで本日は「ファイルなら実行」まではなんとか実装できた。明日はディレクトリの時の処理をやってしまおう。

それから今まで腰が引けて避けてきたUserDefaultでのTabの状態の保存と復帰、という予定。どこまでできるかなあ。

2011年5月12日木曜日

Cocoa Controls

本日は夜にPTAの会議のため長らく学校にいた。夕方、仕事が一段落したのでCocoa関係をいろいろググってみる。(もちろん勤務時間はとっくに終わった後であります)

で、とあるblogで教えてもらったのが

Cocoa Controls

検索してもiOSの方が情報多いですが、カスタムコントロールもiOS優勢なようで。数は少ないながら、OSX用のカスタムコントロールやカスタムUIが紹介されている貴重なサイト。

ここで

SFTabView

というカスタムTabをみつけてしまった。Layer使っているようだ。うーん、勉強になりそう。
他にも自分で作るよりずっと便利で使いやすそうなViewがいくつかあって、こんどのお休みに集中していじってみようかなあ、と思う次第。

本日は結局9時近くに帰宅して、Xcodeもサンプルプロジェクトを走らせるのが精一杯というところ。ま、こんな日もあるさ。

BCCollectionView

BCCollectionViewのサンプルプロジェクトをGitHubで公開してくれている親切な人がいた。

aaronbrethorst / BCCollectionView

ざっとコードを眺めてからビルドしてみたところ、たしかに軽快に動く。


コードはほぼこれだけ。
- (NSSize)cellSizeForCollectionView:(BCCollectionView *)collectionView
{
 return NSMakeSize(64, 64);
}

//Return an empty ViewController, this might not be visible to the user immediately
- (NSViewController *)reusableViewControllerForCollectionView:(BCCollectionView *)collectionView
{
 return [[[CellViewController alloc] init] autorelease];
}

//The CollectionView is about to display the ViewController. Use this method to populate the ViewController with data
- (void)collectionView:(BCCollectionView *)collectionView willShowViewController:(NSViewController *)viewController forItem:(id)anItem
{
 CellViewController *cell = (CellViewController*)viewController;
 [cell.imageView setImage:anItem];
}

デリゲートが3つ、その他に表示のようImageを収納するArrayを生成しているくらい。これだけで動くんだからいじってみる価値はありとみた。

Icon表示はこのViewのお世話になる可能性が高いな。

2011年5月11日水曜日

FileManager 独自Viewはおあずけ

以前、OutlineViewの勉強のために作ったプロジェクトは、右側のペインにNSTableViewとNSCollectionViewを表示できるようにしてあったので、本日改めていじってみた。

どちらのViewも/usr/bin以下の1000ファイルを楽々と表示する。やはりあらかじめ用意されているGUIの方がいいか。

GitHubでObjCでプロジェクトを検索してみたところ、

BCCollectionView
というプロジェクトを見つけた。ReadMeによると

BCCollectionView is intended as a replacement for NSCollectionView (and possibly IKImageBrowserView). It is designed to work with a lot of items and only loads the views that it actually needs.

Unlike NSCollectionView, BCCollectionView smoothly displays 300.000+ items.
Every 'cell' in an BCCollectionView is an NSViewController. At the moment these are only uniform; every cell is supposed to be the same NSViewController subclass.

ということで、こちらも使いこなせるか試してみようと思う。
ざっとソースを眺めたら、やっぱりこの手のViewを独自に作るのはまだまだ私には荷が重い、と判断せざるをえない。知らないことが多すぎる。

ただ、あきらめたらそこで試合終了なので、あくまでも独自Viewによるファイル表示は挑戦し続けるつもり。サイコーに楽しい頭の体操なので。

これでふんぎりがついたので、明日からまずNSTableViewを試していこう。もうbinding忘れてるし。(^^;)

それやこれやを調べているうちに、本日も終了。1日が短い。明日は夜にPTAの会議があるから、もっと勤務時間の長い1日になるなあ。

2011年5月10日火曜日

iPad2発送

iPad2、午後9時過ぎに発送のメールが届いていた。注文は4月29日なので、11日後の発送ですな。当初1〜2週間、という予定で、実際の注文受付メールでの発送予定は5月19日。ま、まあまあの早さということか。

ただ荷物到着予定が18日なんだな。(^^;)あまりにも時間がかかりすぎるようなので「配送状況の確認」のリンクをたどったところ、本日、ヤマトは中国は深センで「海外荷物受付」をしたらしい。

ほうほう、これがいつ、どのような経路で我が家まで着くのか興味津々でありますな。国内での受付なら順当にいって13日金曜日あたりで届くはずだけど、中国から来るならもう何日か余分にかかりそう。

いずれにしても楽しみだ。

FileManager 非アクティブ時の表示

Xcode4なら、アプリがアクティブな時はこういう表示になる。

これがフォーカスを失うと、こう表示される。


ToolBarやらTabやら、全部白っぽくなって「私は非アクティブ」とわかるようになっている。

自分でUI部品を作るとこの挙動も自分でコーディングしないといけない。でもまだ手を抜いているので、現在のプロジェクトだと非アクティブ時はこうなってしまう。


Tabと、その下の(これからつくろうとしている)NavigateViewがアクティブ時と同じ色でなので非常にカッコ悪い。

NavigateViewは「ディレクトリを1つ上に移動」とか「戻る」とか「進む」とかのボタンを表示しようとしている「簡易ToolBar」もどき。


このViewをつくり始めて、非アクティブ時の表示についてちょっと作業してみた。
NSAppが非アクティブになる時にNSApplicationWillResignActiveNotification、アクティブになる時にはNSApplicationWillBecomeActiveNotificationというNotificationを通知するので、それをObserveして表示を切り替えてみた。


@selector内で[NSApp isActive]をチェックしてみたけれどうまく判定できないようなので、appIsActiveみたいなインチキメンバを作っておき、それをdrawRectでチェックするようにしてみたらうまくいった。

うまくいったんだけど、これってNSAppのデリゲートになればいいだけの話ですな。UI部品になるクラスは、みんなアプリケーションのデリゲートになっているのかなあ。

というわけで、まだ手をつけていないTabの「非アクティブ時の表示」はNSAppのデリゲートになってやってみる予定。こうやってちょっとずつフレームワークの知識が増えていくのが、プログラミングの面白さでしょうか。

FileManager 画面描画が遅い

ファイルのダブルクリックについて調べているうち、/usr/bin以下を表示させると動作がおかしくなることを発見。

このディレクトリには1000くらいのファイルが置かれているせいらしい。1000くらいのオーダーでだめになるなら、とてもファイルマネージャとは呼べない。

現在のFileCellのdrawRectはこうなっている。(恥を忍んで公開、ということで)
NSRect rect=[self bounds];
    NSPoint point;
    point=NSMakePoint(CONTENT_CELL_LEFT_MARGINE, rect.size.height-CONTENT_CELL_HEIGHT);

    for (NSInteger i=0; i<[contentFileArray count]; i++) {
        FileCell* cell=[contentFileArray objectAtIndex:i];
        NSRect cellFrameRect=NSMakeRect(point.x, point.y,maxCellSize.width,maxCellSize.height);
        [cell drawWithFrame:cellFrameRect inView:self];
        point.y-=maxCellSize.height;
        if (point.y<0) {
            point.y=rect.size.height-maxCellSize.height;
            point.x+=maxCellSize.width+CONTENT_CELL_CENTER_MARGINE+CONTENT_CELL_LEFT_MARGINE;
        
        }
    }

非常にシンプルというか簡単すぎるというか。ファイル(を収めたCell)がいくらあっても、単純に「縦に最大行数まで表示したら、あらかじめ設定してあるCellの幅+マージン分、CellのFrameのorigin.xをずらす」とやっているだけ。現在Cellの幅は決め打ちで350ピクセル。

これで1000個のファイルがあると、縦に20行表示できるとしたら横の桁は単純に計算して50桁。Viewのframeは350×50で17500ピクセルの横幅(^^;)。

drawRectが呼ばれるたびにこれだけの大きさのViewを描画していたら、そりゃおそくもなるわな。

- (void)drawRect:(NSRect)dirtyRectのdirtyRectだけを描画するようにするか、clipViewの大きさで表示できるだけのCellを描画するようにするか、表示を「ページ」単位にして(もちろんページの大きさの計算は自分でやらないといけない)してしまうか。

Viewの表示の高速化はGUIプログラミングの肝だから、たくさんのサンプルがあちこちころがっている気もするが・・・。当面、「描画の高速化」を研究することになりそうだ。

NSTableViewを使うことにすればこういう問題からは解放されるんだろうなあ、と耳許で囁く声もきこえるぞ。(^^;)

2011年5月9日月曜日

Cocoa FileManager Cellのダブルクリック・ファイルの場合

bloggerのエディタを旧版にしたら無事編集できた。よかったよかった。

さて、ディレクトリではなくてファイルをダブルクリックした場合。
これはもう

[NSWorkspace sharedWorkspace]openURL:

または

[NSWorkspace sharedWorkspace]openFile:

でOK、と。
ただしいくつか問題点があって、一つ目は.appの扱い。もともと.appディレクトリのリソースを手軽にのぞくために作っているToolだから、ディレクトリとして扱っていいわけだが、アプリの起動ができないのではやはり片手落ちだろう。

OutlineViewはディレクトリ表示用のViewなので、ここからの起動は一切しない。FileCellView上でアプリを起動するとしたら・・・右クリックか。あるいは左クリック長押しとか。この辺はもう少し検討することにしよう。

同様にいわゆる「コマンドライン実行ファイル」をどうするか。当然ターミナルを開いて実行するのがベストなんだろうけど。現在もダブルクリックするとターミナルを開いて実行するけど、すぐにターミナルが消えるか、終了した状態で止まっているか、Xcode4のdebugターミナルにエラーが表示されるか、いずれかの状態で実用にならない。コマンドラインで実行するなら当然のように引数を与えられるようにしなければいけないだろう。そのUIとかをどうするか。

コマンドラインの扱いは自分としてはかなり優先順位が低いなー。

bloggerのエディタが変・本文が編集できない

2011年5月8日日曜日

Cocoa FileManager Tab調整

もう少ししたらToolBarをつける予定。そこで現在の状態でどんな見た目になるか試してみる。

うむー、がんばって下から生えてくるTabにしたかったんだけど、こりゃかなり見た目が悪い。Tabの下の部分にセパレータ入れたのが余計な作業だったかも。

ここはがんばって、今の段階で修正したほうがいいだろう、ということで、今日の夕方からTabの描き直しをしてみた。
2時間ほどの作業の結果がこれ。


すこしすっきりしたかな。
ちなみにXcode4のTabはこうなってます。


影の付け方とか、色の感じとか、やっぱ素人とは違いますわな。LionでこのTabコントロールがAPI公開されたらうれしいんだけど。