/*******************************************************************************
 * Copyright (c) 2003, 2011 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Initial Contributors:
 * The following IBM employees contributed to the Remote System Explorer
 * component that contains this file: David McKnight, Kushal Munir, 
 * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, 
 * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley.
 * 
 * Contributors:
 * Martin Oberhuber (Wind River) - [168975] Move RSE Events API to Core
 * Martin Oberhuber (Wind River) - [186773] split ISystemRegistryUI from ISystemRegistry
 * Kevin Doyle 		(IBM)		 - [242431] Register a new unique context menu id, so contributions can be made to all our views
 * David McKnight   (IBM)        - [250169] Problems with extending the menu's of results in Remote Search View
 * David McKnight   (IBM)        - [214395] Properties View not updated when clicking on Search Results
 * David McKnight   (IBM)        - [190015] [performance] Remove All Match's from Search Results Takes a while
 * David McKnight   (IBM)        - [296877] Allow user to choose the attributes for remote search result
 * David McKnight   (IBM)        - [330398] RSE leaks SWT resources
 *******************************************************************************/

package org.eclipse.rse.internal.ui.view.search;

import java.util.ArrayList;
import java.util.Iterator;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.Window;
import org.eclipse.rse.core.RSECorePlugin;
import org.eclipse.rse.core.events.ISystemResourceChangeEvent;
import org.eclipse.rse.core.events.ISystemResourceChangeEvents;
import org.eclipse.rse.core.events.ISystemResourceChangeListener;
import org.eclipse.rse.internal.ui.SystemResources;
import org.eclipse.rse.internal.ui.view.SystemTableTreeViewProvider;
import org.eclipse.rse.internal.ui.view.SystemView;
import org.eclipse.rse.services.clientserver.messages.SystemMessage;
import org.eclipse.rse.services.search.IHostSearchResultConfiguration;
import org.eclipse.rse.services.search.IHostSearchResultSet;
import org.eclipse.rse.ui.ISystemContextMenuConstants;
import org.eclipse.rse.ui.ISystemIconConstants;
import org.eclipse.rse.ui.RSEUIPlugin;
import org.eclipse.rse.ui.SystemMenuManager;
import org.eclipse.rse.ui.SystemWidgetHelpers;
import org.eclipse.rse.ui.actions.SystemPasteFromClipboardAction;
import org.eclipse.rse.ui.dialogs.SystemPromptDialog;
import org.eclipse.rse.ui.messages.ISystemMessageLine;
import org.eclipse.rse.ui.model.ISystemShellProvider;
import org.eclipse.rse.ui.view.IRSEViewPart;
import org.eclipse.rse.ui.view.ISystemRemoveElementAdapter;
import org.eclipse.rse.ui.view.ISystemTableViewColumnManager;
import org.eclipse.rse.ui.view.ISystemViewElementAdapter;
import org.eclipse.rse.ui.view.SystemAdapterHelpers;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.CellEditorActionHandler;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.views.properties.IPropertyDescriptor;

/**
 * This class defines the Remote Search view.
 */
