1 /*
2  * Copyright (C) Azureus Software, Inc, All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details ( see the LICENSE file ).
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18 
19 package org.gudy.azureus2.ui.swt.mainwindow;
20 
21 import java.io.BufferedInputStream;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.PrintWriter;
25 import java.io.StringWriter;
26 import java.net.URL;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.HashMap;
30 import java.util.Iterator;
31 import java.util.Locale;
32 import java.util.Map;
33 
34 import org.eclipse.swt.SWT;
35 import org.eclipse.swt.events.*;
36 import org.eclipse.swt.widgets.*;
37 import org.gudy.azureus2.core3.category.Category;
38 import org.gudy.azureus2.core3.category.CategoryManager;
39 import org.gudy.azureus2.core3.config.COConfigurationManager;
40 import org.gudy.azureus2.core3.config.ParameterListener;
41 import org.gudy.azureus2.core3.disk.DiskManagerFileInfo;
42 import org.gudy.azureus2.core3.download.DownloadManager;
43 import org.gudy.azureus2.core3.download.DownloadManagerState;
44 import org.gudy.azureus2.core3.internat.LocaleTorrentUtil;
45 import org.gudy.azureus2.core3.internat.LocaleUtilDecoder;
46 import org.gudy.azureus2.core3.internat.MessageText;
47 import org.gudy.azureus2.core3.logging.*;
48 import org.gudy.azureus2.core3.torrent.TOTorrent;
49 import org.gudy.azureus2.core3.torrent.TOTorrentAnnounceURLSet;
50 import org.gudy.azureus2.core3.torrent.TOTorrentFactory;
51 import org.gudy.azureus2.core3.torrent.TOTorrentFile;
52 import org.gudy.azureus2.core3.util.*;
53 import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
54 import org.gudy.azureus2.pluginsimpl.local.download.DownloadManagerImpl;
55 import org.gudy.azureus2.ui.common.util.MenuItemManager;
56 import org.gudy.azureus2.ui.swt.*;
57 import org.gudy.azureus2.ui.swt.beta.BetaWizard;
58 import org.gudy.azureus2.ui.swt.components.shell.ShellManager;
59 import org.gudy.azureus2.ui.swt.config.wizard.ConfigureWizard;
60 import org.gudy.azureus2.ui.swt.debug.UIDebugGenerator;
61 import org.gudy.azureus2.ui.swt.donations.DonationWindow;
62 import org.gudy.azureus2.ui.swt.exporttorrent.wizard.ExportTorrentWizard;
63 import org.gudy.azureus2.ui.swt.help.AboutWindow;
64 import org.gudy.azureus2.ui.swt.help.HealthHelpWindow;
65 import org.gudy.azureus2.ui.swt.importtorrent.wizard.ImportTorrentWizard;
66 import org.gudy.azureus2.ui.swt.maketorrent.NewTorrentWizard;
67 import org.gudy.azureus2.ui.swt.minibar.AllTransfersBar;
68 import org.gudy.azureus2.ui.swt.minibar.MiniBarManager;
69 import org.gudy.azureus2.ui.swt.nat.NatTestWindow;
70 import org.gudy.azureus2.ui.swt.plugins.UISWTInputReceiver;
71 import org.gudy.azureus2.ui.swt.pluginsinstaller.InstallPluginWizard;
72 import org.gudy.azureus2.ui.swt.pluginsuninstaller.UnInstallPluginWizard;
73 import org.gudy.azureus2.ui.swt.sharing.ShareUtils;
74 import org.gudy.azureus2.ui.swt.shells.CoreWaiterSWT;
75 import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
76 import org.gudy.azureus2.ui.swt.speedtest.SpeedTestWizard;
77 import org.gudy.azureus2.ui.swt.update.UpdateMonitor;
78 import org.gudy.azureus2.ui.swt.views.stats.StatsView;
79 import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;
80 import org.gudy.azureus2.ui.swt.views.table.utils.TableContextMenuManager;
81 import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
82 import org.gudy.azureus2.ui.swt.welcome.WelcomeWindow;
83 
84 import com.aelitis.azureus.core.*;
85 import com.aelitis.azureus.core.speedmanager.SpeedLimitHandler;
86 import com.aelitis.azureus.core.vuzefile.VuzeFileComponent;
87 import com.aelitis.azureus.core.vuzefile.VuzeFileHandler;
88 import com.aelitis.azureus.ui.UIFunctions;
89 import com.aelitis.azureus.ui.UIFunctionsManager;
90 import com.aelitis.azureus.ui.mdi.MdiEntry;
91 import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
92 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
93 import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
94 
95 import org.gudy.azureus2.plugins.PluginInterface;
96 import org.gudy.azureus2.plugins.ui.UIInputReceiver;
97 import org.gudy.azureus2.plugins.ui.UIInputReceiverListener;
98 import org.gudy.azureus2.plugins.ui.menus.MenuManager;
99 import org.gudy.azureus2.plugins.ui.tables.*;
100 import org.gudy.azureus2.plugins.update.Update;
101 import org.gudy.azureus2.plugins.update.UpdateCheckInstance;
102 import org.gudy.azureus2.plugins.update.UpdateCheckInstanceListener;
103 
104 public class MenuFactory
105 	implements IMenuConstants
106 {
107 
108 	private static boolean isAZ3 = "az3".equalsIgnoreCase(COConfigurationManager.getStringParameter("ui"));
109 
createFileMenuItem(Menu menuParent)110 	public static MenuItem createFileMenuItem(Menu menuParent) {
111 		return createTopLevelMenuItem(menuParent, MENU_ID_FILE);
112 	}
113 
createTransfersMenuItem(Menu menuParent)114 	public static MenuItem createTransfersMenuItem(Menu menuParent) {
115 		MenuItem transferMenuItem = createTopLevelMenuItem(menuParent,
116 				MENU_ID_TRANSFERS);
117 
118 		Menu transferMenu = transferMenuItem.getMenu();
119 
120 		MenuFactory.addStartAllMenuItem(transferMenu);
121 		MenuFactory.addStopAllMenuItem(transferMenu);
122 
123 		final MenuItem itemPause 	= MenuFactory.addPauseMenuItem(transferMenu);
124 		final MenuItem itemPauseFor = MenuFactory.addPauseForMenuItem(transferMenu);
125 		final MenuItem itemResume 	= MenuFactory.addResumeMenuItem(transferMenu);
126 		//		if (notMainWindow) {
127 		//			MenuFactory.performOneTimeDisable(itemPause, true);
128 		//			MenuFactory.performOneTimeDisable(itemResume, true);
129 		//		}
130 
131 		transferMenu.addMenuListener(new MenuListener() {
132 			public void menuShown(MenuEvent menu) {
133 				if (!AzureusCoreFactory.isCoreRunning()) {
134 					itemPause.setEnabled(true);
135 					itemResume.setEnabled(true);
136 				} else {
137 					AzureusCore core = AzureusCoreFactory.getSingleton();
138 					itemPause.setEnabled(core.getGlobalManager().canPauseDownloads());
139 					itemResume.setEnabled(core.getGlobalManager().canResumeDownloads());
140 				}
141 			}
142 
143 			public void menuHidden(MenuEvent menu) {
144 					// this behaviour required to get the accelerators to work properly as they won't fire if the menu item is
145 					// disabled even if if the menu were to be shown they would be...
146 				itemPause.setEnabled(true);
147 				itemResume.setEnabled(true);
148 			}
149 		});
150 
151 		return transferMenuItem;
152 	}
153 
createViewMenuItem(Menu menuParent)154 	public static MenuItem createViewMenuItem(Menu menuParent) {
155 		return createTopLevelMenuItem(menuParent, MENU_ID_VIEW);
156 	}
157 
createAdvancedMenuItem(Menu menuParent)158 	public static MenuItem createAdvancedMenuItem(Menu menuParent) {
159 		return createTopLevelMenuItem(menuParent, MENU_ID_ADVANCED);
160 	}
161 
createTorrentMenuItem(final Menu menuParent)162 	public static Menu createTorrentMenuItem(final Menu menuParent) {
163 		final Menu torrentMenu = createTopLevelMenuItem(menuParent,
164 				MENU_ID_TORRENT).getMenu();
165 
166 		/*
167 		 * The Torrents menu is context-sensitive to which torrent is selected in the UI.
168 		 * For this reason we need to dynamically build the menu when ever it is about to be displayed
169 		 * so that the states of the menu items accurately reflect what was selected in the UI.
170 		 */
171 		MenuBuildUtils.addMaintenanceListenerForMenu(torrentMenu,
172 				new MenuBuildUtils.MenuBuilder() {
173 					public void buildMenu(Menu menu, MenuEvent menuEvent) {
174 						buildTorrentMenu(menu);
175 					}
176 				});
177 		return torrentMenu;
178 	}
179 
buildTorrentMenu(Menu menu)180 	public static void buildTorrentMenu(Menu menu) {
181 		DownloadManager[] current_dls = (DownloadManager[]) menu.getData("downloads");
182 
183 		current_dls = ManagerUtils.cleanUp( current_dls );
184 
185 		if (current_dls.length == 0 ) {
186 			return;
187 		}
188 
189 
190 		if (AzureusCoreFactory.isCoreRunning()) {
191 			boolean is_detailed_view = ((Boolean) menu.getData("is_detailed_view")).booleanValue();
192 			TableViewSWT<?> tv = (TableViewSWT<?>) menu.getData("TableView");
193 			AzureusCore core = AzureusCoreFactory.getSingleton();
194 
195 			TorrentUtil.fillTorrentMenu(menu, current_dls, core,
196 					menu.getShell(), !is_detailed_view, 0, tv);
197 		}
198 
199 		org.gudy.azureus2.plugins.ui.menus.MenuItem[] menu_items;
200 
201 		menu_items = MenuItemManager.getInstance().getAllAsArray(
202 				new String[] {
203 					MenuManager.MENU_TORRENT_MENU,
204 					MenuManager.MENU_DOWNLOAD_CONTEXT
205 				});
206 
207 		final Object[] plugin_dls = DownloadManagerImpl.getDownloadStatic(current_dls);
208 
209 		if (menu_items.length > 0) {
210 			addSeparatorMenuItem(menu);
211 
212 			MenuBuildUtils.addPluginMenuItems(menu_items, menu, true, true,
213 					new MenuBuildUtils.MenuItemPluginMenuControllerImpl(plugin_dls));
214 		}
215 
216 		menu_items = null;
217 
218 		/**
219 		 * OK, "hack" time - we'll allow plugins which add menu items against
220 		 * a table to appear in this menu. We'll have to fake the table row
221 		 * object though. All downloads need to share a common table.
222 		 */
223 			String table_to_use = null;
224 		for (int i = 0; i < current_dls.length; i++) {
225 			String table_name = (current_dls[i].isDownloadComplete(false)
226 					? TableManager.TABLE_MYTORRENTS_COMPLETE
227 							: TableManager.TABLE_MYTORRENTS_INCOMPLETE);
228 			if (table_to_use == null || table_to_use.equals(table_name)) {
229 				table_to_use = table_name;
230 			} else {
231 				table_to_use = null;
232 				break;
233 			}
234 		}
235 
236 		if (table_to_use != null) {
237 			menu_items = TableContextMenuManager.getInstance().getAllAsArray(
238 					table_to_use);
239 		}
240 
241 		if (menu_items != null) {
242 			addSeparatorMenuItem(menu);
243 
244 			TableRow[] dls_as_rows = null;
245 			dls_as_rows = new TableRow[plugin_dls.length];
246 			for (int i = 0; i < plugin_dls.length; i++) {
247 				dls_as_rows[i] = wrapAsRow(plugin_dls[i], table_to_use);
248 			}
249 
250 			MenuBuildUtils.addPluginMenuItems(menu_items, menu, true, true,
251 					new MenuBuildUtils.MenuItemPluginMenuControllerImpl(dls_as_rows));
252 		}
253 
254 	}
255 
createToolsMenuItem(Menu menuParent)256 	public static MenuItem createToolsMenuItem(Menu menuParent) {
257 		return createTopLevelMenuItem(menuParent, MENU_ID_TOOLS);
258 	}
259 
260 	/**
261 	 * Creates the Plugins menu item and all it's children
262 	 * @param menuParent
263 	 * @param includeGetPluginsMenu if <code>true</code> then also include a menu item for getting new plugins
264 	 * @return
265 	 */
createPluginsMenuItem(final Menu menuParent, final boolean includeGetPluginsMenu)266 	public static MenuItem createPluginsMenuItem(final Menu menuParent,
267 			final boolean includeGetPluginsMenu) {
268 
269 		MenuItem pluginsMenuItem = createTopLevelMenuItem(menuParent,
270 				MENU_ID_PLUGINS);
271 		MenuBuildUtils.addMaintenanceListenerForMenu(pluginsMenuItem.getMenu(),
272 				new MenuBuildUtils.MenuBuilder() {
273 					public void buildMenu(Menu menu, MenuEvent menuEvent) {
274 						PluginsMenuHelper.getInstance().buildPluginMenu(menu,
275 								menuParent.getShell(), includeGetPluginsMenu);
276 					}
277 				});
278 
279 		return pluginsMenuItem;
280 	}
281 
createWindowMenuItem(Menu menuParent)282 	public static MenuItem createWindowMenuItem(Menu menuParent) {
283 		return createTopLevelMenuItem(menuParent, MENU_ID_WINDOW);
284 	}
285 
createHelpMenuItem(Menu menuParent)286 	public static MenuItem createHelpMenuItem(Menu menuParent) {
287 		return createTopLevelMenuItem(menuParent, MENU_ID_HELP);
288 	}
289 
addCreateMenuItem(Menu menuParent)290 	public static MenuItem addCreateMenuItem(Menu menuParent) {
291 		MenuItem file_create = addMenuItem(menuParent, MENU_ID_CREATE,
292 				new Listener() {
293 					public void handleEvent(Event e) {
294 						new NewTorrentWizard(e.display);
295 					}
296 				});
297 		return file_create;
298 	}
299 
createOpenMenuItem(Menu menuParent)300 	public static MenuItem createOpenMenuItem(Menu menuParent) {
301 		return createTopLevelMenuItem(menuParent, MENU_ID_OPEN);
302 	}
303 
addLogsViewMenuItem(Menu menuParent)304 	public static MenuItem addLogsViewMenuItem(Menu menuParent) {
305 		return createTopLevelMenuItem(menuParent, MENU_ID_LOG_VIEWS);
306 	}
307 
addOpenTorrentMenuItem(Menu menuParent)308 	public static MenuItem addOpenTorrentMenuItem(Menu menuParent) {
309 		return addMenuItem(menuParent, MENU_ID_OPEN_TORRENT, new Listener() {
310 			public void handleEvent(Event e) {
311 				UIFunctionsManagerSWT.getUIFunctionsSWT().openTorrentWindow();
312 			}
313 		});
314 	}
315 
316 	public static MenuItem addOpenURIMenuItem(Menu menuParent) {
317 		return addMenuItem(menuParent, MENU_ID_OPEN_URI, new Listener() {
318 			public void handleEvent(Event e) {
319 				UIFunctionsManagerSWT.getUIFunctionsSWT().openTorrentWindow();
320 			}
321 		});
322 	}
323 	public static MenuItem addOpenTorrentForTrackingMenuItem(Menu menuParent) {
324 		MenuItem file_new_torrent_for_tracking = addMenuItem(menuParent,
325 				MENU_ID_OPEN_TORRENT_FOR_TRACKING, new Listener() {
326 					public void handleEvent(Event e) {
327 						TorrentOpener.openTorrentTrackingOnly();
328 					}
329 				});
330 		return file_new_torrent_for_tracking;
331 	}
332 
333 	public static MenuItem addSearchMenuItem(Menu menuParent) {
334 		MenuItem item = addMenuItem(menuParent,
335 				"Button.search", new Listener() {
336 					public void handleEvent(Event e) {
337 						UIFunctionsManagerSWT.getUIFunctionsSWT().promptForSearch();
338 					}
339 				});
340 		return item;
341 	}
342 
343 
344 	public static MenuItem addOpenVuzeFileMenuItem(final Menu menuParent) {
345 		return addMenuItem(menuParent, MENU_ID_OPEN_VUZE_FILE, new Listener() {
346 			public void handleEvent(Event e) {
347 				Display display = menuParent.getDisplay();
348 
349 				display.asyncExec(new AERunnable() {
350 					public void runSupport() {
351 						FileDialog dialog = new FileDialog(menuParent.getShell(),
352 								SWT.SYSTEM_MODAL | SWT.OPEN);
353 
354 						dialog.setFilterPath(TorrentOpener.getFilterPathData());
355 
356 						dialog.setText(MessageText.getString("MainWindow.dialog.select.vuze.file"));
357 
358 						dialog.setFilterExtensions(new String[] {
359 							"*.vuze",
360 							"*.vuz",
361 							Constants.FILE_WILDCARD
362 						});
363 						dialog.setFilterNames(new String[] {
364 							"*.vuze",
365 							"*.vuz",
366 							Constants.FILE_WILDCARD
367 						});
368 
369 						String path = TorrentOpener.setFilterPathData(dialog.open());
370 
371 						if (path != null) {
372 
373 							VuzeFileHandler vfh = VuzeFileHandler.getSingleton();
374 
375 							if (vfh.loadAndHandleVuzeFile(path,
376 									VuzeFileComponent.COMP_TYPE_NONE) == null) {
377 
378 								TorrentOpener.openTorrent(path);
379 							}
380 						}
381 					}
382 				});
383 			}
384 		});
385 	}
386 
387 	public static MenuItem createShareMenuItem(Menu menuParent) {
388 		MenuItem file_share = createTopLevelMenuItem(menuParent, MENU_ID_SHARE);
389 		return file_share;
390 	}
391 
392 	public static MenuItem addShareFileMenuItem(final Menu menuParent) {
393 
394 		MenuItem file_share_file = addMenuItem(menuParent, MENU_ID_SHARE_FILE,
395 				new Listener() {
396 					public void handleEvent(Event e) {
397 						ShareUtils.shareFile(menuParent.getShell());
398 					}
399 				});
400 		return file_share_file;
401 	}
402 
403 	public static MenuItem addShareFolderMenuItem(final Menu menuParent) {
404 		MenuItem file_share_dir = addMenuItem(menuParent, MENU_ID_SHARE_DIR,
405 				new Listener() {
406 					public void handleEvent(Event e) {
407 						ShareUtils.shareDir(menuParent.getShell());
408 					}
409 				});
410 		return file_share_dir;
411 	}
412 
413 	public static MenuItem addShareFolderContentMenuItem(final Menu menuParent) {
414 		MenuItem file_share_dircontents = addMenuItem(menuParent,
415 				MENU_ID_SHARE_DIR_CONTENT, new Listener() {
416 					public void handleEvent(Event e) {
417 						ShareUtils.shareDirContents(menuParent.getShell(), false);
418 					}
419 				});
420 		return file_share_dircontents;
421 	}
422 
423 	public static MenuItem addShareFolderContentRecursiveMenuItem(
424 			final Menu menuParent) {
425 		MenuItem file_share_dircontents_rec = addMenuItem(menuParent,
426 				MENU_ID_SHARE_DIR_CONTENT_RECURSE, new Listener() {
427 					public void handleEvent(Event e) {
428 						ShareUtils.shareDirContents(menuParent.getShell(), true);
429 					}
430 				});
431 		return file_share_dircontents_rec;
432 	}
433 
434 	public static MenuItem addImportMenuItem(Menu menuParent) {
435 		MenuItem file_import = addMenuItem(menuParent, MENU_ID_IMPORT,
436 				new Listener() {
437 					public void handleEvent(Event e) {
438 						new ImportTorrentWizard();
439 					}
440 				});
441 		return file_import;
442 	}
443 
444 	public static MenuItem addExportMenuItem(Menu menuParent) {
445 		MenuItem file_export = addMenuItem(menuParent, MENU_ID_EXPORT,
446 				new Listener() {
447 					public void handleEvent(Event e) {
448 						new ExportTorrentWizard();
449 					}
450 				});
451 		return file_export;
452 	}
453 
454 	public static MenuItem addCloseWindowMenuItem(final Menu menuParent) {
455 
456 		MenuItem closeWindow = addMenuItem(menuParent, MENU_ID_WINDOW_CLOSE,
457 				new Listener() {
458 					public void handleEvent(Event event) {
459 						Shell shell = menuParent.getShell();
460 						if (shell != null && !shell.isDisposed()) {
461 							menuParent.getShell().close();
462 						}
463 					}
464 				});
465 		return closeWindow;
466 	}
467 
468 	public static MenuItem addCloseTabMenuItem(Menu menu) {
469 		final MenuItem menuItem = addMenuItem(menu, MENU_ID_CLOSE_TAB, new Listener() {
470 			public void handleEvent(Event event) {
471 				MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
472 				if (mdi != null) {
473 					MdiEntry currentEntry = mdi.getCurrentEntry();
474 					if (currentEntry != null && currentEntry.isCloseable()) {
475 						mdi.closeEntry(currentEntry.getId());
476 					}
477 				}
478 			}
479 		});
480 		menu.addMenuListener(new MenuListener() {
481 			public void menuShown(MenuEvent e) {
482 				MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
483 				if (mdi != null) {
484 					MdiEntry currentEntry = mdi.getCurrentEntry();
485 					if (currentEntry != null && currentEntry.isCloseable()) {
486 						menuItem.setEnabled(true);
487 						return;
488 					}
489 				}
490 				menuItem.setEnabled(false);
491 			}
492 
493 			public void menuHidden(MenuEvent e) {
494 			}
495 		});
496 		return menuItem;
497 	}
498 
499 	public static MenuItem addCloseDetailsMenuItem(Menu menu) {
500 		final MenuItem item = addMenuItem(menu, MENU_ID_CLOSE_ALL_DETAIL,
501 				new Listener() {
502 					public void handleEvent(Event e) {
503 						UIFunctionsManagerSWT.getUIFunctionsSWT().closeAllDetails();
504 					}
505 				});
506 
507 		Listener enableHandler = new Listener() {
508 			public void handleEvent(Event event) {
509 				if (true == MenuFactory.isEnabledForCurrentMode(item)) {
510 					if (false == item.isDisposed() && false == event.widget.isDisposed()) {
511 						boolean hasDetails = UIFunctionsManagerSWT.getUIFunctionsSWT().hasDetailViews();
512 						item.setEnabled(hasDetails);
513 					}
514 				}
515 			}
516 		};
517 
518 		menu.addListener(SWT.Show, enableHandler);
519 
520 		return item;
521 	}
522 
523 	public static MenuItem addCloseDownloadBarsToMenu(Menu menu) {
524 		final MenuItem item = addMenuItem(menu, MENU_ID_CLOSE_ALL_DL_BARS,
525 				new Listener() {
526 					public void handleEvent(Event e) {
527 						MiniBarManager.getManager().closeAll();
528 					}
529 				});
530 
531 		Listener enableHandler = new Listener() {
532 			public void handleEvent(Event event) {
533 				if (false == item.isDisposed()) {
534 					item.setEnabled(false == MiniBarManager.getManager().getShellManager().isEmpty());
535 				}
536 			}
537 		};
538 		menu.addListener(SWT.Show, enableHandler);
539 		//		shell.addListener(SWT.FocusIn, enableHandler);
540 		return item;
541 	}
542 
543 	public static MenuItem addRestartMenuItem(Menu menuParent) {
544 		MenuItem file_restart = new MenuItem(menuParent, SWT.NULL);
545 		Messages.setLanguageText(file_restart, MENU_ID_RESTART); //$NON-NLS-1$
546 
547 		file_restart.addListener(SWT.Selection, new Listener() {
548 
549 			public void handleEvent(Event event) {
550 				UIFunctionsManagerSWT.getUIFunctionsSWT().dispose(true, false);
551 			}
552 		});
553 		return file_restart;
554 	}
555 
556 	public static MenuItem addExitMenuItem(Menu menuParent) {
557 		final MenuItem file_exit = new MenuItem(menuParent, SWT.NULL);
558 		if (!COConfigurationManager.getBooleanParameter("Enable System Tray")
559 				|| !COConfigurationManager.getBooleanParameter("Close To Tray")) {
560 			KeyBindings.setAccelerator(file_exit, MENU_ID_EXIT);
561 		}
562 		Messages.setLanguageText(file_exit, MENU_ID_EXIT); //$NON-NLS-1$
563 
564 		file_exit.addListener(SWT.Selection, new Listener() {
565 			public void handleEvent(Event e) {
566 				UIFunctionsManagerSWT.getUIFunctionsSWT().dispose(false, false);
567 			}
568 		});
569 
570 		// let platform decide
571 		ParameterListener paramListener = new ParameterListener() {
572 			public void parameterChanged(String parameterName) {
573 				if (COConfigurationManager.getBooleanParameter("Enable System Tray")
574 						&& COConfigurationManager.getBooleanParameter("Close To Tray")) {
575 					KeyBindings.removeAccelerator(file_exit, MENU_ID_EXIT);
576 				} else {
577 					KeyBindings.setAccelerator(file_exit, MENU_ID_EXIT);
578 				}
579 			}
580 		};
581 		COConfigurationManager.addParameterListener("Enable System Tray",
582 				paramListener);
583 		COConfigurationManager.addParameterListener("Close To Tray", paramListener);
584 		return file_exit;
585 	}
586 
587 	public static MenuItem addStartAllMenuItem(Menu menu) {
588 		return addMenuItem(menu, MENU_ID_START_ALL_TRANSFERS,
589 				new ListenerNeedingCoreRunning() {
590 					public void handleEvent(AzureusCore core, Event e) {
591 						core.getGlobalManager().startAllDownloads();
592 				/*
593 				 * KN: Not sure why we can not use the call below as opposed to the line above
594 				 *  which was the exiting code
595 				 */
596 				// ManagerUtils.asyncStartAll();
597 			}
598 		});
599 	}
600 
601 	public static MenuItem addStopAllMenuItem(Menu menu) {
602 		return addMenuItem(menu, MENU_ID_STOP_ALL_TRANSFERS, new Listener() {
603 			public void handleEvent(Event event) {
604 				ManagerUtils.asyncStopAll();
605 			}
606 		});
607 	}
608 
609 	public static MenuItem addPauseMenuItem(Menu menu) {
610 		return addMenuItem(menu, MENU_ID_PAUSE_TRANSFERS, new Listener() {
611 			public void handleEvent(Event event) {
612 				ManagerUtils.asyncPause();
613 			}
614 		});
615 	}
616 
617 	public static MenuItem addPauseForMenuItem(final Menu menu) {
618 		return addMenuItem(menu, MENU_ID_PAUSE_TRANSFERS_FOR, new ListenerNeedingCoreRunning() {
619 			public void handleEvent(AzureusCore core, Event event) {
620 
621 				String text = MessageText.getString( "dialog.pause.for.period.text" );
622 
623 				int rem = core.getGlobalManager().getPauseDownloadPeriodRemaining();
624 
625 				if ( rem > 0 ){
626 
627 					text += "\n\n" + MessageText.getString( "dialog.pause.for.period.text2", new String[]{ TimeFormatter.format2( rem, true ) });
628 				}
629 
630 				SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
631 						"dialog.pause.for.period.title",
632 						"!" + text + "!");
633 
634 				int def = COConfigurationManager.getIntParameter( "pause.for.period.default", 10 );
635 
636 				entryWindow.setPreenteredText( String.valueOf( def ), false );
637 
638 				entryWindow.prompt(new UIInputReceiverListener() {
639 					public void UIInputReceiverClosed(UIInputReceiver entryWindow) {
640 						if (!entryWindow.hasSubmittedInput()) {
641 							return;
642 						}
643 						String sReturn = entryWindow.getSubmittedInput();
644 
645 						if (sReturn == null)
646 							return;
647 
648 						int mins = -1;
649 						try {
650 							mins = Integer.valueOf(sReturn).intValue();
651 						} catch (NumberFormatException er) {
652 							// Ignore
653 						}
654 
655 						if (mins <= 0) {
656 							MessageBox mb = new MessageBox(menu.getShell(), SWT.ICON_ERROR
657 									| SWT.OK);
658 							mb.setText(MessageText.getString("MyTorrentsView.dialog.NumberError.title"));
659 							mb.setMessage(MessageText.getString("MyTorrentsView.dialog.NumberError.text"));
660 
661 							mb.open();
662 							return;
663 						}
664 
665 						COConfigurationManager.setParameter( "pause.for.period.default", mins );
666 
667 						ManagerUtils.asyncPauseForPeriod( mins*60 );
668 					}
669 				});
670 			}
671 		});
672 	}
673 	public static MenuItem addResumeMenuItem(Menu menu) {
674 		return addMenuItem(menu, MENU_ID_RESUME_TRANSFERS, new Listener() {
675 			public void handleEvent(Event event) {
676 				ManagerUtils.asyncResume();
677 			}
678 		});
679 	}
680 
681 	public static MenuItem addMyTorrentsMenuItem(Menu menu) {
682 		return addMenuItem(menu, MENU_ID_MY_TORRENTS, new Listener() {
683 			public void handleEvent(Event e) {
684 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
685 				if (uiFunctions != null) {
686 					uiFunctions.getMDI().showEntryByID(
687 							MultipleDocumentInterface.SIDEBAR_SECTION_LIBRARY);
688 				}
689 			}
690 		});
691 	}
692 
693 	public static MenuItem addAllPeersMenuItem(Menu menu) {
694 		return addMenuItem(menu, MENU_ID_ALL_PEERS, new Listener() {
695 			public void handleEvent(Event e) {
696 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
697 				if (uiFunctions != null) {
698 					uiFunctions.getMDI().showEntryByID(
699 							MultipleDocumentInterface.SIDEBAR_SECTION_ALLPEERS);
700 				}
701 			}
702 		});
703 	}
704 
705 	public static MenuItem addClientStatsMenuItem(Menu menu) {
706 		return addMenuItem(menu, MENU_ID_CLIENT_STATS, new Listener() {
707 			public void handleEvent(Event e) {
708 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
709 				if (uiFunctions != null) {
710 					uiFunctions.getMDI().showEntryByID(
711 							MultipleDocumentInterface.SIDEBAR_SECTION_CLIENT_STATS);
712 				}
713 			}
714 		});
715 	}
716 
717 	public static MenuItem addDeviceManagerMenuItem(Menu menu) {
718 		return addMenuItem(menu, MENU_ID_DEVICEMANAGER, new Listener() {
719 			public void handleEvent(Event e) {
720 				MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
721 				mdi.showEntryByID(MultipleDocumentInterface.SIDEBAR_SECTION_DEVICES);
722 			}
723 		});
724 	}
725 
726 	public static MenuItem addSubscriptionMenuItem(Menu menu) {
727 		return addMenuItem(menu, MENU_ID_SUBSCRIPTIONS, new Listener() {
728 			public void handleEvent(Event e) {
729 				MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
730 				mdi.showEntryByID(MultipleDocumentInterface.SIDEBAR_SECTION_SUBSCRIPTIONS);
731 			}
732 		});
733 	}
734 
735 	public static MenuItem addMyTrackerMenuItem(Menu menu) {
736 		return addMenuItem(menu, MENU_ID_MY_TRACKERS, new Listener() {
737 			public void handleEvent(Event e) {
738 				MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
739 				mdi.showEntryByID(MultipleDocumentInterface.SIDEBAR_SECTION_MY_TRACKER);
740 			}
741 		});
742 	}
743 
744 	public static MenuItem addMySharesMenuItem(Menu menu) {
745 		return addMenuItem(menu, MENU_ID_MY_SHARES, new Listener() {
746 			public void handleEvent(Event e) {
747 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
748 				if (uiFunctions != null) {
749 					uiFunctions.getMDI().showEntryByID(
750 							MultipleDocumentInterface.SIDEBAR_SECTION_MY_SHARES);
751 				}
752 			}
753 		});
754 	}
755 
756 	public static MenuItem addViewToolbarMenuItem(Menu menu) {
757 		final MenuItem item = addMenuItem(menu, SWT.CHECK, MENU_ID_TOOLBAR,
758 				new Listener() {
759 					public void handleEvent(Event e) {
760 						UIFunctionsSWT uiFunctions = getUIFunctionSWT();
761 						if (null != uiFunctions) {
762 							IMainWindow mainWindow = uiFunctions.getMainWindow();
763 							boolean isToolbarVisible = mainWindow.isVisible(IMainWindow.WINDOW_ELEMENT_TOOLBAR);
764 							mainWindow.setVisible(IMainWindow.WINDOW_ELEMENT_TOOLBAR,
765 									!isToolbarVisible);
766 						}
767 					}
768 				});
769 
770 		final ParameterListener listener = new ParameterListener() {
771 			public void parameterChanged(String parameterName) {
772 				item.setSelection(COConfigurationManager.getBooleanParameter(parameterName));
773 			}
774 		};
775 
776 		COConfigurationManager.addAndFireParameterListener("IconBar.enabled",
777 				listener);
778 		item.addDisposeListener(new DisposeListener() {
779 			public void widgetDisposed(DisposeEvent e) {
780 				COConfigurationManager.removeParameterListener("IconBar.enabled",
781 						listener);
782 			}
783 		});
784 		return item;
785 	}
786 
787 	public static MenuItem addTransferBarToMenu(final Menu menu) {
788 		final MenuItem item = addMenuItem(menu, SWT.CHECK, MENU_ID_TRANSFER_BAR,
789 				new ListenerNeedingCoreRunning() {
790 					public void handleEvent(AzureusCore core, Event e) {
791 						if (AllTransfersBar.getManager().isOpen(
792 								core.getGlobalManager())) {
793 							AllTransfersBar.closeAllTransfersBar();
794 						} else {
795 							AllTransfersBar.open(menu.getShell());
796 						}
797 					}
798 				});
799 		item.setSelection(!MiniBarManager.getManager().getShellManager().isEmpty());
800 
801 		menu.addListener(SWT.Show, new Listener() {
802 			public void handleEvent(Event event) {
803 				if (item.isDisposed()) {
804 					menu.removeListener(SWT.Show, this);
805 				} else {
806 					item.setSelection(!MiniBarManager.getManager().getShellManager().isEmpty());
807 				}
808 			}
809 		});
810 		return item;
811 	}
812 
813 	public static MenuItem addSpeedLimitsToMenu(final Menu menuParent) {
814 		MenuItem speedLimitsMenuItem = createTopLevelMenuItem(menuParent,
815 				MENU_ID_SPEED_LIMITS);
816 		MenuBuildUtils.addMaintenanceListenerForMenu(speedLimitsMenuItem.getMenu(),
817 				new MenuBuildUtils.MenuBuilder() {
818 					public void
819 					buildMenu(
820 						Menu menu, MenuEvent menuEvent)
821 					{
822 						if ( AzureusCoreFactory.isCoreRunning()){
823 
824 							AzureusCore core = AzureusCoreFactory.getSingleton();
825 
826 							final SpeedLimitHandler slh = SpeedLimitHandler.getSingleton( core );
827 
828 							MenuItem viewCurrentItem = new MenuItem(menu, SWT.PUSH);
829 							Messages.setLanguageText(viewCurrentItem, "MainWindow.menu.speed_limits.view_current" );
830 
831 							viewCurrentItem.addListener(
832 								SWT.Selection,
833 								new Listener()
834 								{
835 									public void
836 									handleEvent(
837 										Event arg0 )
838 									{
839 										showText(
840 											"MainWindow.menu.speed_limits.info.title",
841 											"MainWindow.menu.speed_limits.info.curr",
842 											slh.getCurrent());
843 									}
844 								});
845 
846 							java.util.List<String>	profiles = slh.getProfileNames();
847 
848 							Menu profiles_menu = new Menu(menuParent.getShell(), SWT.DROP_DOWN);
849 							MenuItem profiles_item = new MenuItem( menu, SWT.CASCADE);
850 							profiles_item.setMenu(profiles_menu);
851 
852 
853 							Messages.setLanguageText(profiles_item, "MainWindow.menu.speed_limits.profiles" );
854 
855 							if ( profiles.size() == 0 ){
856 
857 								profiles_item.setEnabled( false );
858 
859 							}else{
860 
861 								for ( final String p: profiles ){
862 
863 									Menu profile_menu = new Menu(menuParent.getShell(), SWT.DROP_DOWN);
864 									MenuItem profile_item = new MenuItem( profiles_menu, SWT.CASCADE);
865 									profile_item.setMenu(profile_menu);
866 									profile_item.setText( p );
867 
868 									MenuItem loadItem = new MenuItem(profile_menu, SWT.PUSH);
869 									Messages.setLanguageText(loadItem, "MainWindow.menu.speed_limits.load" );
870 
871 									loadItem.addListener(
872 										SWT.Selection,
873 										new Listener()
874 										{
875 											public void
876 											handleEvent(
877 												Event arg0 )
878 											{
879 												showText(
880 													"MainWindow.menu.speed_limits.info.title",
881 													MessageText.getString( "MainWindow.menu.speed_limits.info.prof", new String[]{ p }),
882 													slh.loadProfile( p ) );
883 											}
884 										});
885 
886 									MenuItem viewItem = new MenuItem(profile_menu, SWT.PUSH);
887 									Messages.setLanguageText(viewItem, "MainWindow.menu.speed_limits.view" );
888 
889 									viewItem.addListener(
890 										SWT.Selection,
891 										new Listener()
892 										{
893 											public void
894 											handleEvent(
895 												Event arg0 )
896 											{
897 												showText(
898 													"MainWindow.menu.speed_limits.info.title",
899 													MessageText.getString( "MainWindow.menu.speed_limits.info.prof", new String[]{ p }),
900 													slh.getProfile( p ) );
901 											}
902 										});
903 
904 									addSeparatorMenuItem( profile_menu );
905 
906 									MenuItem deleteItem = new MenuItem(profile_menu, SWT.PUSH);
907 									Messages.setLanguageText(deleteItem, "MainWindow.menu.speed_limits.delete" );
908 
909 									deleteItem.addListener(
910 										SWT.Selection,
911 										new Listener()
912 										{
913 											public void
914 											handleEvent(
915 												Event arg0 )
916 											{
917 												slh.deleteProfile( p );
918 											}
919 										});
920 								}
921 							}
922 
923 							MenuItem saveItem = new MenuItem(menu, SWT.PUSH);
924 							Messages.setLanguageText(saveItem, "MainWindow.menu.speed_limits.save_current" );
925 
926 							saveItem.addListener(
927 								SWT.Selection,
928 								new Listener()
929 								{
930 									public void
931 									handleEvent(
932 										Event arg0 )
933 									{
934 										UISWTInputReceiver entry = new SimpleTextEntryWindow();
935 
936 										entry.allowEmptyInput( false );
937 										entry.setLocalisedTitle(MessageText.getString("MainWindow.menu.speed_limits.profile" ));
938 										entry.prompt(new UIInputReceiverListener() {
939 											public void UIInputReceiverClosed(UIInputReceiver entry) {
940 												if (!entry.hasSubmittedInput()){
941 
942 													return;
943 												}
944 
945 												String input = entry.getSubmittedInput().trim();
946 
947 												if ( input.length() > 0 ){
948 
949 													showText(
950 														"MainWindow.menu.speed_limits.info.title",
951 														MessageText.getString( "MainWindow.menu.speed_limits.info.prof", new String[]{ input }),
952 														slh.saveProfile( input ) );
953 												}
954 											}
955 										});
956 									}
957 								});
958 
959 							addSeparatorMenuItem( menu );
960 
961 							MenuItem resetItem = new MenuItem(menu, SWT.PUSH);
962 							Messages.setLanguageText(resetItem, "MainWindow.menu.speed_limits.reset" );
963 
964 							resetItem.addListener(
965 								SWT.Selection,
966 								new Listener()
967 								{
968 									public void
969 									handleEvent(
970 										Event arg0 )
971 									{
972 										showText(
973 											"MainWindow.menu.speed_limits.info.title",
974 											"MainWindow.menu.speed_limits.info.curr",
975 											slh.reset());
976 									}
977 								});
978 
979 						addSeparatorMenuItem( menu );
980 
981 						MenuItem scheduleItem = new MenuItem(menu, SWT.PUSH);
982 						Messages.setLanguageText(scheduleItem, "MainWindow.menu.speed_limits.schedule" );
983 
984 						scheduleItem.addListener(
985 							SWT.Selection,
986 							new Listener()
987 							{
988 								public void
989 								handleEvent(
990 									Event arg0 )
991 								{
992 									Utils.execSWTThreadLater(
993 											1,
994 											new Runnable()
995 											{
996 												public void
997 												run()
998 												{
999 													java.util.List<String> lines = slh.getSchedule();
1000 
1001 													StringBuffer	text = new StringBuffer( 80*lines.size());
1002 
1003 													for ( String s: lines ){
1004 
1005 														if ( text.length() > 0 ){
1006 
1007 															text.append( "\n" );
1008 														}
1009 
1010 														text.append( s );
1011 													}
1012 
1013 													final TextViewerWindow viewer =
1014 														new TextViewerWindow(
1015 															"MainWindow.menu.speed_limits.schedule.title",
1016 															"MainWindow.menu.speed_limits.schedule.msg",
1017 															text.toString(), false );
1018 
1019 													viewer.setEditable( true );
1020 
1021 													viewer.addListener(
1022 														new TextViewerWindow.TextViewerWindowListener()
1023 														{
1024 															public void
1025 															closed()
1026 															{
1027 																String text = viewer.getText();
1028 
1029 																String[] lines = text.split( "\n" );
1030 
1031 																java.util.List<String> updated_lines = new ArrayList<String>( Arrays.asList( lines ));
1032 
1033 																java.util.List<String> result = slh.setSchedule( updated_lines );
1034 
1035 																if ( result != null && result.size() > 0 ){
1036 
1037 																	showText(
1038 																			"MainWindow.menu.speed_limits.schedule.title",
1039 																			"MainWindow.menu.speed_limits.schedule.err",
1040 																			result );
1041 																}
1042 															}
1043 														});
1044 												}
1045 											});
1046 								}
1047 							});
1048 
1049 						addSeparatorMenuItem( menu );
1050 
1051 						MenuItem helpItem = new MenuItem(menu, SWT.PUSH);
1052 						Messages.setLanguageText(helpItem, "MainWindow.menu.speed_limits.wiki" );
1053 
1054 						helpItem.addListener(
1055 							SWT.Selection,
1056 							new Listener()
1057 							{
1058 								public void
1059 								handleEvent(
1060 									Event arg0 )
1061 								{
1062 									Utils.launch( MessageText.getString("MainWindow.menu.speed_limits.wiki.url"));
1063 								}
1064 							});
1065 						}
1066 					}
1067 				});
1068 
1069 		return( speedLimitsMenuItem );
1070 	}
1071 
1072 	public static MenuItem addAdvancedHelpMenuItem(final Menu menuParent) {
1073 		MenuItem advancedHelpMenuItem = createTopLevelMenuItem(menuParent,
1074 				MENU_ID_ADVANCED_TOOLS);
1075 		MenuBuildUtils.addMaintenanceListenerForMenu(advancedHelpMenuItem.getMenu(),
1076 				new MenuBuildUtils.MenuBuilder() {
1077 					public void
1078 					buildMenu(
1079 						final Menu menu, MenuEvent menuEvent)
1080 					{
1081 						MenuItem viewTorrent = new MenuItem(menu, SWT.PUSH);
1082 
1083 						Messages.setLanguageText(viewTorrent, "torrent.view.info" );
1084 
1085 						viewTorrent.addListener(
1086 							SWT.Selection,
1087 							new Listener()
1088 							{
1089 								public void
1090 								handleEvent(
1091 									Event arg )
1092 								{
1093 									Utils.execSWTThreadLater(
1094 											1,
1095 											new Runnable()
1096 											{
1097 												public void
1098 												run()
1099 												{
1100 													handleTorrentView();
1101 												}
1102 											});
1103 								}
1104 							});
1105 
1106 						MenuItem fixTorrent = new MenuItem(menu, SWT.PUSH);
1107 
1108 						Messages.setLanguageText(fixTorrent, "torrent.fix.corrupt" );
1109 
1110 						fixTorrent.addListener(
1111 							SWT.Selection,
1112 							new Listener()
1113 							{
1114 								public void
1115 								handleEvent(
1116 									Event arg )
1117 								{
1118 									Utils.execSWTThreadLater(
1119 											1,
1120 											new Runnable()
1121 											{
1122 												public void
1123 												run()
1124 												{
1125 													handleTorrentFixup();
1126 												}
1127 											});
1128 								}
1129 							});
1130 
1131 						MenuItem importXMLTorrent = new MenuItem(menu, SWT.PUSH);
1132 
1133 						Messages.setLanguageText(importXMLTorrent, "importTorrentWizard.title" );
1134 
1135 						importXMLTorrent.addListener(
1136 							SWT.Selection,
1137 							new Listener()
1138 							{
1139 								public void
1140 								handleEvent(
1141 									Event arg )
1142 								{
1143 									Utils.execSWTThreadLater(
1144 											1,
1145 											new Runnable()
1146 											{
1147 												public void
1148 												run()
1149 												{
1150 													new ImportTorrentWizard();
1151 												}
1152 											});
1153 								}
1154 							});
1155 
1156 						MenuItem bencodeToJSON = new MenuItem(menu, SWT.PUSH);
1157 
1158 						Messages.setLanguageText(bencodeToJSON, "menu.bencode.to.json" );
1159 
1160 						bencodeToJSON.addListener(
1161 							SWT.Selection,
1162 							new Listener()
1163 							{
1164 								public void
1165 								handleEvent(
1166 									Event arg )
1167 								{
1168 									Utils.execSWTThreadLater(
1169 											1,
1170 											new Runnable()
1171 											{
1172 												public void
1173 												run()
1174 												{
1175 													BencodeToJSON();
1176 												}
1177 											});
1178 								}
1179 							});
1180 
1181 						MenuItem JSONToBencode = new MenuItem(menu, SWT.PUSH);
1182 
1183 						Messages.setLanguageText(JSONToBencode, "menu.json.to.bencode" );
1184 
1185 						JSONToBencode.addListener(
1186 							SWT.Selection,
1187 							new Listener()
1188 							{
1189 								public void
1190 								handleEvent(
1191 									Event arg )
1192 								{
1193 									Utils.execSWTThreadLater(
1194 											1,
1195 											new Runnable()
1196 											{
1197 												public void
1198 												run()
1199 												{
1200 													JSONToBencode();
1201 												}
1202 											});
1203 								}
1204 							});
1205 
1206 						MenuItem showChanges = new MenuItem(menu, SWT.PUSH);
1207 
1208 						Messages.setLanguageText(showChanges, "show.config.changes" );
1209 
1210 						showChanges.addListener(
1211 							SWT.Selection,
1212 							new Listener()
1213 							{
1214 								public void
1215 								handleEvent(
1216 									Event arg )
1217 								{
1218 									Utils.execSWTThreadLater(
1219 											1,
1220 											new Runnable()
1221 											{
1222 												public void
1223 												run()
1224 												{
1225 													handleShowChanges();
1226 												}
1227 											});
1228 								}
1229 							});
1230 					}
1231 		});
1232 
1233 		return( advancedHelpMenuItem );
1234 	}
1235 
1236 	private static void
1237 	BencodeToJSON()
1238 	{
1239 		final Shell shell = Utils.findAnyShell();
1240 
1241 		FileDialog dialog = new FileDialog( shell.getShell(), SWT.SYSTEM_MODAL | SWT.OPEN );
1242 
1243 		dialog.setFilterExtensions(new String[] { "*.config", "*.torrent", "*.tor", Constants.FILE_WILDCARD });
1244 
1245 		dialog.setFilterNames(new String[] { "*.config", "*.torrent", "*.tor", Constants.FILE_WILDCARD });
1246 
1247 		dialog.setFilterPath( TorrentOpener.getFilterPathTorrent());
1248 
1249 		dialog.setText(MessageText.getString( "bencode.file.browse" ));
1250 
1251 		String str = dialog.open();
1252 
1253 		if ( str != null ){
1254 
1255 			try{
1256 				BufferedInputStream bis = new BufferedInputStream( new FileInputStream( str ));
1257 
1258 				try{
1259 					Map map = BDecoder.decode( bis );
1260 
1261 					if ( map == null ){
1262 
1263 						throw( new Exception( "BDecode failed" ));
1264 					}
1265 
1266 					final String json = BEncoder.encodeToJSON( map );
1267 
1268 	 				Utils.execSWTThreadLater(
1269 						1,
1270 						new Runnable()
1271 						{
1272 							public void
1273 							run()
1274 							{
1275 				 				FileDialog dialog2 = new FileDialog( shell, SWT.SYSTEM_MODAL | SWT.SAVE );
1276 
1277 								dialog2.setFilterPath( TorrentOpener.getFilterPathTorrent());
1278 
1279 								dialog2.setFilterExtensions(new String[]{ "*.json" });
1280 
1281 								String str2 = dialog2.open();
1282 
1283 								if ( str2 != null ){
1284 
1285 									if ( !( str2.toLowerCase( Locale.US ).endsWith( ".json" ))){
1286 
1287 										str2 += ".json";
1288 									}
1289 
1290 									try{
1291 										if ( !FileUtil.writeStringAsFile( new File( str2 ), json )){
1292 
1293 											throw( new Exception( "Failed to write output file" ));
1294 										}
1295 									}catch( Throwable e ){
1296 
1297 										MessageBoxShell mb = new MessageBoxShell( SWT.ERROR, MessageText.getString( "ConfigView.section.security.resetkey.error.title"), Debug.getNestedExceptionMessage( e ));
1298 
1299 							 			mb.setParent( shell );
1300 
1301 							 			mb.open( null );
1302 									}
1303 								}
1304 							}
1305 						});
1306 				}finally{
1307 
1308 					bis.close();
1309 				}
1310 			}catch( Throwable e ){
1311 
1312 				MessageBoxShell mb = new MessageBoxShell( SWT.ERROR, MessageText.getString( "ConfigView.section.security.resetkey.error.title"), Debug.getNestedExceptionMessage( e ));
1313 
1314 	 			mb.setParent( shell );
1315 
1316 	 			mb.open( null );
1317 			}
1318 		}
1319 	}
1320 
1321 	private static void
1322 	JSONToBencode()
1323 	{
1324 		final Shell shell = Utils.findAnyShell();
1325 
1326 		FileDialog dialog = new FileDialog( shell.getShell(), SWT.SYSTEM_MODAL | SWT.OPEN );
1327 
1328 		dialog.setFilterExtensions(new String[] { "*.json", Constants.FILE_WILDCARD });
1329 
1330 		dialog.setFilterNames(new String[] { "*.json", Constants.FILE_WILDCARD });
1331 
1332 		dialog.setFilterPath( TorrentOpener.getFilterPathTorrent());
1333 
1334 		dialog.setText(MessageText.getString( "json.file.browse" ));
1335 
1336 		String str = dialog.open();
1337 
1338 		if ( str != null ){
1339 
1340 			try{
1341 				String json = FileUtil.readFileAsString( new File( str ), -1, "UTF-8" );
1342 
1343 				if ( json == null ){
1344 
1345 					throw( new Exception( "JSON decode failed" ));
1346 				}
1347 
1348 				final Map map = BDecoder.decodeFromJSON( json );
1349 
1350  				Utils.execSWTThreadLater(
1351 					1,
1352 					new Runnable()
1353 					{
1354 						public void
1355 						run()
1356 						{
1357 			 				FileDialog dialog2 = new FileDialog( shell, SWT.SYSTEM_MODAL | SWT.SAVE );
1358 
1359 							dialog2.setFilterPath( TorrentOpener.getFilterPathTorrent());
1360 
1361 							dialog2.setFilterExtensions(new String[]{ "*.config", "*.torrent", "*.tor", Constants.FILE_WILDCARD });
1362 
1363 							String str2 = dialog2.open();
1364 
1365 							if ( str2 != null ){
1366 
1367 								if ( !str2.contains( "." )){
1368 
1369 									str2 += ".config";
1370 								}
1371 
1372 								try{
1373 									byte[] bytes = BEncoder.encode( map );
1374 
1375 									FileUtil.writeBytesAsFile( str2, bytes );
1376 
1377 								}catch( Throwable e ){
1378 
1379 									MessageBoxShell mb = new MessageBoxShell( SWT.ERROR, MessageText.getString( "ConfigView.section.security.resetkey.error.title"), Debug.getNestedExceptionMessage( e ));
1380 
1381 						 			mb.setParent( shell );
1382 
1383 						 			mb.open( null );
1384 								}
1385 							}
1386 						}
1387 					});
1388 
1389 			}catch( Throwable e ){
1390 
1391 				MessageBoxShell mb = new MessageBoxShell( SWT.ERROR, MessageText.getString( "ConfigView.section.security.resetkey.error.title"), Debug.getNestedExceptionMessage( e ));
1392 
1393 	 			mb.setParent( shell );
1394 
1395 	 			mb.open( null );
1396 			}
1397 		}
1398 	}
1399 
1400 
1401 	private static void
1402 	handleTorrentView()
1403 	{
1404 		final Shell shell = Utils.findAnyShell();
1405 
1406 		try{
1407 			FileDialog dialog = new FileDialog( shell.getShell(), SWT.SYSTEM_MODAL | SWT.OPEN );
1408 
1409 			dialog.setFilterExtensions(new String[] { "*.torrent", "*.tor", Constants.FILE_WILDCARD });
1410 
1411 			dialog.setFilterNames(new String[] { "*.torrent", "*.tor", Constants.FILE_WILDCARD });
1412 
1413 			dialog.setFilterPath( TorrentOpener.getFilterPathTorrent());
1414 
1415 			dialog.setText(MessageText.getString( "torrent.fix.corrupt.browse" ));
1416 
1417 			String str = dialog.open();
1418 
1419 			if ( str != null ){
1420 
1421 				TorrentOpener.setFilterPathTorrent( str );
1422 
1423 				File file = new File( str );
1424 
1425 				StringBuffer content = new StringBuffer();
1426 
1427 				String NL = "\r\n";
1428 
1429 				try{
1430 					TOTorrent torrent = TOTorrentFactory.deserialiseFromBEncodedFile( file );
1431 
1432 					LocaleUtilDecoder	locale_decoder = LocaleTorrentUtil.getTorrentEncoding( torrent );
1433 
1434 					content.append( "Character Encoding:\t" + locale_decoder.getName() + NL );
1435 
1436 					String display_name = locale_decoder.decodeString( torrent.getName());
1437 
1438 					content.append( "Name:\t" + display_name + NL );
1439 
1440 					byte[] hash = torrent.getHash();
1441 
1442 					content.append( "Hash:\t" + ByteFormatter.encodeString( hash ) + NL );
1443 
1444 					content.append(
1445 						"Size:\t" + DisplayFormatters.formatByteCountToKiBEtc( torrent.getSize()) +
1446 						", piece size=" + DisplayFormatters.formatByteCountToKiBEtc( torrent.getPieceLength()) +
1447 						", piece count=" + torrent.getPieces().length + NL );
1448 
1449 					if ( torrent.getPrivate()){
1450 
1451 						content.append( "Private Torrent" + NL );
1452 					}
1453 
1454 					URL announce_url = torrent.getAnnounceURL();
1455 
1456 					if ( announce_url != null ){
1457 
1458 						content.append( "Announce URL:\t" + announce_url + NL );
1459 					}
1460 
1461 					TOTorrentAnnounceURLSet[] sets = torrent.getAnnounceURLGroup().getAnnounceURLSets();
1462 
1463 					if ( sets.length > 0 ){
1464 
1465 						content.append( "Announce List" + NL );
1466 
1467 						for ( TOTorrentAnnounceURLSet set: sets ){
1468 
1469 							String x = "";
1470 
1471 							URL[] urls = set.getAnnounceURLs();
1472 
1473 							for ( URL u: urls ){
1474 
1475 								x += ( x.length()==0?"":", ") + u;
1476 							}
1477 
1478 							content.append( "\t" + x + NL );
1479 						}
1480 					}
1481 
1482 					content.append( "Magnet URI:\t" + UrlUtils.getMagnetURI( display_name, PluginCoreUtils.wrap( torrent )) + NL );
1483 
1484 					long c_date = torrent.getCreationDate();
1485 
1486 					if ( c_date > 0 ){
1487 
1488 						content.append(  "Created On:\t" + DisplayFormatters.formatDate( c_date*1000) + NL );
1489 					}
1490 
1491 					byte[] created_by = torrent.getCreatedBy();
1492 
1493 					if ( created_by != null ){
1494 
1495 						content.append( "Created By:\t" + locale_decoder.decodeString( created_by ) + NL );
1496 					}
1497 
1498 					byte[] comment = torrent.getComment();
1499 
1500 					if ( comment != null ){
1501 
1502 						content.append( "Comment:\t" + locale_decoder.decodeString( comment ) + NL );
1503 					}
1504 
1505 					TOTorrentFile[] files = torrent.getFiles();
1506 
1507 					content.append( "Files:\t" + files.length + " - simple=" + torrent.isSimpleTorrent() + NL );
1508 
1509 					for ( TOTorrentFile tf: files ){
1510 
1511 						byte[][] comps = tf.getPathComponents();
1512 
1513 						String f_name = "";
1514 
1515 						for ( byte[] comp: comps ){
1516 
1517 							f_name += (f_name.length()==0?"":File.separator) + locale_decoder.decodeString( comp );
1518 						}
1519 
1520 						content.append( "\t" + f_name + "\t\t" + DisplayFormatters.formatByteCountToKiBEtc( tf.getLength()) + NL );
1521 					}
1522 
1523 				}catch( Throwable e ){
1524 
1525 					content.append( Debug.getNestedExceptionMessage( e ));
1526 				}
1527 
1528 				new TextViewerWindow(
1529 						MessageText.getString( "MainWindow.menu.quick_view" ) + ": " + file.getName(),
1530 						null, content.toString(), false  );
1531 
1532 			}
1533 		}catch( Throwable e ){
1534 
1535 			Debug.out( e );
1536 		}
1537 	}
1538 
1539 	private static void
1540 	handleTorrentFixup()
1541 	{
1542 			// had some OSX SWT crash issues in this code so moved everything async
1543 
1544 		final Shell shell = Utils.findAnyShell();
1545 
1546 		try{
1547 			FileDialog dialog = new FileDialog( shell.getShell(), SWT.SYSTEM_MODAL | SWT.OPEN );
1548 
1549 			dialog.setFilterExtensions(new String[] { "*.torrent", "*.tor", Constants.FILE_WILDCARD });
1550 
1551 			dialog.setFilterNames(new String[] { "*.torrent", "*.tor", Constants.FILE_WILDCARD });
1552 
1553 			dialog.setFilterPath( TorrentOpener.getFilterPathTorrent());
1554 
1555 			dialog.setText(MessageText.getString( "torrent.fix.corrupt.browse" ));
1556 
1557 			String str = dialog.open();
1558 
1559 			if ( str != null ){
1560 
1561 				TorrentOpener.setFilterPathTorrent( str );
1562 
1563 				File file = new File( str );
1564 
1565 				byte[] bytes = FileUtil.readFileAsByteArray( file );
1566 
1567 				Map existing_map = BDecoder.decode( bytes );
1568 
1569 				Map existing_info = (Map)existing_map.get( "info" );
1570 
1571 				byte[]	existing_info_encoded = BEncoder.encode( existing_info );
1572 
1573 				final TOTorrent t = TOTorrentFactory.deserialiseFromMap( existing_map );
1574 
1575 				final byte[] old_hash = t.getHash();
1576 				byte[] new_hash	= null;
1577 
1578 				for ( int i=0;i<bytes.length-5;i++){
1579 
1580 					if ( 	bytes[i] == ':' &&
1581 							bytes[i+1] == 'i' &&
1582 							bytes[i+2] == 'n' &&
1583 							bytes[i+3] == 'f' &&
1584 							bytes[i+4] == 'o' ){
1585 
1586 						new_hash = new SHA1Simple().calculateHash( bytes, i+5, existing_info_encoded.length );
1587 
1588 						break;
1589 					}
1590 				}
1591 
1592 				if ( new_hash != null ){
1593 
1594 					final byte[] f_new_hash = new_hash;
1595 
1596 					Utils.execSWTThreadLater(
1597 							1,
1598 							new Runnable()
1599 							{
1600 								public void
1601 								run()
1602 								{
1603 									String	title = MessageText.getString( "torrent.fix.corrupt.result.title" );
1604 
1605 									if ( Arrays.equals( old_hash, f_new_hash )){
1606 
1607 										MessageBoxShell mb =
1608 											new MessageBoxShell( SWT.OK, title, MessageText.getString( "torrent.fix.corrupt.result.nothing" ) );
1609 
1610 						 				mb.setParent( shell );
1611 
1612 						 				mb.open( null );
1613 
1614 									}else{
1615 
1616 										MessageBoxShell mb =
1617 											new MessageBoxShell( SWT.OK, title, MessageText.getString( "torrent.fix.corrupt.result.fixed", new String[]{ ByteFormatter.encodeString( f_new_hash ) }));
1618 
1619 						 				mb.setParent( shell );
1620 
1621 						 				mb.open( null );
1622 
1623 						 				mb.waitUntilClosed();
1624 
1625 						 				try{
1626 						 					t.setHashOverride( f_new_hash );
1627 
1628 							 				Utils.execSWTThreadLater(
1629 													1,
1630 													new Runnable()
1631 													{
1632 														public void
1633 														run()
1634 														{
1635 											 				FileDialog dialog2 = new FileDialog( shell, SWT.SYSTEM_MODAL | SWT.SAVE );
1636 
1637 															dialog2.setFilterPath( TorrentOpener.getFilterPathTorrent());
1638 
1639 															dialog2.setFilterExtensions(new String[]{ "*.torrent" });
1640 
1641 															String str2 = dialog2.open();
1642 
1643 															if ( str2 != null ){
1644 
1645 																if ( !( str2.toLowerCase( Locale.US ).endsWith( ".tor" ) || str2.toLowerCase( Locale.US ).endsWith( ".torrent" ))){
1646 
1647 																	str2 += ".torrent";
1648 																}
1649 
1650 																try{
1651 																	t.serialiseToBEncodedFile( new File( str2 ));
1652 
1653 																}catch( Throwable e ){
1654 
1655 																	Debug.out( e );
1656 																}
1657 															}
1658 														}
1659 													});
1660 						 				}catch( Throwable e ){
1661 
1662 						 					Debug.out( e );
1663 						 				}
1664 									}
1665 								}
1666 							});
1667 				}
1668 			}
1669 		}catch( Throwable e ){
1670 
1671 			Debug.out( e );
1672 		}
1673 	}
1674 
1675 	private static void
1676 	handleShowChanges()
1677 	{
1678 		final String NL = "\r\n";
1679 
1680 		StringWriter content = new StringWriter();
1681 
1682 		content.append( "**** Please review the contents of this before submitting it ****" + NL + NL );
1683 
1684 		content.append( "Settings" + NL );
1685 
1686 		IndentWriter iw = new IndentWriter( new PrintWriter( content ));
1687 
1688 		iw.indent();
1689 
1690 		try{
1691 			COConfigurationManager.dumpConfigChanges( iw );
1692 
1693 		}finally{
1694 
1695 			iw.exdent();
1696 
1697 			iw.close();
1698 		}
1699 
1700 		AzureusCore	core = AzureusCoreFactory.getSingleton();
1701 
1702 		content.append( "Plugins" + NL );
1703 
1704 		PluginInterface[] plugins = core.getPluginManager().getPlugins();
1705 
1706 		for ( PluginInterface pi: plugins ){
1707 
1708 			if ( pi.getPluginState().isBuiltIn()){
1709 
1710 				continue;
1711 			}
1712 
1713 			content.append( "    " + pi.getPluginName() + ": " + pi.getPluginVersion() + NL );
1714 		}
1715 
1716 		java.util.List<DownloadManager> dms = core.getGlobalManager().getDownloadManagers();
1717 
1718 		content.append( "Downloads - " + dms.size() + NL );
1719 
1720 		iw = new IndentWriter( new PrintWriter( content ));
1721 
1722 		iw.indent();
1723 
1724 		try{
1725 			for ( DownloadManager dm: dms ){
1726 
1727 				String	hash_str;
1728 
1729 				try{
1730 					byte[] hash = dm.getTorrent().getHash();
1731 
1732 					hash_str = Base32.encode( hash ).substring( 0, 16 );
1733 
1734 				}catch( Throwable e ){
1735 
1736 					hash_str = "<no hash>";
1737 				}
1738 
1739 				content.append( "    " + hash_str + ": " + DisplayFormatters.formatDownloadStatus( dm ) + NL );
1740 
1741 				iw.indent();
1742 
1743 				dm.getDownloadState().dump( iw );
1744 
1745 				try{
1746 
1747 				}finally{
1748 
1749 					iw.exdent();
1750 				}
1751 			}
1752 		}finally{
1753 
1754 			iw.exdent();
1755 
1756 			iw.close();
1757 		}
1758 
1759 		content.append( "Categories" + NL );
1760 
1761 		Category[] cats = CategoryManager.getCategories();
1762 
1763 		iw = new IndentWriter( new PrintWriter( content ));
1764 
1765 		iw.indent();
1766 
1767 		try{
1768 			for ( Category cat: cats ){
1769 
1770 				iw.println( cat.getName());
1771 
1772 				iw.indent();
1773 
1774 				try{
1775 					cat.dump( iw );
1776 
1777 				}finally{
1778 
1779 					iw.exdent();
1780 				}
1781 			}
1782 		}finally{
1783 
1784 			iw.exdent();
1785 
1786 			iw.close();
1787 		}
1788 
1789 		content.append( "Speed Limits" + NL );
1790 
1791 		iw = new IndentWriter( new PrintWriter( content ));
1792 
1793 		iw.indent();
1794 
1795 		try{
1796 			SpeedLimitHandler.getSingleton( core ).dump( iw );
1797 
1798 		}finally{
1799 
1800 			iw.exdent();
1801 
1802 			iw.close();
1803 		}
1804 
1805 		new TextViewerWindow(
1806 				MessageText.getString( "config.changes.title" ),
1807 				null, content.toString(), false  );
1808 
1809 	}
1810 
1811 
1812 	public static void
1813 	showText(
1814 		final String					title,
1815 		final String					message,
1816 		final java.util.List<String>	lines )
1817 	{
1818 		Utils.execSWTThreadLater(
1819 			1,
1820 			new Runnable()
1821 			{
1822 				public void
1823 				run()
1824 				{
1825 					StringBuffer	text = new StringBuffer( lines.size() * 80 );
1826 
1827 					for ( String s: lines ){
1828 
1829 						if ( text.length() > 0 ){
1830 							text.append( "\n" );
1831 						}
1832 						text.append( s );
1833 					}
1834 
1835 					TextViewerWindow viewer = new TextViewerWindow(title, message, text.toString(), false );
1836 
1837 					viewer.setEditable( false );
1838 				}
1839 			});
1840 	}
1841 
1842 	public static MenuItem addBlockedIPsMenuItem(Menu menu) {
1843 		return addMenuItem(menu, MENU_ID_IP_FILTER, new ListenerNeedingCoreRunning() {
1844 			public void handleEvent(AzureusCore core, Event e) {
1845 				BlockedIpsWindow.showBlockedIps(core,
1846 						getUIFunctionSWT().getMainShell());
1847 			}
1848 		});
1849 	}
1850 
1851 	public static MenuItem addConsoleMenuItem(Menu menu) {
1852 		return addMenuItem(menu, MENU_ID_CONSOLE, new Listener() {
1853 			public void handleEvent(Event e) {
1854 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
1855 				if (uiFunctions != null) {
1856 					uiFunctions.getMDI().showEntryByID(
1857 							MultipleDocumentInterface.SIDEBAR_SECTION_LOGGER);
1858 				}
1859 			}
1860 		});
1861 	}
1862 
1863 	public static MenuItem addStatisticsMenuItem(Menu menu) {
1864 		return addMenuItem(menu, MENU_ID_STATS, new Listener() {
1865 			public void handleEvent(Event e) {
1866 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
1867 				if (uiFunctions != null) {
1868 					MultipleDocumentInterface mdi = uiFunctions.getMDI();
1869 					mdi.showEntryByID(StatsView.VIEW_ID);
1870 				}
1871 			}
1872 		});
1873 	}
1874 
1875 	public static MenuItem addNatTestMenuItem(Menu menu) {
1876 		return addMenuItem(menu, MENU_ID_NAT_TEST, new Listener() {
1877 			public void handleEvent(Event e) {
1878 				new NatTestWindow();
1879 			}
1880 		});
1881 	}
1882 
1883 	public static MenuItem addNetStatusMenuItem(Menu menu) {
1884 		return addMenuItem(menu, MENU_ID_NET_STATUS, new Listener() {
1885 			public void handleEvent(Event e) {
1886 				UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
1887 				if (uiFunctions != null) {
1888 
1889 					PluginsMenuHelper.IViewInfo[] views = PluginsMenuHelper.getInstance().getPluginViewsInfo();
1890 
1891 					for ( PluginsMenuHelper.IViewInfo view: views ){
1892 
1893 						String viewID = view.viewID;
1894 
1895 						if ( viewID != null && viewID.equals( "aznetstatus" )){
1896 
1897 							view.openView( uiFunctions );
1898 						}
1899 					}
1900 				}
1901 			}
1902 		});
1903 	}
1904 
1905 	public static MenuItem addSpeedTestMenuItem(Menu menu) {
1906 		return addMenuItem(menu, MENU_ID_SPEED_TEST, new Listener() {
1907 			public void handleEvent(Event e) {
1908 				CoreWaiterSWT.waitForCoreRunning(new AzureusCoreRunningListener() {
1909 					public void azureusCoreRunning(AzureusCore core) {
1910 						new SpeedTestWizard();
1911 					}
1912 				});
1913 			}
1914 		});
1915 	}
1916 
1917 	public static MenuItem addConfigWizardMenuItem(Menu menu) {
1918 		return addMenuItem(menu, MENU_ID_CONFIGURE, new Listener() {
1919 			public void handleEvent(Event e) {
1920 				new ConfigureWizard(false,ConfigureWizard.WIZARD_MODE_FULL);
1921 			}
1922 		});
1923 	}
1924 
1925 	public static MenuItem addOptionsMenuItem(Menu menu) {
1926 		return addMenuItem(menu, MENU_ID_OPTIONS, new Listener() {
1927 			public void handleEvent(Event e) {
1928 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
1929 				if (uiFunctions != null) {
1930 					uiFunctions.getMDI().showEntryByID(
1931 							MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG);
1932 				}
1933 			}
1934 		});
1935 	}
1936 
1937 	public static MenuItem addMinimizeWindowMenuItem(Menu menu) {
1938 		final Shell shell = menu.getShell();
1939 
1940 		final MenuItem item = addMenuItem(menu, MENU_ID_WINDOW_MINIMIZE,
1941 				new Listener() {
1942 					public void handleEvent(Event event) {
1943 						if (null == shell || shell.isDisposed()) {
1944 							event.doit = false;
1945 							return;
1946 						}
1947 						shell.setMinimized(true);
1948 					}
1949 				});
1950 
1951 		Listener enableHandler = new Listener() {
1952 			public void handleEvent(Event event) {
1953 				if (null == shell || true == shell.isDisposed()
1954 						|| true == item.isDisposed()) {
1955 					event.doit = false;
1956 					return;
1957 				}
1958 
1959 				if (((shell.getStyle() & SWT.MIN) != 0)) {
1960 					item.setEnabled(false == shell.getMinimized());
1961 				} else {
1962 					item.setEnabled(false);
1963 				}
1964 			}
1965 		};
1966 
1967 		menu.addListener(SWT.Show, enableHandler);
1968 		shell.addListener(SWT.FocusIn, enableHandler);
1969 		shell.addListener(SWT.Iconify, enableHandler);
1970 		shell.addListener(SWT.Deiconify, enableHandler);
1971 
1972 		return item;
1973 	}
1974 
1975 	public static MenuItem addBringAllToFrontMenuItem(Menu menu) {
1976 		final MenuItem item = addMenuItem(menu, MENU_ID_WINDOW_ALL_TO_FRONT,
1977 				new Listener() {
1978 					public void handleEvent(Event event) {
1979 						Iterator<Shell> iter = ShellManager.sharedManager().getWindows();
1980 						while (iter.hasNext()) {
1981 							Shell shell = iter.next();
1982 							if (!shell.isDisposed() && !shell.getMinimized())
1983 								shell.open();
1984 						}
1985 					}
1986 				});
1987 
1988 		final Listener enableHandler = new Listener() {
1989 			public void handleEvent(Event event) {
1990 				if (item.isDisposed()) {
1991 					return;
1992 				}
1993 				Iterator<Shell> iter = ShellManager.sharedManager().getWindows();
1994 				boolean hasNonMaximizedShell = false;
1995 				while (iter.hasNext()) {
1996 					Shell shell = iter.next();
1997 					if (false == shell.isDisposed() && false == shell.getMinimized()) {
1998 						hasNonMaximizedShell = true;
1999 						break;
2000 					}
2001 				}
2002 				item.setEnabled(hasNonMaximizedShell);
2003 			}
2004 		};
2005 
2006 		menu.addListener(SWT.Show, enableHandler);
2007 		menu.getShell().addListener(SWT.FocusIn, enableHandler);
2008 
2009 		ShellManager.sharedManager().addWindowAddedListener(enableHandler);
2010 		ShellManager.sharedManager().addWindowRemovedListener(enableHandler);
2011 		item.addDisposeListener(new DisposeListener() {
2012 			public void widgetDisposed(DisposeEvent event) {
2013 				ShellManager.sharedManager().removeWindowAddedListener(enableHandler);
2014 				ShellManager.sharedManager().removeWindowRemovedListener(enableHandler);
2015 			}
2016 		});
2017 
2018 		return item;
2019 	}
2020 
2021 	/**
2022 	 * Appends the list of opened interactive windows to the bottom of the specified shell menu
2023 	 * @param menuParent The shell menu
2024 	 * @param shell
2025 	 */
2026 	public static void appendWindowMenuItems(final Menu menuParent) {
2027 		final Shell shell = menuParent.getShell();
2028 		final int numTopItems = menuParent.getItemCount();
2029 		Listener rebuild = new Listener() {
2030 			public void handleEvent(Event event) {
2031 				try {
2032 					if (menuParent.isDisposed() || shell.isDisposed())
2033 						return;
2034 
2035 					final int size = ShellManager.sharedManager().getSize();
2036 					if (size == menuParent.getItemCount() - numTopItems) {
2037 						for (int i = numTopItems; i < menuParent.getItemCount(); i++) {
2038 							final MenuItem item = menuParent.getItem(i);
2039 							item.setSelection(item.getData() == shell);
2040 						}
2041 						return;
2042 					}
2043 
2044 					for (int i = numTopItems; i < menuParent.getItemCount();)
2045 						menuParent.getItem(i).dispose();
2046 
2047 					Iterator<Shell> iter = ShellManager.sharedManager().getWindows();
2048 					for (int i = 0; i < size; i++) {
2049 						final Shell sh = iter.next();
2050 
2051 						if (sh.isDisposed() || sh.getText().length() == 0)
2052 							continue;
2053 
2054 						final MenuItem item = new MenuItem(menuParent, SWT.CHECK);
2055 
2056 						item.setText(sh.getText());
2057 						item.setSelection(shell == sh);
2058 						item.setData(sh);
2059 
2060 						item.addSelectionListener(new SelectionAdapter() {
2061 							public void widgetSelected(SelectionEvent event) {
2062 								if (event.widget.isDisposed() || sh.isDisposed())
2063 									return;
2064 
2065 								if (sh.getMinimized())
2066 									sh.setMinimized(false);
2067 
2068 								sh.open();
2069 							}
2070 						});
2071 					}
2072 				} catch (Exception e) {
2073 					Logger.log(new LogEvent(LogIDs.GUI, "rebuild menu error", e));
2074 				}
2075 			}
2076 		};
2077 
2078 		ShellManager.sharedManager().addWindowAddedListener(rebuild);
2079 		ShellManager.sharedManager().addWindowRemovedListener(rebuild);
2080 		shell.addListener(SWT.FocusIn, rebuild);
2081 		menuParent.addListener(SWT.Show, rebuild);
2082 	}
2083 
2084 	public static MenuItem addZoomWindowMenuItem(Menu menuParent) {
2085 		final Shell shell = menuParent.getShell();
2086 		final MenuItem item = addMenuItem(menuParent, MENU_ID_WINDOW_ZOOM,
2087 				new Listener() {
2088 					public void handleEvent(Event event) {
2089 						if (shell.isDisposed()) {
2090 							event.doit = false;
2091 							return;
2092 						}
2093 						shell.setMaximized(!shell.getMaximized());
2094 					}
2095 				});
2096 
2097 		Listener enableHandler = new Listener() {
2098 			public void handleEvent(Event event) {
2099 				if ( !shell.isDisposed() && !item.isDisposed()) {
2100 					if (false == Constants.isOSX) {
2101 						if (true == shell.getMaximized()) {
2102 							Messages.setLanguageText(
2103 									item,
2104 									MessageText.resolveLocalizationKey(MENU_ID_WINDOW_ZOOM_RESTORE));
2105 						} else {
2106 							Messages.setLanguageText(
2107 									item,
2108 									MessageText.resolveLocalizationKey(MENU_ID_WINDOW_ZOOM_MAXIMIZE));
2109 						}
2110 					}
2111 
2112 					if (((shell.getStyle() & SWT.MAX) != 0)) {
2113 						item.setEnabled(false == shell.getMinimized());
2114 					} else {
2115 						item.setEnabled(false);
2116 					}
2117 				}
2118 			}
2119 		};
2120 
2121 		menuParent.addListener(SWT.Show, enableHandler);
2122 		shell.addListener(SWT.FocusIn, enableHandler);
2123 		shell.addListener(SWT.Iconify, enableHandler);
2124 		shell.addListener(SWT.Deiconify, enableHandler);
2125 
2126 		return item;
2127 	}
2128 
2129 	public static MenuItem addAboutMenuItem(Menu menu) {
2130 		return addMenuItem(menu, MENU_ID_ABOUT, new Listener() {
2131 			public void handleEvent(Event e) {
2132 				AboutWindow.show();
2133 			}
2134 		});
2135 	}
2136 
2137 	public static MenuItem addHealthMenuItem(Menu menu) {
2138 		return addMenuItem(menu, MENU_ID_HEALTH, new Listener() {
2139 			public void handleEvent(Event e) {
2140 				HealthHelpWindow.show(getDisplay());
2141 			}
2142 		});
2143 	}
2144 
2145 	public static MenuItem addWhatsNewMenuItem(Menu menu) {
2146 		return addMenuItem(menu, MENU_ID_WHATS_NEW, new Listener() {
2147 			public void handleEvent(Event e) {
2148 				Utils.launch("http://plugins.vuze.com/changelog.php?version="
2149 						+ Constants.AZUREUS_VERSION);
2150 			}
2151 		});
2152 	}
2153 
2154 	public static MenuItem addWikiMenuItem(Menu menu) {
2155 		return addMenuItem(menu, MENU_ID_COMMUNITY_WIKI, new Listener() {
2156 			public void handleEvent(Event e) {
2157 				Utils.launch(Constants.AZUREUS_WIKI);
2158 			}
2159 		});
2160 	}
2161 
2162 	public static MenuItem addVoteMenuItem(Menu menu) {
2163 		return addMenuItem(menu, MENU_ID_VOTE, new Listener() {
2164 			public void handleEvent(Event e) {
2165 				Utils.launch(MessageText.getString("vote.vuze.url"));
2166 			}
2167 		});
2168 	}
2169 
2170 	public static MenuItem addReleaseNotesMenuItem(final Menu menu) {
2171 		return addMenuItem(menu, MENU_ID_RELEASE_NOTES, new Listener() {
2172 			public void handleEvent(Event e) {
2173 				new WelcomeWindow(menu.getShell());
2174 			}
2175 		});
2176 	}
2177 
2178 
2179 	public static MenuItem addHelpSupportMenuItem(Menu menu, final String support_url ) {
2180 		return addMenuItem(menu, MENU_ID_HELP_SUPPORT, new Listener() {
2181 			public void handleEvent(Event e) {
2182 				Utils.launch( support_url );
2183 			}
2184 		});
2185 	}
2186 
2187 	public static MenuItem addDonationMenuItem(Menu menu) {
2188 		return addMenuItem(menu, MENU_ID_DONATE, new Listener() {
2189       public void handleEvent(Event e) {
2190         DonationWindow.open(true, "menu");
2191       }
2192     });
2193 	}
2194 
2195 
2196 	public static MenuItem addGetPluginsMenuItem(Menu menu) {
2197 		return addMenuItem(menu, MENU_ID_PLUGINS_HELP, new Listener() {
2198 			public void handleEvent(Event e) {
2199 				Utils.launch("http://plugins.vuze.com/plugin_list.php");
2200 				//MultipleDocumentInterface mdi = UIFunctionsManager.getUIFunctions().getMDI();
2201 				//mdi.showEntryByID(MultipleDocumentInterface.SIDEBAR_SECTION_ABOUTPLUGINS);
2202 			}
2203 		});
2204 	}
2205 
2206 	public static MenuItem addDebugHelpMenuItem(Menu menu) {
2207 		return addMenuItem(menu, MENU_ID_DEBUG_HELP, new Listener() {
2208 			public void handleEvent(Event e) {
2209 				UIDebugGenerator.generate(Constants.APP_NAME + " "
2210 						+ Constants.AZUREUS_VERSION, "Generated via Help Menu");
2211 			}
2212 		});
2213 	}
2214 
2215 	public static MenuItem addCheckUpdateMenuItem(final Menu menu) {
2216 		return addMenuItem(menu, MENU_ID_UPDATE_CHECK, new ListenerNeedingCoreRunning() {
2217 			public void handleEvent(final AzureusCore core, Event e) {
2218 				UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
2219 				if (uiFunctions != null) {
2220 					uiFunctions.bringToFront();
2221 				}
2222 				Utils.getOffOfSWTThread(
2223 					new AERunnable()
2224 					{
2225 						public void
2226 						runSupport()
2227 						{
2228 							UpdateMonitor.getSingleton(core).performCheck(true, false, false,
2229 									new UpdateCheckInstanceListener() {
2230 										public void cancelled(UpdateCheckInstance instance) {
2231 										}
2232 
2233 										public void complete(UpdateCheckInstance instance) {
2234 											Update[] updates = instance.getUpdates();
2235 											boolean hasUpdates = false;
2236 											for (Update update : updates) {
2237 												if (update.getDownloaders().length > 0) {
2238 													hasUpdates = true;
2239 													break;
2240 												}
2241 											}
2242 											if (!hasUpdates) {
2243 
2244 												int build = Constants.getIncrementalBuild();
2245 
2246 												if ( COConfigurationManager.getBooleanParameter( "Beta Programme Enabled" ) && build > 0 ){
2247 
2248 													String build_str = "" + build;
2249 
2250 													if ( build_str.length() == 1 ){
2251 
2252 														build_str = "0" + build_str;
2253 													}
2254 
2255 													MessageBoxShell mb = new MessageBoxShell(
2256 															SWT.ICON_INFORMATION | SWT.OK,
2257 															"window.update.noupdates.beta", new String[]{ "B" + build_str });
2258 
2259 													mb.open(null);
2260 
2261 												}else{
2262 
2263 													MessageBoxShell mb = new MessageBoxShell(
2264 															SWT.ICON_INFORMATION | SWT.OK,
2265 															"window.update.noupdates", (String[]) null);
2266 
2267 													mb.open(null);
2268 												}
2269 											}
2270 										}
2271 									});
2272 						}
2273 					});
2274 			}
2275 		});
2276 	}
2277 
2278 	public static void addBetaMenuItem(Menu menuParent) {
2279 		final MenuItem menuItem = addMenuItem(menuParent, MENU_ID_BETA_PROG,
2280 				new Listener() {
2281 					public void handleEvent(Event e) {
2282 						new BetaWizard();
2283 			}
2284 		});
2285 
2286 		COConfigurationManager.addAndFireParameterListener(
2287 				"Beta Programme Enabled", new ParameterListener() {
2288 					public void parameterChanged(String parameterName) {
2289 						Utils.execSWTThread(new AERunnable() {
2290 							public void runSupport() {
2291 								if ( menuItem.isDisposed()){
2292 									return;
2293 								}
2294 								boolean enabled = COConfigurationManager.getBooleanParameter("Beta Programme Enabled");
2295 								Messages.setLanguageText(
2296 										menuItem,
2297 										MessageText.resolveLocalizationKey(MENU_ID_BETA_PROG
2298 												+ (enabled ? ".off" : ".on")));
2299 							}
2300 						});
2301 					}
2302 				});
2303 
2304 		boolean enabled = COConfigurationManager.getBooleanParameter("Beta Programme Enabled");
2305 
2306 		if ( enabled ){
2307 
2308 			addMenuItem(menuParent, MENU_ID_BETA_PROG_BUG, new Listener() {
2309 				public void handleEvent(Event e) {
2310 					Utils.launch( MessageText.getString( "beta.bug.url" ));
2311 				}
2312 			});
2313 		}
2314 	}
2315 
2316 	public static MenuItem addPluginInstallMenuItem(Menu menuParent) {
2317 		return addMenuItem(menuParent, MENU_ID_PLUGINS_INSTALL,
2318 				new Listener() {
2319 					public void handleEvent(Event e) {
2320 						new InstallPluginWizard();
2321 			}
2322 		});
2323 	}
2324 
2325 	public static MenuItem addPluginUnInstallMenuItem(Menu menuParent) {
2326 		return addMenuItem(menuParent, MENU_ID_PLUGINS_UNINSTALL,
2327 				new Listener() {
2328 					public void handleEvent(Event e) {
2329 						new UnInstallPluginWizard(getDisplay());
2330 			}
2331 		});
2332 	}
2333 
2334 	public static void
2335 	addAlertsMenu(
2336 		Menu					menu,
2337 		boolean	createSubmenu,
2338 		final DownloadManager[]	dms )
2339 	{
2340 		if ( dms.length == 0 ){
2341 
2342 			return;
2343 		}
2344 
2345 		Menu alert_menu;
2346 
2347 		if (createSubmenu) {
2348   		alert_menu = new Menu( menu.getShell(), SWT.DROP_DOWN );
2349 
2350   		MenuItem alerts_item = new MenuItem( menu, SWT.CASCADE);
2351 
2352   		Messages.setLanguageText( alerts_item, "ConfigView.section.interface.alerts" );
2353 
2354   		alerts_item.setMenu(alert_menu);
2355 		} else {
2356 			alert_menu = menu;
2357 		}
2358 
2359 		String[][] alert_keys =
2360 			{	{ "Play Download Finished", "playdownloadfinished" },
2361 				{ "Play Download Finished Announcement", "playdownloadspeech" },
2362 				{ "Popup Download Finished", "popupdownloadfinished" },
2363 			};
2364 
2365 		boolean[]	all_enabled = new boolean[ alert_keys.length ];
2366 
2367 		Arrays.fill( all_enabled, true );
2368 
2369 		for ( DownloadManager dm: dms ){
2370 
2371 			DownloadManagerState state = dm.getDownloadState();
2372 
2373 			Map map = state.getMapAttribute( DownloadManagerState.AT_DL_FILE_ALERTS );
2374 
2375 			if ( map == null ){
2376 
2377 				Arrays.fill( all_enabled, false );
2378 
2379 			}else{
2380 
2381 				for (int i=0;i<alert_keys.length;i++ ){
2382 
2383 					if ( !map.containsKey( alert_keys[i][0] )){
2384 
2385 						all_enabled[i] = false;
2386 					}
2387 				}
2388 			}
2389 		}
2390 
2391 		for (int i=0;i<alert_keys.length;i++ ){
2392 
2393 			final String[] entry = alert_keys[i];
2394 
2395 			if ( i != 1 || Constants.isOSX ){
2396 
2397 				final MenuItem item = new MenuItem( alert_menu, SWT.CHECK);
2398 
2399 				item.setText( MessageText.getString( "ConfigView.label." + entry[1] ));
2400 
2401 				item.setSelection( all_enabled[i]);
2402 
2403 				item.addListener(
2404 					SWT.Selection,
2405 					new Listener()
2406 					{
2407 						public void
2408 						handleEvent(
2409 							Event event )
2410 						{
2411 							boolean	selected = item.getSelection();
2412 
2413 							for ( DownloadManager dm: dms ){
2414 
2415 								DownloadManagerState state = dm.getDownloadState();
2416 
2417 								Map map = state.getMapAttribute( DownloadManagerState.AT_DL_FILE_ALERTS );
2418 
2419 								if ( map == null ){
2420 
2421 									map = new HashMap();
2422 
2423 								}else{
2424 
2425 									map = new HashMap( map );
2426 								}
2427 
2428 								if ( selected ){
2429 
2430 									map.put( entry[0], "" );
2431 
2432 								}else{
2433 
2434 									map.remove( entry[0] );
2435 
2436 								}
2437 								state.setMapAttribute( DownloadManagerState.AT_DL_FILE_ALERTS, map );
2438 							}
2439 						}
2440 					});
2441 			}
2442 		}
2443 	}
2444 
2445 	public static void
2446 	addAlertsMenu(
2447 		Menu							menu,
2448 		final DownloadManager			dm,
2449 		final DiskManagerFileInfo[]		files )
2450 	{
2451 		if ( files.length == 0 ){
2452 
2453 			return;
2454 		}
2455 
2456 		String[][] alert_keys =
2457 			{	{ "Play File Finished", "playfilefinished" },
2458 				{ "Play File Finished Announcement", "playfilespeech" },
2459 				{ "Popup File Finished", "popupfilefinished" },
2460 			};
2461 
2462 
2463 		Menu alert_menu = new Menu( menu.getShell(), SWT.DROP_DOWN );
2464 
2465 		MenuItem alerts_item = new MenuItem( menu, SWT.CASCADE);
2466 
2467 		Messages.setLanguageText( alerts_item, "ConfigView.section.interface.alerts" );
2468 
2469 		alerts_item.setMenu(alert_menu);
2470 
2471 		boolean[]	all_enabled = new boolean[ alert_keys.length ];
2472 
2473 		DownloadManagerState state = dm.getDownloadState();
2474 
2475 		Map map = state.getMapAttribute( DownloadManagerState.AT_DL_FILE_ALERTS );
2476 
2477 		if ( map != null ){
2478 
2479 			Arrays.fill( all_enabled, true );
2480 
2481 			for ( DiskManagerFileInfo file: files ){
2482 
2483 				for (int i=0;i<alert_keys.length;i++ ){
2484 
2485 					String key = String.valueOf( file.getIndex()) + "." + alert_keys[i][0];
2486 
2487 					if ( !map.containsKey( key )){
2488 
2489 						all_enabled[i] = false;
2490 					}
2491 				}
2492 			}
2493 		}
2494 
2495 		for (int i=0;i<alert_keys.length;i++ ){
2496 
2497 			final String[] entry = alert_keys[i];
2498 
2499 			if ( i != 1 || Constants.isOSX ){
2500 
2501 				final MenuItem item = new MenuItem( alert_menu, SWT.CHECK);
2502 
2503 				item.setText( MessageText.getString( "ConfigView.label." + entry[1] ));
2504 
2505 				item.setSelection( all_enabled[i]);
2506 
2507 				item.addListener(
2508 					SWT.Selection,
2509 					new Listener()
2510 					{
2511 						public void
2512 						handleEvent(
2513 							Event event )
2514 						{
2515 							DownloadManagerState state = dm.getDownloadState();
2516 
2517 							Map map = state.getMapAttribute( DownloadManagerState.AT_DL_FILE_ALERTS );
2518 
2519 							if ( map == null ){
2520 
2521 								map = new HashMap();
2522 
2523 							}else{
2524 
2525 								map = new HashMap( map );
2526 							}
2527 
2528 							boolean	selected = item.getSelection();
2529 
2530 							for ( DiskManagerFileInfo file: files ){
2531 
2532 								String key = String.valueOf( file.getIndex()) + "." + entry[0];
2533 
2534 								if ( selected ){
2535 
2536 									map.put( key, "" );
2537 
2538 								}else{
2539 
2540 									map.remove( key );
2541 								}
2542 							}
2543 
2544 							state.setMapAttribute( DownloadManagerState.AT_DL_FILE_ALERTS, map );
2545 						}
2546 					});
2547 			}
2548 		}
2549 	}
2550 
2551 	/**
2552 	 * Creates a menu item that is simply a label; it does nothing is selected
2553 	 * @param menu
2554 	 * @param localizationKey
2555 	 * @return
2556 	 */
2557 	public static final MenuItem addLabelMenuItem(Menu menu,
2558 			String localizationKey) {
2559 		MenuItem item = new MenuItem(menu, SWT.NULL);
2560 		Messages.setLanguageText(item, localizationKey);
2561 		item.setEnabled(false);
2562 		return item;
2563 	}
2564 
2565 	public static void addPairingMenuItem(Menu menu) {
2566 		MenuFactory.addMenuItem(menu, MENU_ID_PAIRING, new Listener() {
2567 			public void handleEvent(Event e) {
2568 				UIFunctionsSWT uiFunctionsSWT = UIFunctionsManagerSWT.getUIFunctionsSWT();
2569 				if (uiFunctionsSWT != null) {
2570 					uiFunctionsSWT.openRemotePairingWindow();
2571 				}
2572 			}
2573 		});
2574 
2575 	}
2576 	//==========================
2577 
2578 	public static MenuItem addSeparatorMenuItem(Menu menuParent) {
2579 		return new MenuItem(menuParent, SWT.SEPARATOR);
2580 	}
2581 
2582 	public static MenuItem createTopLevelMenuItem(Menu menuParent,
2583 			String localizationKey) {
2584 		Menu menu = new Menu(menuParent.getShell(), SWT.DROP_DOWN);
2585 		MenuItem menuItem = new MenuItem(menuParent, SWT.CASCADE);
2586 		Messages.setLanguageText(menuItem, localizationKey);
2587 		menuItem.setMenu(menu);
2588 
2589 		/*
2590 		 * A top level menu and its menu item has the same ID; this is used to locate them at runtime
2591 		 */
2592 		menu.setData(KEY_MENU_ID, localizationKey);
2593 		menuItem.setData(KEY_MENU_ID, localizationKey);
2594 
2595 		return menuItem;
2596 	}
2597 
2598 	public static final MenuItem addMenuItem(Menu menu, String localizationKey,
2599 			Listener selListener) {
2600 		return addMenuItem(menu, localizationKey, selListener, SWT.NONE);
2601 	}
2602 
2603 	public static final MenuItem addMenuItem(Menu menu, String localizationKey,
2604 			Listener selListener, int style) {
2605 		MenuItem menuItem = new MenuItem(menu, style);
2606 		Messages.setLanguageText(menuItem,
2607 				MessageText.resolveLocalizationKey(localizationKey));
2608 		KeyBindings.setAccelerator(menuItem,
2609 				MessageText.resolveAcceleratorKey(localizationKey));
2610 		if (null != selListener) {
2611 			menuItem.addListener(SWT.Selection, selListener);
2612 		}
2613 		/*
2614 		 * Using the localizationKey as the id for the menu item; this can be used to locate it at runtime
2615 		 * using .KN: missing method pointers
2616 		 */
2617 		menuItem.setData(KEY_MENU_ID, localizationKey);
2618 		return menuItem;
2619 	}
2620 
2621 	public static final MenuItem addMenuItem(Menu menu, int style,
2622 			String localizationKey, Listener selListener) {
2623 		return addMenuItem(menu, style, -1, localizationKey, selListener);
2624 	}
2625 
2626 	public static final MenuItem addMenuItem(Menu menu, int style, int index,
2627 			String localizationKey, Listener selListener) {
2628 		if (index < 0 || index > menu.getItemCount()) {
2629 			index = menu.getItemCount();
2630 		}
2631 		MenuItem menuItem = new MenuItem(menu, style, index);
2632 		Messages.setLanguageText(menuItem, localizationKey);
2633 		KeyBindings.setAccelerator(menuItem, localizationKey);
2634 		menuItem.addListener(SWT.Selection, selListener);
2635 		/*
2636 		 * Using the localizationKey as the id for the menu item; this can be used to locate it at runtime
2637 		 * using .KN: missing method pointers
2638 		 */
2639 		menuItem.setData(KEY_MENU_ID, localizationKey);
2640 		return menuItem;
2641 	}
2642 
2643 	private static UIFunctionsSWT getUIFunctionSWT() {
2644 		UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
2645 		if (null != uiFunctions) {
2646 			return uiFunctions;
2647 		}
2648 		throw new IllegalStateException(
2649 				"No instance of UIFunctionsSWT found; the UIFunctionsManager might not have been initialized properly");
2650 	}
2651 
2652 	private static Display getDisplay() {
2653 		return SWTThread.getInstance().getDisplay();
2654 	}
2655 
2656 	public static void updateMenuText(Object menu) {
2657 		if (menu == null)
2658 			return;
2659 		if (menu instanceof Menu) {
2660 			MenuItem[] menus = ((Menu) menu).getItems();
2661 			for (int i = 0; i < menus.length; i++) {
2662 				updateMenuText(menus[i]);
2663 			}
2664 		} else if (menu instanceof MenuItem) {
2665 			MenuItem item = (MenuItem) menu;
2666 			if (item.getData(KEY_MENU_ID) instanceof String) {
2667 				String localizationKey = (String) item.getData(KEY_MENU_ID);
2668 				item.setText(MessageText.getString(localizationKey));
2669 				KeyBindings.setAccelerator(item,
2670 						MessageText.resolveAcceleratorKey(localizationKey));
2671 				updateMenuText(item.getMenu());
2672 			} else {
2673 				Messages.updateLanguageForControl(item);
2674 			}
2675 		}
2676 	}
2677 
2678 	public static void performOneTimeDisable(MenuItem item,
2679 			boolean affectsChildMenuItems) {
2680 		item.setEnabled(false);
2681 		if (affectsChildMenuItems) {
2682 			Menu childMenu = item.getMenu();
2683 			if (childMenu == null)
2684 				return;
2685 
2686 			for (int i = 0; i < childMenu.getItemCount(); i++) {
2687 				childMenu.getItem(i).setEnabled(false);
2688 			}
2689 		}
2690 	}
2691 
2692 	/**
2693 	 * Find and return the menu with the given id starting from the given menu
2694 	 *
2695 	 * @param menuToStartWith
2696 	 * @param idToMatch any of the menu keys listed in {@link org.gudy.azureus2.ui.swt.mainwindow.IMenuConstants}
2697 	 * @return may return <code>null</code> if not found
2698 	 */
2699 	public static Menu findMenu(Menu menuToStartWith, String idToMatch) {
2700 
2701 		/*
2702 		 * This is a recursive method; it will start at the given menuToStartWith
2703 		 * and recursively traverse to all its sub menus until a matching
2704 		 * menu is found or until it has touched all sub menus
2705 		 */
2706 		if (null == menuToStartWith || true == menuToStartWith.isDisposed()
2707 				|| null == idToMatch || idToMatch.length() < 1) {
2708 			return null;
2709 		}
2710 
2711 		/*
2712 		 * The given menuToStartWith may be the one we're looking for
2713 		 */
2714 		if (true == idToMatch.equals(getID(menuToStartWith))) {
2715 			return menuToStartWith;
2716 		}
2717 
2718 		MenuItem[] items = menuToStartWith.getItems();
2719 
2720 		/*
2721 		 * Go deeper into each child to try and find it
2722 		 */
2723 		for (int i = 0; i < items.length; i++) {
2724 			MenuItem item = items[i];
2725 			Menu menuToFind = findMenu(item.getMenu(), idToMatch);
2726 			if (null != menuToFind) {
2727 				return menuToFind;
2728 			}
2729 		}
2730 
2731 		return null;
2732 	}
2733 
2734 	/**
2735 	 * Find and return the menu item with the given id starting from the given menu
2736 	 *
2737 	 * @param menuToStartWith
2738 	 * @param idToMatch any of the menu keys listed in {@link org.gudy.azureus2.ui.swt.mainwindow.IMenuConstants}
2739 	 * @return may return <code>null</code> if not found
2740 	 */
2741 	public static MenuItem findMenuItem(Menu menuToStartWith, String idToMatch) {
2742 		return findMenuItem(menuToStartWith, idToMatch, true);
2743 	}
2744 
2745 	public static MenuItem findMenuItem(Menu menuToStartWith, String idToMatch, boolean deep) {
2746 		/*
2747 		 * This is a recursive method; it will start at the given menuToStartWith
2748 		 * and recursively traverse to all its sub menus until a matching
2749 		 * menu item is found or until it has touched all existing menu items
2750 		 */
2751 		if (null == menuToStartWith || true == menuToStartWith.isDisposed()
2752 				|| null == idToMatch || idToMatch.length() < 1) {
2753 			return null;
2754 		}
2755 
2756 		MenuItem[] items = menuToStartWith.getItems();
2757 
2758 		for (int i = 0; i < items.length; i++) {
2759 			MenuItem item = items[i];
2760 			if (true == idToMatch.equals(getID(item))) {
2761 				return item;
2762 			}
2763 
2764 			if (deep) {
2765   			/*
2766   			 * Go deeper into each child to try and find it
2767   			 */
2768   			MenuItem menuItemToFind = findMenuItem(item.getMenu(), idToMatch);
2769   			if (null != menuItemToFind) {
2770   				return menuItemToFind;
2771   			}
2772 			}
2773 		}
2774 
2775 		return null;
2776 	}
2777 
2778 	private static String getID(Widget widget) {
2779 		if (null != widget && false == widget.isDisposed()) {
2780 			Object id = widget.getData(KEY_MENU_ID);
2781 			if (null != id) {
2782 				return id.toString();
2783 			}
2784 		}
2785 		return "";
2786 	}
2787 
2788 	public static void setEnablementKeys(Widget widget, int keys) {
2789 		if (null != widget && false == widget.isDisposed()) {
2790 			widget.setData(KEY_ENABLEMENT, new Integer(keys));
2791 		}
2792 	}
2793 
2794 	public static int getEnablementKeys(Widget widget) {
2795 		if (null != widget && false == widget.isDisposed()) {
2796 			Object keys = widget.getData(KEY_ENABLEMENT);
2797 			if (keys instanceof Integer) {
2798 				return ((Integer) keys).intValue();
2799 			}
2800 		}
2801 		return -1;
2802 	}
2803 
2804 	/**
2805 	 * Updates the enabled state of the given menu and all its applicable children
2806 	 * <p><b>NOTE:</b> This method currently iterates through the menu hierarchy to
2807 	 * set the enablement which may be inefficient since most menus do not have this flag set;
2808 	 * it may be desirable to employ a map of only the effected menus for efficient direct
2809 	 * access to them</p>
2810 	 * @param menuToStartWith
2811 	 */
2812 	public static void updateEnabledStates(Menu menuToStartWith) {
2813 		/*
2814 		 * This is a recursive method; it will start at the given menuToStartWith
2815 		 * and recursively traverse to all its sub menus until a matching
2816 		 * menu item is found or until it has touched all existing menu items
2817 		 */
2818 		if (null == menuToStartWith || true == menuToStartWith.isDisposed()) {
2819 			return;
2820 		}
2821 
2822 		/*
2823 		 * If the given menu itself is disabled then just return since
2824 		 * its menu items can not be seen anyway
2825 		 */
2826 		if (false == setEnablement(menuToStartWith)) {
2827 			return;
2828 		}
2829 
2830 		MenuItem[] items = menuToStartWith.getItems();
2831 
2832 		for (int i = 0; i < items.length; i++) {
2833 			MenuItem item = items[i];
2834 
2835 			/*
2836 			 * If the current menu item is disabled then just return since
2837 			 * its children items can not be seen anyway
2838 			 */
2839 			if (false == setEnablement(item)) {
2840 				continue;
2841 			}
2842 
2843 			/*
2844 			 * Go deeper into the children items and set their enablement
2845 			 */
2846 			updateEnabledStates(item.getMenu());
2847 
2848 		}
2849 	}
2850 
2851 	/**
2852 	 * Sets whether the given widget is enabled or not based on the value of the
2853 	 * KEY_ENABLEMENT object data set into the given widget.
2854 	 * @param widget
2855 	 * @return
2856 	 */
2857 	public static boolean setEnablement(Widget widget) {
2858 		if (null != widget && false == widget.isDisposed()) {
2859 			boolean isEnabled = isEnabledForCurrentMode(widget);
2860 
2861 			if (widget instanceof MenuItem) {
2862 				((MenuItem) widget).setEnabled(isEnabled);
2863 			} else if (widget instanceof Menu) {
2864 				((Menu) widget).setEnabled(isEnabled);
2865 			}
2866 			return isEnabled;
2867 		}
2868 		return false;
2869 	}
2870 
2871 	/**
2872 	 * Returns whether the given widget should be enabled for the current mode;
2873 	 * current mode can be az2, az3, or az3 advanced.
2874 	 * @param widget
2875 	 * @return
2876 	 */
2877 	public static boolean isEnabledForCurrentMode(Widget widget) {
2878 		int keys = getEnablementKeys(widget);
2879 		if (keys <= 0) {
2880 			return true;
2881 		} else if (true == isAZ3) {
2882 			return ((keys & FOR_AZ3) != 0);
2883 		} else {
2884 			return ((keys & FOR_AZ2) != 0);
2885 		}
2886 	}
2887 
2888 	private static final boolean DEBUG_SET_FOREGROUND = System.getProperty("debug.setforeground") != null;
2889 
2890 	private static TableRow wrapAsRow(final Object o, final String table_name) {
2891 		return new TableRow() {
2892 			  public Object getDataSource() {return o;}
2893 			  public String getTableID() {return table_name;}
2894 
2895 			  private void notSupported() {
2896 				  throw new RuntimeException("method is not supported - table row is a \"virtual\" one, only getDataSource and getTableID are supported.");
2897 			  }
2898 
2899 			  private void setForegroundDebug() {
2900 				  if (DEBUG_SET_FOREGROUND) {
2901 					  Debug.out("setForeground on fake TableRow");
2902 				  }
2903 			  }
2904 
2905 			  // Everything below is unsupported.
2906 			  public int getIndex() {notSupported(); return 0;}
2907 			  public void setForeground(int red, int green, int blue) {setForegroundDebug(); notSupported();}
2908 			  public void setForeground(int[] rgb) {setForegroundDebug(); notSupported();}
2909 			  public void setForegroundToErrorColor() {setForegroundDebug(); notSupported();}
2910 			  public boolean isValid() {notSupported(); return false;}
2911 			  public TableCell getTableCell(String sColumnName) {notSupported(); return null;}
2912 			  public boolean isSelected()  {notSupported(); return false;}
2913 			  public void addMouseListener(TableRowMouseListener listener) {notSupported();}
2914 			  public void removeMouseListener(TableRowMouseListener listener) {notSupported();}
2915 			  public Object getData(String id) {return null;}
2916 			  public void setData(String id, Object data) {}
2917 		};
2918 	}
2919 }
2920