custom tasks and types work in progress
diff --git a/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/AddTaskDialog.java b/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/AddTaskDialog.java
new file mode 100644
index 0000000..263697b
--- /dev/null
+++ b/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/AddTaskDialog.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2002 IBM Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors:
+ * IBM - Initial API and implementation
+ ******************************************************************************/
+package org.eclipse.ant.internal.ui;
+
+import java.net.URL;
+
+import org.eclipse.ant.core.AntCorePlugin;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.*;
+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.*;
+
+/**
+ * Dialog to prompt the user to add a custom ant task or type.
+ */
+public class AddTaskDialog extends Dialog {
+	protected String title;
+	protected String description;
+	
+	//task/type attributes
+	protected String taskName;
+	protected String className;
+	protected URL library;
+	
+	//widgets
+	protected Button okButton;
+	protected Text nameField;
+	protected Text classField;
+	protected Combo libraryField;
+	
+	protected URL[] libraryUrls;
+	
+/**
+ * Creates a new task dialog with the given shell and title.
+ */
+protected AddTaskDialog(Shell parentShell, String title, String description) {
+	super(parentShell);
+	this.title = title;
+	this.description = description;
+}
+/**
+ * @see Window#configureShell(Shell)
+ */
+protected void configureShell(Shell newShell) {
+	super.configureShell(newShell);
+	newShell.setText(title);
+}
+/**
+ * @see Dialog#createButtonsForButtonBar(Composite)
+ */
+protected void createButtonsForButtonBar(Composite parent) {
+	okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+	createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+	updateEnablement();
+}
+/**
+ * @see Dialog#createDialogArea(Composite)
+ */
+protected Control createDialogArea(Composite parent) {
+	Composite dialogArea = new Composite(parent, SWT.NONE);
+	GridLayout layout = new GridLayout();
+	layout.numColumns = 2;
+	layout.marginHeight = 10;
+	layout.marginWidth = 10;
+	dialogArea.setLayout(layout);
+	
+	Label label = new Label(dialogArea, SWT.NONE);
+	label.setText(description);
+	GridData data = new GridData(GridData.FILL_HORIZONTAL);
+	data.horizontalSpan = 2;
+	label.setLayoutData(data);
+	
+	label = new Label(dialogArea, SWT.NONE);
+	label.setText(Policy.bind("preferences.customize.addTaskDialogName"));
+	nameField = new Text(dialogArea, SWT.BORDER);
+	data = new GridData(GridData.FILL_HORIZONTAL);
+	data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
+	nameField.setLayoutData(data);
+	nameField.addModifyListener(new ModifyListener() {
+		public void modifyText(ModifyEvent e) {
+			updateEnablement();
+		}
+	});
+
+	label = new Label(dialogArea, SWT.NONE);
+	label.setText(Policy.bind("preferences.customize.addTaskDialogClass"));
+	classField = new Text(dialogArea, SWT.BORDER);
+	data = new GridData(GridData.FILL_HORIZONTAL);
+	data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
+	classField.setLayoutData(data);
+	classField.addModifyListener(new ModifyListener() {
+		public void modifyText(ModifyEvent e) {
+			updateEnablement();
+		}
+	});
+	
+	label = new Label(dialogArea, SWT.NONE);
+	label.setText(Policy.bind("preferences.customize.addTaskDialogLibrary"));
+	libraryField = new Combo(dialogArea, SWT.READ_ONLY | SWT.BORDER);
+	data = new GridData(GridData.FILL_HORIZONTAL);
+	data.widthHint = IDialogConstants.ENTRY_FIELD_WIDTH;
+	libraryField.setLayoutData(data);
+	libraryField.addSelectionListener(new SelectionAdapter() {
+		public void widgetSelected(SelectionEvent e) {
+			updateEnablement();
+		}
+	});
+	
+	//populate library combo and select input library
+	libraryUrls = AntCorePlugin.getPlugin().getPreferences().getCustomURLs();
+	int selection = 0;
+	for (int i = 0; i < libraryUrls.length; i++) {
+		libraryField.add(libraryUrls[i].getFile());
+		if (libraryUrls[i].equals(library))
+			selection = i;
+	}
+		
+	//intialize fields
+	if (taskName != null)
+		nameField.setText(taskName);
+	if (className != null)
+		classField.setText(className);
+	if (libraryUrls.length >= 0)
+		libraryField.select(selection);
+	return dialogArea;
+}
+
+public String getClassName() {
+	return className;
+}
+public void setClassName(String className) {
+	this.className = className;
+}
+public URL getLibrary() {
+	return library;
+}
+/**
+ * @see Dialog#okPressed()
+ */
+protected void okPressed() {
+	className = classField.getText();
+	taskName = nameField.getText();
+	int selection = libraryField.getSelectionIndex();
+	if (selection >= 0)
+		library = libraryUrls[selection];
+	super.okPressed();
+}
+public void setLibrary(URL library) {
+	this.library = library;
+}
+public String getTaskName() {
+	return taskName;
+}
+public void setTaskName(String taskName) {
+	this.taskName = taskName;
+}
+protected void updateEnablement() {
+	if (okButton != null)
+		okButton.setEnabled(nameField.getText().length() > 0 && 
+			classField.getText().length() > 0 &&
+			libraryField.getSelectionIndex() >= 0);
+}
+}
diff --git a/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/CustomizeAntLabelProvider.java b/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/CustomizeAntLabelProvider.java
index 6c8d3cb..646d447 100644
--- a/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/CustomizeAntLabelProvider.java
+++ b/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/CustomizeAntLabelProvider.java
@@ -68,11 +68,11 @@
 	}
 	if (element instanceof Task) {
 		Task task = (Task)element;
-		return task.getTaskName() + "(" + task.getClassName() + ")";
+		return task.getTaskName() + " (" + task.getLibrary().getFile()+ ": " + task.getClassName() + ")";
 	}
 	if (element instanceof Type) {
 		Type type = (Type)element;
-		return type.getTypeName() + "(" + type.getClassName() + ")";
+		return type.getTypeName() + " (" + type.getLibrary().getFile()+ ": " + type.getClassName() + ")";
 	}
 	return element.toString();
 }
