KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > snow > utils > gui > FileField


1 package snow.utils.gui;
2
3 import java.awt.datatransfer.DataFlavor JavaDoc;
4 import java.awt.datatransfer.Transferable JavaDoc;
5 import javax.swing.border.Border JavaDoc;
6 import java.awt.dnd.*;
7 import java.awt.Color JavaDoc;
8 import java.awt.Dimension JavaDoc;
9 import java.awt.GridBagConstraints JavaDoc;
10 import snow.utils.storage.FileUtils;
11 import javax.swing.*;
12 import java.awt.GridBagLayout JavaDoc;
13 import java.awt.event.*;
14 import javax.swing.event.*;
15 import java.io.*;
16 import java.util.*;
17 import snow.utils.SysUtils;
18 import snow.Basics;
19
20 /** a field to edit a file name, with some goodies.
21 * call setAutoColorized() to show in red invalid paths
22 * TODO tab completion is buggy... if files with same name start as folder exists
23 */

24 public class FileField extends JPanel
25 {
26   final private JButton editPathButton = new JButton("...");
27   final private JTextField pathField = new JTextField("");
28   final private boolean saveMode;
29   final private String JavaDoc dialogTitle;
30   private final Vector<ActionListener> actionListeners = new Vector<ActionListener>();
31   final private int fileChooserSelectionMode;
32   private boolean autoColorized = false;
33
34   // empty => all
35
final public Set<String JavaDoc> allowedExtensions = new HashSet<String JavaDoc>();
36   public String JavaDoc fileTypeDescription = "";
37
38   /** @param fileChooserSelectionMode JFileChooser.FILES_AND_DIRECTORIES
39   */

40   public FileField(File path, boolean saveMode, String JavaDoc dialogTitle, int fileChooserSelectionMode)
41   {
42      this(path!=null ? path.getAbsolutePath() : null, saveMode, dialogTitle, fileChooserSelectionMode);
43   }
44
45   /** @param fileChooserSelectionMode JFileChooser.FILES_AND_DIRECTORIES
46   */

47   public FileField(String JavaDoc path, boolean saveMode, String JavaDoc dialogTitle, int fileChooserSelectionMode)
48   {
49      super(); //new FlowLayout(FlowLayout.LEFT,0,0));
50
GridBagLayout JavaDoc gridbag = new GridBagLayout JavaDoc();
51      GridBagConstraints JavaDoc constr = new GridBagConstraints JavaDoc();
52      setLayout(gridbag);
53
54      this.saveMode = saveMode;
55      this.dialogTitle = dialogTitle;
56      this.fileChooserSelectionMode = fileChooserSelectionMode;
57
58      constr.weightx=1;
59      constr.fill = GridBagConstraints.HORIZONTAL;
60      gridbag.setConstraints(pathField, constr);
61      add(pathField);
62      pathField.setText(path);
63
64      constr.weightx=0;
65      gridbag.setConstraints(editPathButton, constr);
66      add(editPathButton);
67
68
69      Dimension JavaDoc dim = new Dimension JavaDoc(
70           (int) pathField.getPreferredSize().getHeight(),
71           (int) pathField.getPreferredSize().getHeight());
72
73      editPathButton.setPreferredSize(dim);
74      editPathButton.setMaximumSize(dim);
75      editPathButton.setMinimumSize(dim);
76      editPathButton.setFocusPainted(false);
77
78
79      editPathButton.addActionListener(new ActionListener()
80      {
81        public void actionPerformed(ActionEvent e)
82        {
83           browseFileAction();
84        }
85      });
86
87      pathField.addActionListener(new ActionListener()
88      {
89        public void actionPerformed(ActionEvent e)
90        {
91           notifyActionListeners();
92        }
93      });
94
95      editPathButton.addMouseListener(new MouseAdapter(){
96        @Override JavaDoc public void mousePressed(MouseEvent me)
97        {
98           if(me.isPopupTrigger()) showPopup(me);
99        }
100        @Override JavaDoc public void mouseReleased(MouseEvent me)
101        {
102           if(me.isPopupTrigger()) showPopup(me);
103        }
104
105        private void showPopup(MouseEvent me)
106        {
107           final File dest = getPath();
108           if(dest==null) return;
109
110           JPopupMenu pop = new JPopupMenu();
111
112
113           if(dest.exists())
114           {
115             if( dest.isFile())
116             {
117               JMenuItem openSFS = new JMenuItem("Open parent dir in OS file explorer");
118               pop.add(openSFS);
119               openSFS.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
120                  SysUtils.openFileExplorer( dest.getParent() );
121               } });
122
123               JMenuItem openSFSE = new JMenuItem("Open file (OS Execution)");
124               pop.addSeparator();
125               pop.add(openSFSE);
126               openSFSE.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
127                  SysUtils.openFileExplorer( dest.getAbsolutePath() );
128               } });
129
130             }
131             else
132             {
133               JMenuItem openSFS = new JMenuItem("Open in OS file explorer");
134               pop.add(openSFS);
135               openSFS.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
136                  SysUtils.openFileExplorer( dest.getAbsolutePath() );
137               } });
138
139
140             }
141           }
142
143           pop.show( editPathButton, pop.getX(), pop.getY()+15);
144        }
145      });
146
147     pathField.addKeyListener(new KeyAdapter()
148     {
149        @Override JavaDoc public void keyReleased(KeyEvent ke)
150        {
151           boolean isCaretAtEnd = pathField.getCaretPosition()==pathField.getText().length();
152
153           if(isCaretAtEnd)
154           {
155              if(ke.getModifiers()==KeyEvent.CTRL_MASK && ke.getKeyCode()==ke.VK_T)
156              {
157                 completePathForward();
158              }
159
160              if(ke.getKeyCode()==ke.VK_TAB)
161              {
162                 if(pathField.getCaretPosition()==pathField.getText().length())
163                 {
164                   completePathForward();
165                 }
166              }
167              if(ke.getKeyCode()==ke.VK_RIGHT)
168              {
169                 pathField.transferFocusBackward();
170              }
171           }
172
173           if(ke.getKeyCode()==ke.VK_UP)
174           {
175              pathField.transferFocusBackward();
176           }
177
178           if(ke.getKeyCode()==ke.VK_DOWN)
179           {
180              pathField.transferFocus();
181           }
182
183
184           //System.out.println(""+ke);
185

186
187           if(autoColorized)
188           {
189             updateColor();
190           }
191        }
192     });
193
194     // deactivate the original tab function
195
Action doNothing = new AbstractAction() {
196         public void actionPerformed(ActionEvent e) {
197             //do nothing
198
System.out.println("DO NOTHING !");
199         }
200     };
201     // don't work !!
202
/* KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0, false);
203     getTextField().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(ks, "doNothing");
204     getTextField().getActionMap().put("doNothing", doNothing);*/

