* Fixed the objectSpecifier of `AIStatusItem`s to be based on the unique ID rather...
[adiumx.git] / Source / AIStateMenuPlugin.m
blobef2097694feb02ba6e9378b2fe8230568ef90746
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  */
17 #import "AIStateMenuPlugin.h"
18 #import <Adium/AIAccountControllerProtocol.h>
19 #import "AIEditStateWindowController.h"
20 #import <Adium/AIMenuControllerProtocol.h>
21 #import "AIStatusController.h"
22 #import <AIUtilities/AIMenuAdditions.h>
23 #import <Adium/AIAccountMenu.h>
24 #import <Adium/AIAccount.h>
25 #import <Adium/AIStatusMenu.h>
27 @interface AIStateMenuPlugin (PRIVATE)
28 - (void)updateKeyEquivalents;
29 @end
31 /*!
32  * @class AIStateMenuPlugin
33  * @brief Implements a list of preset states in the status menu
34  *
35  * This plugin places a list of preset states in the status menu, allowing the user to easily view and change the
36  * active state.  It also manages a list of accounts in the status menu with associate statuses for setting account
37  * statuses individually.
38  */
39 @implementation AIStateMenuPlugin
41 /*!
42  * @brief Initialize the state menu plugin
43  *
44  * Initialize the state menu, registering this class as a state menu plugin.  The status controller will then instruct
45  * us to add and remove state menu items and handle all other details on its own.
46  */
47 - (void)installPlugin
49         //Wait for Adium to finish launching before we perform further actions
50         [[adium notificationCenter] addObserver:self
51                                                                    selector:@selector(adiumFinishedLaunching:)
52                                                                            name:AIApplicationDidFinishLoadingNotification
53                                                                          object:nil];
56 - (void)adiumFinishedLaunching:(NSNotification *)notification
58         accountMenu = [[AIAccountMenu accountMenuWithDelegate:self submenuType:AIAccountStatusSubmenu showTitleVerbs:NO] retain];
60         dockStatusMenuRoot = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:AILocalizedString(@"Status",nil)
61                                                                                                                                                           target:self
62                                                                                                                                                           action:@selector(dummyAction:)
63                                                                                                                                            keyEquivalent:@""];
64         [[adium menuController] addMenuItem:dockStatusMenuRoot toLocation:LOC_Dock_Status];
66         
67         statusMenu = [[AIStatusMenu statusMenuWithDelegate:self] retain];
69         [[adium notificationCenter] addObserver:self
70                                                                    selector:@selector(stateMenuSelectionsChanged:)
71                                                                            name:AIStatusActiveStateChangedNotification
72                                                                          object:nil];
73                 
76 - (void)uninstallPlugin
78         [[adium notificationCenter] removeObserver:self];
79         
80         [accountMenu release]; accountMenu = nil;
81         [statusMenu release]; statusMenu = nil;
84 /*!
85  * @brief Add state menu items to our location
86  *
87  * Implemented as required by the StateMenuPlugin protocol.  Also assigns key equivalents to appropriate
88  * menu items depending on the current status.
89  *
90  * @param menuItemArray An <tt>NSArray</tt> of <tt>NSMenuItem</tt> objects to be added to the menu
91  */
92 - (void)statusMenu:(AIStatusMenu *)inStatusMenu didRebuildStatusMenuItems:(NSArray *)menuItemArray
94         NSEnumerator    *enumerator;
95         NSMenuItem              *menuItem;
96         NSMenu                  *dockStatusMenu = [[NSMenu allocWithZone:[NSMenu zone]] init];
98         enumerator = [menuItemArray objectEnumerator];
99     while ((menuItem = [enumerator nextObject])) {
100                 NSMenuItem      *dockMenuItem;
102                 [[adium menuController] addMenuItem:menuItem toLocation:LOC_Status_State];
103                 
104                 dockMenuItem = [menuItem copy];
105                 [dockStatusMenu addItem:dockMenuItem];
106                 [dockMenuItem release];
107     }
108         
109         [dockStatusMenuRoot setSubmenu:dockStatusMenu];
111         //Tell the status controller to update these items as necessary
112         [statusMenu delegateCreatedMenuItems:[dockStatusMenu itemArray]];
113         [dockStatusMenu release];
114         
115         if (currentMenuItemArray != menuItemArray) {
116                 [currentMenuItemArray release]; currentMenuItemArray = [menuItemArray retain];
117         }
119         [self updateKeyEquivalents];
122 - (void)statusMenu:(AIStatusMenu *)inStatusMenu willRemoveStatusMenuItems:(NSArray *)inMenuItems
124         if ([inMenuItems count]) {
125                 NSEnumerator    *enumerator;
126                 NSMenuItem              *menuItem;
127                 
128                 NSMenu                  *menubarMenu = [(NSMenuItem *)[inMenuItems objectAtIndex:0] menu];
129                 [menubarMenu setMenuChangedMessagesEnabled:NO];
130                 
131                 enumerator = [inMenuItems objectEnumerator];
132                 while ((menuItem = [enumerator nextObject])) {
133                         [[adium menuController] removeMenuItem:menuItem];
134                 }
135                 
136                 [menubarMenu setMenuChangedMessagesEnabled:YES];
137         }
140 - (void)dummyAction:(id)sender {};
143  * @brief Update key equivalents for our main status menu
145  * When available, cmd-y is mapped to custom away.
146  * When away, cmd-y is mapped to available and cmd-option-y is always mapped to custom away.
147  */
148 - (void)updateKeyEquivalents
150         NSEnumerator    *enumerator;
151         NSMenuItem              *menuItem;
153         AIStatusType    activeStatusType = [[adium statusController] activeStatusTypeTreatingInvisibleAsAway:YES];
154         AIStatusType    targetStatusType = AIAvailableStatusType;
155         AIStatus                *targetStatusState = nil;
156         BOOL                    assignCmdOptionY;
157         
158         if (activeStatusType == AIAvailableStatusType) {
159                 //If currently available, set an equivalent for the base away
160                 targetStatusType = AIAwayStatusType;
161                 targetStatusState = nil;
162                 assignCmdOptionY = NO;
164         } else {
165                 //If away, invisible, or offline, set an equivalent for the available state
166                 targetStatusType = AIAvailableStatusType;               
167                 targetStatusState = [[adium statusController] defaultInitialStatusState];
168                 assignCmdOptionY = YES;
169         }
171         enumerator = [currentMenuItemArray objectEnumerator];
172     while ((menuItem = [enumerator nextObject])) {
173                 AIStatus        *representedStatus = [[menuItem representedObject] objectForKey:@"AIStatus"];
175                 int                     tag = [menuItem tag];
176                 if ((tag == targetStatusType) && 
177                    (representedStatus == targetStatusState)) {                  
178                         [menuItem setKeyEquivalent:@"y"];
179                         [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
181                 } else if (assignCmdOptionY && ((tag == AIAwayStatusType) && (representedStatus == nil))) {
182                         [menuItem setKeyEquivalent:@"y"];
183                         [menuItem setKeyEquivalentModifierMask:(NSCommandKeyMask | NSAlternateKeyMask)];
184                         
185                 } else if ((tag == AIAvailableStatusType) && (representedStatus == nil)) {
186                         [menuItem setKeyEquivalent:@"Y"];
187                         [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
188                         
189                 } else {
190                         [menuItem setKeyEquivalent:@""];
191                         
192                 }
193         }
197  * @brief State menu selections changed
198  */
199 - (void)stateMenuSelectionsChanged:(NSNotification *)notification
201         [self updateKeyEquivalents];
204 #pragma mark Account menu items
207 * @brief Add account menu items to our location
209  * Implemented as required by the AccountMenuPlugin protocol.
211  * @param menuItemArray An <tt>NSArray</tt> of <tt>NSMenuItem</tt> objects to be added to the menu
212  */
213 - (void)accountMenu:(AIAccountMenu *)inAccountMenu didRebuildMenuItems:(NSArray *)menuItems
215         NSEnumerator    *enumerator;
216         NSMenuItem              *menuItem;
217         
218         //Remove any existing menu items
219         enumerator = [installedMenuItems objectEnumerator];
220     while ((menuItem = [enumerator nextObject])) {    
221                 [[adium menuController] removeMenuItem:menuItem];
222     }
223         
224         //Add the new menu items
225         enumerator = [menuItems objectEnumerator];
226     while ((menuItem = [enumerator nextObject])) {    
227                 [[adium menuController] addMenuItem:menuItem toLocation:LOC_Status_Accounts];
228     }
229         
230         //Remember the installed items so we can remove them later
231         if (installedMenuItems != menuItems) {
232                 [installedMenuItems release];
233                 installedMenuItems = [menuItems retain];
234         }
237 - (void)accountMenu:(AIAccountMenu *)inAccountMenu didSelectAccount:(AIAccount *)inAccount {
238         [inAccount toggleOnline];
241 - (BOOL)accountMenuShouldIncludeAddAccountsMenu:(AIAccountMenu *)inAccountMenu
243         return NO;
246 - (BOOL)accountMenuShouldIncludeDisabledAccountsMenu:(AIAccountMenu *)inAccountMenu
248         return YES;
251 @end