1//
2//  FileRenameSheetController.m
3//  Transmission
4//
5//  Created by Mitchell Livingston on 1/20/13.
6//  Copyright (c) 2013 The Transmission Project. All rights reserved.
7//
8
9#import "FileRenameSheetController.h"
10#import "FileListNode.h"
11#import "Torrent.h"
12
13typedef void (^CompletionBlock)(BOOL);
14
15@interface FileRenameSheetController ()
16
17@property (nonatomic, strong) Torrent * torrent;
18@property (nonatomic, strong) FileListNode * node;
19@property (nonatomic, copy) CompletionBlock completionHandler;
20
21@property (nonatomic, copy) NSString * originalName;
22
23@end
24
25@implementation FileRenameSheetController
26
27#warning remove ivars in header when 64-bit only (or it compiles in 32-bit mode)
28@synthesize torrent = _torrent;
29@synthesize node = _node;
30@synthesize completionHandler = _completionHandler;
31@synthesize originalName = _originalName;
32@synthesize labelField = _labelField;
33@synthesize inputField = _inputField;
34@synthesize renameButton = _renameButton;
35@synthesize cancelButton = _cancelButton;
36
37+ (void) presentSheetForTorrent: (Torrent *) torrent modalForWindow: (NSWindow *) window completionHandler: (void (^)(BOOL didRename)) completionHandler
38{
39    NSParameterAssert(torrent != nil);
40    NSParameterAssert(window != nil);
41
42    FileRenameSheetController * renamer = [[FileRenameSheetController alloc] initWithWindowNibName: @"FileRenameSheetController"];
43
44    renamer.torrent = torrent;
45    renamer.completionHandler = completionHandler;
46
47    [NSApp beginSheet: [renamer window] modalForWindow: window modalDelegate: self didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:) contextInfo: (__bridge_retained void *)(renamer)];
48}
49
50+ (void) presentSheetForFileListNode: (FileListNode *) node modalForWindow: (NSWindow *) window completionHandler: (void (^)(BOOL didRename)) completionHandler
51{
52    NSParameterAssert(node != nil);
53    NSParameterAssert(window != nil);
54
55    FileRenameSheetController * renamer = [[FileRenameSheetController alloc] initWithWindowNibName: @"FileRenameSheetController"];
56
57    renamer.torrent = [node torrent];
58    renamer.node = node;
59    renamer.completionHandler = completionHandler;
60
61    [NSApp beginSheet: [renamer window] modalForWindow: window modalDelegate: self didEndSelector: @selector(sheetDidEnd:returnCode:contextInfo:) contextInfo: (__bridge_retained void *)(renamer)];
62}
63
64+ (void) sheetDidEnd: (NSWindow *) sheet returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo
65{
66    FileRenameSheetController * renamer = (__bridge_transfer FileRenameSheetController *)(contextInfo);
67    NSParameterAssert([renamer isKindOfClass:[FileRenameSheetController class]]);
68
69    renamer.completionHandler(returnCode == NSOKButton);
70
71    [sheet orderOut: self];
72}
73
74
75- (void) windowDidLoad
76{
77    [super windowDidLoad];
78
79    self.originalName = [self.node name] ?: [self.torrent name];
80    NSString * label = [NSString stringWithFormat: NSLocalizedString(@"Rename the file \"%@\":", "rename sheet label"), self.originalName];
81    [self.labelField setStringValue: label];
82
83    [self.inputField setStringValue: self.originalName];
84    [self.renameButton setEnabled: NO];
85
86    //resize the buttons so that they're long enough and the same width
87    const NSRect oldRenameFrame = [self.renameButton frame];
88    const NSRect oldCancelFrame = [self.cancelButton frame];
89
90    //get the extra width of the rename button from the English xib - the width from sizeToFit is too squished
91    [self.renameButton sizeToFit];
92    const CGFloat extra = NSWidth(oldRenameFrame) - NSWidth([self.renameButton frame]);
93
94    [self.renameButton setTitle: NSLocalizedString(@"Rename", "rename sheet button")];
95    [self.cancelButton setTitle: NSLocalizedString(@"Cancel", "rename sheet button")];
96
97    [self.renameButton sizeToFit];
98    [self.cancelButton sizeToFit];
99    NSRect newRenameFrame = [self.renameButton frame];
100    NSRect newCancelFrame = [self.cancelButton frame];
101    newRenameFrame.size.width = MAX(NSWidth(newRenameFrame), NSWidth(newCancelFrame)) + extra;
102    newCancelFrame.size.width = MAX(NSWidth(newRenameFrame), NSWidth(newCancelFrame)) + extra;
103
104    const CGFloat renameWidthIncrease = NSWidth(newRenameFrame) - NSWidth(oldRenameFrame);
105    newRenameFrame.origin.x -= renameWidthIncrease;
106    [self.renameButton setFrame:newRenameFrame];
107
108    const CGFloat cancelWidthIncrease = NSWidth(newCancelFrame) - NSWidth(oldCancelFrame);
109    newCancelFrame.origin.x -= renameWidthIncrease + cancelWidthIncrease;
110    [self.cancelButton setFrame:newCancelFrame];
111}
112
113- (IBAction) rename: (id) sender
114{
115    void (^completionHandler)(BOOL) = ^(BOOL didRename) {
116        if (didRename)
117            [NSApp endSheet: [self window] returnCode: NSOKButton];
118        else
119        {
120            #warning more thorough error
121            NSBeep();
122        }
123    };
124
125    if (self.node)
126        [self.torrent renameFileNode: self.node withName: [self.inputField stringValue] completionHandler: completionHandler];
127    else
128        [self.torrent renameTorrent: [self.inputField stringValue] completionHandler: completionHandler];
129}
130
131- (IBAction) cancelRename: (id) sender
132{
133    [NSApp endSheet: [self window] returnCode: NSCancelButton];
134}
135
136- (void) controlTextDidChange: (NSNotification *) notification
137{
138    [self.renameButton setEnabled: ![[self.inputField stringValue] isEqualToString: @""] && ![[self.inputField stringValue] isEqualToString: self.originalName]];
139}
140
141@end
142