public class SystemSearchViewPart extends ViewPart 
	implements ISystemResourceChangeListener, ISystemShellProvider,
               IMenuListener, ISelectionChangedListener, 
               ISystemMessageLine, IRSEViewPart
{
	class BrowseAction extends Action
	{

		public BrowseAction()
		{
		}

		public BrowseAction(String label, ImageDescriptor des)
		{
			super(label, des);

			setToolTipText(label);
		}

		public void checkEnabledState()
		{
			Viewer viewer = getRSEViewer();
			if (viewer != null && viewer.getInput() != null)
			{
				setEnabled(true);
			}
			else
			{
				setEnabled(false);
			}
		}

		public void run()
		{
		}
	}
	private class SelectColumnsAction extends BrowseAction
	{

	    class SelectColumnsDialog extends SystemPromptDialog
		{
	        private ISystemViewElementAdapter _adapter;
	        private ISystemTableViewColumnManager _columnManager;
			private IPropertyDescriptor[] _uniqueDescriptors;
			private ArrayList _currentDisplayedDescriptors;
			private ArrayList _availableDescriptors;

			private List _availableList;
			private List _displayedList;

			private Button _addButton;
			private Button _removeButton;
			private Button _upButton;
			private Button _downButton;


			public SelectColumnsDialog(Shell shell, ISystemViewElementAdapter viewAdapter, ISystemTableViewColumnManager columnManager)
			{
				super(shell, SystemResources.RESID_TABLE_SELECT_COLUMNS_LABEL);
				setToolTipText(SystemResources.RESID_TABLE_SELECT_COLUMNS_TOOLTIP);
				_adapter = viewAdapter;
				_columnManager = columnManager;
				_uniqueDescriptors = viewAdapter.getUniquePropertyDescriptors();
				IPropertyDescriptor[] initialDisplayedDescriptors = _columnManager.getVisibleDescriptors(_adapter);
				_currentDisplayedDescriptors = new ArrayList(initialDisplayedDescriptors.length);
				for (int i = 0; i < initialDisplayedDescriptors.length;i++)
				{
					if (!_currentDisplayedDescriptors.contains(initialDisplayedDescriptors[i]))
				    _currentDisplayedDescriptors.add(initialDisplayedDescriptors[i]);
				}
				_availableDescriptors = new ArrayList(_uniqueDescriptors.length);
				for (int i = 0; i < _uniqueDescriptors.length;i++)
				{
				    if (!_currentDisplayedDescriptors.contains(_uniqueDescriptors[i]))
				    {
				        _availableDescriptors.add(_uniqueDescriptors[i]);
				    }
				}
			}


			public void handleEvent(Event e)
			{
			    Widget source = e.widget;
			    if (source == _addButton)
			    {
			        int[] toAdd = _availableList.getSelectionIndices();
			        addToDisplay(toAdd);
			    }
			    else if (source == _removeButton)
			    {
			        int[] toAdd = _displayedList.getSelectionIndices();
			        removeFromDisplay(toAdd);
			    }
			    else if (source == _upButton)
			    {
			        int index = _displayedList.getSelectionIndex();
			        moveUp(index);
			        _displayedList.select(index - 1);
			    }
			    else if (source == _downButton)
			    {
			        int index = _displayedList.getSelectionIndex();
			        moveDown(index);
			        _displayedList.select(index + 1);
			    }

			    // update button enable states
			    updateEnableStates();
			}

			public IPropertyDescriptor[] getDisplayedColumns()
			{
			    IPropertyDescriptor[] displayedColumns = new IPropertyDescriptor[_currentDisplayedDescriptors.size()];
			    for (int i = 0; i< _currentDisplayedDescriptors.size();i++)
			    {
			        displayedColumns[i]= (IPropertyDescriptor)_currentDisplayedDescriptors.get(i);
			    }
			    return displayedColumns;
			}

			private void updateEnableStates()
			{
			    boolean enableAdd = false;
			    boolean enableRemove = false;
			    boolean enableUp = false;
			    boolean enableDown = false;

			    int[] availableSelected = _availableList.getSelectionIndices();
			    for (int i = 0; i < availableSelected.length; i++)
			    {
			        int index = availableSelected[i];
			        IPropertyDescriptor descriptor = (IPropertyDescriptor)_availableDescriptors.get(index);
			        if (!_currentDisplayedDescriptors.contains(descriptor))
			        {
			            enableAdd = true;
			        }
			    }

			    if (_displayedList.getSelectionCount()>0)
			    {
			        enableRemove = true;

			        int index = _displayedList.getSelectionIndex();
			        if (index > 0)
			        {
			            enableUp = true;
			        }
			        if (index < _displayedList.getItemCount()-1)
			        {
			            enableDown = true;
			        }
			    }

			    _addButton.setEnabled(enableAdd);
			    _removeButton.setEnabled(enableRemove);
			    _upButton.setEnabled(enableUp);
			    _downButton.setEnabled(enableDown);

			}

			private void moveUp(int index)
			{
			    Object obj = _currentDisplayedDescriptors.remove(index);
		        _currentDisplayedDescriptors.add(index - 1, obj);
		        refreshDisplayedList();
			}

			private void moveDown(int index)
			{
			    Object obj = _currentDisplayedDescriptors.remove(index);
		        _currentDisplayedDescriptors.add(index + 1, obj);

		        refreshDisplayedList();
			}

			private void addToDisplay(int[] toAdd)
			{
			    ArrayList added = new ArrayList();
			    for (int i = 0; i < toAdd.length; i++)
			    {
			        int index = toAdd[i];

			        IPropertyDescriptor descriptor = (IPropertyDescriptor)_availableDescriptors.get(index);

			        if (!_currentDisplayedDescriptors.contains(descriptor))
			        {
			            _currentDisplayedDescriptors.add(descriptor);
			            added.add(descriptor);
			        }
			    }

			    for (int i = 0; i < added.size(); i++)
			    {
			      _availableDescriptors.remove(added.get(i));
			    }


			    refreshAvailableList();
			    refreshDisplayedList();

			}

			private void removeFromDisplay(int[] toRemove)
			{
			    for (int i = 0; i < toRemove.length; i++)
			    {
			        int index = toRemove[i];
			        IPropertyDescriptor descriptor = (IPropertyDescriptor)_currentDisplayedDescriptors.get(index);
			        _currentDisplayedDescriptors.remove(index);
			        _availableDescriptors.add(descriptor);
			    }
			    refreshDisplayedList();
			    refreshAvailableList();
			}

			protected void buttonPressed(int buttonId)
			{
				setReturnCode(buttonId);

				close();
			}

			protected Control getInitialFocusControl()
			{
				return _availableList;
			}

			public Control createInner(Composite parent)
			{
				Composite main = SystemWidgetHelpers.createComposite(parent, 1);


				Composite c = SystemWidgetHelpers.createComposite(main, 4);
				c.setLayoutData(new GridData(GridData.FILL_BOTH));
				_availableList = SystemWidgetHelpers.createListBox(c, SystemResources.RESID_TABLE_SELECT_COLUMNS_AVAILABLE_LABEL, this, true);

				Composite addRemoveComposite = SystemWidgetHelpers.createComposite(c, 1);
				addRemoveComposite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_CENTER));
				_addButton = SystemWidgetHelpers.createPushButton(addRemoveComposite,
				        SystemResources.RESID_TABLE_SELECT_COLUMNS_ADD_LABEL,
				        this);
				_addButton.setToolTipText(SystemResources.RESID_TABLE_SELECT_COLUMNS_ADD_TOOLTIP);

				_removeButton = SystemWidgetHelpers.createPushButton(addRemoveComposite,
				        SystemResources.RESID_TABLE_SELECT_COLUMNS_REMOVE_LABEL,
				        this);
				_removeButton.setToolTipText(SystemResources.RESID_TABLE_SELECT_COLUMNS_REMOVE_TOOLTIP);

				_displayedList = SystemWidgetHelpers.createListBox(c, SystemResources.RESID_TABLE_SELECT_COLUMNS_DISPLAYED_LABEL, this, false);

				Composite upDownComposite = SystemWidgetHelpers.createComposite(c, 1);
				upDownComposite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_CENTER));
				_upButton = SystemWidgetHelpers.createPushButton(upDownComposite,
				        SystemResources.RESID_TABLE_SELECT_COLUMNS_UP_LABEL,
				        this);
				_upButton.setToolTipText(SystemResources.RESID_TABLE_SELECT_COLUMNS_UP_TOOLTIP);

				_downButton = SystemWidgetHelpers.createPushButton(upDownComposite,
				        SystemResources.RESID_TABLE_SELECT_COLUMNS_DOWN_LABEL,
				        this);
				_downButton.setToolTipText(SystemResources.RESID_TABLE_SELECT_COLUMNS_DOWN_TOOLTIP);

				initLists();

				setHelp();
				return c;
			}

			private void initLists()
			{
			   refreshAvailableList();
			   refreshDisplayedList();
			   updateEnableStates();
			}

			private void refreshAvailableList()
			{
			    _availableList.removeAll();
			    // initialize available list
			    for (int i = 0; i < _availableDescriptors.size(); i++)
			    {
			        IPropertyDescriptor descriptor = (IPropertyDescriptor)_availableDescriptors.get(i);
			        _availableList.add(descriptor.getDisplayName());
			    }
			}

			private void refreshDisplayedList()
			{
			    _displayedList.removeAll();
			    // initialize display list
			    for (int i = 0; i < _currentDisplayedDescriptors.size(); i++)
			    {

			        Object obj = _currentDisplayedDescriptors.get(i);
			        if (obj != null && obj instanceof IPropertyDescriptor)
			        {
			            _displayedList.add(((IPropertyDescriptor)obj).getDisplayName());
			        }
			    }
			}

			private void setHelp()
			{
				setHelp(RSEUIPlugin.HELPPREFIX + "gntc0000"); //$NON-NLS-1$
			}
		}

		public SelectColumnsAction()
		{
			super(SystemResources.ACTION_SELECTCOLUMNS_LABEL, null);
			setToolTipText(SystemResources.ACTION_SELECTCOLUMNS_TOOLTIP);
			setImageDescriptor(RSEUIPlugin.getDefault().getImageDescriptor(ISystemIconConstants.ICON_SYSTEM_FILTER_ID));
		}

		public void checkEnabledState()
		{
			Viewer viewer = getRSEViewer();
			Object input = viewer.getInput();
			if (viewer != null && input != null)
			{			
				boolean flag = getViewAdapter(input).hasChildren((IAdaptable)input);				
				setEnabled(flag);
			}
			else
			{
				setEnabled(false);
			}
		}
		public void run()
		{
			Viewer rviewer = getRSEViewer();
			if (rviewer instanceof SystemSearchTableView){
				SystemSearchTableView viewer = (SystemSearchTableView)rviewer;
				ISystemTableViewColumnManager mgr = viewer.getColumnManager();
				ISystemViewElementAdapter adapter = viewer.getViewAdapterForContents();
				SelectColumnsDialog dlg = new SelectColumnsDialog(getShell(), adapter, mgr);
				if (dlg.open() == Window.OK)
				{
					mgr.setCustomDescriptors(adapter, dlg.getDisplayedColumns());
					viewer.computeLayout(true);
					viewer.refresh();
				}
			}
		}
	}

	
	private PageBook pageBook;
	private StructuredViewer currentViewer;

	private IActionBars actionBars;
	private IMenuManager mMgr;
	private IToolBarManager tbMgr;
	//private IStatusLineManager slMgr;
	
	private static final String MENU_HISTORY_GROUP_NAME = "historyGroup"; //$NON-NLS-1$
	private static final String MENU_CLEAR_HISTORY_GROUP_NAME = "clearHistoryGroup"; //$NON-NLS-1$

	private ArrayList viewers = new ArrayList();
	private ArrayList historyActions = new ArrayList();

	private CancelAction cancelAction;
	private SystemSearchClearHistoryAction clearHistoryAction;
	private SystemSearchRemoveSelectedMatchesAction removeSelectedAction;
	private SystemSearchRemoveAllMatchesAction removeAllAction;
	private SelectColumnsAction _selectColumnsAction;
	
	private SystemSearchCopyToClipboardAction copyAction;
	private SystemPasteFromClipboardAction pasteAction;

	//  for ISystemMessageLine
	private String _message, _errorMessage;
	private SystemMessage sysErrorMessage;
	private IStatusLineManager _statusLine = null;

	
	/**
	 * Double click listener.
	 */
	public class SystemSearchDoubleClickListener implements IDoubleClickListener {

		/**
		 * @see org.eclipse.jface.viewers.IDoubleClickListener#doubleClick(DoubleClickEvent)
		 */
		public void doubleClick(DoubleClickEvent event) {
			IStructuredSelection selection = (IStructuredSelection) (event.getSelection());

			if (!selection.isEmpty()) {
				Object element = selection.getFirstElement();
				ISystemViewElementAdapter adapter = getViewAdapter(element);
				adapter.setViewer(currentViewer);
				adapter.handleDoubleClick(element);
			}
		}
	}

	class SelectAllAction extends Action {
		
		public SelectAllAction() {
			super(SystemResources.ACTION_SELECT_ALL_LABEL, null);
		}

		public void run() {
			
			if ((currentViewer != null) && (currentViewer instanceof TableViewer)) {
				TableViewer viewer = (TableViewer) currentViewer;
				viewer.getTable().selectAll();
				// force viewer selection change
				viewer.setSelection(viewer.getSelection());
			}
		}
	}

	public class CancelAction extends Action {
		
		public CancelAction() {
			super(SystemResources.ACTION_CANCEL_SEARCH_LABEL, RSEUIPlugin.getDefault().getImageDescriptor(ISystemIconConstants.ICON_SYSTEM_STOP_ID));
			setToolTipText(SystemResources.ACTION_CANCEL_SEARCH_TOOLTIP);
			RSEUIPlugin.getDefault().getWorkbench().getHelpSystem().setHelp(this, RSEUIPlugin.HELPPREFIX + "search_cancel"); //$NON-NLS-1$
		}

		public void run() {
			
			if (currentViewer == null) {
				return;
			}
			
			Object input = currentViewer.getInput();
			
			if (input != null) {
				
				if (input instanceof IHostSearchResultSet) {
					IHostSearchResultSet resultSet = (IHostSearchResultSet)input;
					setEnabled(false);
					resultSet.cancel();
				}
			}
		}

		public void updateEnableState(IAdaptable input) {
			
			// no input yet, so disable it
			if (input == null) {
				setEnabled(false);
			}
			
			if (input instanceof IHostSearchResultSet) {
				IHostSearchResultSet set = (IHostSearchResultSet)input;
				
				// running, so enable it
				if (set.isRunning()) {
					setEnabled(true);
				}
				// otherwise, disable
				else {
					setEnabled(false);
				}
			}
			// some other input, disable it
			else {
				setEnabled(false);
			}
		}
	}

	/**
	 * Constructor for SystemSearchViewPart.
	 */
	public SystemSearchViewPart() {
		super();
	}

	/**
	 * Creates a dummy selection provider.
	 * @return a dummy selection provider.
	 */
	private ISelectionProvider createDummySelectionProvider() {
		
		ISelectionProvider provider = new ISelectionProvider() {

			public void addSelectionChangedListener(ISelectionChangedListener listener) {
			}

			public ISelection getSelection() {
				if (currentViewer != null){
					return currentViewer.getSelection();
				}
				return null;
			}

			public void removeSelectionChangedListener(ISelectionChangedListener listener) {
			}

			public void setSelection(ISelection selection) {
				if (currentViewer != null){
					currentViewer.setSelection(selection);
				}
			}
		};
		
		return provider;
	}
	
	/**
	 * @see org.eclipse.ui.IWorkbenchPart#createPartControl(Composite)
	 */
	public void createPartControl(Composite parent) {
		
		// create the page book
		pageBook = new PageBook(parent, SWT.NONE);
		
		// pageBook.showPage(createDummyControl());

		// get view site
		IViewSite site = getViewSite();
		
		// set a dummy selection provider 
		// because when the view is first created we don't have any real viewers (i.e. currentViewer)
		// after addSearchResult() is called, the provider should defer to the selection from the
		// current viewer
		site.setSelectionProvider(createDummySelectionProvider());
		
		// get action bars
		actionBars = site.getActionBars();

		// get the menu manager
		mMgr = actionBars.getMenuManager();

		// get the tool bar manager
		tbMgr = actionBars.getToolBarManager();

		_statusLine = actionBars.getStatusLineManager();

		
		// initialize toolbar actions
		initToolBarActions(tbMgr);

		// get the status line manager
		//slMgr = actionBars.getStatusLineManager();
		
		// update action bars
		actionBars.updateActionBars();

		// add view as a system listener
		RSECorePlugin.getTheSystemRegistry().addSystemResourceChangeListener(this);

		// set help
		SystemWidgetHelpers.setHelp(pageBook, RSEUIPlugin.HELPPREFIX + "srch0000"); //$NON-NLS-1$
	}

	private void initToolBarActions(IToolBarManager tbMgr) {
		
		// create cancel action
		if (cancelAction == null) {
			cancelAction = new CancelAction();
			
			if (currentViewer == null) {
				cancelAction.setEnabled(false);
			}
			else if (currentViewer.getInput() == null){
				cancelAction.setEnabled(false);
			}
			else {
				cancelAction.setEnabled(true);
			}
		}
		
		// create remove selected matches action
		if (removeSelectedAction == null) {
			removeSelectedAction = new SystemSearchRemoveSelectedMatchesAction(this, getShell());
			
			if (currentViewer == null) {
				removeSelectedAction.setEnabled(false);
			}
			else {
				removeSelectedAction.setEnabled(isRemoveSelectedEnabled());
			}
		}
		
		// create remove all matches action
		if (removeAllAction == null) {
			removeAllAction = new SystemSearchRemoveAllMatchesAction(this, getShell());
			
			if (currentViewer == null) {
				removeAllAction.setEnabled(false);
			}
			else {
				Object input = currentViewer.getInput();
				removeAllAction.setEnabled(isRemoveAllEnabled((IAdaptable)input));
			}
		}
		
		if (_selectColumnsAction == null){
			_selectColumnsAction = new SelectColumnsAction();
			if (currentViewer == null){
				_selectColumnsAction.setEnabled(false);
			}
		}
		
		
		// add cancel action
		tbMgr.add(cancelAction);
		
		// add remove selected action
		tbMgr.add(removeSelectedAction);
		
		// add remove all action
		tbMgr.add(removeAllAction);
		
		
		tbMgr.add(new Separator("View")); //$NON-NLS-1$
		tbMgr.add(_selectColumnsAction);

		// clipboard
		Shell shell = RSEUIPlugin.getTheSystemRegistryUI().getShell();
		
		copyAction = new SystemSearchCopyToClipboardAction(shell, null);
		pasteAction = new SystemPasteFromClipboardAction(shell, null);

		CellEditorActionHandler editorActionHandler = new CellEditorActionHandler(getViewSite().getActionBars());

		editorActionHandler.setCopyAction(copyAction);
		editorActionHandler.setPasteAction(pasteAction);
		editorActionHandler.setDeleteAction(removeSelectedAction);
		// editorActionHandler.setSelectAllAction(new SelectAllAction());
	}
	
	/**
	 * Updates the remove selected action.
	 * @return <code>true</code> if remove selected action should be enabled, <code>false</code> otherwise.
	 */
	private boolean isRemoveSelectedEnabled() {
		
		ISelection selection = getSelection();
		
		if (selection == null) {
			return false;
		}
		else if (selection.isEmpty()) {
			return false;
		}
		else {
			
			if (selection instanceof IStructuredSelection) {
				IStructuredSelection strSel = (IStructuredSelection)selection;
				
				// note that SystemSearchTableView returns the current input
				// if the actual selection is null
				// so we check for it and return null
				if (strSel.getFirstElement() == currentViewer.getInput()) {
					return false;
				}
				else {
					return true;
				}
			}
			else {
				return false;
			}
		}
	}
	
	/**
	 * Updates the remove all matches action.
	 * @param input the input to the current viewer, or <code>null</code> if there is currently no input.
	 * @return <code>true</code> if remove all action should be enabled, <code>false</code> otherwise.
	 */
	private boolean isRemoveAllEnabled(IAdaptable input) {
		
		if (input == null) {
			return false;
		}
		
		ISystemViewElementAdapter adapter = getViewAdapter(input);
		
		if (adapter == null) {
			return false;
		}
		else {
			return adapter.hasChildren(input);
		}
	}

	/**
	 * @see org.eclipse.ui.IWorkbenchPart#setFocus()
	 */
	public void setFocus() {
		if (currentViewer != null){
			getSite().setSelectionProvider(currentViewer);
		}
	}

	/**
	 * @see org.eclipse.ui.IViewPart#init(IViewSite, IMemento)
	 */
	public void init(IViewSite site, IMemento memento) throws PartInitException {
		super.init(site, memento);
	}

	/**
	 * @see org.eclipse.ui.IViewPart#saveState(IMemento)
	 */
	public void saveState(IMemento memento) {
		super.saveState(memento);
	}

	/**
	 * Add a search result set.
	 * @param resultSet the search result set
	 */
	public void addSearchResult(IAdaptable resultSet) {
		
		// if the correct adapter is not registered, then return
		ISystemViewElementAdapter adapter = getViewAdapter(resultSet);
		
		if (adapter == null) {
			return;
		}
		
		if (resultSet instanceof IHostSearchResultSet) {
			currentViewer = createSearchResultsTable((IHostSearchResultSet)resultSet, adapter);			
		}
		else {
			currentViewer = createSearchResultsTree(resultSet, adapter);
			
			TreeViewer treeViewer = (TreeViewer)currentViewer;
			MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
			menuMgr.setRemoveAllWhenShown(true);
			menuMgr.addMenuListener(this);
			
			Tree tree = (Tree)treeViewer.getControl();				
			Menu menu = menuMgr.createContextMenu(tree);
			tree.setMenu(menu);	
		}
		
		
		// set input
		currentViewer.setInput(resultSet);
		
		// add as selection changed listener to current viewer
		currentViewer.addSelectionChangedListener(this);
		
		// set as selection provider
		getSite().setSelectionProvider(currentViewer);

		// add double click listener
		currentViewer.addDoubleClickListener(new SystemSearchDoubleClickListener());

		// set help for control
		SystemWidgetHelpers.setHelp(currentViewer.getControl(), RSEUIPlugin.HELPPREFIX + "srch0000"); //$NON-NLS-1$

		// add current viewer to viewer list
		viewers.add(currentViewer);

		// get title to use from adapter
		String title = adapter.getText(resultSet);

		// set the title of the view
		setContentDescription(title);
		
		int num = viewers.size()-1;

		// create history action
		SystemSearchHistoryAction historyAction = new SystemSearchHistoryAction(title, RSEUIPlugin.getDefault().getImageDescriptor(ISystemIconConstants.ICON_SYSTEM_SEARCH_RESULT_ID), this, num);
		
		// add to list of history actions
		historyActions.add(historyAction);
		
		// if this is the first result set, add the clear history action
		if (viewers.size() == 1) {
			
			// create a group for history actions
			mMgr.add(new GroupMarker(MENU_HISTORY_GROUP_NAME));
			
			// create a separator with a group for clear history action
			mMgr.add(new Separator(MENU_CLEAR_HISTORY_GROUP_NAME));
			
			// add the clear history action to the group
			clearHistoryAction = new SystemSearchClearHistoryAction(this, getShell());
			mMgr.appendToGroup(MENU_CLEAR_HISTORY_GROUP_NAME, clearHistoryAction);
		}
		
		// add history action to the menu manager
		mMgr.appendToGroup(MENU_HISTORY_GROUP_NAME, historyAction);

		// add global actions
		// actionBars.setGlobalActionHandler(ActionFactory.DELETE, new SystemSearchDeleteAction(this));

		// update action bars
		actionBars.updateActionBars();
		
		// show the control
		pageBook.showPage(currentViewer.getControl());

		// enable/disable state for this input
		if (cancelAction != null) {
			cancelAction.updateEnableState(resultSet);
		}
		
		// enable/disable state
		if (removeSelectedAction != null) {
			removeSelectedAction.setEnabled(isRemoveSelectedEnabled());
		}
		
		// enable/disable state for this input
		if (removeAllAction != null) {
			removeAllAction.setEnabled(isRemoveAllEnabled(resultSet));
		}
		
		if (_selectColumnsAction != null){
			_selectColumnsAction.checkEnabledState();
		}
	}

	private StructuredViewer createSearchResultsTree(IAdaptable resultSet, ISystemViewElementAdapter adapter)
	{

		// create the current tree
		Tree currentControl = new Tree(pageBook, SWT.MULTI);

		// create the current viewer
		TreeViewer currentViewer = new TreeViewer(currentControl);
		currentViewer.setUseHashlookup(true);
		currentViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS);

		// create a new content provider
		SystemSearchViewContentProvider contentProvider = new SystemSearchViewContentProvider();
		// save the viewpart to the provider
		contentProvider.setViewPart(this);
		// add the content provider to the viewer
		currentViewer.setContentProvider(contentProvider);

		// create a new label provider
		SystemSearchViewLabelProvider labelProvider = new SystemSearchViewLabelProvider();

		// add the label provider to the viewer
		currentViewer.setLabelProvider(labelProvider);

		return currentViewer;
	}

	private StructuredViewer createSearchResultsTable(IHostSearchResultSet resultSet, ISystemViewElementAdapter adapter) {
		
		// create table portion
		// TODO change to tabletree when eclipse fixes the swt widget
		//TableTree table = new TableTree(pageBook, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | SWT.HIDE_SELECTION);
		Tree tabletree = new Tree(pageBook, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | SWT.HIDE_SELECTION);
		SystemSearchTableView viewer = new SystemSearchTableView(tabletree, resultSet, this);
		
		getSite().registerContextMenu(viewer.getContextMenuManager(), viewer);
		getSite().registerContextMenu(ISystemContextMenuConstants.RSE_CONTEXT_MENU, viewer.getContextMenuManager(), viewer);
		return viewer;
	}

	/**
	 * @see org.eclipse.ui.IWorkbenchPart#dispose()
	 */
	public void dispose() {
		
		// remove as resource change listener
		RSECorePlugin.getTheSystemRegistry().removeSystemResourceChangeListener(this);
		
		// clear viewers
		clearViewers();
		
		// clear arrays
		viewers.clear();
		historyActions.clear();

		// call super as required
		super.dispose();
	}
	
	/**
	 * Remove current viewer as selection provider, removes children of all the inputs and disposes
	 * the controls if they haven't already been disposed.
	 */
	private void clearViewers() {
		
		// remove current viewer as selection provider if it exists
		if (currentViewer != null) {
			
			// remove as selection changed listener to current viewer
			currentViewer.removeSelectionChangedListener(this);
			
			if (getSite().getSelectionProvider() == currentViewer) {
				getSite().setSelectionProvider(null);
			}
		}

		for (int i = 0; i < viewers.size(); i++) {
			
			Object viewer = viewers.get(i);
			
			// if we're dealing with universal search
			if (viewer instanceof SystemSearchTableView) {
				
				SystemSearchTableView tableView = (SystemSearchTableView)viewer;
				
				Object input = tableView.getInput();
				
				// dispose the remote search result set
				// which cancels the search and removes contents from the input
				// (i.e. removes from model)
				if (input instanceof IHostSearchResultSet) {
					IHostSearchResultSet set = (IHostSearchResultSet)input;
					set.dispose();
				}
				
				// dispose viewer
				tableView.dispose();
			}
			// other search
			else if (viewer instanceof TreeViewer){
				
				TreeViewer treeView = (TreeViewer)viewer;
				
				Object input = treeView.getInput();
				
				ISystemViewElementAdapter adapter = getViewAdapter(input);
				
				if (adapter != null && adapter instanceof ISystemRemoveElementAdapter) {
					ISystemRemoveElementAdapter rmAdapter = (ISystemRemoveElementAdapter)adapter;
					rmAdapter.removeAllChildren(input);
					
					Control control = treeView.getControl();
					
					if (!control.isDisposed()) {
						control.dispose();
					} 
				}
			}
		}
	}

	/**
	 * Show search result with the given index.
	 * @param index the index in the result history list
	 */
	public void showSearchResult(int index) {
		
		// remove as selection listener from current viewer
		if (currentViewer != null) {
			currentViewer.removeSelectionChangedListener(this);
		}

		// get viewer with this index and make it current
		currentViewer = (StructuredViewer)(viewers.get(index));
		
		// set as selection provider
		getSite().setSelectionProvider(currentViewer);
		
		// add as selection changed listener to current viewer
		currentViewer.addSelectionChangedListener(this);

		// get the input
		IAdaptable resultSet = (IAdaptable)(currentViewer.getInput());
		
		if (resultSet == null) {
			return;
		}
		
		ISystemViewElementAdapter adapter = getViewAdapter(resultSet);

		// if the correct adapter is not registered, then return
		if (adapter == null) {
			return;
		}

		// get title to use from adapter
		String title = adapter.getText(resultSet);

		// set the title of the view
		setContentDescription(title);

		// get the associated control
		Control currentControl = currentViewer.getControl();

		// show the control
		pageBook.showPage(currentControl);

		// enable/disable state for this input
		if (cancelAction != null) {
			cancelAction.updateEnableState(resultSet);
		}
		
		// enable/disable state
		if (removeSelectedAction != null) {
			removeSelectedAction.setEnabled(isRemoveSelectedEnabled());
		}
		
		// enable/disable state for this input
		if (removeAllAction != null) {
			removeAllAction.setEnabled(isRemoveAllEnabled(resultSet));
		}
		
		if (_selectColumnsAction != null){
			_selectColumnsAction.checkEnabledState();
		}
	}

	/**
	 * Delete the selected object in the view.
	 * @return <code>true</code> if the selection has been deleted, <code>false</code> otherwise.
	 */
	public boolean deleteSelected() {
		
		if (currentViewer == null) {
			return false;
		}
		
		IStructuredSelection selection = (IStructuredSelection)(currentViewer.getSelection());
		
		if (selection == null || selection.isEmpty()) {
			return false;
		}
		
		Object input = currentViewer.getInput();
				
		ISystemViewElementAdapter adapter = getViewAdapter(input);
		
		// adapter should be an instance of ISystemRemoveElementAdapter
		if (adapter == null || !(adapter instanceof ISystemRemoveElementAdapter)) {
			return false;
		}
		
		Iterator elements = selection.iterator();
		
		ArrayList removeElements = new ArrayList();

		while (elements.hasNext()) {
			Object element = elements.next();
			((ISystemRemoveElementAdapter)adapter).remove(input, element);
			removeElements.add(element);
		}
		
		// current viewer should be an instance of tree viewer
		// remove the elements from it to update the view
		if (currentViewer instanceof TreeViewer) {
			((TreeViewer)currentViewer).remove(removeElements.toArray());
		}
		
		// get title to use from adapter
		String title = adapter.getText(input);

		// set the title of the view
		setContentDescription(title);

		// enable/disable state for this input
		if (cancelAction != null) {
			cancelAction.updateEnableState((IAdaptable)input);
		}
					
		// enable/disable state for this input
		if (removeSelectedAction != null) {
			removeSelectedAction.setEnabled(isRemoveSelectedEnabled());
		}
					
		// enable/disable state for this input
		if (removeAllAction != null) {
			removeAllAction.setEnabled(isRemoveAllEnabled((IAdaptable)input));
		}
		
		if (_selectColumnsAction != null){
			_selectColumnsAction.checkEnabledState();
		}
		
		return true;
	}
	
	/**
	 * Deletes all the pages in the view.
	 * @return <code>true</code> if all pages have been deleted, <code>false</code> otherwise.
	 */
	public boolean deleteAllPages() {
		
		// first show a dummy control in page book
		// this must be done before viewers are cleared
		// reason is that current showing control in page book can not be disposed
		// SWT doesn't seem to like it
		// This is fixed in 3.0
		pageBook.showPage(createDummyControl());
		
		// clear viewers
		clearViewers();
		
		// current viewer is null again
		currentViewer = null;
		
		// clear the viewer list
		viewers.clear();
		
		// disable cancel action
		cancelAction.setEnabled(false);
		
		// disable remove all action
		removeSelectedAction.setEnabled(false);
		
		// disable remove all action
		removeAllAction.setEnabled(false);
		
		// disable column selection
		_selectColumnsAction.setEnabled(false);
		
		// clear the history action list
		historyActions.clear();
		
		// get rid of all menu manager actions
		mMgr.removeAll();
		
		// update action bars
		actionBars.updateActionBars();
		
		// clear the content description
		setContentDescription(""); //$NON-NLS-1$
				
		return true;
	}
	
	/**
	 * Creates a dummy control to show in the page book.
	 * @return a dummy control.
	 */
	private Control createDummyControl() {
		Control control = new Composite(pageBook, SWT.NONE);
		return control;
	}
	
	/**
	 * Deletes the current page.
	 * @return <code>true</code> if the current page has been deleted, <code>false</code> otherwise.
	 */
	public boolean deleteCurrentPage() {

		// remove current viewer as selection provider if it exists
		if (currentViewer != null) {
			
			// remove as selection changed listener to current viewer
			currentViewer.removeSelectionChangedListener(this);
			
			if (getSite().getSelectionProvider() == currentViewer) {
				getSite().setSelectionProvider(null);
			}
		}
		else {
			return false;
		}
		
		Object input = currentViewer.getInput();
		
		ISystemViewElementAdapter adapter = getViewAdapter(input);
		
		// universal search
		if (currentViewer instanceof SystemSearchTableView) 
		{
			
			SystemSearchTableView tableView = (SystemSearchTableView)currentViewer;
			
			// remove viewer as listener
			tableView.removeAsListener();
			
			// clear model
			if (input instanceof IHostSearchResultSet) {
				IHostSearchResultSet set = (IHostSearchResultSet)input;
				set.dispose();
			}
			
			// now refresh viewer
			// but flush cache of the provider first for an accurate refresh
			SystemTableTreeViewProvider provider = (SystemTableTreeViewProvider)(tableView.getContentProvider());
			provider.flushCache();
			Tree tree = tableView.getTree();
			tree.removeAll();
		}
		// other search
		else if (currentViewer instanceof TreeViewer){
				
			TreeViewer treeView = (TreeViewer)currentViewer;
				
			if (adapter != null && adapter instanceof ISystemRemoveElementAdapter) {
				ISystemRemoveElementAdapter rmAdapter = (ISystemRemoveElementAdapter)adapter;
				rmAdapter.removeAllChildren(input);
				treeView.refresh();
			}
		}
		
		// get title to use from adapter
		String title = null;
		if (adapter != null)
			title = adapter.getText(input);

		// set the title of the view
		setContentDescription(title);
		
		// disable cancel action
		cancelAction.setEnabled(false);
		
		// disable remove selected action
		removeSelectedAction.setEnabled(false);
		
		// disable remove all action
		removeAllAction.setEnabled(false);	
		
		// disable the column selection
		_selectColumnsAction.setEnabled(false);
		
		return true;
	}

	/**
	 * Get the adapter for the given object.
	 * @param element the object the object for which I want the adapter.
	 * @return the adapter for the object.
	 */
	public ISystemViewElementAdapter getViewAdapter(Object element) {
		return SystemAdapterHelpers.getViewAdapter(element);
	}

	/**
	 * Get the shell.
	 * @return the shell
	 */
	public Shell getShell() {
		return getSite().getShell();
	}

	public void systemResourceChanged(ISystemResourceChangeEvent event) {

		// need to introduce another event type for this....
		if (event.getType() == ISystemResourceChangeEvents.EVENT_SEARCH_FINISHED) {
			
			// the view is added as a system listener when the part is created
			// so the current viewer may not exist if the search results has not been added yet
			if (currentViewer == null) {
				return;
			}
			
			Object actualSource = event.getSource();

			if (actualSource instanceof IHostSearchResultConfiguration) {
				
				IHostSearchResultSet source = ((IHostSearchResultConfiguration)actualSource).getParentResultSet();
				
				// get title to use from adapter
				ISystemViewElementAdapter adapter = getViewAdapter(source);
				
				if (adapter == null) {
					return;
				}
				
				int index = -1;
				
				// if the source is the input to the current viewer
				// update view title and cancel action
				// also update the history action corresponding to the current view
				if (currentViewer.getInput() == source) {
					
					// end of a search
					String title = adapter.getText(source);

					// set the title of the view
					setContentDescription(title);

					// enable/disable state for this input
					if (cancelAction != null) {
						cancelAction.updateEnableState((IAdaptable)source);
					}
					
					// enable/disable state for this input
					if (removeSelectedAction != null) {
						removeSelectedAction.setEnabled(isRemoveSelectedEnabled());
					}
					
					// enable/disable state for this input
					if (removeAllAction != null) {
						removeAllAction.setEnabled(isRemoveAllEnabled((IAdaptable)source));
					}
					
					if (_selectColumnsAction != null){
						_selectColumnsAction.checkEnabledState();
					}
						
					// find out where the current viewer is in the viewer list
					index = viewers.indexOf(currentViewer);
				}
				// if the source is not the input to the current view
				// we simply update the history action
				else {
					
					for (int i = 0; i < viewers.size(); i++) {
						
						SystemSearchTableView view = (SystemSearchTableView)viewers.get(i);
				
						if (view.getInput() == source) {
							index = i;
							break;
						} 
					}
				}
				
				// since the history actions list paralles the viewer list, use the index to
				// get the history action
				if (index >= 0) {
					SystemSearchHistoryAction historyAction = (SystemSearchHistoryAction)historyActions.get(index);
					historyAction.setText(adapter.getText(source));
				}
			}
		}
	}
	
	//------------------------------------------------------
	// Methods used by the tree view pop-up menu
	//------------------------------------------------------
	/**
	 * Fill context for the tree view pop-up menu.
	 * @param menu the menu manager.
	 */
	public void fillContextMenu(IMenuManager menu)
	{
		IStructuredSelection selection = (IStructuredSelection)currentViewer.getSelection();
		
		if (selection == null) {
			return;
		}
		
		int selectionCount = selection.size();
		
		if (selectionCount == 0) { // nothing selected
			return;
		}
		else {
			
			// if only one selection, check if selection is the input
			// if so add no actions
			if (selectionCount == 1) {
				
				if (selection.getFirstElement() == currentViewer.getInput()) {
					return;
				}
			}
			
			// if selection count is more than 1
			// check if all have same parent
			// if not, check if they have ancestor relationship
			// if so, add no actions
//			if (selectionCount > 1) {
//				boolean allSelectionsFromSameParent = sameParent();
//				
//				// if all selections do not have the same parent, do not show anything in the menu
//				if (!allSelectionsFromSameParent) {
//					
//					if (selectionHasAncestryRelationship()) {
//						// don't show the menu because actions with
//						//  multiple select on objects that are ancestors 
//						//  of each other is problematic
//						// still create the standard groups
//						SystemView.createStandardGroups(menu);
//						return;
//					}
//				}
//			}
			
			// partition into groups...
			SystemView.createStandardGroups(menu);
				
			// adapter actions
			SystemMenuManager ourMenu = new SystemMenuManager(menu);
			Object element = selection.getFirstElement();
			ISystemViewElementAdapter adapter = getViewAdapter(element);
			adapter.setViewer(currentViewer);	
			adapter.addActions(ourMenu, selection,
							   getShell(),
							   ISystemContextMenuConstants.GROUP_ADAPTERS);
		}
	}
	
	/**
	 * This is called to ensure all elements in a multiple-selection have the same parent in the
	 *  tree viewer. If they don't we automatically disable all actions. 
	 * <p>
	 * Designed to be as fast as possible by going directly to the SWT widgets
	 */
	public boolean sameParent()
	{
		boolean same = true;
		
		Tree tree = null;
		
		if (currentViewer instanceof AbstractTreeViewer) {
			tree = (Tree)(currentViewer.getControl());
		}
		else {
			return false;
		}
		
		TreeItem[] items = tree.getSelection();
		
		if ((items == null) || (items.length == 0))
			return true;
		
		TreeItem prevParent = null;
		TreeItem currParent = null;
		
		for (int idx=0; same && (idx<items.length); idx++)
		{
		   currParent = items[idx].getParentItem();           
		 
		   if ((idx>0) && (currParent != prevParent))
		   {
			 same = false;
		   }
		   else
		   {
			 prevParent = currParent;  
		   }
		}
		
		return same;
	}
	
	/**
	 * Called when the context menu is about to open.
	 * Calls {@link #fillContextMenu(IMenuManager)}
	 */
	public void menuAboutToShow(IMenuManager menu)
	{
	  fillContextMenu(menu);		
	}
	
	public void addSelectionChangedListener(ISelectionChangedListener listener)
	{
		currentViewer.addSelectionChangedListener(listener);
	}
	
	/**
	* Returns the current selection for this provider.
	*
	* @return the current selection
	*/
	public ISelection getSelection()
	{
		if (currentViewer == null) {
			return null;
		}
		else {
			return currentViewer.getSelection();
		}
	}
	/**
	* Removes the given selection change listener from this selection provider.
	* Has no affect if an identical listener is not registered.
	*
	* @param listener a selection changed listener
	*/
	public void removeSelectionChangedListener(ISelectionChangedListener listener)
	{
		currentViewer.removeSelectionChangedListener(listener);
	}
	/**
	* Sets the current selection for this selection provider.
	*
	* @param selection the new selection
	*/
	public void setSelection(ISelection selection)
	{
		currentViewer.setSelection(selection);
	}
	/**
	 * Set the title of this view part
	 * @param title
	 */
	public void setViewPartTitle(String title)
	{
	   setContentDescription(title);
	}

	/**
	 * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
	 */
	public void selectionChanged(SelectionChangedEvent event) {
		
		if (event.getSelectionProvider() == currentViewer) {
			removeSelectedAction.setEnabled(isRemoveSelectedEnabled());
		}
		else {
			removeSelectedAction.setEnabled(false);
		}
		
		IStructuredSelection sel = (IStructuredSelection)(event.getSelection());
		
		Iterator iter = sel.iterator();
		
		// set viewer for adapters of the selected elements
		while (iter.hasNext()) {
		    ISystemViewElementAdapter adapter = getViewAdapter(iter.next());
		    adapter.setViewer(currentViewer);
		}
		
		copyAction.setEnabled(copyAction.updateSelection(sel));
		pasteAction.setEnabled(pasteAction.updateSelection(sel));
	}
	
	/**
	 * Gets the current viewer, i.e. the viewer whose control is being currently displayed in the view.
	 * @return the current viewer, or <code>null</code> if there is no current viewer.
	 */
	public StructuredViewer getCurrentViewer() {
		return currentViewer;
	}
	
	public Viewer getRSEViewer()
	{
		return currentViewer;
	}
	
