/*******************************************************************************
 * Copyright (c) 2004, 2005 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
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.internal.dialogs;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.preference.IPreferenceNode;
import org.eclipse.jface.preference.IPreferencePageContainer;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;

/**
 * The PreferencesPageContainer is the container object for the preference pages
 * in a node.
 */
public class PreferencesPageContainer implements IPreferencePageContainer {

	private Composite control;

	private ScrolledComposite scrolled;

	private class PreferenceEntry {

		Composite composite;

		IPreferenceNode node;

		String title;

		int offset;

		Label expandImage;

		Label titleLabel;

		Composite pageContainer;

		/**
		 * Create a new instance of the receiver.
		 * 
		 * @param displayedNode
		 * @param pageTitle
		 */
		PreferenceEntry(IPreferenceNode displayedNode, String pageTitle) {
			node = displayedNode;
			title = pageTitle;
		}

		/**
		 * Add the subnodes of the receiver.
		 */
		private void addSubNodes() {
			IPreferenceNode[] subnodes = node.getSubNodes();
			PreferenceEntry previous = null;
			for (int i = 0; i < subnodes.length; i++) {
				PreferenceEntry entry = createEntry(subnodes[i], subnodes[i]
						.getLabelText(), offset + 1);
				if (previous == null)
					entry.composite.moveBelow(this.composite);
				else
					entry.composite.moveBelow(previous.composite);
				previous = entry;
			}
		}

		/**
		 * Create the contents of the entry in parent. When laying this out
		 * indent the composite ident units.
		 * 
		 * @param indent
		 */
		void createContents(int indent) {

			composite = new Composite(control, SWT.NULL);

			// Create the title area which will contain
			// a title, message, and image.

			GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
			gridData.horizontalIndent = IDialogConstants.SMALL_INDENT * indent;
			composite.setLayoutData(gridData);

			FormLayout layout = new FormLayout();
			layout.marginHeight = 0;
			layout.marginWidth = 0;
			composite.setLayout(layout);

			Font titleFont = JFaceResources.getBannerFont();

			expandImage = new Label(composite, SWT.RIGHT);
			expandImage.setText("+");//$NON-NLS-1$
			expandImage.setFont(titleFont);

			FormData imageData = new FormData();
			imageData.top = new FormAttachment(0);
			imageData.left = new FormAttachment(0,
					IDialogConstants.HORIZONTAL_SPACING);
			expandImage.setLayoutData(imageData);

			// Title image
			titleLabel = new Label(composite, SWT.LEFT);
			titleLabel.setText(title);
			titleLabel.setFont(titleFont);

			FormData titleData = new FormData();
			titleData.right = new FormAttachment(100);
			titleData.top = new FormAttachment(0);
			titleData.left = new FormAttachment(expandImage,
					IDialogConstants.HORIZONTAL_SPACING);
			titleLabel.setLayoutData(titleData);

			titleLabel.addMouseListener(new MouseAdapter() {
				/*
				 * (non-Javadoc)
				 * 
				 * @see org.eclipse.swt.events.MouseAdapter#mouseDown(org.eclipse.swt.events.MouseEvent)
				 */
				public void mouseDown(MouseEvent e) {

					if (pageContainer == null) {
						boolean adjustScrollbars = false;

						pageContainer = new Composite(composite, SWT.BORDER);

						FormData containerData = new FormData();
						containerData.top = new FormAttachment(titleLabel, 0);
						containerData.left = new FormAttachment(0);
						containerData.right = new FormAttachment(100);
						pageContainer.setLayoutData(containerData);

						pageContainer.setLayout(new GridLayout());

						node.createPage();
						node.getPage().createControl(pageContainer);
						node.getPage().setContainer(
								PreferencesPageContainer.this);
						node.getPage().getControl().setLayoutData(
								new GridData(GridData.FILL_BOTH));
						adjustScrollbars = true;

						Point contentSize = node.getPage().computeSize();
						Rectangle totalArea = composite.getClientArea();

						if (contentSize.x < totalArea.width)
							contentSize.x = totalArea.width;

						node.getPage().setSize(contentSize);
						if (adjustScrollbars)
							adjustScrollbars(contentSize);

						expandImage.setText("-");//$NON-NLS-1$

						addSubNodes();

						setSelectionColors(composite.getDisplay()
								.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
					} else {
						setSelectionColors(null);
						pageContainer.dispose();
						pageContainer = null;
						expandImage.setText("+");//$NON-NLS-1$
					}

					control.layout(true);
				}
			});
			offset = indent;
		}

		/**
		 * Set the background colors and the labels due to selection.
		 * 
		 * @param highlight
		 *            The highlight to set
		 */
		private void setSelectionColors(Color highlight) {
			composite.setBackground(highlight);
			titleLabel.setBackground(highlight);
			expandImage.setBackground(highlight);
		}

	}

