French updates
[adiumx.git] / Source / AIMenuController.m
blob9deb00d102e4b12f06427456000299c35170de99
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 // $Id$
19 #import "AIMenuController.h"
20 #import <Adium/AIAccount.h>
21 #import <Adium/AIChat.h>
22 #import <Adium/AIListContact.h>
23 #import <Adium/AIListObject.h>
24 #import <Adium/AIMetaContact.h>
25 #import <AIUtilities/AIMenuAdditions.h>
26 #import <AIUtilities/AIStringAdditions.h>
28 @interface AIMenuController (PRIVATE)
29 - (void)localizeMenuTitles;
30 - (NSMenu *)contextualMenuWithLocations:(NSArray *)inLocationArray usingMenu:(NSMenu *)inMenu;
31 - (void)addMenuItemsForContact:(AIListContact *)inContact toMenu:(NSMenu *)workingMenu separatorItem:(BOOL *)separatorItem;
32 @end
34 @implementation AIMenuController
36 //Init
37 - (void)initController
39         //Build the array of menu locations
40         locationArray = [[NSMutableArray alloc] initWithObjects:menu_Adium_About, menu_Adium_Preferences,
41                 menu_File_New, menu_File_Close, menu_File_Save, menu_File_Additions,    
42                 menu_Edit_Bottom, menu_Edit_Additions,
43                 menu_View_General, menu_View_Unnamed_A, menu_View_Unnamed_B, menu_View_Unnamed_C, 
44                 menu_Contact_Manage, menu_Contact_Info, menu_Contact_Action, menu_Contact_NegativeAction, menu_Contact_Additions,
45                 menu_Status_State, menu_Status_Accounts, menu_Status_Additions,
46                 menu_Format_Styles, menu_Format_Palettes, menu_Format_Additions,
47                 menu_Window_Top, menu_Window_Commands, menu_Window_Auxiliary, menu_Window_Fixed,
48                 menu_Help_Local, menu_Help_Web, menu_Help_Additions,
49                 menu_Dock_Status, nil];
51         //Set up our contextual menu stuff
52         contextualMenu = [[NSMenu alloc] init];
53         contextualMenuItemDict = [[NSMutableDictionary alloc] init];
54         currentContextMenuObject = nil;
55         textViewContextualMenu = [[NSMenu alloc] init];
56         contextualMenu_TextView = nil;
58         [self localizeMenuTitles];
61 //Close
62 - (void)closeController
64         //There's no need to remove the menu items, the system will take them out for us.
67 //Add a menu item
68 - (void)addMenuItem:(NSMenuItem *)newItem toLocation:(MENU_LOCATION)location
70         NSMenuItem  *menuItem;
71         NSMenu          *targetMenu = nil;
72         int                     targetIndex;
73         int                     destination;
75         //Find the menu item (or the closest one above it)
76         destination = location;
77         menuItem = [locationArray objectAtIndex:destination];
78         while((menuItem == nilMenuItem) && (destination > 0)) {
79                 destination--;
80                 menuItem = [locationArray objectAtIndex:destination];
81         }
82         if([menuItem isKindOfClass:[NSMenuItem class]]) {
83                 //If attached to a menu item, insert below that item
84                 targetMenu = [menuItem menu];
85                 targetIndex = [targetMenu indexOfItem:menuItem];
86         } else {
87                 //If it's attached to an NSMenu (and not an NSMenuItem), insert at the top of the menu
88                 targetMenu = (NSMenu *)menuItem;
89                 targetIndex = -1;
90         }
92         //Insert the new item and a divider (if necessary)
93         if(location != destination) {
94                 [targetMenu insertItem:[NSMenuItem separatorItem] atIndex:++targetIndex];
95         }
96         [targetMenu insertItem:newItem atIndex:targetIndex+1];
98         //update the location array
99         [locationArray replaceObjectAtIndex:location withObject:newItem];
101         [[adium notificationCenter] postNotificationName:Menu_didChange object:[newItem menu] userInfo:nil];
104 //Remove a menu item
105 - (void)removeMenuItem:(NSMenuItem *)targetItem
107         NSMenu          *targetMenu = [targetItem menu];
108         int                     targetIndex = [targetMenu indexOfItem:targetItem];
109         unsigned        loop, maxLoop;
111         //Fix the pointer if this is one
112         for(loop = 0, maxLoop = [locationArray count]; loop < maxLoop; loop++) {
113                 NSMenuItem      *menuItem = [locationArray objectAtIndex:loop];
115                 //Move to the item above it, nil if a divider
116                 if(menuItem == targetItem) {
117                         if(targetIndex != 0) {
118                                 NSMenuItem      *previousItem = [targetMenu itemAtIndex:(targetIndex - 1)];
120                                 if([previousItem isSeparatorItem]) {
121                                         [locationArray replaceObjectAtIndex:loop withObject:nilMenuItem];
122                                 } else {
123                                         [locationArray replaceObjectAtIndex:loop withObject:previousItem];
124                                 }
125                         } else {
126                                 //If there are no more items, attach to the menu
127                                 [locationArray replaceObjectAtIndex:loop withObject:targetMenu];
128                         }
129                 }
130         }
132         //Remove the item
133         [targetMenu removeItem:targetItem];
135         //Remove any double dividers (And dividers at the bottom)
136         for(loop = 0; loop < [targetMenu numberOfItems]; loop++) {
137                 if(([[targetMenu itemAtIndex:loop] isSeparatorItem]) && 
138                    (loop == [targetMenu numberOfItems]-1 || [[targetMenu itemAtIndex:loop+1] isSeparatorItem])) {
139                         [targetMenu removeItemAtIndex:loop];
140                         loop--;//re-search the location
141                 }
142         }
144         [[adium notificationCenter] postNotificationName:Menu_didChange object:targetMenu userInfo:nil];
147 - (void)addContextualMenuItem:(NSMenuItem *)newItem toLocation:(CONTEXT_MENU_LOCATION)location
149         NSNumber                        *key;
150         NSMutableArray          *itemArray;
152         //Search for an existing item array for menu items in this location
153         key = [NSNumber numberWithInt:location];
154         itemArray = [contextualMenuItemDict objectForKey:key];
156         //If one is not found, create it
157         if(!itemArray) {
158                 itemArray = [[NSMutableArray alloc] init];
159                 [contextualMenuItemDict setObject:itemArray forKey:key];
160         }
162         //Add the passed menu item to the array
163         [itemArray addObject:newItem];
166 //Pass an array of NSNumbers corresponding to the desired contextual menu locations
167 - (NSMenu *)contextualMenuWithLocations:(NSArray *)inLocationArray forListObject:(AIListObject *)inObject
169         NSMenu          *workingMenu;
170         BOOL            separatorItem;
172         //Remember what our menu is configured for
173         [currentContextMenuObject release];
174         currentContextMenuObject = [inObject retain];
176         //Get the pre-created contextual menu items
177         workingMenu = [self contextualMenuWithLocations:inLocationArray usingMenu:contextualMenu];
179         //Add any account-specific menu items
180         separatorItem = YES;
181         if([inObject isKindOfClass:[AIMetaContact class]]) {
182                 NSEnumerator    *enumerator;
183                 AIListContact   *aListContact;
184                 enumerator = [[(AIMetaContact *)inObject listContacts] objectEnumerator];
186                 while(aListContact = [enumerator nextObject]) {
187                         [self addMenuItemsForContact:aListContact
188                                                                   toMenu:workingMenu
189                                                    separatorItem:&separatorItem];
190                 }
192         } else  if([inObject isKindOfClass:[AIListContact class]]) {
193                 [self addMenuItemsForContact:(AIListContact *)inObject
194                                                           toMenu:workingMenu
195                                            separatorItem:&separatorItem];
196         }
198         return(workingMenu);
201 - (NSMenu *)contextualMenuWithLocations:(NSArray *)inLocationArray forListObject:(AIListObject *)inObject inChat:(AIChat *)inChat
203         [currentContextMenuChat release];
204         currentContextMenuChat = [inChat retain];
205         
206         return [self contextualMenuWithLocations:inLocationArray forListObject:inObject];
209 //Add menuItems for a passed contact to a specified menu.  *seperatorItem can be YES to indicate that a 
210 //separator item should be inserted before the menu items if desired. It will then be set to NO.
211 - (void)addMenuItemsForContact:(AIListContact *)inContact toMenu:(NSMenu *)workingMenu separatorItem:(BOOL *)separatorItem
213         NSArray                 *itemArray = [[inContact account] menuItemsForContact:inContact];
215         if(itemArray && [itemArray count]) {
216                 NSEnumerator    *enumerator;
217                 NSMenuItem              *menuItem;
219                 if(*separatorItem == YES) {
220                         [workingMenu addItem:[NSMenuItem separatorItem]];
221                         *separatorItem = NO;
222                 }
224                 enumerator = [itemArray objectEnumerator];
225                 while(menuItem = [enumerator nextObject]) {
226                         [workingMenu addItem:menuItem];
227                 }
228         }
231 - (NSMenu *)contextualMenuWithLocations:(NSArray *)inLocationArray forTextView:(NSTextView *)inTextView
233         //remember menu config
234         [contextualMenu_TextView release];
235         contextualMenu_TextView = [inTextView retain];
237         return([self contextualMenuWithLocations:inLocationArray usingMenu:textViewContextualMenu]);
240 - (NSMenu *)contextualMenuWithLocations:(NSArray *)inLocationArray usingMenu:(NSMenu *)inMenu
242         NSEnumerator    *enumerator;
243         NSNumber                *location;
244         NSMenuItem              *menuItem;
245         BOOL                    itemsAbove = NO;
247         //Remove all items from the existing menu
248         [inMenu removeAllItems];
250         //Process each specified location
251         enumerator = [inLocationArray objectEnumerator];
252         while((location = [enumerator nextObject])) {
253                 NSArray                 *menuItems = [contextualMenuItemDict objectForKey:location];
254                 NSEnumerator    *itemEnumerator;
256                 //Add a seperator
257                 if(itemsAbove && [menuItems count]) {
258                         [inMenu addItem:[NSMenuItem separatorItem]];
259                         itemsAbove = NO;
260                 }
262                 //Add each menu item in the location
263                 itemEnumerator = [menuItems objectEnumerator];
264                 while((menuItem = [itemEnumerator nextObject])) {
265                         //Add the menu item
266                         [inMenu addItem:menuItem];
267                         itemsAbove = YES;
268                 }
269         }
271         return(inMenu);
274 - (AIListObject *)currentContextMenuObject
276         return(currentContextMenuObject);
279 - (AIChat *)currentContextMenuChat
281         return(currentContextMenuChat);
284 - (NSTextView *)contextualMenuTextView
286         return(contextualMenu_TextView);
289 - (void)removeItalicsKeyEquivalent
291         [menuItem_Format_Italics setKeyEquivalent:@""];
294 - (void)restoreItalicsKeyEquivalent
296         [menuItem_Format_Italics setKeyEquivalent:@"i"];
299 - (void)localizeMenuTitles
301         //Menu items in MainMenu.nib for localization purposes
302         [menuItem_file setTitle:AILocalizedString(@"File",nil)];
303         [menuItem_edit setTitle:AILocalizedString(@"Edit",nil)];
304         [menuItem_view setTitle:AILocalizedString(@"View",nil)];
305         [menuItem_status setTitle:AILocalizedString(@"Status",nil)];
306         [menuItem_contact setTitle:AILocalizedString(@"Contact",nil)];
307         [menuItem_format setTitle:AILocalizedString(@"Format",nil)];
308         [menuItem_window setTitle:AILocalizedString(@"Window",nil)];
309         [menuItem_help setTitle:AILocalizedString(@"Help",nil)];
311         //Adium menu
312         [menuItem_aboutAdium setTitle:AILocalizedString(@"About Adium",nil)];
313         [menuItem_adiumXtras setTitle:AILocalizedString(@"Adium Xtras",nil)];
314         [menuItem_preferences setTitle:AILocalizedString(@"Preferences...",nil)];
315         [menuItem_services setTitle:AILocalizedString(@"Services","Services menu item in the Adium menu")];
316         [menuItem_hideAdium setTitle:AILocalizedString(@"Hide Adium",nil)];
317         [menuItem_hideOthers setTitle:AILocalizedString(@"Hide Others",nil)];
318         [menuItem_showAll setTitle:AILocalizedString(@"Show All",nil)];
319         [menuItem_quitAdium setTitle:AILocalizedString(@"Quit Adium",nil)];
321         //File menu
322         [menuItem_close setTitle:AILocalizedString(@"Close",nil)];
323         [menuItem_closeChat setTitle:AILocalizedString(@"Close Chat",nil)];
324         [menuItem_saveAs setTitle:AILocalizedString(@"Save As...",nil)];
325         [menuItem_pageSetup setTitle:AILocalizedString(@"Page Setup...",nil)];
326         [menuItem_print setTitle:AILocalizedString(@"Print...",nil)];
328         //Edit menu
329         [menuItem_cut setTitle:AILocalizedString(@"Cut",nil)];
330         [menuItem_copy setTitle:AILocalizedString(@"Copy",nil)];
331         [menuItem_paste setTitle:AILocalizedString(@"Paste",nil)];
332         [menuItem_pasteFormatted setTitle:AILocalizedString(@"Paste Formatted",nil)];
333         [menuItem_clear setTitle:AILocalizedString(@"Clear",nil)];
334         [menuItem_selectAll setTitle:AILocalizedString(@"Select All",nil)];
335         
336 #define TITLE_FIND AILocalizedString(@"Find",nil)
337         [menuItem_find setTitle:TITLE_FIND];
338         [menuItem_findCommand setTitle:[TITLE_FIND stringByAppendingEllipsis]];
339         [menuItem_findNext setTitle:AILocalizedString(@"Find Next",nil)];
340         [menuItem_findPrevious setTitle:AILocalizedString(@"Find Previous",nil)];
341         [menuItem_findUseSelectionForFind setTitle:AILocalizedString(@"Use Selection for Find",nil)];
342         [menuItem_findJumpToSelection setTitle:AILocalizedString(@"Jump to Selection",nil)];
343         
344 #define TITLE_SPELLING AILocalizedString(@"Spelling",nil)
345         [menuItem_spelling setTitle:TITLE_SPELLING];
346         [menuItem_spellingCommand setTitle:[TITLE_SPELLING stringByAppendingEllipsis]];
347         [menuItem_spellingCheckSpelling setTitle:AILocalizedString(@"Check Spelling",nil)];
348         [menuItem_spellingCheckSpellingAsYouType setTitle:AILocalizedString(@"Check Spelling As You Type",nil)];
350         [menuItem_speech setTitle:AILocalizedString(@"Speech",nil)];
351         [menuItem_startSpeaking setTitle:AILocalizedString(@"Start Speaking",nil)];
352         [menuItem_stopSpeaking setTitle:AILocalizedString(@"Stop Speaking",nil)];
353         
354         //View menu
355         [menuItem_customizeToolbar setTitle:AILocalizedString(@"Customize Toolbar...",nil)];
357         //Format menu
358         [menuItem_bold setTitle:AILocalizedString(@"Bold",nil)];
359         [menuItem_italic setTitle:AILocalizedString(@"Italic",nil)];
360         [menuItem_underline setTitle:AILocalizedString(@"Underline",nil)];
361         [menuItem_showFonts setTitle:AILocalizedString(@"Show Fonts",nil)];
362         [menuItem_showColors setTitle:AILocalizedString(@"Show Colors",nil)];
364         //Window menu
365         [menuItem_minimize setTitle:AILocalizedString(@"Minimize",nil)];
366         [menuItem_bringAllToFront setTitle:AILocalizedString(@"Bring All to Front",nil)];
368         //Help menu
369         [menuItem_adiumHelp setTitle:AILocalizedString(@"Adium Help",nil)];
370         [menuItem_reportABug setTitle:AILocalizedString(@"Report a Bug",nil)];
371         [menuItem_sendFeedback setTitle:AILocalizedString(@"Send Feedback",nil)];
372         [menuItem_adiumForums setTitle:AILocalizedString(@"Adium Forums",nil)];
375 @end