205     // BAD ! tricky !
206
//getTextField().setNextFocusableComponent(getTextField());
207
getTextField().setFocusTraversalKeysEnabled(false);
208
209
210   } // Constructor
211

212   /** red if not existing
213   */

214   public void setAutoColorized()
215   {
216     autoColorized = true;
217     updateColor();
218   }
219
220   public JTextField getTextField() { return pathField; }
221
222   /** manual call to set red if not valid
223   */

224   private void updateColor()
225   {
226      if(new File(pathField.getText()).exists())
227      {
228        pathField.setForeground(UIManager.getColor("TextField.foreground"));
229      }
230      else
231      {
232        pathField.setForeground(Color.red.darker());
233      }
234   }
235
236   /**
237   * @return null if the field is empty. (Allow to distinguish between the File("") and NO FILE !!
238   * the path may not exist ! use
239   */

240   public File getPath()
241   {
242      String JavaDoc ft = pathField.getText().trim();
243      if(ft.length()==0) return null;
244      File file = new File( ft );
245      // [Nov2006] makes correct path names ! ("E:" and "e:" not the same)
246
return FileUtils.getCanonicalFileWithCase(file);
247   }
248
249   /** in save mode, all paths are "valid"...
250   * otherwise, valid means "exists"
251   */

252   public boolean isPathValid()
253   {
254      if(saveMode) return true;
255
256      File file = getPath();
257      if(file.exists()) return true;
258      return false;
259   }
260
261   private void browseFileAction()
262   {
263      JFileChooser fileChooser = new JFileChooser();
264      fileChooser.setDialogTitle(dialogTitle);
265      File base = getPath();
266      if(base!=null)
267      {
268        if(base.exists())
269        {
270          fileChooser.setCurrentDirectory(base);
271        }
272        else
273        {
274          // try with the parent
275
if(base.getParentFile()!=null)
276          {
277            fileChooser.setCurrentDirectory(base.getParentFile());
278          }
279          else
280          {
281            File lastGood = this.getFirstValidPathStartingWith();
282            if(lastGood!=null)
283            {
284               if(lastGood.isDirectory())
285               {
286                  fileChooser.setCurrentDirectory(lastGood);
287               }
288               else
289               {
290                  fileChooser.setCurrentDirectory(lastGood.getParentFile());
291               }
292            }
293          }
294        }
295      }
296
297      fileChooser.setFileSelectionMode(this.fileChooserSelectionMode);
298      FileViewWithAttributes view = new FileViewWithAttributes();
299      fileChooser.setFileView(view);
300
301      if(allowedExtensions.size()>0)
302      {
303         fileChooser.setFileFilter(new javax.swing.filechooser.FileFilter JavaDoc()
304         {
305            @Override JavaDoc public boolean accept(File f)
306            {
307               if(f.isDirectory()) return true;
308               String JavaDoc name = f.getName().toLowerCase(Locale.ENGLISH);
309               for(String JavaDoc ext: allowedExtensions)
310               {
311                  if(name.endsWith("."+ext)) return true;
312               }
313               return false;
314            }
315
316            public String JavaDoc getDescription()
317            {
318               return fileTypeDescription;
319            }
320         });
321      }
322
323      if(saveMode)
324      {
325         int rep = fileChooser.showSaveDialog(this);
326         if(rep==JFileChooser.APPROVE_OPTION)
327         {
328           File file = fileChooser.getSelectedFile();
329           setPath(file.getAbsolutePath());
330         }
331      }
332      else
333      {
334         FileChooserFilter fsf = new FileChooserFilter(fileChooser);
335         fileChooser.setAccessory(fsf);
336
337         int rep = fileChooser.showOpenDialog(this);
338         if(rep==JFileChooser.APPROVE_OPTION)
339         {
340           File file = fileChooser.getSelectedFile();
341           setPath(file.getAbsolutePath());
342         }
343      }
344
345
346   }
347
348   public void setEditable(boolean editable)
349   {
350     pathField.setEditable(editable);
351     editPathButton.setEnabled(editable);
352   }
353
354   /** nevessary in the gridlayout3, to be preferred to FileField.setVisible()
355   */