//	 -------------------------------
	// ISystemMessageLine interface...
	// -------------------------------
	/**
	 * Clears the currently displayed error message and redisplayes
	 * the message which was active before the error message was set.
	 */
	public void clearErrorMessage()
	{
		_errorMessage = null;
		sysErrorMessage = null;
		if (_statusLine != null)
			_statusLine.setErrorMessage(_errorMessage);
	}
	/**
	 * Clears the currently displayed message.
	 */
	public void clearMessage()
	{
		_message = null;
		if (_statusLine != null)
			_statusLine.setMessage(_message);
	}
	/**
	 * Get the currently displayed error text.
	 * @return The error message. If no error message is displayed <code>null</code> is returned.
	 */
	public String getErrorMessage()
	{
		return _errorMessage;
	}
	/**
	 * Get the currently displayed message.
	 * @return The message. If no message is displayed <code>null<code> is returned.
	 */
	public String getMessage()
	{
		return _message;
	}
	/**
	 * Display the given error message. A currently displayed message
	 * is saved and will be redisplayed when the error message is cleared.
	 */
	public void setErrorMessage(String message)
	{
		this._errorMessage = message;
		if (_statusLine != null)
			_statusLine.setErrorMessage(message);
	}
	/**
	 * Get the currently displayed error text.
	 * @return The error message. If no error message is displayed <code>null</code> is returned.
	 */
	public SystemMessage getSystemErrorMessage()
	{
		return sysErrorMessage;
	}

	/**
	 * Display the given error message. A currently displayed message
	 * is saved and will be redisplayed when the error message is cleared.
	 */
	public void setErrorMessage(SystemMessage message)
	{
		sysErrorMessage = message;
		setErrorMessage(message.getLevelOneText());
	}
	/**
	 * Display the given error message. A currently displayed message
	 * is saved and will be redisplayed when the error message is cleared.
	 */
	public void setErrorMessage(Throwable exc)
	{
		setErrorMessage(exc.getMessage());
	}

	/**
	 * Set the message text. If the message line currently displays an error,
	 * the message is stored and will be shown after a call to clearErrorMessage
	 */
	public void setMessage(String message)
	{
		this._message = message;
		if (_statusLine != null)
			_statusLine.setMessage(message);
	}
	/** 
	 *If the message line currently displays an error,
	 * the message is stored and will be shown after a call to clearErrorMessage
	 */
	public void setMessage(SystemMessage message)
	{
		setMessage(message.getLevelOneText());
	}

}