Bug Summary

File:Frameworks/Adium Framework/Source/ESTextAndButtonsWindowController.m
Location:line 369, column 2
Description:dead store

Annotated Source Code

1/*
2 * Adium is the legal property of its developers, whose names are listed in the copyright file included
3 * with this source distribution.
4 *
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11 * Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 */
16
17#import <Adium/ESTextAndButtonsWindowController.h>
18
19#define TEXT_AND_BUTTONS_WINDOW_NIB @"TextAndButtonsWindow"
20
21@interface ESTextAndButtonsWindowController (PRIVATE)
22- (void)configureWindow;
23@end
24
25@implementation ESTextAndButtonsWindowController
26
27/*!
28 * @brief Show a text and buttons window which will notify a target when a button is clicked or the window is closed.
29 *
30 * The buttons have titles of defaultButton, alternateButton, and otherButton.
31 * The buttons are laid out on the lower-right corner of the window, with defaultButton on the right, alternateButton on
32 * the left, and otherButton in the middle.
33 *
34 * If defaultButton is nil or an empty string, a default localized button title (“OK” in English) is used.
35 * For the remaining buttons, the window displays them only if their corresponding button title is non-nil.
36 *
37 * @param inTitle Window title
38 * @param inDefaultButton Rightmost button. Localized OK if nil.
39 * @param inAlternateButton Leftmost button. Hidden if nil.
40 * @param inOtherButton Middle button. Hidden if nil. inAlternateButton must be non-nil for inOtherButton to be used.
41 * @param parentWindow Window on which to display as a sheet. Displayed as a normal window if nil.
42 * @param inMessageHeader A plain <tt>NSString</tt> which will be displayed as a bolded header for the message. Hidden if nil.
43 * @param inMessage The <tt>NSAttributedString</tt> which is the body of text for the window.
44 * @param inImage The NSImage to display; if nil, the default application icon will be shown
45 * @param inTarget The target to send the selector <tt>textAndButtonsWindowDidEnd:(NSWindow *)window returnCode:(AITextAndButtonsReturnCode)returnCode userInfo:(id)userInfo</tt> when the sheet ends.
46 * @param inUserInfo User info which will be passed back to inTarget
47 *
48 * @see AITextAndButtonsReturnCode
49 *
50 * @result A retained <tt>ESTextAndButtonsWindowController</tt> which will handle releasing itself when the window is finished.
51 */
52+ (id)showTextAndButtonsWindowWithTitle:(NSString *)inTitle
53 defaultButton:(NSString *)inDefaultButton
54 alternateButton:(NSString *)inAlternateButton
55 otherButton:(NSString *)inOtherButton
56 onWindow:(NSWindow *)parentWindow
57 withMessageHeader:(NSString *)inMessageHeader
58 andMessage:(NSAttributedString *)inMessage
59 image:(NSImage *)inImage
60 target:(id)inTarget
61 userInfo:(id)inUserInfo
62{
63 ESTextAndButtonsWindowController *controller;
64
65 controller = [[self alloc] initWithWindowNibName:TEXT_AND_BUTTONS_WINDOW_NIB@ "TextAndButtonsWindow"];
66 [controller changeWindowToTitle:inTitle
67 defaultButton:inDefaultButton
68 alternateButton:inAlternateButton
69 otherButton:inOtherButton
70 withMessageHeader:inMessageHeader
71 andMessage:inMessage
72 image:inImage
73 target:inTarget
74 userInfo:inUserInfo];
75
76 if (parentWindow) {
77 [NSApp beginSheet:[controller window]
78 modalForWindow:parentWindow
79 modalDelegate:controller
80 didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
81 contextInfo:nil0];
82
83 } else {
84 [controller show];
85 }
86
87 return controller;
88}
89
90+ (id)showTextAndButtonsWindowWithTitle:(NSString *)inTitle
91 defaultButton:(NSString *)inDefaultButton
92 alternateButton:(NSString *)inAlternateButton
93 otherButton:(NSString *)inOtherButton
94 onWindow:(NSWindow *)parentWindow
95 withMessageHeader:(NSString *)inMessageHeader
96 andMessage:(NSAttributedString *)inMessage
97 target:(id)inTarget
98 userInfo:(id)inUserInfo
99{
100 return [self showTextAndButtonsWindowWithTitle:inTitle
101 defaultButton:inDefaultButton
102 alternateButton:inAlternateButton
103 otherButton:inOtherButton
104 onWindow:parentWindow
105 withMessageHeader:inMessageHeader
106 andMessage:inMessage
107 image:nil0
108 target:inTarget
109 userInfo:inUserInfo];
110}
111
112+ (id)controller
113{
114 return [[self alloc] initWithWindowNibName:TEXT_AND_BUTTONS_WINDOW_NIB@ "TextAndButtonsWindow"];
115}
116
117/*!
118 * @brief Change and show a text and buttons window which will notify a target when a button is clicked or the window is closed.
119 *
120 * The buttons have titles of defaultButton, alternateButton, and otherButton.
121 * The buttons are laid out on the lower-right corner of the window, with defaultButton on the right, alternateButton on
122 * the left, and otherButton in the middle.
123 *
124 * If defaultButton is nil or an empty string, a default localized button title (“OK” in English) is used.
125 * For the remaining buttons, the window displays them only if their corresponding button title is non-nil.
126 *
127 * @param inTitle Window title
128 * @param inDefaultButton Rightmost button. Localized OK if nil.
129 * @param inAlternateButton Leftmost button. Hidden if nil.
130 * @param inOtherButton Middle button. Hidden if nil. inAlternateButton must be non-nil for inOtherButton to be used.
131 * @param inMessageHeader A plain <tt>NSString</tt> which will be displayed as a bolded header for the message. Hidden if nil.
132 * @param inMessage The <tt>NSAttributedString</tt> which is the body of text for the window.
133 * @param inImage The NSImage to display; if nil, the default application icon will be shown
134 * @param inTarget The target to send the selector <tt>textAndButtonsWindowDidEnd:(NSWindow *)window returnCode:(AITextAndButtonsReturnCode)returnCode userInfo:(id)userInfo</tt> when the sheet ends.
135 * @param inUserInfo User info which will be passed back to inTarget
136 *
137 * @see AITextAndButtonsReturnCode
138 */
139- (void)changeWindowToTitle:(NSString *)inTitle
140 defaultButton:(NSString *)inDefaultButton
141 alternateButton:(NSString *)inAlternateButton
142 otherButton:(NSString *)inOtherButton
143 withMessageHeader:(NSString *)inMessageHeader
144 andMessage:(NSAttributedString *)inMessage
145 image:(NSImage *)inImage
146 target:(id)inTarget
147 userInfo:(id)inUserInfo
148{
149 [title release];
150 [defaultButton release];
151 [alternateButton release];
152 [otherButton release];
153 [messageHeader release];
154 [message release];
155 [target release];
156 [userInfo release];
157 [image release];
158
159 title = [inTitle retain];
160 defaultButton = [inDefaultButton retain];
161 alternateButton = ([inAlternateButton length] ? [inAlternateButton retain] : nil0);
162 otherButton = ([inOtherButton length] ? [inOtherButton retain] : nil0);
163 messageHeader = ([inMessageHeader length] ? [inMessageHeader retain] : nil0);
164 message = [inMessage retain];
165 target = [inTarget retain];
166 userInfo = [inUserInfo retain];
167 image = [inImage retain];
168
169 userClickedButton = NO( BOOL ) 0;
170 allowsCloseWithoutResponse = YES( BOOL ) 1;
171 [self configureWindow];
172}
173
174- (void)show
175{
176 [self showWindow:nil0];
177 [[self window] orderFront:nil0];
178}
179
180/*!
181 * @brief Can the window be closed without clicking one of the buttons?
182 */
183- (void)setAllowsCloseWithoutResponse:(BOOL)inAllowsCloseWithoutResponse
184{
185 allowsCloseWithoutResponse = inAllowsCloseWithoutResponse;
186
187 [[[self window] standardWindowButton:NSWindowCloseButton] setEnabled:allowsCloseWithoutResponse];
188}
189
190/*!
191 * @brief Set the image
192 */
193- (void)setImage:(NSImage *)inImage;
194{
195 if (inImage != image) {
196 [image release];
197 image = [inImage retain];
198 [imageView setImage:image];
199 }
200}
201
202- (void)setKeyEquivalent:(NSString *)keyEquivalent modifierMask:(unsigned int)mask forButton:(AITextAndButtonsWindowButton)windowButton
203{
204 NSButton *button = nil0;
205 switch (windowButton) {
206 case AITextAndButtonsWindowButtonDefault:
207 button = button_default;
208 break;
209
210 case AITextAndButtonsWindowButtonAlternate:
211 button = button_alternate;
212 break;
213
214 case AITextAndButtonsWindowButtonOther:
215 button = button_other;
216 break;
217 }
218
219 [button setKeyEquivalent:keyEquivalent];
220 [button setKeyEquivalentModifierMask:mask];
221}
222
223/*!
224 * @brief Refuse to let the window close, if allowsCloseWithoutResponse = NO
225 */
226- (BOOL)windowShouldClose:(id)sender
227{
228 if (!userClickedButton) {
229 if (allowsCloseWithoutResponse) {
230 //Notify the target that the window closed with no response
231 [target textAndButtonsWindowDidEnd:[self window]
232 returnCode:AITextAndButtonsClosedWithoutResponse
233 userInfo:userInfo];
234 } else {
235 //Don't allow the close
236 NSBeep();
237 return NO( BOOL ) 0;
238 }
239 }
240
241 return YES( BOOL ) 1;
242}
243
244/*!
245 * @brief Perform behaviors before the window closes
246 *
247 * If the user did not click a button to get us here, inform the target that the window closed
248 * with no response, sending it the AITextAndButtonsClosedWithoutResponse return code (default behavior)
249 *
250 * As our window is closing, we auto-release this window controller instance.
251 */
252- (void)windowWillClose:(id)sender
253{
254 [super windowWillClose:sender];
255
256 [self autorelease];
257
258 //Release our target immediately to avoid a potential mutual retain (if the target is retaining us)
259 [target release]; target = nil0;
260}
261
262/*!
263 * @brief Invoked as the sheet closes, dismiss the sheet
264 */
265- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
266{
267 [sheet orderOut:nil0];
268}
269
270/*!
271 * @brief Configure the window.
272 *
273 * Here we perform configuration and autosizing for our message and buttons.
274 */
275
276- (void)configureWindow
277{
278 NSWindow *window = [self window];
279 int heightChange = 0;
280 int distanceFromBottomOfMessageToButtons = 24;
281 NSRect windowFrame = [window frame];
282
283 //Set the image if we have one
284 if (image) {
285 [imageView setImage:image];
286 }
287
288 //Hide the toolbar and zoom buttons
289 [[window standardWindowButton:NSWindowToolbarButton] setFrame:NSZeroRect];
290 [[window standardWindowButton:NSWindowZoomButton] setFrame:NSZeroRect];
291
292 //Title
293 if (title) {
294 [window setTitle:title];
295 } else {
296 [window setExcludedFromWindowsMenu:YES( BOOL ) 1];
297 }
298
299 //Message header
300 if (messageHeader) {
301 NSRect messageHeaderFrame = [scrollView_messageHeader frame];
302
303 //Resize the window frame to fit the error title
304 [textView_messageHeader setVerticallyResizable:YES( BOOL ) 1];
305 [textView_messageHeader setDrawsBackground:NO( BOOL ) 0];
306 [scrollView_messageHeader setDrawsBackground:NO( BOOL ) 0];
307 [textView_messageHeader setString:messageHeader];
308
309 [textView_messageHeader sizeToFit];
310 heightChange += [textView_messageHeader frame].size.height - [scrollView_messageHeader documentVisibleRect].size.height;
311 messageHeaderFrame.size.height += heightChange;
312 messageHeaderFrame.origin.y -= heightChange;
313
314 [scrollView_messageHeader setFrame:messageHeaderFrame];
315
316 } else {
317 NSRect messageHeaderFrame = [scrollView_messageHeader frame];
318 NSRect scrollFrame = [scrollView_message frame];
319
320 //Remove the header area
321 if ([scrollView_messageHeader respondsToSelector:@selector(setHidden:)]) {
322 [scrollView_messageHeader setHidden:YES( BOOL ) 1];
323 } else {
324 [scrollView_messageHeader setFrame:NSZeroRect];
325 }
326
327 //verticalChange is how far we can move our message area up since we don't have a messageHeader
328 int verticalChange = (messageHeaderFrame.size.height +
329 (messageHeaderFrame.origin.y - (scrollFrame.origin.y+scrollFrame.size.height)));
330
331 scrollFrame.size.height += verticalChange;
332
333 [scrollView_message setFrame:scrollFrame];
334 }
335
336 //Set the message, then change the window size accordingly
337 {
338 int messageHeightChange;
339
340 [textView_message setVerticallyResizable:YES( BOOL ) 1];
341 [textView_message setDrawsBackground:NO( BOOL ) 0];
342 [scrollView_message setDrawsBackground:NO( BOOL ) 0];
343
344 [[textView_message textStorage] setAttributedString:message];
345 [textView_message sizeToFit];
346 messageHeightChange = [textView_message frame].size.height - [scrollView_message documentVisibleRect].size.height;
347 heightChange += messageHeightChange;
348
349 /* distanceFromBottomOfMessageToButtons pixels from the original bottom of scrollView_message to the
350 * proper positioning above the buttons; after that, the window needs to expand.
351 */
352 if (heightChange > distanceFromBottomOfMessageToButtons) {
353 windowFrame.size.height += (heightChange - distanceFromBottomOfMessageToButtons);
354 windowFrame.origin.y -= (heightChange - distanceFromBottomOfMessageToButtons);
355 }
356
357 NSRect messageFrame = [scrollView_message frame];
358 messageFrame.origin.y -= heightChange;
359 if (messageHeightChange > 0) {
360 messageFrame.size.height += messageHeightChange;
361 }
362
363 [scrollView_message setFrame:messageFrame];
364 [scrollView_message setNeedsDisplay:YES( BOOL ) 1];
365 }
366
367 //Set the default button
368 NSRect newFrame, oldFrame;
Value stored to 'oldFrame' is never read
369 oldFrame = [button_default frame];
370
371 [button_default setTitle:(defaultButton ? defaultButton : AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "OK" ) value : @ "" table : ( 0 ) ]
(@"OK",nil))];
372 [button_default sizeToFit];
373
374 newFrame = [button_default frame];
375
376 /* For NSButtons, sizeToFit is 8 pixels smaller than the HIG recommended size */
377 newFrame.size.width += 8;
378 /* Only use integral widths to keep alignment correct; round up as an extra pixel of whitespace never hurt anybody */
379 newFrame.size.width = round(NSWidth(newFrame) + 0.5);
380 if (newFrame.size.width < 90) newFrame.size.width = 90;
381 newFrame.origin.x = NSWidth([window frame]) - NSWidth(newFrame) - 14;
382
383 [button_default setFrame:newFrame];
384
385 //Set the alternate button if we were provided one, otherwise hide it
386 if (alternateButton) {
387 oldFrame = [button_alternate frame];
388
389 [button_alternate setTitle:alternateButton];
390 [button_alternate sizeToFit];
391
392 newFrame = [button_alternate frame];
393 /* For NSButtons, sizeToFit is 8 pixels smaller than the HIG recommended size */
394 newFrame.size.width += 8;
395 /* Only use integral widths to keep alignment correct; round up as an extra pixel of whitespace never hurt anybody */
396 newFrame.size.width = round(NSWidth(newFrame) + 0.5);
397 if (newFrame.size.width < 90) newFrame.size.width = 90;
398 newFrame.origin.x = NSMinX([button_default frame]) - NSWidth(newFrame) + 2;
399
400 [button_alternate setFrame:newFrame];
401
402 //Set the other button if we were provided one, otherwise hide it
403 if (otherButton) {
404 [window setFrame:windowFrame display:NO( BOOL ) 0 animate:NO( BOOL ) 0];
405
406 oldFrame = [button_other frame];
407
408 [button_other setTitle:otherButton];
409
410 [button_other sizeToFit];
411
412 newFrame = [button_other frame];
413 /* For NSButtons, sizeToFit is 8 pixels smaller than the HIG recommended size */
414 newFrame.size.width += 8;
415 /* Only use integral widths to keep alignment correct; round up as an extra pixel of whitespace never hurt anybody */
416 newFrame.size.width = round(NSWidth(newFrame) + 0.5);
417 if (newFrame.size.width < 90) newFrame.size.width = 90;
418
419 newFrame.origin.x = NSMinX([button_alternate frame]) - 36 - NSWidth(newFrame);
420
421 [button_other setFrame:newFrame];
422
423 //Increase the window size to keep our origin in the same location after resizing
424 unsigned int oldAutosizingMask = [button_other autoresizingMask];
425 [button_other setAutoresizingMask:(NSViewMinYMargin | NSViewMinXMargin)];
426 windowFrame.size.width += oldFrame.origin.x - newFrame.origin.x;
427 [window setFrame:windowFrame display:NO( BOOL ) 0 animate:NO( BOOL ) 0];
428 if (NSMinX([button_other frame]) < 18) {
429 //Keep the left side far enough away from the left side of the window
430 windowFrame.size.width += 18 - NSMinX([button_other frame]);
431 [window setFrame:windowFrame display:NO( BOOL ) 0 animate:NO( BOOL ) 0];
432 }
433
434 [button_other setAutoresizingMask:oldAutosizingMask];
435
436 } else {
437 [button_other setHidden:YES( BOOL ) 1];
438 }
439
440 } else {
441 [button_alternate setHidden:YES( BOOL ) 1];
442 [button_other setHidden:YES( BOOL ) 1];
443 }
444
445 //Resize the window to fit the message
446 [window setFrame:windowFrame display:NO( BOOL ) 0 animate:NO( BOOL ) 0];
447
448 //Center the window (if we're not a sheet)
449 [window center];
450 [window display];
451}
452
453- (IBActionvoid)pressedButton:(id)sender
454{
455 AITextAndButtonsReturnCode returnCode;
456
457 userClickedButton = YES( BOOL ) 1;
458
459 if (sender == button_default)
460 returnCode = AITextAndButtonsDefaultReturn;
461 else if (sender == button_alternate)
462 returnCode = AITextAndButtonsAlternateReturn;
463 else if (sender == button_other)
464 returnCode = AITextAndButtonsOtherReturn;
465 else
466 returnCode = AITextAndButtonsClosedWithoutResponse;
467
468 //Notify the target
469 if ([target textAndButtonsWindowDidEnd:[self window]
470 returnCode:returnCode
471 userInfo:userInfo]) {
472
473 //Close the window if the target returns YES
474 [self closeWindow:nil0];
475 }
476}
477
478/*!
479 * @brief If escape or return are pressed inside one of our text views, pass the action on to our buttons
480 */
481- (BOOL)textView:(NSTextView *)aTextView doCommandBySelector:(SEL)aSelector
482{
483 NSButton *equivalentButton = nil0;
484
485 AILogWithSignatureAILogWithPrefix ( __PRETTY_FUNCTION__ , @ "escape? %i newline? %i"
, [ [ button_alternate keyEquivalent ] isEqualToString : @ "\E"
] , [ [ button_default keyEquivalent ] isEqualToString : @ "\n"
] ) ;
(@"escape? %i newline? %i",[[button_alternate keyEquivalent] isEqualToString:@"\E"],[[button_default keyEquivalent] isEqualToString:@"\n"]);
486
487 if (aSelector == @selector(cancelOperation:) &&
488 [[button_alternate keyEquivalent] isEqualToString:@"\E"]) {
489 equivalentButton = button_alternate;
490
491 } else if (((aSelector == @selector(insertNewline:)) || (aSelector == @selector(insertNewlineIgnoringFieldEditor:))) &&
492 [[button_default keyEquivalent] isEqualToString:@"\n"]) {
493 equivalentButton = button_default;
494
495 }
496
497 if (equivalentButton) {
498 [equivalentButton performClick:aTextView];
499 return YES( BOOL ) 1;
500
501 } else {
502 return NO( BOOL ) 0;
503 }
504}
505
506
507- (void)dealloc
508{
509 [title release];
510 [defaultButton release];
511 [target release];
512 [alternateButton release];
513 [otherButton release];
514 [messageHeader release];
515 [message release];
516 [userInfo release];
517 [image release];
518
519 [super dealloc];
520}
521
522@end