/*
 * Copyright (C) Azureus Software, Inc, All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details ( see the LICENSE file ).
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.gudy.azureus2.ui.swt.views.table.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.gudy.azureus2.core3.config.COConfigurationManager;
import org.gudy.azureus2.core3.config.ParameterListener;
import org.gudy.azureus2.core3.config.impl.ConfigurationManager;
import org.gudy.azureus2.core3.download.DownloadManager;
import org.gudy.azureus2.core3.internat.MessageText;
import org.gudy.azureus2.core3.util.Constants;
import org.gudy.azureus2.core3.util.Debug;
import org.gudy.azureus2.core3.util.IndentWriter;
import org.gudy.azureus2.plugins.download.Download;
import org.gudy.azureus2.pluginsimpl.local.PluginCoreUtils;
import org.gudy.azureus2.ui.swt.Messages;
import org.gudy.azureus2.ui.swt.Utils;
import org.gudy.azureus2.ui.swt.plugins.UISWTInstance;
import org.gudy.azureus2.ui.swt.plugins.UISWTView;
import org.gudy.azureus2.ui.swt.plugins.UISWTViewEvent;
import org.gudy.azureus2.ui.swt.plugins.UISWTInstance.UISWTViewEventListenerWrapper;
import org.gudy.azureus2.ui.swt.pluginsimpl.*;
import org.gudy.azureus2.ui.swt.views.table.TableViewSWT;

import com.aelitis.azureus.ui.UIFunctions;
import com.aelitis.azureus.ui.UIFunctionsManager;
import com.aelitis.azureus.ui.swt.UIFunctionsManagerSWT;
import com.aelitis.azureus.ui.swt.UIFunctionsSWT;

/**
 * 
 * @author TuxPaper
 *
 * @TODO dynamically load tab contents, like SBC_TorrentDetailsView does
 */
public class TableViewSWT_TabsCommon
{
	private static final Object	NULL_DS = new Object();
	
	UISWTView parentView;
	TableViewSWT<?> tv;
	
		/** TabViews */
	private ArrayList<UISWTViewCore> 					tabViews 		= new ArrayList<UISWTViewCore>(1);

	private ArrayList<UISWTViewEventListenerWrapper>	removedViews 	= new ArrayList<UISWTViewEventListenerWrapper>();
	
	/** TabViews */
	private CTabFolder 			tabFolder;
	
	/** Composite that stores the table (sometimes the same as mainComposite) */
	public Composite tableComposite;

	private boolean minimized;
	private UISWTViewCore selectedView;

	private DownloadManager		maximizeTo;
	
	public TableViewSWT_TabsCommon(UISWTView parentView, TableViewSWT<?> tv) {
		this.parentView = parentView;
		this.tv = tv;
	}

	public void triggerTabViewsDataSourceChanged(boolean sendParent) {
		if (tabViews == null || tabViews.size() == 0) {
			return;
		}
		
		if (sendParent) {
			for (int i = 0; i < tabViews.size(); i++) {
				UISWTViewCore view = tabViews.get(i);
				if (view != null) {
					dataSourceChanged( view, tv.getParentDataSource());
				}
			}
			return;
		}

		// Set Data Object for all tabs.  

		Object[] dataSourcesCore = tv.getSelectedDataSources(true);
		Object[] dataSourcesPlugin = null;

		for (int i = 0; i < tabViews.size(); i++) {
			UISWTViewCore view = tabViews.get(i);
			if (view != null) {
				if (view.useCoreDataSource()) {
					dataSourceChanged( view, dataSourcesCore.length == 0 ? tv.getParentDataSource()	: dataSourcesCore);
				} else {
					if (dataSourcesPlugin == null) {
						dataSourcesPlugin = tv.getSelectedDataSources(false);
					}

					dataSourceChanged( 
						view,
						dataSourcesPlugin.length == 0 ? PluginCoreUtils.convert( tv.getParentDataSource(), false) : dataSourcesPlugin);
				}
			}
		}
	}

