home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / jfc.bin / JDirectoryPane.java < prev    next >
Text File  |  1998-02-26  |  16KB  |  573 lines

  1. /*
  2.  * @(#)JDirectoryPane.java    1.12 98/02/03
  3.  * 
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  */
  20.  
  21. package com.sun.java.swing.preview;
  22.  
  23. import com.sun.java.swing.*;
  24. import com.sun.java.swing.plaf.*;
  25. import com.sun.java.swing.event.*;
  26. import java.io.File;
  27. import java.beans.*;
  28. import java.util.*;
  29. import java.awt.event.*;
  30. import com.sun.java.accessibility.*;
  31.  
  32. /**
  33.  * A pane used to display a directory listing.
  34.  * <p>
  35.  * Warning: serialized objects of this class will not be compatible with
  36.  * future swing releases.  The current serialization support is appropriate 
  37.  * for short term storage or RMI between Swing1.0 applications.  It will
  38.  * not be possible to load serialized Swing1.0 objects with future releases
  39.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  40.  * baseline for the serialized form of Swing objects.
  41.  *
  42.  * @version 1.12 02/03/98
  43.  * @author Ray Ryan
  44.  */
  45.  
  46. public class JDirectoryPane extends JComponent 
  47.     implements SwingConstants, Accessible {
  48.     /**
  49.      * The model of the directory shown by this JDirectoryPane
  50.      */
  51.     protected DirectoryModel directoryModel = null;
  52.  
  53.     /**
  54.      * The selection model of this JDirectoryPane
  55.      */
  56.     protected ListSelectionModel listSelectionModel = null;
  57.  
  58.     /**
  59.      * Listens to property changes from directoryModel
  60.      * and rebroadcasts them with this as the source
  61.      */
  62.     transient protected Redirector redirector = null;
  63.  
  64.     /**
  65.      * Listens to value changes from listSelectionModel,
  66.      * firing an action if appropriate
  67.      */
  68.     transient protected SelListener selListener = null;
  69.  
  70.     protected String command;
  71.     protected String doubleClickCommand = "doubleClick";
  72.     protected String doubleClickContainerCommand = "doubleClickContainer";
  73.  
  74.     GoUpAction goUpAction = new GoUpAction();
  75.  
  76.     DefaultActionListener defaultActionListener = new DefaultActionListener();
  77.  
  78.     /**
  79.      * Creates a JDirectoryPane on the user's home directory
  80.      */
  81.     public JDirectoryPane() {
  82.     this((File)null);
  83.     }
  84.  
  85.     /**
  86.      * Creates a JDirectoryPane on the given path
  87.      */
  88.     public JDirectoryPane(String path) {
  89.     this(path == null ? null : new File(path));
  90.     }
  91.  
  92.     /**
  93.      * Creates a JDirectoryPane on the given File
  94.      */
  95.     public JDirectoryPane(File directory) {
  96.     this.setModel(this.createDirectoryModel(directory));
  97.     this.setSelectionModel(this.createSelectionModel());
  98.     this.addActionListener(this.getDefaultActionListener());
  99.     updateUI();
  100.     }
  101.  
  102.     /**
  103.      * Override point for people who want to muck with the DirectoryModel
  104.      */
  105.     protected DirectoryModel createDirectoryModel(File directory) {
  106.     return new DirectoryModel(directory);
  107.     }
  108.  
  109.     /**
  110.      * Override point for people who want to muck with the ListSelectionModel
  111.      */
  112.     protected ListSelectionModel createSelectionModel() {
  113.     return new DefaultListSelectionModel();
  114.     }
  115.  
  116.     /**
  117.      * Convenient way to tell this JDirectoryPane to go up.
  118.      */
  119.     public Action getGoUpAction() {
  120.     return this.goUpAction;
  121.     }
  122.  
  123.     /**
  124.      * By default, the returned object is registered as a listener to
  125.      * this JDirectoryPane, waiting for a container to be double-clicked.
  126.      *
  127.      * <p>To defeat this behavior, do something like
  128.      * <pre><code>
  129.      * myDirPane.removeActionListener(myDirPane.getDefaultActionListener());
  130.      * </code></pre>
  131.      */
  132.     public ActionListener getDefaultActionListener() {
  133.     return this.defaultActionListener;
  134.     }
  135.  
  136.     /**
  137.      * To be called by UIs on doubleclick. 
  138.      */
  139.     public void performDoubleClick() {
  140.     TypedFile f = this.getSelectedFile();
  141.     if (f.getType().isContainer()) {
  142.         this.fireActionPerformed(this.getDoubleClickContainerCommand());
  143.     } else {
  144.         this.fireActionPerformed(this.getDoubleClickCommand());
  145.     }
  146.     }
  147.  
  148.     //
  149.     // Selection Helpers
  150.     //
  151.     // Some pass through to listSelectionModel, some are conveniences
  152.     // implemented here
  153.  
  154.     /**
  155.      * Returns the lead selected file or null
  156.      */
  157.     public TypedFile getSelectedFile() {
  158.     int index = this.getListSelectionModel().getLeadSelectionIndex();
  159.     if (index >= 0) {
  160.         return (TypedFile)this.getModel().getTypedFiles().elementAt(index);
  161.     } else {
  162.         return null;
  163.     }
  164.     }
  165.  
  166.     /**
  167.      * Returns the set of selected files, possibly empty, never null.
  168.      * Objects in vector are TypedFiles
  169.      */
  170.     public Vector getSelectedFiles() {
  171.     ListSelectionModel sel = this.getListSelectionModel();
  172.     int anchor = sel.getAnchorSelectionIndex();
  173.     int lead = sel.getLeadSelectionIndex();
  174.     Vector v = new Vector();
  175.  
  176.     if (anchor >= 0 && lead >= 0) {
  177.         Vector files = this.getModel().getTypedFiles();
  178.         int max = Math.max(anchor, lead);
  179.         for (int i = Math.min(anchor, lead); i <= max; i++) {
  180.         v.addElement(files.elementAt(i));
  181.         }
  182.     }
  183.  
  184.     return v;
  185.     }
  186.     
  187.     /**
  188.      * Returns true if nothing is selected This is a convenience
  189.      * method that just delegates to the listSelectionModel.
  190.      * 
  191.      * @return True if nothing is selected
  192.      * @see ListSelectionModel#isSelectionEmpty
  193.      * @see clearSelection
  194.      * @see ListSelectionModel#addListSelectionListener
  195.      */
  196.     public boolean isSelectionEmpty() {
  197.         return this.getListSelectionModel().isSelectionEmpty();
  198.     }
  199.  
  200.     /**
  201.      * Clears the selection - after calling this method
  202.      * isSelectionEmpty() will return true.  This is a convenience
  203.      * method that just delegates to the listSelectionModel.
  204.      * 
  205.      * @see ListSelectionModel#clearSelection
  206.      * @see #isSelectionEmpty
  207.      * @see ListSelectionModel#addListSelectionListener
  208.      */
  209.     public void clearSelection() {
  210.         this.getListSelectionModel().clearSelection();
  211.     }
  212.  
  213.     //
  214.     // Pass through to model
  215.     //
  216.  
  217.     public File getCurrentDirectory() {
  218.     return this.directoryModel.getCurrentDirectory();
  219.     }
  220.  
  221.     public void setCurrentDirectory(File dir) {
  222.     this.directoryModel.setCurrentDirectory(dir);
  223.     }
  224.  
  225.     public TypedFile getTypedFile(String path, String name) {
  226.     return this.directoryModel.getTypedFile(path, name);
  227.     }
  228.  
  229.     public TypedFile getTypedFile(String path) {
  230.     return this.directoryModel.getTypedFile(path);
  231.     }
  232.  
  233.     public Vector getTypedFiles() {
  234.     return this.directoryModel.getTypedFiles();
  235.     }
  236.  
  237.     public Vector getTypedFilesForDirectory(File dir) {
  238.     return this.directoryModel.getTypedFilesForDirectory(dir);
  239.     }
  240.  
  241.     public boolean canGoUp() {
  242.     return this.directoryModel.canGoUp();
  243.     }
  244.  
  245.     public void goUp() {
  246.     this.directoryModel.goUp();
  247.     }
  248.     
  249.     public void setHiddenRule(FileType rule) {
  250.     this.directoryModel.setHiddenRule(rule);
  251.     }
  252.  
  253.     public FileType getHiddenRule() {
  254.     return this.directoryModel.getHiddenRule();
  255.     }
  256.  
  257.     public void addKnownFileType(FileType type) {
  258.     this.directoryModel.addKnownFileType(type);
  259.     }
  260.  
  261.     public Enumeration enumerateKnownFileTypes() {
  262.     return this.directoryModel.enumerateKnownFileTypes();
  263.     }
  264.  
  265.     public Vector getKnownFileTypes() {
  266.     return this.directoryModel.getKnownFileTypes();
  267.     }
  268.  
  269.     public boolean isKnownFileType(FileType t) {
  270.     return this.directoryModel.isKnownFileType(t);
  271.     }
  272.  
  273.     public void setKnownFileTypes(FileType[] types) {
  274.     directoryModel.setKnownFileTypes(types);
  275.     }
  276.  
  277.     //
  278.     // Swinging UI
  279.     //
  280.  
  281.     public DirectoryPaneUI getUI() {
  282.     return (DirectoryPaneUI)ui;
  283.     }
  284.  
  285.     public void setUI(DirectoryPaneUI ui) {
  286.         super.setUI(ui);
  287.     }
  288.  
  289.     /**
  290.      * Called to replace the UI with the latest version from the 
  291.      * default UIFactory.
  292.      */
  293.     public void updateUI() {
  294.     setUI((DirectoryPaneUI)UIManager.getUI(this));
  295.     }
  296.  
  297.     /**
  298.      * @return "DirectoryPaneUI"
  299.      * @see JComponent#getUIClassID
  300.      * @see UIDefaults#getUI
  301.      */
  302.     public String getUIClassID() {
  303.     return "DirectoryPaneUI";
  304.     }
  305.  
  306.     //
  307.     // DirectoryModel
  308.     //
  309.     
  310.     public DirectoryModel getModel() {
  311.     return directoryModel;
  312.     }
  313.  
  314.     /**
  315.      * Note that this is protected. A JDirectoryPane does not
  316.      * like having its model switched out from under it.
  317.      */
  318.     protected void setModel(DirectoryModel newModel) 
  319.     {
  320.     DirectoryModel oldModel = getModel();
  321.  
  322.     if (oldModel != null) {
  323.         oldModel.removePropertyChangeListener(redirector);
  324.         redirector = null;
  325.     }
  326.  
  327.     directoryModel = newModel;
  328.  
  329.     if (newModel != null) {
  330.         redirector = createRedirector();
  331.         newModel.addPropertyChangeListener(redirector);
  332.     }
  333.     }
  334.  
  335.     //
  336.     // Selection Model
  337.     //
  338.  
  339.     public ListSelectionModel getListSelectionModel() {
  340.     return listSelectionModel;
  341.     }
  342.  
  343.     /**
  344.      * Note that this is protected. A JDirectoryPane does not
  345.      * like having its selection model switched out from under it.
  346.      */
  347.     protected void setSelectionModel(ListSelectionModel newModel) {
  348.     ListSelectionModel oldModel = getListSelectionModel();
  349.  
  350.     if (oldModel != null) {
  351.         oldModel.removeListSelectionListener(selListener);
  352.         selListener = null;
  353.     }
  354.     
  355.     listSelectionModel = newModel;
  356.  
  357.     if (newModel != null) {
  358.         selListener = createSelectionListener();
  359.         newModel.addListSelectionListener(selListener);
  360.     }
  361.     }
  362.  
  363.     /**
  364.      * Can be overridden by subclasses that want to specialize
  365.      * listening to property events from the model
  366.      */
  367.     protected Redirector createRedirector() {
  368.     return new Redirector();
  369.     }
  370.  
  371.     /**
  372.      * Serves as the PropertyChangeListener on this JDirectoryPane's
  373.      * DirectoryModel.
  374.      */
  375.     protected class Redirector implements PropertyChangeListener {
  376.     /**
  377.      * Clear selection if we've changed directories.  Rebroadcast
  378.      * all events with this JDirectoryPane as the source.
  379.      */
  380.         public void propertyChange(PropertyChangeEvent evt) {
  381.         if (evt.getPropertyName() == "currentDirectory") {
  382.         getListSelectionModel().clearSelection();
  383.         }
  384.         /*
  385.           firePropertyChange(evt.getPropertyName(),
  386.           evt.getOldValue(),
  387.           evt.getNewValue());
  388.           */
  389.     }
  390.     }
  391.  
  392.     protected SelListener createSelectionListener() {
  393.     return new SelListener();
  394.     }
  395.  
  396.     protected class SelListener implements ListSelectionListener {
  397.     /**
  398.      * If the event isn't adjusting, fire my action
  399.      */
  400.     public void valueChanged(ListSelectionEvent evt) {
  401.         if (!evt.getValueIsAdjusting()) {
  402.         fireActionPerformed(command);
  403.         }
  404.     }
  405.     }
  406.  
  407.     /**
  408.      * Adds the specified action listener to receive action events
  409.      * from this JDirectoryPane
  410.      *
  411.      * @param l the action listener
  412.      */ 
  413.     public synchronized void addActionListener(ActionListener l) {
  414.     listenerList.add(ActionListener.class, l);
  415.     }
  416.  
  417.     /**
  418.      * Removes the specified action listener so that it no longer
  419.      * receives action events from this JDirectoryPane
  420.      *
  421.      * @param l the action listener 
  422.      */ 
  423.     public synchronized void removeActionListener(ActionListener l) {
  424.     listenerList.remove(ActionListener.class, l);
  425.     }
  426.  
  427.     /*
  428.      * Notify all listeners that have registered interest for
  429.      * notification on this event type.  The event instance 
  430.      * is lazily created using the parameters passed into 
  431.      * the fire method.
  432.      * @see EventListenerList
  433.      */
  434.     protected void fireActionPerformed(String command) {
  435.     // Guaranteed to return a non-null array
  436.     Object[] listeners = listenerList.getListenerList();
  437.     ActionEvent e = null;
  438.     // Process the listeners last to first, notifying
  439.     // those that are interested in this event
  440.     for (int i = listeners.length-2; i>=0; i-=2) {
  441.         if (listeners[i]==ActionListener.class) {
  442.         // Lazily create the event:
  443.         if (e == null) {
  444.             e = new ActionEvent(this,
  445.                     ActionEvent.ACTION_PERFORMED,
  446.                     command);
  447.         }
  448.         ((ActionListener)listeners[i+1]).actionPerformed(e);
  449.         }           
  450.     }
  451.     }
  452.  
  453.     /**
  454.      * Sets the command string used for general action events, dispatched on
  455.      * selection change.
  456.      *
  457.      * @param command the command string
  458.      */
  459.     public void setActionCommand(String command) {
  460.     String oldCommand = this.command;
  461.     this.command = command;
  462.     this.firePropertyChange("actionCommand", oldCommand, command);
  463.     }
  464.  
  465.     public String getActionCommand() {
  466.     return command;
  467.     }
  468.  
  469.     /**
  470.      * Sets the command string used for action events dispatched on
  471.      * double click of non-containers
  472.      *
  473.      * @param command the command string
  474.      */
  475.     public void setDoubleClickCommand(String command) {
  476.     String oldCommand = this.doubleClickCommand;
  477.     this.doubleClickCommand = command;
  478.     this.firePropertyChange("doubleClickCommand", oldCommand, command);
  479.     }
  480.  
  481.     public String getDoubleClickCommand() {
  482.     return doubleClickCommand;
  483.     }
  484.  
  485.     /**
  486.      * Sets the command string used for action events dispatched on
  487.      * double click of containers
  488.      *
  489.      * @param command the command string
  490.      */
  491.     public void setDoubleClickContainerCommand(String command) {
  492.     String oldCommand = this.doubleClickContainerCommand;
  493.     this.doubleClickContainerCommand = command;
  494.     this.firePropertyChange("doubleClickContainerCommand", oldCommand,
  495.                 command);
  496.     }
  497.  
  498.     public String getDoubleClickContainerCommand() {
  499.     return doubleClickContainerCommand;
  500.     }
  501.  
  502.     /**
  503.      * The Action object that implements an upward move to the directory
  504.      * that contains this one.
  505.      * <p>
  506.      * Warning: serialized objects of this class will not be compatible with
  507.      * future swing releases.  The current serialization support is appropriate
  508.      * for short term storage or RMI between Swing1.0 applications.  It will
  509.      * not be possible to load serialized Swing1.0 objects with future releases
  510.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  511.      * baseline for the serialized form of Swing objects.
  512.      */
  513.     protected class GoUpAction extends AbstractAction {
  514.     protected GoUpAction() {
  515.         super("Go Up");
  516.     }
  517.     public void actionPerformed(ActionEvent ignored) {
  518.         goUp();
  519.     }
  520.     }
  521.  
  522.     protected class DefaultActionListener implements ActionListener {
  523.     public void actionPerformed(ActionEvent e) {
  524.         String command = e.getActionCommand();
  525.         if (command != null &&
  526.         command.equals(getDoubleClickContainerCommand())) {
  527.         setCurrentDirectory(getSelectedFile());
  528.         }
  529.     }
  530.     }
  531.  
  532. /// 
  533. /// Accessibility Support 
  534. ///
  535.  
  536.     /** 
  537.      * Get the AccessibleContext of this object 
  538.      *
  539.      * @return the AccessibleContext of this object
  540.      */
  541.     public AccessibleContext getAccessibleContext() {
  542.     if (accessibleContext == null) {
  543.         accessibleContext = new AccessibleJDirectoryPane();
  544.     }
  545.     return accessibleContext;
  546.     }
  547.  
  548.     /**
  549.      * The class used to obtain the accessible role for this object.
  550.      * <p>
  551.      * Warning: serialized objects of this class will not be compatible with
  552.      * future swing releases.  The current serialization support is appropriate
  553.      * for short term storage or RMI between Swing1.0 applications.  It will
  554.      * not be possible to load serialized Swing1.0 objects with future releases
  555.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  556.      * baseline for the serialized form of Swing objects.
  557.      */
  558.     protected class AccessibleJDirectoryPane extends AccessibleJComponent {
  559.  
  560.         /**
  561.          * Get the role of this object.
  562.          *
  563.          * @return an instance of AccessibleRole describing the role of the 
  564.      * object
  565.          * @see AccessibleRole
  566.          */
  567.         public AccessibleRole getAccessibleRole() {
  568.             return AccessibleRole.DIRECTORY_PANE;
  569.         }
  570.  
  571.     }  // AccessibleJDirectoryPane
  572. }
  573.