/*
 * Copyright 2006 Mask@ Project.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.maskat.ide.editors;

import java.util.Iterator;

import org.eclipse.draw2d.PositionConstants;
import org.eclipse.gef.EditDomain;
import org.eclipse.gef.palette.CombinedTemplateCreationEntry;
import org.eclipse.gef.palette.MarqueeToolEntry;
import org.eclipse.gef.palette.PaletteDrawer;
import org.eclipse.gef.palette.PaletteGroup;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.palette.SelectionToolEntry;
import org.eclipse.gef.palette.ToolEntry;
import org.eclipse.gef.ui.palette.FlyoutPaletteComposite;
import org.eclipse.gef.ui.palette.PaletteViewer;
import org.eclipse.gef.ui.palette.PaletteViewerProvider;
import org.eclipse.gef.ui.palette.FlyoutPaletteComposite.FlyoutPreferences;
import org.eclipse.gef.ui.views.palette.PalettePage;
import org.eclipse.gef.ui.views.palette.PaletteViewerPage;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IWorkbenchPage;
import org.maskat.framework.screendef.customize.IComponentPluginConfig;
import org.maskat.framework.screendef.customize.PluginDefFactory;
import org.maskat.ide.gef.requests.ComponentCreateFactory;
import org.maskat.ide.gef.requests.CustomizeComponentCreateFactory;

/**
 * editDomainとswtのCompositeに対して、flyoutPaletteのサポートを提供する
 * 
 * @author shengshen
 * 
 */
public class PaletteSupport {
	private PaletteViewerProvider provider;

	private EditDomain ed;

	private FlyoutPaletteComposite splitter;

	PaletteSupport(EditDomain ed) {
		this.ed = ed;
		ed.setPaletteRoot(getPaletteRoot());
	}

	/**
	 * parentを親widgetとして、FlyoutPaletteCompositeを作る
	 * 
	 * @param parent
	 * @param page
	 * @return
	 */
	protected Composite getEditorComposite(Composite parent, IWorkbenchPage page) {
		if (splitter != null)
			return splitter;
		splitter = new FlyoutPaletteComposite(parent, SWT.NONE, page,
				getPaletteViewerProvider(), getPalettePreferences());
		return splitter;
	}

	/**
	 * paletteCompositeに子widgetとして、graphicalControlを追加
	 * 
	 * @param control
	 */
	protected void setGraphicalControl(Control control) {
		splitter.setGraphicalControl(control);
	}

	private PaletteRoot getPaletteRoot() {
		PaletteRoot palette = new PaletteRoot();

		PaletteGroup group = new PaletteGroup("tools"); //$NON-NLS-1$
		ToolEntry entry = new SelectionToolEntry();
		palette.setDefaultEntry(entry);
		group.add(entry);

		group.add(new MarqueeToolEntry());
		palette.add(group);

		ImageDescriptor smallIcon, largeIcon; // パレットで使用するアイコン

		smallIcon = ImageDescriptor.createFromFile(MaskatEditor.class,
				"/images/componenticon.gif"); //$NON-NLS-1$
		largeIcon = ImageDescriptor.createFromFile(MaskatEditor.class,
				"/images/componenticon.gif"); //$NON-NLS-1$
		PaletteDrawer group_comp = new PaletteDrawer("単一コンポーネント");

		// toolEntry.setToolProperty(AbstractTool.PROPERTY_UNLOAD_WHEN_FINISHED,Boolean.FALSE);

		group_comp.add(new CombinedTemplateCreationEntry("ラベル", "ラベルコンポーネント", null,
				ComponentCreateFactory.labelFactory, smallIcon, largeIcon));
		group_comp.add(new CombinedTemplateCreationEntry("テキスト", "テキストコンポーネント", null,
				ComponentCreateFactory.textFactory, smallIcon, largeIcon));
		group_comp.add(new CombinedTemplateCreationEntry("ボタン", "ボタンコンポーネント", null,
				ComponentCreateFactory.btnFactory, smallIcon, largeIcon));
		group_comp.add(new CombinedTemplateCreationEntry("イメージ", "イメージコンポーネント", null,
				ComponentCreateFactory.imgFactory, smallIcon, largeIcon));
		group_comp.add(new CombinedTemplateCreationEntry("コードリブ", "コードリブコンポーネント", null,
				ComponentCreateFactory.codeLibFactory, smallIcon, largeIcon));
		group_comp.add(new CombinedTemplateCreationEntry("ラジオ", "ラジオコンポーネント", null,
				ComponentCreateFactory.radioFactory, smallIcon, largeIcon));
		group_comp.add(new CombinedTemplateCreationEntry("チェックボックス", "チェックボックスコンポーネント",
				null, ComponentCreateFactory.checkboxFactory, smallIcon, largeIcon));
		group_comp.add(new CombinedTemplateCreationEntry("コンボボックス", "コンボボックスコンポーネント",
				null, ComponentCreateFactory.comboFactory, smallIcon, largeIcon));
		palette.add(group_comp);

		PaletteDrawer group_container = new PaletteDrawer("コンテナ");
		group_container.add(new CombinedTemplateCreationEntry("フレーム", "フレームコンポーネント",
				null, ComponentCreateFactory.frameFactory, smallIcon, largeIcon));
		group_container.add(new CombinedTemplateCreationEntry("splitter",
				"splitterコンポーネント", null, ComponentCreateFactory.splitterFactory,
				smallIcon, largeIcon));
		group_container.add(new CombinedTemplateCreationEntry("tabFolder",
				"tabFolderコンポーネント", null, ComponentCreateFactory.tabFolderFactory,
				smallIcon, largeIcon));
		group_container.add(new CombinedTemplateCreationEntry("タブアイテム", "タブアイテムコンポーネント",
				null, ComponentCreateFactory.tabItemFactory, smallIcon, largeIcon));
		group_container.add(new CombinedTemplateCreationEntry("グリッド", "グリッドコンポーネント",
				null, ComponentCreateFactory.gridFactory, smallIcon, largeIcon));
		group_container.add(new CombinedTemplateCreationEntry("グリッドヘッダー",
				"グリッドヘッダーコンポーネント", null, ComponentCreateFactory.gridHeaderFactory,
				smallIcon, largeIcon));
		group_container.add(new CombinedTemplateCreationEntry("ツリー", "ツリーコンポーネント", null,
				ComponentCreateFactory.treeFactory, smallIcon, largeIcon));
		palette.add(group_container);

		PaletteDrawer group_custom = new PaletteDrawer("カスタマイズ部品");
		Iterator it = PluginDefFactory.getPluginComps();
		boolean hasCustomizeComponent = false;
		while (it.hasNext()) {
			IComponentPluginConfig config = (IComponentPluginConfig) it.next();
			group_custom.add(new CombinedTemplateCreationEntry(config.getNodeName(),
					config.getNodeName(), null, new CustomizeComponentCreateFactory(
							config), smallIcon, largeIcon));
			hasCustomizeComponent = true;
		}
		if (hasCustomizeComponent == true) {
			palette.add(group_custom);
		}
		
		return palette;
	}

