/*******************************************************************************
 * Copyright (c) 2004, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.tools.internal;

import java.io.*;
import java.lang.reflect.*;

import org.eclipse.swt.*;
import org.eclipse.swt.custom.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class JNIGeneratorAppUI {

	Display display;
	Shell shell;
	
	Composite actionsPanel;
	Combo mainClassCb, outputDirCb;
	Table classesLt, membersLt, paramsLt;
	ProgressBar progressBar;
	Label progressLabel;
	FileDialog fileDialog;
	
	TableEditor paramTextEditor, memberTextEditor, classTextEditor;
	FlagsEditor paramListEditor, memberListEditor, classListEditor;
	Text paramEditorTx, memberEditorTx, classEditorTx;
	List paramEditorLt, memberEditorLt, classEditorLt;
	
	static class FlagsEditor {
		Table parent;
		int column = -1;
		TableItem item;
		
		public FlagsEditor(Table parent) {
			this.parent = parent;
		}
		
		public int getColumn() {
			return column;
		}
		
		public TableItem getItem() {
			return item;
		}
		
		public void setColumn(int column) {
			this.column = column;
		}
		
		public void setItem(TableItem item) {
			this.item = item;
		}
	}
	
	JNIGeneratorApp app;

	static final int CLASS_NAME_COLUMN = 0;
	static final int CLASS_FLAGS_COLUMN = 1;
	static final int CLASS_EXCLUDE_COLUMN = 2;
	
	static final int FIELD_NAME_COLUMN = 0;
	static final int FIELD_FLAGS_COLUMN = 1;
	static final int FIELD_CAST_COLUMN = 2;
	static final int FIELD_ACCESSOR_COLUMN = 3;
	static final int FIELD_EXCLUDE_COLUMN = 4;
	
	static final int METHOD_NAME_COLUMN = 0;
	static final int METHOD_FLAGS_COLUMN = 1;
	static final int METHOD_ACCESSOR_COLUMN = 2;
	static final int METHOD_EXCLUDE_COLUMN = 3;
	
	static final int PARAM_INDEX_COLUMN = 0;
	static final int PARAM_TYPE_COLUMN = 1;
	static final int PARAM_FLAGS_COLUMN = 2;
	static final int PARAM_CAST_COLUMN = 3;
	
public JNIGeneratorAppUI() {
	this (new JNIGeneratorApp());
}

public JNIGeneratorAppUI(JNIGeneratorApp app) {
	this.app = app;
}

void cleanup() {
	display.dispose();
}

void generateStructsHeader () {
	StructsGenerator gen = new StructsGenerator(true);
	gen.setMainClass(app.getMainClass());
	gen.setMetaData(app.getMetaData());
	gen.setClasses(getSelectedClasses());
	gen.generate();
}

void generateStructs () {
	StructsGenerator gen = new StructsGenerator(false);
	gen.setMainClass(app.getMainClass());
	gen.setMetaData(app.getMetaData());
	gen.setClasses(getSelectedClasses());
	gen.generate();
}

void generateSizeof () {
	SizeofGenerator gen = new SizeofGenerator();
	gen.setMainClass(app.getMainClass());
	gen.setMetaData(app.getMetaData());
	gen.setClasses(getSelectedClasses());
	gen.generate();
}

void generateMetaData () {
	MetaDataGenerator gen = new MetaDataGenerator();
	gen.setMainClass(app.getMainClass());
	gen.setMetaData(app.getMetaData());
	JNIMethod[] methods = getSelectedMethods();
	if (methods.length != 0) {
		gen.generate(methods);
	} else {
		gen.setClasses(getSelectedClasses());
		gen.generate();
	}
}

void generateNatives () {
	NativesGenerator gen = new NativesGenerator();
	gen.setMainClass(app.getMainClass());
	gen.setMetaData(app.getMetaData());
	JNIMethod[] methods = getSelectedMethods();
	if (methods.length != 0) {
		gen.generate(methods);
	} else {
		gen.setClasses(getSelectedClasses());
		gen.generate();
	}
}

void generateAll() {
	if (!updateOutputDir()) return;
	Cursor cursor = display.getSystemCursor(SWT.CURSOR_WAIT);
	shell.setCursor(cursor);
	shell.setEnabled(false);
	Control[] children = actionsPanel.getChildren();
	for (Control child : children) {
		if (child instanceof Button) child.setEnabled(false);				
	}
	boolean showProgress = true;
	final boolean finalShowProgress = showProgress; /* avoid dead code warning below */
	if (showProgress) {
		progressLabel.setText("");
		progressBar.setSelection(0);
		progressLabel.setVisible(true);
		progressBar.setVisible(true);
	}
	final boolean[] done = new boolean[1];
	new Thread() {
		@Override
		public void run() {
			try {
				app.generate(!finalShowProgress ? null : new ProgressMonitor() {
					int total, step, maximum = 100;
					@Override
					public void setTotal(final int total) {
						this.total = total;
						display.syncExec(() -> progressBar.setMaximum(maximum));
					}
					@Override
					public void step() {
						int oldValue = step * maximum / total;
						step++;
						final int newValue = step * maximum / total;
						if (oldValue == newValue) return;
						display.syncExec(() -> progressBar.setSelection(newValue));					
					}
					@Override
					public void setMessage(final String message) {
						display.syncExec(() -> {
							progressLabel.setText(message);
							progressLabel.update();
						});
					}
				});
			} finally {
				done[0] = true;
				display.wake();
			}
		}
	}.start();
	while (!done[0]) {
		if (!display.readAndDispatch()) display.sleep();
	}
	for (Control child : children) {
		if (child instanceof Button) child.setEnabled(true);				
	}
	if (showProgress) {
		progressBar.setVisible(false);
		progressLabel.setVisible(false);
	}
	shell.setEnabled(true);
	shell.setCursor(null);
}

