source: trunk/PrefsPane/src/AlertHelper.m @ 1046

Revision 1046, 6.7 KB checked in by speck, 3 days ago (diff)

printf %d formatting fixes.
1.5b23

Line 
1/* Copyright (C) 2008-2009 Peter Speck
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#import "AlertHelper.h"
18#import "GBDebug.h"
19
20@interface AlertHelper ()
21
22- (void)releaseDelegate;
23- (BOOL)checkHasPreparedAlert:(NSString*)doingWhat;
24
25
26- (void)simpleAlertDidEnd:(NSAlert *)alert returnCode:(int)returnCode
27              contextInfo:(void *)contextInfo;
28
29@end
30
31//=======================================================================================================
32
33@implementation AlertHelper
34
35- (id)initWindowView:(NSView*)windowView
36        withGbBundle:(NSBundle*)gbBundle
37{
38    if ((self = [super init])) {
39        _windowView = [windowView retain];
40        NSString* iconPath = [gbBundle pathForResource:@"tangerine" ofType:@"icns"];
41        NSAssert(iconPath, @"Missing tangerine.icns");
42        _glimmerIcon = [[[NSImage alloc] initWithContentsOfFile:iconPath] retain];
43    }
44    return self;
45}
46
47- (void)dealloc
48{
49    [_glimmerIcon release];
50    [_windowView release];
51    [_accessoryView release];
52    [super dealloc];
53}
54
55- (NSWindow*)window
56{
57    return [_windowView window];
58}
59
60- (BOOL)canDisplayAlert
61{
62    return !_alertIsOpen && [_windowView window];
63}
64
65#pragma mark ------------------------ private
66
67- (void)releaseDelegate
68{
69    [_callbackDelegate release];
70    _callbackDelegate = NULL;
71    _callbackSelector = NULL;
72}
73
74- (void)dismissAlert
75{
76    DebugNSLog(@"dismissAlert, open = %d", _alertIsOpen);
77    [self dismissAlertWithInvokeDelegate:NO withReturnCode:0];
78}
79
80- (void)dismissAlertWithInvokeDelegate:(BOOL)callDelegate withReturnCode:(NSInteger)returnCode
81{
82    if (!_alertIsOpen)
83        return;
84    DebugNSLog(@"dismissAlertWithInvokeDelegate, isOpen=%d, callDelegate=%d, returnCode=%ld", _alertIsOpen, callDelegate, (long)returnCode);
85    _alertIsOpen = NO; // otherwise the method is called recursively by simpleAlertDidEnd
86    _lastAlertReturnCode = returnCode;
87    /*
88     Make the alert sheet go away before the delegate is called, so the delegate is able to show another sheet.
89     Must call [NSApp endSheet] to get the sheet really gone, otherwise we can't show another sheet.
90     [orderOut] performs the animation.
91    */
92    if (_usingSheet) {
93        [NSApp endSheet:[_alert window]];
94        [[_alert window] orderOut:self];
95        _usingSheet = NO;
96    }
97    if (callDelegate && _callbackDelegate) {
98        // http://theocacao.com/document.page/264
99        NSMethodSignature* sig = [[_callbackDelegate class] instanceMethodSignatureForSelector:_callbackSelector];
100        NSInvocation* invo = [NSInvocation invocationWithMethodSignature:sig];
101        [invo setTarget:_callbackDelegate];
102        [invo setSelector:_callbackSelector];
103        [invo setArgument:&returnCode atIndex:2];
104        [invo invoke];
105        [self releaseDelegate];
106    }
107    [_alert autorelease];
108    _alert = NULL;
109    [_accessoryView autorelease];
110    _accessoryView = NULL;
111}
112
113- (NSInteger)lastAlertReturnCode
114{
115    return _lastAlertReturnCode;
116}
117
118- (void)simpleAlertDidEnd:(NSAlert *)alert returnCode:(int)returnCode
119              contextInfo:(void *)contextInfo
120{
121    if (alert == _alert)
122        [self dismissAlertWithInvokeDelegate:YES withReturnCode:returnCode];
123}
124
125- (BOOL)checkHasPreparedAlert:(NSString*)doingWhat
126{
127    if (!_alert) {
128        NSLog(@"Can't %@ when no alert has been prepared.", doingWhat);
129        [GBDebug debugDumpStackframe];
130        return NO;
131    }
132    if (_alertIsOpen) {
133        NSLog(@"Can't %@ when alert already is open.", doingWhat);
134        [GBDebug debugDumpStackframe];
135        return NO;
136    }
137    return YES;
138}
139
140
141#pragma mark ------------------------ building blocks
142
143- (void)prepareWarningAlertWithTitle:(NSString*)title
144              withInformativeText:(NSString*)infoText
145{
146    [self prepareAlertWithTitle:title withInformativeText:infoText withStyle:NSWarningAlertStyle];
147}
148
149- (void)prepareCriticalAlertWithTitle:(NSString*)title
150               withInformativeText:(NSString*)infoText
151{
152    [self prepareAlertWithTitle:title withInformativeText:infoText withStyle:NSCriticalAlertStyle];
153}
154
155- (void)prepareInformativeAlertWithTitle:(NSString*)title
156                  withInformativeText:(NSString*)infoText
157{
158    [self prepareAlertWithTitle:title withInformativeText:infoText withStyle:NSInformationalAlertStyle];
159}
160
161- (void)prepareAlertWithTitle:(NSString*)title
162          withInformativeText:(NSString*)infoText
163                    withStyle:(NSAlertStyle)alertStyle
164{
165    if (_alertIsOpen) {
166        [GBDebug debugDumpStackframe];
167        NSLog(@"Can't prepare another alert while an alert is open.");
168        return;
169    }
170    if (!title) {
171        [GBDebug debugDumpStackframe];
172        NSLog(@"the title must not be NULL");
173        title = @"?"; // better than crashing with NSAssert.
174    }
175    if (!_alert) {
176        _alert = [[NSAlert alloc] init]; // release in delegate
177        [_alert setIcon:_glimmerIcon];
178    }
179    [_alert setMessageText:title];
180    if (infoText) // NSAlert can't handle NULL
181        [_alert setInformativeText:infoText];
182}
183
184- (void)setDelegate:(NSObject*)callbackDelegate
185       withSelector:(SEL)callbackSelector
186{
187    NSAssert((_callbackDelegate != NULL) == (_callbackSelector != NULL), @"_callbackDelegate / _callbackSelector");
188    if (![self checkHasPreparedAlert:@"set delegate"])
189        return;
190    [self releaseDelegate];
191    _callbackDelegate = [callbackDelegate retain];
192    _callbackSelector = callbackSelector;
193}
194
195- (NSButton*)addButtonWithTitle:(NSString*)title
196{
197    if (!title) {
198        [GBDebug debugDumpStackframe];
199        NSLog(@"the button title must not be NULL");
200        title = @"?"; // better than crashing with NSAssert.
201    }
202    if (![self checkHasPreparedAlert:@"add button"])
203        return NULL;
204    return [_alert addButtonWithTitle:title];
205}
206
207- (void)setAccessoryView:(NSView*)view
208{
209    if (!view) {
210        [GBDebug debugDumpStackframe];
211        NSLog(@"the view param must not be NULL");
212        return;
213    }
214    if (![self checkHasPreparedAlert:@"set accessory view"])
215        return;
216    if (view == _accessoryView)
217        return;
218    NSView* oldView = _accessoryView;
219    _accessoryView = [view retain];
220    [_alert setAccessoryView:view];
221    [oldView release];
222}
223
224- (void)layoutAlert
225{
226    if (![self checkHasPreparedAlert:@"layout alert"])
227        return;
228    [_alert layout];
229}
230
231- (void)showPreparedAlert
232{
233    if (![self checkHasPreparedAlert:@"show alert"])
234        return;
235    NSWindow* window = [self window];
236    _alertIsOpen = YES;
237    if (!window) {
238        NSInteger returnCode = [_alert runModal];
239        [self dismissAlertWithInvokeDelegate:YES withReturnCode:returnCode];
240        return;
241    }
242    _usingSheet = YES;
243    [_alert beginSheetModalForWindow:window
244                      modalDelegate:self
245                     didEndSelector:@selector(simpleAlertDidEnd:returnCode:contextInfo:)
246                        contextInfo:NULL];
247}
248
249@end
Note: See TracBrowser for help on using the repository browser.