2 * Adium is the legal property of its developers, whose names are listed in the copyright file included
3 * with this source distribution.
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.
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.
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.
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;
32 * @class AIStateMenuPlugin
33 * @brief Implements a list of preset states in the status menu
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.
39 @implementation AIStateMenuPlugin
42 * @brief Initialize the state menu plugin
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.
49 //Wait for Adium to finish launching before we perform further actions
50 [[adium notificationCenter] addObserver:self
51 selector:@selector(adiumFinishedLaunching:)
52 name:AIApplicationDidFinishLoadingNotification
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)
62 action:@selector(dummyAction:)
64 [[adium menuController] addMenuItem:dockStatusMenuRoot toLocation:LOC_Dock_Status];
67 statusMenu = [[AIStatusMenu statusMenuWithDelegate:self] retain];
69 [[adium notificationCenter] addObserver:self
70 selector:@selector(stateMenuSelectionsChanged:)
71 name:AIStatusActiveStateChangedNotification
76 - (void)uninstallPlugin
78 [[adium notificationCenter] removeObserver:self];
80 [accountMenu release]; accountMenu = nil;
81 [statusMenu release]; statusMenu = nil;
85 * @brief Add state menu items to our location
87 * Implemented as required by the StateMenuPlugin protocol. Also assigns key equivalents to appropriate
88 * menu items depending on the current status.
90 * @param menuItemArray An <tt>NSArray</tt> of <tt>NSMenuItem</tt> objects to be added to the menu
92 - (void)statusMenu:(AIStatusMenu *)inStatusMenu didRebuildStatusMenuItems:(NSArray *)menuItemArray
94 NSEnumerator *enumerator;
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];
104 dockMenuItem = [menuItem copy];
105 [dockStatusMenu addItem:dockMenuItem];
106 [dockMenuItem release];
109 [dockStatusMenuRoot setSubmenu:dockStatusMenu];
111 //Tell the status controller to update these items as necessary
112 [statusMenu delegateCreatedMenuItems:[dockStatusMenu itemArray]];
113 [dockStatusMenu release];
115 if (currentMenuItemArray != menuItemArray) {
116 [currentMenuItemArray release]; currentMenuItemArray = [menuItemArray retain];
119 [self updateKeyEquivalents];
122 - (void)statusMenu:(AIStatusMenu *)inStatusMenu willRemoveStatusMenuItems:(NSArray *)inMenuItems
124 if ([inMenuItems count]) {
125 NSEnumerator *enumerator;
126 NSMenuItem *menuItem;
128 NSMenu *menubarMenu = [(NSMenuItem *)[inMenuItems objectAtIndex:0] menu];
129 [menubarMenu setMenuChangedMessagesEnabled:NO];
131 enumerator = [inMenuItems objectEnumerator];
132 while ((menuItem = [enumerator nextObject])) {
133 [[adium menuController] removeMenuItem:menuItem];
136 [menubarMenu setMenuChangedMessagesEnabled:YES];
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.
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;
158 if (activeStatusType == AIAvailableStatusType) {
159 //If currently available, set an equivalent for the base away
160 targetStatusType = AIAwayStatusType;
161 targetStatusState = nil;
162 assignCmdOptionY = NO;
165 //If away, invisible, or offline, set an equivalent for the available state
166 targetStatusType = AIAvailableStatusType;
167 targetStatusState = [[adium statusController] defaultInitialStatusState];
168 assignCmdOptionY = YES;
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)];
185 } else if ((tag == AIAvailableStatusType) && (representedStatus == nil)) {
186 [menuItem setKeyEquivalent:@"Y"];
187 [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask];
190 [menuItem setKeyEquivalent:@""];
197 * @brief State menu selections changed
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
213 - (void)accountMenu:(AIAccountMenu *)inAccountMenu didRebuildMenuItems:(NSArray *)menuItems
215 NSEnumerator *enumerator;
216 NSMenuItem *menuItem;
218 //Remove any existing menu items
219 enumerator = [installedMenuItems objectEnumerator];
220 while ((menuItem = [enumerator nextObject])) {
221 [[adium menuController] removeMenuItem:menuItem];
224 //Add the new menu items
225 enumerator = [menuItems objectEnumerator];
226 while ((menuItem = [enumerator nextObject])) {
227 [[adium menuController] addMenuItem:menuItem toLocation:LOC_Status_Accounts];
230 //Remember the installed items so we can remove them later
231 if (installedMenuItems != menuItems) {
232 [installedMenuItems release];
233 installedMenuItems = [menuItems retain];
237 - (void)accountMenu:(AIAccountMenu *)inAccountMenu didSelectAccount:(AIAccount *)inAccount {
238 [inAccount toggleOnline];
241 - (BOOL)accountMenuShouldIncludeAddAccountsMenu:(AIAccountMenu *)inAccountMenu
246 - (BOOL)accountMenuShouldIncludeDisabledAccountsMenu:(AIAccountMenu *)inAccountMenu