1 package jp.sourceforge.stigmata.ui.swing;
7 import java.awt.BorderLayout;
8 import java.awt.datatransfer.DataFlavor;
9 import java.awt.datatransfer.Transferable;
10 import java.awt.datatransfer.UnsupportedFlavorException;
11 import java.awt.dnd.DnDConstants;
12 import java.awt.dnd.DragGestureEvent;
13 import java.awt.dnd.DragGestureListener;
14 import java.awt.dnd.DragSource;
15 import java.awt.dnd.DragSourceAdapter;
16 import java.awt.dnd.DragSourceDropEvent;
17 import java.awt.dnd.DragSourceListener;
18 import java.awt.dnd.DropTarget;
19 import java.awt.dnd.DropTargetDragEvent;
20 import java.awt.dnd.DropTargetDropEvent;
21 import java.awt.dnd.DropTargetEvent;
22 import java.awt.event.ActionEvent;
24 import java.io.IOException;
25 import java.text.MessageFormat;
26 import java.util.ArrayList;
27 import java.util.List;
29 import javax.swing.AbstractAction;
30 import javax.swing.Action;
31 import javax.swing.Box;
32 import javax.swing.DefaultListModel;
33 import javax.swing.JButton;
34 import javax.swing.JComponent;
35 import javax.swing.JList;
36 import javax.swing.JOptionPane;
37 import javax.swing.JPanel;
38 import javax.swing.JPopupMenu;
39 import javax.swing.JScrollPane;
40 import javax.swing.event.ListSelectionEvent;
41 import javax.swing.event.ListSelectionListener;
42 import javax.swing.filechooser.FileFilter;
44 import jp.sourceforge.stigmata.ui.swing.actions.PopupShowAction;
45 import jp.sourceforge.talisman.i18n.Messages;
49 * @author Haruaki TAMADA
52 public class TargetSelectionPane extends JPanel{
53 private static final long serialVersionUID = 3209435745432235432L;
55 private StigmataFrame stigmata;
56 private FileFilter[] filters;
57 private List<String> extensions = new ArrayList<String>();
58 private String description;
59 private DefaultListModel model = new DefaultListModel();
60 private List<DataChangeListener> listeners = new ArrayList<DataChangeListener>();
61 private boolean directorySelectable = false;
62 private boolean multipleSelectable = true;
64 private Action addAction;
65 private Action removeAction;
67 public TargetSelectionPane(StigmataFrame stigmata){
68 this.stigmata = stigmata;
72 DropTarget dropTarget = new TargetSelectionDropTarget();
73 list.setDropTarget(dropTarget);
74 DragSource dragSource = DragSource.getDefaultDragSource();
75 dragSource.createDefaultDragGestureRecognizer(
76 list, DnDConstants.ACTION_MOVE,
77 new TargetDragGestureListener(list, model)
81 public void addDataChangeListener(DataChangeListener listener){
82 listeners.add(listener);
85 public void addTargetExtension(String ext){
92 public void addTargetExtensions(String[] exts){
96 for(String ext: exts){
101 public void addValue(String value){
102 model.addElement(value);
106 public void addValues(String[] values){
107 for(String value: values){
112 public String getDescription(){
116 public synchronized String[] getExtensions(){
117 return extensions.toArray(new String[extensions.size()]);
120 public FileFilter[] getFileFilters(){
122 String[] exts = getExtensions();
123 filters = new FileFilter[exts.length];
124 for(int i = 0; i < exts.length; i++){
125 filters[i] = new ExtensionFilter(
126 exts[i], MessageFormat.format(getSelectDescription(), exts[i])
134 public String getSelectDescription(){
138 public String[] getSelectedValues(){
139 int[] indeces = list.getSelectedIndices();
140 String[] strings = new String[indeces.length];
141 for(int i = 0; i < strings.length; i++){
142 strings[i] = (String)model.getElementAt(indeces[i]);
147 public String[] getValues(){
148 String[] strings = new String[model.getSize()];
149 for(int i = 0; i < strings.length; i++){
150 strings[i] = (String)model.getElementAt(i);
155 public boolean isDirectorySelectable(){
156 return directorySelectable;
159 public boolean isMultipleSelectable(){
160 return multipleSelectable;
163 public void removeAllElements(){
164 model.removeAllElements();
168 public void setDescription(String description){
169 this.description = description;
172 public void setDirectorySelectable(boolean flag){
173 directorySelectable = flag;
177 public void setEnabled(boolean flag){
178 super.setEnabled(flag);
179 addAction.setEnabled(flag);
180 removeAction.setEnabled(false);
181 list.setEnabled(flag);
184 public void setFileFilter(FileFilter filter){
185 setFileFilters(new FileFilter[] { filter, });
188 public void setFileFilters(FileFilter[] filters){
189 this.filters = filters;
192 public void setMultipleSelectable(boolean flag){
193 multipleSelectable = flag;
196 public void setSelectDescription(String description){
197 this.description = description;
200 private void addButtonActionPerformed(ActionEvent evt){
201 File[] files = stigmata.openFiles(getFileFilters(), true, true);
202 for(File file: files){
203 addValue(file.getPath());
207 private void fireEvent(){
208 for(int i = listeners.size() - 1; i >= 0; i--){
209 DataChangeListener listener = listeners.get(i);
210 listener.valueChanged(model);
214 private void initComponents(){
215 final Messages messages = stigmata.getMessages();
216 JScrollPane scroll = new JScrollPane();
217 JComponent south = Box.createHorizontalBox();
220 addAction = new AbstractAction(){
221 private static final long serialVersionUID = 1406018312294328837L;
224 public void actionPerformed(ActionEvent e){
225 addButtonActionPerformed(e);
228 removeAction = new AbstractAction(){
229 private static final long serialVersionUID = 7910621850068803554L;
232 public void actionPerformed(ActionEvent e){
233 removeButtonActionPerformed(e);
237 JButton addButton = GUIUtility.createButton(messages, "addpackage", addAction);
238 JButton removeButton = GUIUtility.createButton(messages, "removepackage", removeAction);
239 removeAction.setEnabled(false);
241 final JPopupMenu popup = new JPopupMenu();
242 popup.add(GUIUtility.createJMenuItem(messages, "addpackage", addAction));
243 popup.add(GUIUtility.createJMenuItem(messages, "removepackage", removeAction));
245 setLayout(new BorderLayout());
247 scroll.setViewportView(list);
248 south.add(Box.createHorizontalGlue());
249 south.add(addButton);
250 south.add(Box.createHorizontalGlue());
251 south.add(removeButton);
252 south.add(Box.createHorizontalGlue());
254 list.addListSelectionListener(new ListSelectionListener(){
256 public void valueChanged(ListSelectionEvent evt){
257 listValueChanged(evt);
261 list.addMouseListener(new PopupShowAction(popup));
263 add(scroll, java.awt.BorderLayout.CENTER);
264 add(south, BorderLayout.SOUTH);
267 private void listValueChanged(ListSelectionEvent evt){
268 int[] indeces = list.getSelectedIndices();
269 removeAction.setEnabled(isEnabled() && indeces != null);
272 private void removeButtonActionPerformed(ActionEvent evt){
273 int[] indeces = list.getSelectedIndices();
274 if(indeces != null && indeces.length >= 1){
275 for(int i = indeces.length - 1; i >= 0; i--){
276 model.removeElementAt(indeces[i]);
280 removeAction.setEnabled(false);
283 private class DataRemoveWhenDragSuccessfulAdapter extends DragSourceAdapter{
284 private DefaultListModel model;
285 private int[] indeces;
287 public DataRemoveWhenDragSuccessfulAdapter(DefaultListModel model,
290 this.indeces = indeces;
294 public void dragDropEnd(DragSourceDropEvent dsde){
295 for(int i = indeces.length - 1; i >= 0; i--){
296 model.removeElementAt(indeces[i]);
299 super.dragDropEnd(dsde);
303 private class TargetDragGestureListener implements DragGestureListener{
306 public TargetDragGestureListener(JList list, DefaultListModel model){
311 public void dragGestureRecognized(DragGestureEvent dge){
312 int[] indeces = list.getSelectedIndices();
313 if(indeces.length > 0){
314 String[] strings = new String[indeces.length];
315 for(int i = 0; i < strings.length; i++){
316 strings[i] = (String)model.getElementAt(indeces[i]);
318 Transferable transferable = new TargetTransferable(strings);
319 DragSourceListener listener = new DataRemoveWhenDragSuccessfulAdapter(
322 dge.startDrag(DragSource.DefaultMoveDrop, transferable,
328 private class TargetSelectionDropTarget extends DropTarget{
329 private static final long serialVersionUID = 3204457621345L;
332 public void dragEnter(DropTargetDragEvent arg0){
336 public void dragExit(DropTargetEvent arg0){
340 public void dragOver(DropTargetDragEvent arg0){
344 public void drop(DropTargetDropEvent dtde){
345 dtde.acceptDrop(DnDConstants.ACTION_REFERENCE);
346 Transferable trans = dtde.getTransferable();
348 if(trans.isDataFlavorSupported(DataFlavor.javaFileListFlavor)){
349 @SuppressWarnings("rawtypes")
350 List list = (List)trans.getTransferData(DataFlavor.javaFileListFlavor);
351 List<String> errorList = checkAndAddDroppedFile(list);
352 if(errorList.size() > 0){
353 showError(errorList);
356 } catch(UnsupportedFlavorException e){
357 } catch(IOException e){
362 public void dropActionChanged(DropTargetDragEvent arg0){
365 @SuppressWarnings("rawtypes")
366 private List<String> checkAndAddDroppedFile(List list){
367 List<String> errorList = new ArrayList<String>();
369 FileFilter[] filters = getFileFilters();
370 for(int i = 0; i < list.size(); i++){
371 File file = (File)list.get(i);
372 boolean neverAddedFlag = true;
373 for(FileFilter filter: filters){
374 if(filter.accept(file)){
375 addValue(file.getPath());
376 neverAddedFlag = false;
380 errorList.add(file.getName());
386 private void showError(List<String> errorList){
387 StringBuilder builder = new StringBuilder("<html><body>");
388 builder.append(stigmata.getMessages().get("unsupportedfiletype.dialog.message"));
389 builder.append("<ul>");
390 for(int i = 0; i < errorList.size(); i++){
391 builder.append("<li>").append(errorList.get(i)).append("</li>");
393 builder.append("</ul></body></html>");
394 JOptionPane.showMessageDialog(
395 TargetSelectionPane.this, new String(builder),
396 stigmata.getMessages().get("unsupportedfiletype.dialog.title"),
397 JOptionPane.ERROR_MESSAGE
402 private class TargetTransferable implements Transferable{
403 private String[] strings;
405 public TargetTransferable(String[] strings){
406 this.strings = strings;
410 public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException,
412 List<File> list = new ArrayList<File>();
413 for(int i = 0; i < strings.length; i++){
414 list.add(new File(strings[i]));
420 public DataFlavor[] getTransferDataFlavors(){
421 return new DataFlavor[] { DataFlavor.javaFileListFlavor, };
425 public boolean isDataFlavorSupported(DataFlavor flavor){
426 return flavor.equals(DataFlavor.javaFileListFlavor);