OSDN Git Service

オーバーライドしているメソッド全てに @Override アノテーションを追加した.
[stigmata/stigmata-core.git] / src / main / java / jp / sourceforge / stigmata / ui / swing / TargetSelectionPane.java
1 package jp.sourceforge.stigmata.ui.swing;
2
3 /*
4  * $Id$
5  */
6
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;
23 import java.io.File;
24 import java.io.IOException;
25 import java.text.MessageFormat;
26 import java.util.ArrayList;
27 import java.util.List;
28
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;
43
44 import jp.sourceforge.stigmata.ui.swing.actions.PopupShowAction;
45 import jp.sourceforge.talisman.i18n.Messages;
46
47 /**
48  * 
49  * @author Haruaki TAMADA
50  * @version $Revision$ 
51  */
52 public class TargetSelectionPane extends JPanel{
53     private static final long serialVersionUID = 3209435745432235432L;
54
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;
63     private JList list;
64     private Action addAction;
65     private Action removeAction;
66
67     public TargetSelectionPane(StigmataFrame stigmata){
68         this.stigmata = stigmata;
69         initComponents();
70         list.setModel(model);
71
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)
78         );
79     }
80
81     public void addDataChangeListener(DataChangeListener listener){
82         listeners.add(listener);
83     }
84
85     public void addTargetExtension(String ext){
86         if(filters != null){
87             filters = null;
88         }
89         extensions.add(ext);
90     }
91
92     public void addTargetExtensions(String[] exts){
93         if(filters != null){
94             filters = null;
95         }
96         for(String ext: exts){
97             extensions.add(ext);
98         }
99     }
100
101     public void addValue(String value){
102         model.addElement(value);
103         fireEvent();
104     }
105
106     public void addValues(String[] values){
107         for(String value: values){
108             addValue(value);
109         }
110     }
111
112     public String getDescription(){
113         return description;
114     }
115
116     public synchronized String[] getExtensions(){
117         return extensions.toArray(new String[extensions.size()]);
118     }
119
120     public FileFilter[] getFileFilters(){
121         if(filters == null){
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])
127                 );
128             }
129             ;
130         }
131         return filters;
132     }
133
134     public String getSelectDescription(){
135         return description;
136     }
137
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]);
143         }
144         return strings;
145     }
146
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);
151         }
152         return strings;
153     }
154
155     public boolean isDirectorySelectable(){
156         return directorySelectable;
157     }
158
159     public boolean isMultipleSelectable(){
160         return multipleSelectable;
161     }
162
163     public void removeAllElements(){
164         model.removeAllElements();
165         fireEvent();
166     }
167
168     public void setDescription(String description){
169         this.description = description;
170     }
171
172     public void setDirectorySelectable(boolean flag){
173         directorySelectable = flag;
174     }
175
176     @Override
177     public void setEnabled(boolean flag){
178         super.setEnabled(flag);
179         addAction.setEnabled(flag);
180         removeAction.setEnabled(false);
181         list.setEnabled(flag);
182     }
183
184     public void setFileFilter(FileFilter filter){
185         setFileFilters(new FileFilter[] { filter, });
186     }
187
188     public void setFileFilters(FileFilter[] filters){
189         this.filters = filters;
190     }
191
192     public void setMultipleSelectable(boolean flag){
193         multipleSelectable = flag;
194     }
195
196     public void setSelectDescription(String description){
197         this.description = description;
198     }
199
200     private void addButtonActionPerformed(ActionEvent evt){
201         File[] files = stigmata.openFiles(getFileFilters(), true, true);
202         for(File file: files){
203             addValue(file.getPath());
204         }
205     }
206
207     private void fireEvent(){
208         for(int i = listeners.size() - 1; i >= 0; i--){
209             DataChangeListener listener = listeners.get(i);
210             listener.valueChanged(model);
211         }
212     }
213
214     private void initComponents(){
215         final Messages messages = stigmata.getMessages();
216         JScrollPane scroll = new JScrollPane();
217         JComponent south = Box.createHorizontalBox();
218         list = new JList();
219
220         addAction = new AbstractAction(){
221             private static final long serialVersionUID = 1406018312294328837L;
222
223             @Override
224             public void actionPerformed(ActionEvent e){
225                 addButtonActionPerformed(e);
226             }
227         };
228         removeAction = new AbstractAction(){
229             private static final long serialVersionUID = 7910621850068803554L;
230
231             @Override
232             public void actionPerformed(ActionEvent e){
233                 removeButtonActionPerformed(e);
234             }
235         };
236
237         JButton addButton = GUIUtility.createButton(messages, "addpackage", addAction);
238         JButton removeButton = GUIUtility.createButton(messages, "removepackage", removeAction);
239         removeAction.setEnabled(false);
240
241         final JPopupMenu popup = new JPopupMenu();
242         popup.add(GUIUtility.createJMenuItem(messages, "addpackage", addAction));
243         popup.add(GUIUtility.createJMenuItem(messages, "removepackage", removeAction));
244
245         setLayout(new BorderLayout());
246
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());
253
254         list.addListSelectionListener(new ListSelectionListener(){
255             @Override
256             public void valueChanged(ListSelectionEvent evt){
257                 listValueChanged(evt);
258             }
259         });
260
261         list.addMouseListener(new PopupShowAction(popup));
262
263         add(scroll, java.awt.BorderLayout.CENTER);
264         add(south, BorderLayout.SOUTH);
265     }
266
267     private void listValueChanged(ListSelectionEvent evt){
268         int[] indeces = list.getSelectedIndices();
269         removeAction.setEnabled(isEnabled() && indeces != null);
270     }
271
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]);
277                 fireEvent();
278             }
279         }
280         removeAction.setEnabled(false);
281     }
282
283     private class DataRemoveWhenDragSuccessfulAdapter extends DragSourceAdapter{
284         private DefaultListModel model;
285         private int[] indeces;
286
287         public DataRemoveWhenDragSuccessfulAdapter(DefaultListModel model,
288             int[] indeces){
289             this.model = model;
290             this.indeces = indeces;
291         }
292
293         @Override
294         public void dragDropEnd(DragSourceDropEvent dsde){
295             for(int i = indeces.length - 1; i >= 0; i--){
296                 model.removeElementAt(indeces[i]);
297             }
298             fireEvent();
299             super.dragDropEnd(dsde);
300         }
301     };
302
303     private class TargetDragGestureListener implements DragGestureListener{
304         private JList list;
305
306         public TargetDragGestureListener(JList list, DefaultListModel model){
307             this.list = list;
308         }
309
310         @Override
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]);
317                 }
318                 Transferable transferable = new TargetTransferable(strings);
319                 DragSourceListener listener = new DataRemoveWhenDragSuccessfulAdapter(
320                     model, indeces);
321
322                 dge.startDrag(DragSource.DefaultMoveDrop, transferable,
323                     listener);
324             }
325         }
326     };
327
328     private class TargetSelectionDropTarget extends DropTarget{
329         private static final long serialVersionUID = 3204457621345L;
330
331         @Override
332         public void dragEnter(DropTargetDragEvent arg0){
333         }
334
335         @Override
336         public void dragExit(DropTargetEvent arg0){
337         }
338
339         @Override
340         public void dragOver(DropTargetDragEvent arg0){
341         }
342
343         @Override
344         public void drop(DropTargetDropEvent dtde){
345             dtde.acceptDrop(DnDConstants.ACTION_REFERENCE);
346             Transferable trans = dtde.getTransferable();
347             try{
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);
354                     }
355                 }
356             } catch(UnsupportedFlavorException e){
357             } catch(IOException e){
358             }
359         }
360
361         @Override
362         public void dropActionChanged(DropTargetDragEvent arg0){
363         }
364
365         @SuppressWarnings("rawtypes")
366         private List<String> checkAndAddDroppedFile(List list){
367             List<String> errorList = new ArrayList<String>();
368
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;
377                     }
378                 }
379                 if(neverAddedFlag){
380                     errorList.add(file.getName());
381                 }
382             }
383             return errorList;
384         }
385
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>");
392             }
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
398             );
399         }
400     };
401
402     private class TargetTransferable implements Transferable{
403         private String[] strings;
404
405         public TargetTransferable(String[] strings){
406             this.strings = strings;
407         }
408
409         @Override
410         public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException,
411                                                         IOException{
412             List<File> list = new ArrayList<File>();
413             for(int i = 0; i < strings.length; i++){
414                 list.add(new File(strings[i]));
415             }
416             return list;
417         }
418
419         @Override
420         public DataFlavor[] getTransferDataFlavors(){
421             return new DataFlavor[] { DataFlavor.javaFileListFlavor, };
422         }
423
424         @Override
425         public boolean isDataFlavorSupported(DataFlavor flavor){
426             return flavor.equals(DataFlavor.javaFileListFlavor);
427         }
428     }
429 }