/*******************************************************************************
 * Copyright (c) 2008 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.draw2d.examples.swt;

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.Ellipse;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.Polyline;
import org.eclipse.draw2d.RectangleFigure;
import org.eclipse.draw2d.RoundedRectangle;
import org.eclipse.draw2d.Shape;
import org.eclipse.draw2d.Triangle;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;

public class ShapeStylesExample {

	static StyleAxis[] styleAxes = new StyleAxis[] {
		new StyleAxis(
			"Line Width",
			new StyleItem[] {
				new StyleItem(0.0f),
				new StyleItem(0.25f),
				new StyleItem(0.5f),
				new StyleItem(1.0f),
				new StyleItem(2.5f),
				new StyleItem(5.0f),
				new StyleItem(10.0f),
			}) {
				public void applyTo(Shape shape, int i) {
					shape.setLineWidthFloat(elements[i].getValue());					
				}
			},
			
		new StyleAxis(
			"Line Style",
			new StyleItem[] {
				new StyleItem("SWT.LINE_SOLID", SWT.LINE_SOLID),
				new StyleItem("SWT.LINE_DASH", SWT.LINE_DASH),
				new StyleItem("SWT.LINE_DASHDOT", SWT.LINE_DASHDOT),
				new StyleItem("SWT.LINE_DASHDOTDOT", SWT.LINE_DASHDOTDOT),
				new StyleItem("SWT.LINE_DOT", SWT.LINE_DOT),
			}) {
				public void applyTo(Shape shape, int i) {
					shape.setLineStyle((int)elements[i].getValue());					
				}
			},
			
		new StyleAxis(
			"Line Cap",
			new StyleItem[] {
				new StyleItem("SWT.CAP_FLAT", SWT.CAP_FLAT),
				new StyleItem("SWT.CAP_ROUND", SWT.CAP_ROUND),
				new StyleItem("SWT.CAP_SQUARE", SWT.CAP_SQUARE),
			}) {
				public void applyTo(Shape shape, int i) {
					shape.setLineCap((int)elements[i].getValue());					
				}
			},
			
		new StyleAxis(
			"Line Miter Limit",
			new StyleItem[] {
				new StyleItem(0.0f),
				new StyleItem(0.5f),
				new StyleItem(1.0f),
				new StyleItem(2.0f),
				new StyleItem(5.0f),
				new StyleItem(10.0f),
				new StyleItem(50.0f),
			}) {
				public void applyTo(Shape shape, int i) {
					shape.setLineMiterLimit(elements[i].getValue());					
				}
			},
		
		new StyleAxis(
			"Line Dash Offset",
			new StyleItem[] {
				new StyleItem(0.0f),
				new StyleItem(0.25f),
				new StyleItem(0.5f),
				new StyleItem(1.0f),
				new StyleItem(2.0f),
				new StyleItem(2.5f),
				new StyleItem(5.0f),
				new StyleItem(10.0f),
			}) {
				public void applyTo(Shape shape, int i) {
					shape.setLineDashOffset(elements[i].getValue());					
				}
			},	
			
		new StyleAxis(
			"Anti-Aliasing",
			new StyleItem[] {
				new StyleItem("SWT.ON", SWT.ON),
				new StyleItem("SWT.OFF", SWT.OFF),
				new StyleItem("SWT.DEFAULT", SWT.DEFAULT),
			}) {
				public void applyTo(Shape shape, int i) {
					shape.setAntialias((int)elements[i].getValue());					
				}
			},

		new StyleAxis(
			"Alpha",
			new StyleItem[] {
				new StyleItem(0),
				new StyleItem(10),
				new StyleItem(50),
				new StyleItem(100),
				new StyleItem(150),
				new StyleItem(200),
				new StyleItem(255),
			}) {
				public void applyTo(Shape shape, int i) {
					shape.setAlpha((int)elements[i].getValue());
				}
			},

		new StyleAxis(
			"Enabled",
			new StyleItem[] {
				new StyleItem("true", 1),
				new StyleItem("false", 0),
			}) {
				public void applyTo(Shape shape, int i) {
					int setting = (int)elements[i].getValue();
					if(setting == 1) {
						shape.setEnabled(true);
					} else {
						shape.setEnabled(false);
					}
				}
			},
	};
	
	static final String[] sampleShapeClasses = new String[] {
			Ellipse.class.getName(), RectangleFigure.class.getName(),
			RoundedRectangle.class.getName(), Triangle.class.getName(),
			Polyline.class.getName()};

	static final String[] defaultLineWidths = new String[] { "0", "0.5", "1",
			"2.5", "5", "10", "30" };
	
	private static Shell shell;
	private static Group styleGrid;

	private static StyleAxis xAxis;
	private static StyleAxis yAxis;
	private static float defaultLineWidth;
	private static Class sampleShape;
	
	
	public static void main(String[] args) {
		
		// create outer shell/window
		Display display = Display.getDefault();
		shell = new Shell(display, SWT.SHELL_TRIM);
		shell.setText("Shape Style Example");
		shell.setLayout(new GridLayout(2, false));
		
		// create control pane
		Group controlPane = new Group(shell, SWT.NONE);
		controlPane.setText("Style Axis Settings");
		controlPane.setLayout(new GridLayout(2, false));
		controlPane.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, true, 1, 1));
		
		// x-axis selection
		Label xAxisSelectionLabel = new Label(controlPane, SWT.NONE);
		xAxisSelectionLabel.setText("X Axis");
		final Combo xAxisSelection = new Combo(controlPane, SWT.READ_ONLY);
		for(int i=0; i < styleAxes.length; i++) {
			xAxisSelection.add(styleAxes[i].getName());
		}
		xAxisSelection.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				xAxis = styleAxes[xAxisSelection.getSelectionIndex()];
				refreshGrid();
			}
			public void widgetDefaultSelected(SelectionEvent e) {
				widgetSelected(e);
			}
		});
	
		// y-axis selection
		Label yAxisSelectionLabel = new Label(controlPane, SWT.NONE);
		yAxisSelectionLabel.setText("Y Axis");
		final Combo yAxisSelection = new Combo(controlPane, SWT.READ_ONLY);
		for(int i=0; i < styleAxes.length; i++) {
			yAxisSelection.add(styleAxes[i].getName());
		}
		yAxisSelection.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				yAxis = styleAxes[yAxisSelection.getSelectionIndex()];
				refreshGrid();
			}
			public void widgetDefaultSelected(SelectionEvent e) {
				widgetSelected(e);
			}
		});		
		
		// shape selection
		Label shapeSelectionLabel = new Label(controlPane, SWT.NONE);
		shapeSelectionLabel.setText("Shape");
		final Combo shapeSelection = new Combo(controlPane, SWT.NONE);
		shapeSelection.setItems(sampleShapeClasses);
		shapeSelection.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				try {
					sampleShape = Class.forName(shapeSelection.getText());
				} catch (ClassNotFoundException e1) {
					e1.printStackTrace();
				}
				refreshGrid();
			}
			public void widgetDefaultSelected(SelectionEvent e) {
				widgetSelected(e);
			}
		});				
		
		// default line width selection
		Label lineWidthSelectionLabel = new Label(controlPane, SWT.NONE);
		lineWidthSelectionLabel.setText("Line Width");
		final Combo lineWidthSelection = new Combo(controlPane, SWT.NONE);
		lineWidthSelection.setItems(defaultLineWidths);
		lineWidthSelection.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				defaultLineWidth = Float.parseFloat(lineWidthSelection.getText());
				refreshGrid();
			}
			public void widgetDefaultSelected(SelectionEvent e) {
				widgetSelected(e);
			}
		});				
		
		// set defaults		
		xAxis = styleAxes[0];
		yAxis = styleAxes[1];
		defaultLineWidth = Float.parseFloat(defaultLineWidths[4]);
		try {
			sampleShape = Class.forName(sampleShapeClasses[0]);
		} catch (ClassNotFoundException e1) {
			e1.printStackTrace();
		}
		xAxisSelection.select(0);
		yAxisSelection.select(1);
		lineWidthSelection.select(4);
		shapeSelection.select(0);

		// display grid
		refreshGrid();

		shell.open();
		while (!shell.isDisposed()) {
			while (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}
	
	static void refreshGrid() {
		if(styleGrid != null) {
			styleGrid.dispose();
			shell.pack();
		}
		
		styleGrid = new Group(shell, SWT.NONE);
		styleGrid.setText(xAxis.getName() + " vs. " + yAxis.getName());
		styleGrid.setLayout(new GridLayout(xAxis.getCount() + 1, false));
		styleGrid.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true, 1, 1));

		// put blank label in top left corner
		Label label = new Label(styleGrid, SWT.NONE);

		// add x-axis labels
		for(int x=0; x < xAxis.getCount(); x++) {
			label = new Label(styleGrid, SWT.NONE);
			label.setText(xAxis.getName() + " =\n" + xAxis.getAt(x).getName());
		}
		
		// iterate over the y-axis style settings
		for(int y=1; y < yAxis.getCount() + 1; y++) {
			
			// add y-axis label for this row
			label = new Label(styleGrid, SWT.NONE);
			label.setText(yAxis.getName() + " =\n" + yAxis.getAt(y - 1).getName());
			
			// iterate over the x-axis style settings
			for(int x=1; x < xAxis.getCount() + 1; x++) {
				
				// create a sample shape instance
				Shape shape;
				if(sampleShape == Polyline.class) {
					Polyline poly = new Polyline();
					poly.addPoint(new Point(20, 20));
					poly.addPoint(new Point(50, 80));
					poly.addPoint(new Point(10, 50));
					shape = poly;
				} else {
					try {
						shape = (Shape)sampleShape.getConstructor(null).newInstance(null);
					} catch (Exception e) {
						throw new RuntimeException("Could not find a no args constructor for " + sampleShape.getName());
					}
					shape.setBounds(new Rectangle(0, 0, 100, 75));
				}
				
				// apply default style
				shape.setBackgroundColor(ColorConstants.orange);
				shape.setLineWidthFloat(defaultLineWidth);
				shape.setAntialias(SWT.ON);
				
				// apply styles imposed by each axis
				xAxis.applyTo(shape, x - 1);
				yAxis.applyTo(shape, y - 1);

				FigureCanvas figureBox = new FigureCanvas(styleGrid);
				figureBox.setContents(shape);
			}
		}
		shell.pack();
	}
	
	static abstract class StyleAxis {
		private String name;
		protected StyleItem[] elements;
		
		public StyleAxis(String name, StyleItem[] elements) {
			this.name = name;
			this.elements = elements;
		}

		public int getCount() {
			return elements.length;
		}
		
		public StyleItem getAt(int i) {
			return elements[i];
		}
		
		public String getName() {
			return name;
		}
		
		public abstract void applyTo(Shape shape, int i);
	}
	
	static class StyleItem {
		private String name;
		private float value;
		
		public StyleItem(float value) {
			this.name = Float.toString(value);
			this.value = value;
		}
		
		public StyleItem(String name, float value) {
			this.name = name;
			this.value = value;
		}
		
		public String getName() {
			return name;
		}
		
		public float getValue() {
			return value;
		}
	}
}