356   public void makeVisible(boolean v)
357   {
358     pathField.setVisible(v);
359     editPathButton.setVisible(v);
360   }
361
362   public void setFile(File path)
363   {
364      setPath(path);
365   }
366
367   public void setPath(File path)
368   {
369     setPath(path.getAbsolutePath());
370   }
371
372
373   public void setPath(String JavaDoc path)
374   {
375     pathField.setText(path);
376     if(autoColorized) this.updateColor();
377     notifyActionListeners();
378   }
379
380   public boolean isValidCandidate(File f)
381   {
382      if(f==null) return true; // as default (no file selected!)
383
if(fileChooserSelectionMode == JFileChooser.FILES_ONLY && f.isDirectory()) return false;
384      if(fileChooserSelectionMode == JFileChooser.DIRECTORIES_ONLY && !f.isDirectory()) return false;
385      return true;
386   }
387
388
389
390   public void addActionListener(ActionListener al)
391   {
392      actionListeners.add(al);
393   }
394
395   public void removeActionListener(ActionListener al)
396   {
397      actionListeners.remove(al);
398   }
399
400   private void notifyActionListeners()
401   {
402     ActionListener[] als = actionListeners.toArray(new ActionListener[actionListeners.size()]);
403     for(ActionListener al : als)
404     {
405       al.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_FIRST, "File selected"));
406     }
407   }
408
409   public void setComponentWidth(int width)
410   {
411     Dimension JavaDoc dim = pathField.getPreferredSize();
412     dim.width = width;
413     pathField.setMinimumSize(dim);
414     pathField.setPreferredSize(dim);
415     pathField.setMaximumSize(dim);
416   }
417
418   /** null if none
419   */

