ファイルを保存する場所を選べる様にする
バージョン1.2.2でファイルを保存する場所を選べる様にしましたので、これの説明をします。
インターフェイスファイルの変更
ユーザが選択したパスを表示するテキストフィールドを追加するので、そのアウトレットを追加します。
パスを覚えておく変数ですが、固定ではなく書き換えられないといけないのでNSStringをNSMutableStringに変更します。
またユーザが保存場所を選ぶ時にボタンを押すので、それを受けるアクションを追加します。
@class RepeatingMotif;
@interface RepeatingMotifSaverView : ScreenSaverView
{
IBOutlet id optionWindow;
IBOutlet id randomizer,generator;
IBOutlet id optionWindowTabView;
IBOutlet id creditTextView;
IBOutlet id directoryText;
BOOL fixToLayerMax,saveToFile,enableSaveToFile;
BOOL preview;
BOOL saveMarkedOnly,marked,playClick;
int counter,transition,hold,layerMax;
int selectedIndex;
NSImage *image;
NSMutableString *directory;
NSMutableArray *masterMotifs,*repeatingMotifs;
RepeatingMotif *repeatingMotif;
}
- (IBAction)closeOptionWindow:(id)sender;
- (IBAction)selectDirectoryToSaveFile:(id)sender;
@end
デフォルトデータベースから読み込んで初期化する
これまでは初期化メソッドで、ファイルを保存するパスをある決まった場所に設定していましたが、これをデフォルトデータベースから読み込む処理に変更します。
- (id)initWithFrame:(NSRect)frame isPreview:(BOOL)isPreview
{
self = [super initWithFrame:frame isPreview:isPreview];
if(self)
{
ScreenSaverDefaults *ssd = [ScreenSaverDefaults
defaultsForModuleWithName:RMSModuleName];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSLibraryDirectory, NSUserDomainMask, YES);
[self setAnimationTimeInterval:1/10.0];
[NSBundle loadNibNamed:RMSResourceName owner:self];
transition = [ssd integerForKey:@"transition"];
hold = [ssd integerForKey:@"hold"];
layerMax = [ssd integerForKey:@"layerMax"];
fixToLayerMax = [ssd boolForKey:@"fixToLayerMax"];
selectedIndex = [ssd integerForKey:@"selectedIndex"];
saveToFile = [ssd boolForKey:@"saveToFile"];
saveMarkedOnly = [ssd boolForKey:@"saveMarkedOnly"];
playClick = [ssd boolForKey:@"playClick"];
enableSaveToFile = YES;
preview = isPreview;
masterMotifs = repeatingMotifs = nil;
repeatingMotif = nil;
directory = [[NSString stringWithFormat:@"%@/%@",
[paths objectAtIndex:0], RMSDirectoryName] retain];
directory = [[NSMutableString alloc]
initWithString:[ssd stringForKey:@"directory"]];
if(![fileManager fileExistsAtPath:directory])
[fileManager createDirectoryAtPath:directory
attributes:nil];
}
return self;
}
なお、初回は読み込もうにも何もありませんので"UserDefaults.plist"にデフォルトの場所を追加しておく必要があります。
<key>directory</key>
<string>~/Library/Repeating Motif Saver</string>
アクションを追加する
インターフェイスファイルで追加したアクションを実装します。やっている事はオープンパネルを用意して、それにオプションを設定し、runModalで実行しているだけです。OKならパスを保存する変数とテキストフィールドを更新します。
このアクションが呼び出される時は、スクリーンセーバの設定をシステム環境設定のウィンドウにぶら下がっているシートで行なっている訳ですから、モーダルダイアログで処理を実行するしかありません。
オープンパネルの設定は、
- ファイル選択:不可
- 複数選択:不可
- ディレクトリ選択:可
- ディレクトリ作成:可
です。
- (void)selectDirectoryToSaveFile:(id)sender
{
int result;
NSOpenPanel *openPanel = [NSOpenPanel openPanel];
[openPanel setCanChooseFiles:NO];
[openPanel setAllowsMultipleSelection:NO];
[openPanel setCanChooseDirectories:YES];
[openPanel setCanCreateDirectories:YES];
result = [openPanel runModal];
if(result == NSFileHandlingPanelOKButton)
{
[directory setString:[openPanel directory]];
[directoryText setStringValue:directory];
}
}
シート表示前の処理
シートを表示する前に、現在選択されているパスをテキストフィールドにセットする処理を追加します。
- (NSWindow *)configureSheet
{
[NSBundle loadNibNamed:RMSResourceName owner:self];
[optionWindowTabView selectTabViewItemAtIndex:selectedIndex];
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSAttributedString *creditsString =
[[NSAttributedString alloc]
initWithPath:[bundle pathForResource:@"Credits"
ofType:@"rtf"]
documentAttributes:nil];
[[creditTextView textStorage] setAttributedString:creditsString];
[creditsString release];
[creditTextView setBackgroundColor:
[NSColor windowBackgroundColor]];
[directoryText setStringValue:directory];
return optionWindow;
}
シート表示後の処理
シートを閉じるときに、選択されたパスをデフォルトデータベースに書き込む処理を追加します。
- (void)closeOptionWindow:(id)sender
{
ScreenSaverDefaults *ssd = [ScreenSaverDefaults
defaultsForModuleWithName:RMSModuleName];
[ssd setInteger:transition forKey:@"transition"];
[ssd setInteger:hold forKey:@"hold"];
[ssd setInteger:layerMax forKey:@"layerMax"];
[ssd setBool:fixToLayerMax forKey:@"fixToLayerMax"];
[ssd setInteger:selectedIndex forKey:@"selectedIndex"];
[ssd setBool:saveToFile forKey:@"saveToFile"];
[ssd setBool:saveMarkedOnly forKey:@"saveMarkedOnly"];
[ssd setBool:playClick forKey:@"playClick"];
[ssd setObject:directory forKey:@"directory"];
[randomizer writeToDefaults];
[ssd synchronize];
[NSApp endSheet:optionWindow];
}
Interface Builderでの作業
後はInterface Builderでテキストフィールドとボタンを追加し、アウトレットとアクションを接続すれば完成です。見えないですが、ボタンの左側にテキストフィールドを追加してあります。
部品が色々と増えてきたので、タブを一つ増やして保存に関する設定を独立させました。
ちなみにテキストフィールドの設定では、Line BreakingをTruncate Headにしています。パスが長い場合、末尾が省略されてしまうよりも先頭が省略された方がよいという判断です。