/**
 * File:    ModelOutlinePage.java
 * Created: 12.12.2008
 *
/*******************************************************************************
 * Copyright (c) 2005-2011
 * University of Augsburg, Germany <www.ds-lab.org>
 *
 * 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
 *
 * Contributors:
 *    Christian Saad, Programming distributed Systems Lab, University of Augsburg 
 *    	- initial API and implementation
 *******************************************************************************/

package org.eclipse.jwt.we.editors.outline;

import java.util.ArrayList;

import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.gef.ui.actions.ActionRegistry;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jwt.meta.model.processes.Activity;
import org.eclipse.jwt.we.editors.WEEditor;
import org.eclipse.jwt.we.editors.preferences.PreferenceReader;
import org.eclipse.jwt.we.internal.ActionBarContributor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.views.contentoutline.ContentOutlinePage;


/**
 * Outline that shows the model structure in a tree and/or graphical viewer.
 * 
 * <p>
 * The outline provides also all actions to create and delete model elements. It displays
 * the complete model tree and not only the activity related models like the
 * {@link ActivityEditor}.
 * </p>
 * 
 * <p>
 * The contents of the tree is gathered through the edit providers of the model elements.
 * The {@link AdapterFactory} of the {@link ActivityEditor} is used to adapt the model
 * elements.
 * </p>
 * 
 * <p>
 * The context menu of the outline is registered to the {@link ActivityEditor} which
 * provides all neccessary actions through the {@link ActionBarContributor}.
 * </p>
 * 
 * <p>
 * The outline is able to drag & drop elements from the outline to the
 * {@link ActivityEditor}.
 * </p>
 * 
 * <p>
 * On double click on an {@link Activity}, the activity is shown in the
 * {@link ActivityEditor}.
 * </p>
 * 
 * @version $Id: ModelOutlinePage.java,v 1.5 2009-11-26 12:41:38 chsaad Exp $
 * @author Markus Bauer (markusbauer@users.sourceforge.net), Programming distributed
 *         Systems Lab, University of Augsburg, Germany, www.ds-lab.org
 */
