/*******************************************************************************
 * Copyright (c) 2000, 2010 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.gef.ui.palette.customize;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.ControlPaintHandler;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuCreator;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.PageBook;

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.swt.SWT;
import org.eclipse.draw2d.widgets.MultiLineLabel;

import org.eclipse.gef.internal.Internal;
import org.eclipse.gef.internal.ui.palette.ToolbarDropdownContributionItem;
import org.eclipse.gef.palette.PaletteEntry;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.ui.palette.PaletteCustomizer;
import org.eclipse.gef.ui.palette.PaletteMessages;

/**
 * This class implements a default dialog that allows customization of the
 * different entries/items on a GEF palette, i.e. the model behind the palette.
 * <p>
 * The construction of the dialog is broken down into different methods in order
 * to allow clients to further customize the appearance of the dialog, if so
 * desired.
 * </p>
 * <p>
 * This dialog can be re-used, i.e., it can be re-opened once closed. There is
 * no need to create a new <code>PaletteCustomizerDialog</code> everytime a
 * palette needs to be customized.
 * </p>
 * 
 * @author Pratik Shah
 * @see org.eclipse.gef.palette.PaletteEntry
 * @see org.eclipse.gef.ui.palette.PaletteCustomizer
 */
public class PaletteCustomizerDialog extends Dialog implements
		EntryPageContainer {

	/**
	 * The unique ID for the Apply Button. It can be used to retrieve that
	 * widget from the internal map (using {@link #getWidget(int)} or
	 * {@link #getButton(int)}), or to identify that widget in
	 * {@link #buttonPressed(int)}.
	 */
	protected static final int APPLY_ID = IDialogConstants.CLIENT_ID + 1;

	/**
	 * Sub-classes that need to create their own unique IDs should do so by
	 * adding to this ID.
	 */
	protected static final int CLIENT_ID = 16;

	private HashMap widgets = new HashMap();
	private HashMap entriesToPages = new HashMap();
	private List actions;

	private String errorMessage;
	private Tree tree;
	private Composite titlePage, errorPage;
	private PageBook propertiesPanelContainer;
	// This PageBook is used to switch the title of the properties panel to
	// either an error
	// message or the currently active entry's label
	private PageBook titleSwitcher;
	private PaletteCustomizer customizer;
	private EntryPage activePage, noSelectionPage;
	private CLabel title;
	private MultiLineLabel errorTitle;
	private Image titleImage;
	private TreeViewer treeviewer;
	private ILabelProvider treeViewerLabelProvider;
	private PaletteEntry activeEntry;
	private PaletteEntry initialSelection;
	private PaletteRoot root;
	private PropertyChangeListener titleUpdater = new PropertyChangeListener() {
		public void propertyChange(PropertyChangeEvent evt) {
			if (title == null) {
				return;
			}

			title.setText(((PaletteEntry) evt.getSource()).getLabel());
		}
	};
	private ISelectionChangedListener pageFlippingPreventer = new ISelectionChangedListener() {
		public void selectionChanged(SelectionChangedEvent event) {
			treeviewer.removePostSelectionChangedListener(this);
			treeviewer.setSelection(new StructuredSelection(activeEntry));
		}
	};
	private boolean isSetup = true;

	/**
	 * Constructs a new customizer dialog.
	 * 
	 * @param shell
	 *            the parent Shell
	 * @param customizer
	 *            the customizer
	 * @param root
	 *            the palette root
	 */
	public PaletteCustomizerDialog(Shell shell, PaletteCustomizer customizer,
			PaletteRoot root) {
		super(shell);
		this.customizer = customizer;
		this.root = root;
		setShellStyle(getShellStyle() | SWT.RESIZE);
	}

	/**
	 * This method will be invoked whenever any <code>Button</code> created
	 * using {@link #createButton(Composite, int, String, int, ImageDescriptor)}
	 * or {@link Dialog#createButton(Composite, int, String, boolean)} is
	 * selected.
	 * 
	 * @see Dialog#buttonPressed(int)
	 */
	protected void buttonPressed(int buttonId) {
		if (APPLY_ID == buttonId) {
			handleApplyPressed();
		} else {
			super.buttonPressed(buttonId);
		}
	}

	/**
	 * This method should be invoked by EntryPages when an error that they had
	 * earlier reported (using {@link #showProblem(String)}) is fixed. This will
	 * hide the error message, enable the OK and Apply buttons and re-allow
	 * changing selection in the outline tree.
	 * 
	 * @see org.eclipse.gef.ui.palette.customize.EntryPageContainer#clearProblem()
	 * @see #showProblem(String)
	 */
	public void clearProblem() {
		if (errorMessage != null) {
			titleSwitcher.showPage(titlePage);
			getButton(IDialogConstants.OK_ID).setEnabled(true);
			getButton(APPLY_ID).setEnabled(true);
			errorMessage = null;
		}
	}

	/**
	 * <p>
	 * NOTE: This dialog can be re-opened.
	 * </p>
	 * 
	 * @see org.eclipse.jface.window.Window#close()
	 */
	public boolean close() {
		// Remove listeners
		if (activeEntry != null) {
			activeEntry.removePropertyChangeListener(titleUpdater);
		}

		// Save or dump changes
		// This needs to be done here and not in the handle methods because the
		// user can
		// also close the dialog with the 'X' in the top right of the window
		// (which
		// corresponds to a cancel).
		if (getReturnCode() == OK) {
			save();
		} else {
			revertToSaved();
		}

		// Close the dialog
		boolean returnVal = super.close();

		// Reset variables
		entriesToPages.clear();
		widgets.clear();
		actions = null;
		activePage = null;
		tree = null;
		propertiesPanelContainer = null;
		titleSwitcher = null;
		titlePage = null;
		errorPage = null;
		title = null;
		errorTitle = null;
		treeviewer = null;
		noSelectionPage = null;
		initialSelection = null;
		activeEntry = null;
		errorMessage = null;
		isSetup = true;

		return returnVal;
	}

	/**
	 * @see org.eclipse.jface.window.Window#configureShell(Shell)
	 */
	protected void configureShell(Shell newShell) {
		newShell.setText(PaletteMessages.CUSTOMIZE_DIALOG_TITLE);
		super.configureShell(newShell);
	}

	/**
	 * This method should not be used to create buttons for the button bar. Use
	 * {@link Dialog#createButton(Composite, int, String, boolean)} for that.
	 * This method can be used to create any other button in the dialog. The
	 * parent <code>Composite</code> must have a GridLayout. These buttons will
	 * be available through {@link #getButton(int)} and {@link #getWidget(int)}.
	 * Ensure that the various buttons created by this method are given unique
	 * IDs. Pass in a <code>null</code> image descriptor if you don't want the
	 * button to have an icon. This method will take care of disposing the
	 * images that it creates. {@link #buttonPressed(int)} will be called when
	 * any of the buttons created by this method are clicked (selected).
	 * 
	 * @param parent
	 *            The composite in which the button is to be created
	 * @param id
	 *            The button's unique ID
	 * @param label
	 *            The button's text
	 * @param stylebits
	 *            The style bits for creating the button (eg.,
	 *            <code>SWT.PUSH</code> or <code>SWT.CHECK</code>)
	 * @param descriptor
	 *            The ImageDescriptor from which the image/icon for this button
	 *            should be created
	 * @return The newly created button for convenience
	 */
	protected Button createButton(Composite parent, int id, String label,
			int stylebits, ImageDescriptor descriptor) {
		Button button = new Button(parent, stylebits);
		button.setText(label);
		button.setFont(parent.getFont());
		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
		button.setLayoutData(data);

		button.setData(new Integer(id));
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				buttonPressed(((Integer) event.widget.getData()).intValue());
			}
		});
		widgets.put(new Integer(id), button);

		if (descriptor != null) {
			button.setImage(new Image(parent.getDisplay(), descriptor
					.getImageData()));
			button.addDisposeListener(new DisposeListener() {
				public void widgetDisposed(DisposeEvent e) {
					Image img = ((Button) e.getSource()).getImage();
					if (img != null && !img.isDisposed()) {
						img.dispose();
					}
				}
			});
		}

		return button;
	}

	/**
	 * Creates the OK, Cancel and Apply buttons
	 * 
	 * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(Composite)
	 */
	protected void createButtonsForButtonBar(Composite parent) {
		super.createButtonsForButtonBar(parent);
		createButton(parent, APPLY_ID, PaletteMessages.APPLY_LABEL, false);
	}

	/**
	 * The dialog area contains the following:
	 * <UL>
	 * <LI>Outline ({@link #createOutline(Composite)})</LI>
	 * <LI>Properties Panel ({@link #createPropertiesPanel(Composite)})</LI>
	 * </UL>
	 * 
	 * <p>
	 * It is recommended that this method not be overridden. Override one of the
	 * methods that this method calls in order to customize the appearance of
	 * the dialog.
	 * </p>
	 * 
	 * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(Composite)
	 */
	protected Control createDialogArea(Composite parent) {
		Composite composite = (Composite) super.createDialogArea(parent);
		GridLayout gridLayout = (GridLayout) composite.getLayout();
		gridLayout.numColumns = 2;
		gridLayout.horizontalSpacing = 10;

		// Create the tree
		Control child = createOutline(composite);
		GridData data = new GridData(GridData.VERTICAL_ALIGN_FILL);
		data.verticalSpan = 2;
		child.setLayoutData(data);

		// Create the panel where the properties of the selected palette entry
		// will
		// be shown
		child = createPropertiesPanel(composite);
		child.setLayoutData(new GridData(GridData.FILL_BOTH));

		// Create the separator b/w the dialog area and the button bar
		Label label = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
		data = new GridData(GridData.FILL_HORIZONTAL);
		data.horizontalSpan = 2;
		label.setLayoutData(data);

		// Select an element in the outline and set focus on the outline.
		if (initialSelection == null) {
			// We have to manually select the first item in the tree, because
			// otherwise the
			// will scroll to show the last item, and then will select the first
			// visible item.
			List children = getPaletteRoot().getChildren();
			if (!children.isEmpty()) {
				initialSelection = (PaletteEntry) children.get(0);
			}
		}
		if (initialSelection != null) {
			treeviewer.setSelection(new StructuredSelection(initialSelection));
		} else {
			setActiveEntry(null);
		}
		isSetup = false;
		tree.setFocus();

		return composite;
	}

	/**
	 * Creates the outline part of the dialog.
	 * 
	 * <p>
	 * The outline creates the following:
	 * <UL>
	 * <LI>ToolBar ({@link #createOutlineToolBar(Composite)})</LI>
	 * <LI>TreeViewer ({@link #createOutlineTreeViewer(Composite)})</LI>
	 * <LI>Context menu ({@link #createOutlineContextMenu()})</LI>
	 * </UL>
	 * </p>
	 * 
	 * @param container
	 *            The Composite within which the outline has to be created
	 * @return The newly created Control that has the outline
	 */
	protected Control createOutline(Composite container) {
		// Create the Composite that will contain the outline
		Composite composite = new Composite(container, SWT.NONE);
		composite.setFont(container.getFont());
		GridLayout layout = new GridLayout();
		layout.horizontalSpacing = 0;
		layout.verticalSpacing = 0;
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		composite.setLayout(layout);

		// Create the ToolBar
		createOutlineToolBar(composite);

		// Create the actual outline (TreeViewer)
		treeviewer = createOutlineTreeViewer(composite);
		tree = treeviewer.getTree();

		// Create the context menu for the Tree
		tree.setMenu(createOutlineContextMenu());

		return composite;
	}

	/**
	 * Creates the actions that manipulate the palette model. These actions will
	 * populate the toolbar and the outline's context menu.
	 * 
	 * <p>
	 * IMPORTANT: All the elements in the returned List MUST be
	 * <code>PaletteCustomizationAction</code>s.
	 * </p>
	 * 
	 * @return A List of {@link PaletteCustomizationAction
	 *         PaletteCustomizationActions}
	 */
	protected List createOutlineActions() {
		List actions = new ArrayList();
		actions.add(new NewAction());
		actions.add(new DeleteAction());
		actions.add(new MoveDownAction());
		actions.add(new MoveUpAction());
		return actions;
	}

	/**
	 * Uses a <code>MenuManager</code> to create the context menu for the
	 * outline. The <code>IActions</code> used to create the context menu are
	 * those created in {@link #createOutlineActions()}.
	 * 
	 * @return The newly created Menu
	 */
	protected Menu createOutlineContextMenu() {
		// MenuManager for the tree's context menu
		final MenuManager outlineMenu = new MenuManager();

		List actions = getOutlineActions();
		// Add all the actions to the context menu
		for (Iterator iter = actions.iterator(); iter.hasNext();) {
			IAction action = (IAction) iter.next();
			if (action instanceof IMenuCreator)
				outlineMenu.add(new ActionContributionItem(action) {
					public boolean isDynamic() {
						return true;
					}
				});
			else
				outlineMenu.add(action);
			// Add separators after new and delete
			if (action instanceof NewAction || action instanceof DeleteAction) {
				outlineMenu.add(new Separator());
			}
		}

		outlineMenu.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager manager) {
				outlineMenu.update(true);
			}
		});

		outlineMenu.createContextMenu(tree);
		return outlineMenu.getMenu();
	}

	/**
	 * Uses a ToolBarManager to create the ToolBar in the outline part of the
	 * dialog. The Actions used in the ToolBarManager are those that are created
	 * in {@link #createOutlineActions()}.
	 * 
	 * @param parent
	 *            The Composite to which the ToolBar is to be added
	 * @return The newly created ToolBar
	 */
	protected Control createOutlineToolBar(Composite parent) {
		// A customized composite for the toolbar
		final Composite composite = new Composite(parent, SWT.NONE) {
			public Rectangle getClientArea() {
				Rectangle area = super.getClientArea();
				area.x += 2;
				area.y += 2;
				area.height -= 2;
				area.width -= 4;
				return area;
			}

			public Point computeSize(int wHint, int hHint, boolean changed) {
				Point size = super.computeSize(wHint, hHint, changed);
				size.x += 4;
				size.y += 2;
				return size;
			}
		};
		composite.setFont(parent.getFont());
		composite.setLayout(new FillLayout());

		// A paint listener that draws an etched border around the toolbar
		ControlPaintHandler helper = new ControlPaintHandler(composite);
		helper.addPaintListener(new PaintListener() {
			public void paintControl(PaintEvent e) {
				Rectangle area = composite.getBounds();
				GC gc = e.gc;
				// UNSUPPORTED - api not implemented in RAP
				// gc.setLineStyle(SWT.LINE_SOLID);
				gc.setForeground(ColorConstants.buttonDarker);
				gc.drawLine(area.x, area.y, area.x + area.width - 2, area.y);
				gc.drawLine(area.x, area.y, area.x, area.y + area.height - 1);
				gc.drawLine(area.x + area.width - 2, area.y, area.x
						+ area.width - 2, area.y + area.height - 1);
				gc.setForeground(ColorConstants.buttonLightest);
				gc.drawLine(area.x + 1, area.y + 1, area.x + area.width - 3,
						area.y + 1);
				gc.drawLine(area.x + area.width - 1, area.y + 1, area.x
						+ area.width - 1, area.y + area.height - 1);
				gc.drawLine(area.x + 1, area.y + 1, area.x + 1, area.y
						+ area.height - 1);
			}
		});

		// Create the ToolBarManager and add all the actions to it
		ToolBarManager tbMgr = new ToolBarManager(SWT.FLAT | SWT.HORIZONTAL);
		List actions = getOutlineActions();
		for (int i = 0; i < actions.size(); i++) {
			tbMgr.add(new ToolbarDropdownContributionItem(((IAction) actions
					.get(i))));
		}
		tbMgr.createControl(composite);
		tbMgr.getControl().setFont(composite.getFont());

		// By default, the ToolBarManager does not set text on ToolItems. Since,
		// we want to display the text, we will have to do it manually.
		ToolItem[] items = tbMgr.getControl().getItems();
		for (int i = 0; i < items.length; i++) {
			ToolItem item = items[i];
			item.setText(((IAction) actions.get(i)).getText());
		}

		return tbMgr.getControl();
	}

	/**
	 * Creates the TreeViewer that is the outline of the model.
	 * 
	 * @param composite
	 *            The Composite to which the ToolBar is to be added
	 * @return The newly created TreeViewer
	 */
	protected TreeViewer createOutlineTreeViewer(Composite composite) {
		Tree treeForViewer = new Tree(composite, SWT.BORDER);
		treeForViewer.setFont(composite.getFont());
		GridData data = new GridData(GridData.FILL_VERTICAL
				| GridData.HORIZONTAL_ALIGN_FILL);
		data.widthHint = 185;
		// Make the tree this tall even when there is nothing in it. This will
		// keep the
		// dialog from shrinking to an unusually small size.
		data.heightHint = 200;
		treeForViewer.setLayoutData(data);
		TreeViewer viewer = new TreeViewer(treeForViewer) {
			protected void preservingSelection(Runnable updateCode) {
				if ((getTree().getStyle() & SWT.SINGLE) != 0)
					updateCode.run();
				else
					super.preservingSelection(updateCode);
			}
		};
		viewer.setContentProvider(new PaletteTreeProvider(viewer));
		treeViewerLabelProvider = new PaletteLabelProvider(viewer);
		viewer.setLabelProvider(treeViewerLabelProvider);
		viewer.setInput(getPaletteRoot());
		viewer.addSelectionChangedListener(new ISelectionChangedListener() {
			public void selectionChanged(SelectionChangedEvent event) {
				handleOutlineSelectionChanged();
			}
		});

		return viewer;
	}

	/**
	 * Creates the part of the dialog where the properties of the element
	 * selected in the outline will be displayed.
	 * 
	 * <p>
	 * The properties panel contains the following:
	 * <UL>
	 * <LI>Title ({@link #createPropertiesPanelTitle(Composite)})</LI>
	 * </UL>
	 * The rest of the panel is constructed in this method.
	 * </p>
	 * 
	 * @param container
	 *            The Composite to which this part is to be added
	 * @return The properties panel
	 */
	protected Control createPropertiesPanel(Composite container) {
		Composite composite = new Composite(container, SWT.NONE);
		composite.setFont(container.getFont());
		GridLayout layout = new GridLayout(1, false);
		layout.horizontalSpacing = 0;
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		layout.verticalSpacing = 0;
		composite.setLayout(layout);

		titleSwitcher = createPropertiesPanelTitle(composite);

		propertiesPanelContainer = new PageBook(composite, SWT.NONE);
		propertiesPanelContainer.setFont(composite.getFont());
		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL
				| GridData.FILL_VERTICAL);
		data.horizontalSpan = 2;
		propertiesPanelContainer.setLayoutData(data);
		propertiesPanelContainer.addListener(SWT.Resize, new Listener() {
			public void handleEvent(Event event) {
				if (activePage != null) {
					propertiesPanelContainer.layout();
				}
			}
		});

		return composite;
	}

	/**
	 * Creates the title for the properties panel. It is a PageBook that can
	 * switch between showing the regular title (the selected entry's label and
	 * icon) and an error message if an error has occured.
	 * 
	 * @param parent
	 *            The parent composite
	 * @return The newly created PageBook title
	 */
	protected PageBook createPropertiesPanelTitle(Composite parent) {
		GridLayout layout;
		PageBook book = new PageBook(parent, SWT.NONE);
		book.setFont(parent.getFont());
		book.setLayoutData(new GridData(GridData.FILL_HORIZONTAL
				| GridData.VERTICAL_ALIGN_FILL));

		titlePage = new Composite(book, SWT.NONE);
		titlePage.setFont(book.getFont());
		layout = new GridLayout(2, false);
		layout.horizontalSpacing = 0;
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		layout.verticalSpacing = 0;
		titlePage.setLayout(layout);
		title = createSectionTitle(titlePage,
				PaletteMessages.NO_SELECTION_TITLE);

		errorPage = new Composite(book, SWT.NONE);
		errorPage.setFont(book.getFont());
		layout = new GridLayout(1, false);
		layout.horizontalSpacing = 0;
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		layout.verticalSpacing = 0;
		errorPage.setLayout(layout);
		Composite intermediary = new Composite(errorPage, SWT.NONE) {
			public Point computeSize(int wHint, int hHint, boolean changed) {
				Rectangle bounds = title.getBounds();
				return new Point(bounds.width, bounds.height);
			}
		};
		intermediary.setLayoutData(new GridData(GridData.FILL_HORIZONTAL
				| GridData.VERTICAL_ALIGN_FILL));
		StackLayout stackLayout = new StackLayout();
		intermediary.setLayout(stackLayout);
		errorTitle = new MultiLineLabel(intermediary);
		stackLayout.topControl = errorTitle;
		errorTitle.setImage(JFaceResources.getImage(DLG_IMG_MESSAGE_ERROR));
		errorTitle.setFont(errorPage.getFont());
		Label separator = new Label(errorPage, SWT.SEPARATOR | SWT.HORIZONTAL);
		separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		book.showPage(titlePage);
		return book;
	}

	/**
	 * A convenient method to create CLabel titles (like the ones used in the
	 * Preferences dialog in the Eclipse workbench) throughout the dialog.
	 * 
	 * @param composite
	 *            The composite in which the title is to be created (it must
	 *            have a GridLayout with two columns).
	 * @param text
	 *            The title to be displayed
	 * @return The newly created CLabel for convenience
	 */
	protected CLabel createSectionTitle(Composite composite, String text) {
		CLabel cTitle = new CLabel(composite, SWT.LEFT);
		Color background = JFaceColors.getBannerBackground(composite
				.getDisplay());
		Color foreground = JFaceColors.getBannerForeground(composite
				.getDisplay());
		JFaceColors.setColors(cTitle, foreground, background);
		cTitle.setFont(JFaceResources.getBannerFont());
		cTitle.setText(text);
		cTitle.setLayoutData(new GridData(GridData.FILL_HORIZONTAL
				| GridData.VERTICAL_ALIGN_FILL));

		if (titleImage == null) {
			titleImage = new Image(composite.getDisplay(), ImageDescriptor
					.createFromFile(Internal.class,
							"icons/customizer_dialog_title.gif").getImageData()); //$NON-NLS-1$
			composite.addDisposeListener(new DisposeListener() {
				public void widgetDisposed(DisposeEvent e) {
					titleImage.dispose();
					titleImage = null;
				}
			});
		}

		Label imageLabel = new Label(composite, SWT.LEFT);
		imageLabel.setBackground(background);
		imageLabel.setImage(titleImage);
		imageLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL
				| GridData.VERTICAL_ALIGN_FILL));

		Label separator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
		data.horizontalSpan = 2;
		separator.setLayoutData(data);

		return cTitle;
	}

	/**
	 * Returns the Button with the given id; or <code>null</code> if none was
	 * found.
	 * 
	 * @see org.eclipse.jface.dialogs.Dialog#getButton(int)
	 */
	protected Button getButton(int id) {
		Button button = null;
		Widget widget = getWidget(id);
		if (widget instanceof Button) {
			button = (Button) widget;
		}

		return button;
	}

	/**
	 * @return The customizer that is responsible for handling the various tasks
	 *         and updating the model.
	 */
	protected PaletteCustomizer getCustomizer() {
		return customizer;
	}

	/**
	 * Returns the <code>EntryPage</code> for the given
	 * <code>PaletteEntry</code> . The <code>EntryPage</code> is retrieved from
	 * the customizer. If the given entry is <code>null</code>,
	 * <code>null</code> will be returned. If the customizer returns
	 * <code>null</code> for the valid entry, a default page will be created and
	 * returned.
	 * 
	 * @param entry
	 *            The PaletteEntry whose properties need to be displayed
	 * @return The EntryPage with the properties of the given PaletteEntry
	 */
	protected EntryPage getEntryPage(PaletteEntry entry) {
		if (entry == null) {
			return null;
		}

		if (entriesToPages.containsKey(entry)) {
			return (EntryPage) entriesToPages.get(entry);
		}

		EntryPage page = getCustomizer().getPropertiesPage(entry);
		if (page == null) {
			page = new DefaultEntryPage();
		}
		page.createControl(propertiesPanelContainer, entry);
		page.setPageContainer(this);
		entriesToPages.put(entry, page);

		return page;
	}

	/**
	 * Provides access to the actions that are used to manipulate the model. The
	 * actions will be created, if they haven't been yet.
	 * 
	 * @return the list of <code>PaletteCustomizationAction</code>s
	 * @see #createOutlineActions()
	 */
	protected final List getOutlineActions() {
		if (actions == null) {
			actions = createOutlineActions();
		}
		return actions;
	}

	/**
	 * Provides sub-classes with access to the PaletteRoot
	 * 
	 * @return the palette root
	 */
	protected PaletteRoot getPaletteRoot() {
		return root;
	}

	/**
	 * @return The PaletteEntry that is currently selected in the Outline Tree;
	 *         <code>null</code> if none is selected
	 */
	protected PaletteEntry getSelectedPaletteEntry() {
		TreeItem item = getSelectedTreeItem();
		if (item != null) {
			return (PaletteEntry) item.getData();
		}
		return null;

	}

	/**
	 * @return The TreeItem that is currently selected in the Outline Tree;
	 *         <code>null</code> if none is selected
	 */
	protected TreeItem getSelectedTreeItem() {
		TreeItem[] items = tree.getSelection();
		if (items.length > 0) {
			return items[0];
		}
		return null;
	}

	/**
	 * The <code>Widget</code>s that were created with a unique ID and added to
	 * this class' internal map can be retrieved through this method.
	 * 
	 * @param id
	 *            The unique ID of the Widget that you wish to retrieve
	 * @return The Widget, if one with the given id exists; <code>null</code>
	 *         otherwise
	 */
	protected Widget getWidget(int id) {
		Widget widget = (Widget) widgets.get(new Integer(id));
		if (widget == null) {
			widget = super.getButton(id);
		}

		return widget;
	}

	/**
	 * This method is invoked when the Apply button is pressed
	 * <p>
	 * IMPORTANT: It is recommended that you not override this method. Closing
	 * the dialog with the 'X' at the top right of the window, or by hitting
	 * 'Esc' or any other way, corresponds to a "Cancel." That will, however,
	 * not result in this method being invoked. To handle such cases, saving or
	 * rejecting the changes is handled in {@link #close()}. Override
	 * {@link #save()} and {@link #revertToSaved()} to add to what needs to be
	 * done when saving or cancelling.
	 * </p>
	 */
	protected final void handleApplyPressed() {
		save();
	}

	/**
	 * This method is called when the "Delete" action is run (either through the
	 * context menu or the toolbar). It deletes the selected palette entry.
	 */
	protected void handleDelete() {
		getCustomizer().performDelete(getSelectedPaletteEntry());
		handleOutlineSelectionChanged();
	}

	/**
	 * This method is called when the "Move Down" action is run (either through
	 * the context menu or the toolbar). It moves the selected palette entry
	 * down.
	 */
	protected void handleMoveDown() {
		PaletteEntry entry = getSelectedPaletteEntry();
		getCustomizer().performMoveDown(entry);
		treeviewer.setSelection(new StructuredSelection(entry), true);
		updateActions();
	}

	/**
	 * This method is called when the "Move Up" action is run (either through
	 * the context menu or the toolbar). It moves the selected entry up.
	 */
	protected void handleMoveUp() {
		PaletteEntry entry = getSelectedPaletteEntry();
		getCustomizer().performMoveUp(entry);
		treeviewer.setSelection(new StructuredSelection(entry), true);
		updateActions();
	}

	/**
	 * This is the method that is called everytime the selection in the outline
	 * (treeviewer) changes.
	 */
	protected void handleOutlineSelectionChanged() {
		PaletteEntry entry = getSelectedPaletteEntry();

		if (activeEntry == entry) {
			return;
		}

		if (errorMessage != null) {
			MessageDialog dialog = new MessageDialog(getShell(),
					PaletteMessages.ERROR,
					null,
					PaletteMessages.ABORT_PAGE_FLIPPING_MESSAGE
							+ "\n" + errorMessage, //$NON-NLS-1$
					MessageDialog.ERROR,
					new String[] { IDialogConstants.get().OK_LABEL }, 0);
			dialog.open();
			treeviewer.addPostSelectionChangedListener(pageFlippingPreventer);
		} else {
			setActiveEntry(entry);
		}
		updateActions();
	}

	/**
	 * This method is invoked when the changes made since the last save need to
	 * be cancelled.
	 */
	protected void revertToSaved() {
		getCustomizer().revertToSaved();
	}

	/**
	 * This method is invoked when the changes made since the last save need to
	 * be saved.
	 */
	protected void save() {
		if (activePage != null) {
			activePage.apply();
		}
		getCustomizer().save();
	}

	/**
	 * This methods sets the active entry. Based on the selection, this method
	 * will appropriately enable or disable the ToolBar items, will change the
	 * CLabel heading of the propreties panel, and will show the properties of
	 * the selected item in the properties panel.
	 * 
	 * @param entry
	 *            The new active entry, i.e., the new selected entry (it can be
	 *            <code>null</code>)
	 */
	protected void setActiveEntry(PaletteEntry entry) {
		if (activeEntry != null) {
			activeEntry.removePropertyChangeListener(titleUpdater);
		}

		activeEntry = entry;

		if (entry != null) {
			title.setText(entry.getLabel());
			Image img = treeViewerLabelProvider.getImage(entry);
			if (img == null) {
				img = getSelectedTreeItem().getImage();
			}
			title.setImage(img);
			entry.addPropertyChangeListener(titleUpdater);
			EntryPage panel = getEntryPage(entry);
			setActiveEntryPage(panel);
		} else {
			title.setImage(null);
			title.setText(PaletteMessages.NO_SELECTION_TITLE);
			// Lazy creation
			if (noSelectionPage == null) {
				noSelectionPage = new EntryPage() {
					private Text text;

					public void apply() {
					}

					public void createControl(Composite parent,
							PaletteEntry entry) {
						text = new Text(parent, SWT.READ_ONLY);
						text.setFont(parent.getFont());
						text.setText(PaletteMessages.NO_SELECTION_MADE);
					}

					public Control getControl() {
						return text;
					}

					public void setPageContainer(
							EntryPageContainer pageContainer) {
					}
				};
				noSelectionPage.createControl(propertiesPanelContainer, null);
			}
			setActiveEntryPage(noSelectionPage);
		}
	}

	/**
	 * Sets the given EntryPage as the top page in the PageBook that shows the
	 * properties of the item selected in the Outline. If the given EntryPage is
	 * null, nothing will be shown.
	 * 
	 * @param page
	 *            The EntryPage to be shown
	 */
	protected void setActiveEntryPage(EntryPage page) {
		// Have the currently displayed page save its changes
		if (activePage != null) {
			activePage.apply();
		}

		if (page == null) {
			// No page available to display, so hide the panel container
			propertiesPanelContainer.setVisible(false);
		} else {
			// Show the page and grow the shell, if necessary, so that the page
			// is
			// completely visible
			Point oldSize = getShell().getSize();
			propertiesPanelContainer.showPage(page.getControl());

			/*
			 * Fix for bug #34748 There's no need to resize the Shell if
			 * initializeBounds() hasn't been called yet. It will automatically
			 * resize the Shell so that everything fits in the Dialog. After
			 * that, we can resize the Shell whenever there's an entry page that
			 * cannot fit in the dialog.
			 */
			if (!isSetup) {
				Point newSize = getShell().computeSize(SWT.DEFAULT,
						SWT.DEFAULT, true);
				int x = newSize.x - oldSize.x;
				x = (x < 0) ? 0 : x;
				int y = newSize.y - oldSize.y;
				y = (y < 0) ? 0 : y;
				if (x > 0 || y > 0) {
					getShell().setSize(oldSize.x + x, oldSize.y + y);
				}
			}

			// Show the property panel container if it was hidden
			if (!propertiesPanelContainer.isVisible()) {
				propertiesPanelContainer.setVisible(true);
			}
		}

		activePage = page;
	}

	/**
	 * Sets the given PaletteEntry as the one to be selected when the dialog
	 * opens. It is discarded when the dialog is closed.
	 * 
	 * @param entry
	 *            The PaletteEntry that should be selected when the dialog is
	 *            opened
	 */
	public void setDefaultSelection(PaletteEntry entry) {
		initialSelection = entry;
	}

	/**
	 * This method should be invoked by EntryPages when there is an error. It
	 * will show the given error in the title of the properties panel. OK and
	 * Apply buttons will be disabled. Selecting some other entry in the outline
	 * tree will not be allowed until the error is fixed.
	 * 
	 * @see org.eclipse.gef.ui.palette.customize.EntryPageContainer#showProblem(String)
	 */
	public void showProblem(String error) {
		Assert.isNotNull(error);
		errorTitle.setText(error);
		titleSwitcher.showPage(errorPage);
		getButton(IDialogConstants.OK_ID).setEnabled(false);
		getButton(APPLY_ID).setEnabled(false);
		errorMessage = error;
	}

	/**
	 * Updates the actions created in {@link #createOutlineActions()}, enabling
	 * or disabling them as necessary.
	 */
	protected void updateActions() {
		List actions = getOutlineActions();
		for (Iterator iter = actions.iterator(); iter.hasNext();) {
			PaletteCustomizationAction action = (PaletteCustomizationAction) iter
					.next();
			action.update();
		}
	}

	/*
	 * Delete Action
	 */
	private class DeleteAction extends PaletteCustomizationAction {
		public DeleteAction() {
			setEnabled(false);
			setText(PaletteMessages.DELETE_LABEL);
			ISharedImages sharedImages = PlatformUI.getWorkbench()
					.getSharedImages();
			setImageDescriptor(sharedImages
					.getImageDescriptor(ISharedImages.IMG_TOOL_DELETE));
			setDisabledImageDescriptor(sharedImages
					.getImageDescriptor(ISharedImages.IMG_TOOL_DELETE_DISABLED));
		}

		public void run() {
			handleDelete();
		}

		public void update() {
			boolean enabled = false;
			PaletteEntry entry = getSelectedPaletteEntry();
			if (entry != null) {
				enabled = getCustomizer().canDelete(entry);
			}
			setEnabled(enabled);
		}
	}

	/*
	 * Move Down Action
	 */
	private class MoveDownAction extends PaletteCustomizationAction {
		public MoveDownAction() {
			setEnabled(false);
			setText(PaletteMessages.MOVE_DOWN_LABEL);
			setImageDescriptor(ImageDescriptor.createFromFile(Internal.class,
					"icons/next_nav.gif"));//$NON-NLS-1$
			setDisabledImageDescriptor(ImageDescriptor.createFromFile(
					Internal.class, "icons/move_down_disabled.gif"));//$NON-NLS-1$
		}

		public void run() {
			handleMoveDown();
		}

		public void update() {
			boolean enabled = false;
			PaletteEntry entry = getSelectedPaletteEntry();
			if (entry != null) {
				enabled = getCustomizer().canMoveDown(entry);
			}
			setEnabled(enabled);
		}
	}

	/*
	 * Move Up Action
	 */
	private class MoveUpAction extends PaletteCustomizationAction {
		public MoveUpAction() {
			setEnabled(false);
			setText(PaletteMessages.MOVE_UP_LABEL);
			setImageDescriptor(ImageDescriptor.createFromFile(Internal.class,
					"icons/prev_nav.gif"));//$NON-NLS-1$
			setDisabledImageDescriptor(ImageDescriptor.createFromFile(
					Internal.class, "icons/move_up_disabled.gif")); //$NON-NLS-1$
		}

		public void run() {
			handleMoveUp();
		}

		public void update() {
			boolean enabled = false;
			PaletteEntry entry = getSelectedPaletteEntry();
			if (entry != null) {
				enabled = getCustomizer().canMoveUp(entry);
			}
			setEnabled(enabled);
		}
	}

	/*
	 * New Action
	 */
	private class NewAction extends PaletteCustomizationAction implements
			IMenuCreator {
		private List factories;
		private MenuManager menuMgr;

		public NewAction() {
			factories = wrap(getCustomizer().getNewEntryFactories());
			if (factories.isEmpty()) {
				setEnabled(false);
			} else {
				setMenuCreator(this);
			}

			setText(PaletteMessages.NEW_LABEL);
			setImageDescriptor(ImageDescriptor.createFromFile(Internal.class,
					"icons/add.gif")); //$NON-NLS-1$
			setDisabledImageDescriptor(ImageDescriptor.createFromFile(
					Internal.class, "icons/add-disabled.gif")); //$NON-NLS-1$
		}

		private void addActionToMenu(Menu parent, IAction action) {
			ActionContributionItem item = new ActionContributionItem(action);
			item.fill(parent, -1);
		}

		public void dispose() {
			if (menuMgr != null) {
				menuMgr.dispose();
				menuMgr = null;
			}
		}

		public Menu getMenu(Control parent) {
			// Create the menu manager and add all the NewActions to it
			if (menuMgr == null) {
				// Lazily create the manager
				menuMgr = new MenuManager();
				menuMgr.createContextMenu(parent);
			}

			updateMenuManager(menuMgr);
			return menuMgr.getMenu();
		}

		public Menu getMenu(Menu parent) {
			Menu menu = new Menu(parent);
			for (Iterator iter = factories.iterator(); iter.hasNext();) {
				FactoryWrapperAction action = (FactoryWrapperAction) iter
						.next();
				if (action.isEnabled()) {
					addActionToMenu(menu, action);
				}
			}

			return menu;
		}

		public void run() {
		}

		public void update() {
			boolean enabled = false;
			PaletteEntry entry = getSelectedPaletteEntry();
			if (entry == null) {
				entry = getPaletteRoot();
			}
			// Enable or disable the FactoryWrapperActions
			for (Iterator iter = factories.iterator(); iter.hasNext();) {
				FactoryWrapperAction action = (FactoryWrapperAction) iter
						.next();
				action.setEnabled(action.canCreate(entry));
				enabled = enabled || action.isEnabled();
			}

			// Enable this action IFF at least one of the new actions is enabled
			setEnabled(enabled);
		}

		protected void updateMenuManager(MenuManager manager) {
			manager.removeAll();
			for (Iterator iter = factories.iterator(); iter.hasNext();) {
				FactoryWrapperAction action = (FactoryWrapperAction) iter
						.next();
				if (action.isEnabled()) {
					manager.add(action);
				}
			}
		}

		private List wrap(List list) {
			List newList = new ArrayList();
			if (list != null) {
				for (Iterator iter = list.iterator(); iter.hasNext();) {
					PaletteEntryFactory element = (PaletteEntryFactory) iter
							.next();
					newList.add(new FactoryWrapperAction(element));
				}
			}

			return newList;
		}
	}

	/*
	 * FactoryWrapperAction class
	 */
	private class FactoryWrapperAction extends Action {
		private PaletteEntryFactory factory;

		public FactoryWrapperAction(PaletteEntryFactory factory) {
			this.factory = factory;
			setText(factory.getLabel());
			setImageDescriptor(factory.getImageDescriptor());
			setHoverImageDescriptor(factory.getImageDescriptor());
		}

		public boolean canCreate(PaletteEntry entry) {
			return factory.canCreate(entry);
		}

		public void run() {
			PaletteEntry selected = getSelectedPaletteEntry();
			if (selected == null)
				selected = getPaletteRoot();
			PaletteEntry newEntry = factory
					.createNewEntry(getShell(), selected);
			treeviewer.setSelection(new StructuredSelection(newEntry), true);
			updateActions();
		}
	}

}