	/**
	 * Create a new instance of the receiver.
	 */
	public PreferencesPageContainer() {
		super();
	}

	/**
	 * Create the contents area of the composite.
	 * 
	 * @param parent
	 * @param style
	 */
	void createContents(Composite parent, int style) {
		scrolled = new ScrolledComposite(parent, SWT.V_SCROLL | SWT.H_SCROLL);

		GridData newPageData = new GridData(GridData.FILL_BOTH);
		scrolled.setLayoutData(newPageData);

		control = new Composite(scrolled, style);

		scrolled.setContent(control);
		scrolled.setExpandVertical(true);
		scrolled.setExpandHorizontal(true);
		GridData controlData = new GridData(GridData.FILL_BOTH);
		control.setLayoutData(controlData);

		GridLayout layout = new GridLayout();
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		layout.verticalSpacing = 1;
		control.setLayout(layout);

	}

	/**
	 * Return the top level control
	 * 
	 * @return Control
	 */
	Control getControl() {
		return control;
	}

	/**
	 * Show the selected node. Return whether or not this succeeded.
	 * 
	 * @param node
	 * @return <code>true</code> if the page selection was sucessful
	 *         <code>false</code> is unsuccessful
	 */
	boolean show(IPreferenceNode node) {
		createGeneralEntry(node);
		control.layout(true);
		return true;
	}

	/**
	 * Create an entry for the receiver with the general tag. Do not recurse
	 * through the children as this is the implied top node.
	 * 
	 * @param node
	 */
	private void createGeneralEntry(IPreferenceNode node) {
		PreferenceEntry entry = createEntry(node, "General", 0); //$NON-NLS-1$
		entry.addSubNodes();

	}

	/**
	 * Create an entry with the given title for the IPreferenceNode with an
	 * indent i.
	 * 
	 * @param node
	 * @param name
	 * @param indent
	 * @return the entry
	 */
	private PreferenceEntry createEntry(IPreferenceNode node, String name,
			int indent) {
		PreferenceEntry entry = new PreferenceEntry(node, name);
		entry.createContents(indent);
		return entry;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.preference.IPreferencePageContainer#getPreferenceStore()
	 */
	public IPreferenceStore getPreferenceStore() {
		// TODO Auto-generated method stub
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.preference.IPreferencePageContainer#updateButtons()
	 */
	public void updateButtons() {
		// TODO Auto-generated method stub

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.preference.IPreferencePageContainer#updateMessage()
	 */
	public void updateMessage() {
		// TODO Auto-generated method stub

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.preference.IPreferencePageContainer#updateTitle()
	 */
	public void updateTitle() {
		// TODO Auto-generated method stub

	}

	/**
	 * Adjust the scrollbars for the content that just got added.
	 * 
	 * @param contentSize
	 */
	private void adjustScrollbars(Point contentSize) {

		Point size = control.getSize();
		scrolled.setMinHeight(size.y + contentSize.y);
		scrolled.setMinWidth(Math.max(size.x, contentSize.x));
	}

}