	private PaletteViewerProvider createPaletteViewerProvider() {
		return new PaletteViewerProvider(ed);
	}

	private PaletteViewerProvider getPaletteViewerProvider() {
		if (provider == null)
			provider = createPaletteViewerProvider();
		return provider;
	}

	private FlyoutPreferences getPalettePreferences() {
		// パレット設定の保存と復元

		return new FlyoutPreferences() {

			public int getDockLocation() {
				return PositionConstants.EAST;
			}

			public int getPaletteState() {
				return FlyoutPaletteComposite.STATE_PINNED_OPEN;
			}

			public int getPaletteWidth() {
				return 100;
			}

			public void setDockLocation(int location) {

			}

			public void setPaletteState(int state) {

			}

			public void setPaletteWidth(int width) {

			}
		};
	}

	private CustomPalettePage page;

	/**
	 * 
	 */
	final Object getAdapter(Class type) {
		if (type == PalettePage.class) {
			if (splitter == null) {
				page = createPalettePage();
				return page;
			}
			return createPalettePage();
		}
		return null;
	}

	/**
	 * @return a newly-created {@link CustomPalettePage} to be shown in the
	 *         palette view, if null nothing will be shown
	 */
	protected CustomPalettePage createPalettePage() {
		return new CustomPalettePage(getPaletteViewerProvider());
	}

	/**
	 * A custom PalettePage that helps GraphicalEditorWithFlyoutPalette keep the
	 * two PaletteViewers (one displayed in the editor and the other displayed
	 * in the PaletteView) in sync when switching from one to the other (i.e.,
	 * it helps maintain state across the two viewers).
	 * 
	 * @author Pratik Shah
	 */
	private class CustomPalettePage extends PaletteViewerPage {
		/**
		 * Constructor
		 * 
		 * @param provider
		 *            the provider used to create a PaletteViewer
		 */
		public CustomPalettePage(PaletteViewerProvider provider) {
			super(provider);
		}

		/**
		 * @see org.eclipse.ui.part.IPage#createControl(org.eclipse.swt.widgets.Composite)
		 */
		public void createControl(Composite parent) {
			super.createControl(parent);
			if (splitter != null)
				splitter.setExternalViewer(viewer);
		}

		/**
		 * @see org.eclipse.ui.part.IPage#dispose()
		 */
		public void dispose() {
			if (splitter != null)
				splitter.setExternalViewer(null);
			super.dispose();
		}

		/**
		 * @return the PaletteViewer created and displayed by this page
		 */
		public PaletteViewer getPaletteViewer() {
			return viewer;
		}
	}
}