public class ModelOutlinePage
		extends ContentOutlinePage
		implements IDoubleClickListener
{

	/**
	 * The editor that uses the outline.
	 */
	private WEEditor editor;

	/**
	 * The context menu of the outline.
	 */
	private MenuManager contextMenuManager;

	/**
	 * The main composite area.
	 */
	private SashForm mainArea;

	/**
	 * The overview area of the outline.
	 */
	private ModelOutlineAreaOverview overviewOutlineArea;

	/**
	 * Thetreeview area of the outline.
	 */
	private ModelOutlineAreaTreeviewer treeviewerOutlineArea;

	/**
	 * The current display mode.
	 */
	public String current_display_mode = ""; //$NON-NLS-1$

	/**
	 * Display mode: Show only graphical overview.
	 */
	public static String OUTLINE_AREA_OVERVIEW = "outlinearea_overview"; //$NON-NLS-1$

	/**
	 * Display mode: Show only treeview.
	 */
	public static String OUTLINE_AREA_TREEVIEW = "outlinearea_treeview"; //$NON-NLS-1$

	/**
	 * Display mode: Show graphical overview and treeview.
	 */
	public static String OUTLINE_AREA_BOTH = "outlinearea_both"; //$NON-NLS-1$


	/**
	 * @param editor
	 *            The editor that uses the outline.
	 */
	public ModelOutlinePage(WEEditor editor)
	{
		assert editor != null;
		this.editor = editor;
	}


	/**
	 * Returns the MenuManager that is responsible for the popup menu.
	 * 
	 * @return Returns the contextMenuManager.
	 */
	public MenuManager getContextMenuManager()
	{
		if (contextMenuManager == null)
		{
			contextMenuManager = new MenuManager();
			contextMenuManager.setRemoveAllWhenShown(true);

		}
		return contextMenuManager;
	}


	/**
	 * @return The EMF EditingDomain.
	 */
	public EditingDomain getEditingDomain()
	{
		return (EditingDomain) editor.getAdapter(EditingDomain.class);
	}


	/**
	 * @return The {@link AdapterFactory} from an {@link AdapterFactoryEditingDomain} if
	 *         available.
	 */
	public AdapterFactory getAdapterFactory()
	{
		return (AdapterFactory) editor.getAdapter(AdapterFactory.class);
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.views.contentoutline.ContentOutlinePage#init(org.eclipse.ui.part
	 * .IPageSite)
	 */
	@Override
	public void init(IPageSite pageSite)
	{
		super.init(pageSite);

		// add outline to selection synchronizer
		editor.getSelectionSynchronizer().addSelectionProvider(this);

		// add context menu listener
		getContextMenuManager().addMenuListener(editor.getContextMenuProvider());

		// register action handlers for context manu
		ActionRegistry ar = (ActionRegistry) editor.getAdapter(ActionRegistry.class);
		IActionBars actionBars = pageSite.getActionBars();
		ArrayList globalActionIDs = editor.getGlobalActionKeys();

		for (int i = 0; i < globalActionIDs.size(); i++)
		{
			String id = (String) globalActionIDs.get(i);
			actionBars.setGlobalActionHandler(id, ar.getAction(id));
		}
		actionBars.updateActionBars();
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.views.contentoutline.ContentOutlinePage#createControl(org.eclipse
	 * .swt.widgets.Composite)
	 */
	@Override
	public void createControl(Composite parent)
	{
		// create the main area
		mainArea = new SashForm(parent, SWT.VERTICAL);
		mainArea.setSashWidth(3);

		// create the overview outline area
		overviewOutlineArea = new ModelOutlineAreaOverview(this);

		// create the content outline area
		super.createControl(mainArea);
		treeviewerOutlineArea = new ModelOutlineAreaTreeviewer(this, editor,
				getTreeViewer());

		// refresh the outline page
		refresh();
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.views.contentoutline.ContentOutlinePage#getControl()
	 */
	@Override
	public Control getControl()
	{
		return mainArea;
	}

	
	/**
	 * The current display mode.
	 * 
	 * @return The display mode.
	 */
	public String getCurrentDisplayMode()
	{
		return current_display_mode;
	}

	
	/**
	 * Refreshes this outline, i.e. forces an update of the outline and resets sorting and
	 * filtering options.
	 */
	public void refresh()
	{
		// only if outline is active
		if (mainArea == null || mainArea.isDisposed())
		{
			return;
		}

		// on refresh (view changed, preferences set), refresh only if setting has
		// actually changed

		// if both areas should be displayed
		if (PreferenceReader.outlineShowArea.get().equals(OUTLINE_AREA_BOTH)
				&& !current_display_mode.equals(OUTLINE_AREA_BOTH))
		{
			mainArea.setSashWidth(3);
			int[] weights =
			{ Math.max(PreferenceReader.outlineOverviewSize.get(), 50),
					Math.max(PreferenceReader.outlineTreeviewSize.get(), 50) };
			mainArea.setWeights(weights);

			current_display_mode = OUTLINE_AREA_BOTH;
		}
		// if overview should be displayed
		else if (PreferenceReader.outlineShowArea.get().equals(OUTLINE_AREA_OVERVIEW)
				&& !current_display_mode.equals(OUTLINE_AREA_OVERVIEW))
		{
			mainArea.setSashWidth(0);
			int[] weights =
			{ 100, 0 };
			mainArea.setWeights(weights);

			current_display_mode = OUTLINE_AREA_OVERVIEW;
		}
		// if treeview should be displayed
		else if (PreferenceReader.outlineShowArea.get().equals(OUTLINE_AREA_TREEVIEW)
				&& !current_display_mode.equals(OUTLINE_AREA_TREEVIEW))
		{
			mainArea.setSashWidth(0);
			int[] weights =
			{ 0, 100 };
			mainArea.setWeights(weights);

			current_display_mode = OUTLINE_AREA_TREEVIEW;
		}

		// refresh overview area
		if (overviewOutlineArea != null)
		{
			overviewOutlineArea.refresh(editor);
		}

		// refresh tree viewer area
		if (treeviewerOutlineArea != null)
		{
			treeviewerOutlineArea.refresh(getTreeViewer());
		}
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.jface.viewers.IDoubleClickListener#doubleClick(org.eclipse.jface.viewers
	 * .DoubleClickEvent)
	 */
	public void doubleClick(DoubleClickEvent event)
	{
		// on double click in tree viewer, open activity in new page
		if (!(event.getSelection() instanceof IStructuredSelection))
		{
			return;
		}
		IStructuredSelection selection = (IStructuredSelection) event.getSelection();

		// if an activity is selected, show it in a new page
		if (selection.size() == 1 && selection.getFirstElement() instanceof Activity)
		{
			editor.openActivityInNewPage((Activity) selection.getFirstElement());
		}
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.part.Page#dispose()
	 */
	@Override
	public void dispose()
	{
		// remove from selectionsynchronizer
		editor.getSelectionSynchronizer().removeSelectionProvider(this);

		// dispose overview outline
		if (overviewOutlineArea != null)
		{
			overviewOutlineArea.dispose();
		}
		
		// dispose tree viewer
		if (treeviewerOutlineArea != null)
		{
			treeviewerOutlineArea.dispose();
		}

		super.dispose();
	}

}