void generateConstants () {
	ConstantsGenerator gen = new ConstantsGenerator();
	gen.setMainClass(app.getMainClass());
	gen.setMetaData(app.getMetaData());
	JNIField[] fields = getSelectedFields();
	if (fields.length != 0) {
		gen.generate(fields);
	} else {
		gen.setClasses(getSelectedClasses());
		gen.generate();
	}
}

JNIClass[] getSelectedClasses() {
	TableItem[] items = classesLt.getSelection();
	JNIClass[] classes = new JNIClass[items.length];
	for (int i = 0; i < items.length; i++) {
		TableItem item = items[i];
		classes[i] = (JNIClass)item.getData();
	}
	return classes;
}

JNIMethod[] getSelectedMethods() {
	TableItem[] selection = membersLt.getSelection();
	JNIMethod[] methods = new JNIMethod[selection.length];
	int count = 0;
	for (TableItem item : selection) {
		Object data = item.getData();
		if (data instanceof JNIMethod) {
			methods[count++] = (JNIMethod)data;
		}
	}
	if (count != methods.length) {
		JNIMethod[] result = new JNIMethod[count];
		System.arraycopy(methods, 0, result, 0, count);
		methods = result;
	}
	return methods;
}

JNIField[] getSelectedFields() {
	TableItem[] selection = membersLt.getSelection();
	JNIField[] fields = new JNIField[selection.length];
	int count = 0;
	for (TableItem item : selection) {
		Object data = item.getData();
		if (data instanceof JNIField) {
			fields[count++] = (JNIField)data;
		}
	}
	if (count != fields.length) {
		JNIField[] result = new JNIField[count];
		System.arraycopy(fields, 0, result, 0, count);
		fields = result;
	}
	return fields;
}

public void open () {
	display = new Display();
	shell = new Shell(display);
	shell.setText("JNI Generator");

	GridData data;
	GridLayout shellLayout = new GridLayout();
	shellLayout.numColumns = 2;
	shell.setLayout(shellLayout);
	
	Composite panel = new Composite(shell, SWT.NONE);
	data = new GridData(GridData.FILL_BOTH);
	panel.setLayoutData(data);
	
	GridLayout panelLayout = new GridLayout();
	panelLayout.numColumns = 1;
	panel.setLayout(panelLayout);
	
	Listener updateMainClassListener =  e -> {
		updateMainClass();
		if (!updateOutputDir()) return;
		updateClasses();
		updateMembers();
		updateParameters();
	};	
	createMainClassPanel(panel, updateMainClassListener);
	createClassesPanel(panel);
	createMembersPanel(panel);
	createParametersPanel(panel);
	createActionButtons(shell);

	Point preferredSize = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
	shell.setSize(shell.getSize().x, preferredSize.y);
	
	updateMainClass();
	updateClasses();
	updateMembers();
	updateParameters();
}

void createMainClassPanel(Composite panel, Listener updateListener) {
	Label mainClassLb = new Label(panel, SWT.NONE);
	mainClassLb.setText("&Main Class:");

	GridData data;
	mainClassCb = new Combo(panel, SWT.DROP_DOWN);
	String mainClass = app.getMainClassName();
	mainClassCb.setText(mainClass == null ? "" : mainClass);
	data = new GridData(GridData.FILL_HORIZONTAL);
	mainClassCb.setLayoutData(data);
	mainClassCb.addListener(SWT.Selection, updateListener);
	mainClassCb.addListener(SWT.DefaultSelection, updateListener);

	Label outputDirLb = new Label(panel, SWT.NONE);
	outputDirLb.setText("&Output Dir:");
	
	outputDirCb = new Combo(panel, SWT.DROP_DOWN);
	String outputDir = app.getOutputDir();
	outputDirCb.setText(outputDir == null ? "" : outputDir);
	data = new GridData(GridData.FILL_HORIZONTAL);
	outputDirCb.setLayoutData(data);
	outputDirCb.addListener(SWT.Selection, updateListener);
	outputDirCb.addListener(SWT.DefaultSelection, updateListener);

	String mainClasses = app.getMetaData().getMetaData("swt_main_classes", null);
	if (mainClasses != null) {
		String[] list = JNIGenerator.split(mainClasses, ",");
		for (int i = 0; i < list.length; i += 2) {
			String className = list[i].trim();
			try {
				Class.forName(className, false, getClass().getClassLoader());
				mainClassCb.add(className);
				outputDirCb.add(list[i + 1].trim());
			} catch (Exception e) {}
		}
	}
}

