1 /**
2  * Created on Nov 15, 2010
3  *
4  * Copyright (C) Azureus Software, Inc, All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
19  */
20 
21 package org.gudy.azureus2.ui.swt.views.utils;
22 
23 import java.io.File;
24 import java.util.*;
25 import java.util.List;
26 
27 import org.eclipse.swt.SWT;
28 import org.eclipse.swt.events.DisposeEvent;
29 import org.eclipse.swt.events.DisposeListener;
30 import org.eclipse.swt.layout.FillLayout;
31 import org.eclipse.swt.widgets.*;
32 import org.gudy.azureus2.core3.config.COConfigurationManager;
33 import org.gudy.azureus2.core3.download.DownloadManager;
34 import org.gudy.azureus2.core3.download.DownloadManagerState;
35 import org.gudy.azureus2.core3.internat.MessageText;
36 import org.gudy.azureus2.core3.util.*;
37 import org.gudy.azureus2.plugins.PluginInterface;
38 import org.gudy.azureus2.plugins.ui.menus.MenuItemListener;
39 import org.gudy.azureus2.plugins.ui.menus.MenuManager;
40 import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
41 import org.gudy.azureus2.pluginsimpl.local.utils.FormattersImpl;
42 import org.gudy.azureus2.ui.common.util.MenuItemManager;
43 import org.gudy.azureus2.ui.swt.*;
44 import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
45 import org.gudy.azureus2.ui.swt.mainwindow.MenuFactory;
46 import org.gudy.azureus2.ui.swt.mainwindow.TorrentOpener;
47 import org.gudy.azureus2.ui.swt.maketorrent.MultiTrackerEditor;
48 import org.gudy.azureus2.ui.swt.maketorrent.TrackerEditorListener;
49 import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
50 import org.gudy.azureus2.ui.swt.views.FilesView;
51 import org.gudy.azureus2.ui.swt.views.ViewUtils;
52 import org.gudy.azureus2.ui.swt.views.ViewUtils.SpeedAdapter;
53 import org.gudy.azureus2.ui.swt.views.stats.StatsView;
54 
55 import com.aelitis.azureus.core.AzureusCore;
56 import com.aelitis.azureus.core.AzureusCoreFactory;
57 import com.aelitis.azureus.core.AzureusCoreRunningListener;
58 import com.aelitis.azureus.core.tag.*;
59 import com.aelitis.azureus.core.tag.TagFeatureProperties.TagProperty;
60 import com.aelitis.azureus.core.util.AZ3Functions;
61 import com.aelitis.azureus.plugins.net.buddy.BuddyPlugin;
62 import com.aelitis.azureus.plugins.net.buddy.BuddyPluginBuddy;
63 import com.aelitis.azureus.ui.*;
64 import com.aelitis.azureus.ui.common.updater.UIUpdatable;
65 import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
66 import com.aelitis.azureus.ui.swt.uiupdater.UIUpdaterSWT;
67 
68 /**
69  * @author TuxPaper
70  * @created Nov 15, 2010
71  *
72  */
73 public class TagUIUtils
74 {
75 	public static final int MAX_TOP_LEVEL_TAGS_IN_MENU	= 20;
76 
77 	public static String
getChatKey( Tag tag )78 	getChatKey(
79 		Tag		tag )
80 	{
81 		return( "Tag: " + tag.getTagName( true ));
82 	}
83 
84 	public static void
setupSideBarMenus( final MenuManager menuManager )85 	setupSideBarMenus(
86 		final MenuManager	menuManager )
87 	{
88 		org.gudy.azureus2.plugins.ui.menus.MenuItem menuItem = menuManager.addMenuItem("sidebar."
89 				+ MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS,
90 				"ConfigView.section.style.TagInSidebar");
91 
92 		menuItem.setStyle(org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_CHECK);
93 
94 		menuItem.addListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemListener() {
95 			public void selected(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object target) {
96 				boolean b = COConfigurationManager.getBooleanParameter("Library.TagInSideBar");
97 				COConfigurationManager.setParameter("Library.TagInSideBar", !b);
98 			}
99 		});
100 
101 		menuItem.addFillListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener() {
102 			public void menuWillBeShown(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object data) {
103 				menu.setData(Boolean.valueOf(COConfigurationManager.getBooleanParameter("Library.TagInSideBar")));
104 			}
105 		});
106 
107 			// tag options
108 
109 		menuItem = menuManager.addMenuItem("sidebar."
110 				+ MultipleDocumentInterface.SIDEBAR_HEADER_TRANSFERS,
111 				"label.tags");
112 
113 		menuItem.setStyle(org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_MENU);
114 
115 		menuItem.addFillListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener() {
116 			public void menuWillBeShown(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object data) {
117 				menu.removeAllChildItems();
118 
119 
120 					// manual
121 
122 				final TagType manual_tt = TagManagerFactory.getTagManager().getTagType( TagType.TT_DOWNLOAD_MANUAL );
123 
124 				org.gudy.azureus2.plugins.ui.menus.MenuItem menuItem = menuManager.addMenuItem( menu, manual_tt.getTagTypeName( false ));
125 
126 				menuItem.setStyle( org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_MENU );
127 
128 				menuItem.addFillListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener() {
129 					public void menuWillBeShown(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object data) {
130 						menu.removeAllChildItems();
131 
132 						final List<Tag> all_tags = manual_tt.getTags();
133 
134 						List<String>	menu_names 		= new ArrayList<String>();
135 						Map<String,Tag>	menu_name_map 	= new IdentityHashMap<String, Tag>();
136 
137 						boolean	all_visible 	= true;
138 						boolean all_invisible 	= true;
139 
140 						boolean	has_ut	= false;
141 
142 						for ( Tag t: all_tags ){
143 
144 							String name = t.getTagName( true );
145 
146 							menu_names.add( name );
147 							menu_name_map.put( name, t );
148 
149 							if ( t.isVisible()){
150 								all_invisible = false;
151 							}else{
152 								all_visible = false;
153 							}
154 
155 							TagFeatureProperties props = (TagFeatureProperties)t;
156 
157 							TagProperty prop = props.getProperty( TagFeatureProperties.PR_UNTAGGED );
158 
159 							if ( prop != null ){
160 
161 								Boolean b = prop.getBoolean();
162 
163 								if ( b != null && b ){
164 
165 									has_ut = true;
166 								}
167 							}
168 						}
169 
170 						org.gudy.azureus2.plugins.ui.menus.MenuItem showAllItem = menuManager.addMenuItem( menu, "label.show.all" );
171 						showAllItem.setStyle(org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_PUSH );
172 
173 						showAllItem.addListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemListener() {
174 							public void selected(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object target) {
175 								for ( Tag t: all_tags ){
176 									t.setVisible( true );
177 								}
178 							}
179 						});
180 
181 						org.gudy.azureus2.plugins.ui.menus.MenuItem hideAllItem = menuManager.addMenuItem( menu, "popup.error.hideall" );
182 						hideAllItem.setStyle(org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_PUSH );
183 
184 						hideAllItem.addListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemListener() {
185 							public void selected(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object target) {
186 								for ( Tag t: all_tags ){
187 									t.setVisible( false );
188 								}
189 							}
190 						});
191 
192 						org.gudy.azureus2.plugins.ui.menus.MenuItem sepItem = menuManager.addMenuItem( menu, "sepm" );
193 
194 						sepItem.setStyle(org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_SEPARATOR );
195 
196 						showAllItem.setEnabled( !all_visible );
197 						hideAllItem.setEnabled( !all_invisible );
198 
199 						List<Object>	menu_structure = MenuBuildUtils.splitLongMenuListIntoHierarchy( menu_names, TagUIUtils.MAX_TOP_LEVEL_TAGS_IN_MENU );
200 
201 						for ( Object obj: menu_structure ){
202 
203 							List<Tag>	bucket_tags = new ArrayList<Tag>();
204 
205 							org.gudy.azureus2.plugins.ui.menus.MenuItem parent_menu;
206 
207 							if ( obj instanceof String ){
208 
209 								parent_menu = menu;
210 
211 								bucket_tags.add( menu_name_map.get((String)obj));
212 
213 							}else{
214 
215 								Object[]	entry = (Object[])obj;
216 
217 								List<String>	tag_names = (List<String>)entry[1];
218 
219 								boolean	sub_all_visible 	= true;
220 								boolean sub_some_visible	= false;
221 
222 								for ( String name: tag_names ){
223 
224 									Tag tag = menu_name_map.get( name );
225 
226 									if ( tag.isVisible()){
227 
228 										sub_some_visible = true;
229 
230 									}else{
231 
232 										sub_all_visible = false;
233 									}
234 
235 									bucket_tags.add( tag );
236 								}
237 
238 								String mod;
239 
240 								if ( sub_all_visible ){
241 
242 									mod = " (*)";
243 
244 								}else if ( sub_some_visible ){
245 
246 									mod = " (+)";
247 
248 								}else{
249 
250 									mod = "";
251 								}
252 
253 								parent_menu = menuManager.addMenuItem (menu, "!" + (String)entry[0] + mod + "!" );
254 
255 								parent_menu.setStyle( org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_MENU );
256 
257 
258 							}
259 
260 							for ( final Tag tag: bucket_tags ){
261 
262 								org.gudy.azureus2.plugins.ui.menus.MenuItem m = menuManager.addMenuItem( parent_menu, tag.getTagName( false ));
263 
264 								m.setStyle( org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_CHECK );
265 
266 								m.setData( new Boolean( tag.isVisible()));
267 
268 								m.addListener(
269 									new MenuItemListener()
270 									{
271 										public void
272 										selected(
273 											org.gudy.azureus2.plugins.ui.menus.MenuItem			menu,
274 											Object 												target )
275 										{
276 											tag.setVisible( !tag.isVisible());
277 										}
278 									});
279 							}
280 						}
281 
282 						if ( !has_ut ){
283 
284 							sepItem = menuManager.addMenuItem( menu, "sepu" );
285 
286 							sepItem.setStyle(org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_SEPARATOR );
287 
288 
289 							org.gudy.azureus2.plugins.ui.menus.MenuItem m = menuManager.addMenuItem( menu, "label.untagged" );
290 
291 							m.setStyle( org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_PUSH );
292 
293 							m.addListener(
294 								new MenuItemListener()
295 								{
296 									public void
297 									selected(
298 										org.gudy.azureus2.plugins.ui.menus.MenuItem			menu,
299 										Object 												target )
300 									{
301 										try{
302 											String tag_name = MessageText.getString( "label.untagged" );
303 
304 											Tag ut_tag = manual_tt.getTag( tag_name, true );
305 
306 											if ( ut_tag == null ){
307 
308 
309 												ut_tag = manual_tt.createTag( tag_name, true );
310 											}
311 
312 											TagFeatureProperties tp = (TagFeatureProperties)ut_tag;
313 
314 											tp.getProperty( TagFeatureProperties.PR_UNTAGGED ).setBoolean( true );
315 
316 										}catch( TagException e ){
317 
318 											Debug.out( e );
319 										}
320 									}
321 								});
322 						}
323 					}
324 				});
325 
326 				menuItem = menuManager.addMenuItem( menu, "label.add.tag");
327 
328 				menuItem.addListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemListener() {
329 					public void selected(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object target) {
330 						createManualTag(null);
331 					}
332 				});
333 
334 				org.gudy.azureus2.plugins.ui.menus.MenuItem sepItem = menuManager.addMenuItem( menu, "sep1" );
335 
336 				sepItem.setStyle(org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_SEPARATOR );
337 
338 
339 					// auto
340 
341 				menuItem = menuManager.addMenuItem( menu, "wizard.maketorrent.auto" );
342 
343 				menuItem.setStyle( org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_MENU );
344 
345 				menuItem.addFillListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener() {
346 					public void menuWillBeShown(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object data) {
347 						menu.removeAllChildItems();
348 
349 							// content
350 
351 						org.gudy.azureus2.plugins.ui.menus.MenuItem menuItem = menuManager.addMenuItem( menu, "label.content" );
352 
353 						menuItem.setStyle(org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_MENU);
354 
355 						menuItem.addFillListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener() {
356 							public void menuWillBeShown(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object data) {
357 								menu.removeAllChildItems();
358 
359 								String[]	tag_ids = { "tag.type.man.vhdn", "tag.type.man.featcon" };
360 
361 								for ( String id: tag_ids ){
362 
363 									final String c_id = id + ".enabled";
364 
365 									org.gudy.azureus2.plugins.ui.menus.MenuItem menuItem = menuManager.addMenuItem( menu, id);
366 
367 									menuItem.setStyle(org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_CHECK );
368 
369 									menuItem.addListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemListener() {
370 										public void selected(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object target) {
371 											COConfigurationManager.setParameter( c_id, menu.isSelected());
372 										}
373 									});
374 									menuItem.addFillListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener() {
375 										public void menuWillBeShown(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object data) {
376 											menu.setData( COConfigurationManager.getBooleanParameter( c_id, true ));
377 										}
378 									});
379 								}
380 							}});
381 
382 
383 							// autos
384 
385 
386 						List<TagType> tag_types = TagManagerFactory.getTagManager().getTagTypes();
387 
388 						for ( final TagType tag_type: tag_types ){
389 
390 							if ( tag_type.getTagType() == TagType.TT_DOWNLOAD_CATEGORY ){
391 
392 								continue;
393 							}
394 
395 							if ( !tag_type.isTagTypeAuto()){
396 
397 								continue;
398 							}
399 
400 							if ( tag_type.getTags().size() == 0 ){
401 
402 								continue;
403 							}
404 
405 							menuItem = menuManager.addMenuItem( menu, tag_type.getTagTypeName( false ));
406 
407 							menuItem.setStyle(org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_MENU);
408 
409 							menuItem.addFillListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener() {
410 								public void menuWillBeShown(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object data) {
411 									menu.removeAllChildItems();
412 
413 									final List<Tag> tags = tag_type.getTags();
414 
415 									org.gudy.azureus2.plugins.ui.menus.MenuItem showAllItem = menuManager.addMenuItem( menu, "label.show.all" );
416 									showAllItem.setStyle(org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_PUSH );
417 
418 									showAllItem.addListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemListener() {
419 										public void selected(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object target) {
420 											for ( Tag t: tags ){
421 												t.setVisible( true );
422 											}
423 										}
424 									});
425 
426 									org.gudy.azureus2.plugins.ui.menus.MenuItem hideAllItem = menuManager.addMenuItem( menu, "popup.error.hideall" );
427 									hideAllItem.setStyle(org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_PUSH );
428 
429 									hideAllItem.addListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemListener() {
430 										public void selected(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object target) {
431 											for ( Tag t: tags ){
432 												t.setVisible( false );
433 											}
434 										}
435 									});
436 
437 									boolean	all_visible 	= true;
438 									boolean all_invisible 	= true;
439 
440 									for ( Tag t: tags ){
441 										if ( t.isVisible()){
442 											all_invisible = false;
443 										}else{
444 											all_visible = false;
445 										}
446 									}
447 
448 									showAllItem.setEnabled( !all_visible );
449 									hideAllItem.setEnabled( !all_invisible );
450 
451 									org.gudy.azureus2.plugins.ui.menus.MenuItem sepItem = menuManager.addMenuItem( menu, "sep2" );
452 
453 									sepItem.setStyle(org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_SEPARATOR );
454 
455 									for ( final Tag t: tags ){
456 
457 										org.gudy.azureus2.plugins.ui.menus.MenuItem  menuItem = menuManager.addMenuItem( menu, t.getTagName( false ));
458 
459 										menuItem.setStyle(org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_CHECK );
460 
461 										menuItem.addListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemListener() {
462 											public void selected(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object target) {
463 												t.setVisible( menu.isSelected());
464 											}
465 										});
466 										menuItem.addFillListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemFillListener() {
467 											public void menuWillBeShown(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object data) {
468 												menu.setData( t.isVisible());
469 											}
470 										});
471 									}
472 								}
473 							});
474 						}
475 					}
476 				});
477 
478 				sepItem = menuManager.addMenuItem( menu, "sep3" );
479 
480 				sepItem.setStyle(org.gudy.azureus2.plugins.ui.menus.MenuItem.STYLE_SEPARATOR );
481 
482 
483 				menuItem = menuManager.addMenuItem( menu, "tag.show.stats");
484 
485 				menuItem.addListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemListener() {
486 					public void selected(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object target) {
487 						UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
488 						uiFunctions.getMDI().showEntryByID(StatsView.VIEW_ID, "TagStatsView");
489 
490 					}
491 				});
492 
493 				menuItem = menuManager.addMenuItem( menu, "tag.show.overview");
494 
495 				menuItem.addListener(new org.gudy.azureus2.plugins.ui.menus.MenuItemListener() {
496 					public void selected(org.gudy.azureus2.plugins.ui.menus.MenuItem menu, Object target) {
497 						UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
498 						uiFunctions.getMDI().showEntryByID(MultipleDocumentInterface.SIDEBAR_SECTION_TAGS);
499 					}
500 				});
501 			}
502 		});
503 
504 		AzureusCoreFactory.addCoreRunningListener(
505 			new AzureusCoreRunningListener()
506 			{
507 				public void
508 				azureusCoreRunning(
509 					AzureusCore core)
510 				{
511 					checkTagSharing( true );
512 				}
513 			});
514 
515 	}
516 
517 	public static void
checkTagSharing( boolean start_of_day )518 	checkTagSharing(
519 		boolean		start_of_day )
520 	{
521 		UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
522 
523 		if ( uiFunctions != null ){
524 
525 			TagManager tm = TagManagerFactory.getTagManager();
526 
527 			if ( start_of_day ){
528 
529 				if ( COConfigurationManager.getBooleanParameter( "tag.sharing.default.checked", false )){
530 
531 					return;
532 				}
533 
534 				COConfigurationManager.setParameter( "tag.sharing.default.checked", true );
535 
536 				List<TagType> tag_types = tm.getTagTypes();
537 
538 				boolean	prompt_required = false;
539 
540 				for ( TagType tag_type: tag_types ){
541 
542 					List<Tag> tags = tag_type.getTags();
543 
544 					for ( Tag tag: tags ){
545 
546 						if ( tag.isPublic()){
547 
548 							prompt_required = true;
549 						}
550 					}
551 				}
552 
553 				if ( !prompt_required ){
554 
555 					return;
556 				}
557 			}
558 
559 			String title = MessageText.getString("tag.sharing.enable.title");
560 
561 			String text = MessageText.getString("tag.sharing.enable.text" );
562 
563 			UIFunctionsUserPrompter prompter = uiFunctions.getUserPrompter(title, text, new String[] {
564 				MessageText.getString("Button.yes"),
565 				MessageText.getString("Button.no")
566 			}, 0);
567 
568 			prompter.setRemember( "tag.share.default", true,
569 					MessageText.getString("MessageBoxWindow.nomoreprompting"));
570 
571 			prompter.setAutoCloseInMS(0);
572 
573 			prompter.open(null);
574 
575 			boolean	share = prompter.waitUntilClosed() == 0;
576 
577 			tm.setTagPublicDefault( share );
578 		}
579 	}
580 
581 	public static void
createManualTag( UIFunctions.TagReturner tagReturner)582 	createManualTag(
583 		UIFunctions.TagReturner tagReturner)
584 	{
585 		UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
586 		if (uiFunctions != null) {
587 			uiFunctions.showCreateTagDialog(tagReturner);
588 		}
589 	}
590 
591 	public static void
createSideBarMenuItems( final Menu menu, final Tag tag )592 	createSideBarMenuItems(
593 		final Menu menu, final Tag tag )
594 	{
595 	    int userMode = COConfigurationManager.getIntParameter("User Mode");
596 
597 		final TagType	tag_type = tag.getTagType();
598 
599 		boolean	needs_separator_next = false;
600 
601 		int countBefore = menu.getItemCount();
602 
603 		if ( tag_type.hasTagTypeFeature( TagFeature.TF_RATE_LIMIT )) {
604 			createTF_RateLimitMenuItems(menu, tag, tag_type, userMode);
605 		}
606 
607 		if ( tag_type.hasTagTypeFeature( TagFeature.TF_RUN_STATE )) {
608 			createTF_RunState(menu, tag);
609 		}
610 
611 		if ( tag_type.hasTagTypeFeature( TagFeature.TF_FILE_LOCATION )) {
612 			createTF_FileLocationMenuItems(menu, tag);
613 		}
614 
615 		if ( tag_type.hasTagTypeFeature( TagFeature.TF_EXEC_ON_ASSIGN )){
616 
617 			final TagFeatureExecOnAssign	tf_eoa = (TagFeatureExecOnAssign)tag;
618 
619 			int	supported_actions = tf_eoa.getSupportedActions();
620 
621 			if ( supported_actions != TagFeatureExecOnAssign.ACTION_NONE ){
622 
623 				final Menu eoa_menu = new Menu( menu.getShell(), SWT.DROP_DOWN);
624 
625 				MenuItem eoa_item = new MenuItem( menu, SWT.CASCADE);
626 
627 				Messages.setLanguageText( eoa_item, "label.exec.on.assign" );
628 
629 				eoa_item.setMenu( eoa_menu );
630 
631 				int[]	action_ids =
632 					{ 	TagFeatureExecOnAssign.ACTION_DESTROY,
633 						TagFeatureExecOnAssign.ACTION_START,
634 						TagFeatureExecOnAssign.ACTION_FORCE_START,
635 						TagFeatureExecOnAssign.ACTION_NOT_FORCE_START,
636 						TagFeatureExecOnAssign.ACTION_STOP ,
637 						TagFeatureExecOnAssign.ACTION_SCRIPT };
638 
639 				String[] action_keys =
640 					{ 	"v3.MainWindow.button.delete",
641 						"v3.MainWindow.button.start",
642 						"v3.MainWindow.button.forcestart",
643 						"v3.MainWindow.button.notforcestart",
644 						"v3.MainWindow.button.stop",
645 						"label.script" };
646 
647 				for ( int i=0;i<action_ids.length;i++ ){
648 
649 					final int action_id = action_ids[i];
650 
651 					if ( tf_eoa.supportsAction( action_id )){
652 
653 						if ( action_id == TagFeatureExecOnAssign.ACTION_SCRIPT ){
654 
655 							final MenuItem action_item = new MenuItem( eoa_menu, SWT.PUSH);
656 
657 							String script = tf_eoa.getActionScript();
658 
659 							if ( script.length() > 23 ){
660 								script = script.substring( 0, 20) + "...";
661 							}
662 
663 							String msg = MessageText.getString( action_keys[i] );
664 
665 							if ( script.length() > 0 ){
666 
667 								msg += ": " + script;
668 							}
669 
670 							msg += "...";
671 
672 							action_item.setText( msg );
673 
674 							action_item.addListener( SWT.Selection, new Listener(){
675 								public void
676 								handleEvent(Event event)
677 								{
678 									String msg = MessageText.getString( "UpdateScript.message" );
679 
680 									SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow( "UpdateScript.title", "!" + msg + "!" );
681 
682 									entryWindow.setPreenteredText( tf_eoa.getActionScript(), false );
683 									entryWindow.selectPreenteredText( true );
684 
685 									entryWindow.prompt();
686 
687 									if ( entryWindow.hasSubmittedInput()){
688 
689 										String text = entryWindow.getSubmittedInput().trim();
690 
691 										tf_eoa.setActionScript( text );
692 									}
693 
694 								}});
695 
696 						}else{
697 
698 							final MenuItem action_item = new MenuItem( eoa_menu, SWT.CHECK);
699 
700 							Messages.setLanguageText( action_item, action_keys[i] );
701 
702 							action_item.setSelection( tf_eoa.isActionEnabled( action_id ));
703 
704 							action_item.addListener( SWT.Selection, new Listener(){
705 									public void
706 									handleEvent(Event event)
707 									{
708 										tf_eoa.setActionEnabled( action_id, action_item.getSelection());
709 									}
710 								});
711 						}
712 					}
713 				}
714 			}
715 		}
716 
717 		// options
718 
719 		if ( tag instanceof TagDownload ){
720 
721 			needs_separator_next = true;
722 
723 			MenuItem itemOptions = new MenuItem(menu, SWT.PUSH);
724 
725 			final Set<DownloadManager> dms = ((TagDownload)tag).getTaggedDownloads();
726 
727 			Messages.setLanguageText(itemOptions, "cat.options");
728 			itemOptions.addListener(SWT.Selection, new Listener() {
729 				public void handleEvent(Event event) {
730 					UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
731 					if (uiFunctions != null) {
732 						uiFunctions.getMDI().showEntryByID(
733 								MultipleDocumentInterface.SIDEBAR_SECTION_TORRENT_OPTIONS,
734 								dms.toArray(new DownloadManager[dms.size()]));
735 					}
736 				}
737 			});
738 
739 			if (dms.size() == 0) {
740 
741 				itemOptions.setEnabled(false);
742 			}
743 		}
744 
745 		if ( userMode > 0 ){
746 
747 			if ( tag_type.hasTagTypeFeature( TagFeature.TF_PROPERTIES )){
748 
749 				createTFProperitesMenuItems(menu, tag);
750 			}
751 		}
752 
753 		if (menu.getItemCount() > countBefore) {
754 			needs_separator_next = true;
755 		}
756 
757 		if ( needs_separator_next ){
758 
759 			new MenuItem( menu, SWT.SEPARATOR);
760 
761 			needs_separator_next = false;
762 		}
763 
764 
765 		/* Seldom Used: Can be set in Tags Overview
766 		// sharing
767 		if ( tag.canBePublic()){
768 
769 			needs_separator_next = true;
770 
771 			final MenuItem itemPublic = new MenuItem(menu, SWT.CHECK );
772 
773 			itemPublic.setSelection( tag.isPublic());
774 
775 			Messages.setLanguageText(itemPublic, "tag.share");
776 
777 			itemPublic.addListener(SWT.Selection, new Listener() {
778 				public void handleEvent(Event event) {
779 
780 					tag.setPublic( itemPublic.getSelection());
781 				}});
782 		}
783 		*/
784 
785 		if ( tag_type.getTagType() == TagType.TT_DOWNLOAD_MANUAL ){
786 
787 			needs_separator_next = true;
788 
789 			MenuItem search = new MenuItem(menu, SWT.PUSH);
790 			Messages.setLanguageText(search, "tag.search");
791 			search.addListener(SWT.Selection, new Listener() {
792 				public void handleEvent(Event event){
793 					UIFunctionsManager.getUIFunctions().doSearch( "tag:" + tag.getTagName( true ));
794 				}});
795 		}
796 
797 			// share with friends
798 		addShareWithFriendsMenuItems(menu, tag, tag_type);
799 
800 
801 			// rss feed
802 
803 		if ( tag_type.hasTagTypeFeature( TagFeature.TF_RSS_FEED )) {
804 
805 			final TagFeatureRSSFeed tfrss = (TagFeatureRSSFeed)tag;
806 
807 			// rss feed
808 
809 			final MenuItem rssOption = new MenuItem(menu, SWT.CHECK );
810 
811 			rssOption.setSelection( tfrss.isTagRSSFeedEnabled());
812 
813 			Messages.setLanguageText(rssOption, "cat.rss.gen");
814 			rssOption.addListener(SWT.Selection, new Listener() {
815 				public void handleEvent(Event event) {
816 					boolean set = rssOption.getSelection();
817 					tfrss.setTagRSSFeedEnabled( set );
818 				}
819 			});
820 		}
821 
822 		if ( tag_type.hasTagTypeFeature( TagFeature.TF_XCODE )) {
823 			createXCodeMenuItems(menu, tag);
824 		}
825 
826 		needs_separator_next = true;
827 
828 		if ( tag_type.getTagType() == TagType.TT_DOWNLOAD_MANUAL ){
829 
830 			MenuBuildUtils.addChatMenu( menu, "label.chat", getChatKey( tag ));
831 		}
832 
833 		MenuItem itemShowStats = new MenuItem(menu, SWT.PUSH);
834 
835 		Messages.setLanguageText(itemShowStats, "tag.show.stats");
836 		itemShowStats.addListener(SWT.Selection, new Listener() {
837 			public void handleEvent( Event event ){
838 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
839 				uiFunctions.getMDI().loadEntryByID(StatsView.VIEW_ID, true, false, "TagStatsView");
840 			}
841 		});
842 
843 		if ( tag.getTaggableTypes() == Taggable.TT_DOWNLOAD ){
844 
845 			MenuItem itemShowFiles = new MenuItem(menu, SWT.PUSH);
846 
847 			Messages.setLanguageText(itemShowFiles, "menu.show.files");
848 			itemShowFiles.addListener(SWT.Selection, new Listener() {
849 				public void handleEvent( Event event ){
850 					showFilesView( (TagDownload)tag );
851 				}
852 			});
853 		}
854 
855 		if ( needs_separator_next ){
856 
857 			new MenuItem( menu, SWT.SEPARATOR);
858 
859 			needs_separator_next = false;
860 		}
861 
862 		boolean	auto = tag_type.isTagTypeAuto();
863 
864 		boolean	closable = auto;
865 
866 		if ( tag.getTaggableTypes() == Taggable.TT_DOWNLOAD ){
867 
868 			closable = true;	// extended closable tags to include manual ones due to user request
869 		}
870 
871 		Menu[] menuShowHide = { null };
872 
873 		if ( closable ){
874 			createCloseableMenuItems(menu, tag, tag_type, menuShowHide, needs_separator_next);
875 		}
876 
877 		if ( !auto ){
878 			createNonAutoMenuItems(menu, tag, tag_type, menuShowHide);
879 		}
880 
881 		MenuItem menuSettings = new MenuItem(menu, SWT.PUSH);
882 		Messages.setLanguageText(menuSettings, "TagSettingsView.title");
883 		menuSettings.addListener(SWT.Selection, new Listener() {
884 			public void handleEvent(Event event) {
885 				UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
886 				uiFunctions.getMDI().showEntryByID(MultipleDocumentInterface.SIDEBAR_SECTION_TAGS, tag);
887 			}
888 		});
889 
890 		org.gudy.azureus2.plugins.ui.menus.MenuItem[] items = MenuItemManager.getInstance().getAllAsArray(
891 				MenuManager.MENU_TAG_CONTEXT);
892 
893 		if (items.length > 0) {
894 			MenuFactory.addSeparatorMenuItem(menu);
895 
896 			// TODO: Don't send Tag.. send a yet-to-be-created plugin interface version of Tag
897 			MenuBuildUtils.addPluginMenuItems(items, menu, true, true,
898 					new MenuBuildUtils.MenuItemPluginMenuControllerImpl(new Tag[] { tag }));
899 		}
900 	}
901 
createTF_RunState(Menu menu, Tag tag)902 	private static void createTF_RunState(Menu menu, Tag tag) {
903 
904 		final TagFeatureRunState	tf_run_state = (TagFeatureRunState)tag;
905 
906 		int caps = tf_run_state.getRunStateCapabilities();
907 
908 		int[] op_set = {
909 				TagFeatureRunState.RSC_START, TagFeatureRunState.RSC_STOP,
910 				TagFeatureRunState.RSC_PAUSE, TagFeatureRunState.RSC_RESUME };
911 
912 		boolean[] can_ops_set = tf_run_state.getPerformableOperations( op_set );
913 
914 		if ((caps & TagFeatureRunState.RSC_START ) != 0 ){
915 
916 			final MenuItem itemOp = new MenuItem(menu, SWT.PUSH);
917 			Messages.setLanguageText(itemOp, "MyTorrentsView.menu.queue");
918 			Utils.setMenuItemImage(itemOp, "start");
919 			itemOp.addListener(SWT.Selection, new Listener() {
920 				public void handleEvent(Event event) {
921 					tf_run_state.performOperation( TagFeatureRunState.RSC_START );
922 				}
923 			});
924 			itemOp.setEnabled(can_ops_set[0]);
925 		}
926 
927 		if ((caps & TagFeatureRunState.RSC_STOP ) != 0 ){
928 
929 			final MenuItem itemOp = new MenuItem(menu, SWT.PUSH);
930 			Messages.setLanguageText(itemOp, "MyTorrentsView.menu.stop");
931 			Utils.setMenuItemImage(itemOp, "stop");
932 			itemOp.addListener(SWT.Selection, new Listener() {
933 				public void handleEvent(Event event) {
934 					tf_run_state.performOperation( TagFeatureRunState.RSC_STOP );
935 				}
936 			});
937 			itemOp.setEnabled(can_ops_set[1]);
938 		}
939 
940 		if ((caps & TagFeatureRunState.RSC_PAUSE ) != 0 ){
941 
942 			final MenuItem itemOp = new MenuItem(menu, SWT.PUSH);
943 			Messages.setLanguageText(itemOp, "v3.MainWindow.button.pause");
944 			Utils.setMenuItemImage(itemOp, "pause");
945 			itemOp.addListener(SWT.Selection, new Listener() {
946 				public void handleEvent(Event event) {
947 					tf_run_state.performOperation( TagFeatureRunState.RSC_PAUSE );
948 				}
949 			});
950 			itemOp.setEnabled(can_ops_set[2]);
951 		}
952 
953 		if ((caps & TagFeatureRunState.RSC_RESUME ) != 0 ){
954 
955 			final MenuItem itemOp = new MenuItem(menu, SWT.PUSH);
956 			Messages.setLanguageText(itemOp, "v3.MainWindow.button.resume");
957 			Utils.setMenuItemImage(itemOp, "start");
958 			itemOp.addListener(SWT.Selection, new Listener() {
959 				public void handleEvent(Event event) {
960 					tf_run_state.performOperation( TagFeatureRunState.RSC_RESUME );
961 				}
962 			});
963 			itemOp.setEnabled(can_ops_set[3]);
964 		}
965 	}
966 
967 	private static void
createTF_RateLimitMenuItems( Menu menu, Tag tag, TagType tag_type, int userMode)968 		createTF_RateLimitMenuItems(
969 				Menu menu,
970 				Tag tag,
971 				TagType tag_type,
972 				int userMode)
973 	{
974 
975 		final TagFeatureRateLimit	tf_rate_limit = (TagFeatureRateLimit)tag;
976 
977 		boolean	has_up 		= tf_rate_limit.supportsTagUploadLimit();
978 		boolean	has_down 	= tf_rate_limit.supportsTagDownloadLimit();
979 
980 		if ( has_up || has_down ){
981 
982 			long kInB = DisplayFormatters.getKinB();
983 
984 			long maxDownload = COConfigurationManager.getIntParameter(
985 					"Max Download Speed KBs", 0) * kInB;
986 			long maxUpload = COConfigurationManager.getIntParameter(
987 					"Max Upload Speed KBs", 0) * kInB;
988 
989 			int down_speed 	= tf_rate_limit.getTagDownloadLimit();
990 			int up_speed 	= tf_rate_limit.getTagUploadLimit();
991 
992 			Map<String,Object> menu_properties = new HashMap<String,Object>();
993 
994 			if ( tag_type.getTagType() == TagType.TT_PEER_IPSET || tag_type.getTagType() == TagType.TT_DOWNLOAD_MANUAL ){
995 
996 				if ( has_up ){
997 					menu_properties.put( ViewUtils.SM_PROP_PERMIT_UPLOAD_DISABLE, true );
998 				}
999 				if ( has_down ){
1000 					menu_properties.put( ViewUtils.SM_PROP_PERMIT_DOWNLOAD_DISABLE, true );
1001 				}
1002 			}
1003 
1004 			ViewUtils.addSpeedMenu(
1005 					menu.getShell(), menu, has_up, has_down, true, true,
1006 					down_speed == -1, down_speed == 0, down_speed, down_speed, maxDownload,
1007 					up_speed == -1,	up_speed == 0, up_speed, up_speed, maxUpload,
1008 					1,	menu_properties,
1009 					new SpeedAdapter() {
1010 						public void setDownSpeed(int val) {
1011 							tf_rate_limit.setTagDownloadLimit(val);
1012 						}
1013 
1014 						public void setUpSpeed(int val) {
1015 							tf_rate_limit.setTagUploadLimit(val);
1016 						}
1017 					});
1018 		}
1019 
1020 		if ( userMode > 0 ){
1021 
1022 			if ( tf_rate_limit.getTagUploadPriority() >= 0 ){
1023 
1024 
1025 				final MenuItem upPriority = new MenuItem(menu, SWT.CHECK );
1026 
1027 				upPriority.setSelection( tf_rate_limit.getTagUploadPriority() > 0 );
1028 
1029 				Messages.setLanguageText(upPriority, "cat.upload.priority");
1030 				upPriority.addListener(SWT.Selection, new Listener() {
1031 					public void handleEvent(Event event) {
1032 						boolean set = upPriority.getSelection();
1033 						tf_rate_limit.setTagUploadPriority( set?1:0 );
1034 					}
1035 				});
1036 			}
1037 
1038 			/* Usually set once: Can be set in Tags Overview*/
1039 			if ( tf_rate_limit.getTagMinShareRatio() >= 0 ){
1040 
1041 				MenuItem itemSR = new MenuItem(menu, SWT.PUSH);
1042 
1043 				final String existing = String.valueOf( tf_rate_limit.getTagMinShareRatio()/1000.0f);
1044 
1045 				Messages.setLanguageText(itemSR, "menu.min.share.ratio", new String[]{existing} );
1046 
1047 				itemSR.addListener(SWT.Selection, new Listener() {
1048 					public void handleEvent(Event event) {
1049 						SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
1050 								"min.sr.window.title", "min.sr.window.message");
1051 
1052 						entryWindow.setPreenteredText( existing, false );
1053 						entryWindow.selectPreenteredText( true );
1054 
1055 						entryWindow.prompt();
1056 
1057 						if ( entryWindow.hasSubmittedInput()){
1058 
1059 							try{
1060 								String text = entryWindow.getSubmittedInput().trim();
1061 
1062 								int	sr = 0;
1063 
1064 								if ( text.length() > 0 ){
1065 
1066 									try{
1067 										float f = Float.parseFloat( text );
1068 
1069 										sr = (int)(f * 1000 );
1070 
1071 										if ( sr < 0 ){
1072 
1073 											sr = 0;
1074 
1075 										}else if ( sr == 0 && f > 0 ){
1076 
1077 											sr = 1;
1078 										}
1079 
1080 									}catch( Throwable e ){
1081 
1082 										Debug.out( e );
1083 									}
1084 
1085 									tf_rate_limit.setTagMinShareRatio( sr );
1086 
1087 								}
1088 							}catch( Throwable e ){
1089 
1090 								Debug.out( e );
1091 							}
1092 						}
1093 					}
1094 				});
1095 			}
1096 
1097 			if ( tf_rate_limit.getTagMaxShareRatio() >= 0 ){
1098 
1099 				MenuItem itemSR = new MenuItem(menu, SWT.PUSH);
1100 
1101 				final String existing = String.valueOf( tf_rate_limit.getTagMaxShareRatio()/1000.0f);
1102 
1103 				Messages.setLanguageText(itemSR, "menu.max.share.ratio", new String[]{existing} );
1104 
1105 				itemSR.addListener(SWT.Selection, new Listener() {
1106 					public void handleEvent(Event event) {
1107 						SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
1108 								"max.sr.window.title", "max.sr.window.message");
1109 
1110 						entryWindow.setPreenteredText( existing, false );
1111 						entryWindow.selectPreenteredText( true );
1112 
1113 						entryWindow.prompt();
1114 
1115 						if ( entryWindow.hasSubmittedInput()){
1116 
1117 							try{
1118 								String text = entryWindow.getSubmittedInput().trim();
1119 
1120 								int	sr = 0;
1121 
1122 								if ( text.length() > 0 ){
1123 
1124 									try{
1125 										float f = Float.parseFloat( text );
1126 
1127 										sr = (int)(f * 1000 );
1128 
1129 										if ( sr < 0 ){
1130 
1131 											sr = 0;
1132 
1133 										}else if ( sr == 0 && f > 0 ){
1134 
1135 											sr = 1;
1136 										}
1137 
1138 									}catch( Throwable e ){
1139 
1140 										Debug.out( e );
1141 									}
1142 
1143 									tf_rate_limit.setTagMaxShareRatio( sr );
1144 
1145 								}
1146 							}catch( Throwable e ){
1147 
1148 								Debug.out( e );
1149 							}
1150 						}
1151 					}
1152 				});
1153 			}
1154 			/**/
1155 		}
1156 	}
1157 
createTF_FileLocationMenuItems(Menu menu, final Tag tag)1158 	private static void createTF_FileLocationMenuItems(Menu menu, final Tag tag) {
1159 
1160 		final TagFeatureFileLocation fl = (TagFeatureFileLocation)tag;
1161 
1162 		if ( fl.supportsTagInitialSaveFolder() || fl.supportsTagMoveOnComplete() || fl.supportsTagCopyOnComplete()){
1163 
1164 			Menu files_menu = new Menu( menu.getShell(), SWT.DROP_DOWN);
1165 
1166 			MenuItem files_item = new MenuItem( menu, SWT.CASCADE);
1167 
1168 			Messages.setLanguageText( files_item, "ConfigView.section.files" );
1169 
1170 			files_item.setMenu( files_menu );
1171 
1172 			if ( fl.supportsTagInitialSaveFolder()){
1173 
1174 				final Menu moc_menu = new Menu( files_menu.getShell(), SWT.DROP_DOWN);
1175 
1176 				MenuItem isl_item = new MenuItem( files_menu, SWT.CASCADE);
1177 
1178 				Messages.setLanguageText( isl_item, "label.init.save.loc" );
1179 
1180 				isl_item.setMenu( moc_menu );
1181 
1182 				MenuItem clear_item = new MenuItem( moc_menu, SWT.CASCADE);
1183 
1184 				Messages.setLanguageText( clear_item, "Button.clear" );
1185 
1186 				clear_item.addListener(SWT.Selection, new Listener() {
1187 					public void handleEvent(Event event) {
1188 						fl.setTagInitialSaveFolder( null );
1189 					}});
1190 
1191 					// apply
1192 
1193 				final File existing = fl.getTagInitialSaveFolder();
1194 
1195 				MenuItem apply_item = new MenuItem( moc_menu, SWT.CASCADE);
1196 
1197 				Messages.setLanguageText( apply_item, "apply.to.current" );
1198 
1199 				apply_item.addListener(SWT.Selection, new Listener() {
1200 					public void handleEvent(Event event) {
1201 						applyLocationToCurrent( tag, existing, false );
1202 					}});
1203 
1204 				new MenuItem( moc_menu, SWT.SEPARATOR);
1205 
1206 				if ( existing != null ){
1207 
1208 					MenuItem current_item = new MenuItem( moc_menu, SWT.RADIO );
1209 					current_item.setSelection( true );
1210 
1211 					current_item.setText( existing.getAbsolutePath());
1212 
1213 					new MenuItem( moc_menu, SWT.SEPARATOR);
1214 
1215 				}else{
1216 
1217 					apply_item.setEnabled( false );
1218 					clear_item.setEnabled( false );
1219 				}
1220 
1221 				MenuItem set_item = new MenuItem( moc_menu, SWT.CASCADE);
1222 
1223 				Messages.setLanguageText( set_item, "label.set" );
1224 
1225 				set_item.addListener(SWT.Selection, new Listener() {
1226 					public void handleEvent(Event event){
1227 						DirectoryDialog dd = new DirectoryDialog(moc_menu.getShell());
1228 
1229 						dd.setFilterPath( TorrentOpener.getFilterPathData());
1230 
1231 						dd.setText(MessageText.getString("MyTorrentsView.menu.movedata.dialog"));
1232 
1233 						String path = dd.open();
1234 
1235 						if ( path != null ){
1236 
1237 							TorrentOpener.setFilterPathData( path );
1238 
1239 							fl.setTagInitialSaveFolder( new File( path ));
1240 						}
1241 					}});
1242 			}
1243 
1244 			if ( fl.supportsTagMoveOnComplete()){
1245 
1246 				final Menu moc_menu = new Menu( files_menu.getShell(), SWT.DROP_DOWN);
1247 
1248 				MenuItem moc_item = new MenuItem( files_menu, SWT.CASCADE);
1249 
1250 				Messages.setLanguageText( moc_item, "label.move.on.comp" );
1251 
1252 				moc_item.setMenu( moc_menu );
1253 
1254 				MenuItem clear_item = new MenuItem( moc_menu, SWT.CASCADE);
1255 
1256 				Messages.setLanguageText( clear_item, "Button.clear" );
1257 
1258 				clear_item.addListener(SWT.Selection, new Listener() {
1259 					public void handleEvent(Event event) {
1260 						fl.setTagMoveOnCompleteFolder( null );
1261 					}});
1262 
1263 
1264 					// apply
1265 
1266 				final File existing = fl.getTagMoveOnCompleteFolder();
1267 
1268 				MenuItem apply_item = new MenuItem( moc_menu, SWT.CASCADE);
1269 
1270 				Messages.setLanguageText( apply_item, "apply.to.current" );
1271 
1272 				apply_item.addListener(SWT.Selection, new Listener() {
1273 					public void handleEvent(Event event) {
1274 						applyLocationToCurrent( tag, existing, true );
1275 					}});
1276 
1277 				new MenuItem( moc_menu, SWT.SEPARATOR);
1278 
1279 				if ( existing != null ){
1280 
1281 					MenuItem current_item = new MenuItem( moc_menu, SWT.RADIO );
1282 					current_item.setSelection( true );
1283 
1284 					current_item.setText( existing.getAbsolutePath());
1285 
1286 					new MenuItem( moc_menu, SWT.SEPARATOR);
1287 
1288 				}else{
1289 
1290 					apply_item.setEnabled( false );
1291 					clear_item.setEnabled( false );
1292 				}
1293 
1294 				MenuItem set_item = new MenuItem( moc_menu, SWT.CASCADE);
1295 
1296 				Messages.setLanguageText( set_item, "label.set" );
1297 
1298 				set_item.addListener(SWT.Selection, new Listener() {
1299 					public void handleEvent(Event event){
1300 						DirectoryDialog dd = new DirectoryDialog(moc_menu.getShell());
1301 
1302 						dd.setFilterPath( TorrentOpener.getFilterPathData());
1303 
1304 						dd.setText(MessageText.getString("MyTorrentsView.menu.movedata.dialog"));
1305 
1306 						String path = dd.open();
1307 
1308 						if ( path != null ){
1309 
1310 							TorrentOpener.setFilterPathData( path );
1311 
1312 							fl.setTagMoveOnCompleteFolder( new File( path ));
1313 						}
1314 					}});
1315 			}
1316 
1317 			if ( fl.supportsTagCopyOnComplete()){
1318 
1319 				final Menu moc_menu = new Menu( files_menu.getShell(), SWT.DROP_DOWN);
1320 
1321 				MenuItem moc_item = new MenuItem( files_menu, SWT.CASCADE);
1322 
1323 				Messages.setLanguageText( moc_item, "label.copy.on.comp" );
1324 
1325 				moc_item.setMenu( moc_menu );
1326 
1327 				MenuItem clear_item = new MenuItem( moc_menu, SWT.CASCADE);
1328 
1329 				Messages.setLanguageText( clear_item, "Button.clear" );
1330 
1331 				clear_item.addListener(SWT.Selection, new Listener() {
1332 					public void handleEvent(Event event) {
1333 						fl.setTagCopyOnCompleteFolder( null );
1334 					}});
1335 
1336 				new MenuItem( moc_menu, SWT.SEPARATOR);
1337 
1338 				File existing = fl.getTagCopyOnCompleteFolder();
1339 
1340 				if ( existing != null ){
1341 
1342 					MenuItem current_item = new MenuItem( moc_menu, SWT.RADIO );
1343 					current_item.setSelection( true );
1344 
1345 					current_item.setText( existing.getAbsolutePath());
1346 
1347 					new MenuItem( moc_menu, SWT.SEPARATOR);
1348 
1349 				}else{
1350 
1351 					clear_item.setEnabled( false );
1352 				}
1353 
1354 				MenuItem set_item = new MenuItem( moc_menu, SWT.CASCADE);
1355 
1356 				Messages.setLanguageText( set_item, "label.set" );
1357 
1358 				set_item.addListener(SWT.Selection, new Listener() {
1359 					public void handleEvent(Event event){
1360 						DirectoryDialog dd = new DirectoryDialog(moc_menu.getShell());
1361 
1362 						dd.setFilterPath( TorrentOpener.getFilterPathData());
1363 
1364 						dd.setText(MessageText.getString("MyTorrentsView.menu.movedata.dialog"));
1365 
1366 						String path = dd.open();
1367 
1368 						if ( path != null ){
1369 
1370 							TorrentOpener.setFilterPathData( path );
1371 
1372 							fl.setTagCopyOnCompleteFolder( new File( path ));
1373 						}
1374 					}});
1375 			}
1376 		}
1377 	}
1378 
createTFProperitesMenuItems(Menu menu, Tag tag)1379 	private static void createTFProperitesMenuItems(Menu menu, Tag tag) {
1380 
1381 		TagFeatureProperties props = (TagFeatureProperties)tag;
1382 
1383 		TagProperty[] tps = props.getSupportedProperties();
1384 
1385 		if ( tps.length > 0 ){
1386 
1387 			final Menu props_menu = new Menu( menu.getShell(), SWT.DROP_DOWN);
1388 
1389 			MenuItem props_item = new MenuItem( menu, SWT.CASCADE);
1390 
1391 			Messages.setLanguageText( props_item, "label.properties" );
1392 
1393 			props_item.setMenu( props_menu );
1394 
1395 			for ( final TagProperty tp: tps ){
1396 
1397 				if ( tp.getType() == TagFeatureProperties.PT_STRING_LIST ){
1398 
1399 					String tp_name = tp.getName( false );
1400 
1401 					if ( tp_name.equals( TagFeatureProperties.PR_CONSTRAINT )){
1402 
1403 						MenuItem const_item = new MenuItem( props_menu, SWT.PUSH);
1404 
1405 						Messages.setLanguageText( const_item, "label.contraints" );
1406 
1407 						const_item.addListener(SWT.Selection, new Listener() {
1408 							public void
1409 							handleEvent(Event event)
1410 							{
1411 								final String[] old_value = tp.getStringList();
1412 
1413 								String def_val;
1414 
1415 								if ( old_value != null && old_value.length > 0 ){
1416 
1417 									def_val = old_value[0];
1418 
1419 								}else{
1420 
1421 									def_val = "";
1422 								}
1423 
1424 								String msg = MessageText.getString( "UpdateConstraint.message" );
1425 
1426 								SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow( "UpdateConstraint.title", "!" + msg + "!" );
1427 
1428 								entryWindow.setPreenteredText( def_val, false );
1429 								entryWindow.selectPreenteredText( true );
1430 
1431 								entryWindow.prompt();
1432 
1433 								if ( entryWindow.hasSubmittedInput()){
1434 
1435 									try{
1436 										String text = entryWindow.getSubmittedInput().trim();
1437 
1438 										if ( text.length() ==  0 ){
1439 
1440 											tp.setStringList( null );
1441 
1442 										}else{
1443 
1444 											String old_options = old_value.length>1?old_value[1]:"";
1445 
1446 											tp.setStringList( new String[]{ text, old_options });
1447 										}
1448 									}catch( Throwable e ){
1449 
1450 										Debug.out( e );
1451 									}
1452 								}
1453 							}});
1454 
1455 					}else if ( tp_name.equals( TagFeatureProperties.PR_TRACKER_TEMPLATES )){
1456 
1457 						final TrackersUtil tut = TrackersUtil.getInstance();
1458 
1459 						List<String> templates = new ArrayList<String>( tut.getMultiTrackers().keySet());
1460 
1461 						String str_merge 	= MessageText.getString("label.merge" );
1462 						String str_replace 	= MessageText.getString("label.replace" );
1463 						String str_remove 	= MessageText.getString("Button.remove" );
1464 
1465 						String[] val = tp.getStringList();
1466 
1467 						String def_str;
1468 
1469 						final List<String> selected = new ArrayList<String>();
1470 
1471 						if ( val == null || val.length == 0 ){
1472 
1473 							def_str = "";
1474 
1475 						}else{
1476 
1477 							def_str = "";
1478 
1479 							for ( String v: val ){
1480 
1481 								String[] bits = v.split( ":" );
1482 
1483 								if ( bits.length == 2 ){
1484 
1485 									String tn = bits[1];
1486 
1487 									if ( templates.contains( tn )){
1488 
1489 										String type = bits[0];
1490 
1491 										if ( type.equals( "m" )){
1492 
1493 											tn += ": " + str_merge;
1494 
1495 										}else if ( type.equals( "r" )){
1496 
1497 											tn += ": " + str_replace;
1498 
1499 										}else{
1500 											tn += ": " + str_remove;
1501 										}
1502 
1503 										selected.add( v );
1504 
1505 										def_str += (def_str.length()==0?"":", ") + tn;
1506 									}
1507 								}
1508 							}
1509 						}
1510 
1511 						Collections.sort( templates );
1512 
1513 							// deliberately hanging this off the main menu, not properties...
1514 
1515 						Menu ttemp_menu = new Menu( menu.getShell(), SWT.DROP_DOWN);
1516 
1517 						MenuItem ttemp_item = new MenuItem( menu, SWT.CASCADE);
1518 
1519 						ttemp_item.setText( MessageText.getString( "label.tracker.templates" ) + (def_str.length()==0?"":(" (" + def_str + ")  ")));
1520 
1521 						ttemp_item.setMenu( ttemp_menu );
1522 
1523 						MenuItem new_item = new MenuItem( ttemp_menu, SWT.PUSH);
1524 
1525 						Messages.setLanguageText( new_item, "wizard.multitracker.new" );
1526 
1527 						new_item.addListener(SWT.Selection, new Listener() {
1528 							public void
1529 							handleEvent(Event event)
1530 							{
1531 								List<List<String>> group = new ArrayList<List<String>>();
1532 								List<String> tracker = new ArrayList<String>();
1533 								group.add(tracker);
1534 
1535 								new MultiTrackerEditor(
1536 									props_menu.getShell(),
1537 									null,
1538 									group,
1539 									new TrackerEditorListener() {
1540 
1541 										public void
1542 										trackersChanged(
1543 											String 				oldName,
1544 											String 				newName,
1545 											List<List<String>> 	trackers)
1546 										{
1547 											if ( trackers != null ){
1548 
1549 												tut.addMultiTracker(newName , trackers );
1550 											}
1551 										}
1552 									});
1553 							}});
1554 
1555 						MenuItem reapply_item = new MenuItem( ttemp_menu, SWT.PUSH);
1556 
1557 						Messages.setLanguageText( reapply_item, "label.reapply" );
1558 
1559 						reapply_item.addListener(SWT.Selection, new Listener() {
1560 							public void
1561 							handleEvent(Event event)
1562 							{
1563 								tp.syncListeners();
1564 							}});
1565 
1566 						reapply_item.setEnabled( def_str.length() > 0 );
1567 
1568 						if ( templates.size() > 0 ){
1569 
1570 							new MenuItem( ttemp_menu, SWT.SEPARATOR);
1571 
1572 							for ( final String template_name: templates ){
1573 
1574 								Menu t_menu = new Menu( ttemp_menu.getShell(), SWT.DROP_DOWN);
1575 
1576 								MenuItem t_item = new MenuItem( ttemp_menu, SWT.CASCADE);
1577 
1578 								t_item.setText( template_name );
1579 
1580 								t_item.setMenu( t_menu );
1581 
1582 								boolean	r_selected = false;
1583 
1584 								for ( int i=0;i<3;i++){
1585 
1586 									final MenuItem sel_item = new MenuItem( t_menu, SWT.CHECK);
1587 
1588 									final String key = (i==0?"m":(i==1?"r":"x")) + ":" + template_name;
1589 
1590 									sel_item.setText( i==0?str_merge:(i==1?str_replace:str_remove));
1591 
1592 									boolean is_sel = selected.contains( key );
1593 
1594 									r_selected |= is_sel;
1595 
1596 									sel_item.setSelection( is_sel );
1597 
1598 									sel_item.addListener(SWT.Selection, new Listener() {
1599 										public void
1600 										handleEvent(Event event)
1601 										{
1602 											if ( sel_item.getSelection()){
1603 
1604 												selected.add( key );
1605 
1606 											}else{
1607 
1608 												selected.remove( key );
1609 											}
1610 
1611 											Utils.getOffOfSWTThread(new AERunnable() {
1612 
1613 												@Override
1614 												public void runSupport() {
1615 													tp.setStringList( selected.toArray( new String[ selected.size()]));
1616 												}
1617 											});
1618 
1619 										}});
1620 								}
1621 
1622 								if ( r_selected ){
1623 
1624 									Utils.setMenuItemImage( t_item, "graytick" );
1625 								}
1626 
1627 								new MenuItem( t_menu, SWT.SEPARATOR);
1628 
1629 								MenuItem edit_item = new MenuItem( t_menu, SWT.PUSH);
1630 
1631 								Messages.setLanguageText( edit_item, "wizard.multitracker.edit" );
1632 
1633 								edit_item.addListener(SWT.Selection, new Listener() {
1634 									public void
1635 									handleEvent(Event event)
1636 									{
1637 										new MultiTrackerEditor(
1638 											props_menu.getShell(),
1639 											template_name,
1640 											tut.getMultiTrackers().get( template_name ),
1641 											new TrackerEditorListener() {
1642 
1643 												public void
1644 												trackersChanged(
1645 													String 				oldName,
1646 													String 				newName,
1647 													List<List<String>> 	trackers)
1648 												{
1649 													if  ( oldName != null && !oldName.equals( newName )){
1650 
1651 														tut.removeMultiTracker( oldName );
1652 												    }
1653 
1654 													tut.addMultiTracker(newName , trackers );
1655 												}
1656 											});
1657 									}});
1658 
1659 								MenuItem del_item = new MenuItem( t_menu, SWT.PUSH);
1660 
1661 								Messages.setLanguageText( del_item, "FileItem.delete" );
1662 
1663 								Utils.setMenuItemImage( del_item, "delete" );
1664 
1665 								del_item.addListener(SWT.Selection, new Listener() {
1666 									public void
1667 									handleEvent(Event event)
1668 									{
1669 										MessageBoxShell mb =
1670 												new MessageBoxShell(
1671 													MessageText.getString("message.confirm.delete.title"),
1672 													MessageText.getString("message.confirm.delete.text",
1673 															new String[] { template_name	}),
1674 													new String[] {
1675 														MessageText.getString("Button.yes"),
1676 														MessageText.getString("Button.no")
1677 													},
1678 													1 );
1679 
1680 											mb.open(new UserPrompterResultListener() {
1681 												public void prompterClosed(int result) {
1682 													if (result == 0) {
1683 														tut.removeMultiTracker( template_name );
1684 													}
1685 												}
1686 											});
1687 									}});
1688 							}
1689 						}
1690 					}else{
1691 						String[] val = tp.getStringList();
1692 
1693 						String def_str;
1694 
1695 						if ( val == null || val.length == 0 ){
1696 
1697 							def_str = "";
1698 
1699 						}else{
1700 
1701 							def_str = "";
1702 
1703 							for ( String v: val ){
1704 
1705 								def_str += (def_str.length()==0?"":", ") + v;
1706 							}
1707 						}
1708 
1709 						MenuItem set_item = new MenuItem( props_menu, SWT.PUSH);
1710 
1711 						set_item.setText( tp.getName( true ) + (def_str.length()==0?"":(" (" + def_str + ") ")) + "..." );
1712 
1713 						final String f_def_str = def_str;
1714 
1715 						set_item.addListener(SWT.Selection, new Listener() {
1716 							public void handleEvent(Event event){
1717 
1718 								String msg = MessageText.getString( "UpdateProperty.list.message", new String[]{ tp.getName( true ) } );
1719 
1720 								SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow( "UpdateProperty.title", "!" + msg + "!" );
1721 
1722 								entryWindow.setPreenteredText( f_def_str, false );
1723 								entryWindow.selectPreenteredText( true );
1724 
1725 								entryWindow.prompt();
1726 
1727 								if ( entryWindow.hasSubmittedInput()){
1728 
1729 									try{
1730 										String text = entryWindow.getSubmittedInput().trim();
1731 
1732 										if ( text.length() ==  0 ){
1733 
1734 											tp.setStringList( null );
1735 
1736 										}else{
1737 											text = text.replace( ';', ',');
1738 											text = text.replace( ' ', ',');
1739 											text = text.replaceAll( "[,]+", "," );
1740 
1741 											String[] bits = text.split( "," );
1742 
1743 											List<String> vals = new ArrayList<String>();
1744 
1745 											for ( String bit: bits ){
1746 
1747 												bit = bit.trim();
1748 
1749 												if ( bit.length() > 0 ){
1750 
1751 													vals.add( bit );
1752 												}
1753 											}
1754 
1755 											if ( vals.size() == 0 ){
1756 
1757 												tp.setStringList( null );
1758 											}else{
1759 
1760 												tp.setStringList( vals.toArray( new String[ vals.size()]));
1761 											}
1762 										}
1763 									}catch( Throwable e ){
1764 
1765 										Debug.out( e );
1766 									}
1767 								}
1768 							}});
1769 					}
1770 				}else if ( tp.getType() == TagFeatureProperties.PT_BOOLEAN ){
1771 
1772 					final MenuItem set_item = new MenuItem( props_menu, SWT.CHECK);
1773 
1774 					set_item.setText( tp.getName( true ));
1775 
1776 					Boolean val = tp.getBoolean();
1777 
1778 					set_item.setSelection( val != null && val );
1779 
1780 					set_item.addListener(
1781 						SWT.Selection,
1782 						new Listener()
1783 						{
1784 							public void
1785 							handleEvent(
1786 								Event event)
1787 							{
1788 								tp.setBoolean( set_item.getSelection());
1789 							}
1790 						});
1791 
1792 				}else{
1793 
1794 					Debug.out( "Unknown property" );
1795 				}
1796 			}
1797 		}
1798 	}
1799 
addShareWithFriendsMenuItems(Menu menu, Tag tag, TagType tag_type)1800 	private static void addShareWithFriendsMenuItems(Menu menu, Tag tag,
1801 			TagType tag_type) {
1802 		PluginInterface bpi = PluginInitializer.getDefaultInterface().getPluginManager().getPluginInterfaceByClass(
1803 				BuddyPlugin.class);
1804 
1805 		if ( tag_type.getTagType() == TagType.TT_DOWNLOAD_MANUAL && bpi != null ){
1806 
1807 			TagFeatureProperties props = (TagFeatureProperties)tag;
1808 
1809 			TagProperty tp = props.getProperty( TagFeatureProperties.PR_UNTAGGED );
1810 
1811 			Boolean is_ut = tp==null?null:tp.getBoolean();
1812 
1813 			if ( is_ut == null || !is_ut ){
1814 
1815 				final BuddyPlugin buddy_plugin = (BuddyPlugin) bpi.getPlugin();
1816 
1817 				if (buddy_plugin.isClassicEnabled()) {
1818 
1819 					final Menu share_menu = new Menu(menu.getShell(), SWT.DROP_DOWN);
1820 					final MenuItem share_item = new MenuItem(menu, SWT.CASCADE);
1821 					Messages.setLanguageText(share_item, "azbuddy.ui.menu.cat.share");
1822 					share_item.setText( share_item.getText() + "  " );	// nasty hack to fix nastyness on windows
1823 					share_item.setMenu(share_menu);
1824 
1825 					List<BuddyPluginBuddy> buddies = buddy_plugin.getBuddies();
1826 
1827 					if (buddies.size() == 0) {
1828 
1829 						final MenuItem item = new MenuItem(share_menu, SWT.CHECK);
1830 
1831 						item.setText(MessageText.getString("general.add.friends"));
1832 
1833 						item.setEnabled(false);
1834 
1835 					} else {
1836 						final String tag_name = tag.getTagName( true );
1837 
1838 						final boolean is_public = buddy_plugin.isPublicTagOrCategory( tag_name );
1839 
1840 						final MenuItem itemPubCat = new MenuItem(share_menu, SWT.CHECK);
1841 
1842 						Messages.setLanguageText(itemPubCat, "general.all.friends");
1843 
1844 						itemPubCat.setSelection(is_public);
1845 
1846 						itemPubCat.addListener(SWT.Selection, new Listener() {
1847 							public void handleEvent(Event event) {
1848 								if (is_public) {
1849 
1850 									buddy_plugin.removePublicTagOrCategory( tag_name );
1851 
1852 								} else {
1853 
1854 									buddy_plugin.addPublicTagOrCategory( tag_name );
1855 								}
1856 							}
1857 						});
1858 
1859 						new MenuItem(share_menu, SWT.SEPARATOR);
1860 
1861 						for (final BuddyPluginBuddy buddy : buddies) {
1862 
1863 							if (buddy.getNickName() == null) {
1864 
1865 								continue;
1866 							}
1867 
1868 							final boolean auth = buddy.isLocalRSSTagOrCategoryAuthorised(tag_name);
1869 
1870 							final MenuItem itemShare = new MenuItem(share_menu, SWT.CHECK);
1871 
1872 							itemShare.setText(buddy.getName());
1873 
1874 							itemShare.setSelection(auth || is_public);
1875 
1876 							if (is_public) {
1877 
1878 								itemShare.setEnabled(false);
1879 							}
1880 
1881 							itemShare.addListener(SWT.Selection, new Listener() {
1882 								public void handleEvent(Event event) {
1883 									if (auth) {
1884 
1885 										buddy.removeLocalAuthorisedRSSTagOrCategory(tag_name);
1886 
1887 									} else {
1888 
1889 										buddy.addLocalAuthorisedRSSTagOrCategory(tag_name);
1890 									}
1891 								}
1892 							});
1893 
1894 						}
1895 					}
1896 				}
1897 			}
1898 		}
1899 	}
1900 
createXCodeMenuItems(Menu menu, Tag tag)1901 	private static void createXCodeMenuItems(Menu menu, Tag tag) {
1902 
1903 
1904 		final TagFeatureTranscode tf_xcode = (TagFeatureTranscode)tag;
1905 
1906 		if ( tf_xcode.supportsTagTranscode()){
1907 
1908 			AZ3Functions.provider provider = AZ3Functions.getProvider();
1909 
1910 			if ( provider != null ){
1911 
1912 				AZ3Functions.provider.TranscodeTarget[] tts = provider.getTranscodeTargets();
1913 
1914 				if (tts.length > 0) {
1915 
1916 					final Menu t_menu = new Menu(menu.getShell(), SWT.DROP_DOWN);
1917 
1918 					final MenuItem t_item = new MenuItem(menu, SWT.CASCADE);
1919 
1920 					Messages.setLanguageText( t_item, "cat.autoxcode" );
1921 
1922 					t_item.setMenu(t_menu);
1923 
1924 					String[] existing = tf_xcode.getTagTranscodeTarget();
1925 
1926 					for ( final AZ3Functions.provider.TranscodeTarget tt : tts ){
1927 
1928 						AZ3Functions.provider.TranscodeProfile[] profiles = tt.getProfiles();
1929 
1930 						if ( profiles.length > 0 ){
1931 
1932 							final Menu tt_menu = new Menu(t_menu.getShell(), SWT.DROP_DOWN);
1933 
1934 							final MenuItem tt_item = new MenuItem(t_menu, SWT.CASCADE);
1935 
1936 							tt_item.setText(tt.getName());
1937 
1938 							tt_item.setMenu(tt_menu);
1939 
1940 							for (final AZ3Functions.provider.TranscodeProfile tp : profiles) {
1941 
1942 								final MenuItem p_item = new MenuItem(tt_menu, SWT.CHECK);
1943 
1944 								p_item.setText(tp.getName());
1945 
1946 								boolean	selected = existing != null	&& existing[0].equals(tp.getUID());
1947 
1948 								if ( selected ){
1949 
1950 									Utils.setMenuItemImage(tt_item, "graytick");
1951 								}
1952 
1953 								p_item.setSelection(selected );
1954 
1955 								p_item.addListener(SWT.Selection, new Listener(){
1956 									public void handleEvent(Event event) {
1957 
1958 										String name = tt.getName() + " - " + tp.getName();
1959 
1960 										if ( p_item.getSelection()){
1961 
1962 											tf_xcode.setTagTranscodeTarget( tp.getUID(), name );
1963 
1964 										}else{
1965 
1966 											tf_xcode.setTagTranscodeTarget( null, null );
1967 										}
1968 									}
1969 								});
1970 							}
1971 
1972 							new MenuItem(tt_menu, SWT.SEPARATOR );
1973 
1974 							final MenuItem no_xcode_item = new MenuItem(tt_menu, SWT.CHECK);
1975 
1976 							final String never_str = MessageText.getString( "v3.menu.device.defaultprofile.never" );
1977 
1978 							no_xcode_item.setText( never_str );
1979 
1980 							final String never_uid = tt.getID() + "/blank";
1981 
1982 							boolean	selected = existing != null	&& existing[0].equals(never_uid);
1983 
1984 							if ( selected ){
1985 
1986 								Utils.setMenuItemImage(tt_item, "graytick");
1987 							}
1988 
1989 							no_xcode_item.setSelection(selected );
1990 
1991 							no_xcode_item.addListener(SWT.Selection, new Listener(){
1992 
1993 								public void handleEvent(Event event) {
1994 
1995 									String name = tt.getName() + " - " + never_str;
1996 
1997 									if ( no_xcode_item.getSelection()){
1998 
1999 										tf_xcode.setTagTranscodeTarget( never_uid, name );
2000 
2001 									}else{
2002 
2003 										tf_xcode.setTagTranscodeTarget( null, null );
2004 									}
2005 								}
2006 							});
2007 						}
2008 					}
2009 				}
2010 			}
2011 		}
2012 	}
2013 
2014 	private static void
createCloseableMenuItems( Menu menu, Tag tag, TagType tag_type, Menu[] menuShowHide, boolean needs_separator_next)2015 		createCloseableMenuItems(
2016 				Menu menu,
2017 				Tag tag,
2018 				TagType tag_type,
2019 				Menu[] menuShowHide,
2020 				boolean needs_separator_next)
2021 	{
2022 
2023 		final List<Tag>	tags = tag_type.getTags();
2024 
2025 		int	visible_count 	= 0;
2026 		int	invisible_count = 0;
2027 
2028 		for ( Tag t: tags ){
2029 
2030 			if ( t.isVisible()){
2031 				visible_count++;
2032 			}else{
2033 				invisible_count++;
2034 			}
2035 		}
2036 
2037 		menuShowHide[0] = new Menu(menu.getShell(), SWT.DROP_DOWN);
2038 
2039 		final MenuItem showhideitem = new MenuItem(menu, SWT.CASCADE);
2040 		showhideitem.setText( MessageText.getString( "label.showhide.tag" ));
2041 		showhideitem.setMenu(menuShowHide[0]);
2042 
2043 		MenuItem title = new MenuItem(menuShowHide[0], SWT.PUSH);
2044 		title.setText( "[" + tag_type.getTagTypeName( true ) + "]" );
2045 		title.setEnabled( false );
2046 		new MenuItem( menuShowHide[0], SWT.SEPARATOR);
2047 
2048 		if ( invisible_count > 0 ){
2049 			MenuItem showAll = new MenuItem(menuShowHide[0], SWT.PUSH);
2050 			Messages.setLanguageText(showAll, "label.show.all");
2051 			showAll.addListener(SWT.Selection, new Listener() {
2052 				public void handleEvent(Event event){
2053 					for ( Tag t: tags ){
2054 
2055 						if ( !t.isVisible()){
2056 							t.setVisible( true );
2057 						}
2058 					}
2059 				}});
2060 
2061 			needs_separator_next = true;
2062 		}
2063 
2064 		if ( visible_count > 0 ){
2065 			MenuItem hideAll = new MenuItem(menuShowHide[0], SWT.PUSH);
2066 			Messages.setLanguageText(hideAll, "popup.error.hideall");
2067 			hideAll.addListener(SWT.Selection, new Listener() {
2068 				public void handleEvent(Event event){
2069 					for ( Tag t: tags ){
2070 
2071 						if ( t.isVisible()){
2072 							t.setVisible( false );
2073 						}
2074 					}
2075 				}});
2076 
2077 			needs_separator_next = true;
2078 		}
2079 
2080 		if ( tags.size() > 0 ){
2081 
2082 			if ( needs_separator_next ){
2083 
2084 				new MenuItem( menuShowHide[0], SWT.SEPARATOR);
2085 
2086 				needs_separator_next = false;
2087 			}
2088 
2089 			List<String>	menu_names 		= new ArrayList<String>();
2090 			Map<String,Tag>	menu_name_map 	= new IdentityHashMap<String, Tag>();
2091 
2092 			for ( Tag t: tags ){
2093 
2094 				String name = t.getTagName( true );
2095 
2096 				menu_names.add( name );
2097 				menu_name_map.put( name, t );
2098 			}
2099 
2100 			List<Object>	menu_structure = MenuBuildUtils.splitLongMenuListIntoHierarchy( menu_names, MAX_TOP_LEVEL_TAGS_IN_MENU );
2101 
2102 			for ( Object obj: menu_structure ){
2103 
2104 				List<Tag>	bucket_tags = new ArrayList<Tag>();
2105 
2106 				Menu parent_menu;
2107 
2108 				if ( obj instanceof String ){
2109 
2110 					parent_menu = menuShowHide[0];
2111 
2112 					bucket_tags.add( menu_name_map.get((String)obj));
2113 
2114 				}else{
2115 
2116 					Object[]	entry = (Object[])obj;
2117 
2118 					List<String>	tag_names = (List<String>)entry[1];
2119 
2120 					boolean	sub_all_visible 	= true;
2121 					boolean sub_some_visible	= false;
2122 
2123 					for ( String name: tag_names ){
2124 
2125 						Tag sub_tag = menu_name_map.get( name );
2126 
2127 						if ( sub_tag.isVisible()){
2128 
2129 							sub_some_visible = true;
2130 
2131 						}else{
2132 
2133 							sub_all_visible = false;
2134 						}
2135 
2136 						bucket_tags.add( sub_tag );
2137 					}
2138 
2139 					String mod;
2140 
2141 					if ( sub_all_visible ){
2142 
2143 						mod = " (*)";
2144 
2145 					}else if ( sub_some_visible ){
2146 
2147 						mod = " (+)";
2148 
2149 					}else{
2150 
2151 						mod = "";
2152 					}
2153 
2154 					Menu menu_bucket = new Menu( menuShowHide[0].getShell(), SWT.DROP_DOWN );
2155 
2156 					MenuItem bucket_item = new MenuItem( menuShowHide[0], SWT.CASCADE );
2157 
2158 					bucket_item.setText((String)entry[0] + mod);
2159 
2160 					bucket_item.setMenu( menu_bucket );
2161 
2162 					parent_menu = menu_bucket;
2163 				}
2164 
2165 				for ( final Tag t: bucket_tags ){
2166 
2167 					MenuItem showTag = new MenuItem( parent_menu, SWT.CHECK );
2168 
2169 					showTag.setSelection( t.isVisible());
2170 
2171 					Messages.setLanguageText(showTag, t.getTagName( false ));
2172 
2173 					showTag.addListener(SWT.Selection, new Listener() {
2174 						public void handleEvent(Event event){
2175 							t.setVisible( !t.isVisible());
2176 						}});
2177 				}
2178 			}
2179 		}
2180 
2181 		showhideitem.setEnabled( true );
2182 	}
2183 
2184 	private static void
createNonAutoMenuItems( final Menu menu, final Tag tag, final TagType tag_type, Menu[] menuShowHide)2185 		createNonAutoMenuItems(
2186 				final Menu menu,
2187 				final Tag tag,
2188 				final TagType tag_type,
2189 				Menu[] menuShowHide)
2190 	{
2191 
2192 		if ( tag_type.hasTagTypeFeature( TagFeature.TF_PROPERTIES )){
2193 
2194 			TagFeatureProperties props = (TagFeatureProperties)tag;
2195 
2196 			boolean has_ut = props.getProperty( TagFeatureProperties.PR_UNTAGGED ) != null;
2197 
2198 			if ( has_ut ){
2199 
2200 				has_ut = false;
2201 
2202 				for ( Tag t: tag_type.getTags()){
2203 
2204 					props = (TagFeatureProperties)t;
2205 
2206 					TagProperty prop = props.getProperty( TagFeatureProperties.PR_UNTAGGED );
2207 
2208 					if ( prop != null ){
2209 
2210 						Boolean b = prop.getBoolean();
2211 
2212 						if ( b != null && b ){
2213 
2214 							has_ut = true;
2215 
2216 							break;
2217 						}
2218 					}
2219 				}
2220 
2221 				if  ( !has_ut ){
2222 
2223 					if ( menuShowHide[0] == null ){
2224 
2225 						menuShowHide[0] = new Menu(menu.getShell(), SWT.DROP_DOWN);
2226 
2227 						MenuItem showhideitem = new MenuItem(menu, SWT.CASCADE);
2228 						showhideitem.setText( MessageText.getString( "label.showhide.tag" ));
2229 						showhideitem.setMenu(menuShowHide[0]);
2230 
2231 					}else{
2232 
2233 						new MenuItem( menuShowHide[0], SWT.SEPARATOR );
2234 					}
2235 
2236 					MenuItem showAll = new MenuItem(menuShowHide[0], SWT.PUSH);
2237 					Messages.setLanguageText(showAll, "label.untagged");
2238 					showAll.addListener(SWT.Selection, new Listener() {
2239 						public void handleEvent(Event event){
2240 							try{
2241 								String tag_name = MessageText.getString( "label.untagged" );
2242 
2243 								Tag ut_tag = tag_type.getTag( tag_name, true );
2244 
2245 								if ( ut_tag == null ){
2246 
2247 
2248 									ut_tag = tag_type.createTag( tag_name, true );
2249 								}
2250 
2251 								TagFeatureProperties tp = (TagFeatureProperties)ut_tag;
2252 
2253 								tp.getProperty( TagFeatureProperties.PR_UNTAGGED ).setBoolean( true );
2254 
2255 							}catch( TagException e ){
2256 
2257 								Debug.out( e );
2258 							}
2259 						}});
2260 				}
2261 			}
2262 		}
2263 
2264 		/*
2265 		MenuItem item_create = new MenuItem( menu, SWT.PUSH);
2266 
2267 		Messages.setLanguageText(item_create, "label.add.tag");
2268 		item_create.addListener(SWT.Selection, new Listener() {
2269 			public void handleEvent(Event event) {
2270 
2271 				createManualTag(null);
2272 			}
2273 		});
2274 		*/
2275 
2276 		/* Seldom Used: Color can be set in Tags Overview
2277 		MenuItem itemSetColor = new MenuItem(menu, SWT.PUSH);
2278 
2279 		itemSetColor.setText( MessageText.getString( "label.color") + "..." );
2280 
2281 		itemSetColor.addListener(SWT.Selection, new Listener() {
2282 			public void handleEvent(Event event) {
2283 
2284 				int[] existing = tag.getColor();
2285 
2286 				RGB e_rg = existing==null?null:new RGB(existing[0],existing[1],existing[2]);
2287 
2288 				RGB rgb = Utils.showColorDialog( menu.getShell(), e_rg );
2289 
2290 				if ( rgb != null ){
2291 
2292 					tag.setColor( new int[]{ rgb.red, rgb.green, rgb.blue });
2293 				}
2294 			}
2295 		});
2296 	 */
2297 
2298 		MenuItem itemGroup = new MenuItem(menu, SWT.PUSH);
2299 
2300 		Messages.setLanguageText(itemGroup, "MyTorrentsView.menu.group");
2301 		itemGroup.addListener(SWT.Selection, new Listener() {
2302 			public void handleEvent(Event event) {
2303 				SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
2304 						"TagGroupWindow.title", "TagGroupWindow.message");
2305 
2306 				String group = tag.getGroup();
2307 
2308 				if ( group == null ){
2309 					group = "";
2310 				}
2311 				entryWindow.setPreenteredText( group, false );
2312 				entryWindow.selectPreenteredText( true );
2313 
2314 				entryWindow.prompt();
2315 
2316 				if ( entryWindow.hasSubmittedInput()){
2317 
2318 					try{
2319 						group = entryWindow.getSubmittedInput().trim();
2320 
2321 						if ( group.length() == 0 ){
2322 							group = null;
2323 						}
2324 						tag.setGroup( group );
2325 
2326 					}catch( Throwable e ){
2327 
2328 						Debug.out( e );
2329 					}
2330 				}
2331 			}
2332 		});
2333 
2334 		/* Seldom Used: can be set in Tags Overview
2335 		MenuItem itemRename = new MenuItem(menu, SWT.PUSH);
2336 
2337 		Messages.setLanguageText(itemRename, "MyTorrentsView.menu.rename");
2338 		itemRename.addListener(SWT.Selection, new Listener() {
2339 			public void handleEvent(Event event) {
2340 				SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
2341 						"TagRenameWindow.title", "TagRenameWindow.message");
2342 
2343 				entryWindow.setPreenteredText( tag.getTagName( true ), false );
2344 				entryWindow.selectPreenteredText( true );
2345 
2346 				entryWindow.prompt();
2347 
2348 				if ( entryWindow.hasSubmittedInput()){
2349 
2350 					try{
2351 						tag.setTagName( entryWindow.getSubmittedInput().trim());
2352 
2353 					}catch( Throwable e ){
2354 
2355 						Debug.out( e );
2356 					}
2357 				}
2358 			}
2359 		});
2360 		*/
2361 
2362 		MenuItem itemDelete = new MenuItem(menu, SWT.PUSH);
2363 
2364 		Utils.setMenuItemImage(itemDelete, "delete");
2365 
2366 		Messages.setLanguageText(itemDelete, "FileItem.delete");
2367 		itemDelete.addListener(SWT.Selection, new Listener() {
2368 			public void handleEvent(Event event) {
2369 				tag.removeTag();
2370 			}
2371 		});
2372 	}
2373 
2374 	public static void
createSideBarMenuItems( final Menu menu, final List<Tag> _tags )2375 	createSideBarMenuItems(
2376 		final Menu 			menu,
2377 		final List<Tag>	 	_tags )
2378 	{
2379 		final List<Tag> tags = new ArrayList<Tag>( _tags );
2380 
2381 		Iterator<Tag> it = tags.iterator();
2382 
2383 		boolean	can_show 	= false;
2384 		boolean	can_hide	= false;
2385 
2386 		while( it.hasNext()){
2387 
2388 			Tag tag = it.next();
2389 
2390 			if ( tag.getTagType().getTagType() != TagType.TT_DOWNLOAD_MANUAL ){
2391 
2392 				it.remove();
2393 			}else{
2394 
2395 				if ( tag.isVisible()){
2396 
2397 					can_hide = true;
2398 
2399 				}else{
2400 
2401 					can_show = true;
2402 				}
2403 			}
2404 		}
2405 
2406 		if ( tags.size() == 0 ){
2407 
2408 			return;
2409 		}
2410 
2411 		MenuItem itemShow = new MenuItem(menu, SWT.PUSH);
2412 
2413 		Messages.setLanguageText(itemShow, "Button.bar.show");
2414 		itemShow.addListener(SWT.Selection, new Listener() {
2415 			public void handleEvent(Event event) {
2416 				for ( Tag tag: tags ){
2417 					tag.setVisible( true );
2418 				}
2419 			}
2420 		});
2421 
2422 		itemShow.setEnabled( can_show );
2423 
2424 		MenuItem itemHide = new MenuItem(menu, SWT.PUSH);
2425 
2426 		Messages.setLanguageText(itemHide, "Button.bar.hide");
2427 		itemHide.addListener(SWT.Selection, new Listener() {
2428 			public void handleEvent(Event event) {
2429 				for ( Tag tag: tags ){
2430 					tag.setVisible( false );
2431 				}
2432 			}
2433 		});
2434 
2435 		itemHide.setEnabled( can_hide );
2436 
2437 		MenuItem itemGroup = new MenuItem(menu, SWT.PUSH);
2438 
2439 		Messages.setLanguageText(itemGroup, "MyTorrentsView.menu.group");
2440 		itemGroup.addListener(SWT.Selection, new Listener() {
2441 			public void handleEvent(Event event) {
2442 				SimpleTextEntryWindow entryWindow = new SimpleTextEntryWindow(
2443 						"TagGroupWindow.title", "TagGroupWindow.message");
2444 
2445 				String group = "";
2446 
2447 				entryWindow.setPreenteredText( group, false );
2448 				entryWindow.selectPreenteredText( true );
2449 
2450 				entryWindow.prompt();
2451 
2452 				if ( entryWindow.hasSubmittedInput()){
2453 
2454 					try{
2455 						group = entryWindow.getSubmittedInput().trim();
2456 
2457 						if ( group.length() == 0 ){
2458 							group = null;
2459 						}
2460 
2461 						for ( Tag tag: tags ){
2462 
2463 							tag.setGroup( group );
2464 						}
2465 					}catch( Throwable e ){
2466 
2467 						Debug.out( e );
2468 					}
2469 				}
2470 			}
2471 		});
2472 
2473 		org.gudy.azureus2.plugins.ui.menus.MenuItem[] items = MenuItemManager.getInstance().getAllAsArray(
2474 				MenuManager.MENU_TAG_CONTEXT);
2475 
2476 		if (items.length > 0) {
2477 			MenuFactory.addSeparatorMenuItem(menu);
2478 
2479 			// TODO: Don't send Tag.. send a yet-to-be-created plugin interface version of Tag
2480 			MenuBuildUtils.addPluginMenuItems(items, menu, true, true,
2481 					new MenuBuildUtils.MenuItemPluginMenuControllerImpl(tags.toArray(new Tag[0])));
2482 		}
2483 	}
2484 
2485 	private static final AsyncDispatcher move_dispatcher = new AsyncDispatcher( "tag:applytocurrent" );
2486 
2487 	private static void
applyLocationToCurrent( final Tag tag, final File location, final boolean complete_only )2488 	applyLocationToCurrent(
2489 		final Tag			tag,
2490 		final File			location,
2491 		final boolean		complete_only )
2492 	{
2493 		move_dispatcher.dispatch(
2494 			new AERunnable()
2495 			{
2496 				public void
2497 				runSupport()
2498 				{
2499 					Set<DownloadManager>	downloads = ((TagDownload)tag).getTaggedDownloads();
2500 
2501 					for ( DownloadManager download: downloads ){
2502 
2503 						boolean dl_is_complete = download.isDownloadComplete( false );
2504 
2505 						if ( complete_only && !dl_is_complete){
2506 
2507 								// applying move-on-complete so ignore incomplete
2508 
2509 							continue;
2510 						}
2511 
2512 						if ( dl_is_complete && !complete_only ){
2513 
2514 								// applying initial-save-folder, ignore completed files
2515 								// that have been moved somewhere already
2516 
2517 							if ( download.getDownloadState().getFlag( DownloadManagerState.FLAG_MOVE_ON_COMPLETION_DONE )){
2518 
2519 								continue;
2520 							}
2521 						}
2522 
2523 						try{
2524 							download.moveDataFilesLive( location );
2525 
2526 						}catch( Throwable e ){
2527 
2528 							Debug.out( e );
2529 						}
2530 					}
2531 				}
2532 			});
2533 	}
2534 
2535 	public static void
addLibraryViewTagsSubMenu( final DownloadManager[] dms, Menu menu_tags, final Composite composite)2536 	addLibraryViewTagsSubMenu(
2537 		final DownloadManager[] 	dms,
2538 		Menu 						menu_tags,
2539 		final Composite 			composite)
2540 	{
2541 		MenuItem[] items = menu_tags.getItems();
2542 
2543 		for ( MenuItem item: items ){
2544 
2545 			item.dispose();
2546 		}
2547 
2548 		final TagManager tm = TagManagerFactory.getTagManager();
2549 
2550 		Map<TagType,List<Tag>>	auto_map = new HashMap<TagType, List<Tag>>();
2551 
2552 		TagType manual_tt = tm.getTagType( TagType.TT_DOWNLOAD_MANUAL );
2553 
2554 		Map<Tag,Integer>	manual_map = new HashMap<Tag, Integer>();
2555 
2556 		for ( DownloadManager dm: dms ){
2557 
2558 			List<Tag> tags = tm.getTagsForTaggable( dm );
2559 
2560 			for ( Tag t: tags ){
2561 
2562 				TagType tt = t.getTagType();
2563 
2564 				if ( tt.isTagTypeAuto() || t.isTagAuto()[0] || t.isTagAuto()[1]){
2565 
2566 					List<Tag> x = auto_map.get( tt );
2567 
2568 					if ( x == null ){
2569 
2570 						x = new ArrayList<Tag>();
2571 
2572 						auto_map.put( tt, x );
2573 					}
2574 
2575 					x.add( t );
2576 
2577 				}else if ( tt == manual_tt ){
2578 
2579 					Integer i = manual_map.get( t );
2580 
2581 					manual_map.put( t, i==null?1:i+1 );
2582 				}
2583 			}
2584 		}
2585 
2586 		if ( auto_map.size() > 0 ){
2587 
2588 			final Menu menuAuto = new Menu(menu_tags.getShell(), SWT.DROP_DOWN);
2589 			final MenuItem autoItem = new MenuItem(menu_tags, SWT.CASCADE);
2590 			Messages.setLanguageText(autoItem, "wizard.maketorrent.auto" );
2591 			autoItem.setMenu(menuAuto);
2592 
2593 			List<TagType>	auto_tags = sortTagTypes( auto_map.keySet());
2594 
2595 			for ( TagType tt: auto_tags ){
2596 
2597 				MenuItem tt_i = new MenuItem(menuAuto, Constants.isOSX?SWT.CHECK:SWT.PUSH);
2598 
2599 				String tt_str = tt.getTagTypeName( true ) + ": ";
2600 
2601 				List<Tag> tags = auto_map.get( tt );
2602 
2603 				Map<Tag,Integer>	tag_counts = new HashMap<Tag, Integer>();
2604 
2605 				for ( Tag t: tags ){
2606 
2607 					Integer i = tag_counts.get( t );
2608 
2609 					tag_counts.put( t, i==null?1:i+1 );
2610 				}
2611 
2612 				tags = sortTags( tag_counts.keySet());
2613 
2614 				int	 num = 0;
2615 
2616 				for ( Tag t: tags ){
2617 
2618 					tt_str += (num==0?"":", " ) + t.getTagName( true );
2619 
2620 					num++;
2621 
2622 					if ( dms.length > 1 ){
2623 
2624 						tt_str += " (" + tag_counts.get( t ) + ")";
2625 					}
2626 				}
2627 
2628 				tt_i.setText( tt_str );
2629 				if ( Constants.isOSX ){
2630 					tt_i.setSelection(true);
2631 				}else{
2632 					Utils.setMenuItemImage( tt_i, "graytick" );
2633 				}
2634 
2635 				//tt_i.setEnabled(false);
2636 			}
2637 		}
2638 
2639 		List<Tag>	manual_t = manual_tt.getTags();
2640 
2641 		if ( manual_t.size() > 0 ){
2642 
2643 			if ( auto_map.size() > 0 ){
2644 
2645 				new MenuItem( menu_tags, SWT.SEPARATOR );
2646 			}
2647 
2648 			List<String>	menu_names 		= new ArrayList<String>();
2649 			Map<String,Tag>	menu_name_map 	= new IdentityHashMap<String, Tag>();
2650 
2651 			for ( Tag t: manual_t ){
2652 
2653 					// don't allow manual adding of taggables to auto-tags
2654 
2655 				if ( !t.isTagAuto()[0]){
2656 
2657 					String name = t.getTagName( true );
2658 
2659 					menu_names.add( name );
2660 					menu_name_map.put( name, t );
2661 				}
2662 			}
2663 
2664 			List<Object>	menu_structure = MenuBuildUtils.splitLongMenuListIntoHierarchy( menu_names, MAX_TOP_LEVEL_TAGS_IN_MENU );
2665 
2666 			for ( Object obj: menu_structure ){
2667 
2668 				List<Tag>	bucket_tags = new ArrayList<Tag>();
2669 
2670 				Menu	 parent_menu;
2671 
2672 				if ( obj instanceof String ){
2673 
2674 					parent_menu = menu_tags;
2675 
2676 					bucket_tags.add( menu_name_map.get((String)obj));
2677 
2678 				}else{
2679 
2680 					Object[]	entry = (Object[])obj;
2681 
2682 					List<String>	tag_names = (List<String>)entry[1];
2683 
2684 					boolean	sub_all_selected 	= true;
2685 					boolean sub_some_selected	= false;
2686 
2687 					for ( String name: tag_names ){
2688 
2689 						Tag sub_tag = menu_name_map.get( name );
2690 
2691 						Integer c = manual_map.get( sub_tag );
2692 
2693 						if ( c != null && c == dms.length ){
2694 
2695 							sub_some_selected = true;
2696 
2697 						}else{
2698 
2699 							sub_all_selected = false;
2700 						}
2701 
2702 						bucket_tags.add( sub_tag );
2703 					}
2704 
2705 					String mod;
2706 
2707 					if ( sub_all_selected ){
2708 
2709 						mod = " (*)";
2710 
2711 					}else if ( sub_some_selected ){
2712 
2713 						mod = " (+)";
2714 
2715 					}else{
2716 
2717 						mod = "";
2718 					}
2719 
2720 					Menu menu_bucket = new Menu( menu_tags.getShell(), SWT.DROP_DOWN );
2721 
2722 					MenuItem bucket_item = new MenuItem( menu_tags, SWT.CASCADE );
2723 
2724 					bucket_item.setText((String)entry[0] + mod);
2725 
2726 					bucket_item.setMenu( menu_bucket );
2727 
2728 					parent_menu = menu_bucket;
2729 				}
2730 
2731 				for ( final Tag t: bucket_tags ){
2732 
2733 					final MenuItem t_i = new MenuItem( parent_menu, SWT.CHECK );
2734 
2735 					String tag_name = t.getTagName( true );
2736 
2737 					Integer c = manual_map.get( t );
2738 
2739 					if ( c != null ){
2740 
2741 						if ( c == dms.length ){
2742 
2743 							t_i.setSelection( true );
2744 
2745 							t_i.setText( tag_name );
2746 
2747 						}else{
2748 
2749 							t_i.setText( tag_name + " (" + c + ")" );
2750 						}
2751 					}else{
2752 
2753 						t_i.setText( tag_name );
2754 					}
2755 
2756 					t_i.addListener(SWT.Selection, new Listener() {
2757 						public void handleEvent(Event event) {
2758 
2759 							boolean	selected = t_i.getSelection();
2760 
2761 							for ( DownloadManager dm: dms ){
2762 
2763 								if ( selected ){
2764 
2765 									t.addTaggable( dm );
2766 
2767 								}else{
2768 
2769 									t.removeTaggable( dm );
2770 								}
2771 							}
2772 						}
2773 					});
2774 				}
2775 			}
2776 		}
2777 
2778 		new MenuItem( menu_tags, SWT.SEPARATOR );
2779 
2780 		MenuItem item_create = new MenuItem( menu_tags, SWT.PUSH);
2781 
2782 		Messages.setLanguageText(item_create, "label.add.tag");
2783 		item_create.addListener(SWT.Selection, new Listener() {
2784 			public void handleEvent(Event event) {
2785 
2786 				createManualTag(new UIFunctions.TagReturner() {
2787 					public void returnedTags(Tag[] tags) {
2788 						if ( tags != null ){
2789 							for (Tag new_tag : tags) {
2790 								for ( DownloadManager dm: dms ){
2791 
2792 									new_tag.addTaggable( dm );
2793 								}
2794 
2795 								COConfigurationManager.setParameter( "Library.TagInSideBar", true );
2796 							}
2797 						}
2798 					}
2799 				});
2800 			}
2801 		});
2802 	}
2803 
2804 	public static List<TagType>
sortTagTypes( Collection<TagType> _tag_types )2805 	sortTagTypes(
2806 		Collection<TagType>	_tag_types )
2807 	{
2808 		List<TagType>	tag_types = new ArrayList<TagType>( _tag_types );
2809 
2810 		Collections.sort(
2811 			tag_types,
2812 			new Comparator<TagType>()
2813 			{
2814 				final Comparator<String> comp = new FormattersImpl().getAlphanumericComparator( true );
2815 
2816 				public int
2817 				compare(
2818 					TagType o1, TagType o2)
2819 				{
2820 					return( comp.compare( o1.getTagTypeName(true), o2.getTagTypeName(true)));
2821 				}
2822 			});
2823 
2824 		return( tag_types );
2825 	}
2826 
2827 	public static List<Tag>
sortTags( Collection<Tag> _tags )2828 	sortTags(
2829 		Collection<Tag>	_tags )
2830 	{
2831 		List<Tag>	tags = new ArrayList<Tag>( _tags );
2832 
2833 		if ( tags.size() < 2 ){
2834 
2835 			return( tags );
2836 		}
2837 
2838 		Collections.sort( tags, getTagComparator());
2839 
2840 		return( tags );
2841 	}
2842 
2843 	public static Comparator<Tag>
getTagComparator()2844 	getTagComparator()
2845 	{
2846 		return( new Comparator<Tag>()
2847 		{
2848 			final Comparator<String> comp = new FormattersImpl().getAlphanumericComparator( true );
2849 
2850 			public int
2851 			compare(
2852 				Tag o1, Tag o2)
2853 			{
2854 				String	g1 = o1.getGroup();
2855 				String	g2 = o2.getGroup();
2856 
2857 				if ( g1 != g2 ){
2858 					if ( g1 == null ){
2859 						return( 1 );
2860 					}else if ( g2 == null ){
2861 						return( -1 );
2862 					}else{
2863 
2864 						int	res = comp.compare( g1,  g2 );
2865 
2866 						if ( res != 0 ){
2867 							return( res );
2868 						}
2869 					}
2870 				}
2871 				return( comp.compare( o1.getTagName(true), o2.getTagName(true)));
2872 			}
2873 		});
2874 	}
2875 
2876 	public static String
getTagTooltip( Tag tag )2877 	getTagTooltip(
2878 		Tag		tag )
2879 	{
2880 		return( getTagTooltip( tag, false ));
2881 	}
2882 
2883 	public static String
getTagTooltip( Tag tag, boolean skip_name )2884 	getTagTooltip(
2885 		Tag			tag,
2886 		boolean		skip_name )
2887 	{
2888 		TagType tag_type = tag.getTagType();
2889 
2890 		String 	str = skip_name?"":(tag_type.getTagTypeName( true ) + ": " + tag.getTagName( true ));
2891 
2892 		String desc = tag.getDescription();
2893 
2894 		if ( desc != null ){
2895 
2896 			if ( str.length() > 0 ){
2897 
2898 				str += "\r\n";
2899 			}
2900 
2901 			str += desc;
2902 		}
2903 
2904 		if ( tag_type.hasTagTypeFeature( TagFeature.TF_RATE_LIMIT )){
2905 
2906 			TagFeatureRateLimit rl = (TagFeatureRateLimit)tag;
2907 
2908 			String 	up_str 		= "";
2909 			String	down_str 	= "";
2910 
2911 			int	limit_up = rl.getTagUploadLimit();
2912 
2913 			if ( limit_up > 0 ){
2914 
2915 				up_str += MessageText.getString( "label.limit" ) + "=" + DisplayFormatters.formatByteCountToKiBEtcPerSec( limit_up );
2916 			}
2917 
2918 			int current_up 		= rl.getTagCurrentUploadRate();
2919 
2920 			if ( current_up >= 0 ){
2921 
2922 				up_str += (up_str.length()==0?"":", " ) + MessageText.getString( "label.current" ) + "=" + DisplayFormatters.formatByteCountToKiBEtcPerSec( current_up);
2923 			}
2924 
2925 			int	limit_down = rl.getTagDownloadLimit();
2926 
2927 			if ( limit_down > 0 ){
2928 
2929 				down_str += MessageText.getString( "label.limit" ) + "=" + DisplayFormatters.formatByteCountToKiBEtcPerSec( limit_down );
2930 			}
2931 
2932 			int current_down 		= rl.getTagCurrentDownloadRate();
2933 
2934 			if ( current_down >= 0 ){
2935 
2936 				down_str += (down_str.length()==0?"":", " ) + MessageText.getString( "label.current" ) + "=" + DisplayFormatters.formatByteCountToKiBEtcPerSec( current_down);
2937 			}
2938 
2939 
2940 			if ( up_str.length() > 0 ){
2941 
2942 				str += "\r\n    " + MessageText.getString("iconBar.up") + ": " + up_str;
2943 			}
2944 
2945 			if ( down_str.length() > 0 ){
2946 
2947 				str += "\r\n    " + MessageText.getString("iconBar.down") + ": " + down_str;
2948 			}
2949 
2950 
2951 			int up_pri = rl.getTagUploadPriority();
2952 
2953 			if ( up_pri > 0 ){
2954 
2955 				str += "\r\n    " + MessageText.getString("cat.upload.priority");
2956 			}
2957 		}
2958 
2959 		if ( tag_type.hasTagTypeFeature( TagFeature.TF_FILE_LOCATION )) {
2960 
2961 			TagFeatureFileLocation fl = (TagFeatureFileLocation)tag;
2962 
2963 			if ( fl.supportsTagInitialSaveFolder()){
2964 
2965 				File init_loc = fl.getTagInitialSaveFolder();
2966 
2967 				if ( init_loc != null ){
2968 
2969 					str += "\r\n    " + MessageText.getString("label.init.save.loc") + "=" + init_loc.getAbsolutePath();
2970 				}
2971 			}
2972 
2973 			if ( fl.supportsTagMoveOnComplete()){
2974 
2975 				File move_on_comp = fl.getTagMoveOnCompleteFolder();
2976 
2977 				if ( move_on_comp != null ){
2978 
2979 					str += "\r\n    " + MessageText.getString("label.move.on.comp") + "=" + move_on_comp.getAbsolutePath();
2980 				}
2981 			}
2982 			if ( fl.supportsTagCopyOnComplete()){
2983 
2984 				File copy_on_comp = fl.getTagCopyOnCompleteFolder();
2985 
2986 				if ( copy_on_comp != null ){
2987 
2988 					str += "\r\n    " + MessageText.getString("label.copy.on.comp") + "=" + copy_on_comp.getAbsolutePath();
2989 				}
2990 			}
2991 		}
2992 
2993 		if ( str.startsWith( "\r\n" )){
2994 
2995 			str = str.substring(2);
2996 		}
2997 
2998 		return( str );
2999 	}
3000 
3001 	private static void
showFilesView( final TagDownload tag )3002 	showFilesView(
3003 		final TagDownload		tag )
3004 	{
3005 		Shell shell = ShellFactory.createShell(Utils.findAnyShell(), SWT.SHELL_TRIM);
3006 
3007 		FillLayout fillLayout = new FillLayout();
3008 		fillLayout.marginHeight = 2;
3009 		fillLayout.marginWidth = 2;
3010 		shell.setLayout(fillLayout);
3011 
3012 		final FilesView view = new FilesView(false);
3013 
3014 		view.setDisableWhenEmpty( false );
3015 
3016 		Set<DownloadManager>	dms = tag.getTaggedDownloads();
3017 
3018 		view.dataSourceChanged( dms.toArray());
3019 
3020 		view.initialize(shell);
3021 
3022 		view.viewActivated();
3023 		view.refresh();
3024 
3025 		final UIUpdatable viewUpdater = new UIUpdatable() {
3026 			public void updateUI() {
3027 				view.refresh();
3028 			}
3029 
3030 			public String getUpdateUIName() {
3031 				return view.getFullTitle();
3032 			}
3033 		};
3034 
3035 		UIUpdaterSWT.getInstance().addUpdater(viewUpdater);
3036 
3037 		final TagListener tag_listener =
3038 			new TagListener() {
3039 
3040 				public void taggableSync(Tag tag) {
3041 				}
3042 
3043 				public void
3044 				taggableRemoved(
3045 					Tag t, Taggable tagged)
3046 				{
3047 					Set<DownloadManager>	dms = tag.getTaggedDownloads();
3048 
3049 					view.dataSourceChanged( dms.toArray());
3050 				}
3051 
3052 				public void
3053 				taggableAdded(
3054 					Tag t, Taggable tagged)
3055 				{
3056 					Set<DownloadManager>	dms = tag.getTaggedDownloads();
3057 
3058 					view.dataSourceChanged( dms.toArray());
3059 				}
3060 			};
3061 
3062 		tag.addTagListener( tag_listener, false );
3063 
3064 		shell.addDisposeListener(
3065 			new DisposeListener()
3066 			{
3067 				public void
3068 				widgetDisposed(
3069 					DisposeEvent e)
3070 				{
3071 					tag.removeTagListener( tag_listener );
3072 
3073 					UIUpdaterSWT.getInstance().removeUpdater(viewUpdater);
3074 					view.delete();
3075 				}
3076 			});
3077 
3078 		shell.layout(true, true);
3079 
3080 
3081 		shell.setText( tag.getTagName(true));
3082 
3083 		shell.open();
3084 	}
3085 }
3086