1 /*
2  * Created on 05-Sep-2005
3  * Created by Paul Gardner
4  * Copyright (C) Azureus Software, Inc, All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  *
18  */
19 
20 package org.gudy.azureus2.ui.swt.pluginsimpl;
21 
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.lang.ref.WeakReference;
26 import java.net.URL;
27 import java.util.*;
28 
29 import org.eclipse.swt.SWT;
30 import org.eclipse.swt.graphics.Image;
31 import org.eclipse.swt.graphics.ImageData;
32 import org.eclipse.swt.graphics.Resource;
33 import org.eclipse.swt.widgets.Display;
34 import org.eclipse.swt.widgets.Shell;
35 
36 import org.gudy.azureus2.core3.config.COConfigurationManager;
37 import org.gudy.azureus2.core3.download.DownloadManager;
38 import org.gudy.azureus2.core3.internat.MessageText;
39 import org.gudy.azureus2.core3.util.AERunnable;
40 import org.gudy.azureus2.core3.util.AETemporaryFileHandler;
41 import org.gudy.azureus2.core3.util.Debug;
42 import org.gudy.azureus2.plugins.PluginInterface;
43 import org.gudy.azureus2.plugins.download.Download;
44 import org.gudy.azureus2.plugins.torrent.Torrent;
45 import org.gudy.azureus2.plugins.ui.*;
46 import org.gudy.azureus2.plugins.ui.menus.MenuItem;
47 import org.gudy.azureus2.plugins.ui.model.BasicPluginConfigModel;
48 import org.gudy.azureus2.plugins.ui.model.BasicPluginViewModel;
49 import org.gudy.azureus2.plugins.ui.tables.TableColumn;
50 import org.gudy.azureus2.plugins.ui.tables.TableColumnCreationListener;
51 import org.gudy.azureus2.plugins.ui.tables.TableContextMenuItem;
52 import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarItem;
53 import org.gudy.azureus2.plugins.ui.toolbar.UIToolBarManager;
54 import org.gudy.azureus2.pluginsimpl.local.PluginInitializer;
55 import org.gudy.azureus2.pluginsimpl.local.download.DownloadImpl;
56 import org.gudy.azureus2.pluginsimpl.local.ui.UIManagerImpl;
57 import org.gudy.azureus2.pluginsimpl.local.ui.config.ConfigSectionRepository;
58 import org.gudy.azureus2.ui.common.util.MenuItemManager;
59 import org.gudy.azureus2.ui.swt.*;
60 import org.gudy.azureus2.ui.swt.components.shell.ShellFactory;
61 import org.gudy.azureus2.ui.swt.mainwindow.*;
62 import org.gudy.azureus2.ui.swt.minibar.AllTransfersBar;
63 import org.gudy.azureus2.ui.swt.minibar.DownloadBar;
64 import org.gudy.azureus2.ui.swt.plugins.*;
65 import org.gudy.azureus2.ui.swt.shells.MessageBoxShell;
66 import org.gudy.azureus2.ui.swt.views.table.utils.TableContextMenuManager;
67 import org.gudy.azureus2.ui.swt.views.utils.ManagerUtils;
68 
69 import com.aelitis.azureus.ui.IUIIntializer;
70 import com.aelitis.azureus.ui.common.table.TableColumnCore;
71 import com.aelitis.azureus.ui.common.table.TableStructureEventDispatcher;
72 import com.aelitis.azureus.ui.common.table.impl.TableColumnImpl;
73 import com.aelitis.azureus.ui.common.table.impl.TableColumnManager;
74 import com.aelitis.azureus.ui.mdi.MultipleDocumentInterface;
75 import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
76 import com.aelitis.azureus.ui.swt.UIFunctionsSWT;
77 
78 public class
79 UISWTInstanceImpl
80 	implements UIInstanceFactory, UISWTInstance, UIManagerEventListener
81 {
82 	private Map<BasicPluginConfigModel,BasicPluginConfigImpl> 	config_view_map = new WeakHashMap<BasicPluginConfigModel,BasicPluginConfigImpl>();
83 
84 	// Map<ParentId, Map<ViewId, Listener>>
85 	private Map<String,Map<String,UISWTViewEventListenerHolder>> views = new HashMap<String,Map<String,UISWTViewEventListenerHolder>>();
86 
87 	private Map<PluginInterface,UIInstance>	plugin_map = new WeakHashMap<PluginInterface,UIInstance>();
88 
89 	private boolean bUIAttaching;
90 
91 	private final UIFunctionsSWT 		uiFunctions;
92 
93 	public static interface SWTViewListener {
setViewAdded(String parent, String id, UISWTViewEventListener l)94 		public void setViewAdded(String parent, String id, UISWTViewEventListener l);
setViewRemoved(String parent, String id, UISWTViewEventListener l)95 		public void setViewRemoved(String parent, String id, UISWTViewEventListener l);
96 	}
97 
98 	private List<SWTViewListener> listSWTViewListeners = new ArrayList<SWTViewListener>(0);
99 
UISWTInstanceImpl()100 	public UISWTInstanceImpl() {
101 		// Since this is a UI **SWT** Instance Implementor, it's assumed
102 		// that the UI Functions are of UIFunctionsSWT
103 		uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
104 	}
105 
106 	public int
getUIType()107 	getUIType()
108 	{
109 		return( UIT_SWT );
110 	}
111 
init(IUIIntializer init)112 	public void init(IUIIntializer init) {
113 		UIManager ui_manager = PluginInitializer.getDefaultInterface().getUIManager();
114 		ui_manager.addUIEventListener(this);
115 
116 		bUIAttaching = true;
117 
118 		((UIManagerImpl) ui_manager).attachUI(this, init);
119 
120 		bUIAttaching = false;
121 	}
122 
123 	public UIInstance
getInstance( PluginInterface plugin_interface )124 	getInstance(
125 		PluginInterface		plugin_interface )
126 	{
127 		UIInstance	instance = plugin_map.get( plugin_interface );
128 
129 		if ( instance == null ){
130 
131 			instance = new instanceWrapper( plugin_interface, uiFunctions, this );
132 
133 			plugin_map.put( plugin_interface, instance );
134 		}
135 
136 		return( instance );
137 	}
138 
139 	public boolean
eventOccurred( final UIManagerEvent event )140 	eventOccurred(
141 		final UIManagerEvent	event )
142 	{
143 		boolean	done = true;
144 
145 		final Object	data = event.getData();
146 
147 		switch( event.getType()){
148 
149 			case UIManagerEvent.ET_SHOW_TEXT_MESSAGE:
150 			{
151 				Utils.execSWTThread(
152 					new Runnable()
153 					{
154 						public void
155 						run()
156 						{
157 							String[]	params = (String[])data;
158 
159 							new TextViewerWindow( params[0], params[1], params[2] );
160 						}
161 					});
162 
163 				break;
164 			}
165 			case UIManagerEvent.ET_SHOW_MSG_BOX:
166 			{
167 				final int[] result = { UIManagerEvent.MT_NONE };
168 
169 					Utils.execSWTThread(
170 					new Runnable()
171 					{
172 						public void
173 						run()
174 						{
175 							UIFunctionsManagerSWT.getUIFunctionsSWT().bringToFront();
176 
177 							Object[]	params = (Object[])data;
178 
179 							long	_styles = ((Long)(params[2])).longValue();
180 
181 							int		styles	= 0;
182 							int		def		= 0;
183 
184 							if (( _styles & UIManagerEvent.MT_YES ) != 0 ){
185 
186 								styles |= SWT.YES;
187 							}
188 							if (( _styles & UIManagerEvent.MT_YES_DEFAULT ) != 0 ){
189 
190 								styles |= SWT.YES;
191 								def = SWT.YES;
192 							}
193 							if (( _styles & UIManagerEvent.MT_NO ) != 0 ){
194 
195 								styles |= SWT.NO;
196 							}
197 							if (( _styles & UIManagerEvent.MT_NO_DEFAULT ) != 0 ){
198 
199 								styles |= SWT.NO;
200 								def = SWT.NO;
201 							}
202 							if (( _styles & UIManagerEvent.MT_OK ) != 0 ){
203 
204 								styles |= SWT.OK;
205 							}
206 							if (( _styles & UIManagerEvent.MT_OK_DEFAULT ) != 0 ){
207 
208 								styles |= SWT.OK;
209 								def = SWT.OK;
210 							}
211 
212 							if (( _styles & UIManagerEvent.MT_CANCEL ) != 0 ){
213 
214 								styles |= SWT.CANCEL;
215 							}
216 
217 
218 							MessageBoxShell mb =
219 								new MessageBoxShell(
220 									styles,
221 									MessageText.getString((String)params[0]),
222 									MessageText.getString((String)params[1]));
223 
224 							if ( def != 0 ){
225 
226 								mb.setDefaultButtonUsingStyle( def );
227 							}
228 
229 							if ( params.length == 4 && params[3] instanceof Map ){
230 
231 								Map<String,Object>	options = (Map<String,Object>)params[3];
232 
233 								String	rememberID 			= (String)options.get( UIManager.MB_PARAM_REMEMBER_ID );
234 								Boolean	rememberByDefault 	= (Boolean)options.get( UIManager.MB_PARAM_REMEMBER_BY_DEF );
235 								String	rememberText		= (String)options.get( UIManager.MB_PARAM_REMEMBER_RES );
236 
237 								if ( rememberID != null && rememberByDefault != null && rememberText != null ){
238 
239 									mb.setRemember( rememberID, rememberByDefault, rememberText );
240 								}
241 
242 								Number	auto_close_ms = (Number)options.get( UIManager.MB_PARAM_AUTO_CLOSE_MS );
243 
244 								if ( auto_close_ms != null ){
245 
246 									mb.setAutoCloseInMS( auto_close_ms.intValue());
247 								}
248 							}else if ( params.length >= 6 ){
249 
250 								String	rememberID 			= (String)params[3];
251 								Boolean	rememberByDefault 	= (Boolean)params[4];
252 								String	rememberText		= (String)params[5];
253 
254 								if ( rememberID != null && rememberByDefault != null && rememberText != null ){
255 
256 									mb.setRemember( rememberID, rememberByDefault, rememberText );
257 								}
258 							}
259 
260 							mb.open(null);
261 
262 							int _r = mb.waitUntilClosed();
263 
264 							int	r = 0;
265 
266 							if (( _r & SWT.YES ) != 0 ){
267 
268 								r |= UIManagerEvent.MT_YES;
269 							}
270 							if (( _r & SWT.NO ) != 0 ){
271 
272 								r |= UIManagerEvent.MT_NO;
273 							}
274 							if (( _r & SWT.OK ) != 0 ){
275 
276 								r |= UIManagerEvent.MT_OK;
277 							}
278 							if (( _r & SWT.CANCEL ) != 0 ){
279 
280 								r |= UIManagerEvent.MT_CANCEL;
281 							}
282 
283 							result[0] = r;
284 						}
285 					}, false );
286 
287 				event.setResult( new Long( result[0] ));
288 
289 				break;
290 			}
291 			case UIManagerEvent.ET_OPEN_TORRENT_VIA_FILE:
292 			{
293 				TorrentOpener.openTorrent(((File)data).toString());
294 
295 				break;
296 			}
297 			case UIManagerEvent.ET_OPEN_TORRENT_VIA_TORRENT:
298 			{
299 				Torrent t = (Torrent)data;
300 
301 				try{
302 					File f = AETemporaryFileHandler.createTempFile();
303 
304 					t.writeToFile( f );
305 
306 					TorrentOpener.openTorrent( f.toString());
307 
308 				}catch( Throwable e ){
309 
310 					Debug.printStackTrace( e );
311 				}
312 
313 				break;
314 			}
315 			case UIManagerEvent.ET_OPEN_TORRENT_VIA_URL:
316 			{
317 				Display display = SWTThread.getInstance().getDisplay();
318 
319 				display.syncExec(new AERunnable() {
320 					public void runSupport() {
321 						Object[] params = (Object[]) data;
322 
323 						URL 		target 				= (URL) params[0];
324 						URL 		referrer 			= (URL) params[1];
325 						boolean 	auto_download 		= ((Boolean) params[2]).booleanValue();
326 						Map<?, ?>			request_properties	= (Map<?, ?>)params[3];
327 
328 						// programmatic request to add a torrent, make sure az is visible
329 
330 						if (auto_download) {
331 							Shell shell = uiFunctions.getMainShell();
332 							if (shell != null) {
333 								new FileDownloadWindow(shell, target.toString(),
334 										referrer == null ? null : referrer.toString(),
335 										request_properties );
336 							}
337 						} else {
338 
339 							// TODO: handle referrer?
340 
341 							TorrentOpener.openTorrent(target.toString());
342 						}
343 					}
344 				});
345 
346 				break;
347 			}
348 			case UIManagerEvent.ET_PLUGIN_VIEW_MODEL_CREATED:
349 			{
350 				if ( data instanceof BasicPluginViewModel ){
351 					BasicPluginViewModel model = (BasicPluginViewModel)data;
352 
353 					// property bundles can't handle spaces in keys
354 					//
355 					// If this behaviour changes, change the openView(model)
356 					// method lower down.
357 					String sViewID = model.getName().replaceAll(" ", ".");
358 					BasicPluginViewImpl view = new BasicPluginViewImpl(model);
359 					addView(UISWTInstance.VIEW_MAIN, sViewID, view);
360 				}
361 
362 				break;
363 			}
364 			case UIManagerEvent.ET_PLUGIN_VIEW_MODEL_DESTROYED:
365 			{
366 				if ( data instanceof BasicPluginViewModel ){
367 					BasicPluginViewModel model = (BasicPluginViewModel)data;
368 					// property bundles can't handle spaces in keys
369 					//
370 					// If this behaviour changes, change the openView(model)
371 					// method lower down.
372 					String sViewID = model.getName().replaceAll(" ", ".");
373 					removeViews(UISWTInstance.VIEW_MAIN, sViewID);
374 				}
375 
376 				break;
377 			}
378 			case UIManagerEvent.ET_PLUGIN_CONFIG_MODEL_CREATED:
379 			{
380 				if ( data instanceof BasicPluginConfigModel ){
381 
382 					BasicPluginConfigModel	model = (BasicPluginConfigModel)data;
383 
384 					BasicPluginConfigImpl view = new BasicPluginConfigImpl( new WeakReference<BasicPluginConfigModel>( model ));
385 
386 					config_view_map.put( model, view );
387 
388 			  	ConfigSectionRepository.getInstance().addConfigSection(view, model.getPluginInterface());
389 				}
390 
391 				break;
392 			}
393 			case UIManagerEvent.ET_PLUGIN_CONFIG_MODEL_DESTROYED:
394 			{
395 				if ( data instanceof BasicPluginConfigModel ){
396 
397 					BasicPluginConfigModel	model = (BasicPluginConfigModel)data;
398 
399 					BasicPluginConfigImpl view = config_view_map.get( model );
400 
401 					if ( view != null ){
402 
403 				  	ConfigSectionRepository.getInstance().removeConfigSection(view);
404 
405 					}
406 				}
407 
408 				break;
409 			}
410 			case UIManagerEvent.ET_COPY_TO_CLIPBOARD:
411 			{
412 				ClipboardCopy.copyToClipBoard((String)data);
413 
414 				break;
415 			}
416 			case UIManagerEvent.ET_OPEN_URL:
417 			{
418 				Utils.launch(((URL)data).toExternalForm());
419 
420 				break;
421 			}
422 			case UIManagerEvent.ET_CREATE_TABLE_COLUMN:{
423 
424 				if (data instanceof TableColumn) {
425 					event.setResult(data);
426 				} else {
427 					String[] args = (String[]) data;
428 
429 					event.setResult(new TableColumnImpl(args[0], args[1]));
430 				}
431 
432 	 			break;
433 			}
434 			case UIManagerEvent.ET_ADD_TABLE_COLUMN:{
435 
436 				TableColumn	_col = (TableColumn)data;
437 
438 				if ( _col instanceof TableColumnImpl ){
439 
440 					TableColumnManager.getInstance().addColumns(new TableColumnCore[] {	(TableColumnCore) _col });
441 
442 					TableStructureEventDispatcher tsed = TableStructureEventDispatcher.getInstance(_col.getTableID());
443 
444 					tsed.tableStructureChanged(true, _col.getForDataSourceType());
445 
446 				}else{
447 
448 					throw(new UIRuntimeException("TableManager.addColumn(..) can only add columns created by createColumn(..)"));
449 				}
450 
451 				break;
452 			}
453 			case UIManagerEvent.ET_REGISTER_COLUMN:{
454 
455 				Object[] params = (Object[])data;
456 
457 				TableColumnManager tcManager = TableColumnManager.getInstance();
458 
459 				Class<?> 	dataSource 	= (Class<?>)params[0];
460 				String	columnName	= (String)params[1];
461 
462 				tcManager.registerColumn(dataSource, columnName, (TableColumnCreationListener)params[2]);
463 
464 				String[] tables = tcManager.getTableIDs();
465 
466 				for ( String tid: tables ){
467 
468 						// we don't know which tables are affected at this point to refresh all.
469 						// if this proves to be a performance issue then we would have to use the
470 						// datasource to derive affected tables somehow
471 
472 					TableStructureEventDispatcher tsed = TableStructureEventDispatcher.getInstance( tid );
473 
474 					tsed.tableStructureChanged(true, dataSource);
475 				}
476 
477 				break;
478 			}
479 			case UIManagerEvent.ET_UNREGISTER_COLUMN:{
480 
481 				Object[] params = (Object[])data;
482 
483 				TableColumnManager tcManager = TableColumnManager.getInstance();
484 
485 				Class<?> 	dataSource 	= (Class<?>)params[0];
486 				String	columnName	= (String)params[1];
487 
488 				tcManager.unregisterColumn(dataSource, columnName, (TableColumnCreationListener)params[2]);
489 
490 				String[] tables = tcManager.getTableIDs();
491 
492 				for ( String tid: tables ){
493 
494 					TableColumnCore col = tcManager.getTableColumnCore( tid, columnName );
495 
496 					if ( col != null ){
497 
498 						col.remove();
499 					}
500 				}
501 
502 				break;
503 			}
504 			case UIManagerEvent.ET_ADD_TABLE_CONTEXT_MENU_ITEM:{
505 				TableContextMenuItem	item = (TableContextMenuItem)data;
506 				TableContextMenuManager.getInstance().addContextMenuItem(item);
507 				break;
508 			}
509 			case UIManagerEvent.ET_ADD_MENU_ITEM: {
510 				MenuItem item = (MenuItem)data;
511 				MenuItemManager.getInstance().addMenuItem(item);
512 				break;
513 			}
514 			case UIManagerEvent.ET_REMOVE_TABLE_CONTEXT_MENU_ITEM:{
515 				TableContextMenuItem item = (TableContextMenuItem)data;
516 				TableContextMenuManager.getInstance().removeContextMenuItem(item);
517 				break;
518 			}
519 			case UIManagerEvent.ET_REMOVE_MENU_ITEM: {
520 				MenuItem item = (MenuItem)data;
521 				MenuItemManager.getInstance().removeMenuItem(item);
522 				break;
523 			}
524 			case UIManagerEvent.ET_SHOW_CONFIG_SECTION: {
525 				event.setResult(new Boolean(false));
526 
527 				if (!(data instanceof String)){
528 					break;
529 				}
530 
531 				event.setResult(Boolean.TRUE);
532 
533 				uiFunctions.getMDI().showEntryByID(
534 						MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG, data);
535 
536 				break;
537 			}
538 			case UIManagerEvent.ET_FILE_OPEN: {
539 				File file_to_use = (File)data;
540 				Utils.launch(file_to_use.getAbsolutePath());
541 				break;
542 			}
543 			case UIManagerEvent.ET_FILE_SHOW: {
544 				File file_to_use = (File)data;
545 				final boolean use_open_containing_folder = COConfigurationManager.getBooleanParameter("MyTorrentsView.menu.show_parent_folder_enabled");
546 				ManagerUtils.open(file_to_use, use_open_containing_folder);
547 				break;
548 			}
549 			case UIManagerEvent.ET_HIDE_ALL: {
550 				boolean hide = (Boolean)data;
551 
552 				uiFunctions.setHideAll( hide );
553 
554 				break;
555 			}
556 			default:
557 			{
558 				done	= false;
559 
560 				break;
561 			}
562 		}
563 
564 		return( done );
565 	}
566 
567 	public Display
getDisplay()568 	getDisplay()
569 	{
570 		return SWTThread.getInstance().getDisplay();
571 	}
572 
573 	public Image
loadImage( String resource )574 	loadImage(
575 		String	resource )
576 	{
577 		throw( new RuntimeException( "plugin specific instance required" ));
578 	}
579 
580 	public UISWTGraphic
createGraphic( Image img)581 	createGraphic(
582 		Image img)
583 	{
584 		return new UISWTGraphicImpl(img);
585 	}
586 
createShell(int style)587 	public Shell createShell(int style) {
588 		Shell shell = ShellFactory.createMainShell(style);
589 		Utils.setShellIcon(shell);
590 		return shell;
591 	}
592 
593 
594 	public void
detach()595 	detach()
596 
597 		throws UIException
598 	{
599 		throw( new UIException( "not supported" ));
600 	}
601 
602 
603 	/* (non-Javadoc)
604 	 * @see org.gudy.azureus2.ui.swt.plugins.UISWTInstance#addView(java.lang.String, java.lang.String, java.lang.Class, java.lang.Object)
605 	 */
addView(String sParentID, String sViewID, Class<? extends UISWTViewEventListener> cla, Object datasource)606 	public void addView(String sParentID, String sViewID,
607 			Class<? extends UISWTViewEventListener> cla, Object datasource) {
608 		addView(null, sParentID, sViewID, cla, datasource);
609 	}
610 
addView(PluginInterface pi, String sParentID, String sViewID, Class<? extends UISWTViewEventListener> cla, Object datasource)611 	public void addView(PluginInterface pi, String sParentID, String sViewID,
612 			Class<? extends UISWTViewEventListener> cla, Object datasource) {
613 
614 		UISWTViewEventListenerHolder _l = new UISWTViewEventListenerHolder(sViewID,
615 				cla, datasource, pi);
616 		addView( sParentID, sViewID, _l );
617 	}
618 
619 	/* (non-Javadoc)
620 	 * @see org.gudy.azureus2.ui.swt.plugins.UISWTInstance#addView(java.lang.String, java.lang.String, org.gudy.azureus2.ui.swt.plugins.UISWTViewEventListener)
621 	 */
addView(String sParentID, String sViewID, final UISWTViewEventListener l)622 	public void addView(String sParentID, String sViewID,
623 			final UISWTViewEventListener l) {
624 		UISWTViewEventListenerHolder _l = new UISWTViewEventListenerHolder(sViewID, l, null );
625 		addView( sParentID, sViewID, _l );
626 	}
627 
addView( String sParentID, final String sViewID, final UISWTViewEventListenerHolder holder)628 	public void addView( String sParentID,
629 			final String sViewID, final UISWTViewEventListenerHolder holder)
630 	{
631 		if (sParentID == null) {
632 			sParentID = UISWTInstance.VIEW_MAIN;
633 		}
634 		Map<String,UISWTViewEventListenerHolder> subViews = views.get(sParentID);
635 		if (subViews == null) {
636 			subViews = new LinkedHashMap<String,UISWTViewEventListenerHolder>();
637 			views.put(sParentID, subViews);
638 		}
639 
640 		subViews.put(sViewID, holder );
641 
642 		if (sParentID.equals(UISWTInstance.VIEW_MAIN)) {
643 			Utils.execSWTThread(new AERunnable() {
644 				public void runSupport() {
645 					try {
646 						uiFunctions.addPluginView(sViewID, holder );
647 					} catch (Throwable e) {
648 						// SWT not available prolly
649 					}
650 				}
651 			});
652 		}
653 
654 		SWTViewListener[] viewListeners = listSWTViewListeners.toArray(new SWTViewListener[0]);
655 		for (SWTViewListener l : viewListeners) {
656 			l.setViewAdded(sParentID, sViewID, holder);
657 		}
658 	}
659 
addSWTViewListener(SWTViewListener l)660 	public void addSWTViewListener(SWTViewListener l) {
661 		listSWTViewListeners.add(l);
662 	}
663 
removeSWTViewListener(SWTViewListener l)664 	public void removeSWTViewListener(SWTViewListener l) {
665 		listSWTViewListeners.remove(l);
666 	}
667 
668 	// TODO: Remove views from PeersView, etc
removeViews(String sParentID, final String sViewID)669 	public void removeViews(String sParentID, final String sViewID) {
670 		Map<String,UISWTViewEventListenerHolder> subViews = views.get(sParentID);
671 		if (subViews == null)
672 			return;
673 
674 		if (sParentID.equals(UISWTInstance.VIEW_MAIN)) {
675 			Utils.execSWTThread(new AERunnable() {
676 				public void runSupport() {
677 					try {
678 						if (uiFunctions != null) {
679 							uiFunctions.removePluginView(sViewID);
680 						}
681 					} catch (Throwable e) {
682 						// SWT not available prolly
683 					}
684 				}
685 			});
686 		}
687 
688 		SWTViewListener[] viewListeners = listSWTViewListeners.toArray(new SWTViewListener[0]);
689 		for (UISWTViewEventListener holder : subViews.values()) {
690   		for (SWTViewListener l : viewListeners) {
691   			l.setViewRemoved(sParentID, sViewID, holder);
692   		}
693 		}
694 
695 		subViews.remove(sViewID);
696 	}
697 
openView(final String sParentID, final String sViewID, final Object dataSource)698 	public boolean openView(final String sParentID, final String sViewID,
699 			final Object dataSource) {
700 		return openView(sParentID, sViewID, dataSource, true);
701 	}
702 
openView(final String sParentID, final String sViewID, final Object dataSource, final boolean setfocus)703 	public boolean openView(final String sParentID, final String sViewID,
704 			final Object dataSource, final boolean setfocus) {
705 		Map<String,UISWTViewEventListenerHolder> subViews = views.get(sParentID);
706 		if (subViews == null) {
707 			return false;
708 		}
709 
710 		final UISWTViewEventListenerHolder l = subViews.get(sViewID);
711 		if (l == null) {
712 			return false;
713 		}
714 
715 		Utils.execSWTThread(new AERunnable() {
716 			public void runSupport() {
717 				if (uiFunctions != null) {
718 					uiFunctions.openPluginView(
719 							sParentID, sViewID, l, dataSource,
720 							setfocus && !bUIAttaching);
721 				}
722 			}
723 		});
724 
725 		return true;
726 	}
727 
openMainView(final String sViewID, UISWTViewEventListener l, Object dataSource)728 	public void openMainView(final String sViewID,
729 			UISWTViewEventListener l, Object dataSource) {
730 		openMainView(null,sViewID, l, dataSource, true);
731 	}
732 
openMainView(PluginInterface pi, String sViewID, UISWTViewEventListener l, Object dataSource)733 	public void openMainView(PluginInterface pi, String sViewID,
734 			UISWTViewEventListener l, Object dataSource) {
735 		openMainView( pi, sViewID, l, dataSource, true);
736 	}
737 
openMainView(final String sViewID, final UISWTViewEventListener l, final Object dataSource, final boolean setfocus)738 	public void openMainView(final String sViewID,
739 			final UISWTViewEventListener l, final Object dataSource,
740 			final boolean setfocus) {
741 		openMainView( null, sViewID, l, dataSource, setfocus );
742 	}
openMainView(final PluginInterface pi, final String sViewID, final UISWTViewEventListener _l, final Object dataSource, final boolean setfocus)743 	public void openMainView(final PluginInterface pi, final String sViewID,
744 			final UISWTViewEventListener _l, final Object dataSource,
745 			final boolean setfocus) {
746 		Utils.execSWTThread(new AERunnable() {
747 			public void runSupport() {
748 				if (uiFunctions != null) {
749 					UISWTViewEventListenerHolder l = new UISWTViewEventListenerHolder(sViewID, _l, pi );
750 
751 					uiFunctions.openPluginView(UISWTInstance.VIEW_MAIN, sViewID, l, dataSource, setfocus && !bUIAttaching);
752 				}
753 			}
754 		});
755 	}
756 
getOpenViews(String sParentID)757 	public UISWTView[] getOpenViews(String sParentID) {
758 		if (sParentID.equals(UISWTInstance.VIEW_MAIN)) {
759 			try {
760 				if (uiFunctions != null) {
761 					return uiFunctions.getPluginViews();
762 				}
763 			} catch (Throwable e) {
764 				// SWT not available prolly
765 			}
766 		}
767 		return new UISWTView[0];
768 	}
769 
770 	// @see org.gudy.azureus2.plugins.ui.UIInstance#promptUser(java.lang.String, java.lang.String, java.lang.String[], int)
promptUser(String title, String text, String[] options, int defaultOption)771 	public int promptUser(String title, String text, String[] options,
772 			int defaultOption) {
773 
774 		MessageBoxShell mb = new MessageBoxShell(title, text, options,
775 				defaultOption);
776 		mb.open(null);
777 		// bah, no way to change this to use the UserPrompterResultListener trigger
778 		return mb.waitUntilClosed();
779 	}
780 
showDownloadBar(Download download, final boolean display)781 	public void showDownloadBar(Download download, final boolean display) {
782 		if (!(download instanceof DownloadImpl)) {return;}
783 		final DownloadManager dm = ((DownloadImpl)download).getDownload();
784 		if (dm == null) {return;} // Not expecting this, but just in case...
785 		Utils.execSWTThread(new AERunnable() {
786 			public void runSupport() {
787 				if (display) {
788 					DownloadBar.open(dm, getDisplay().getActiveShell());
789 				}
790 				else {
791 					DownloadBar.close(dm);
792 				}
793 			}
794 		}, false);
795 	}
796 
showTransfersBar(final boolean display)797 	public void showTransfersBar(final boolean display) {
798 		Utils.execSWTThread(new AERunnable() {
799 			public void runSupport() {
800 				if (display) {
801 					AllTransfersBar.open(getDisplay().getActiveShell());
802 				}
803 				else {
804 					AllTransfersBar.closeAllTransfersBar();
805 				}
806 			}
807 		}, false);
808 	}
809 
810 	// Core Functions
811 	// ==============
812 
getViewListeners(String sParentID)813 	public UISWTViewEventListenerHolder[] getViewListeners(String sParentID) {
814 		Map<String, UISWTViewEventListenerHolder> map = views.get(sParentID);
815 		if (map == null) {
816 			return new UISWTViewEventListenerHolder[0];
817 		}
818 		UISWTViewEventListenerHolder[] array = map.values().toArray(new UISWTViewEventListenerHolder[0]);
819 		Arrays.sort(array, new Comparator<UISWTViewEventListenerHolder>() {
820 			public int compare(UISWTViewEventListenerHolder o1,
821 					UISWTViewEventListenerHolder o2) {
822 				if ((o1.getPluginInterface() == null) && (o2.getPluginInterface() == null)) {
823 					return 0;
824 				}
825 				if ((o1.getPluginInterface() != null) && (o2.getPluginInterface() != null)) {
826 					return 0;
827 				}
828 				return o1.getPluginInterface() == null ? -1 : 1;
829 			}
830 		});
831 		return array;
832 	}
833 
834 	// @see org.gudy.azureus2.plugins.ui.UIInstance#getInputReceiver()
getInputReceiver()835 	public UIInputReceiver getInputReceiver() {
836 		return new SimpleTextEntryWindow();
837 	}
838 
839 	// @see org.gudy.azureus2.plugins.ui.UIInstance#createMessage()
createMessage()840 	public UIMessage createMessage() {
841 		return new UIMessageImpl();
842 	}
843 
createStatusEntry()844 	public UISWTStatusEntry createStatusEntry() {
845 		final UISWTStatusEntryImpl entry = new UISWTStatusEntryImpl();
846 		UIFunctionsSWT functionsSWT = UIFunctionsManagerSWT.getUIFunctionsSWT();
847 		if (functionsSWT == null) {
848 			Debug.outNoStack("No UIFunctionsSWT on createStatusEntry");
849 			return null;
850 		}
851 
852 		IMainStatusBar mainStatusBar = functionsSWT.getMainStatusBar();
853 		if (mainStatusBar == null) {
854 			Debug.outNoStack("No MainStatusBar on createStatusEntry");
855 			return null;
856 		}
857 		mainStatusBar.createStatusEntry(entry);
858 
859 		return entry;
860 	}
861 
openView(BasicPluginViewModel model)862 	public boolean openView(BasicPluginViewModel model) {
863 		return openView(VIEW_MAIN, model.getName().replaceAll(" ", "."), null);
864 	}
865 
openConfig(final BasicPluginConfigModel model)866 	public void openConfig(final BasicPluginConfigModel model) {
867 		Utils.execSWTThread(new Runnable() {
868 			public void run() {
869 				uiFunctions.getMDI().loadEntryByID(
870 						MultipleDocumentInterface.SIDEBAR_SECTION_CONFIG, true, false,
871 						model.getSection());
872 			}
873 		});
874 	}
875 
getToolBarManager()876 	public UIToolBarManager getToolBarManager() {
877 		throw( new RuntimeException( "plugin specific instance required" ));
878 	}
879 
880 	protected static class
881 	instanceWrapper
882 		implements UISWTInstance, UIToolBarManager
883 	{
884 		private WeakReference<PluginInterface>		pi_ref;
885 		private UIFunctionsSWT						ui_functions;
886 		private UISWTInstanceImpl					delegate;
887 
888 		private UIToolBarManagerCore 	toolBarManager;
889 		private List<UIToolBarItem> 	listItems			= new ArrayList<UIToolBarItem>();
890 		private List<Resource> 			listDisposeOnUnload = new ArrayList<Resource>();
891 
892 		protected
instanceWrapper( PluginInterface _pi, UIFunctionsSWT _ui_functions, UISWTInstanceImpl _delegate )893 		instanceWrapper(
894 			PluginInterface			_pi,
895 			UIFunctionsSWT			_ui_functions,
896 			UISWTInstanceImpl		_delegate )
897 		{
898 			pi_ref			= new WeakReference<PluginInterface>(_pi );
899 			ui_functions	= _ui_functions;
900 			delegate		= _delegate;
901 		}
902 
getToolBarItem(String id)903 		public UIToolBarItem getToolBarItem(String id) {
904 			return toolBarManager.getToolBarItem(id);
905 		}
906 
getAllToolBarItems()907 		public UIToolBarItem[] getAllToolBarItems() {
908 			return toolBarManager.getAllToolBarItems();
909 		}
910 
911 		public UIToolBarItem
createToolBarItem( String id )912 		createToolBarItem(
913 			String id )
914 		{
915 			UIToolBarItem addToolBarItem = toolBarManager.createToolBarItem( id );
916 
917 			synchronized( this ){
918 
919 				listItems.add( addToolBarItem );
920 			}
921 
922 			return addToolBarItem;
923 		}
924 
addToolBarItem(UIToolBarItem item)925 		public void addToolBarItem(UIToolBarItem item) {
926 			toolBarManager.addToolBarItem(item);
927 		}
928 
removeToolBarItem(String id)929 		public void removeToolBarItem(String id) {
930 			toolBarManager.removeToolBarItem(id);
931 		}
932 
933 		public void
detach()934 		detach()
935 
936 			throws UIException
937 		{
938 			delegate.detach();
939 		}
940 
941 		public int
getUIType()942 		getUIType()
943 		{
944 			return( delegate.getUIType());
945 		}
946 
947 		public Display
getDisplay()948 		getDisplay()
949 		{
950 			return( delegate.getDisplay());
951 		}
952 
953 		public Image
loadImage( String resource )954 		loadImage(
955 			String	resource )
956 		{
957 			PluginInterface pi = pi_ref.get();
958 
959 			if ( pi == null ){
960 
961 				return( null );
962 			}
963 
964 			InputStream is = pi.getPluginClassLoader().getResourceAsStream( resource);
965 
966 			if ( is != null ){
967 
968 				ImageData imageData = new ImageData(is);
969 
970 				try {
971 					is.close();
972 				} catch (IOException e) {
973 					Debug.out(e);
974 				}
975 
976 				Display display = getDisplay();
977 
978 				Image image = new Image(display, imageData);
979 
980 				image = Utils.adjustPXForDPI( display,  image );
981 
982 				listDisposeOnUnload.add(image);
983 
984 				return image;
985 			}
986 
987 			return null;
988 		}
989 
990 		public UISWTGraphic
createGraphic( Image img )991 		createGraphic(
992 			Image img )
993 		{
994 			return( delegate.createGraphic( img ));
995 		}
996 
997 		public void
addView(String sParentID, String sViewID, UISWTViewEventListener l)998 		addView(String sParentID, String sViewID, UISWTViewEventListener l)
999 		{
1000 			PluginInterface pi = pi_ref.get();
1001 
1002 			delegate.addView( sParentID, sViewID, new UISWTViewEventListenerHolder(sViewID, l, pi) );
1003 		}
1004 
addView(String sParentID, String sViewID, Class<? extends UISWTViewEventListener> cla, Object datasource)1005 		public void addView(String sParentID, String sViewID,
1006 				Class<? extends UISWTViewEventListener> cla, Object datasource) {
1007 			PluginInterface pi = pi_ref.get();
1008 
1009 			delegate.addView(sParentID, sViewID, new UISWTViewEventListenerHolder(sViewID,
1010 					cla, datasource, pi));
1011 		}
1012 
1013 		public void
openMainView(String sViewID, UISWTViewEventListener l,Object dataSource)1014 		openMainView(String sViewID, UISWTViewEventListener l,Object dataSource)
1015 		{
1016 			PluginInterface pi = pi_ref.get();
1017 
1018 			delegate.openMainView( pi, sViewID, l, dataSource );
1019 		}
1020 
1021 		public void
openMainView(String sViewID, UISWTViewEventListener l,Object dataSource, boolean setfocus)1022 		openMainView(String sViewID, UISWTViewEventListener l,Object dataSource, boolean setfocus)
1023 		{
1024 			PluginInterface pi = pi_ref.get();
1025 
1026 			delegate.openMainView( pi, sViewID, l, dataSource, setfocus );
1027 		}
1028 
1029 
1030 		public void
removeViews(String sParentID, String sViewID)1031 		removeViews(String sParentID, String sViewID)
1032 		{
1033 			delegate.removeViews(sParentID, sViewID );
1034 		}
1035 
1036 
1037 		public UISWTView[]
getOpenViews(String sParentID)1038 		getOpenViews(String sParentID)
1039 		{
1040 			return( delegate.getOpenViews(sParentID));
1041 		}
1042 
promptUser(String title, String text, String[] options, int defaultOption)1043 		public int promptUser(String title, String text, String[] options,
1044 				int defaultOption) {
1045 			return delegate.promptUser(title, text, options, defaultOption);
1046 		}
1047 
openView(String sParentID, String sViewID, Object dataSource)1048 		public boolean openView(String sParentID, String sViewID, Object dataSource) {
1049 			return delegate.openView(sParentID, sViewID, dataSource);
1050 		}
1051 
openView(String sParentID, String sViewID, Object dataSource, boolean setfocus)1052 		public boolean openView(String sParentID, String sViewID, Object dataSource, boolean setfocus) {
1053 			return delegate.openView(sParentID, sViewID, dataSource, setfocus);
1054 		}
1055 
getViewListeners(String sParentId)1056 		public UISWTViewEventListenerWrapper[] getViewListeners(String sParentId) {
1057 			return delegate.getViewListeners(sParentId);
1058 		}
getInputReceiver()1059 		public UIInputReceiver getInputReceiver() {
1060 			return delegate.getInputReceiver();
1061 		}
1062 
createMessage()1063 		public UIMessage createMessage() {
1064 			return delegate.createMessage();
1065 		}
1066 
showDownloadBar(Download download, boolean display)1067 		public void showDownloadBar(Download download, boolean display) {
1068 			delegate.showDownloadBar(download, display);
1069 		}
1070 
showTransfersBar(boolean display)1071 		public void showTransfersBar(boolean display) {
1072 			delegate.showTransfersBar(display);
1073 		}
1074 
createStatusEntry()1075 		public UISWTStatusEntry createStatusEntry() {
1076 			return delegate.createStatusEntry();
1077 		}
1078 
openView(BasicPluginViewModel model)1079 		public boolean openView(BasicPluginViewModel model) {
1080 			return delegate.openView(model);
1081 		}
1082 
openConfig(BasicPluginConfigModel model)1083 		public void openConfig(BasicPluginConfigModel model) {
1084 			delegate.openConfig(model);
1085 		}
1086 
createShell(int style)1087 		public Shell createShell(int style) {
1088 			return delegate.createShell(style);
1089 		}
1090 
1091 		public UIToolBarManager
getToolBarManager()1092 		getToolBarManager()
1093 		{
1094 			if ( toolBarManager == null ){
1095 
1096 				UIToolBarManager tbm = ui_functions.getToolBarManager();
1097 
1098 				if ( tbm instanceof UIToolBarManagerCore ){
1099 
1100 					toolBarManager = (UIToolBarManagerCore)tbm;
1101 
1102 				}else{
1103 
1104 					return( null );
1105 				}
1106 			}
1107 
1108 			return( this );
1109 		}
1110 
1111 		public void
unload( PluginInterface pi )1112 		unload(
1113 			PluginInterface pi )
1114 		{
1115 			if ( toolBarManager != null ){
1116 
1117 				synchronized( this ){
1118 
1119 					for (UIToolBarItem item : listItems) {
1120 
1121 						toolBarManager.removeToolBarItem(item.getID());
1122 					}
1123 
1124 					listItems.clear();
1125 				}
1126 			}
1127 
1128 			Utils.disposeSWTObjects(listDisposeOnUnload);
1129 
1130 			listDisposeOnUnload.clear();
1131 		}
1132 	}
1133 
1134 	public void
unload( PluginInterface pi )1135 	unload(
1136 		PluginInterface pi )
1137 	{
1138 		throw( new RuntimeException( "plugin specific instance required" ));
1139 	}
1140 }
1141