diff --git a/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/CustomizeAntPage.java b/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/CustomizeAntPage.java
index 07d83d0..dd35dbf 100644
--- a/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/CustomizeAntPage.java
+++ b/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/CustomizeAntPage.java
@@ -15,6 +15,7 @@
 
 import org.eclipse.jface.dialogs.Dialog;
 import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.*;
 import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.viewers.TableViewer;
 import org.eclipse.swt.SWT;
@@ -49,7 +50,7 @@
 /**
  * Should be overwritten by subclasses to handle button behaviour.
  */
-protected void buttonPressed(int buttonID) {
+protected void buttonPressed(int buttonId) {
 }
 
 /**
@@ -98,7 +99,13 @@
 	contentProvider = new CustomizeAntContentProvider();
 	tableViewer.setContentProvider(contentProvider);
 	tableViewer.setLabelProvider(new CustomizeAntLabelProvider());
+	tableViewer.addSelectionChangedListener(new ISelectionChangedListener() {
+		public void selectionChanged(SelectionChangedEvent event) {
+			tableSelectionChanged((IStructuredSelection)event.getSelection());
+		}
+	});
 }
+
 /**
  * Returns the currently listed objects in the table.  Returns null
  * if this widget has not yet been created or has been disposed.
@@ -111,7 +118,10 @@
 }
 protected void removeButtonPressed() {
 	IStructuredSelection selection = (IStructuredSelection)tableViewer.getSelection();
-	tableViewer.remove(selection.toArray());
+	Object[] selected = selection.toArray();
+	for (int i = 0; i < selected.length; i++) {
+		contentProvider.remove(selected[i]);
+	}
 }
 /**
  * Sets the contents of the table on this page.  Has no effect
@@ -121,6 +131,12 @@
 	if (tableViewer == null || tableViewer.getControl().isDisposed())
 		return;
 	tableViewer.setInput(inputs);
+	tableSelectionChanged((IStructuredSelection)tableViewer.getSelection());
+}
+/**
+ * Subclasses may override to add behaviour when table selection changes.
+ */
+protected void tableSelectionChanged(IStructuredSelection newSelection) {
 }
 
 /**
diff --git a/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/TasksPage.java b/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/TasksPage.java
index 76db60c..04286b4 100644
--- a/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/TasksPage.java
+++ b/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/TasksPage.java
@@ -10,7 +10,11 @@
  ******************************************************************************/
 package org.eclipse.ant.internal.ui;
 
+import org.eclipse.ant.internal.core.Task;
+import org.eclipse.jface.dialogs.Dialog;
 import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.*;
 import org.eclipse.ui.ISharedImages;
@@ -20,7 +24,8 @@
  * A widget group for the tasks tab of the ant classpath preference page.
  */
 public class TasksPage extends CustomizeAntPage {
-	protected Control control;
+	protected Button editButton;
+	protected Button removeButton;
 
 	//button constants
 	protected static final int ADD_TASK_BUTTON= IDialogConstants.CLIENT_ID + 1;
@@ -31,12 +36,35 @@
 }
 protected void addButtonsToButtonGroup(Composite parent) {
 	createButton(parent, "preferences.customize.addTaskButtonTitle", ADD_TASK_BUTTON);
-	createButton(parent, "preferences.customize.editTaskButtonTitle", EDIT_TASK_BUTTON);
+	editButton = createButton(parent, "preferences.customize.editTaskButtonTitle", EDIT_TASK_BUTTON);
 	createSeparator(parent);
-	createButton(parent, "preferences.customize.removeButtonTitle", REMOVE_BUTTON);
+	removeButton = createButton(parent, "preferences.customize.removeButtonTitle", REMOVE_BUTTON);
 }
-protected void buttonPressed(int buttonID) {
-	super.buttonPressed(buttonID);
+protected void addTaskButtonPressed() {
+	String title = Policy.bind("preferences.customize.addTaskDialogTitle");
+	String msg = Policy.bind("preferences.customize.addTaskDialogDescription");
+	AddTaskDialog dialog = new AddTaskDialog(tableViewer.getControl().getShell(), title, msg);
+	if (dialog.open() == Dialog.CANCEL)
+		return;
+		
+	Task task = new Task();
+	task.setTaskName(dialog.getTaskName());
+	task.setClassName(dialog.getClassName());
+	task.setLibrary(dialog.getLibrary());
+	contentProvider.add(task);	
+}
+protected void buttonPressed(int buttonId) {
+	switch (buttonId) {
+		case ADD_TASK_BUTTON:
+			addTaskButtonPressed();
+			break;
+		case EDIT_TASK_BUTTON:
+			editTaskButtonPressed();
+			break;
+		case REMOVE_BUTTON:
+			removeButtonPressed();
+			break;
+	}
 }
 /**
  * Creates and returns a tab item that contains this widget group.
@@ -49,4 +77,32 @@
 	item.setControl(createControl(folder));
 	return item;
 }
+protected void editTaskButtonPressed() {
+	String title = Policy.bind("preferences.customize.editTaskDialogTitle");
+	String msg = Policy.bind("preferences.customize.editTaskDialogDescription");
+	AddTaskDialog dialog = new AddTaskDialog(tableViewer.getControl().getShell(), title, msg);
+	IStructuredSelection selection = (IStructuredSelection)tableViewer.getSelection();
+	if (selection.isEmpty())
+		return;
+	Task task = (Task)selection.getFirstElement();
+	dialog.setClassName(task.getClassName());
+	dialog.setTaskName(task.getTaskName());
+	dialog.setLibrary(task.getLibrary());
+	if (dialog.open() == Dialog.CANCEL)
+		return;
+		
+	task.setTaskName(dialog.getTaskName());
+	task.setClassName(dialog.getClassName());
+	task.setLibrary(dialog.getLibrary());
+	tableViewer.update(task, null);
+}
+/**
+ * @see CustomizeAntPage#tableSelectionChanged(ISelection)
+ */
+protected void tableSelectionChanged(IStructuredSelection newSelection) {
+	int size = newSelection.size();
+	editButton.setEnabled(size == 1);
+	removeButton.setEnabled(size > 0);
+}
+
 }
\ No newline at end of file
diff --git a/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/TypesPage.java b/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/TypesPage.java
index 8bedbe3..a04d5be 100644
--- a/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/TypesPage.java
+++ b/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/TypesPage.java
@@ -10,7 +10,10 @@
  ******************************************************************************/
 package org.eclipse.ant.internal.ui;
 
+import org.eclipse.ant.internal.core.Type;
+import org.eclipse.jface.dialogs.Dialog;
 import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.DisposeEvent;
 import org.eclipse.swt.events.DisposeListener;
@@ -21,6 +24,9 @@
  * A widget group for the types tab of the ant classpath preference page.
  */
 public class TypesPage extends CustomizeAntPage {
+	protected Button editButton;
+	protected Button removeButton;
+
 	//button constants
 	protected static final int ADD_TYPE_BUTTON= IDialogConstants.CLIENT_ID + 1;
 	protected static final int EDIT_TYPE_BUTTON = IDialogConstants.CLIENT_ID + 2;
@@ -30,12 +36,35 @@
 }
 protected void addButtonsToButtonGroup(Composite parent) {
 	createButton(parent, "preferences.customize.addTypeButtonTitle", ADD_TYPE_BUTTON);
-	createButton(parent, "preferences.customize.editTypeButtonTitle", EDIT_TYPE_BUTTON);
+	editButton = createButton(parent, "preferences.customize.editTypeButtonTitle", EDIT_TYPE_BUTTON);
 	createSeparator(parent);
-	createButton(parent, "preferences.customize.removeButtonTitle", REMOVE_BUTTON);
+	removeButton = createButton(parent, "preferences.customize.removeButtonTitle", REMOVE_BUTTON);
 }
-protected void buttonPressed(int buttonID) {
-	super.buttonPressed(buttonID);
+protected void addTypeButtonPressed() {
+	String title = Policy.bind("preferences.customize.addTypeDialogTitle");
+	String msg = Policy.bind("preferences.customize.addTypeDialogDescription");
+	AddTaskDialog dialog = new AddTaskDialog(tableViewer.getControl().getShell(), title, msg);
+	if (dialog.open() == Dialog.CANCEL)
+		return;
+		
+	Type type = new Type();
+	type.setTypeName(dialog.getTaskName());
+	type.setClassName(dialog.getClassName());
+	type.setLibrary(dialog.getLibrary());
+	contentProvider.add(type);	
+}
+protected void buttonPressed(int buttonId) {
+	switch (buttonId) {
+		case ADD_TYPE_BUTTON:
+			addTypeButtonPressed();
+			break;
+		case EDIT_TYPE_BUTTON:
+			editTypeButtonPressed();
+			break;
+		case REMOVE_BUTTON:
+			removeButtonPressed();
+			break;
+	}
 }
 public TabItem createTabItem(TabFolder folder) {
 	TabItem item = new TabItem(folder, SWT.NONE);
@@ -52,4 +81,31 @@
 	});
 	return item;
 }