	public void triggerTabViewsDataSourceChanged(TableViewSWT<?> tv) {
		if (tabViews == null || tabViews.size() == 0) {
			return;
		}

		// Set Data Object for all tabs.  

		Object[] dataSourcesCore = tv.getSelectedDataSources(true);
		Object[] dataSourcesPlugin = null;

		for (int i = 0; i < tabViews.size(); i++) {
			UISWTViewCore view = tabViews.get(i);
			if (view != null) {
				if (view.useCoreDataSource()) {
					dataSourceChanged( 
							view,
							dataSourcesCore.length == 0 ? tv.getParentDataSource()
									: dataSourcesCore);
				} else {
					if (dataSourcesPlugin == null) {
						dataSourcesPlugin = tv.getSelectedDataSources(false);
					}

					dataSourceChanged( 
							view,
							dataSourcesPlugin.length == 0 ? PluginCoreUtils.convert(
									tv.getParentDataSource(), false) : dataSourcesPlugin);
				}
			}
		}
	}
	
	public void triggerTabViewDataSourceChanged(UISWTViewCore view) {
		if (view != null) {
			dataSourceChanged( view, tv.getParentDataSource());

			if (view.useCoreDataSource()) {
				Object[] dataSourcesCore = tv.getSelectedDataSources(true);
				if (dataSourcesCore.length > 0) {
					dataSourceChanged( 
						view,
						dataSourcesCore.length == 0 ? tv.getParentDataSource()
									: dataSourcesCore);
				}
			} else {
				Object[] dataSourcesPlugin = tv.getSelectedDataSources(false);
				if (dataSourcesPlugin.length > 0) {
					dataSourceChanged( 
						view,
						dataSourcesPlugin.length == 0 ? PluginCoreUtils.convert(
									tv.getParentDataSource(), false) : dataSourcesPlugin);
				}
			}
		}
		
	}

	public void delete() {
		if (tabViews != null && tabViews.size() > 0) {
			for (int i = 0; i < tabViews.size(); i++) {
				UISWTViewCore view = tabViews.get(i);
				if (view != null) {
					view.triggerEvent(UISWTViewEvent.TYPE_DESTROY, null);
				}
			}
		}
	}

	public void generate(IndentWriter writer) {
		writer.println("# of SubViews: " + tabViews.size());
		writer.indent();
		try {
			for (Iterator<UISWTViewCore> iter = tabViews.iterator(); iter.hasNext();) {
				UISWTViewCore view = iter.next();
				writer.println(view.getTitleID() + ": " + view.getFullTitle());
			}
		} finally {
			writer.exdent();
		}
	}

	public void localeChanged() {
		if (tabViews != null && tabViews.size() > 0) {
			for (int i = 0; i < tabViews.size(); i++) {
				UISWTViewCore view = tabViews.get(i);
				if (view != null) {
					view.triggerEvent(UISWTViewEvent.TYPE_LANGUAGEUPDATE, null);
				}
			}
		}
	}

	public UISWTViewCore getActiveSubView() {
		if (!tv.isTabViewsEnabled() || tabFolder == null || tabFolder.isDisposed()
				|| minimized) {
			return null;
		}

		return selectedView;
	}