420   public File getFirstValidPathStartingWith()
421   {
422      StringBuilder JavaDoc partialPath = new StringBuilder JavaDoc(this.getTextField().getText());
423      while(partialPath.length()>0)
424      {
425         File f = new File(partialPath.toString());
426         if(f.exists()) return FileUtils.getCanonicalFileWithCase(f);
427         partialPath.setLength( partialPath.length()-1);
428      }
429      return null;
430   }
431
432
433   private void completePathForward()
434   {
435      // TODO: buggy for windows/system3 !
436
final File firstValid = getFirstValidPathStartingWith();
437      if(firstValid==null) return;
438
439      String JavaDoc firstValidP = FileUtils.getCanonicalName(firstValid);
440      System.out.println("firstValid="+firstValidP);
441
442      String JavaDoc typedpath = FileUtils.getCanonicalName(getPath());
443      System.out.println("typedpath="+typedpath);
444
445     /*if(!typedpath.startsWith(firstValidP))
446      {
447         // remove the "/" at end, as occurng when completing "windows/system3" !
448         firstValidP = firstValidP.substring(0, firstValidP.length()-1);
449      }*/

450
451      String JavaDoc invalidStartsWith = typedpath.substring(firstValidP.length()).toUpperCase();
452      System.out.println("invalidStartsWith="+invalidStartsWith);
453
454      // look for files in firstValid startingwith invalidStartsWith
455
List<File> candidates = new ArrayList<File>();
456      for(File f : firstValid.listFiles())
457      {
458         if(this.fileChooserSelectionMode==JFileChooser.DIRECTORIES_ONLY && !f.isDirectory()) continue;
459
460
461         String JavaDoc can = FileUtils.getCanonicalName(f).toUpperCase();
462         String JavaDoc canDiff = can.substring(firstValidP.length()).toUpperCase();
463         if(canDiff.startsWith(invalidStartsWith))
464         {
465            //System.out.println("candidate: "+can);
466

467            candidates.add(f);
468         }
469      }
470
471      if(candidates.size()==1)
472      {
473         this.setPath(candidates.get(0));
474      }
475      else if(candidates.size()>1)
476      {
477         // popup
478
JPopupMenu pop = new JPopupMenu();
479         int n=0;
480         for(final File c : candidates)
481         {
482            JMenuItem mi = new JMenuItem(""+c);
483            pop.add(mi);
484            mi.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
485               setPath(c);
486            } });
487            n++;
488
489            if(n>20)
490            {
491               break;
492            }
493         }
494
495         // offers parents
496
if(firstValid.getParentFile()!=null)
497         {
498            JMenuItem mi = new JMenuItem(""+firstValid.getParentFile());
499            mi.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, 0));
500            pop.add(mi);
501            mi.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
502               setPath(firstValid.getParentFile());
503            } });
504
505         }
506
507
508         if(n>20)
509         {
510            JMenuItem mib = new JMenuItem(""+(candidates.size()-n)+" more entries... use the file browser or be more precise");
511            pop.add(mib);
512            mib.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) {
513               browseFileAction();
514            } });
515         }
516
517
518         pop.show(this.getTextField(),0,15);
519
520      }
521   }
522
523
524   class FileDropTarget extends DropTarget
525   {
526      public FileDropTarget(JComponent c)
527      {
528         super(c, DnDConstants.ACTION_COPY, new FileDropTargetListener(c), true);
529         c.setDropTarget(this);
530
531      }
532   }
533
534
535   class FileDropTargetListener implements DropTargetListener
536   {
537      JComponent comp;
538      Border JavaDoc originalBorder = null;
539      Border JavaDoc redBorder = BorderFactory.createLineBorder(Color.red, 1);
540      Border JavaDoc greenBorder = BorderFactory.createLineBorder(Color.green, 1);
541      public FileDropTargetListener(JComponent comp)
542      {
543         this.comp = comp;
544         this.originalBorder = comp.getBorder();
545
546      }
547
548
549      File fileToDrop = null;
550
551        public void dragEnter(DropTargetDragEvent dte) {
552           //System.out.println("dragEnter");
553

554           boolean accept = false;
555           for(DataFlavor JavaDoc df : dte.getCurrentDataFlavors())
556           {
557              if(df.isFlavorJavaFileListType())
558              {
559                 Transferable JavaDoc tr = dte.getTransferable();
560                 try
561                 {
562                    Object JavaDoc data = tr.getTransferData( df.javaFileListFlavor );
563                    //System.out.println(""+data);
564
@SuppressWarnings JavaDoc("unchecked")
565                    List<File> lf = (List<File>) data;
566                    if(lf.size()==1)
567                    {
568                      if(isValidCandidate(lf.get(0)))
569                      {
570                        fileToDrop = lf.get(0);
571                        pathField.setToolTipText("Droping "+lf.get(0));
572                        dte.acceptDrag(DnDConstants.ACTION_COPY);
573                        accept = true;
574                        break;
575                      }
576                    }
577                 }
578                 catch(Exception JavaDoc e)
579                 {
580                    comp.setBorder( redBorder);
581                    e.printStackTrace();
582                 }
583              }
584              else if (df.isFlavorTextType())
585              {
586                 Transferable JavaDoc tr = dte.getTransferable();
587                 try
588                 {
589                    String JavaDoc data = ""+tr.getTransferData( df.javaFileListFlavor );
590                    if(data.toLowerCase().startsWith("file:///")) data = data.substring(7);
591
592                    File f = new File(data);
593                    if(isValidCandidate(f))
594                    {
595                        fileToDrop = f;
596                        pathField.setToolTipText("Droping "+f); // don't work
597
//ToolTipManager.sharedInstance().setDismissDelay(.showTipWindow();
598
dte.acceptDrag(DnDConstants.ACTION_COPY);
599                        accept = true;
600                        break;
601                    }
602
603                 }
604                 catch(Exception JavaDoc e)
605                 {
606                    comp.setBorder( redBorder);
607                    e.printStackTrace();
608                 }
609              }
610              System.out.println(""+df);
611           }
612
613           if(accept)
614           {
615              comp.setBorder( greenBorder);
616           }
617           else
618           {
619             comp.setBorder( redBorder);
620           }
621        }
622
623        public void dragExit(DropTargetEvent dte) {
624           System.out.println("dragExit");
625           pathField.setToolTipText(null);
626           comp.setBorder(originalBorder);
627        }
628
629        public void dragOver(DropTargetDragEvent dte) {
630           //System.out.println("dragOver");
631
}
632
633        public void drop(DropTargetDropEvent dte) {
634           comp.setBorder(originalBorder);
635           pathField.setToolTipText(null);
636           if(fileToDrop!=null)
637           {
638              setFile(fileToDrop);
639           }
640           //System.out.println("drop");
641
}
642
643        public void dropActionChanged(DropTargetDragEvent dte) {
644           System.out.println("dropActionChanged");
645        }
646
647   }
648
649   public static void main(String JavaDoc[] arguments)
650   {
651      JFrame f = new JFrame();
652      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
653      FileField ff = new FileField("", false, "Hello", JFileChooser.FILES_ONLY);
654      ff.setComponentWidth(250);
655      ff.setAutoColorized();
656      f.setContentPane(ff);
657      f.pack();
658      f.setLocationRelativeTo(null);
659      f.setVisible(true);
660   }
661
662
663 } // FileField
Popular Tags