void createClassesPanel(Composite panel) {
	Label classesLb = new Label(panel, SWT.NONE);
	classesLb.setText("&Classes:");

	GridData data;
	classesLt = new Table(panel, SWT.CHECK | SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
	data = new GridData(GridData.FILL_BOTH);
	data.heightHint = classesLt.getItemHeight() * 6;
	classesLt.setLayoutData(data);
	classesLt.setHeaderVisible(true);
	classesLt.addListener(SWT.Selection, e -> {
		if (e.detail == SWT.CHECK) {
			updateGenerate((TableItem)e.item);
		} else {
			updateMembers();
			updateParameters();
		}
	});
	TableColumn column;
	column = new TableColumn(classesLt, SWT.NONE, CLASS_NAME_COLUMN);
	column.setText("Class");
	column = new TableColumn(classesLt, SWT.NONE, CLASS_FLAGS_COLUMN);
	column.setText("Flags");
	/*
	column = new TableColumn(classesLt, SWT.NONE, CLASS_EXCLUDE_COLUMN);
	column.setText("Exclude");
	*/
	
	classTextEditor = new TableEditor(classesLt);
	classTextEditor.grabHorizontal = true;
	classEditorTx = new Text(classesLt, SWT.SINGLE);
	classTextEditor.setEditor(classEditorTx);
	Listener classTextListener = e -> {
		if (e.type == SWT.Traverse) {
			switch (e.detail) {
				case SWT.TRAVERSE_ESCAPE:
					classTextEditor.setItem(null);
					break;
				default:
					return;
			}
		}
		classEditorTx.setVisible(false);
		TableItem item = classTextEditor.getItem();
		if (item == null) return;
		int column1 = classTextEditor.getColumn();
		JNIClass clazz = (JNIClass)item.getData();
		if (column1 == CLASS_EXCLUDE_COLUMN) {
			String text = classEditorTx.getText();
			clazz.setExclude(text);
			item.setText(column1, clazz.getExclude());
			classesLt.getColumn(column1).pack();
		}
	};
	classEditorTx.addListener(SWT.DefaultSelection, classTextListener);
	classEditorTx.addListener(SWT.FocusOut, classTextListener);
	classEditorTx.addListener(SWT.Traverse, classTextListener);
	
	final Shell floater = new Shell(shell, SWT.NO_TRIM);
	floater.setLayout(new FillLayout());
	classListEditor = new FlagsEditor(classesLt);
	classEditorLt = new List(floater, SWT.MULTI | SWT.BORDER);
	classEditorLt.setItems(JNIClass.FLAGS);
	floater.pack();
	floater.addListener(SWT.Close, e -> {
		classListEditor.setItem(null);
		e.doit = false;
		floater.setVisible(false);
	});
	Listener classesListListener = e -> {
		if (e.type == SWT.Traverse) {
			switch (e.detail) {
				case SWT.TRAVERSE_RETURN:
					break;
				default:
					return;
			}
		}
		floater.setVisible(false);
		TableItem item = classListEditor.getItem();
		if (item == null) return;
		int column1 = classListEditor.getColumn();
		JNIClass clazz = (JNIClass)item.getData();
		if (column1 == CLASS_FLAGS_COLUMN) {
			String[] flags = classEditorLt.getSelection();
			clazz.setFlags(flags);
			item.setText(column1, getFlagsString(clazz.getFlags()));
			item.setChecked(clazz.getGenerate());
			classesLt.getColumn(column1).pack();
		}
	};
	classEditorLt.addListener(SWT.DefaultSelection, classesListListener);
	classEditorLt.addListener(SWT.FocusOut, classesListListener);
	classEditorLt.addListener(SWT.Traverse, classesListListener);

	classesLt.addListener(SWT.MouseDown, e -> e.display.asyncExec (() -> {
		if (classesLt.isDisposed ()) return;
		if (e.button != 1) return;
		Point pt = new Point(e.x, e.y);
		TableItem item = classesLt.getItem(pt);
		if (item == null) return;
		int column1 = -1;
		for (int i = 0; i < classesLt.getColumnCount(); i++) {
			if (item.getBounds(i).contains(pt)) {
				column1 = i;
				break;
			}				
		}
		if (column1 == -1) return;
		JNIClass data1 = (JNIClass)item.getData();
		if (column1 == CLASS_EXCLUDE_COLUMN) {
			classTextEditor.setColumn(column1);
			classTextEditor.setItem(item);
			classEditorTx.setText(data1.getExclude());
			classEditorTx.selectAll();
			classEditorTx.setVisible(true);
			classEditorTx.setFocus();
		} else if (column1 == CLASS_FLAGS_COLUMN) {
			classListEditor.setColumn(column1);
			classListEditor.setItem(item);
			classEditorLt.setSelection(data1.getFlags());
			floater.setLocation(classesLt.toDisplay(e.x, e.y));
			floater.setVisible(true);
			classEditorLt.setFocus();
		}
	}));
}

void createMembersPanel(Composite panel) {
	GridData data;
	Composite comp = new Composite(panel, SWT.NONE);
	data = new GridData(GridData.FILL_HORIZONTAL);
	comp.setLayoutData(data);	
	GridLayout layout = new GridLayout(2, false);
	layout.marginWidth = layout.marginHeight = 0;
	comp.setLayout(layout);
	Label membersLb = new Label(comp, SWT.NONE);
	membersLb.setText("Mem&bers [regex]:");
	final Text searchText = new Text(comp, SWT.SINGLE | SWT.SEARCH);
	searchText.setText(".*");
	data = new GridData(GridData.FILL_HORIZONTAL);
	searchText.setLayoutData(data);
	searchText.addListener(SWT.DefaultSelection, new Listener() {
		boolean match (int index, String pattern) {
			TableItem item = membersLt.getItem(index);
			String text = item.getText();
			try {
				if (text.matches(pattern)) {
					membersLt.setSelection(index);
					return true;
				}
			} catch (Exception ex) {}
			return false;
		}
		@Override
		public void handleEvent(Event e) {
			String pattern = searchText.getText();
			int selection = membersLt.getSelectionIndex();
			int count = membersLt.getItemCount();
			selection++;
			for (int i = selection; i < count; i++) {
				if (match (i, pattern)) return;
			}
			for (int i = 0; i < selection; i++) {
				if (match (i, pattern)) return;
			}
		}
	});

	membersLt = new Table(panel, SWT.CHECK | SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
	data = new GridData(GridData.FILL_BOTH);
	data.heightHint = membersLt.getItemHeight() * 6;
	membersLt.setLayoutData(data);
	membersLt.addListener(SWT.Selection, e -> {
		if (e.detail == SWT.CHECK) {
			updateGenerate((TableItem)e.item);
		} else {
			updateParameters();
		}
	});
	
	memberTextEditor = new TableEditor(membersLt);
	memberTextEditor.grabHorizontal = true;
	memberEditorTx = new Text(membersLt, SWT.SINGLE);
	memberTextEditor.setEditor(memberEditorTx);
	Listener memberTextListener = e -> {
		if (e.type == SWT.Traverse) {
			switch (e.detail) {
				case SWT.TRAVERSE_ESCAPE:
					memberTextEditor.setItem(null);
					break;
				default:
					return;
			}
		}
		memberEditorTx.setVisible(false);
		TableItem item = memberTextEditor.getItem();
		if (item == null) return;
		int column = memberTextEditor.getColumn();
		JNIItem memberData = (JNIItem)item.getData();
		String text = memberEditorTx.getText();
		if (memberData instanceof JNIField) {
			JNIField field = (JNIField)memberData;
			switch (column) {
				case FIELD_CAST_COLUMN: {
					field.setCast(text);
					item.setText(column, field.getCast());
					break;
				}
				case FIELD_ACCESSOR_COLUMN: {
					field.setAccessor(text.equals(field.getName()) ? "" : text);
					item.setText(column, field.getAccessor());
					break;
				}
				case FIELD_EXCLUDE_COLUMN: {
					field.setExclude(text);
					item.setText(column, field.getExclude());
					break;
				}
			}
			membersLt.getColumn(column).pack();
		} else if (memberData instanceof JNIMethod) {
			JNIMethod method = (JNIMethod)memberData;
			switch (column) {
				case METHOD_ACCESSOR_COLUMN: {
					method.setAccessor(text.equals(method.getName()) ? "" : text);
					item.setText(column, method.getAccessor());
					break;
				}
				case METHOD_EXCLUDE_COLUMN: {
					method.setExclude(text);
					item.setText(column, method.getExclude());
					break;
				}
			}
			membersLt.getColumn(column).pack();
		}
	};
	memberEditorTx.addListener(SWT.DefaultSelection, memberTextListener);
	memberEditorTx.addListener(SWT.FocusOut, memberTextListener);
	memberEditorTx.addListener(SWT.Traverse, memberTextListener);
	
	final Shell floater = new Shell(shell, SWT.NO_TRIM);
	floater.setLayout(new FillLayout());
	memberListEditor = new FlagsEditor(membersLt);
	memberEditorLt = new List(floater, SWT.MULTI | SWT.BORDER);
	floater.addListener(SWT.Close, e -> {
		memberListEditor.setItem(null);
		e.doit = false;
		floater.setVisible(false);
	});
	Listener memberListListener = e -> {
		if (e.type == SWT.Traverse) {
			switch (e.detail) {
				case SWT.TRAVERSE_RETURN:
					break;
				default:
					return;
			}
		}
		floater.setVisible(false);
		TableItem item = memberListEditor.getItem();
		if (item == null) return;
		int column = memberListEditor.getColumn();
		JNIItem data1 = (JNIItem)item.getData();
		String[] flags = memberEditorLt.getSelection();
		data1.setFlags(flags);
		item.setText(column, getFlagsString(data1.getFlags()));
		item.setChecked(data1.getGenerate());
		membersLt.getColumn(column).pack();
	};
	memberEditorLt.addListener(SWT.DefaultSelection, memberListListener);
	memberEditorLt.addListener(SWT.FocusOut, memberListListener);
	memberEditorLt.addListener(SWT.Traverse, memberListListener);
	
	membersLt.addListener(SWT.MouseDown, e -> e.display.asyncExec (() -> {
		if (membersLt.isDisposed ()) return;
		if (e.button != 1) return;
		Point pt = new Point(e.x, e.y);
		TableItem item = membersLt.getItem(pt);
		if (item == null) return;
		int column = -1;
		for (int i = 0; i < membersLt.getColumnCount(); i++) {
			if (item.getBounds(i).contains(pt)) {
				column = i;
				break;
			}				
		}
		if (column == -1) return;
		Object itemData = item.getData();
		if (itemData instanceof JNIField) {
			JNIField field = (JNIField)itemData;
			if (column == FIELD_CAST_COLUMN || column == FIELD_ACCESSOR_COLUMN || column == FIELD_EXCLUDE_COLUMN) {
				memberTextEditor.setColumn(column);
				memberTextEditor.setItem(item);
				String text1 = "";
				switch (column) {
					case FIELD_CAST_COLUMN: text1 = field.getCast(); break;
					case FIELD_ACCESSOR_COLUMN: {
						text1 = field.getAccessor(); 
						if (text1.length() == 0) {
							text1 = field.getName();
							int index = text1.lastIndexOf('_');
							if (index != -1) {
								char[] chars = text1.toCharArray();
								chars[index] = '.';
								text1 = new String(chars);
							}
						}
						break;
					}
					case FIELD_EXCLUDE_COLUMN: text1 = field.getExclude(); break;
				}
				memberEditorTx.setText(text1);
				memberEditorTx.selectAll();
				memberEditorTx.setVisible(true);
				memberEditorTx.setFocus();
			} else if (column == FIELD_FLAGS_COLUMN) {
				memberListEditor.setColumn(column);
				memberListEditor.setItem(item);
				memberEditorLt.setItems(JNIField.FLAGS);
				memberEditorLt.setSelection(field.getFlags());
				floater.setLocation(membersLt.toDisplay(e.x, e.y));
				floater.pack();
				floater.setVisible(true);
				memberEditorLt.setFocus();
			}
		} else if (itemData instanceof JNIMethod) {
			JNIMethod method = (JNIMethod)itemData;
			if (column == METHOD_EXCLUDE_COLUMN || column == METHOD_ACCESSOR_COLUMN) {
				memberTextEditor.setColumn(column);
				memberTextEditor.setItem(item);
				String text2 = "";
				switch (column) {
					case METHOD_ACCESSOR_COLUMN: {
						text2 = method.getAccessor();
						if (text2.length() == 0) text2 = method.getName();
						break;
					}
					case METHOD_EXCLUDE_COLUMN: text2 = method.getExclude(); break;
				}
				memberEditorTx.setText(text2);
				memberEditorTx.selectAll();
				memberEditorTx.setVisible(true);
				memberEditorTx.setFocus();
			} else if (column == METHOD_FLAGS_COLUMN) {
				memberListEditor.setColumn(column);
				memberListEditor.setItem(item);
				memberEditorLt.setItems(JNIMethod.FLAGS);
				memberEditorLt.setSelection(method.getFlags());
				floater.setLocation(membersLt.toDisplay(e.x, e.y));
				floater.pack();
				floater.setVisible(true);
				memberEditorLt.setFocus();
			}
		}
	}));
}

void createParametersPanel(Composite panel) {
	Label paramsLb = new Label(panel, SWT.NONE);
	paramsLb.setText("&Parameters:");
	
	GridData data;
	paramsLt = new Table(panel, SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
	data = new GridData(GridData.FILL_BOTH);
	int itemHeight = paramsLt.getItemHeight();
	data.heightHint = itemHeight * 6;
	paramsLt.setLayoutData(data);
	paramsLt.addListener(SWT.Selection, e -> {
		if (e.detail == SWT.CHECK) {
			updateGenerate((TableItem)e.item);
		}
	});

	TableColumn column;
	column = new TableColumn(paramsLt, SWT.NONE, PARAM_INDEX_COLUMN);
	column = new TableColumn(paramsLt, SWT.NONE, PARAM_TYPE_COLUMN);
	column.setText("Type");
	column = new TableColumn(paramsLt, SWT.NONE, PARAM_FLAGS_COLUMN);
	column.setText("Flags");
	column = new TableColumn(paramsLt, SWT.NONE, PARAM_CAST_COLUMN);
	column.setText("Cast");
	
	paramTextEditor = new TableEditor(paramsLt);
	paramTextEditor.grabHorizontal = true;
	paramEditorTx = new Text(paramsLt, SWT.SINGLE);
	paramTextEditor.setEditor(paramEditorTx);
	Listener paramTextListener = e -> {
		if (e.type == SWT.Traverse) {
			switch (e.detail) {
				case SWT.TRAVERSE_ESCAPE:
					paramTextEditor.setItem(null);
					break;
				default:
					return;
			}
		}
		paramEditorTx.setVisible(false);
		TableItem item = paramTextEditor.getItem();
		if (item == null) return;
		int column1 = paramTextEditor.getColumn();
		JNIParameter param = (JNIParameter)item.getData();
		if (column1 == PARAM_CAST_COLUMN) {
			String text = paramEditorTx.getText();
			param.setCast(text);
			item.setText(column1, param.getCast());
			paramsLt.getColumn(column1).pack();
		}
	};
	paramEditorTx.addListener(SWT.DefaultSelection, paramTextListener);
	paramEditorTx.addListener(SWT.FocusOut, paramTextListener);
	paramEditorTx.addListener(SWT.Traverse, paramTextListener);
	
	final Shell floater = new Shell(shell, SWT.NO_TRIM);
	floater.setLayout(new FillLayout());
	paramListEditor = new FlagsEditor(paramsLt);
	paramEditorLt = new List(floater, SWT.MULTI | SWT.BORDER);
	paramEditorLt.setItems(JNIParameter.FLAGS);
	floater.pack();
	floater.addListener(SWT.Close, e -> {
		paramListEditor.setItem(null);
		e.doit = false;
		floater.setVisible(false);
	});
	Listener paramListListener = e -> {
		if (e.type == SWT.Traverse) {
			switch (e.detail) {
				case SWT.TRAVERSE_RETURN:
					break;
				default:
					return;
			}
		}
		floater.setVisible(false);
		TableItem item = paramListEditor.getItem();
		if (item == null) return;
		int column1 = paramListEditor.getColumn();
		JNIParameter param = (JNIParameter)item.getData();
		if (column1 == PARAM_FLAGS_COLUMN) {
			String[] flags = paramEditorLt.getSelection();
			param.setFlags(flags);
			item.setText(column1, getFlagsString(param.getFlags()));
			paramsLt.getColumn(column1).pack();
		}
	};
	paramEditorLt.addListener(SWT.DefaultSelection, paramListListener);
	paramEditorLt.addListener(SWT.FocusOut, paramListListener);
	paramEditorLt.addListener(SWT.Traverse, paramListListener);

	paramsLt.addListener(SWT.MouseDown, e -> e.display.asyncExec (() -> {
		if (paramsLt.isDisposed ()) return;
		if (e.button != 1) return;
		Point pt = new Point(e.x, e.y);
		TableItem item = paramsLt.getItem(pt);
		if (item == null) return;
		int column1 = -1;
		for (int i = 0; i < paramsLt.getColumnCount(); i++) {
			if (item.getBounds(i).contains(pt)) {
				column1 = i;
				break;
			}				
		}
		if (column1 == -1) return;
		JNIParameter param = (JNIParameter)item.getData();
		if (column1 == PARAM_CAST_COLUMN) {
			paramTextEditor.setColumn(column1);
			paramTextEditor.setItem(item);
			paramEditorTx.setText(param.getCast());
			paramEditorTx.selectAll();
			paramEditorTx.setVisible(true);
			paramEditorTx.setFocus();
		} else if (column1 == PARAM_FLAGS_COLUMN) {
			paramListEditor.setColumn(column1);
			paramListEditor.setItem(item);
			paramEditorLt.setSelection(param.getFlags());
			floater.setLocation(paramsLt.toDisplay(e.x, e.y));
			floater.setVisible(true);
			paramEditorLt.setFocus();
		}
	}));
}

Button createActionButton(Composite parent, String text, Listener listener) {
	Button action = new Button(parent, SWT.PUSH);
	action.setText(text);
	GridData data = new GridData(GridData.FILL_HORIZONTAL);
	action.setLayoutData(data);
	action.addListener(SWT.Selection, listener);
	return action;
}

void createActionButtons(Composite parent) {		
	actionsPanel = new Composite(parent, SWT.NONE);

	GridData data = new GridData(GridData.FILL_VERTICAL);
	actionsPanel.setLayoutData(data);
		
	GridLayout actionsLayout = new GridLayout();
	actionsLayout.numColumns = 1;
	actionsPanel.setLayout(actionsLayout);
	
	createActionButton(actionsPanel, "Generate &All", e -> generateAll());
	
	Label separator = new Label(actionsPanel, SWT.SEPARATOR | SWT.HORIZONTAL);
	data = new GridData(GridData.FILL_HORIZONTAL);
	separator.setLayoutData(data);
	separator = new Label(actionsPanel, SWT.SEPARATOR | SWT.HORIZONTAL);
	data = new GridData(GridData.FILL_HORIZONTAL);
	separator.setLayoutData(data);
	
	createActionButton(actionsPanel, "Generate Structs &Header", e -> generateStructsHeader());
	createActionButton(actionsPanel, "Generate &Structs", e -> generateStructs());
	createActionButton(actionsPanel, "Generate &Natives", e -> generateNatives());
	createActionButton(actionsPanel, "Generate Meta &Data", e -> generateMetaData());
	createActionButton(actionsPanel, "Generate Cons&tants", e -> generateConstants());	
	createActionButton(actionsPanel, "Generate Si&zeof", e -> generateSizeof());

	Composite filler = new Composite(actionsPanel, SWT.NONE);
	filler.setLayoutData(new GridData(GridData.FILL_BOTH));
	
	progressLabel = new Label(actionsPanel, SWT.NONE);
	data = new GridData(GridData.FILL_HORIZONTAL);
	progressLabel.setLayoutData(data);
	progressLabel.setVisible(false);
	
	progressBar = new ProgressBar(actionsPanel, SWT.NONE);
	data = new GridData(GridData.FILL_HORIZONTAL);
	progressBar.setLayoutData(data);
	progressBar.setVisible(false);
}

public void run() {
	shell.open();
	MessageBox box = new MessageBox(shell, SWT.YES | SWT.NO);
	box.setText("Warning");
	box.setMessage("This tool is obsolete as of Eclipse 3.5 M2.\nThe meta data has been embedded in java source files.\nThere is a new plugin tool that replaces this tool.\nSee http://www.eclipse.org/swt/jnigen.php.\n\n Continue?");
	int result = box.open();
	if (result == SWT.NO) {
		shell.dispose();
	}
	while (!shell.isDisposed()) {
		if (!display.readAndDispatch()) display.sleep ();
	}
	cleanup();
}

String getPackageString() {
	int dot = app.getMainClassName().lastIndexOf('.');
	if (dot == -1) return "";
	return app.getMainClassName().substring(0, dot);
}

String getClassString(JNIType type) {
	String name = type.getTypeSignature3();
	int index = name.lastIndexOf('.');
	if (index == -1) return name;
	return name.substring(index + 1, name.length());
}

String getFlagsString(String[] flags) {
	if (flags.length == 0) return "";
	return String.join(", ", flags);
}

String getMethodString(JNIMethod method) {
	String pkgName = getPackageString();
	StringBuilder buffer = new StringBuilder();
	buffer.append(method.getName());
	buffer.append("(");
	JNIParameter[] params = method.getParameters();
	for (int i = 0; i < params.length; i++) {
		JNIParameter param = params[i];
		if (i != 0) buffer.append(",");
		String string = param.getType().getTypeSignature3();
		if (string.startsWith(pkgName)) string = string.substring(pkgName.length() + 1);
		buffer.append(string);
	}
	buffer.append(")");
	return buffer.toString();
}

String getFieldString(JNIField field) {
	return field.getName();
}

void updateClasses() {
	classesLt.removeAll();
	JNIClass[] classes = app.getClasses();
	int mainIndex = 0;
	for (int i = 0; i < classes.length; i++) {
		JNIClass clazz = classes[i];
		if (clazz.equals(app.getMainClass())) mainIndex = i;
		TableItem item = new TableItem(classesLt, SWT.NONE);
		item.setData(clazz);
		item.setText(CLASS_NAME_COLUMN, clazz.getSimpleName());
		item.setText(CLASS_FLAGS_COLUMN, getFlagsString(clazz.getFlags()));
		item.setChecked(clazz.getGenerate());
	}
	for (TableColumn column : classesLt.getColumns()) {
		column.pack();
	}
	classesLt.setSelection(mainIndex);
}

void updateMembers() {
	membersLt.removeAll();
	membersLt.setHeaderVisible(false);
	TableColumn[] columns = membersLt.getColumns();
	for (TableColumn column : columns) {
		column.dispose();
	}
	int[] indices = classesLt.getSelectionIndices();
	if (indices.length != 1) return;
	TableItem classItem = classesLt.getItem(indices[0]);
	JNIClass clazz = (JNIClass)classItem.getData();
	boolean hasNatives = false;
	JNIMethod[] methods = clazz.getDeclaredMethods();
	for (JNIMethod method : methods) {
		int mods = method.getModifiers();
		if (hasNatives =((mods & Modifier.NATIVE) != 0)) break;
	}
	membersLt.setRedraw(false);
	if (hasNatives) {
		TableColumn column;
		column = new TableColumn(membersLt, SWT.NONE, METHOD_NAME_COLUMN);
		column.setText("Method");
		column = new TableColumn(membersLt, SWT.NONE, METHOD_FLAGS_COLUMN);
		column.setText("Flags");
		column = new TableColumn(membersLt, SWT.NONE, METHOD_ACCESSOR_COLUMN);
		column.setText("Accessor");
		/*
		column = new TableColumn(membersLt, SWT.NONE, METHOD_EXCLUDE_COLUMN);
		column.setText("Exclude");
		*/
		JNIGenerator.sort(methods);
		for (JNIMethod method : methods) {
			if ((method.getModifiers() & Modifier.NATIVE) == 0) continue;
			TableItem item = new TableItem(membersLt, SWT.NONE);
			item.setData(method);
			item.setText(METHOD_NAME_COLUMN, getMethodString(method));
			item.setChecked(method.getGenerate());
			item.setText(METHOD_FLAGS_COLUMN, getFlagsString(method.getFlags()));
			item.setText(METHOD_ACCESSOR_COLUMN, method.getAccessor());
			/*
			item.setText(METHOD_EXCLUDE_COLUMN, methodData.getExclude());
			*/
		}
	} else {
		TableColumn column;
		column = new TableColumn(membersLt, SWT.NONE, FIELD_NAME_COLUMN);
		column.setText("Field");
		column = new TableColumn(membersLt, SWT.NONE, FIELD_FLAGS_COLUMN);
		column.setText("Flags");
		column = new TableColumn(membersLt, SWT.NONE, FIELD_CAST_COLUMN);
		column.setText("Cast");
		column = new TableColumn(membersLt, SWT.NONE, FIELD_ACCESSOR_COLUMN);
		column.setText("Accessor");
		/*
		column = new TableColumn(membersLt, SWT.NONE, FIELD_EXCLUDE_COLUMN);
		column.setText("Exclude");
		*/
		for (JNIField field : clazz.getDeclaredFields()) {
			int mods = field.getModifiers(); 
			if (((mods & Modifier.PUBLIC) == 0) ||
				((mods & Modifier.FINAL) != 0) ||
				((mods & Modifier.STATIC) != 0)) continue;
			TableItem item = new TableItem(membersLt, SWT.NONE);
			item.setData(field);
			item.setText(FIELD_NAME_COLUMN, getFieldString(field));
			item.setChecked(field.getGenerate());
			item.setText(FIELD_CAST_COLUMN, field.getCast());
			item.setText(FIELD_FLAGS_COLUMN, getFlagsString(field.getFlags()));
			item.setText(FIELD_ACCESSOR_COLUMN, field.getAccessor());
			/*
			item.setText(FIELD_EXCLUDE_COLUMN, fieldData.getExclude());
			*/
		}
	}
	for (TableColumn column : membersLt.getColumns()) {
		column.pack();
	}
	membersLt.setHeaderVisible(true);
	membersLt.setRedraw(true);
}

void updateParameters() {
	paramsLt.removeAll();
	int[] indices = membersLt.getSelectionIndices();
	if (indices.length != 1) {
		paramsLt.setHeaderVisible(false);
		return;
	}
	TableItem memberItem = membersLt.getItem(indices[0]);
	Object data = memberItem.getData();
	if (!(data instanceof JNIMethod)) return;
	paramsLt.setRedraw(false);
	JNIMethod method = (JNIMethod)data;
	JNIParameter[] params = method.getParameters();
	for (int i = 0; i < params.length; i++) {
		JNIParameter param = params[i];
		TableItem item = new TableItem(paramsLt, SWT.NONE);
		item.setData(param);
		item.setText(PARAM_INDEX_COLUMN, String.valueOf(i));
		item.setText(PARAM_TYPE_COLUMN, getClassString(param.getType()));
		item.setText(PARAM_CAST_COLUMN, param.getCast());
		item.setText(PARAM_FLAGS_COLUMN, getFlagsString(param.getFlags()));
	}
	for (TableColumn column : paramsLt.getColumns()) {
		column.pack();
	}
	paramsLt.setRedraw(true);
	paramsLt.setHeaderVisible(true);
}

void updateGenerate(TableItem item) {
	JNIItem itemData = (JNIItem)item.getData();
	itemData.setGenerate(item.getChecked());
//	MetaData metaData = app.getMetaData();
//	if (itemData instanceof JNIClass) {
//		ClassData data = (ClassData)itemData;
//		metaData.setMetaData(data.getClazz(), data);
//	} else if (itemData instanceof FieldData) {
//		FieldData data = (FieldData)itemData;
//		item.setText(FIELD_FLAGS_COLUMN, getFlagsString(data.getFlags()));
//		metaData.setMetaData(data.getField(), data);
//	} else if (itemData instanceof MethodData) {
//		MethodData data = (MethodData)itemData;
//		item.setText(METHOD_FLAGS_COLUMN, getFlagsString(data.getFlags()));
//		metaData.setMetaData(data.getMethod(), data);
//	} else if (itemData instanceof ParameterData) {
//		ParameterData data = (ParameterData)itemData;
//		item.setText(PARAM_FLAGS_COLUMN, getFlagsString(data.getFlags()));
//		metaData.setMetaData(data.getMethod(), data.getParameter(), data);
//	}
}

boolean updateOutputDir() {
	String outputDirStr = outputDirCb.getText();
	File file = new File(outputDirStr);
	if (!file.exists()) {
		MessageBox dialog = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
		dialog.setMessage("Output directory does not exist.");
		dialog.open();
		return false;
	}
	if (!file.isDirectory()) {
		MessageBox dialog = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
		dialog.setMessage("Output directory is not a directory.");
		dialog.open();
		return false;
	}
	if (outputDirStr.length() > 0) {
		if (!outputDirStr.equals(app.getOutputDir())) {
			app.setOutputDir(outputDirStr);
		}
		if (outputDirCb.indexOf(outputDirStr) == -1) {
			outputDirCb.add(outputDirStr);
		}
	}
	return true;
}

void updateMainClass() {
	String mainClassStr = mainClassCb.getText();
	if (mainClassStr.length() > 0) {
		if (!mainClassStr.equals(app.getMainClassName())) {
			app.setMainClassName(mainClassStr);
		}
		if (mainClassCb.indexOf(mainClassStr) == -1) {
			mainClassCb.add(mainClassStr);
		}
		if (app.getOutputDir() != null) {
			int index = outputDirCb.indexOf(app.getOutputDir());
			if (index != -1) outputDirCb.select(index);
		}
	}
}

public static void main(String[] args) {
	JNIGeneratorApp gen = new JNIGeneratorApp ();
	if (args.length > 0) {
		gen.setMainClassName(args[0]);
		if (args.length > 1) gen.setOutputDir(args[1]);
	} else {
		gen.setMainClassName(JNIGeneratorApp.getDefaultMainClass());
	}
	JNIGeneratorAppUI ui = new JNIGeneratorAppUI(gen);
	ui.open();
	ui.run();
}

}