	private void
	dataSourceChanged(
		final UISWTViewCore			view,
		final Object				ds )
	{
		Composite comp = view.getComposite();
		
		if ( comp == null || comp.isDisposed()){
			
			return;
		}
		
		Utils.execSWTThread(
			new Runnable()
			{	
				public void 
				run() 
				{
					Composite comp = view.getComposite();
					
					if ( comp == null || comp.isDisposed()){
						
						return;
					}
										
					if ( ds instanceof Object[]){
						Object[] temp = (Object[])ds;
						if ( temp.length==1 ){
							Object obj = temp[0];
							
							if ( obj instanceof DownloadManager ){
								maximizeTo = (DownloadManager)obj;
							}else if ( obj instanceof Download ){
								maximizeTo = PluginCoreUtils.unwrap((Download)obj);
							}
						}
					}

					tabFolder.setMaximizeVisible( maximizeTo != null );
					
					if ( comp.isVisible()){
					
						Object old_ds = view.getUserData( TableViewSWT_TabsCommon.class );
						
						if ( old_ds != null ){
							
							view.setUserData( TableViewSWT_TabsCommon.class, null );
						}
						
						view.triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, ds);
						
					}else{
						
						view.setUserData( TableViewSWT_TabsCommon.class, ds==null?NULL_DS:ds );
					}
				}
			});
	}
	
	private void
	checkPendingDataSourceChange(
		UISWTViewCore		view )
	{
		Object ds = view.getUserData( TableViewSWT_TabsCommon.class );
		
		if ( ds != null ){
			
			if ( ds == NULL_DS ){
				
				ds = null;
			}
						
			view.setUserData( TableViewSWT_TabsCommon.class, null );
			
			view.triggerEvent(UISWTViewEvent.TYPE_DATASOURCE_CHANGED, ds);
		}
	}
	
	public void 
	refreshSelectedSubView()
	{
		UISWTViewCore view = getActiveSubView();
		
		if ( view != null && view.getComposite().isVisible()){
			
			checkPendingDataSourceChange( view );
			
			view.triggerEvent(UISWTViewEvent.TYPE_REFRESH, null);
		}
	}

	private String
	getViewTitleID(
		String	view_id )
	{
		String history_key = "swt.ui.table.tab.view.namecache." + view_id;

		String id = COConfigurationManager.getStringParameter( history_key, "" );

		if ( id.length() == 0 ){
			
			String test = view_id + ".title.full";
			
			if ( MessageText.keyExists( test )){
			
				return( test );
			}
			
			id = "!" + view_id + "!";
		}
		
		return( id );
	}

		// TabViews Functions
	
	private void 
	addTabView(
		UISWTViewEventListenerWrapper 	listener,
		boolean							start_of_day,
		boolean							start_minimized )
	{
		if ( tabFolder == null){
			
			return;
		}
				
		String view_id = listener.getViewID();
		
		try{
			UISWTViewImpl view = new UISWTViewImpl(tv.getTableID(), view_id, listener, null);
			
			if ( parentView != null ){	
				view.setParentView( parentView );
			}
			
			triggerTabViewDataSourceChanged(view);
	
			int	insert_at = tabFolder.getItemCount();
			
			if ( !start_of_day && insert_at > 0 ){
				
				UIFunctionsSWT ui_func  = UIFunctionsManagerSWT.getUIFunctionsSWT();
				
				if ( ui_func != null ){
					
					UISWTInstance ui_swt = ui_func.getUISWTInstance();

					if ( ui_swt != null ){
						
						ArrayList<UISWTViewEventListenerWrapper> listeners = new ArrayList<UISWTViewEventListenerWrapper>( Arrays.asList( ui_swt.getViewListeners(tv.getTableID())));
					
						int	l_index = listeners.indexOf( listener );
						
						CTabItem[] items = tabFolder.getItems();
													
						for ( int j=0;j<items.length;j++){
									
							UISWTViewImpl v = (UISWTViewImpl)items[j].getData( "IView" );
									
							if ( v != null ){
										
								int v_index = listeners.indexOf( v.getEventListener());
							
								if ( v_index > l_index ){
									
									insert_at = j;
									
									break;
								}
							}
						}
					}
				}
			}
			
			CTabItem item = new CTabItem( tabFolder, SWT.NULL, insert_at );
			
			boolean	is_minimized;
			
			if ( start_of_day ){
				
				is_minimized = start_minimized;
				
			}else{
				
				is_minimized = tabFolder.getMinimized();
			}
						
			item.setToolTipText( MessageText.getString( is_minimized?"label.click.to.restore":"label.dblclick.to.min"));
			
			item.setData("IView", view);
			
			String title_id = view.getTitleID();
			
			String history_key = "swt.ui.table.tab.view.namecache." + view_id;
			
			String existing = COConfigurationManager.getStringParameter( history_key, "" );
			
			if ( !existing.equals( title_id )){
				
				COConfigurationManager.setParameter( history_key, title_id );
			}
			
			Messages.setLanguageText(item, title_id );
			
			view.initialize(tabFolder);
			
			item.setControl(view.getComposite());
			
			tabViews.add(view);
			
			if ( !start_of_day ){
				
				removedViews.remove( listener );
				
				tabFolder.setSelection(item);
				selectedView = (UISWTViewImpl)item.getData( "IView" );
			}

		}catch( Throwable e ){
			
			Debug.out( e );
		}
	}
	
	private void
	checkTabViews(
		Map		closed )
	{
		for ( UISWTViewEventListenerWrapper l: new ArrayList<UISWTViewEventListenerWrapper>( removedViews )){
			
			String view_id = l.getViewID();
			
			if ( !closed.containsKey( view_id )){
				
				addTabView( l, false, false );
			}
		}
		
		for ( CTabItem item: tabFolder.getItems()){
			
			UISWTViewImpl view = (UISWTViewImpl)item.getData( "IView" );
			
			if ( view != null ){
				
				String view_id = view.getViewID();
				
				if ( closed.containsKey( view_id )){
					
					removeTabView( item );
				}
			}
		}
	}
	
	private void
	removeTabView(
		CTabItem		item )
	{
		UISWTViewImpl view = (UISWTViewImpl)item.getData( "IView" );
		
		if ( view != null ){
						
			removedViews.add((UISWTViewEventListenerWrapper)view.getEventListener());
			
			tabViews.remove( view );
			
			view.triggerEvent(UISWTViewEvent.TYPE_DESTROY, null);
		
			item.dispose();
		}
	}

	public Composite createSashForm(final Composite composite) {
		if (!tv.isTabViewsEnabled()) {
			tableComposite = tv.createMainPanel(composite);
			return tableComposite;
		}

		ConfigurationManager configMan = ConfigurationManager.getInstance();
		
		int iNumViews = 0;

		UIFunctionsSWT uiFunctions = UIFunctionsManagerSWT.getUIFunctionsSWT();
		UISWTViewEventListenerWrapper[] pluginViews = null;
		if (uiFunctions != null) {
			UISWTInstance pluginUI = uiFunctions.getUISWTInstance();

			if (pluginUI != null) {
				pluginViews = pluginUI.getViewListeners(tv.getTableID());
				iNumViews += pluginViews.length;
			}
		}

		if (iNumViews == 0) {
			tableComposite = tv.createMainPanel(composite);
			return tableComposite;
		}

		final String	props_prefix = tv.getTableID() + "." + tv.getPropertiesPrefix();
		
		FormData formData;

		final Composite form = new Composite(composite, SWT.NONE);
		FormLayout flayout = new FormLayout();
		flayout.marginHeight = 0;
		flayout.marginWidth = 0;
		form.setLayout(flayout);
		GridData gridData;
		gridData = new GridData(GridData.FILL_BOTH);
		form.setLayoutData(gridData);

		// Create them in reverse order, so we can have the table auto-grow, and
		// set the tabFolder's height manually

		final int TABHEIGHT = 22;
		tabFolder = new CTabFolder(form, SWT.TOP | SWT.BORDER);
		tabFolder.setMinimizeVisible(true);
		tabFolder.setTabHeight(TABHEIGHT);
		final int iFolderHeightAdj = tabFolder.computeSize(SWT.DEFAULT, 0).y;

		final int SASH_WIDTH = 5;
		
		final Sash sash = Utils.createSash( form, SASH_WIDTH );

		tableComposite = tv.createMainPanel(form);
		Composite cFixLayout = tableComposite;
		while (cFixLayout != null && cFixLayout.getParent() != form) {
			cFixLayout = cFixLayout.getParent();
		}
		if (cFixLayout == null) {
			cFixLayout = tableComposite;
		}
		GridLayout layout = new GridLayout();
		layout.numColumns = 1;
		layout.horizontalSpacing = 0;
		layout.verticalSpacing = 0;
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		cFixLayout.setLayout(layout);

		// FormData for Folder
		formData = new FormData();
		formData.left = new FormAttachment(0, 0);
		formData.right = new FormAttachment(100, 0);
		formData.bottom = new FormAttachment(100, 0);
		int iSplitAt = configMan.getIntParameter(props_prefix + ".SplitAt",
				3000);
		// Was stored at whole
		if (iSplitAt < 100) {
			iSplitAt *= 100;
		}

		double pct = iSplitAt / 10000.0;
		if (pct < 0.03) {
			pct = 0.03;
		} else if (pct > 0.97) {
			pct = 0.97;
		}

		// height will be set on first resize call
		sash.setData("PCT", new Double(pct));
		tabFolder.setLayoutData(formData);
		final FormData tabFolderData = formData;

		// FormData for Sash
		formData = new FormData();
		formData.left = new FormAttachment(0, 0);
		formData.right = new FormAttachment(100, 0);
		formData.bottom = new FormAttachment(tabFolder);
		formData.height = SASH_WIDTH;
		sash.setLayoutData(formData);

		// FormData for table Composite
		formData = new FormData();
		formData.left = new FormAttachment(0, 0);
		formData.right = new FormAttachment(100, 0);
		formData.top = new FormAttachment(0, 0);
		formData.bottom = new FormAttachment(sash);
		cFixLayout.setLayoutData(formData);


		final CTabFolder2Adapter folderListener = new CTabFolder2Adapter() {
			public void minimize(CTabFolderEvent event) {
				minimized = true;
				
				tabFolder.setMinimized(true);
				tabFolderData.height = iFolderHeightAdj;
				CTabItem[] items = tabFolder.getItems();
				String tt = MessageText.getString( "label.click.to.restore" );
				for (int i = 0; i < items.length; i++) {
					CTabItem tabItem = items[i];
					tabItem.setToolTipText( tt );
					tabItem.getControl().setVisible(false);
				}
				form.layout();

				UISWTViewCore view = getActiveSubView();
				
				fireFocusLost( view );	// fire even if null so we pick up current...
				
				ConfigurationManager configMan = ConfigurationManager.getInstance();
				configMan.setParameter(props_prefix + ".subViews.minimized", true);
			}
			public void maximize(CTabFolderEvent event){
				if ( maximizeTo != null){

					UIFunctions uiFunctions = UIFunctionsManager.getUIFunctions();
					
					if ( uiFunctions != null ){					
				
						uiFunctions.openView(UIFunctions.VIEW_DM_DETAILS, maximizeTo );
					}
				}	
			}
			
			public void restore(CTabFolderEvent event_maybe_null ) {
				minimized = false;
				tabFolder.setMinimized(false);
				CTabItem selection = tabFolder.getSelection();
				if (selection != null) {
					selection.getControl().setVisible(true);
				}
				
				CTabItem[] items = tabFolder.getItems();
				String tt = MessageText.getString( "label.dblclick.to.min"  );
				
				for (int i = 0; i < items.length; i++) {
					CTabItem tabItem = items[i];
					tabItem.setToolTipText( tt );
				}
				
				form.notifyListeners(SWT.Resize, null);

				UISWTViewCore view = getActiveSubView();
				if (view != null) {
					fireFocusGained( view );
				}
				refreshSelectedSubView();

				ConfigurationManager configMan = ConfigurationManager.getInstance();
				configMan.setParameter(props_prefix + ".subViews.minimized", false);
				
				tabFolder.setToolTipText( "max" );
			}

		};
		
		// Listeners to size the folder
		sash.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				final boolean FASTDRAG = true;

				if (FASTDRAG && e.detail == SWT.DRAG) {
					return;
				}

				if (tabFolder.getMinimized()) {
					folderListener.restore( null );
				}

				Rectangle area = form.getClientArea();
				
				int height = area.height - e.y - e.height - iFolderHeightAdj;
				
				if ( !Constants.isWindows ){
					height -= SASH_WIDTH;
				}
				
					// prevent sash from being dragged too far up. In the worst case it ends up 
					// overlaying the split my-torrents sash and the user can't easily separate the two...
				
				if ( area.height - height < 100 ){
					height = area.height - 100;
				}
				
				if ( height < 0 ){
					height = 0;
				}
				
				tabFolderData.height = height;
				form.layout();

				Double l = new Double((double) tabFolder.getBounds().height
						/ form.getBounds().height);
				sash.setData("PCT", l);
				if (e.detail != SWT.DRAG) {
					ConfigurationManager configMan = ConfigurationManager.getInstance();
					configMan.setParameter(props_prefix + ".SplitAt",
							(int) (l.doubleValue() * 10000));
				}
			}
		});
		
		tabFolder.addCTabFolder2Listener(folderListener);

		tabFolder.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				selectedView = null;
				// make sure its above
				try {
					((CTabItem) e.item).getControl().setVisible(true);
					((CTabItem) e.item).getControl().moveAbove(null);

					selectedView = (UISWTViewImpl)e.item.getData( "IView" );
					// Call getActiveSubView and don't use selectedView. Function
					// may return null even if there's a selectedView
					UISWTViewCore view = getActiveSubView();
					if (view != null) {
						fireFocusGained( view );
					}
					
				} catch (Exception t) {
				}
			}

			public void widgetDefaultSelected(SelectionEvent e) {
			}
		});

		tabFolder.addMouseListener(new MouseAdapter() {
			public void mouseDown(MouseEvent e) {
				if (tabFolder.getMinimized()) {
					folderListener.restore(null);
					// If the user clicked down on the restore button, and we restore
					// before the CTabFolder does, CTabFolder will minimize us again
					// There's no way that I know of to determine if the mouse is 
					// on that button!

					// one of these will tell tabFolder to cancel
					e.button = 0;
					tabFolder.notifyListeners(SWT.MouseExit, null);
				}
			}
			public void mouseDoubleClick(MouseEvent e) {
				if (!tabFolder.getMinimized()) {
					folderListener.minimize( null );
				}
			}
		});

		final Menu menu = new Menu( tabFolder );
		
		tabFolder.addListener(SWT.MenuDetect, new Listener() {
			public void handleEvent(Event event) {
				
				for ( MenuItem item: menu.getItems()){
					
					item.dispose();
				}
												
				final CTabItem item = tabFolder.getItem( tabFolder.toControl( event.x, event.y ));
				
				boolean	need_sep = false;
				
				if ( item != null ){
					
					tabFolder.setSelection(item);
					selectedView = (UISWTViewImpl)item.getData( "IView" );
						
					if ( selectedView != null ){
						
						final String view_id = selectedView.getViewID();
						
						MenuItem mi = new MenuItem( menu, SWT.PUSH );
						
						mi.setText( MessageText.getString( "label.close.tab" ));
						
						mi.addListener(
							SWT.Selection,
							new Listener()
							{
								public void 
								handleEvent(
									Event event ) 
								{
									String key = props_prefix + ".closedtabs";
									
									Map closedtabs = COConfigurationManager.getMapParameter(key, new HashMap());
									
									if ( !closedtabs.containsKey( view_id )){
										
										closedtabs.put( view_id, "" );
										
										COConfigurationManager.setParameter( key, closedtabs );
									}
								}
							});
						
						need_sep = true;
					}
				}else{
					
					for ( final UISWTViewEventListenerWrapper l: removedViews ){
						
						need_sep = true;
						
						final String view_id = l.getViewID();
						
						MenuItem mi = new MenuItem( menu, SWT.PUSH );
						
						mi.setText( MessageText.getString( getViewTitleID( view_id )));
						
						mi.addListener(
							SWT.Selection,
							new Listener()
							{
								public void 
								handleEvent(
									Event event ) 
								{
									String key = props_prefix + ".closedtabs";
									
									Map closedtabs = COConfigurationManager.getMapParameter(key, new HashMap());
									
									if ( closedtabs.containsKey( view_id )){
									
										closedtabs.remove( view_id );
									
										COConfigurationManager.setParameter( key, closedtabs );
									}
								}
							});
					}
				}
				
				if ( need_sep ){
				
					new MenuItem( menu, SWT.SEPARATOR );
				}
				
				final MenuItem mi = new MenuItem( menu, SWT.CHECK );
				
				mi.setSelection( COConfigurationManager.getBooleanParameter( "Library.ShowTabsInTorrentView"));
				
				mi.setText( MessageText.getString( "ConfigView.section.style.ShowTabsInTorrentView" ));
				
				mi.addListener(
					SWT.Selection,
					new Listener()
					{
						public void 
						handleEvent(
							Event event ) 
						{
							COConfigurationManager.setParameter( "Library.ShowTabsInTorrentView", mi.getSelection());
						}
					});
				
				menu.setVisible(true);

			}
		});
		
		form.addListener(SWT.Resize, new Listener() {
			public void handleEvent(Event e) {
				if (tabFolder.getMinimized()) {
					return;
				}

				Double l = (Double) sash.getData("PCT");
				if (l != null) {
					tabFolderData.height = (int) (form.getBounds().height * l.doubleValue())
							- iFolderHeightAdj;
					form.layout();
				}
			}
		});

		String key = props_prefix + ".closedtabs";
		
		Map closed_tabs = COConfigurationManager.getMapParameter(key, new HashMap());

		COConfigurationManager.addParameterListener(
			key,
			new ParameterListener()
			{
				public void 
				parameterChanged(
					String	name )
				{
					if ( tabFolder.isDisposed()){
						
						COConfigurationManager.removeParameterListener( name, this );
						
					}else{
						
						checkTabViews( COConfigurationManager.getMapParameter(name, new HashMap()));
					}
				}
			});
		
		String[] restricted_to = tv.getTabViewsRestrictedTo();
		
		Set<String> rt_set = new HashSet<String>();
		
		if ( restricted_to != null ){
			
			rt_set.addAll( Arrays.asList( restricted_to ));
		}
		
		boolean folder_minimized = 
			configMan.getBooleanParameter( props_prefix + ".subViews.minimized", !tv.getTabViewsExpandedByDefault());
		
		// Call plugin listeners
		
		if (pluginViews != null) {
			for (UISWTViewEventListenerWrapper l : pluginViews) {
				if (l != null) {
					try {
						String view_id = l.getViewID();
						
						if ( restricted_to == null || rt_set.contains( view_id )){
						
							if ( closed_tabs.containsKey( view_id )){
								
								removedViews.add( l );
								
							}else{
								
								addTabView( l, true, folder_minimized );
							}
						}
					} catch (Exception e) {
						// skip, plugin probably specifically asked to not be added
					}
				}
			}
		}

		if ( folder_minimized ){
			
			tabFolder.setMinimized(true);
			
			tabFolderData.height = iFolderHeightAdj;
			
		}else{
			
			tabFolder.setMinimized(false);
		}

		if (tabFolder.getItemCount() > 0) {
			CTabItem item = tabFolder.getItem(0);
			tabFolder.setSelection(item);
			selectedView = (UISWTViewImpl)item.getData( "IView" );
		}

		return form;
	}

	private UISWTViewCore	focused_view = null;
	
	private void
	fireFocusGained(
		UISWTViewCore		view )
	{
		if ( focused_view != null ){
			
			focused_view.triggerEvent(UISWTViewEvent.TYPE_FOCUSLOST, null);
		}
		
		focused_view = view;
		
		checkPendingDataSourceChange( view );
		
		view.triggerEvent(UISWTViewEvent.TYPE_FOCUSGAINED, null);
	}
	
	private void
	fireFocusLost(
		UISWTViewCore		view )
	{
		if ( focused_view != null && focused_view != view ){
			
			focused_view.triggerEvent(UISWTViewEvent.TYPE_FOCUSLOST, null);
		}
		
		focused_view = null;
		
		if ( view != null ){
		
			view.triggerEvent(UISWTViewEvent.TYPE_FOCUSLOST, null);
		}
	}
	
	public void swt_refresh() {
		if (tv.isTabViewsEnabled() && tabFolder != null && !tabFolder.isDisposed()
				&& !tabFolder.getMinimized()){
			
			refreshSelectedSubView();
		}
	}
}
