Bug Summary

File:Frameworks/Adium Framework/Source/AIEditStateWindowController.m
Location:line 514, 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/AIAccount.h>
18#import <Adium/AIEditStateWindowController.h>
19#import <Adium/AIStatus.h>
20#import <Adium/AIStatusControllerProtocol.h>
21#import <Adium/AIContentControllerProtocol.h>
22#import <Adium/AIPreferenceControllerProtocol.h>
23#import <AIUtilities/AIAttributedStringAdditions.h>
24#import <AIUtilities/AIAutoScrollView.h>
25#import <AIUtilities/AIStringFormatter.h>
26#import <AIUtilities/AITextAttributes.h>
27#import <AIUtilities/AIWindowAdditions.h>
28#import <AIUtilities/AIApplicationAdditions.h>
29#import <Adium/AIMessageEntryTextView.h>
30
31#define CONTROL_SPACING 8
32#define WINDOW_HEIGHT_PADDING 30
33
34#define SEND_ON_ENTER @"Send On Enter"
35
36@interface AIEditStateWindowController (PRIVATE)
37- (id)initWithWindowNibName:(NSString *)windowNibName forType:(AIStatusType)inStatusType andAccount:(AIAccount *)inAccount customState:(AIStatus *)inStatusState notifyingTarget:(id)inTarget showSaveCheckbox:(BOOL)inShowSaveCheckbox;
38- (id)_positionControl:(id)control relativeTo:(id)guide height:(int *)height;
39- (void)configureStateMenu;
40
41- (void)setOriginalStatusState:(AIStatus *)inState forType:(AIStatusType)inStatusType;
42- (void)setAccount:(AIAccount *)inAccount;
43- (void)configureForAccountAndWorkingStatusState;
44@end
45
46/*!
47 * @class AIEditStateWindowController
48 * @brief Interface for editing a status state
49 *
50 * This class provides an interface for editing a status state dictionary's properties.
51 */
52@implementation AIEditStateWindowController
53
54static NSMutableDictionary *controllerDict = nil0;
55
56/*!
57 * @brief Open a custom state editor window or sheet
58 *
59 * Open either a sheet or window containing a state editor. The state editor will be primed with the passed state
60 * dictionary. When the user successfully closes the editor, the target will be notified and passed the updated
61 * state dictionary. Only one window will be shown per target at a time.
62 *
63 * @param inStatusState Initial AIStatus
64 * @param inStatusType AIStatusType to use initially if inStatusState is nil
65 * @param inAccount The account which to configure the custom state window; nil to configure globally
66 * @param inShowSaveCheckbox YES if the save checkbox should be shown; NO if it should not. If YES, the title on an incoming status will be cleared to make it auto-update.
67 * @param parentWindow Parent window for a sheet, nil for a stand alone editor
68 * @param inTarget Target object to notify when editing is complete
69 */
70+ (id)editCustomState:(AIStatus *)inStatusState forType:(AIStatusType)inStatusType andAccount:(AIAccount *)inAccount withSaveOption:(BOOL)inShowSaveCheckbox onWindow:(id)parentWindow notifyingTarget:(id)inTarget
71{
72 AIEditStateWindowController *controller;
73
74 NSNumber *targetHash = [NSNumber numberWithUnsignedInt:[inTarget hash]];
75
76 if ((controller = [controllerDict objectForKey:targetHash])) {
77 [controller setAccount:inAccount];
78
79 if ([[controller currentConfiguration] statusType] != inStatusType) {
80 //It's not currently editing a status of the type requested; configure based on the passed status
81 [controller setOriginalStatusState:inStatusState forType:inStatusType];
82 [controller configureForAccountAndWorkingStatusState];
83 }
84
85 } else {
86 controller = [[self alloc] initWithWindowNibName:@"EditStateSheet"
87 forType:inStatusType
88 andAccount:inAccount
89 customState:inStatusState
90 notifyingTarget:inTarget
91 showSaveCheckbox:inShowSaveCheckbox];
92 if (!controllerDict) controllerDict = [[NSMutableDictionary alloc] init];
93 [controllerDict setObject:controller forKey:targetHash];
94 }
95
96 if (parentWindow) {
97 [NSApp beginSheet:[controller window]
98 modalForWindow:parentWindow
99 modalDelegate:controller
100 didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
101 contextInfo:nil0];
102 } else {
103 [controller showWindow:nil0];
104 [[controller window] makeKeyAndOrderFront:nil0];
105 [NSApp activateIgnoringOtherApps:YES( BOOL ) 1];
106 }
107
108 return controller;
109}
110
111/*!
112 * @brief Init the window controller
113 */
114- (id)initWithWindowNibName:(NSString *)windowNibName forType:(AIStatusType)inStatusType andAccount:(AIAccount *)inAccount customState:(AIStatus *)inStatusState notifyingTarget:(id)inTarget showSaveCheckbox:(BOOL)inShowSaveCheckbox
115{
116 if ((self = [super initWithWindowNibName:windowNibName])) {
117 target = inTarget;
118 showSaveCheckbox = inShowSaveCheckbox;
119
120 [self setOriginalStatusState:inStatusState forType:inStatusType];
121 [self setAccount:inAccount];
122 }
123
124 return self;
125}
126
127/*!
128 * @brief Set our status state
129 *
130 * Also create the working state if we don't have one or the original status state is of the wrong statusType.
131 * If showSaveCheckbox is YES, clear workingStatusState's title so it will autoupdate.
132 */
133- (void)setOriginalStatusState:(AIStatus *)inStatusState forType:(AIStatusType)inStatusType
134{
135 if (originalStatusState != inStatusState) {
136 [originalStatusState release];
137 originalStatusState = [inStatusState retain];
138 }
139
140 [workingStatusState release];
141 workingStatusState = (originalStatusState ?
142 [originalStatusState mutableCopy] :
143 [[AIStatus statusOfType:inStatusType] retain]);
144
145 //Clear the title if the save checkbox is showing so it will autoupdate.
146 if (showSaveCheckbox) [workingStatusState setTitle:nil0];
147}
148
149- (void)setAccount:(AIAccount *)inAccount
150{
151 if (inAccount != account) {
152 [account release];
153 account = [inAccount retain];
154 }
155}
156
157/*!
158 * Deallocate
159 */
160- (void)dealloc
161{
162 [originalStatusState release];
163 [workingStatusState release];
164 [account release];
165
166 [super dealloc];
167}
168
169/*!
170 * @brief Configure the window after it loads
171 */
172- (void)windowDidLoad
173{
174// NSNumberFormatter *intFormatter;
175 BOOL sendOnEnter;
176
177 sendOnEnter = [[[adium preferenceController] preferenceForKey:SEND_ON_ENTER@ "Send On Enter"
178 group:PREF_GROUP_GENERAL@ "General"] boolValue];
179
180 [scrollView_statusMessage setAutohidesScrollers:YES( BOOL ) 1];
181 [scrollView_statusMessage setAlwaysDrawFocusRingIfFocused:YES( BOOL ) 1];
182 [textView_statusMessage setTarget:self action:@selector(okay:)];
183 [textView_statusMessage setDelegate:self];
184
185 [textView_statusMessage setAllowsDocumentBackgroundColorChange:YES( BOOL ) 1];
186 [textView_autoReply setAllowsDocumentBackgroundColorChange:YES( BOOL ) 1];
187
188 [textView_statusMessage setSendOnReturn:NO( BOOL ) 0];
189 [textView_statusMessage setSendOnEnter:sendOnEnter];
190
191 if ([textView_statusMessage isKindOfClass:[AIMessageEntryTextView class]]) {
192 [(AIMessageEntryTextView *)textView_statusMessage setClearOnEscape:NO( BOOL ) 0];
193 [(AIMessageEntryTextView *)textView_statusMessage setPushPopEnabled:NO( BOOL ) 0];
194 [(AIMessageEntryTextView *)textView_statusMessage setHistoryEnabled:NO( BOOL ) 0];
195 }
196
197 [scrollView_autoReply setAutohidesScrollers:YES( BOOL ) 1];
198 [scrollView_autoReply setAlwaysDrawFocusRingIfFocused:YES( BOOL ) 1];
199 [textView_autoReply setTarget:self action:@selector(okay:)];
200 [textView_autoReply setDelegate:self];
201
202 //Return inserts a new line
203 [textView_autoReply setSendOnReturn:NO( BOOL ) 0];
204
205 /* Enter follows the user's preference. By default, then, enter will send the okay: selector.
206 * If the user expects enter to insert a newline in a message, however, it will do that here, too. */
207 [textView_autoReply setSendOnEnter:sendOnEnter];
208
209 if ([textView_autoReply isKindOfClass:[AIMessageEntryTextView class]]) {
210 [(AIMessageEntryTextView *)textView_autoReply setClearOnEscape:NO( BOOL ) 0];
211 [(AIMessageEntryTextView *)textView_autoReply setPushPopEnabled:NO( BOOL ) 0];
212 [(AIMessageEntryTextView *)textView_autoReply setHistoryEnabled:NO( BOOL ) 0];
213 }
214
215 [self configureForAccountAndWorkingStatusState];
216
217 [textView_statusMessage setTypingAttributes:[[adium contentController] defaultFormattingAttributes]];
218 [textView_autoReply setTypingAttributes:[[adium contentController] defaultFormattingAttributes]];
219
220 NSMutableCharacterSet *noNewlinesCharacterSet;
221 noNewlinesCharacterSet = [[[NSCharacterSet characterSetWithCharactersInString:@""] invertedSet] mutableCopy];
222 [noNewlinesCharacterSet removeCharactersInString:@"\n\r"];
223 [textField_title setFormatter:[AIStringFormatter stringFormatterAllowingCharacters:noNewlinesCharacterSet
224 length:0 /* No length limit */
225 caseSensitive:NO( BOOL ) 0
226 errorMessage:nil0]];
227 [noNewlinesCharacterSet release];
228
229 if (!showSaveCheckbox) {
230 [checkBox_save setHidden:YES( BOOL ) 1];
231 }
232
233 [super windowDidLoad];
234
235 [self updateControlVisibilityAndResizeWindow];
236}
237
238/*!
239 * @brief Configure for our account and working status state
240 *
241 * This means updating the state menu to be appropriate for our account's service as well as setting up
242 * the rest of the fields.
243 */
244- (void)configureForAccountAndWorkingStatusState
245{
246 [self configureStateMenu];
247
248 //Configure our editor for the working state
249 [self configureForState:workingStatusState];
250}
251
252/*!
253 * @brief Configure the state menu with a fresh menu of active statuses
254 */
255- (void)configureStateMenu
256{
257 [popUp_state setMenu:[[adium statusController] menuOfStatusesForService:(account ? [account service] : nil0)
258 withTarget:self]];
259 needToRebuildPopUpState = NO( BOOL ) 0;
260}
261
262/*!
263 * @brief Called before the window is closed
264 *
265 * As our window is closing, we auto-release this window controller instance. This allows our editor to function
266 * independently without needing a separate object to retain and release it.
267 */
268- (void)windowWillClose:(id)sender
269{
270 [super windowWillClose:sender];
271
272 //Stop tracking with the controllerDict
273 NSNumber *targetHash = [NSNumber numberWithUnsignedInt:[target hash]];
274 [controllerDict removeObjectForKey:targetHash];
275
276 [self autorelease];
277}
278
279/*!
280 * Invoked as the sheet closes, dismiss the sheet
281 */
282- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
283{
284 //Stop tracking with the controllerDict
285 NSNumber *targetHash = [NSNumber numberWithUnsignedInt:[target hash]];
286 [controllerDict removeObjectForKey:targetHash];
287
288 [sheet orderOut:nil0];
289}
290
291- (NSString *)adiumFrameAutosaveName
292{
293 return @"EditStateWindow";
294}
295
296//Behavior -------------------------------------------------------------------------------------------------------------
297#pragma mark Behavior
298/*!
299 * @brief Okay
300 *
301 * Save changes, notify our target of the new configuration, and close the editor.
302 */
303- (IBActionvoid)okay:(id)sender
304{
305 if (target && [target respondsToSelector:@selector(customStatusState:changedTo:forAccount:)]) {
306 //Perform on a delay so the sheet can begin closing immediately.
307 [self performSelector:@selector(notifyOfStateChange)
308 withObject:nil0
309 afterDelay:0];
310 }
311
312 [self closeWindow:nil0];
313}
314
315/*!
316 * @brief Notify our target of the state changing
317 *
318 * Called by -[self okay:]
319 */
320- (void)notifyOfStateChange
321{
322 [target customStatusState:originalStatusState changedTo:[self currentConfiguration] forAccount:account];
323}
324
325/*!
326 * @brief Cancel
327 *
328 * Close the editor without saving changes.
329 */
330- (IBActionvoid)cancel:(id)sender
331{
332 [self closeWindow:nil0];
333}
334
335- (void)textViewDidCancel:(NSTextView *)inTextView
336{
337 [self cancel:inTextView];
338}
339
340/*!
341 * @brief Update the display of the status's title in the window
342 */
343- (void)updateTitleDisplay
344{
345 [textField_title setStringValue:[workingStatusState title]];
346}
347
348/*!
349 * @brief Invoked when a control value is changed
350 *
351 * Invoked with the user changes the value of an editor control. In response, we update control visibility and
352 * resize the window.
353 */
354- (IBActionvoid)statusControlChanged:(id)sender
355{
356 if (sender == checkbox_autoReply)
357 [workingStatusState setHasAutoReply:[checkbox_autoReply state]];
358 else if (sender == checkbox_customAutoReply)
359 [workingStatusState setAutoReplyIsStatusMessage:![checkbox_customAutoReply state]];
360 else if (sender == checkbox_idle)
361 [workingStatusState setShouldForceInitialIdleTime:[checkbox_idle state]];
362 else if (sender == checkBox_muteSounds)
363 [workingStatusState setMutesSound:[checkBox_muteSounds state]];
364 else if (sender == checkBox_silenceGrowl)
365 [workingStatusState setSilencesGrowl:[checkBox_silenceGrowl state]];
366
367 [self updateControlVisibilityAndResizeWindow];
368 [self updateTitleDisplay];
369}
370
371/*!
372 * @brief NSTextField changed
373 */
374- (void)controlTextDidChange:(NSNotification *)notification
375{
376 id sender = [notification object];
377
378 if (sender == textField_title) {
379 NSString *newTitle = [textField_title stringValue];
380
381 if ([newTitle length]) [workingStatusState setTitle:newTitle];
382 }
383}
384
385/*!
386 * @brief NSTextView changed
387 */
388- (void)textDidChange:(NSNotification *)notification
389{
390 id sender = [notification object];
391
392 if (sender == textView_statusMessage) {
393 [workingStatusState setStatusMessage:[[[textView_statusMessage textStorage] copy] autorelease]];
394
395 } else if (sender == textView_autoReply) {
396 [workingStatusState setAutoReply:[[[textView_autoReply textStorage] copy] autorelease]];
397
398 }
399
400 [self updateTitleDisplay];
401}
402
403/*!
404 * @brief NSTextField ended editing
405 *
406 * If our title is cleared out, restore it to using the default title for the rest of the configuration
407 */
408- (void)controlTextDidEndEditing:(NSNotification *)notification
409{
410 id sender = [notification object];
411
412 if (sender == textField_title) {
413 NSString *newTitle = [textField_title stringValue];
414
415 //Set to nil if the field is cleared to get back to the automatically generated value
416 if (![newTitle length]) {
417 [workingStatusState setTitle:nil0];
418
419 [self updateTitleDisplay];
420 }
421 }
422}
423
424/*!
425 * @brief Invoked when a new status type is selected
426 */
427- (IBActionvoid)selectStatus:(id)sender
428{
429 NSDictionary *stateDict = [[popUp_state selectedItem] representedObject];
430 if (stateDict) {
431 [workingStatusState setStatusType:[[stateDict objectForKey:KEY_STATUS_TYPE@ "Status Type"] intValue]];
432 [workingStatusState setStatusName:[stateDict objectForKey:KEY_STATUS_NAME@ "Status Name"]];
433 }
434
435 [self updateTitleDisplay];
436}
437
438/*!
439 * @brief Override AIWindowController's stringWithSavedFrame to provide a custom saved frame
440 *
441 * We want our savedframe to match the way the window will load, which means it needs to be as if all controls were visible.
442 */
443- (NSString *)stringWithSavedFrame
444{
445 NSWindow *window = [self window];
446 NSString *stringWithSavedFrame;
447
448 NSRect frame = [window frame];
449 float delta = 0;
450 delta += ([scrollView_autoReply isHidden] ? ([scrollView_autoReply frame].size.height + CONTROL_SPACING8) : 0);
451 delta += ([checkbox_customAutoReply isHidden] ? ([checkbox_customAutoReply frame].size.height + CONTROL_SPACING8) : 0);
452 delta += ([box_idle isHidden] ? ([box_idle frame].size.height + CONTROL_SPACING8) : 0);
453
454 frame.size.height += delta;
455 frame.origin.y -= delta;
456
457 NSRect screenFrame = [[window screen] frame];
458 stringWithSavedFrame = [NSString stringWithFormat:@"%0f %0f %0f %0f %0f %0f %0f %0f",
459 frame.origin.x, frame.origin.y, frame.size.width, frame.size.height,
460 screenFrame.origin.x, screenFrame.origin.y, screenFrame.size.width, screenFrame.size.height];
461
462 return stringWithSavedFrame;
463}
464
465- (NSRect)savedFrameFromString:(NSString *)frameString
466{
467 NSRect savedFrame = [super savedFrameFromString:frameString];
468
469 float delta = 0;
470 delta += ([scrollView_autoReply isHidden] ? ([scrollView_autoReply frame].size.height + CONTROL_SPACING8) : 0);
471 delta += ([checkbox_customAutoReply isHidden] ? ([checkbox_customAutoReply frame].size.height + CONTROL_SPACING8) : 0);
472 delta += ([box_idle isHidden] ? ([box_idle frame].size.height + CONTROL_SPACING8) : 0);
473
474 savedFrame.size.height -= delta;
475 savedFrame.origin.y += delta;
476
477 //Magic? This is the amount our numbers are off from the nib... if the nib changes, this magic will probably change, too.
478 savedFrame.size.height += CONTROL_SPACING8*3;
479
480 return savedFrame;
481}
482
483
484/*!
485 * @brief Update control visibility and resize the editor window
486 *
487 * This method updates control visibility (When checkboxes are off we hide the controls below them) and resizes the
488 * window to fit just the remaining visible controls.
489 */
490- (void)updateControlVisibilityAndResizeWindow
491{
492 //Visibility
493 NSWindow *window = [self window];
494
495 [scrollView_autoReply setHidden:(![checkbox_autoReply state] || ![checkbox_customAutoReply state])];
496 [checkbox_customAutoReply setHidden:![checkbox_autoReply state]];
497 [box_idle setHidden:![checkbox_idle state]];
498
499 //Sizing
500 //XXX - This is quick & dirty -ai
501 id current = box_title;
502 int height = WINDOW_HEIGHT_PADDING30 + [current frame].size.height;
503
504 current = [self _positionControl:box_separatorLine relativeTo:current height:&height];
505 current = [self _positionControl:box_state relativeTo:current height:&height];
506 current = [self _positionControl:box_statusMessage relativeTo:current height:&height];
507 current = [self _positionControl:checkbox_autoReply relativeTo:current height:&height];
508 current = [self _positionControl:checkbox_customAutoReply relativeTo:current height:&height];
509 current = [self _positionControl:scrollView_autoReply relativeTo:current height:&height];
510 current = [self _positionControl:checkbox_idle relativeTo:current height:&height];
511 current = [self _positionControl:box_idle relativeTo:current height:&height];
512 current = [self _positionControl:checkBox_muteSounds relativeTo:current height:&height];
513 current = [self _positionControl:checkBox_silenceGrowl relativeTo:current height:&height];
Value stored to 'current' is never read
514 current = [self _positionControl:checkBox_save relativeTo:current height:&height];
515
516 [window setContentSize:NSMakeSize([[window contentView] frame].size.width, height)
517 display:YES( BOOL ) 1
518 animate:NO( BOOL ) 0];
519}
520
521/*!
522 * @brief Position a control
523 *
524 * Position the passed control relative to another control in the editor window, keeping track of total control
525 * height. If the passed control is hidden, it won't be positioned or influence the total height at all.
526 * @param control The control to reposition
527 * @param guide The control we're positoining relative to
528 * @param height A pointer to the total control height, which will be updated to include control
529 * @return Returns control if it's visible, otherwise returns guide
530 */
531- (id)_positionControl:(id)control relativeTo:(id)guide height:(int *)height
532{
533 if (![control isHidden]) {
534 NSRect frame = [control frame];
535
536 //Position this control relative to the one above it
537 frame.origin.y = [guide frame].origin.y - CONTROL_SPACING8 - frame.size.height;
538
539 [control setFrame:frame];
540 (*height) += frame.size.height + CONTROL_SPACING8;
541
542 return control;
543 } else {
544 return guide;
545 }
546}
547
548
549//Configuration --------------------------------------------------------------------------------------------------------
550#pragma mark Configuration
551/*!
552 * @brief Configure the editor for a state
553 *
554 * Configured the editor's controls to represent the passed state dictionary.
555 * @param statusState A NSDictionary containing status state keys and values
556 */
557- (void)configureForState:(AIStatus *)statusState
558{
559 //State menu
560 NSString *description;
561 int index;
562
563 if (needToRebuildPopUpState) {
564 [self configureStateMenu];
565 }
566
567 description = [[adium statusController] descriptionForStateOfStatus:statusState];
568 index = (description ? [popUp_state indexOfItemWithTitle:description] : -1);
569 if (index != -1) {
570 [popUp_state selectItemAtIndex:index];
571
572 } else {
573 if (description) {
574 [popUp_state setTitle:[NSString stringWithFormat:@"%@ (%@)",
575 description,
576 AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "No compatible accounts connected" ) value : @ "" table
: ( 0 ) ]
(@"No compatible accounts connected", nil)]];
577
578 } else {
579 [popUp_state setTitle:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "Unknown" ) value : @ "" table : ( 0 ) ]
(@"Unknown", nil)];
580 }
581
582 needToRebuildPopUpState = YES( BOOL ) 1;
583 }
584
585 //Toggles
586 [checkbox_idle setState:[statusState shouldForceInitialIdleTime]];
587 [checkbox_autoReply setState:[statusState hasAutoReply]];
588 [checkbox_customAutoReply setState:![statusState autoReplyIsStatusMessage]];
589 [checkBox_muteSounds setState:[statusState mutesSound]];
590 [checkBox_silenceGrowl setState:[statusState silencesGrowl]];
591
592 //Strings
593 NSAttributedString *statusMessage = [statusState statusMessage];
594 NSAttributedString *autoReply = [statusState autoReply];
595
596 NSAttributedString *blankString = [NSAttributedString stringWithString:@""];
597
598 if (!statusMessage) statusMessage = blankString;
599 [[textView_statusMessage textStorage] setAttributedString:statusMessage];
600 [textView_statusMessage setSelectedRange:NSMakeRange(0, [statusMessage length])];
601
602 if (!autoReply) autoReply = blankString;
603 [[textView_autoReply textStorage] setAttributedString:autoReply];
604
605 //Set Background Colors
606 if([autoReply attribute:AIBodyColorAttributeName@ "AIBodyColor" atIndex:0 effectiveRange:nil0]) {
607 [textView_autoReply setBackgroundColor:[autoReply attribute:AIBodyColorAttributeName@ "AIBodyColor" atIndex:0 effectiveRange:nil0]];
608 }
609
610 if([statusMessage attribute:AIBodyColorAttributeName@ "AIBodyColor" atIndex:0 effectiveRange:nil0]) {
611 [textView_statusMessage setBackgroundColor:[statusMessage attribute:AIBodyColorAttributeName@ "AIBodyColor" atIndex:0 effectiveRange:nil0]];
612 }
613
614 //Disallow an undo to before this point
615 [[textView_autoReply undoManager] removeAllActions];
616 [[textView_statusMessage undoManager] removeAllActions];
617
618 //Idle start
619 double idleStart = [statusState forcedInitialIdleTime];
620 [textField_idleMinutes setIntValue:(int)((((int)idleStart)%3600)/60)];
621 [textField_idleHours setIntValue:(int)(idleStart/3600)];
622
623 //Update visiblity and size
624 [self updateControlVisibilityAndResizeWindow];
625
626 //Update our title
627 [self updateTitleDisplay];
628}
629
630/*!
631 * @brief Returns the current state
632 *
633 * Builds and returns a state dictionary representation of the current editor values. If no controls have been
634 * modified since the editor was configured, the returned state will be identical in content to the one passed
635 * to configureForState:.
636 */
637- (AIStatus *)currentConfiguration
638{
639 double idleStart = [textField_idleHours intValue]*3600 + [textField_idleMinutes intValue]*60;
640
641 [workingStatusState setMutabilityType:((!showSaveCheckbox || ([checkBox_save state] == NSOnState)) ?
642 AIEditableStatusState :
643 AITemporaryEditableStatusState)];
644
645 [workingStatusState setForcedInitialIdleTime:idleStart];
646
647 //Set the title if necessary
648 if (![[workingStatusState title] isEqualToString:[textField_title stringValue]]) {
649 [workingStatusState setTitle:[textField_title stringValue]];
650 }
651
652 //Do not allow the creation of a Now Playing status
653 if ([workingStatusState specialStatusType] == AINowPlayingSpecialStatusType) {
654 [workingStatusState setSpecialStatusType:AINoSpecialStatusType];
655 }
656
657 return workingStatusState;
658}
659
660@end
661