|
|
|
svn_geotools
|
Author: mbedward
Date: 2009-10-30 08:33:06 -0400 (Fri, 30 Oct 2009) New Revision: 34289 Added: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/DnDList.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/DnDListItemsTransferable.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/DnDListModel.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/IntegerDocument.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/JIntegerField.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/JValueField.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/ValueChangedEvent.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/ValueChangedListener.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/package-info.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialog/ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialog/JFileImageChooser.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialog/JMapImageDialog.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialog/package-info.java Removed: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/DnDList.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/DnDListItemsTransferable.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/DnDListModel.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/IntegerDocument.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/JIntegerField.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/JValueField.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/ValueChangedEvent.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/ValueChangedListener.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/package-info.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialogs/JFileImageChooser.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialogs/JMapImageDialog.java trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialogs/package-info.java Modified: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/MapLayerTable.java trunk/modules/unsupported/swing/src/test/java/org/geotools/swing/dndlist/DnDListModelTest.java trunk/modules/unsupported/swing/src/test/java/org/geotools/swing/dndlist/DnDListTest.java Log: twiddled package names Modified: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/MapLayerTable.java =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/MapLayerTable.java 2009-10-30 11:10:24 UTC (rev 34288) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/MapLayerTable.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -23,7 +23,7 @@ import java.awt.event.MouseEvent; import javax.swing.Icon; import javax.swing.event.ListDataEvent; -import org.geotools.swing.controls.DnDList; +import org.geotools.swing.control.DnDList; import java.awt.Point; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; @@ -34,7 +34,7 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.event.ListDataListener; -import org.geotools.swing.controls.DnDListModel; +import org.geotools.swing.control.DnDListModel; import org.geotools.map.MapLayer; import org.geotools.styling.Style; import org.geotools.swing.styling.JSimpleStyleDialog; Copied: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/DnDList.java (from rev 34283, trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/DnDList.java) =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/DnDList.java (rev 0) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/DnDList.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -0,0 +1,300 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +package org.geotools.swing.control; + +import java.awt.datatransfer.Transferable; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceDragEvent; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DragSourceEvent; +import java.awt.dnd.DragSourceListener; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; +import java.util.List; +import java.util.ResourceBundle; + +import javax.swing.JList; + +/** + * A sub-class of JList that supports drag and drop to reorder items within a single list + * and to copy or move items between lists. It is used by the + * {@linkplain org.geotools.swing.MapLayerTable} widget but has been written + * in a general fashion so that it may be used for other pusposes. + * + * @see DnDListModel + * + * @author Michael Bedward + * @since 2.6 + * @source $URL$ + * @version $Id$ + */ +public class DnDList<T> extends JList implements DragGestureListener, DragSourceListener, DropTargetListener { + private static final long serialVersionUID = 3310751294076288683L; + + private static final ResourceBundle stringRes = ResourceBundle.getBundle("org/geotools/swing/Text"); + + private DragSource src; + + @SuppressWarnings("unused") + private DropTarget tgt; // this is not used? what is it for + + private boolean movingItems; + private int overIndex; + private int[] dragIndices; + + /** + * Default constructor. An DnDListModel object will be created + * for the list. + */ + public DnDList() { + this(new DnDListModel<T>()); + } + + /** + * Constructor allowing the list model to be specified + * @param model an instance of DnDListModel + * @throws IllegalArgumentException if model is null + */ + public DnDList(DnDListModel<T> model) { + super( model ); + if (model == null) { + throw new IllegalArgumentException(stringRes.getString("arg_null_error")); + } + //this.setModel(model); + + src = new DragSource(); + src.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, this); + + tgt = new DropTarget(this, this); + + setDragEnabled(true); + movingItems = false; + overIndex = -1; + } + + @SuppressWarnings("unchecked") + @Override + public DnDListModel<T> getModel() { + return (DnDListModel<T>) super.getModel(); + } + /** + * Called by the system when a drag gesture starts + */ + public void dragGestureRecognized(DragGestureEvent dge) { + dragIndices = getSelectedIndices(); + if (dragIndices.length > 0) { + List<T> items = getModel().getElementsAt(dragIndices); + Transferable stuff = new DnDListItemsTransferable<T>(items); + movingItems = true; + src.startDrag(dge, DragSource.DefaultMoveDrop, stuff, this); + } + } + + + /** + * DragSourceListener method - presently ignored + * <p> + * Description copied from interface:<br> + * Called as the cursor's hotspot enters a platform-dependent drop site. + * This method is invoked when all the following conditions are true: + * <ul> + * <li> The cursor's hotspot enters the operable part of a platform- dependent drop site. + * <li> The drop site is active. + * <li> The drop site accepts the drag. + * </ul> + */ + public void dragEnter(DragSourceDragEvent dsde) { + // do nothing + } + + /** + * DragSourceListener method - presently ignored + * <p> + * Description copied from interface:<br> + * Called as the cursor's hotspot moves over a platform-dependent drop site. + * This method is invoked when all the following conditions are true: + * <ul> + * <li> The cursor's hotspot has moved, but still intersects the operable part + * of the drop site associated with the previous dragEnter() invocation. + * <li> The drop site is still active. + * <li> The drop site accepts the drag. + * </ul> + */ + public void dragOver(DragSourceDragEvent dsde) { + // do nothing + } + + /** + * DragSourceListener method - presently ignored + * <p> + * Description copied from interface:<br> + * Called when the user has modified the drop gesture. This method is invoked when + * the state of the input device(s) that the user is interacting with changes. + * Such devices are typically the mouse buttons or keyboard modifiers that the + * user is interacting with. + */ + public void dropActionChanged(DragSourceDragEvent dsde) { + // do nothing + } + + /** + * DragSourceListener method - presently ignored + * <p> + * Description copied from interface:<br> + * Called as the cursor's hotspot exits a platform-dependent drop site. + * This method is invoked when <b>any</b> of the following conditions are true: + * <ul> + * <li> The cursor's hotspot no longer intersects the operable part of the + * drop site associated with the previous dragEnter() invocation. + * <li> The drop site associated with the previous dragEnter() invocation is + * no longer active. + * <li> The drop site associated with the previous dragEnter() invocation + * has rejected the drag. + * </ul> + */ + public void dragExit(DragSourceEvent dse) { + // do nothing + } + + /** + * Description copied from interface:<br> + * This method is invoked to signify that the Drag and Drop operation is + * complete. The getDropSuccess() method of the DragSourceDropEvent can be + * used to determine the termination state. The getDropAction() method returns + * the operation that the drop site selected to apply to the Drop operation. + * Once this method is complete, the current DragSourceContext and associated + * resources become invalid. + */ + public void dragDropEnd(DragSourceDropEvent dsde) { + movingItems = false; + overIndex = -1; + } + + /** + * Records the index of the list item (if any) pointed to by the mouse cursor + * <p> + * Description copied from interface:<br> + * Called while a drag operation is ongoing, when the mouse pointer enters + * the operable part of the drop site for the DropTarget registered with + * this listener. + */ + public void dragEnter(DropTargetDragEvent dtde) { + overIndex = this.locationToIndex(dtde.getLocation()); + setSelectedIndex(overIndex); + } + + + /** + * Records the index of the list item (if any) pointed to by the mouse cursor + * <p> + * Description copied from interface:<br> + * Called when a drag operation is ongoing, while the mouse pointer is still + * over the operable part of the drop site for the DropTarget registered with + * this listener. + */ + public void dragOver(DropTargetDragEvent dtde) { + int index = this.locationToIndex(dtde.getLocation()); + if (index >= 0 && index != overIndex) { + overIndex = index; + setSelectedIndex(overIndex); + } + } + + /** + * DropTargetListener method - presently ignored + * <p> + * Description copied from interface:<br> + * Called if the user has modified the current drop gesture. + */ + public void dropActionChanged(DropTargetDragEvent dtde) { + // do nothing + } + + /** + * Description copied from interface:<br> + * Called while a drag operation is ongoing, when the mouse pointer has exited + * the operable part of the drop site for the DropTarget registered with this + * listener. + */ + public void dragExit(DropTargetEvent dte) { + overIndex = -1; + } + + /** + * Handles the moving (for drag and drop actions within this list) or transfer + * (for actions between lists) of list items. + * Description copied from interface:<br> + * Called when the drag operation has terminated with a drop on the operable part + * of the drop site for the DropTarget registered with this listener. + * <p> + * This method is responsible for undertaking the transfer of the data associated + * with the gesture. The DropTargetDropEvent provides a means to obtain a Transferable + * object that represents the data object(s) to be transfered. + * <p> + * From this method, the DropTargetListener shall accept or reject the drop via + * the acceptDrop(int dropAction) or rejectDrop() methods of the DropTargetDropEvent + * parameter. + * <p> + * Subsequent to acceptDrop(), but not before, DropTargetDropEvent's getTransferable() + * method may be invoked, and data transfer may be performed via the returned + * Transferable's getTransferData() method. + * <p> + * At the completion of a drop, an implementation of this method is required to + * signal the success/failure of the drop by passing an appropriate boolean to the + * DropTargetDropEvent's dropComplete(boolean success) method. + * <p> + * Note: The data transfer should be completed before the call to the + * DropTargetDropEvent's dropComplete(boolean success) method. After that, a call + * to the getTransferData() method of the Transferable returned by + * DropTargetDropEvent.getTransferable() is guaranteed to succeed only if the data + * transfer is local; that is, only if DropTargetDropEvent.isLocalTransfer() + * returns true. Otherwise, the behavior of the call is implementation-dependent. + */ + public void drop(DropTargetDropEvent dtde) { + //Transferable stuff = dtde.getTransferable(); + + /* + * @todo check DataFlavor of stuff + */ + dtde.acceptDrop(DnDConstants.ACTION_MOVE); + + if (movingItems) { + /* + * This is a local drag and drop to reorder items + */ + DnDListModel<T> model = getModel(); + model.moveItems(overIndex, dragIndices); + + } else { + + // @todo stuff dragged from other list + + } + + overIndex = -1; + movingItems = false; + dtde.getDropTargetContext().dropComplete(true); + } + +} Copied: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/DnDListItemsTransferable.java (from rev 34283, trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/DnDListItemsTransferable.java) =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/DnDListItemsTransferable.java (rev 0) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/DnDListItemsTransferable.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -0,0 +1,85 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +package org.geotools.swing.control; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * Implements the Transferable interface to carry list item data + * during drag and drop actions. This class is used by DnDList. + * Client code will not normally need to refer to it. + * + * @see DnDList + * @author Michael Bedward + * @since 2.6 + * @source $URL$ + * @version $Id$ + */ +public class DnDListItemsTransferable<T> implements Transferable { + + private List<T> items; + + /** + * Constructor + * @param stuff a Collection of list item data + */ + public DnDListItemsTransferable(Collection<T> stuff) { + super(); + items = new ArrayList<T>(); + items.addAll(stuff); + } + + /** + * Description copies from interface:<br> + * Returns an array of DataFlavor objects indicating the flavors + * the data can be provided in. The array should be ordered according + * to preference for providing the data (from most richly descriptive + * to least descriptive). + */ + public DataFlavor[] getTransferDataFlavors() { + // @todo WRITE ME ! + return null; + } + + /** + * Description copies from interface:<br> + * Returns whether or not the specified data flavor is supported for this object. + */ + public boolean isDataFlavorSupported(DataFlavor flavor) { + // @todo WRITE ME ! + return true; + } + + /** + * Returns a List of items to be transferred. + * + * @param flavor - required by the interface but ignored here + * + * @throws IOException if the data is no longer available in the requested flavor. + * @throws UnsupportedFlavorException if the requested data flavor is not supported. + */ + public List<T> getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { + return items; + } +} Copied: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/DnDListModel.java (from rev 34283, trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/DnDListModel.java) =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/DnDListModel.java (rev 0) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/DnDListModel.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -0,0 +1,296 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ +package org.geotools.swing.control; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.ListIterator; + +import javax.swing.AbstractListModel; + +/** + * A generic ListModel class to support {@linkplain DnDList}. + * <p> + * The DnDListModel acts as a wrapper around an internal list of + * items; providing notification as the items are changed. + * </p> + * @author Michael Bedward + * @since 2.6 + * @source $URL$ + * @version $Id$ + */ +public class DnDListModel<T> extends AbstractListModel { + private static final long serialVersionUID = -6110074993686576005L; + List<T> items; + private boolean notify; + + /** + * Default constructor + */ + public DnDListModel() { + items = new ArrayList<T>(); + notify = true; + } + + public void setNofifyListeners(boolean notify) { + this.notify = notify; + } + + public boolean getNotifyListeners() { + return notify; + } + + public int getSize() { + return items.size(); + } + + /** + * Get the list item at the specified index. + * <p> + * Note: this method returns a live reference. + * + * @throws IndexOutOfBoundsException if index is invalid + */ + public T getElementAt(int index) { + return items.get(index); + } + + /** + * Returns a list of the items at the specified indices. + * <p> + * Note: The returned List contains live references. + * + * @throws IndexOutOfBoundsException if any of the indices are invalid + */ + public List<T> getElementsAt(int[] indices) { + List<T> refs = new ArrayList<T>(); + for (int k = 0; k < indices.length; k++) { + refs.add(items.get(indices[k])); + } + + return refs; + } + + /** + * Returns a list of the items at the indices specified in the Collection. + * <p> + * Note: The returned List contains live references. + * + * @throws IndexOutOfBoundsException if any of the indices are invalid + */ + public List<T> getElementsAt(Collection<Integer> indices) { + List<T> refs = new ArrayList<T>(); + for (Integer index : indices) { + refs.add(items.get(index)); + } + + return refs; + } + + /** + * Append a new item to the end of the list of current items + */ + public void addItem(T newItem) { + int index = items.size(); + items.add(newItem); + + if (notify) { + fireIntervalAdded(this, index, index); + } + } + + /** + * Add new items to the end of the list of current items + */ + public void addItems(T[] newItems) { + if (newItems.length > 0) { + int index0 = items.size(); + + for (T item : newItems) { + items.add(item); + } + + if (notify) { + fireIntervalAdded(this, index0, index0 + newItems.length - 1); + } + } + } + + /** + * Add new items to the end of the list of current items + */ + public void addItems(Collection<T> newItems) { + if (!newItems.isEmpty()) { + int index0 = items.size(); + + for (T item : newItems) { + items.add(item); + } + + if (notify) { + fireIntervalAdded(this, index0, index0 + newItems.size() - 1); + } + } + } + + /** + * Insert an item into the list at the specified position. + * @param destIndex the position of the new item: if < 0 the item will + * be inserted at the start of the list; if >= the current list size + * the item will be appended to the end of the list + */ + public void insertItem(int destIndex, T newItem) { + if (destIndex < 0) { + destIndex = 0; + } else if (destIndex >= getSize()) { + addItem(newItem); + return; + } + + items.add(destIndex, newItem); + + if (notify) { + fireIntervalAdded(this, destIndex, destIndex); + } + } + + /** + * Insert new items into the list at the specified position. + * + * @param destIndex the position of the new item: if < 0 the items will + * be inserted at the start of the list; if >= the current list size + * the items will be appended to the end of the list + */ + public void insertItems(int destIndex, T[] newItems) { + insertItems(destIndex, Arrays.asList(newItems)); + } + + /** + * Insert new items into the list at the specified position. + * + * @param destIndex the position of the new item: if < 0 the items will + * be inserted at the start of the list; if >= the current list size + * the items will be appended to the end of the list + */ + public void insertItems(int destIndex, Collection<T> newItems) { + if (destIndex < 0) { + destIndex = 0; + } else if (destIndex >= getSize()) { + addItems(newItems); + return; + } + + items.addAll(destIndex, newItems); + + if (notify) { + fireIntervalAdded(this, destIndex, destIndex + newItems.size() - 1); + } + } + + /** + * Move the items currently positioned at the indices in the + * {@code srcIndices} array as block such that they are inserted + * into the list at {@code destIndex}. It is <b>assumed</b> that + * srcIndices is sorted in ascending order. + */ + public void moveItems(int destIndex, int[] srcIndices) { + if (srcIndices.length > 0) { + List<T> copies = getElementsAt(srcIndices); + + int minIndex = Math.min(destIndex, srcIndices[0]); + int maxIndex = Math.max(destIndex - 1, srcIndices[srcIndices.length - 1]); + + for (int k = srcIndices.length - 1; k >= 0; k--) { + items.remove(srcIndices[k]); + } + + notify = false; + insertItems(destIndex, copies); + this.fireContentsChanged(this, minIndex, maxIndex); + notify = true; + } + } + + /** + * Remove the item at the specified index + */ + public void removeAt(int index) { + items.remove(index); + if (notify) { + fireIntervalRemoved(this, index, index); + } + } + + /** + * Removes the first instance of the specified item if it is contained in the list + */ + public void removeItem(T item) { + ListIterator<T> iter = items.listIterator(); + int index = 0; + boolean found = false; + + while (iter.hasNext()) { + T anItem = iter.next(); + if (anItem.equals(item)) { + iter.remove(); + found = true; + break; + } + + index++; + } + + if (found && notify) { + this.fireIntervalRemoved(this, index, index); + } + } + + /** + * Remove all items from the list + */ + public void clear() { + int prevSize = items.size(); + items.clear(); + if (notify) { + this.fireIntervalRemoved(this, 0, prevSize); + } + } + + /** + * Query whether this list contains the specified item + */ + public boolean contains(T item) { + return items.contains(item); + } + + /** + * Get the (first) index of the given item in the list of items held by this model. + * + * @param item the item to search for + * @return the index or -1 if the item is not present + */ + public int indexOf(T item) { + return items.indexOf(item); + } + + @Override + public String toString() { + return "DnD:"+items; + } +} Copied: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/IntegerDocument.java (from rev 34283, trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/IntegerDocument.java) =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/IntegerDocument.java (rev 0) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/IntegerDocument.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -0,0 +1,138 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +package org.geotools.swing.control; + +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.PlainDocument; + +/** + * A document class to handle integer verification and parsing for + * {@code JIntTextField} and other classes wishing to restrict user input + * to integer values. + * + * @author Michael Bedward + * @since 2.6.1 + * @source $URL$ + * @version $Id$ + */ +class IntegerDocument extends PlainDocument { + + private int value; + private boolean allowNegative; + + /** + * Creates a new document that will allow both positive and negative values + */ + public IntegerDocument() { + this(true); + } + + /** + * Creates a new document + * + * @param allowNegative true to allow negative values; false to allow only positive values + */ + public IntegerDocument(boolean allowNegative) { + this.allowNegative = allowNegative; + } + + /** + * Get the value corresponding to the current text + * @return the current value + */ + public int getValue() { + return value; + } + + /** + * Test if this document allows negative values + * + * @return true if negative values are allowed; false if only positive values are allowed + */ + public boolean getAllowsNegative() { + return allowNegative; + } + + /** + * {@inheritDoc} + */ + @Override + public void insertString(int offset, String text, AttributeSet attributes) throws BadLocationException { + if (text != null) { + String newText; + + if (getLength() == 0) { + newText = text; + + } else { + StringBuilder sb = new StringBuilder(getText(0, getLength())); + sb.insert(offset, text); + newText = sb.toString(); + } + + if (allowNegative && offset == 0 && newText.equals("-")) { + value = 0; + } else { + value = checkInput(newText, offset); + } + super.insertString(offset, text, attributes); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void remove(int offset, int length) throws BadLocationException { + final int curLen = getLength(); + final String currentContent = getText(0, curLen); + final String newText = currentContent.substring(0, offset) + + currentContent.substring(length + offset, curLen); + + if (allowNegative && offset == 0 && newText.equals("-")) { + value = 0; + } else { + value = checkInput(newText, offset); + } + super.remove(offset, length); + } + + /** + * Check the proposed text and, if it is valid, parse it as an integer value. + * + * @param proposedText the proposed text value + * @param offset position in the document + * @return the parsed integer value + * + * @throws BadLocationException if the string did not represent a value integer + */ + public int checkInput(String proposedText, int offset) throws BadLocationException { + int newValue = 0; + + if (proposedText != null && proposedText.length() > 0) { + try { + newValue = Integer.parseInt(proposedText); + } catch (NumberFormatException ex) { + throw new BadLocationException(proposedText, offset); + } + } + + return newValue; + } +} Copied: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/JIntegerField.java (from rev 34283, trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/JIntegerField.java) =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/JIntegerField.java (rev 0) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/JIntegerField.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -0,0 +1,164 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +package org.geotools.swing.control; + +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; + +/** + * A text field control to work with integer values. It can be constrained to positive values if + * desired. It also provides an API for listening to value changes that is simpler than messing + * about with Swing {@code KeyListener} and {@code DocumentListener}. + * <p> + * Example of use: + * <pre><code> + * int initialValue = ... + * boolean allowNegatives = false; + * JIntegerField control = new JIntegerField(initialValue, allowNegatives); + * control.addValueChangedListener( new ValueChangedListener() { + * public void onValueChanged( ValueChangedEvent ev ) { + * System.out.println("The new value is " + ev.getValue()); + * } + * }); + * </code></pre> + * + * @author Michael Bedward + * @since 2.6.1 + * @source $URL$ + * @version $Id$ + */ +public class JIntegerField extends JValueField { + + private IntegerDocument document; + private boolean fireEvents; + + /** + * Creates a new text field that allows negative values and + * has an initial value of 0. + */ + public JIntegerField() { + this(0, true); + } + + /** + * Creates a new text field with an initial value of 0. + * + * @param allowNegative true if this field should allow negative values to + * be entered; false if only positive values are allowed + */ + public JIntegerField(boolean allowsNegative) { + this(0, allowsNegative); + } + + /** + * Creates a new text field that allows negative values and + * the given initial value. + * + * @param value the initial value to display + */ + public JIntegerField(int value) { + this(value, true); + } + + /** + * Creates a new text field with the given initial value. + * + * @param value the initial value to display + * @param allowNegative true if this field should allow negative values to + * be entered; false if only positive values are allowed + */ + public JIntegerField(int value, boolean allowNegative) { + this.document = new IntegerDocument(allowNegative); + setDocument(document); + setValue(value); + + document.addDocumentListener(new DocumentListener() { + + public void insertUpdate(DocumentEvent e) { + if (fireEvents) { + ValueChangedEvent<Integer> ev = new ValueChangedEvent<Integer>( + JIntegerField.this, Integer.valueOf(document.getValue())); + + fireValueChangedEvent( ev ); + } + } + + public void removeUpdate(DocumentEvent e) { + if (fireEvents) { + ValueChangedEvent<Integer> ev = new ValueChangedEvent<Integer>( + JIntegerField.this, Integer.valueOf(document.getValue())); + + fireValueChangedEvent( ev ); + } + } + + public void changedUpdate(DocumentEvent e) { + } + }); + } + + /** + * Get the current value of this control. + * + * @return the current value + */ + public int getValue() { + return document.getValue(); + } + + /** + * Set the integer value of this control. A {@code ValueChangedEvent} will be + * published to all {@code ValueChangedListeners}. + * + * @param value the value to set + * + * @throws IllegalArgumentException if {@code value} is negative but the field + * only allows positive values + */ + public void setValue(int value) { + setValue(value, true); + } + + /** + * Set the integer value of this control, optionally skipping notification of + * the change to listeners. + * <p> + * This version is useful when two or more controls are synchronized (ie. changes + * to the value of one control results in changes to the values of other controls). + * In such a setting, firing change events can result in an endless cycle or a + * mutex violation. + * + * @param value the value to set + * @param publishEvent true to notify listeners of this change; false to skip + * notification + * + * @throws IllegalArgumentException if {@code value} is negative but the field + * only allows positive values + */ + public void setValue(int value, boolean publishEvent) { + fireEvents = publishEvent; + + if (!document.getAllowsNegative() && value < 0) { + throw new IllegalArgumentException( + String.format("Negative value (%d) but text field set to only allow positive values", value)); + } + setText(String.valueOf(value)); + fireEvents = true; + } + +} Copied: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/JValueField.java (from rev 34283, trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/JValueField.java) =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/JValueField.java (rev 0) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/JValueField.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -0,0 +1,66 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.geotools.swing.control; + +import java.util.HashSet; +import java.util.Set; +import javax.swing.JTextField; + +/** + * Abstract base class for text field controls that work with a simple + * value such as {@code JIntegerField}. Provides methods to add and + * remove listeners for value changes offering a simpler API than + * messing about with Swing {@code KeyListener} and {@code DocumentListener} + * classes. + * + * @author Michael Bedward + * @since 2.6.1 + * @source $URL$ + * @version $Id$ + */ +public abstract class JValueField extends JTextField { + + private final Set<ValueChangedListener> listeners; + + /** + * Default constructor + */ + public JValueField() { + listeners = new HashSet<ValueChangedListener>(); + } + + /** + * Register a new listener. If the listener is already registered + * this method does nothing. + * + * @param listener the listener to register + */ + public void addValueChangedListener( ValueChangedListener listener ) { + listeners.add(listener); + } + + /** + * Remove the given listener. If the listener is not registered + * this method does nothing. + * + * @param listener the listener to remove + */ + public void removeValueChangedListener( ValueChangedListener listener ) { + listeners.remove(listener); + } + + /** + * Notify listeners of a value change + * + * @param ev the event with details of the value change + */ + protected void fireValueChangedEvent( ValueChangedEvent ev ) { + for (ValueChangedListener listener : listeners) { + listener.onValueChanged(ev); + } + } + +} Copied: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/ValueChangedEvent.java (from rev 34283, trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/ValueChangedEvent.java) =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/ValueChangedEvent.java (rev 0) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/ValueChangedEvent.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -0,0 +1,66 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +package org.geotools.swing.control; + +import java.awt.Component; + +/** + * An event published when the value of a control derived from {@code JValueField} + * changes. + * + * @see JValueField + * @see ValueChangedListener + * + * @author Michael Bedward + * @since 2.6.1 + * @source $URL$ + * @version $Id$ + */ +public class ValueChangedEvent<T> { + + private Component source; + private T newValue; + + /** + * Create a value changed event + * @param source the control holding the value + * @param newValue the updated value + */ + public ValueChangedEvent(Component source, T newValue) { + this.newValue = newValue; + this.source = source; + } + + /** + * Get the control that invoked this event + * + * @return the invoking control + */ + public Component getSource() { + return source; + } + + /** + * Get the updated value + * + * @return the updated value + */ + public T getValue() { + return newValue; + } +} Copied: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/ValueChangedListener.java (from rev 34283, trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/ValueChangedListener.java) =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/ValueChangedListener.java (rev 0) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/ValueChangedListener.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -0,0 +1,40 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +package org.geotools.swing.control; + +/** + * A listener to work with controls derived from {@code JValueTextField}. + * + * @see JValueField + * @see ValueChangedEvent + * + * @author Michael Bedward + * @since 2.6.1 + * @source $URL$ + * @version $Id$ + */ +public interface ValueChangedListener { + + /** + * Called by the control whose value has just changed + * + * @param ev the event + */ + public void onValueChanged( ValueChangedEvent ev ); + +} Copied: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/package-info.java (from rev 34283, trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/package-info.java) =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/package-info.java (rev 0) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/control/package-info.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -0,0 +1,22 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2009, Open Source Geospatial Foundation (OSGeo) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +/** + * A small collection of Swing controls including type-specific text fields and a list + * class with drag and drop item re-ordering. + */ +package org.geotools.swing.control; Deleted: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/DnDList.java =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/DnDList.java 2009-10-30 11:10:24 UTC (rev 34288) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/DnDList.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -1,300 +0,0 @@ -/* - * GeoTools - The Open Source Java GIS Toolkit - * http://geotools.org - * - * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ - -package org.geotools.swing.controls; - -import java.awt.datatransfer.Transferable; -import java.awt.dnd.DnDConstants; -import java.awt.dnd.DragGestureEvent; -import java.awt.dnd.DragGestureListener; -import java.awt.dnd.DragSource; -import java.awt.dnd.DragSourceDragEvent; -import java.awt.dnd.DragSourceDropEvent; -import java.awt.dnd.DragSourceEvent; -import java.awt.dnd.DragSourceListener; -import java.awt.dnd.DropTarget; -import java.awt.dnd.DropTargetDragEvent; -import java.awt.dnd.DropTargetDropEvent; -import java.awt.dnd.DropTargetEvent; -import java.awt.dnd.DropTargetListener; -import java.util.List; -import java.util.ResourceBundle; - -import javax.swing.JList; - -/** - * A sub-class of JList that supports drag and drop to reorder items within a single list - * and to copy or move items between lists. It is used by the - * {@linkplain org.geotools.swing.MapLayerTable} widget but has been written - * in a general fashion so that it may be used for other pusposes. - * - * @see DnDListModel - * - * @author Michael Bedward - * @since 2.6 - * @source $URL$ - * @version $Id$ - */ -public class DnDList<T> extends JList implements DragGestureListener, DragSourceListener, DropTargetListener { - private static final long serialVersionUID = 3310751294076288683L; - - private static final ResourceBundle stringRes = ResourceBundle.getBundle("org/geotools/swing/Text"); - - private DragSource src; - - @SuppressWarnings("unused") - private DropTarget tgt; // this is not used? what is it for - - private boolean movingItems; - private int overIndex; - private int[] dragIndices; - - /** - * Default constructor. An DnDListModel object will be created - * for the list. - */ - public DnDList() { - this(new DnDListModel<T>()); - } - - /** - * Constructor allowing the list model to be specified - * @param model an instance of DnDListModel - * @throws IllegalArgumentException if model is null - */ - public DnDList(DnDListModel<T> model) { - super( model ); - if (model == null) { - throw new IllegalArgumentException(stringRes.getString("arg_null_error")); - } - //this.setModel(model); - - src = new DragSource(); - src.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_MOVE, this); - - tgt = new DropTarget(this, this); - - setDragEnabled(true); - movingItems = false; - overIndex = -1; - } - - @SuppressWarnings("unchecked") - @Override - public DnDListModel<T> getModel() { - return (DnDListModel<T>) super.getModel(); - } - /** - * Called by the system when a drag gesture starts - */ - public void dragGestureRecognized(DragGestureEvent dge) { - dragIndices = getSelectedIndices(); - if (dragIndices.length > 0) { - List<T> items = getModel().getElementsAt(dragIndices); - Transferable stuff = new DnDListItemsTransferable<T>(items); - movingItems = true; - src.startDrag(dge, DragSource.DefaultMoveDrop, stuff, this); - } - } - - - /** - * DragSourceListener method - presently ignored - * <p> - * Description copied from interface:<br> - * Called as the cursor's hotspot enters a platform-dependent drop site. - * This method is invoked when all the following conditions are true: - * <ul> - * <li> The cursor's hotspot enters the operable part of a platform- dependent drop site. - * <li> The drop site is active. - * <li> The drop site accepts the drag. - * </ul> - */ - public void dragEnter(DragSourceDragEvent dsde) { - // do nothing - } - - /** - * DragSourceListener method - presently ignored - * <p> - * Description copied from interface:<br> - * Called as the cursor's hotspot moves over a platform-dependent drop site. - * This method is invoked when all the following conditions are true: - * <ul> - * <li> The cursor's hotspot has moved, but still intersects the operable part - * of the drop site associated with the previous dragEnter() invocation. - * <li> The drop site is still active. - * <li> The drop site accepts the drag. - * </ul> - */ - public void dragOver(DragSourceDragEvent dsde) { - // do nothing - } - - /** - * DragSourceListener method - presently ignored - * <p> - * Description copied from interface:<br> - * Called when the user has modified the drop gesture. This method is invoked when - * the state of the input device(s) that the user is interacting with changes. - * Such devices are typically the mouse buttons or keyboard modifiers that the - * user is interacting with. - */ - public void dropActionChanged(DragSourceDragEvent dsde) { - // do nothing - } - - /** - * DragSourceListener method - presently ignored - * <p> - * Description copied from interface:<br> - * Called as the cursor's hotspot exits a platform-dependent drop site. - * This method is invoked when <b>any</b> of the following conditions are true: - * <ul> - * <li> The cursor's hotspot no longer intersects the operable part of the - * drop site associated with the previous dragEnter() invocation. - * <li> The drop site associated with the previous dragEnter() invocation is - * no longer active. - * <li> The drop site associated with the previous dragEnter() invocation - * has rejected the drag. - * </ul> - */ - public void dragExit(DragSourceEvent dse) { - // do nothing - } - - /** - * Description copied from interface:<br> - * This method is invoked to signify that the Drag and Drop operation is - * complete. The getDropSuccess() method of the DragSourceDropEvent can be - * used to determine the termination state. The getDropAction() method returns - * the operation that the drop site selected to apply to the Drop operation. - * Once this method is complete, the current DragSourceContext and associated - * resources become invalid. - */ - public void dragDropEnd(DragSourceDropEvent dsde) { - movingItems = false; - overIndex = -1; - } - - /** - * Records the index of the list item (if any) pointed to by the mouse cursor - * <p> - * Description copied from interface:<br> - * Called while a drag operation is ongoing, when the mouse pointer enters - * the operable part of the drop site for the DropTarget registered with - * this listener. - */ - public void dragEnter(DropTargetDragEvent dtde) { - overIndex = this.locationToIndex(dtde.getLocation()); - setSelectedIndex(overIndex); - } - - - /** - * Records the index of the list item (if any) pointed to by the mouse cursor - * <p> - * Description copied from interface:<br> - * Called when a drag operation is ongoing, while the mouse pointer is still - * over the operable part of the drop site for the DropTarget registered with - * this listener. - */ - public void dragOver(DropTargetDragEvent dtde) { - int index = this.locationToIndex(dtde.getLocation()); - if (index >= 0 && index != overIndex) { - overIndex = index; - setSelectedIndex(overIndex); - } - } - - /** - * DropTargetListener method - presently ignored - * <p> - * Description copied from interface:<br> - * Called if the user has modified the current drop gesture. - */ - public void dropActionChanged(DropTargetDragEvent dtde) { - // do nothing - } - - /** - * Description copied from interface:<br> - * Called while a drag operation is ongoing, when the mouse pointer has exited - * the operable part of the drop site for the DropTarget registered with this - * listener. - */ - public void dragExit(DropTargetEvent dte) { - overIndex = -1; - } - - /** - * Handles the moving (for drag and drop actions within this list) or transfer - * (for actions between lists) of list items. - * Description copied from interface:<br> - * Called when the drag operation has terminated with a drop on the operable part - * of the drop site for the DropTarget registered with this listener. - * <p> - * This method is responsible for undertaking the transfer of the data associated - * with the gesture. The DropTargetDropEvent provides a means to obtain a Transferable - * object that represents the data object(s) to be transfered. - * <p> - * From this method, the DropTargetListener shall accept or reject the drop via - * the acceptDrop(int dropAction) or rejectDrop() methods of the DropTargetDropEvent - * parameter. - * <p> - * Subsequent to acceptDrop(), but not before, DropTargetDropEvent's getTransferable() - * method may be invoked, and data transfer may be performed via the returned - * Transferable's getTransferData() method. - * <p> - * At the completion of a drop, an implementation of this method is required to - * signal the success/failure of the drop by passing an appropriate boolean to the - * DropTargetDropEvent's dropComplete(boolean success) method. - * <p> - * Note: The data transfer should be completed before the call to the - * DropTargetDropEvent's dropComplete(boolean success) method. After that, a call - * to the getTransferData() method of the Transferable returned by - * DropTargetDropEvent.getTransferable() is guaranteed to succeed only if the data - * transfer is local; that is, only if DropTargetDropEvent.isLocalTransfer() - * returns true. Otherwise, the behavior of the call is implementation-dependent. - */ - public void drop(DropTargetDropEvent dtde) { - //Transferable stuff = dtde.getTransferable(); - - /* - * @todo check DataFlavor of stuff - */ - dtde.acceptDrop(DnDConstants.ACTION_MOVE); - - if (movingItems) { - /* - * This is a local drag and drop to reorder items - */ - DnDListModel<T> model = getModel(); - model.moveItems(overIndex, dragIndices); - - } else { - - // @todo stuff dragged from other list - - } - - overIndex = -1; - movingItems = false; - dtde.getDropTargetContext().dropComplete(true); - } - -} Deleted: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/DnDListItemsTransferable.java =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/DnDListItemsTransferable.java 2009-10-30 11:10:24 UTC (rev 34288) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/DnDListItemsTransferable.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -1,85 +0,0 @@ -/* - * GeoTools - The Open Source Java GIS Toolkit - * http://geotools.org - * - * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ - -package org.geotools.swing.controls; - -import java.awt.datatransfer.DataFlavor; -import java.awt.datatransfer.Transferable; -import java.awt.datatransfer.UnsupportedFlavorException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -/** - * Implements the Transferable interface to carry list item data - * during drag and drop actions. This class is used by DnDList. - * Client code will not normally need to refer to it. - * - * @see DnDList - * @author Michael Bedward - * @since 2.6 - * @source $URL$ - * @version $Id$ - */ -public class DnDListItemsTransferable<T> implements Transferable { - - private List<T> items; - - /** - * Constructor - * @param stuff a Collection of list item data - */ - public DnDListItemsTransferable(Collection<T> stuff) { - super(); - items = new ArrayList<T>(); - items.addAll(stuff); - } - - /** - * Description copies from interface:<br> - * Returns an array of DataFlavor objects indicating the flavors - * the data can be provided in. The array should be ordered according - * to preference for providing the data (from most richly descriptive - * to least descriptive). - */ - public DataFlavor[] getTransferDataFlavors() { - // @todo WRITE ME ! - return null; - } - - /** - * Description copies from interface:<br> - * Returns whether or not the specified data flavor is supported for this object. - */ - public boolean isDataFlavorSupported(DataFlavor flavor) { - // @todo WRITE ME ! - return true; - } - - /** - * Returns a List of items to be transferred. - * - * @param flavor - required by the interface but ignored here - * - * @throws IOException if the data is no longer available in the requested flavor. - * @throws UnsupportedFlavorException if the requested data flavor is not supported. - */ - public List<T> getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { - return items; - } -} Deleted: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/DnDListModel.java =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/DnDListModel.java 2009-10-30 11:10:24 UTC (rev 34288) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/DnDListModel.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -1,296 +0,0 @@ -/* - * GeoTools - The Open Source Java GIS Toolkit - * http://geotools.org - * - * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ -package org.geotools.swing.controls; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.ListIterator; - -import javax.swing.AbstractListModel; - -/** - * A generic ListModel class to support {@linkplain DnDList}. - * <p> - * The DnDListModel acts as a wrapper around an internal list of - * items; providing notification as the items are changed. - * </p> - * @author Michael Bedward - * @since 2.6 - * @source $URL$ - * @version $Id$ - */ -public class DnDListModel<T> extends AbstractListModel { - private static final long serialVersionUID = -6110074993686576005L; - List<T> items; - private boolean notify; - - /** - * Default constructor - */ - public DnDListModel() { - items = new ArrayList<T>(); - notify = true; - } - - public void setNofifyListeners(boolean notify) { - this.notify = notify; - } - - public boolean getNotifyListeners() { - return notify; - } - - public int getSize() { - return items.size(); - } - - /** - * Get the list item at the specified index. - * <p> - * Note: this method returns a live reference. - * - * @throws IndexOutOfBoundsException if index is invalid - */ - public T getElementAt(int index) { - return items.get(index); - } - - /** - * Returns a list of the items at the specified indices. - * <p> - * Note: The returned List contains live references. - * - * @throws IndexOutOfBoundsException if any of the indices are invalid - */ - public List<T> getElementsAt(int[] indices) { - List<T> refs = new ArrayList<T>(); - for (int k = 0; k < indices.length; k++) { - refs.add(items.get(indices[k])); - } - - return refs; - } - - /** - * Returns a list of the items at the indices specified in the Collection. - * <p> - * Note: The returned List contains live references. - * - * @throws IndexOutOfBoundsException if any of the indices are invalid - */ - public List<T> getElementsAt(Collection<Integer> indices) { - List<T> refs = new ArrayList<T>(); - for (Integer index : indices) { - refs.add(items.get(index)); - } - - return refs; - } - - /** - * Append a new item to the end of the list of current items - */ - public void addItem(T newItem) { - int index = items.size(); - items.add(newItem); - - if (notify) { - fireIntervalAdded(this, index, index); - } - } - - /** - * Add new items to the end of the list of current items - */ - public void addItems(T[] newItems) { - if (newItems.length > 0) { - int index0 = items.size(); - - for (T item : newItems) { - items.add(item); - } - - if (notify) { - fireIntervalAdded(this, index0, index0 + newItems.length - 1); - } - } - } - - /** - * Add new items to the end of the list of current items - */ - public void addItems(Collection<T> newItems) { - if (!newItems.isEmpty()) { - int index0 = items.size(); - - for (T item : newItems) { - items.add(item); - } - - if (notify) { - fireIntervalAdded(this, index0, index0 + newItems.size() - 1); - } - } - } - - /** - * Insert an item into the list at the specified position. - * @param destIndex the position of the new item: if < 0 the item will - * be inserted at the start of the list; if >= the current list size - * the item will be appended to the end of the list - */ - public void insertItem(int destIndex, T newItem) { - if (destIndex < 0) { - destIndex = 0; - } else if (destIndex >= getSize()) { - addItem(newItem); - return; - } - - items.add(destIndex, newItem); - - if (notify) { - fireIntervalAdded(this, destIndex, destIndex); - } - } - - /** - * Insert new items into the list at the specified position. - * - * @param destIndex the position of the new item: if < 0 the items will - * be inserted at the start of the list; if >= the current list size - * the items will be appended to the end of the list - */ - public void insertItems(int destIndex, T[] newItems) { - insertItems(destIndex, Arrays.asList(newItems)); - } - - /** - * Insert new items into the list at the specified position. - * - * @param destIndex the position of the new item: if < 0 the items will - * be inserted at the start of the list; if >= the current list size - * the items will be appended to the end of the list - */ - public void insertItems(int destIndex, Collection<T> newItems) { - if (destIndex < 0) { - destIndex = 0; - } else if (destIndex >= getSize()) { - addItems(newItems); - return; - } - - items.addAll(destIndex, newItems); - - if (notify) { - fireIntervalAdded(this, destIndex, destIndex + newItems.size() - 1); - } - } - - /** - * Move the items currently positioned at the indices in the - * {@code srcIndices} array as block such that they are inserted - * into the list at {@code destIndex}. It is <b>assumed</b> that - * srcIndices is sorted in ascending order. - */ - public void moveItems(int destIndex, int[] srcIndices) { - if (srcIndices.length > 0) { - List<T> copies = getElementsAt(srcIndices); - - int minIndex = Math.min(destIndex, srcIndices[0]); - int maxIndex = Math.max(destIndex - 1, srcIndices[srcIndices.length - 1]); - - for (int k = srcIndices.length - 1; k >= 0; k--) { - items.remove(srcIndices[k]); - } - - notify = false; - insertItems(destIndex, copies); - this.fireContentsChanged(this, minIndex, maxIndex); - notify = true; - } - } - - /** - * Remove the item at the specified index - */ - public void removeAt(int index) { - items.remove(index); - if (notify) { - fireIntervalRemoved(this, index, index); - } - } - - /** - * Removes the first instance of the specified item if it is contained in the list - */ - public void removeItem(T item) { - ListIterator<T> iter = items.listIterator(); - int index = 0; - boolean found = false; - - while (iter.hasNext()) { - T anItem = iter.next(); - if (anItem.equals(item)) { - iter.remove(); - found = true; - break; - } - - index++; - } - - if (found && notify) { - this.fireIntervalRemoved(this, index, index); - } - } - - /** - * Remove all items from the list - */ - public void clear() { - int prevSize = items.size(); - items.clear(); - if (notify) { - this.fireIntervalRemoved(this, 0, prevSize); - } - } - - /** - * Query whether this list contains the specified item - */ - public boolean contains(T item) { - return items.contains(item); - } - - /** - * Get the (first) index of the given item in the list of items held by this model. - * - * @param item the item to search for - * @return the index or -1 if the item is not present - */ - public int indexOf(T item) { - return items.indexOf(item); - } - - @Override - public String toString() { - return "DnD:"+items; - } -} Deleted: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/IntegerDocument.java =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/IntegerDocument.java 2009-10-30 11:10:24 UTC (rev 34288) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/IntegerDocument.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -1,138 +0,0 @@ -/* - * GeoTools - The Open Source Java GIS Toolkit - * http://geotools.org - * - * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ - -package org.geotools.swing.controls; - -import javax.swing.text.AttributeSet; -import javax.swing.text.BadLocationException; -import javax.swing.text.PlainDocument; - -/** - * A document class to handle integer verification and parsing for - * {@code JIntTextField} and other classes wishing to restrict user input - * to integer values. - * - * @author Michael Bedward - * @since 2.6.1 - * @source $URL$ - * @version $Id$ - */ -class IntegerDocument extends PlainDocument { - - private int value; - private boolean allowNegative; - - /** - * Creates a new document that will allow both positive and negative values - */ - public IntegerDocument() { - this(true); - } - - /** - * Creates a new document - * - * @param allowNegative true to allow negative values; false to allow only positive values - */ - public IntegerDocument(boolean allowNegative) { - this.allowNegative = allowNegative; - } - - /** - * Get the value corresponding to the current text - * @return the current value - */ - public int getValue() { - return value; - } - - /** - * Test if this document allows negative values - * - * @return true if negative values are allowed; false if only positive values are allowed - */ - public boolean getAllowsNegative() { - return allowNegative; - } - - /** - * {@inheritDoc} - */ - @Override - public void insertString(int offset, String text, AttributeSet attributes) throws BadLocationException { - if (text != null) { - String newText; - - if (getLength() == 0) { - newText = text; - - } else { - StringBuilder sb = new StringBuilder(getText(0, getLength())); - sb.insert(offset, text); - newText = sb.toString(); - } - - if (allowNegative && offset == 0 && newText.equals("-")) { - value = 0; - } else { - value = checkInput(newText, offset); - } - super.insertString(offset, text, attributes); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void remove(int offset, int length) throws BadLocationException { - final int curLen = getLength(); - final String currentContent = getText(0, curLen); - final String newText = currentContent.substring(0, offset) + - currentContent.substring(length + offset, curLen); - - if (allowNegative && offset == 0 && newText.equals("-")) { - value = 0; - } else { - value = checkInput(newText, offset); - } - super.remove(offset, length); - } - - /** - * Check the proposed text and, if it is valid, parse it as an integer value. - * - * @param proposedText the proposed text value - * @param offset position in the document - * @return the parsed integer value - * - * @throws BadLocationException if the string did not represent a value integer - */ - public int checkInput(String proposedText, int offset) throws BadLocationException { - int newValue = 0; - - if (proposedText != null && proposedText.length() > 0) { - try { - newValue = Integer.parseInt(proposedText); - } catch (NumberFormatException ex) { - throw new BadLocationException(proposedText, offset); - } - } - - return newValue; - } -} Deleted: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/JIntegerField.java =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/JIntegerField.java 2009-10-30 11:10:24 UTC (rev 34288) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/JIntegerField.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -1,164 +0,0 @@ -/* - * GeoTools - The Open Source Java GIS Toolkit - * http://geotools.org - * - * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ - -package org.geotools.swing.controls; - -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; - -/** - * A text field control to work with integer values. It can be constrained to positive values if - * desired. It also provides an API for listening to value changes that is simpler than messing - * about with Swing {@code KeyListener} and {@code DocumentListener}. - * <p> - * Example of use: - * <pre><code> - * int initialValue = ... - * boolean allowNegatives = false; - * JIntegerField control = new JIntegerField(initialValue, allowNegatives); - * control.addValueChangedListener( new ValueChangedListener() { - * public void onValueChanged( ValueChangedEvent ev ) { - * System.out.println("The new value is " + ev.getValue()); - * } - * }); - * </code></pre> - * - * @author Michael Bedward - * @since 2.6.1 - * @source $URL$ - * @version $Id$ - */ -public class JIntegerField extends JValueField { - - private IntegerDocument document; - private boolean fireEvents; - - /** - * Creates a new text field that allows negative values and - * has an initial value of 0. - */ - public JIntegerField() { - this(0, true); - } - - /** - * Creates a new text field with an initial value of 0. - * - * @param allowNegative true if this field should allow negative values to - * be entered; false if only positive values are allowed - */ - public JIntegerField(boolean allowsNegative) { - this(0, allowsNegative); - } - - /** - * Creates a new text field that allows negative values and - * the given initial value. - * - * @param value the initial value to display - */ - public JIntegerField(int value) { - this(value, true); - } - - /** - * Creates a new text field with the given initial value. - * - * @param value the initial value to display - * @param allowNegative true if this field should allow negative values to - * be entered; false if only positive values are allowed - */ - public JIntegerField(int value, boolean allowNegative) { - this.document = new IntegerDocument(allowNegative); - setDocument(document); - setValue(value); - - document.addDocumentListener(new DocumentListener() { - - public void insertUpdate(DocumentEvent e) { - if (fireEvents) { - ValueChangedEvent<Integer> ev = new ValueChangedEvent<Integer>( - JIntegerField.this, Integer.valueOf(document.getValue())); - - fireValueChangedEvent( ev ); - } - } - - public void removeUpdate(DocumentEvent e) { - if (fireEvents) { - ValueChangedEvent<Integer> ev = new ValueChangedEvent<Integer>( - JIntegerField.this, Integer.valueOf(document.getValue())); - - fireValueChangedEvent( ev ); - } - } - - public void changedUpdate(DocumentEvent e) { - } - }); - } - - /** - * Get the current value of this control. - * - * @return the current value - */ - public int getValue() { - return document.getValue(); - } - - /** - * Set the integer value of this control. A {@code ValueChangedEvent} will be - * published to all {@code ValueChangedListeners}. - * - * @param value the value to set - * - * @throws IllegalArgumentException if {@code value} is negative but the field - * only allows positive values - */ - public void setValue(int value) { - setValue(value, true); - } - - /** - * Set the integer value of this control, optionally skipping notification of - * the change to listeners. - * <p> - * This version is useful when two or more controls are synchronized (ie. changes - * to the value of one control results in changes to the values of other controls). - * In such a setting, firing change events can result in an endless cycle or a - * mutex violation. - * - * @param value the value to set - * @param publishEvent true to notify listeners of this change; false to skip - * notification - * - * @throws IllegalArgumentException if {@code value} is negative but the field - * only allows positive values - */ - public void setValue(int value, boolean publishEvent) { - fireEvents = publishEvent; - - if (!document.getAllowsNegative() && value < 0) { - throw new IllegalArgumentException( - String.format("Negative value (%d) but text field set to only allow positive values", value)); - } - setText(String.valueOf(value)); - fireEvents = true; - } - -} Deleted: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/JValueField.java =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/JValueField.java 2009-10-30 11:10:24 UTC (rev 34288) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/JValueField.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -1,66 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ - -package org.geotools.swing.controls; - -import java.util.HashSet; -import java.util.Set; -import javax.swing.JTextField; - -/** - * Abstract base class for text field controls that work with a simple - * value such as {@code JIntegerField}. Provides methods to add and - * remove listeners for value changes offering a simpler API than - * messing about with Swing {@code KeyListener} and {@code DocumentListener} - * classes. - * - * @author Michael Bedward - * @since 2.6.1 - * @source $URL$ - * @version $Id$ - */ -public abstract class JValueField extends JTextField { - - private final Set<ValueChangedListener> listeners; - - /** - * Default constructor - */ - public JValueField() { - listeners = new HashSet<ValueChangedListener>(); - } - - /** - * Register a new listener. If the listener is already registered - * this method does nothing. - * - * @param listener the listener to register - */ - public void addValueChangedListener( ValueChangedListener listener ) { - listeners.add(listener); - } - - /** - * Remove the given listener. If the listener is not registered - * this method does nothing. - * - * @param listener the listener to remove - */ - public void removeValueChangedListener( ValueChangedListener listener ) { - listeners.remove(listener); - } - - /** - * Notify listeners of a value change - * - * @param ev the event with details of the value change - */ - protected void fireValueChangedEvent( ValueChangedEvent ev ) { - for (ValueChangedListener listener : listeners) { - listener.onValueChanged(ev); - } - } - -} Deleted: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/ValueChangedEvent.java =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/ValueChangedEvent.java 2009-10-30 11:10:24 UTC (rev 34288) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/ValueChangedEvent.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -1,66 +0,0 @@ -/* - * GeoTools - The Open Source Java GIS Toolkit - * http://geotools.org - * - * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ - -package org.geotools.swing.controls; - -import java.awt.Component; - -/** - * An event published when the value of a control derived from {@code JValueField} - * changes. - * - * @see JValueField - * @see ValueChangedListener - * - * @author Michael Bedward - * @since 2.6.1 - * @source $URL$ - * @version $Id$ - */ -public class ValueChangedEvent<T> { - - private Component source; - private T newValue; - - /** - * Create a value changed event - * @param source the control holding the value - * @param newValue the updated value - */ - public ValueChangedEvent(Component source, T newValue) { - this.newValue = newValue; - this.source = source; - } - - /** - * Get the control that invoked this event - * - * @return the invoking control - */ - public Component getSource() { - return source; - } - - /** - * Get the updated value - * - * @return the updated value - */ - public T getValue() { - return newValue; - } -} Deleted: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/ValueChangedListener.java =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/ValueChangedListener.java 2009-10-30 11:10:24 UTC (rev 34288) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/ValueChangedListener.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -1,40 +0,0 @@ -/* - * GeoTools - The Open Source Java GIS Toolkit - * http://geotools.org - * - * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ - -package org.geotools.swing.controls; - -/** - * A listener to work with controls derived from {@code JValueTextField}. - * - * @see JValueField - * @see ValueChangedEvent - * - * @author Michael Bedward - * @since 2.6.1 - * @source $URL$ - * @version $Id$ - */ -public interface ValueChangedListener { - - /** - * Called by the control whose value has just changed - * - * @param ev the event - */ - public void onValueChanged( ValueChangedEvent ev ); - -} Deleted: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/package-info.java =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/package-info.java 2009-10-30 11:10:24 UTC (rev 34288) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/controls/package-info.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -1,22 +0,0 @@ -/* - * GeoTools - The Open Source Java GIS Toolkit - * http://geotools.org - * - * (C) 2009, Open Source Geospatial Foundation (OSGeo) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ - -/** - * A small collection of Swing controls including type-specific text fields and a list - * class with drag and drop item re-ordering. - */ -package org.geotools.swing.controls; Copied: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialog/JFileImageChooser.java (from rev 34283, trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialogs/JFileImageChooser.java) =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialog/JFileImageChooser.java (rev 0) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialog/JFileImageChooser.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -0,0 +1,299 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +package org.geotools.swing.dialog; + +import java.awt.Component; +import java.io.File; +import java.util.Set; +import java.util.TreeSet; +import javax.imageio.ImageIO; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.filechooser.FileFilter; + +/** + * A file chooser dialog for common raster image format files. + * It provides static methods to display the dialog for opening or + * saving an image file with basic validation of user input. + * + * <pre><code> + * // Prompting for an input image file + * File file = JFileImageChooser.showOpenFile(null); + * if (file != null) { + * ... + * } + * + * // Prompting for a file name to save an image + * File file = JFileImageChooser.showSaveFile(null); + * if (file != null) { + * ... + * } + * </code></pre> + * + * The file formats offered by the dialog are a subset of those supported by + * {@code ImageIO} on the host system. + * <p> + * + * @see JFileDataStoreChooser + * @see JParameterListWizard + * @see ImageIO + * + * @author Michael Bedward + * @since 2.6.1 + * @source $URL$ + * @version $Id$ + */ +public class JFileImageChooser extends JFileChooser { + + private static enum FormatSpecifier { + BMP("bmp", "BMP image", ".bmp"), + GIF("gif", "GIF image", ".gif"), + JPG("jpg", "JPEG image", ".jpg", ".jpeg"), + PNG("png", "PNG image", "png"), + TIF("tif", "TIFF image", ".tif", ".tiff"); + + private String id; + private String desc; + private String[] suffixes; + + private FormatSpecifier(String id, String desc, String ...suffixes) { + this.id = id; + this.desc = desc; + this.suffixes = new String[suffixes.length]; + for (int i = 0; i < suffixes.length; i++) { + this.suffixes[i] = suffixes[i]; + } + } + }; + + private static final Set<FormatSpecifier> supportedReaders = new TreeSet<FormatSpecifier>(); + private static final Set<FormatSpecifier> supportedWriters = new TreeSet<FormatSpecifier>(); + static { + for (FormatSpecifier format : FormatSpecifier.values()) { + if (ImageIO.getImageReadersBySuffix(format.id).hasNext()) { + supportedReaders.add(format); + } + + if (ImageIO.getImageWritersBySuffix(format.id).hasNext()) { + supportedWriters.add(format); + } + } + } + + private static class FormatFilter extends FileFilter { + private FormatSpecifier format; + + FormatFilter(FormatSpecifier format) { + this.format = format; + } + + @Override + public boolean accept(File f) { + if (f.isDirectory()) { + return true; + } + + for (String suffix : format.suffixes) { + if (f.getPath().endsWith(suffix) || + f.getPath().endsWith(suffix.toUpperCase())) { + return true; + } + } + + return false; + } + + @Override + public String getDescription() { + return format.desc; + } + + public String getDefaultSuffix() { + return format.suffixes[0]; + } + } + + /* + * Create a new image file chooser + */ + public JFileImageChooser() { + this(null); + } + + /** + * Create a new image file chooser + * + * @param workingDir the initial directory to display + */ + public JFileImageChooser(File workingDir) { + super(workingDir); + } + + + /** + * Overridden method to validate the dialog content prior to closing. + */ + @Override + public void approveSelection() { + FormatFilter filter = (FormatFilter) getFileFilter(); + File file = getSelectedFile(); + String name = file.getAbsolutePath(); + int dot = name.lastIndexOf('.'); + + boolean ok = true; + + if (dot < 0) { + /* + * No file extension. Set the default one + */ + name = name + filter.getDefaultSuffix(); + file = new File(name); + setSelectedFile(file); + } + + if (this.getDialogType() == JFileImageChooser.SAVE_DIALOG) { + if (!filter.accept(getSelectedFile())) { + StringBuilder sb = new StringBuilder(); + sb.append("'"); + sb.append(name.substring(dot + 1)); + sb.append("' "); + sb.append("is not a standard suffix for a "); + sb.append(filter.getDescription()); + sb.append("."); + sb.append("\nDo you want to save with this name ?"); + + int answer = JOptionPane.showConfirmDialog( + getParent(), sb.toString(), "Incompatible file suffix", + JOptionPane.YES_NO_OPTION); + + ok = answer == JOptionPane.YES_OPTION; + } + + if (ok && file.exists()) { + int answer = JOptionPane.showConfirmDialog( + this, + "Overwrite the existing file ?", + "File exists", + JOptionPane.YES_NO_OPTION); + + ok = answer == JOptionPane.YES_OPTION; + } + + } else { + if (!file.exists()) { + JOptionPane.showMessageDialog( + this, "Can't file this file", "File not found", JOptionPane.WARNING_MESSAGE); + ok = false; + } + } + + if (ok) { + super.approveSelection(); + } + } + + /** + * Set the file filters. This is a helper for the static showXXXXFile methods. + * + * @param supportedFormats the set of file formats that will be offered + */ + private void setFilter(Set<FormatSpecifier> supportedFormats) { + this.setAcceptAllFileFilterUsed(false); + for (final FormatSpecifier format : supportedFormats) { + addChoosableFileFilter(new FormatFilter(format)); + } + } + + + /** + * Display a dialog to choose a file name to save an image to + * + * @param parent parent component (may be {@code null}) + * + * @return the selected file or {@code null} if the dialog was cancelled + */ + public static File showSaveFile(Component parent) { + return showSaveFile(parent, null); + } + + + /** + * Display a dialog to choose a file name to save an image to + * + * @param parent parent component (may be {@code null}) + * @param workingDir the initial directory to display + * + * @return the selected file or {@code null} if the dialog was cancelled + */ + public static File showSaveFile(Component parent, File workingDir) { + JFileImageChooser chooser = new JFileImageChooser(workingDir); + chooser.setFilter(supportedWriters); + chooser.setDialogTitle("Save image"); + + File file = null; + + if (chooser.showSaveDialog(parent) == JFileImageChooser.APPROVE_OPTION) { + file = chooser.getSelectedFile(); + + String name = file.getAbsolutePath(); + int dot = name.lastIndexOf('.'); + + FormatFilter filter = (FormatFilter) chooser.getFileFilter(); + if (dot < 0) { + name = name + filter.getDefaultSuffix(); + file = new File(name); + } + } + + return file; + } + + /** + * Display a dialog to choose an image file to open + * + * @param parent parent component (may be {@code null}) + * @param workingDir the initial directory to display + * + * @return the selected file or {@code null} if the dialog was cancelled + */ + public static File showOpenFile(Component parent) { + return showOpenFile(parent, null); + } + + /** + * Display a dialog to choose an image file to open + * + * @param parent parent component (may be {@code null}) + * @param workingDir the initial directory to display + * + * @return the selected file or {@code null} if the dialog was cancelled + */ + public static File showOpenFile(Component parent, File workingDir) { + JFileImageChooser chooser = new JFileImageChooser(workingDir); + chooser.setFilter(supportedReaders); + chooser.setDialogTitle("Open image file"); + + File file = null; + + if (chooser.showOpenDialog(parent) == JFileImageChooser.APPROVE_OPTION) { + file = chooser.getSelectedFile(); + } + + return file; + } +} Copied: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialog/JMapImageDialog.java (from rev 34283, trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialogs/JMapImageDialog.java) =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialog/JMapImageDialog.java (rev 0) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialog/JMapImageDialog.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -0,0 +1,369 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +package org.geotools.swing.dialog; + +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import javax.swing.ButtonGroup; +import javax.swing.DefaultComboBoxModel; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import net.miginfocom.swing.MigLayout; +import org.geotools.geometry.jts.ReferencedEnvelope; +import org.geotools.swing.control.JIntegerField; +import org.geotools.swing.control.ValueChangedEvent; +import org.geotools.swing.control.ValueChangedListener; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.cs.AxisDirection; +import org.opengis.referencing.cs.CoordinateSystem; + +/** + * A dialog to prompt for the size of an image into which a map + * will be drawn and the name and format of the file to save this + * image to. It allows the image size to be set indirectly, + * by setting the map pixel scale, or directly. + * + * @todo Add ability to work with DPI setting + * + * @author Michael Bedward + * @since 2.6.1 + * @source $URL$ + * @version $Id$ + */ + +public class JMapImageDialog extends JDialog { + + public static final int DEFAULT_IMAGE_WIDTH = 1000; + + private static final int WIDTH_FIELD = 0; + private static final int HEIGHT_FIELD = 1; + + private JTextField fileField; + private JComboBox scaleCombo; + private JIntegerField widthField; + private JIntegerField heightField; + + private boolean completed; + private Rectangle imageSize; + private boolean setByScale; + private File selectedFile; + private double heightToWidth; + + private ReferencedEnvelope mapBounds; + private final int XAXIS; + private final int YAXIS; + + /** + * Creates a new dialog + * + * @param mapBounds the bounds (world coordinates) of the map area to + * draw into the image + */ + public JMapImageDialog(ReferencedEnvelope mapBounds) { + if (mapBounds == null) { + throw new IllegalArgumentException("The mapBounds argument cannot be null"); + } + + setTitle("Output image size"); + setModal(true); + setResizable(false); + + this.mapBounds = new ReferencedEnvelope(mapBounds); + CoordinateReferenceSystem crs = mapBounds.getCoordinateReferenceSystem(); + boolean swapAxes = false; + if (crs != null) { + CoordinateSystem cs = crs.getCoordinateSystem(); + if (cs != null) { + AxisDirection dir = cs.getAxis(0).getDirection().absolute(); + if (dir.equals(AxisDirection.NORTH) || dir.equals(AxisDirection.DISPLAY_UP)) { + swapAxes = true; + } + } + } + + XAXIS = swapAxes ? 1 : 0; + YAXIS = swapAxes ? 0 : 1; + + initComponents(); + initValues(); + } + + /** + * Test if the dialog was completed + * + * @return true if the dialog was completed; false otherwise + */ + public boolean isCompleted() { + return completed; + } + + /** + * Get the requested image bounds + * + * @return image bounds + */ + public Rectangle getImageSize() { + return imageSize; + } + + /** + * Get the file to save the map image to + * + * @return the selected file + */ + public File getSelectedFile() { + return selectedFile; + } + + /** + * Get the image file format as a file suffix understood + * by {@code ImageIO} + * + * @return file suffix representing the image file format + */ + public String getImageFormat() { + String format = null; + + if (selectedFile != null) { + int dot = selectedFile.getName().lastIndexOf('.'); + if (dot > 0) { + format = selectedFile.getName().substring(dot + 1); + } + } + + return format; + } + + /** + * Create and lay out the dialog components + */ + private void initComponents() { + MigLayout layout = new MigLayout( + "", + "[][]30px[][]", // col constraints + "[][][][]30px[]"); // row constraints + + JPanel panel = new JPanel(layout); + + JLabel fileLabel = new JLabel("File"); + panel.add(fileLabel, "cell 0 0"); + + fileField = new JTextField(20); + panel.add(fileField, "cell 1 0 3 1"); + + JButton browseBtn = new JButton("Browse..."); + browseBtn.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + brosweFile(); + } + }); + panel.add(browseBtn, "cell 1 0"); + + int[] baseScales = {10, 25, 50}; + int[] multipliers = {1, 10, 100, 1000, 10000, 100000}; + + Object[] scales = new Object[baseScales.length * multipliers.length]; + for (int i = 0, k=0; i < multipliers.length; i++) { + for (int j = 0; j < baseScales.length; j++, k++) { + scales[k] = new Integer(multipliers[i] * baseScales[j]); + } + } + + final JCheckBox scaleCheck = new JCheckBox("Set by pixel scale", false); + panel.add(scaleCheck, "cell 1 1"); + + JLabel scaleLabel = new JLabel("Scale 1:"); + panel.add(scaleLabel, "cell 1 2, gapbefore indent"); + + DefaultComboBoxModel scaleModel = new DefaultComboBoxModel(scales); + scaleCombo = new JComboBox(scaleModel); + scaleCombo.setEditable(true); + scaleCombo.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + onScaleChange(); + } + }); + panel.add(scaleCombo, "cell 1 2"); + + final JCheckBox sizeCheck = new JCheckBox("Set by image size", true); + panel.add(sizeCheck, "cell 2 1 2 1"); + + JLabel widthLabel = new JLabel("width"); + panel.add(widthLabel, "cell 2 2, gapbefore indent"); + + widthField = new JIntegerField(); + widthField.addValueChangedListener( new ValueChangedListener() { + public void onValueChanged(ValueChangedEvent ev) { + onImageSizeChange(WIDTH_FIELD); + } + } ); + + final int fieldWidth = widthField.getFontMetrics(widthField.getFont()).stringWidth("00000000"); + panel.add(widthField, String.format("cell 3 2, w %d!", fieldWidth)); + + JLabel heightLabel = new JLabel("height"); + panel.add(heightLabel, "cell 2 3, gapbefore indent"); + + heightField = new JIntegerField(); + heightField.addValueChangedListener( new ValueChangedListener() { + public void onValueChanged(ValueChangedEvent ev) { + onImageSizeChange(HEIGHT_FIELD); + } + } ); + panel.add(heightField, String.format("cell 3 3, w %d!", fieldWidth)); + + JButton okBtn = new JButton("OK"); + okBtn.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + completed = true; + setVisible(false); + } + }); + panel.add(okBtn, "cell 1 4 3 1"); + + JButton cancelBtn = new JButton("Cancel"); + cancelBtn.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + completed = false; + setVisible(false); + } + }); + panel.add(cancelBtn, "cell 1 4"); + + ButtonGroup grp = new ButtonGroup(); + grp.add(scaleCheck); + grp.add(sizeCheck); + + + scaleCheck.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setByScale = scaleCheck.isSelected(); + enableItems(); + } + }); + + sizeCheck.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setByScale = scaleCheck.isSelected(); + enableItems(); + } + }); + + setByScale = scaleCheck.isSelected(); + enableItems(); + + getContentPane().add(panel); + pack(); + } + + /** + * Enable dialog controls for the current dialog mode: + * setting map scale or setting image size directly. + */ + private void enableItems() { + scaleCombo.setEnabled(setByScale); + + widthField.setEnabled(!setByScale); + heightField.setEnabled(!setByScale); + } + + /** + * Set initial default values for image size + */ + private void initValues() { + heightToWidth = mapBounds.getSpan(YAXIS) / mapBounds.getSpan(XAXIS); + imageSize = new Rectangle(); + + // this will cause the height and scale controls to be updated + widthField.setValue(DEFAULT_IMAGE_WIDTH); + } + + /** + * Update controls when one of the image size fields has been edited + * + * @param controlModified constant indicating which field was edited + */ + private void onImageSizeChange(int controlModified) { + switch (controlModified) { + case WIDTH_FIELD: + imageSize.width = widthField.getValue(); + imageSize.height = (int) Math.round(imageSize.width * heightToWidth); + heightField.setValue(imageSize.height, false); + break; + + case HEIGHT_FIELD: + imageSize.height = heightField.getValue(); + imageSize.width = (int) Math.round(imageSize.height / heightToWidth); + widthField.setValue(imageSize.width, false); + break; + } + + int scaleDenominator = 0; + if (imageSize.width > 0) { + scaleDenominator = (int) Math.round(mapBounds.getSpan(XAXIS) / imageSize.width); + } + scaleCombo.getEditor().setItem(Integer.valueOf(scaleDenominator)); + } + + /** + * Update the controls when the scale has been changed + */ + private void onScaleChange() { + int scaleDenominator = ((Number) scaleCombo.getEditor().getItem()).intValue(); + if (scaleDenominator > 0) { + imageSize.width = (int) (mapBounds.getSpan(XAXIS) / scaleDenominator); + imageSize.height = (int) (mapBounds.getSpan(YAXIS) / scaleDenominator); + } else { + imageSize.width = imageSize.height = 0; + } + + widthField.setValue( imageSize.width, false ); + heightField.setValue( imageSize.height, false ); + } + + /** + * Display a {@code JFileImageChooser} to browse for the path and file + * to save the image to + */ + private void brosweFile() { + File file = JFileImageChooser.showSaveFile(this); + if (file != null) { + selectedFile = file; + fileField.setText(file.getAbsolutePath()); + } + } + + /** + * Demonstrate the dialog + * @param args ignored + */ + public static void main(String[] args) { + ReferencedEnvelope bounds = new ReferencedEnvelope(0, 10000, 0, 20000, null); + JMapImageDialog dialog = new JMapImageDialog(bounds); + dialog.setVisible(true); + dialog.dispose(); + } +} + Copied: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialog/package-info.java (from rev 34283, trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialogs/package-info.java) =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialog/package-info.java (rev 0) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialog/package-info.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -0,0 +1,22 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2009, Open Source Geospatial Foundation (OSGeo) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +/** + * General dialog classes + */ +package org.geotools.swing.dialog; + Deleted: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialogs/JFileImageChooser.java =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialogs/JFileImageChooser.java 2009-10-30 11:10:24 UTC (rev 34288) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialogs/JFileImageChooser.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -1,299 +0,0 @@ -/* - * GeoTools - The Open Source Java GIS Toolkit - * http://geotools.org - * - * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ - -package org.geotools.swing.dialogs; - -import java.awt.Component; -import java.io.File; -import java.util.Set; -import java.util.TreeSet; -import javax.imageio.ImageIO; -import javax.swing.JFileChooser; -import javax.swing.JOptionPane; -import javax.swing.filechooser.FileFilter; - -/** - * A file chooser dialog for common raster image format files. - * It provides static methods to display the dialog for opening or - * saving an image file with basic validation of user input. - * - * <pre><code> - * // Prompting for an input image file - * File file = JFileImageChooser.showOpenFile(null); - * if (file != null) { - * ... - * } - * - * // Prompting for a file name to save an image - * File file = JFileImageChooser.showSaveFile(null); - * if (file != null) { - * ... - * } - * </code></pre> - * - * The file formats offered by the dialog are a subset of those supported by - * {@code ImageIO} on the host system. - * <p> - * - * @see JFileDataStoreChooser - * @see JParameterListWizard - * @see ImageIO - * - * @author Michael Bedward - * @since 2.6.1 - * @source $URL$ - * @version $Id$ - */ -public class JFileImageChooser extends JFileChooser { - - private static enum FormatSpecifier { - BMP("bmp", "BMP image", ".bmp"), - GIF("gif", "GIF image", ".gif"), - JPG("jpg", "JPEG image", ".jpg", ".jpeg"), - PNG("png", "PNG image", "png"), - TIF("tif", "TIFF image", ".tif", ".tiff"); - - private String id; - private String desc; - private String[] suffixes; - - private FormatSpecifier(String id, String desc, String ...suffixes) { - this.id = id; - this.desc = desc; - this.suffixes = new String[suffixes.length]; - for (int i = 0; i < suffixes.length; i++) { - this.suffixes[i] = suffixes[i]; - } - } - }; - - private static final Set<FormatSpecifier> supportedReaders = new TreeSet<FormatSpecifier>(); - private static final Set<FormatSpecifier> supportedWriters = new TreeSet<FormatSpecifier>(); - static { - for (FormatSpecifier format : FormatSpecifier.values()) { - if (ImageIO.getImageReadersBySuffix(format.id).hasNext()) { - supportedReaders.add(format); - } - - if (ImageIO.getImageWritersBySuffix(format.id).hasNext()) { - supportedWriters.add(format); - } - } - } - - private static class FormatFilter extends FileFilter { - private FormatSpecifier format; - - FormatFilter(FormatSpecifier format) { - this.format = format; - } - - @Override - public boolean accept(File f) { - if (f.isDirectory()) { - return true; - } - - for (String suffix : format.suffixes) { - if (f.getPath().endsWith(suffix) || - f.getPath().endsWith(suffix.toUpperCase())) { - return true; - } - } - - return false; - } - - @Override - public String getDescription() { - return format.desc; - } - - public String getDefaultSuffix() { - return format.suffixes[0]; - } - } - - /* - * Create a new image file chooser - */ - public JFileImageChooser() { - this(null); - } - - /** - * Create a new image file chooser - * - * @param workingDir the initial directory to display - */ - public JFileImageChooser(File workingDir) { - super(workingDir); - } - - - /** - * Overridden method to validate the dialog content prior to closing. - */ - @Override - public void approveSelection() { - FormatFilter filter = (FormatFilter) getFileFilter(); - File file = getSelectedFile(); - String name = file.getAbsolutePath(); - int dot = name.lastIndexOf('.'); - - boolean ok = true; - - if (dot < 0) { - /* - * No file extension. Set the default one - */ - name = name + filter.getDefaultSuffix(); - file = new File(name); - setSelectedFile(file); - } - - if (this.getDialogType() == JFileImageChooser.SAVE_DIALOG) { - if (!filter.accept(getSelectedFile())) { - StringBuilder sb = new StringBuilder(); - sb.append("'"); - sb.append(name.substring(dot + 1)); - sb.append("' "); - sb.append("is not a standard suffix for a "); - sb.append(filter.getDescription()); - sb.append("."); - sb.append("\nDo you want to save with this name ?"); - - int answer = JOptionPane.showConfirmDialog( - getParent(), sb.toString(), "Incompatible file suffix", - JOptionPane.YES_NO_OPTION); - - ok = answer == JOptionPane.YES_OPTION; - } - - if (ok && file.exists()) { - int answer = JOptionPane.showConfirmDialog( - this, - "Overwrite the existing file ?", - "File exists", - JOptionPane.YES_NO_OPTION); - - ok = answer == JOptionPane.YES_OPTION; - } - - } else { - if (!file.exists()) { - JOptionPane.showMessageDialog( - this, "Can't file this file", "File not found", JOptionPane.WARNING_MESSAGE); - ok = false; - } - } - - if (ok) { - super.approveSelection(); - } - } - - /** - * Set the file filters. This is a helper for the static showXXXXFile methods. - * - * @param supportedFormats the set of file formats that will be offered - */ - private void setFilter(Set<FormatSpecifier> supportedFormats) { - this.setAcceptAllFileFilterUsed(false); - for (final FormatSpecifier format : supportedFormats) { - addChoosableFileFilter(new FormatFilter(format)); - } - } - - - /** - * Display a dialog to choose a file name to save an image to - * - * @param parent parent component (may be {@code null}) - * - * @return the selected file or {@code null} if the dialog was cancelled - */ - public static File showSaveFile(Component parent) { - return showSaveFile(parent, null); - } - - - /** - * Display a dialog to choose a file name to save an image to - * - * @param parent parent component (may be {@code null}) - * @param workingDir the initial directory to display - * - * @return the selected file or {@code null} if the dialog was cancelled - */ - public static File showSaveFile(Component parent, File workingDir) { - JFileImageChooser chooser = new JFileImageChooser(workingDir); - chooser.setFilter(supportedWriters); - chooser.setDialogTitle("Save image"); - - File file = null; - - if (chooser.showSaveDialog(parent) == JFileImageChooser.APPROVE_OPTION) { - file = chooser.getSelectedFile(); - - String name = file.getAbsolutePath(); - int dot = name.lastIndexOf('.'); - - FormatFilter filter = (FormatFilter) chooser.getFileFilter(); - if (dot < 0) { - name = name + filter.getDefaultSuffix(); - file = new File(name); - } - } - - return file; - } - - /** - * Display a dialog to choose an image file to open - * - * @param parent parent component (may be {@code null}) - * @param workingDir the initial directory to display - * - * @return the selected file or {@code null} if the dialog was cancelled - */ - public static File showOpenFile(Component parent) { - return showOpenFile(parent, null); - } - - /** - * Display a dialog to choose an image file to open - * - * @param parent parent component (may be {@code null}) - * @param workingDir the initial directory to display - * - * @return the selected file or {@code null} if the dialog was cancelled - */ - public static File showOpenFile(Component parent, File workingDir) { - JFileImageChooser chooser = new JFileImageChooser(workingDir); - chooser.setFilter(supportedReaders); - chooser.setDialogTitle("Open image file"); - - File file = null; - - if (chooser.showOpenDialog(parent) == JFileImageChooser.APPROVE_OPTION) { - file = chooser.getSelectedFile(); - } - - return file; - } -} Deleted: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialogs/JMapImageDialog.java =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialogs/JMapImageDialog.java 2009-10-30 11:10:24 UTC (rev 34288) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialogs/JMapImageDialog.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -1,369 +0,0 @@ -/* - * GeoTools - The Open Source Java GIS Toolkit - * http://geotools.org - * - * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ - -package org.geotools.swing.dialogs; - -import java.awt.Rectangle; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.io.File; -import javax.swing.ButtonGroup; -import javax.swing.DefaultComboBoxModel; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JComboBox; -import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; -import net.miginfocom.swing.MigLayout; -import org.geotools.geometry.jts.ReferencedEnvelope; -import org.geotools.swing.controls.JIntegerField; -import org.geotools.swing.controls.ValueChangedEvent; -import org.geotools.swing.controls.ValueChangedListener; -import org.opengis.referencing.crs.CoordinateReferenceSystem; -import org.opengis.referencing.cs.AxisDirection; -import org.opengis.referencing.cs.CoordinateSystem; - -/** - * A dialog to prompt for the size of an image into which a map - * will be drawn and the name and format of the file to save this - * image to. It allows the image size to be set indirectly, - * by setting the map pixel scale, or directly. - * - * @todo Add ability to work with DPI setting - * - * @author Michael Bedward - * @since 2.6.1 - * @source $URL$ - * @version $Id$ - */ - -public class JMapImageDialog extends JDialog { - - public static final int DEFAULT_IMAGE_WIDTH = 1000; - - private static final int WIDTH_FIELD = 0; - private static final int HEIGHT_FIELD = 1; - - private JTextField fileField; - private JComboBox scaleCombo; - private JIntegerField widthField; - private JIntegerField heightField; - - private boolean completed; - private Rectangle imageSize; - private boolean setByScale; - private File selectedFile; - private double heightToWidth; - - private ReferencedEnvelope mapBounds; - private final int XAXIS; - private final int YAXIS; - - /** - * Creates a new dialog - * - * @param mapBounds the bounds (world coordinates) of the map area to - * draw into the image - */ - public JMapImageDialog(ReferencedEnvelope mapBounds) { - if (mapBounds == null) { - throw new IllegalArgumentException("The mapBounds argument cannot be null"); - } - - setTitle("Output image size"); - setModal(true); - setResizable(false); - - this.mapBounds = new ReferencedEnvelope(mapBounds); - CoordinateReferenceSystem crs = mapBounds.getCoordinateReferenceSystem(); - boolean swapAxes = false; - if (crs != null) { - CoordinateSystem cs = crs.getCoordinateSystem(); - if (cs != null) { - AxisDirection dir = cs.getAxis(0).getDirection().absolute(); - if (dir.equals(AxisDirection.NORTH) || dir.equals(AxisDirection.DISPLAY_UP)) { - swapAxes = true; - } - } - } - - XAXIS = swapAxes ? 1 : 0; - YAXIS = swapAxes ? 0 : 1; - - initComponents(); - initValues(); - } - - /** - * Test if the dialog was completed - * - * @return true if the dialog was completed; false otherwise - */ - public boolean isCompleted() { - return completed; - } - - /** - * Get the requested image bounds - * - * @return image bounds - */ - public Rectangle getImageSize() { - return imageSize; - } - - /** - * Get the file to save the map image to - * - * @return the selected file - */ - public File getSelectedFile() { - return selectedFile; - } - - /** - * Get the image file format as a file suffix understood - * by {@code ImageIO} - * - * @return file suffix representing the image file format - */ - public String getImageFormat() { - String format = null; - - if (selectedFile != null) { - int dot = selectedFile.getName().lastIndexOf('.'); - if (dot > 0) { - format = selectedFile.getName().substring(dot + 1); - } - } - - return format; - } - - /** - * Create and lay out the dialog components - */ - private void initComponents() { - MigLayout layout = new MigLayout( - "", - "[][]30px[][]", // col constraints - "[][][][]30px[]"); // row constraints - - JPanel panel = new JPanel(layout); - - JLabel fileLabel = new JLabel("File"); - panel.add(fileLabel, "cell 0 0"); - - fileField = new JTextField(20); - panel.add(fileField, "cell 1 0 3 1"); - - JButton browseBtn = new JButton("Browse..."); - browseBtn.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - brosweFile(); - } - }); - panel.add(browseBtn, "cell 1 0"); - - int[] baseScales = {10, 25, 50}; - int[] multipliers = {1, 10, 100, 1000, 10000, 100000}; - - Object[] scales = new Object[baseScales.length * multipliers.length]; - for (int i = 0, k=0; i < multipliers.length; i++) { - for (int j = 0; j < baseScales.length; j++, k++) { - scales[k] = new Integer(multipliers[i] * baseScales[j]); - } - } - - final JCheckBox scaleCheck = new JCheckBox("Set by pixel scale", false); - panel.add(scaleCheck, "cell 1 1"); - - JLabel scaleLabel = new JLabel("Scale 1:"); - panel.add(scaleLabel, "cell 1 2, gapbefore indent"); - - DefaultComboBoxModel scaleModel = new DefaultComboBoxModel(scales); - scaleCombo = new JComboBox(scaleModel); - scaleCombo.setEditable(true); - scaleCombo.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - onScaleChange(); - } - }); - panel.add(scaleCombo, "cell 1 2"); - - final JCheckBox sizeCheck = new JCheckBox("Set by image size", true); - panel.add(sizeCheck, "cell 2 1 2 1"); - - JLabel widthLabel = new JLabel("width"); - panel.add(widthLabel, "cell 2 2, gapbefore indent"); - - widthField = new JIntegerField(); - widthField.addValueChangedListener( new ValueChangedListener() { - public void onValueChanged(ValueChangedEvent ev) { - onImageSizeChange(WIDTH_FIELD); - } - } ); - - final int fieldWidth = widthField.getFontMetrics(widthField.getFont()).stringWidth("00000000"); - panel.add(widthField, String.format("cell 3 2, w %d!", fieldWidth)); - - JLabel heightLabel = new JLabel("height"); - panel.add(heightLabel, "cell 2 3, gapbefore indent"); - - heightField = new JIntegerField(); - heightField.addValueChangedListener( new ValueChangedListener() { - public void onValueChanged(ValueChangedEvent ev) { - onImageSizeChange(HEIGHT_FIELD); - } - } ); - panel.add(heightField, String.format("cell 3 3, w %d!", fieldWidth)); - - JButton okBtn = new JButton("OK"); - okBtn.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - completed = true; - setVisible(false); - } - }); - panel.add(okBtn, "cell 1 4 3 1"); - - JButton cancelBtn = new JButton("Cancel"); - cancelBtn.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - completed = false; - setVisible(false); - } - }); - panel.add(cancelBtn, "cell 1 4"); - - ButtonGroup grp = new ButtonGroup(); - grp.add(scaleCheck); - grp.add(sizeCheck); - - - scaleCheck.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - setByScale = scaleCheck.isSelected(); - enableItems(); - } - }); - - sizeCheck.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - setByScale = scaleCheck.isSelected(); - enableItems(); - } - }); - - setByScale = scaleCheck.isSelected(); - enableItems(); - - getContentPane().add(panel); - pack(); - } - - /** - * Enable dialog controls for the current dialog mode: - * setting map scale or setting image size directly. - */ - private void enableItems() { - scaleCombo.setEnabled(setByScale); - - widthField.setEnabled(!setByScale); - heightField.setEnabled(!setByScale); - } - - /** - * Set initial default values for image size - */ - private void initValues() { - heightToWidth = mapBounds.getSpan(YAXIS) / mapBounds.getSpan(XAXIS); - imageSize = new Rectangle(); - - // this will cause the height and scale controls to be updated - widthField.setValue(DEFAULT_IMAGE_WIDTH); - } - - /** - * Update controls when one of the image size fields has been edited - * - * @param controlModified constant indicating which field was edited - */ - private void onImageSizeChange(int controlModified) { - switch (controlModified) { - case WIDTH_FIELD: - imageSize.width = widthField.getValue(); - imageSize.height = (int) Math.round(imageSize.width * heightToWidth); - heightField.setValue(imageSize.height, false); - break; - - case HEIGHT_FIELD: - imageSize.height = heightField.getValue(); - imageSize.width = (int) Math.round(imageSize.height / heightToWidth); - widthField.setValue(imageSize.width, false); - break; - } - - int scaleDenominator = 0; - if (imageSize.width > 0) { - scaleDenominator = (int) Math.round(mapBounds.getSpan(XAXIS) / imageSize.width); - } - scaleCombo.getEditor().setItem(Integer.valueOf(scaleDenominator)); - } - - /** - * Update the controls when the scale has been changed - */ - private void onScaleChange() { - int scaleDenominator = ((Number) scaleCombo.getEditor().getItem()).intValue(); - if (scaleDenominator > 0) { - imageSize.width = (int) (mapBounds.getSpan(XAXIS) / scaleDenominator); - imageSize.height = (int) (mapBounds.getSpan(YAXIS) / scaleDenominator); - } else { - imageSize.width = imageSize.height = 0; - } - - widthField.setValue( imageSize.width, false ); - heightField.setValue( imageSize.height, false ); - } - - /** - * Display a {@code JFileImageChooser} to browse for the path and file - * to save the image to - */ - private void brosweFile() { - File file = JFileImageChooser.showSaveFile(this); - if (file != null) { - selectedFile = file; - fileField.setText(file.getAbsolutePath()); - } - } - - /** - * Demonstrate the dialog - * @param args ignored - */ - public static void main(String[] args) { - ReferencedEnvelope bounds = new ReferencedEnvelope(0, 10000, 0, 20000, null); - JMapImageDialog dialog = new JMapImageDialog(bounds); - dialog.setVisible(true); - dialog.dispose(); - } -} - Deleted: trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialogs/package-info.java =================================================================== --- trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialogs/package-info.java 2009-10-30 11:10:24 UTC (rev 34288) +++ trunk/modules/unsupported/swing/src/main/java/org/geotools/swing/dialogs/package-info.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -1,22 +0,0 @@ -/* - * GeoTools - The Open Source Java GIS Toolkit - * http://geotools.org - * - * (C) 2009, Open Source Geospatial Foundation (OSGeo) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ - -/** - * General dialog classes - */ -package org.geotools.swing.dialogs; - Modified: trunk/modules/unsupported/swing/src/test/java/org/geotools/swing/dndlist/DnDListModelTest.java =================================================================== --- trunk/modules/unsupported/swing/src/test/java/org/geotools/swing/dndlist/DnDListModelTest.java 2009-10-30 11:10:24 UTC (rev 34288) +++ trunk/modules/unsupported/swing/src/test/java/org/geotools/swing/dndlist/DnDListModelTest.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -17,7 +17,7 @@ package org.geotools.swing.dndlist; -import org.geotools.swing.controls.DnDListModel; +import org.geotools.swing.control.DnDListModel; import static org.junit.Assert.*; import java.util.ArrayList; Modified: trunk/modules/unsupported/swing/src/test/java/org/geotools/swing/dndlist/DnDListTest.java =================================================================== --- trunk/modules/unsupported/swing/src/test/java/org/geotools/swing/dndlist/DnDListTest.java 2009-10-30 11:10:24 UTC (rev 34288) +++ trunk/modules/unsupported/swing/src/test/java/org/geotools/swing/dndlist/DnDListTest.java 2009-10-30 12:33:06 UTC (rev 34289) @@ -17,8 +17,8 @@ package org.geotools.swing.dndlist; -import org.geotools.swing.controls.DnDListModel; -import org.geotools.swing.controls.DnDList; +import org.geotools.swing.control.DnDListModel; +import org.geotools.swing.control.DnDList; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; ------------------------------------------------------------------------------ Come build with us! The BlackBerry(R) Developer Conference in SF, CA is the only developer event you need to attend this year. Jumpstart your developing skills, take BlackBerry mobile applications to market and stay ahead of the curve. Join us from November 9 - 12, 2009. Register now! http://p.sf.net/sfu/devconference _______________________________________________ GeoTools-commits mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/geotools-commits |
||||||||||||||||
| Free Embeddable Forum Powered by Nabble | Help |