+protected void editTypeButtonPressed() {
+	String title = Policy.bind("preferences.customize.editTypeDialogTitle");
+	String msg = Policy.bind("preferences.customize.editTypeDialogDescription");
+	AddTaskDialog dialog = new AddTaskDialog(tableViewer.getControl().getShell(), title, msg);
+	IStructuredSelection selection = (IStructuredSelection)tableViewer.getSelection();
+	if (selection.isEmpty())
+		return;
+	Type type= (Type)selection.getFirstElement();
+	dialog.setClassName(type.getClassName());
+	dialog.setTaskName(type.getTypeName());
+	dialog.setLibrary(type.getLibrary());
+	if (dialog.open() == Dialog.CANCEL)
+		return;
+		
+	type.setTypeName(dialog.getTaskName());
+	type.setClassName(dialog.getClassName());
+	type.setLibrary(dialog.getLibrary());
+	tableViewer.update(type, null);
+}
+/**
+ * @see CustomizeAntPage#tableSelectionChanged(ISelection)
+ */
+protected void tableSelectionChanged(IStructuredSelection newSelection) {
+	int size = newSelection.size();
+	editButton.setEnabled(size == 1);
+	removeButton.setEnabled(size > 0);
+}
 }
\ No newline at end of file
diff --git a/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/messages.properties b/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/messages.properties
index df4bd07..bc7e3c4 100644
--- a/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/messages.properties
+++ b/ant/org.eclipse.ant.ui/src/org/eclipse/ant/internal/ui/messages.properties
@@ -41,7 +41,17 @@
 preferences.customize.editTypeButtonTitle = &Edit Type
 preferences.customize.addTaskButtonTitle = &Add Task
 preferences.customize.editTaskButtonTitle = &Edit Task
-
+preferences.customize.addTaskDialogName = &Name
+preferences.customize.addTaskDialogClass = &Class
+preferences.customize.addTaskDialogLibrary = &Library
+preferences.customize.addTaskDialogDescription = Enter a name, java class, and library for your custom task.
+preferences.customize.addTaskDialogTitle = Add Task
+preferences.customize.editTaskDialogDescription = Modify the name, java class, and library of your custom task
+preferences.customize.editTaskDialogTitle = Edit Task
+preferences.customize.addTypeDialogDescription = Enter a name, java class, and library for your custom type.
+preferences.customize.addTypeDialogTitle = Add Type
+preferences.customize.editTypeDialogDescription = Modify the name, java class, and library of your custom type
+preferences.customize.editTypeDialogTitle = Edit Type
 
 ### console labels
 find_action.label=&Find...@Ctrl+F