2 // ESStatusPreferences.m
5 // Created by Evan Schoenberg on 2/26/05.
6 // Copyright 2006 The Adium Team. All rights reserved.
9 #import "ESStatusPreferences.h"
10 #import "AIStatusController.h"
11 #import <Adium/AIAccountControllerProtocol.h>
12 #import "ESEditStatusGroupWindowController.h"
13 #import <Adium/AIAccount.h>
14 #import <Adium/AIEditStateWindowController.h>
15 #import <Adium/AIStatusMenu.h>
16 #import <Adium/AIStatusGroup.h>
17 #import <AIUtilities/AIImageTextCell.h>
18 #import <AIUtilities/AIAutoScrollView.h>
19 #import <AIUtilities/AIVerticallyCenteredTextCell.h>
20 #import <AIUtilities/AIOutlineViewAdditions.h>
21 #import <AIUtilities/AIImageAdditions.h>
22 #import "KFTypeSelectTableView.h"
24 #define STATE_DRAG_TYPE @"AIState"
26 @interface ESStatusPreferences (PRIVATE)
27 - (void)configureOtherControls;
28 - (void)configureAutoAwayStatusStatePopUp;
29 - (void)saveTimeValues;
30 - (void)_selectStatusWithUniqueID:(NSNumber *)uniqueID inPopUpButton:(NSPopUpButton *)inPopUpButton;
32 - (BOOL)addItemIfNeeded:(NSMenuItem *)menuItem toPopUpButton:(NSPopUpButton *)popUpButton alreadyShowingAnItem:(BOOL)alreadyShowing;
35 @implementation ESStatusPreferences
40 - (AIPreferenceCategory)category{
47 return AILocalizedString(@"Status",nil);
53 - (NSString *)nibName{
54 return @"StatusPreferences";
58 * @brief Configure the preference view
62 //Configure the controls
63 [self configureStateList];
65 //Manually size and position our buttons
67 NSRect newFrame, oldFrame;
69 //Edit, right justified and far enough away from Remove that it can't conceivably overlap
70 oldFrame = [button_editState frame];
71 [button_editState setTitle:AILocalizedString(@"Edit",nil)];
72 [button_editState sizeToFit];
73 newFrame = [button_editState frame];
74 if (newFrame.size.width < oldFrame.size.width) newFrame.size.width = oldFrame.size.width;
75 if (newFrame.size.height < oldFrame.size.height) newFrame.size.height = oldFrame.size.height;
76 newFrame.origin.x = oldFrame.origin.x + oldFrame.size.width - newFrame.size.width;
77 [button_editState setFrame:newFrame];
80 oldFrame = [button_addGroup frame];
81 [button_addGroup setTitle:AILocalizedString(@"Add Group",nil)];
82 [button_addGroup sizeToFit];
83 newFrame = [button_addGroup frame];
84 if (newFrame.size.height < oldFrame.size.height) newFrame.size.height = oldFrame.size.height;
85 [button_addGroup setFrame:newFrame];
89 /* Register as an observer of state array changes so we can refresh our list
90 * in response to changes. */
91 [[adium notificationCenter] addObserver:self
92 selector:@selector(stateArrayChanged:)
93 name:AIStatusStateArrayChangedNotification
95 [self stateArrayChanged:nil];
97 [self configureOtherControls];
101 * @brief Preference view is closing
103 - (void)viewWillClose
105 [self saveTimeValues];
106 [[adium notificationCenter] removeObserver:self];
117 #pragma mark Status state list and controls
119 * @brief Configure the state list
121 * Configure the state list table view, setting up the custom table cells, padding, scroll view settings and other
122 * state list interface related setup.
124 - (void)configureStateList
126 AIImageTextCell *cell;
128 //Configure the table view
129 [outlineView_stateList setTarget:self];
130 [outlineView_stateList setDoubleAction:@selector(editState:)];
131 [outlineView_stateList setIntercellSpacing:NSMakeSize(4,4)];
132 [scrollView_stateList setAutohidesScrollers:YES];
134 //Enable dragging of states
135 [outlineView_stateList registerForDraggedTypes:[NSArray arrayWithObject:STATE_DRAG_TYPE]];
137 //Custom vertically-centered text cell for status state names
138 cell = [[AIVerticallyCenteredTextCell alloc] init];
139 [cell setFont:[NSFont systemFontOfSize:13]];
140 [[outlineView_stateList tableColumnWithIdentifier:@"name"] setDataCell:cell];
145 * @brief Update table control availability
147 * Updates table control availability based on the current state selection. If no states are selected this method dims the
148 * edit and delete buttons since they require a selection to function. The edit and delete buttons are also
149 * dimmed if the selected state is a built-in state.
151 - (void)updateTableControlAvailability
153 // NSArray *selectedItems = [outlineView_stateList arrayOfSelectedItems];
154 NSIndexSet *selectedIndexes = [outlineView_stateList selectedRowIndexes];
155 int count = [selectedIndexes count];
157 [button_editState setEnabled:(count &&
158 ([[outlineView_stateList itemAtRow:[selectedIndexes firstIndex]] mutabilityType] == AIEditableStatusState))];
159 [button_deleteState setEnabled:count];
163 * @brief Invoked when the state array changes
165 * This method is invoked when the state array changes. In response, we hold onto the new array and refresh our state
168 - (void)stateArrayChanged:(NSNotification *)notification
170 [outlineView_stateList reloadData];
171 [self updateTableControlAvailability];
173 //Update the auto away status pop up as necessary
174 [self configureAutoAwayStatusStatePopUp];
177 //State Editing --------------------------------------------------------------------------------------------------------
178 #pragma mark State Editing
180 * @brief Edit the selected state
182 * Opens an edit state sheet for the selected state. If the sheet is closed with success our
183 * customStatusState:changedTo: method will be invoked and we can save the changes
185 - (IBAction)editState:(id)sender
187 int selectedRow = [outlineView_stateList selectedRow];
188 AIStatusItem *statusState = [outlineView_stateList itemAtRow:selectedRow];
191 if ([statusState isKindOfClass:[AIStatus class]]) {
192 [AIEditStateWindowController editCustomState:(AIStatus *)statusState
193 forType:[statusState statusType]
196 onWindow:[[self view] window]
197 notifyingTarget:self];
199 } else if ([statusState isKindOfClass:[AIStatusGroup class]]) {
200 [ESEditStatusGroupWindowController editStatusGroup:(AIStatusGroup *)statusState
201 onWindow:[[self view] window]
202 notifyingTarget:self];
208 * @brief State edited callback
210 * Invoked when the user successfully edits a state. This method adds the new or updated state to Adium's state array.
212 - (void)customStatusState:(AIStatus *)originalState changedTo:(AIStatus *)newState forAccount:(AIAccount *)account
215 /* As far the user was concerned, this was an edit. The unique status ID should remain the same so that anything
216 * depending upon this status will update to using it. Furthermore, since this may be a copy of originalState
217 * rather than the exact same object, we should update all accounts which are using this state to use the new copy
219 [newState setUniqueStatusID:[originalState uniqueStatusID]];
221 NSEnumerator *enumerator;
224 enumerator = [[[adium accountController] accounts] objectEnumerator];
225 while ((account = [enumerator nextObject])) {
226 if ([account statusState] == originalState) {
227 [account setStatusStateAndRemainOffline:newState];
229 [account notifyOfChangedStatusSilently:YES];
233 [[originalState containingStatusGroup] replaceExistingStatusState:originalState withStatusState:newState];
235 [originalState setUniqueStatusID:nil];
238 [[adium statusController] addStatusState:newState];
241 [outlineView_stateList selectItemsInArray:[NSArray arrayWithObject:newState]];
242 [outlineView_stateList scrollRowToVisible:[outlineView_stateList rowForItem:newState]];
245 - (void)finishedSatusGroupEdit:(AIStatusGroup *)inStatusGroup
247 if (![inStatusGroup containingStatusGroup]) {
248 //Add it if it's not already in a group
249 [[[adium statusController] rootStateGroup] addStatusItem:inStatusGroup atIndex:-1];
252 //Otherwise just save
253 [[adium statusController] savedStatusesChanged];
256 [outlineView_stateList selectItemsInArray:[NSArray arrayWithObject:inStatusGroup]];
257 [outlineView_stateList scrollRowToVisible:[outlineView_stateList rowForItem:inStatusGroup]];
261 * @brief Delete the selected state
263 * Deletes the selected state from Adium's state array.
265 - (IBAction)deleteState:(id)sender
267 int selectedIndex = [outlineView_stateList selectedRow];
268 AIStatusItem *statusItem = [outlineView_stateList itemAtRow:selectedIndex];
271 //Confirm deletion of a status group with contents
272 if ([statusItem isKindOfClass:[AIStatusGroup class]] &&
273 [[(AIStatusGroup *)statusItem containedStatusItems] count]) {
274 unsigned count = [[(AIStatusGroup *)statusItem containedStatusItems] count];
278 message = [NSString stringWithFormat:AILocalizedString(@"Are you sure you want to delete the group \"%@\" containing %i saved status items?",nil),
279 [statusItem title], count];
282 message = [NSString stringWithFormat:AILocalizedString(@"Are you sure you want to delete the group \"%@\" containing 1 saved status item?",nil),
283 [statusItem title], count];
286 //Warn if deleting a group containing status items
287 NSBeginAlertSheet(AILocalizedString(@"Status Group Deletion Confirmation",nil),
288 AILocalizedString(@"Delete", nil),
289 AILocalizedString(@"Cancel", nil), nil,
290 [[self view] window], self,
291 @selector(sheetDidEnd:returnCode:contextInfo:), NULL,
296 [[statusItem containingStatusGroup] removeStatusItem:statusItem];
302 * @brief Confirmed a status item deletion operation
304 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
306 if (returnCode == NSAlertDefaultReturn) {
307 AIStatusItem *statusItem = (AIStatusItem *)contextInfo;
308 [[statusItem containingStatusGroup] removeStatusItem:statusItem];
313 * @brief Add a new state
315 * Creates a new state. This is done by invoking an edit window without passing it a base state. When the edit window
316 * returns successfully, it will invoke our customStatusState:changedTo: which adds the new state to Adium's state
319 - (IBAction)newState:(id)sender
321 [AIEditStateWindowController editCustomState:nil
322 forType:AIAwayStatusType
325 onWindow:[[self view] window]
326 notifyingTarget:self];
329 - (IBAction)addGroup:(id)sender
331 [ESEditStatusGroupWindowController editStatusGroup:nil
332 onWindow:[[self view] window]
333 notifyingTarget:self];
336 //State List OutlinView Delegate --------------------------------------------------------------------------------------------
337 #pragma mark State List (OutlinView Delegate)
338 - (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item
340 AIStatusGroup *statusGroup = (item ? item : [[adium statusController] rootStateGroup]);
342 return [[statusGroup containedStatusItems] objectAtIndex:index];
345 - (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
347 AIStatusGroup *statusGroup = (item ? item : [[adium statusController] rootStateGroup]);
349 return [[statusGroup containedStatusItems] count];
352 - (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
357 - (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
359 NSString *identifier = [tableColumn identifier];
361 if ([identifier isEqualToString:@"icon"]) {
362 return ([item respondsToSelector:@selector(icon)] ? [item icon] : nil);
364 } else if ([identifier isEqualToString:@"name"]) {
365 NSImage *icon = ([item respondsToSelector:@selector(icon)] ? [item icon] : nil);
368 NSMutableAttributedString *name;
370 NSTextAttachment *attachment;
371 NSTextAttachmentCell *cell;
373 NSSize iconSize = [icon size];
375 if ((iconSize.width > 13) || (iconSize.height > 13)) {
376 icon = [icon imageByScalingToSize:NSMakeSize(13, 13)];
379 cell = [[[NSTextAttachmentCell alloc] init] autorelease];
380 [cell setImage:icon];
382 attachment = [[[NSTextAttachment alloc] init] autorelease];
383 [attachment setAttachmentCell:cell];
385 name = [[NSAttributedString attributedStringWithAttachment:attachment] mutableCopy];
386 [name appendAttributedString:[[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@" %@",([item title] ? [item title] : @"")]
387 attributes:nil] autorelease]];
388 return [name autorelease];
397 - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
399 return [item isKindOfClass:[AIStatusGroup class]];
403 * @brief Delete the selected row
405 - (void)outlineViewDeleteSelectedRows:(NSTableView *)tableView
407 [self deleteState:nil];
411 * @brief Selection change
413 - (void)outlineViewSelectionDidChange:(NSNotification *)notification
415 [self updateTableControlAvailability];
421 - (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard
423 draggingItems = [items retain];
425 [pboard declareTypes:[NSArray arrayWithObject:STATE_DRAG_TYPE] owner:self];
426 [pboard setString:@"State" forType:STATE_DRAG_TYPE]; //Arbitrary state
431 - (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index
433 if (index == NSOutlineViewDropOnItemIndex && ![item isKindOfClass:[AIStatusGroup class]]) {
434 AIStatusGroup *dropItem = [item containingStatusGroup];
435 if (dropItem == [[adium statusController] rootStateGroup])
438 [outlineView setDropItem:dropItem
439 dropChildIndex:[[[item containingStatusGroup] containedStatusItems] indexOfObjectIdenticalTo:item]];
442 return NSDragOperationPrivate;
446 * @brief Drag complete
448 - (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index
450 NSString *avaliableType = [[info draggingPasteboard] availableTypeFromArray:[NSArray arrayWithObject:STATE_DRAG_TYPE]];
451 if ([avaliableType isEqualToString:STATE_DRAG_TYPE]) {
452 [[adium statusController] setDelayStatusMenuRebuilding:YES];
454 if (!item) item = [[adium statusController] rootStateGroup];
456 NSEnumerator *enumerator;
457 AIStatusItem *statusItem;
459 enumerator = [draggingItems objectEnumerator];
461 while ((statusItem = [enumerator nextObject])) {
462 if ([statusItem containingStatusGroup] == item) {
463 BOOL shouldIncrement = NO;
464 if ([[[statusItem containingStatusGroup] containedStatusItems] indexOfObject:statusItem] > index) {
465 shouldIncrement = YES;
468 //Move the state and select it in the new location
469 [item moveStatusItem:statusItem toIndex:index];
471 if (shouldIncrement) index++;
473 //Don't let an object be moved into itself...
474 if (item != statusItem) {
476 [[statusItem containingStatusGroup] removeStatusItem:statusItem];
477 [item addStatusItem:statusItem atIndex:index];
478 [statusItem release];
485 //Notify and reselect outside of the NSOutlineView callback
486 [self performSelector:@selector(reselectDraggedItems:)
487 withObject:draggingItems
490 [draggingItems release]; draggingItems = nil;
498 - (void)reselectDraggedItems:(NSArray *)theDraggedItems
500 [[adium statusController] setDelayStatusMenuRebuilding:NO];
502 [outlineView_stateList selectItemsInArray:theDraggedItems];
503 [outlineView_stateList scrollRowToVisible:[outlineView_stateList rowForItem:[theDraggedItems objectAtIndex:0]]];
507 * @brief Set up KFTypeSelectTableView
509 * Only search the "name" column.
511 - (void)configureTypeSelectTableView:(KFTypeSelectTableView *)tableView
513 [tableView setSearchColumnIdentifiers:[NSSet setWithObject:@"name"]];
516 #pragma mark Other status-related controls
519 * @brief Configure initial values for idle, auto-away, etc., preferences.
522 - (void)configureOtherControls
524 NSDictionary *prefDict = [[adium preferenceController] preferencesForGroup:PREF_GROUP_STATUS_PREFERENCES];
526 [checkBox_idle setState:[[prefDict objectForKey:KEY_STATUS_REPORT_IDLE] boolValue]];
527 [textField_idleMinutes setDoubleValue:([[prefDict objectForKey:KEY_STATUS_REPORT_IDLE_INTERVAL] doubleValue] / 60.0)];
529 [checkBox_autoAway setState:[[prefDict objectForKey:KEY_STATUS_AUTO_AWAY] boolValue]];
530 [textField_autoAwayMinutes setDoubleValue:([[prefDict objectForKey:KEY_STATUS_AUTO_AWAY_INTERVAL] doubleValue] / 60.0)];
532 [checkBox_fastUserSwitching setState:[[prefDict objectForKey:KEY_STATUS_FUS] boolValue]];
534 [checkBox_showStatusWindow setState:[[prefDict objectForKey:KEY_STATUS_SHOW_STATUS_WINDOW] boolValue]];
536 [self configureControlDimming];
540 * @brief Configure the pop up of states for autoAway.
542 * Should be called by stateArrayChanged: both for initial set up and for updating when the states change.
544 - (void)configureAutoAwayStatusStatePopUp
546 NSMenu *statusStatesMenu;
547 NSNumber *targetUniqueStatusIDNumber;
549 statusStatesMenu = [AIStatusMenu staticStatusStatesMenuNotifyingTarget:self selector:@selector(changedAutoAwayStatus:)];
550 [popUp_autoAwayStatusState setMenu:statusStatesMenu];
552 statusStatesMenu = [AIStatusMenu staticStatusStatesMenuNotifyingTarget:self selector:@selector(changedFastUserSwitchingStatus:)];
553 [popUp_fastUserSwitchingStatusState setMenu:[[statusStatesMenu copy] autorelease]];
555 //Now select the proper state, or deselect all items if there is no chosen state or the chosen state doesn't exist
556 targetUniqueStatusIDNumber = [[adium preferenceController] preferenceForKey:KEY_STATUS_AUTO_AWAY_STATUS_STATE_ID
557 group:PREF_GROUP_STATUS_PREFERENCES];
558 [self _selectStatusWithUniqueID:targetUniqueStatusIDNumber inPopUpButton:popUp_autoAwayStatusState];
560 targetUniqueStatusIDNumber = [[adium preferenceController] preferenceForKey:KEY_STATUS_FUS_STATUS_STATE_ID
561 group:PREF_GROUP_STATUS_PREFERENCES];
562 [self _selectStatusWithUniqueID:targetUniqueStatusIDNumber inPopUpButton:popUp_fastUserSwitchingStatusState];
566 * @brief Add all items in inMenu to an array, returning the resulting array
568 * This method adds items deeply; that is, submenus and their contents are recursively included
570 * @param inMenu The menu to start from
571 * @param recursiveArray The array thus far; if nil an array will be created
573 * @result All the menu items in inMenu
575 - (NSMutableArray *)addItemsFromMenu:(NSMenu *)inMenu toArray:(NSMutableArray *)recursiveArray
577 NSArray *itemArray = [inMenu itemArray];
578 NSEnumerator *enumerator;
579 NSMenuItem *menuItem;
581 if (!recursiveArray) recursiveArray = [NSMutableArray array];
583 enumerator = [itemArray objectEnumerator];
584 while ((menuItem = [enumerator nextObject])) {
585 [recursiveArray addObject:menuItem];
587 if ([menuItem submenu]) {
588 [self addItemsFromMenu:[menuItem submenu] toArray:recursiveArray];
592 return recursiveArray;
596 * @brief Select a status with uniqueID in inPopUpButton
598 - (void)_selectStatusWithUniqueID:(NSNumber *)uniqueID inPopUpButton:(NSPopUpButton *)inPopUpButton
600 NSMenuItem *menuItem = nil;
603 int targetUniqueStatusID= [uniqueID intValue];
604 NSEnumerator *enumerator;
606 enumerator = [[self addItemsFromMenu:[inPopUpButton menu] toArray:nil] objectEnumerator];
608 while ((menuItem = [enumerator nextObject])) {
609 AIStatusItem *statusState;
611 statusState = [[menuItem representedObject] objectForKey:@"AIStatus"];
613 //Found the right status by matching its status ID to our preferred one
614 if ([statusState preexistingUniqueStatusID] == targetUniqueStatusID) {
621 [inPopUpButton selectItem:menuItem];
623 //Add it if we weren't able to select it initially
624 if (![inPopUpButton selectedItem]) {
625 [self addItemIfNeeded:menuItem toPopUpButton:inPopUpButton alreadyShowingAnItem:NO];
627 if (inPopUpButton == popUp_autoAwayStatusState) {
628 showingSubmenuItemInAutoAway = YES;
630 } else if (inPopUpButton == popUp_fastUserSwitchingStatusState) {
631 showingSubmenuItemInFastUserSwitching = YES;
639 * @brief Configure control dimming for idle, auto-away, etc., preferences.
641 - (void)configureControlDimming
643 BOOL idleControlsEnabled, autoAwayControlsEnabled;
645 idleControlsEnabled = ([checkBox_idle state] == NSOnState);
646 [textField_idleMinutes setEnabled:idleControlsEnabled];
647 [stepper_idleMinutes setEnabled:idleControlsEnabled];
649 autoAwayControlsEnabled = ([checkBox_autoAway state] == NSOnState);
650 [popUp_autoAwayStatusState setEnabled:autoAwayControlsEnabled];
651 [textField_autoAwayMinutes setEnabled:autoAwayControlsEnabled];
652 [stepper_autoAwayMinutes setEnabled:autoAwayControlsEnabled];
654 [popUp_fastUserSwitchingStatusState setEnabled:([checkBox_fastUserSwitching state] == NSOnState)];
658 * @brief Change preference
660 * Sent when controls are clicked
662 - (void)changePreference:(id)sender
664 if (sender == checkBox_idle) {
665 [[adium preferenceController] setPreference:[NSNumber numberWithBool:[sender state]]
666 forKey:KEY_STATUS_REPORT_IDLE
667 group:PREF_GROUP_STATUS_PREFERENCES];
668 [self configureControlDimming];
670 } else if (sender == checkBox_autoAway) {
671 [[adium preferenceController] setPreference:[NSNumber numberWithBool:[sender state]]
672 forKey:KEY_STATUS_AUTO_AWAY
673 group:PREF_GROUP_STATUS_PREFERENCES];
674 [self configureControlDimming];
676 } else if (sender == checkBox_showStatusWindow) {
677 [[adium preferenceController] setPreference:[NSNumber numberWithBool:[sender state]]
678 forKey:KEY_STATUS_SHOW_STATUS_WINDOW
679 group:PREF_GROUP_STATUS_PREFERENCES];
681 } else if (sender == checkBox_fastUserSwitching) {
682 [[adium preferenceController] setPreference:[NSNumber numberWithBool:[sender state]]
683 forKey:KEY_STATUS_FUS
684 group:PREF_GROUP_STATUS_PREFERENCES];
685 [self configureControlDimming];
691 * @brief If menuItem is not selectable in popUpButton, add it and select it
693 * Menu items located within submenus can't be directly selected. This method will add a spearator item and then the item itself
694 * to the bottom of popUpButton if needed. alreadyShowing should be YES if a similarly set separate + item exists; it will be removed
697 * @result YES if the item was added to popUpButton.
699 - (BOOL)addItemIfNeeded:(NSMenuItem *)menuItem toPopUpButton:(NSPopUpButton *)popUpButton alreadyShowingAnItem:(BOOL)alreadyShowing
701 BOOL nowShowing = NO;
702 NSMenu *menu = [popUpButton menu];
705 if (alreadyShowing) {
706 int count = [menu numberOfItems];
707 [menu removeItemAtIndex:--count];
708 [menu removeItemAtIndex:--count];
711 if ([popUpButton selectedItem] != menuItem) {
712 NSMenuItem *imitationMenuItem = [menuItem copy];
714 [menu addItem:[NSMenuItem separatorItem]];
715 [menu addItem:imitationMenuItem];
717 [popUpButton selectItem:imitationMenuItem];
718 [imitationMenuItem release];
726 - (void)changedAutoAwayStatus:(id)sender
728 AIStatus *statusState = [[sender representedObject] objectForKey:@"AIStatus"];
730 [[adium preferenceController] setPreference:[statusState uniqueStatusID]
731 forKey:KEY_STATUS_AUTO_AWAY_STATUS_STATE_ID
732 group:PREF_GROUP_STATUS_PREFERENCES];
734 showingSubmenuItemInAutoAway = [self addItemIfNeeded:sender
735 toPopUpButton:popUp_autoAwayStatusState
736 alreadyShowingAnItem:showingSubmenuItemInAutoAway];
739 - (void)changedFastUserSwitchingStatus:(id)sender
741 AIStatus *statusState = [[sender representedObject] objectForKey:@"AIStatus"];
743 [[adium preferenceController] setPreference:[statusState uniqueStatusID]
744 forKey:KEY_STATUS_FUS_STATUS_STATE_ID
745 group:PREF_GROUP_STATUS_PREFERENCES];
747 showingSubmenuItemInFastUserSwitching = [self addItemIfNeeded:sender
748 toPopUpButton:popUp_fastUserSwitchingStatusState
749 alreadyShowingAnItem:showingSubmenuItemInFastUserSwitching];
753 * @brief Control text did end editing
755 * In an attempt to get closer to a live-apply of preferences, save the preference when the
756 * text field loses focus. See saveTimeValues for more information.
758 - (void)controlTextDidEndEditing:(NSNotification *)notification
760 [self saveTimeValues];
764 * @brief Save time text field values
766 * We can't get notified when the associated NSStepper is clicked, so we just save as requested.
767 * This method should be called before the view closes.
769 - (void)saveTimeValues
771 [[adium preferenceController] setPreference:[NSNumber numberWithDouble:([textField_idleMinutes doubleValue]*60.0)]
772 forKey:KEY_STATUS_REPORT_IDLE_INTERVAL
773 group:PREF_GROUP_STATUS_PREFERENCES];
775 [[adium preferenceController] setPreference:[NSNumber numberWithDouble:([textField_autoAwayMinutes doubleValue]*60.0)]
776 forKey:KEY_STATUS_AUTO_AWAY_INTERVAL
777 group:PREF_GROUP_STATUS_PREFERENCES];