/* * ShellListView.java * * Created on April 20, 2002, 11:29 PM */ package kiyut.swing.shell.shelllistview; import java.io.File; import java.util.List; import java.util.ArrayList; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; import javax.swing.filechooser.FileSystemView; /** ShellListView is a component which show the file system * it have 4 view: detail, list, icon, thumbnail * * @version 1.0 * @author tonny */ public class ShellListView extends JComponent { /** the detail view style */ public static final int VS_DETAIL = 0; /** the list view style */ public static final int VS_LIST = 1; /** the icon view style */ public static final int VS_ICON = 2; /** the thumbnail view style */ public static final int VS_THUMBNAIL = 3; /** the data model of <code>ShellListView</code> */ protected ShellListViewModel dataModel; /** the selection model of <code>ShellListView</code> */ protected ShellListViewSelectionModel selectionModel; /** the scroll pane of <code>ShellListView</code> */ protected JScrollPane scrollPane; /** the detail view of <code>ShellListView</code> */ protected DetailView detailView; /** the list view of <code>ShellListView</code> */ protected ListView listView; /** the icon view of <code>ShellListView</code> */ protected IconView iconView; /** the thumbnail view of <code>ShellListView</code> */ protected ThumbnailView thumbnailView; /** the view style of <code>ShellListView</code> */ protected int viewStyle; /** Constructs a <code>ShellListView</code> with all default values */ public ShellListView() { this(FileSystemView.getFileSystemView().getHomeDirectory(),FileSystemView.getFileSystemView(),true,VS_DETAIL,true); } /** Constructs a <code>ShellListViewModel</code> and initialize with the passing parameter * @param dir start directory * @param fsv fileSystemView * @param useFileHiding the boolean value that determines whether file hiding is turned on * @param viewStyle VS_DETAIL,VS_LIST,VS_ICON,VS_THUMBNAIL * @param thumbnailEnabled the boolean value that determines whether the thumbnail view is enabled * @see ThumbnailView#setEnabled(boolean) */ public ShellListView(File dir, FileSystemView fsv, boolean useFileHiding, int viewStyle, boolean thumbnailEnabled) { ViewMouseHandler viewMouseHandler = new ViewMouseHandler(); ViewKeyHandler viewKeyHandler = new ViewKeyHandler(); dataModel = new ShellListViewModel(fsv); selectionModel = new ShellListViewSelectionModel(dataModel); detailView = new DetailView(dataModel); detailView.setSelectionModel(selectionModel); detailView.addMouseListener(viewMouseHandler); detailView.addKeyListener(viewKeyHandler); listView = new ListView(dataModel); listView.setSelectionModel(selectionModel); listView.addMouseListener(viewMouseHandler); listView.addKeyListener(viewKeyHandler); iconView = new IconView(dataModel); iconView.setSelectionModel(selectionModel); iconView.addMouseListener(viewMouseHandler); iconView.addKeyListener(viewKeyHandler); thumbnailView = new ThumbnailView(dataModel); thumbnailView.setSelectionModel(selectionModel); thumbnailView.setEnabled(thumbnailEnabled); thumbnailView.addMouseListener(viewMouseHandler); thumbnailView.addKeyListener(viewKeyHandler); dataModel.addListDataListener(new javax.swing.event.ListDataListener() { public void contentsChanged(ListDataEvent evt) { onContentsChanged(evt); } public void intervalAdded(ListDataEvent evt) { /* do nothing */ } public void intervalRemoved(ListDataEvent evt) { /* do nothing */ } }); scrollPane = new JScrollPane(); setFileHidingEnabled(useFileHiding); setViewStyle(viewStyle); setBackground(UIManager.getColor("List.background")); setForeground(UIManager.getColor("List.foreground")); setFont(UIManager.getFont("Table.font")); scrollPane.getViewport().setBackground(getBackground()); setLayout(new BorderLayout()); add(scrollPane,BorderLayout.CENTER); refresh(); //updateUI(); } /** {@inheritDoc} */ /*public void paintComponent(Graphics g) { super.paintComponent(g); //scrollPane.getViewport().setBackground(getBackground()); }*/ /** Returns the <code>ShellListViewModel</code> that provides the data displayed by this component. * @return the <code>ShellListViewModel</code> that provides the data displayed by this component. */ public ShellListViewModel getModel() { return dataModel; } /** Returns the last selected index. * This is a convenience method which delegates to ShellListViewSelectionModel. * @return the selected index or -1 if selection is empty and value is adjusting * @see #getLastSelectedFile */ public int getLastSelectedIndex() { return selectionModel.getLastSelectedIndex(); } /** Returns the last selected file. * This is a convenience method which delegates to ShellListViewSelectionModel. * @return the selected file or null if selection is empty and value is adjusting * @see #getLastSelectedIndex */ public File getLastSelectedFile() { return selectionModel.getLastSelectedFile(); } /** Return a list of selected files * This is a convenience method which delegates to ShellListViewSelectionModel. * @return a list of files or null if selection is empty and value is adjusting */ public List<File> getSelectedFiles() { return selectionModel.getSelectedFiles(); } /** Return a list of all files in the current directory * This is a convenience method which delegates to ShellListViewSelectionModel. * @return a list of all files or null if selection is empty and value is adjusting */ public List<File> getAllFiles() { return selectionModel.getAllFiles(); } /** refresh the data model */ public void refresh() { dataModel.refresh(); } /** Return the current view style. * @return One of the following constants defined in <code>ShellListView</code>: VS_DETAIL, VS_LIST, VS_ICON, VS_THUMBNAIL * * @see #setViewStyle(int) */ public int getViewStyle() { return this.viewStyle; } /** Sets the view style. * @param viewStyle One of the following constants defined in <code>ShellListView</code>: VS_DETAIL, VS_LIST, VS_ICON, VS_THUMBNAIL * @throws IllegalArgumentException if <code>viewStyle</code> is an illegal viewStyle * @see #getViewStyle() */ public void setViewStyle(int viewStyle) { if (viewStyle == VS_DETAIL) { scrollPane.setViewportView(detailView); this.viewStyle = viewStyle; } else if (viewStyle == VS_LIST) { scrollPane.setViewportView(listView); this.viewStyle = viewStyle; } else if (viewStyle == VS_ICON) { scrollPane.setViewportView(iconView); this.viewStyle = viewStyle; } else if (viewStyle == VS_THUMBNAIL) { scrollPane.setViewportView(thumbnailView); this.viewStyle = viewStyle; } else { throw new IllegalArgumentException("Illegal viewStyle"); } revalidate(); } /** Sets the current directory. Passing in <code>null</code> sets the <code>ShellListView</code> * to point to the user's default directory. * This default depends on the operating system. It is typically the "My Documents" folder on Windows, * and the user's home directory on Unix. * @param dir - the current directory to point to * * @see #getCurrentDirectory() * @see ShellListViewModel#setCurrentDirectory(java.io.File) * @see ShellListViewModel#getCurrentDirectory */ public void setCurrentDirectory(File dir) { dataModel.setCurrentDirectory(dir); } /** Returns the current directory. * @return the current directory * * @see #setCurrentDirectory(java.io.File) * @see ShellListViewModel#setCurrentDirectory(java.io.File) * @see ShellListViewModel#getCurrentDirectory */ public File getCurrentDirectory() { return dataModel.getCurrentDirectory(); } /** Sets file hiding on or off. If true, hidden files are not shown. * @param useFileHiding the boolean value that determines whether file hiding is turned on * * @see #isFileHidingEnabled() * @see ShellListViewModel#setFileHidingEnabled(boolean) */ public void setFileHidingEnabled(boolean useFileHiding) { dataModel.setFileHidingEnabled(useFileHiding); } /** Returns true if hidden files are not shown ; otherwise, returns false. * @return the status of the file hiding * * @see #setFileHidingEnabled(boolean) * @see ShellListViewModel#isFileHidingEnabled() */ public boolean isFileHidingEnabled() { return dataModel.isFileHidingEnabled(); } /** Return current ViewComponent * @return current ViewComponent * @see #getViewStyle() * @see #setViewStyle(int) */ public ViewComponent getViewComponent() { Component comp = scrollPane.getViewport().getView(); if (comp == null) { return null; } return (ViewComponent)comp; } /** Return the detail view of this component * @return detail view */ public DetailView getDetailView() { return detailView; } /** Return the list view of this component * @return list view */ public ListView getListView() { return listView; } /** Return the icon view of this component * @return icon view */ public IconView getIconView() { return iconView; } /** Return the ThumbnailView view of this component * @return thumbnail view */ public ThumbnailView getThumbnailView() { return thumbnailView; } /** Traves the data model based on selectionModel.getMaxSelectionIndex() */ protected void traves() { int index = selectionModel.getMaxSelectionIndex(); if ( (index>=0) && (dataModel.isTraversable(index)) ) { File file = dataModel.getFile(index); selectionModel.setValueIsAdjusting(true); dataModel.setCurrentDirectory(file); selectionModel.setValueIsAdjusting(false); dataModel.refresh(); } } /** This is only a convenience method to setTransferHandler to each view component. * {@inheritDoc} */ @Override public void setTransferHandler(TransferHandler newHandler) { detailView.setTransferHandler(newHandler); listView.setTransferHandler(newHandler); iconView.setTransferHandler(newHandler); thumbnailView.setTransferHandler(newHandler); } /** This is only a convenience method to setDragEnabled to each view component. * @param b true or false */ public void setDragEnabled(boolean b) { detailView.setDragEnabled(b); listView.setDragEnabled(b); iconView.setDragEnabled(b); thumbnailView.setDragEnabled(b); } /** * Removes a listener from the list that's notified each time a * change to the selection model model occurs. * * @param l the <code>ListSelectionListener</code> to be removed */ public void removeListSelectionListener(ListSelectionListener l) { selectionModel.removeListSelectionListener(l); } /** * Adds a listener to the list that's notified each time a change * to the selection model occurs. * * @param l the <code>ListSelectionListener</code> to be added */ public void addListSelectionListener(ListSelectionListener l) { selectionModel.addListSelectionListener(l); } /** * Adds a listener to the list that's notified each time a change * to the data model occurs. * * @param l the <code>ListDataListener</code> to be added */ public void addListDataListener(ListDataListener l) { dataModel.addListDataListener(l); } /** * Removes a listener from the list that's notified each time a * change to the data model occurs. * * @param l the <code>ListDataListener</code> to be removed */ public void removeListDataListener(ListDataListener l) { dataModel.removeListDataListener(l); } /** Adds a listener to the list that's notified when the each view editor stops, or cancels editing. * This is a convenience method that wrap each view cellEditor. * @param l CellEditorListener */ public void addCellEditorListener(CellEditorListener l) { detailView.getColumnModel().getColumn(0).getCellEditor().addCellEditorListener(l); listView.getCellEditor().addCellEditorListener(l); iconView.getCellEditor().addCellEditorListener(l); thumbnailView.getCellEditor().addCellEditorListener(l); } /** Removes a listener from the list that's notified of each view editor. * This is a convenience method that wrap each view cellEditor. * @param l CellEditorListener */ public void removeCellEditorListener(CellEditorListener l) { detailView.getColumnModel().getColumn(0).getCellEditor().removeCellEditorListener(l); listView.getCellEditor().removeCellEditorListener(l); iconView.getCellEditor().removeCellEditorListener(l); thumbnailView.getCellEditor().removeCellEditorListener(l); } /** Start editing cell programatically. It delegate to the current view * @param index the index of data model to be edited * @return true if editing is started; false otherwise * @throws IndexOutOfBoundsException if an invalid index was given */ public boolean editCellAt(int index) { boolean result = false; dataModel.setState(ShellListViewModel.EDIT); switch (viewStyle) { case VS_DETAIL: result = detailView.editCellAt(index,0); break; case VS_LIST: result = listView.editCellAt(index); break; case VS_ICON: result = iconView.editCellAt(index); break; case VS_THUMBNAIL: result = thumbnailView.editCellAt(index); break; default: result = false; break; } return result; } /** Overriden to redirect or forward to each view addMouseListener * It is a convenience method that wrap each view addMouseListener. * {@inheritDoc} */ public void addMouseListener(MouseListener l) { detailView.addMouseListener(l); listView.addMouseListener(l); iconView.addMouseListener(l); thumbnailView.addMouseListener(l); } /** Overriden to redirect or forward to each view removeMouseListener * It is a convenience method that wrap each view removeMouseListener. * {@inheritDoc} */ public void removeMouseListener(MouseListener l) { detailView.removeMouseListener(l); listView.removeMouseListener(l); iconView.removeMouseListener(l); thumbnailView.removeMouseListener(l); } /** Overriden to redirect or forward to each view addKeyListener * It is a convenience method that wrap each view addKeyListener. * {@inheritDoc} */ public void addKeyListener(KeyListener l) { detailView.addKeyListener(l); listView.addKeyListener(l); iconView.addKeyListener(l); thumbnailView.addKeyListener(l); } /** Overriden to redirect or forward to each view removeKeyListener * It is a convenience method that wrap each view removeKeyListener. * {@inheritDoc} */ public void removeKeyListener(KeyListener l) { detailView.removeKeyListener(l); listView.removeKeyListener(l); iconView.removeKeyListener(l); thumbnailView.removeKeyListener(l); } //////////////////////////////////////////// // EVENT HANDLER /////////////////////////////////////////// /** Sent when the contents of the data model has changed in * a way that's too complex to characterize. * For example, this is sent when an item has been replaced. * Index0 and index1 bracket the change. * @param e a <code>ListDataEvent</code> encapsulating the event information */ private void onContentsChanged(ListDataEvent e) { // changeAll if ((e.getIndex0()==ShellListViewModel.ALL_INDEX) && (e.getIndex1()==ShellListViewModel.ALL_INDEX) ){ return; } if (e.getIndex0() != e.getIndex1()) { return; } int index = e.getIndex1(); if (dataModel.getSize() >= index) { selectionModel.setSelectionInterval(index,index); } } private class ViewMouseHandler extends MouseInputAdapter { @Override public void mouseClicked(MouseEvent evt) { if (evt.getClickCount() == 2) { traves(); } } } private class ViewKeyHandler extends KeyAdapter { @Override public void keyPressed(KeyEvent evt) { if (evt.getKeyCode()==KeyEvent.VK_ENTER) { traves(); } } } }