< prev index next >
src/java.desktop/share/classes/sun/swing/FilePane.java
Print this page
*** 22,66 ****
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.swing;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.*;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.util.*;
import java.util.List;
! import java.util.concurrent.Callable;
import javax.accessibility.AccessibleContext;
import javax.swing.*;
import javax.swing.border.*;
! import javax.swing.event.*;
import javax.swing.filechooser.*;
import javax.swing.plaf.basic.*;
import javax.swing.table.*;
import javax.swing.text.*;
import sun.awt.shell.*;
/**
! * <b>WARNING:</b> This class is an implementation detail and is only
! * public so that it can be used by two packages. You should NOT consider
! * this public API.
* <p>
* This component is intended to be used in a subclass of
* javax.swing.plaf.basic.BasicFileChooserUI. It realies heavily on the
* implementation of BasicFileChooserUI, and is intended to be API compatible
* with earlier implementations of MetalFileChooserUI and WindowsFileChooserUI.
*
* @author Leif Samuelsson
*/
- @SuppressWarnings("serial") // JDK-implementation class
public class FilePane extends JPanel implements PropertyChangeListener {
// Constants for actions. These are used for the actions' ACTION_COMMAND_KEY
// and as keys in the action maps for FilePane and the corresponding UI classes
public static final String ACTION_APPROVE_SELECTION = "approveSelection";
--- 22,84 ----
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.swing;
+ import com.sun.java.swing.plaf.windows.WindowsFileChooserUI;
+ import com.sun.java.swing.plaf.windows.WindowsFileChooserUI.WindowsFileListUI;
+ import static com.sun.java.swing.plaf.windows.WindowsFileChooserUI.WindowsFileListUI.HOVER_CELL_PROPERTY;
+ import com.sun.java.swing.plaf.windows.WindowsFileChooserUI.WindowsFileTableUI;
import java.awt.*;
+ import static java.awt.Color.BLACK;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.*;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.util.*;
import java.util.List;
! import java.util.concurrent.ConcurrentHashMap;
! import java.util.concurrent.Executor;
! import java.util.concurrent.Executors;
! import java.util.function.Supplier;
! import java.util.stream.IntStream;
import javax.accessibility.AccessibleContext;
import javax.swing.*;
+ import static javax.swing.JList.HORIZONTAL_WRAP;
+ import static javax.swing.SwingConstants.BOTTOM;
+ import static javax.swing.SwingConstants.CENTER;
+ import static javax.swing.SwingConstants.LEFT;
+ import static javax.swing.SwingConstants.RIGHT;
import javax.swing.border.*;
! import javax.swing.event.ListDataEvent;
! import javax.swing.event.ListDataListener;
! import javax.swing.event.ListSelectionListener;
! import javax.swing.event.RowSorterEvent;
! import javax.swing.event.RowSorterListener;
! import javax.swing.event.TableModelEvent;
! import javax.swing.event.TableModelListener;
import javax.swing.filechooser.*;
import javax.swing.plaf.basic.*;
import javax.swing.table.*;
import javax.swing.text.*;
import sun.awt.shell.*;
/**
! * <b>WARNING:</b> This class is an implementation detail and is only public so
! * that it can be used by two packages. You should NOT consider this public API.
* <p>
* This component is intended to be used in a subclass of
* javax.swing.plaf.basic.BasicFileChooserUI. It realies heavily on the
* implementation of BasicFileChooserUI, and is intended to be API compatible
* with earlier implementations of MetalFileChooserUI and WindowsFileChooserUI.
*
* @author Leif Samuelsson
*/
public class FilePane extends JPanel implements PropertyChangeListener {
// Constants for actions. These are used for the actions' ACTION_COMMAND_KEY
// and as keys in the action maps for FilePane and the corresponding UI classes
public static final String ACTION_APPROVE_SELECTION = "approveSelection";
*** 70,90 ****
public static final String ACTION_CHANGE_TO_PARENT_DIRECTORY = "Go Up";
public static final String ACTION_NEW_FOLDER = "New Folder";
public static final String ACTION_VIEW_LIST = "viewTypeList";
public static final String ACTION_VIEW_DETAILS = "viewTypeDetails";
! private Action[] actions;
! // "enums" for setViewType()
! public static final int VIEWTYPE_LIST = 0;
! public static final int VIEWTYPE_DETAILS = 1;
! private static final int VIEWTYPE_COUNT = 2;
! private int viewType = -1;
! private JPanel[] viewPanels = new JPanel[VIEWTYPE_COUNT];
private JPanel currentViewPanel;
! private String[] viewTypeActionNames;
private String filesListAccessibleName = null;
private String filesDetailsAccessibleName = null;
private JPopupMenu contextMenu;
--- 88,176 ----
public static final String ACTION_CHANGE_TO_PARENT_DIRECTORY = "Go Up";
public static final String ACTION_NEW_FOLDER = "New Folder";
public static final String ACTION_VIEW_LIST = "viewTypeList";
public static final String ACTION_VIEW_DETAILS = "viewTypeDetails";
! public static enum ViewType {
! MEDIUM_ICONS("mediumIcons",
! /* listOrientation: */ HORIZONTAL_WRAP,
! /* horizTextPos: */ CENTER,
! /* vertTextPos: */ BOTTOM,
! /* prefSize: */ new Dimension(125, 75),
! /* horizAlign: */ CENTER,
! /* wrapFilename: */ true,
! /* largeIcons: */ true,
! /* fileMetaLines: */ false
! ),
! SMALL_ICONS("smallIcons",
! /* listOrientation: */ HORIZONTAL_WRAP,
! /* horizTextPos: */ RIGHT,
! /* vertTextPos: */ CENTER,
! /* prefSize: */ null,
! /* horizAlign: */ LEFT,
! /* wrapFilename: */ true,
! /* largeIcons: */ false,
! /* fileMetaLines: */ false
! ),
! LIST("list",
! /* listOrientation: */ JList.VERTICAL_WRAP,
! /* horizTextPos: */ RIGHT,
! /* vertTextPos: */ CENTER,
! /* prefSize: */ null,
! /* horizAlign: */ LEFT,
! /* wrapFilename: */ false,
! /* largeIcons: */ false,
! /* fileMetaLines: */ false
! ),
! DETAILS("details", null, RIGHT, CENTER, null, LEFT, false, false, false),
! TILES("tiles",
! /* listOrientation: */ JList.HORIZONTAL_WRAP,
! /* horizTextPos: */ RIGHT,
! /* vertTextPos: */ CENTER,
! /* prefSize: */ new Dimension(313, 66),
! /* horizAlign: */ LEFT,
! /* wrapFilename: */ false,
! /* largeIcons: */ true,
! /* fileMetaLines: */ true
! );
!
! private final String l10nKey;
! private final boolean isTable;
! private final Integer listOrientation;
! private final Integer horizTextPos;
! private final Integer vertTextPos;
! private final Dimension prefSize;
! private final Integer horizAlign;
! private final boolean wrapFilename;
! private final boolean largeIcons;
! private final boolean fileMetaLines;
!
! private ViewType(String l10nKey, Integer listOrientation,
! Integer horizTextPos, Integer vertTextPos, Dimension prefSize,
! Integer horizAlign, boolean wrapFilename, boolean largeIcons,
! boolean fileMetaLines) {
! this.listOrientation = listOrientation;
! this.l10nKey = l10nKey;
! this.isTable = listOrientation == null;
!
! this.horizTextPos = horizTextPos;
! this.vertTextPos = vertTextPos;
! this.prefSize = prefSize;
! this.horizAlign = horizAlign;
! this.wrapFilename = wrapFilename;
! this.largeIcons = largeIcons;
! this.fileMetaLines = fileMetaLines;
! }
!
! }
! private Action[] actions;
! private ViewType viewType;
! private Map<ViewType, JPanel> viewPanels = new EnumMap<>(ViewType.class);
private JPanel currentViewPanel;
! private final Map<ViewType, String> viewTypeActionNames = new EnumMap<>(ViewType.class);
private String filesListAccessibleName = null;
private String filesDetailsAccessibleName = null;
private JPopupMenu contextMenu;
*** 117,132 ****
timeFactor = (l != null) ? l : 1000L;
}
/**
* Moves the keyboard focus to the first element whose prefix matches
! * the sequence of alphanumeric keys pressed by the user with delay
! * less than value of <code>timeFactor</code>. Subsequent same key
! * presses move the keyboard focus to the next object that starts with
! * the same letter until another key is pressed, then it is treated
! * as the prefix with appropriate number of the same letters followed
! * by first typed another letter.
*/
public void keyTyped(KeyEvent e) {
BasicDirectoryModel model = getModel();
int rowCount = model.getSize();
--- 203,218 ----
timeFactor = (l != null) ? l : 1000L;
}
/**
* Moves the keyboard focus to the first element whose prefix matches
! * the sequence of alphanumeric keys pressed by the user with delay less
! * than value of <code>timeFactor</code>. Subsequent same key presses
! * move the keyboard focus to the next object that starts with the same
! * letter until another key is pressed, then it is treated as the prefix
! * with appropriate number of the same letters followed by first typed
! * another letter.
*/
public void keyTyped(KeyEvent e) {
BasicDirectoryModel model = getModel();
int rowCount = model.getSize();
*** 307,372 ****
protected BasicDirectoryModel getModel() {
return fileChooserUIAccessor.getModel();
}
! public int getViewType() {
return viewType;
}
! public void setViewType(int viewType) {
if (viewType == this.viewType) {
return;
}
! int oldValue = this.viewType;
this.viewType = viewType;
JPanel createdViewPanel = null;
Component newFocusOwner = null;
! switch (viewType) {
! case VIEWTYPE_LIST:
! if (viewPanels[viewType] == null) {
createdViewPanel = fileChooserUIAccessor.createList();
if (createdViewPanel == null) {
createdViewPanel = createList();
}
! list = findChildComponent(createdViewPanel, JList.class);
if (listSelectionModel == null) {
listSelectionModel = list.getSelectionModel();
if (detailsTable != null) {
detailsTable.setSelectionModel(listSelectionModel);
}
} else {
list.setSelectionModel(listSelectionModel);
}
}
! list.setLayoutOrientation(JList.VERTICAL_WRAP);
newFocusOwner = list;
- break;
-
- case VIEWTYPE_DETAILS:
- if (viewPanels[viewType] == null) {
- createdViewPanel = fileChooserUIAccessor.createDetailsView();
- if (createdViewPanel == null) {
- createdViewPanel = createDetailsView();
- }
-
- detailsTable = findChildComponent(createdViewPanel, JTable.class);
- detailsTable.setRowHeight(Math.max(detailsTable.getFont().getSize() + 4, 16 + 1));
- if (listSelectionModel != null) {
- detailsTable.setSelectionModel(listSelectionModel);
- }
- }
- newFocusOwner = detailsTable;
- break;
}
if (createdViewPanel != null) {
! viewPanels[viewType] = createdViewPanel;
recursivelySetInheritsPopupMenu(createdViewPanel, true);
}
boolean isFocusOwner = false;
--- 393,458 ----
protected BasicDirectoryModel getModel() {
return fileChooserUIAccessor.getModel();
}
! public ViewType getViewType() {
return viewType;
}
! public void setViewType(ViewType viewType) {
if (viewType == this.viewType) {
return;
}
! ViewType oldValue = this.viewType;
this.viewType = viewType;
JPanel createdViewPanel = null;
Component newFocusOwner = null;
! if (viewType.isTable) {
! if (viewPanels.get(viewType) == null) {
! createdViewPanel = fileChooserUIAccessor.createDetailsView();
! if (createdViewPanel == null) {
! createdViewPanel = createDetailsView();
! }
!
! detailsTable = (JTable) findChildComponent(createdViewPanel, JTable.class);
! assert detailsTable != null;
! detailsTable.setRowHeight(Math.max(detailsTable.getFont().getSize() + 4, 16 + 5));
! if(listSelectionModel == null) {
! listSelectionModel = detailsTable.getSelectionModel();
! if(list != null)
! list.setSelectionModel(listSelectionModel);
! }else
! detailsTable.setSelectionModel(listSelectionModel);
! }
! newFocusOwner = detailsTable;
! } else {
! if (viewPanels.get(viewType) == null) {
createdViewPanel = fileChooserUIAccessor.createList();
if (createdViewPanel == null) {
createdViewPanel = createList();
}
! list = (JList<?>) findChildComponent(createdViewPanel, JList.class);
if (listSelectionModel == null) {
listSelectionModel = list.getSelectionModel();
if (detailsTable != null) {
detailsTable.setSelectionModel(listSelectionModel);
}
} else {
list.setSelectionModel(listSelectionModel);
}
}
! list.setLayoutOrientation(viewType.listOrientation);
newFocusOwner = list;
}
if (createdViewPanel != null) {
! viewPanels.put(viewType, createdViewPanel);
recursivelySetInheritsPopupMenu(createdViewPanel, true);
}
boolean isFocusOwner = false;
*** 377,387 ****
isFocusOwner = owner == detailsTable || owner == list;
remove(currentViewPanel);
}
! currentViewPanel = viewPanels[viewType];
add(currentViewPanel, BorderLayout.CENTER);
if (isFocusOwner && newFocusOwner != null) {
newFocusOwner.requestFocusInWindow();
}
--- 463,473 ----
isFocusOwner = owner == detailsTable || owner == list;
remove(currentViewPanel);
}
! currentViewPanel = viewPanels.get(viewType);
add(currentViewPanel, BorderLayout.CENTER);
if (isFocusOwner && newFocusOwner != null) {
newFocusOwner.requestFocusInWindow();
}
*** 390,422 ****
repaint();
updateViewMenu();
firePropertyChange("viewType", oldValue, viewType);
}
- @SuppressWarnings("serial") // JDK-implementation class
class ViewTypeAction extends AbstractAction {
- private int viewType;
! ViewTypeAction(int viewType) {
! super(viewTypeActionNames[viewType]);
this.viewType = viewType;
! String cmd;
! switch (viewType) {
! case VIEWTYPE_LIST: cmd = ACTION_VIEW_LIST; break;
! case VIEWTYPE_DETAILS: cmd = ACTION_VIEW_DETAILS; break;
! default: cmd = (String)getValue(Action.NAME);
! }
! putValue(Action.ACTION_COMMAND_KEY, cmd);
}
public void actionPerformed(ActionEvent e) {
setViewType(viewType);
}
}
! public Action getViewTypeAction(int viewType) {
return new ViewTypeAction(viewType);
}
private static void recursivelySetInheritsPopupMenu(Container container, boolean b) {
if (container instanceof JComponent) {
--- 476,502 ----
repaint();
updateViewMenu();
firePropertyChange("viewType", oldValue, viewType);
}
class ViewTypeAction extends AbstractAction {
! private final ViewType viewType;
!
! ViewTypeAction(ViewType viewType) {
! super(viewTypeActionNames.get(viewType));
this.viewType = viewType;
! putValue(Action.ACTION_COMMAND_KEY, viewType.l10nKey);
}
public void actionPerformed(ActionEvent e) {
setViewType(viewType);
}
}
! public Action getViewTypeAction(ViewType viewType) {
return new ViewTypeAction(viewType);
}
private static void recursivelySetInheritsPopupMenu(Container container, boolean b) {
if (container instanceof JComponent) {
*** 435,457 ****
listViewBackground = UIManager.getColor("FileChooser.listViewBackground");
listViewWindowsStyle = UIManager.getBoolean("FileChooser.listViewWindowsStyle");
readOnly = UIManager.getBoolean("FileChooser.readOnly");
// TODO: On windows, get the following localized strings from the OS
!
! viewMenuLabelText =
! UIManager.getString("FileChooser.viewMenuLabelText", l);
! refreshActionLabelText =
! UIManager.getString("FileChooser.refreshActionLabelText", l);
! newFolderActionLabelText =
! UIManager.getString("FileChooser.newFolderActionLabelText", l);
!
! viewTypeActionNames = new String[VIEWTYPE_COUNT];
! viewTypeActionNames[VIEWTYPE_LIST] =
! UIManager.getString("FileChooser.listViewActionLabelText", l);
! viewTypeActionNames[VIEWTYPE_DETAILS] =
! UIManager.getString("FileChooser.detailsViewActionLabelText", l);
kiloByteString = UIManager.getString("FileChooser.fileSizeKiloBytes", l);
megaByteString = UIManager.getString("FileChooser.fileSizeMegaBytes", l);
gigaByteString = UIManager.getString("FileChooser.fileSizeGigaBytes", l);
fullRowSelection = UIManager.getBoolean("FileView.fullRowSelection");
--- 515,537 ----
listViewBackground = UIManager.getColor("FileChooser.listViewBackground");
listViewWindowsStyle = UIManager.getBoolean("FileChooser.listViewWindowsStyle");
readOnly = UIManager.getBoolean("FileChooser.readOnly");
// TODO: On windows, get the following localized strings from the OS
! viewMenuLabelText
! = UIManager.getString("FileChooser.viewMenuLabelText", l);
! refreshActionLabelText
! = UIManager.getString("FileChooser.refreshActionLabelText", l);
! newFolderActionLabelText
! = UIManager.getString("FileChooser.newFolderActionLabelText", l);
!
! for (ViewType viewType : ViewType.values()) {
! final String key = "FileChooser." + viewType.l10nKey
! + "ViewActionLabel.textAndMnemonic";
! viewTypeActionNames.put(viewType,
! UIManager.getString(key, l));
! }
kiloByteString = UIManager.getString("FileChooser.fileSizeKiloBytes", l);
megaByteString = UIManager.getString("FileChooser.fileSizeMegaBytes", l);
gigaByteString = UIManager.getString("FileChooser.fileSizeGigaBytes", l);
fullRowSelection = UIManager.getBoolean("FileView.fullRowSelection");
*** 463,474 ****
renameErrorText = UIManager.getString("FileChooser.renameErrorText", l);
renameErrorFileExistsText = UIManager.getString("FileChooser.renameErrorFileExistsText", l);
}
/**
! * Fetches the command list for the FilePane. These commands
! * are useful for binding to events, such as in a keymap.
*
* @return the command list
*/
public Action[] getActions() {
if (actions == null) {
--- 543,554 ----
renameErrorText = UIManager.getString("FileChooser.renameErrorText", l);
renameErrorFileExistsText = UIManager.getString("FileChooser.renameErrorFileExistsText", l);
}
/**
! * Fetches the command list for the FilePane. These commands are useful for
! * binding to events, such as in a keymap.
*
* @return the command list
*/
public Action[] getActions() {
if (actions == null) {
*** 505,515 ****
getFileChooser().rescanCurrentDirectory();
}
}
public boolean isEnabled() {
! String cmd = (String)getValue(Action.ACTION_COMMAND_KEY);
if (cmd == ACTION_CANCEL) {
return getFileChooser().isEnabled();
} else if (cmd == ACTION_EDIT_FILE_NAME) {
return !readOnly && getFileChooser().isEnabled();
} else {
--- 585,595 ----
getFileChooser().rescanCurrentDirectory();
}
}
public boolean isEnabled() {
! String cmd = (String) getValue(Action.ACTION_COMMAND_KEY);
if (cmd == ACTION_CANCEL) {
return getFileChooser().isEnabled();
} else if (cmd == ACTION_EDIT_FILE_NAME) {
return !readOnly && getFileChooser().isEnabled();
} else {
*** 535,549 ****
}
action = getNewFolderAction();
if (action != null) {
actionList.add(action);
}
! action = getViewTypeAction(VIEWTYPE_LIST);
if (action != null) {
actionList.add(action);
}
! action = getViewTypeAction(VIEWTYPE_DETAILS);
if (action != null) {
actionList.add(action);
}
actions = actionList.toArray(new Action[actionList.size()]);
}
--- 615,629 ----
}
action = getNewFolderAction();
if (action != null) {
actionList.add(action);
}
! action = getViewTypeAction(ViewType.LIST);
if (action != null) {
actionList.add(action);
}
! action = getViewTypeAction(ViewType.DETAILS);
if (action != null) {
actionList.add(action);
}
actions = actionList.toArray(new Action[actionList.size()]);
}
*** 553,576 ****
protected void createActionMap() {
addActionsToMap(super.getActionMap(), getActions());
}
-
public static void addActionsToMap(ActionMap map, Action[] actions) {
if (map != null && actions != null) {
for (Action a : actions) {
! String cmd = (String)a.getValue(Action.ACTION_COMMAND_KEY);
if (cmd == null) {
! cmd = (String)a.getValue(Action.NAME);
}
map.put(cmd, a);
}
}
}
-
private void updateListRowCount(JList<?> list) {
if (smallIconsView) {
list.setVisibleRowCount(getModel().getSize() / 3);
} else {
list.setVisibleRowCount(-1);
--- 633,654 ----
protected void createActionMap() {
addActionsToMap(super.getActionMap(), getActions());
}
public static void addActionsToMap(ActionMap map, Action[] actions) {
if (map != null && actions != null) {
for (Action a : actions) {
! String cmd = (String) a.getValue(Action.ACTION_COMMAND_KEY);
if (cmd == null) {
! cmd = (String) a.getValue(Action.NAME);
}
map.put(cmd, a);
}
}
}
private void updateListRowCount(JList<?> list) {
if (smallIconsView) {
list.setVisibleRowCount(getModel().getSize() / 3);
} else {
list.setVisibleRowCount(-1);
*** 578,589 ****
}
public JPanel createList() {
JPanel p = new JPanel(new BorderLayout());
final JFileChooser fileChooser = getFileChooser();
-
- @SuppressWarnings("serial") // anonymous class
final JList<Object> list = new JList<Object>() {
public int getNextMatch(String prefix, int startIndex, Position.Bias bias) {
ListModel<?> model = getModel();
int max = model.getSize();
if (prefix == null || startIndex < 0 || startIndex >= max) {
--- 656,665 ----
*** 597,607 ****
--- 673,690 ----
return i;
}
}
return -1;
}
+
+ {
+ if (listViewWindowsStyle) {
+ setUI(new WindowsFileListUI(getFileChooser()));
+ }
+ }
};
+
list.setCellRenderer(new FileRenderer());
list.setLayoutOrientation(JList.VERTICAL_WRAP);
// 4835633 : tell BasicListUI that this is a file list
list.putClientProperty("List.isFileList", Boolean.TRUE);
*** 641,651 ****
JScrollPane scrollpane = new JScrollPane(list);
if (listViewBackground != null) {
list.setBackground(listViewBackground);
}
! if (listViewBorder != null) {
scrollpane.setBorder(listViewBorder);
}
list.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, filesListAccessibleName);
--- 724,736 ----
JScrollPane scrollpane = new JScrollPane(list);
if (listViewBackground != null) {
list.setBackground(listViewBackground);
}
! if (listViewWindowsStyle) {
! scrollpane.setBorder(null);
! } else if (listViewBorder != null) {
scrollpane.setBorder(listViewBorder);
}
list.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY, filesListAccessibleName);
*** 654,664 ****
}
/**
* This model allows for sorting JList
*/
- @SuppressWarnings("serial") // JDK-implementation class
private class SortableListModel extends AbstractListModel<Object>
implements TableModelListener, RowSorterListener {
public SortableListModel() {
getDetailsTableModel().addTableModelListener(this);
--- 739,748 ----
*** 682,699 ****
fireContentsChanged(this, 0, getSize());
}
}
private DetailsTableModel getDetailsTableModel() {
! if(detailsTableModel == null) {
detailsTableModel = new DetailsTableModel(getFileChooser());
}
return detailsTableModel;
}
- @SuppressWarnings("serial") // JDK-implementation class
class DetailsTableModel extends AbstractTableModel implements ListDataListener {
JFileChooser chooser;
BasicDirectoryModel directoryModel;
ShellFolderColumnInfo[] columns;
int[] columnMap;
--- 766,783 ----
fireContentsChanged(this, 0, getSize());
}
}
private DetailsTableModel getDetailsTableModel() {
! if (detailsTableModel == null) {
detailsTableModel = new DetailsTableModel(getFileChooser());
}
return detailsTableModel;
}
class DetailsTableModel extends AbstractTableModel implements ListDataListener {
+
JFileChooser chooser;
BasicDirectoryModel directoryModel;
ShellFolderColumnInfo[] columns;
int[] columnMap;
*** 716,727 ****
}
}
ShellFolderColumnInfo[] allColumns = ShellFolder.getFolderColumns(dir);
! ArrayList<ShellFolderColumnInfo> visibleColumns =
! new ArrayList<ShellFolderColumnInfo>();
columnMap = new int[allColumns.length];
for (int i = 0; i < allColumns.length; i++) {
ShellFolderColumnInfo column = allColumns[i];
if (column.isVisible()) {
columnMap[visibleColumns.size()] = i;
--- 800,811 ----
}
}
ShellFolderColumnInfo[] allColumns = ShellFolder.getFolderColumns(dir);
! ArrayList<ShellFolderColumnInfo> visibleColumns
! = new ArrayList<ShellFolderColumnInfo>();
columnMap = new int[allColumns.length];
for (int i = 0; i < allColumns.length; i++) {
ShellFolderColumnInfo column = allColumns[i];
if (column.isVisible()) {
columnMap[visibleColumns.size()] = i;
*** 807,824 ****
if (FilePane.this.getModel().renameFile(f, f2)) {
if (fsv.isParent(chooser.getCurrentDirectory(), f2)) {
// The setSelectedFile method produces a new setValueAt invocation while the JTable
// is editing. Postpone file selection to be sure that edit mode of the JTable
// is completed
! SwingUtilities.invokeLater(new Runnable() {
! public void run() {
if (chooser.isMultiSelectionEnabled()) {
chooser.setSelectedFiles(new File[]{f2});
} else {
chooser.setSelectedFile(f2);
}
- }
});
} else {
// Could be because of delay in updating Desktop folder
// chooser.setSelectedFile(null);
}
--- 891,906 ----
if (FilePane.this.getModel().renameFile(f, f2)) {
if (fsv.isParent(chooser.getCurrentDirectory(), f2)) {
// The setSelectedFile method produces a new setValueAt invocation while the JTable
// is editing. Postpone file selection to be sure that edit mode of the JTable
// is completed
! SwingUtilities.invokeLater(() -> {
if (chooser.isMultiSelectionEnabled()) {
chooser.setSelectedFiles(new File[]{f2});
} else {
chooser.setSelectedFile(f2);
}
});
} else {
// Could be because of delay in updating Desktop folder
// chooser.setSelectedFile(null);
}
*** 863,873 ****
public ShellFolderColumnInfo[] getColumns() {
return columns;
}
}
-
private void updateDetailsColumnModel(JTable table) {
if (table != null) {
ShellFolderColumnInfo[] columns = detailsTableModel.getColumns();
TableColumnModel columnModel = new DefaultTableColumnModel();
--- 945,954 ----
*** 898,907 ****
--- 979,990 ----
if (!readOnly && columnModel.getColumnCount() > COLUMN_FILENAME) {
columnModel.getColumn(COLUMN_FILENAME).
setCellEditor(getDetailsTableCellEditor());
}
+ columnModel.getColumn(0).setPreferredWidth(160); // TODO néha 250 körüli (pl. dl mappa)
+
table.setColumnModel(columnModel);
}
}
private DetailsTableRowSorter getRowSorter() {
*** 913,928 ****
private class DetailsTableRowSorter extends TableRowSorter<TableModel> {
public DetailsTableRowSorter() {
SorterModelWrapper modelWrapper = new SorterModelWrapper();
setModelWrapper(modelWrapper);
! modelWrapper.getModel().addTableModelListener(
! new TableModelListener() {
! @Override
! public void tableChanged(TableModelEvent e) {
modelStructureChanged();
- }
});
}
public void updateComparators(ShellFolderColumnInfo [] columns) {
for (int i = 0; i < columns.length; i++) {
--- 996,1007 ----
private class DetailsTableRowSorter extends TableRowSorter<TableModel> {
public DetailsTableRowSorter() {
SorterModelWrapper modelWrapper = new SorterModelWrapper();
setModelWrapper(modelWrapper);
! modelWrapper.getModel().addTableModelListener(evt -> {
modelStructureChanged();
});
}
public void updateComparators(ShellFolderColumnInfo [] columns) {
for (int i = 0; i < columns.length; i++) {
*** 934,948 ****
}
}
@Override
public void sort() {
! ShellFolder.invoke(new Callable<Void>() {
! public Void call() {
DetailsTableRowSorter.super.sort();
return null;
- }
});
}
public void modelStructureChanged() {
super.modelStructureChanged();
--- 1013,1025 ----
}
}
@Override
public void sort() {
! ShellFolder.invoke(() -> {
DetailsTableRowSorter.super.sort();
return null;
});
}
public void modelStructureChanged() {
super.modelStructureChanged();
*** 975,984 ****
--- 1052,1062 ----
/**
* This class sorts directories before files, comparing directory to
* directory and file to file using the wrapped comparator.
*/
private class DirectoriesFirstComparatorWrapper implements Comparator<File> {
+
private Comparator<Object> comparator;
private int column;
@SuppressWarnings("unchecked")
public DirectoriesFirstComparatorWrapper(int column, Comparator<?> comparator) {
*** 1068,1092 ****
public Insets getInsets(Insets i) {
// Provide some space between columns
i = super.getInsets(i);
i.left += 4;
i.right += 4;
return i;
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
! if ((table.convertColumnIndexToModel(column) != COLUMN_FILENAME ||
! (listViewWindowsStyle && !table.isFocusOwner())) &&
! !fullRowSelection) {
isSelected = false;
}
super.getTableCellRendererComponent(table, value, isSelected,
hasFocus, row, column);
setIcon(null);
int modelColumn = table.convertColumnIndexToModel(column);
ShellFolderColumnInfo columnInfo = detailsTableModel.getColumns()[modelColumn];
--- 1146,1192 ----
public Insets getInsets(Insets i) {
// Provide some space between columns
i = super.getInsets(i);
i.left += 4;
i.right += 4;
+ if (listViewWindowsStyle) {
+ i.bottom++;
+ }
return i;
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
! if ((table.convertColumnIndexToModel(column) != COLUMN_FILENAME
! || (listViewWindowsStyle && !table.isFocusOwner()))
! && !fullRowSelection) {
isSelected = false;
}
super.getTableCellRendererComponent(table, value, isSelected,
hasFocus, row, column);
+ Object hoverCelllValue = table.getClientProperty(WindowsFileListUI.HOVER_CELL_PROPERTY);
+ if(!isSelected)
+ if(hoverCelllValue instanceof Integer && row == (int) hoverCelllValue)
+ setBackground(WindowsFileListUI.ITEM_HOVERED_COLOR);
+ else
+ setBackground(null);
+
+ if(isSelected) {
+ Border border = column == 0 ?
+ WindowsFileTableUI.ITEM_SELECTED_BORDER_LEFT_CELL:
+ column == table.getModel().getColumnCount()-1?
+ WindowsFileTableUI.ITEM_SELECTED_BORDER_RIGHT_CELL:
+ WindowsFileTableUI.ITEM_SELECTED_BORDER_MID_CELL;
+
+ setBorder(border);
+ }
+
+ setForeground(column == 0 ? BLACK : listViewWindowsStyle ?
+ SystemColor.controlDkShadow : new Color(150, 150, 150));
setIcon(null);
int modelColumn = table.convertColumnIndexToModel(column);
ShellFolderColumnInfo columnInfo = detailsTableModel.getColumns()[modelColumn];
*** 1107,1117 ****
text = "";
} else if (value instanceof File) {
File file = (File)value;
text = chooser.getName(file);
! Icon icon = chooser.getIcon(file);
setIcon(icon);
} else if (value instanceof Long) {
long len = ((Long) value) / 1024L;
if (listViewWindowsStyle) {
--- 1207,1218 ----
text = "";
} else if (value instanceof File) {
File file = (File)value;
text = chooser.getName(file);
! Icon icon = new FileIcon(file, () -> chooser.getIcon(file),
! table, 16, 16);
setIcon(icon);
} else if (value instanceof Long) {
long len = ((Long) value) / 1024L;
if (listViewWindowsStyle) {
*** 1144,1155 ****
public JPanel createDetailsView() {
final JFileChooser chooser = getFileChooser();
JPanel p = new JPanel(new BorderLayout());
- @SuppressWarnings("serial") // anonymous class
final JTable detailsTable = new JTable(getDetailsTableModel()) {
// Handle Escape key events here
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE && getCellEditor() == null) {
// We are not editing, forward to filechooser.
chooser.dispatchEvent(e);
--- 1245,1261 ----
public JPanel createDetailsView() {
final JFileChooser chooser = getFileChooser();
JPanel p = new JPanel(new BorderLayout());
final JTable detailsTable = new JTable(getDetailsTableModel()) {
+
+ {
+ if(listViewWindowsStyle)
+ setUI(new WindowsFileChooserUI.WindowsFileTableUI(chooser));
+ }
+
// Handle Escape key events here
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE && getCellEditor() == null) {
// We are not editing, forward to filechooser.
chooser.dispatchEvent(e);
*** 1171,1189 ****
detailsTable.setRowSorter(getRowSorter());
detailsTable.setAutoCreateColumnsFromModel(false);
detailsTable.setComponentOrientation(chooser.getComponentOrientation());
detailsTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
detailsTable.setShowGrid(false);
detailsTable.putClientProperty("JTable.autoStartsEdit", Boolean.FALSE);
detailsTable.addKeyListener(detailsKeyListener);
! Font font = list.getFont();
! detailsTable.setFont(font);
! detailsTable.setIntercellSpacing(new Dimension(0, 0));
TableCellRenderer headerRenderer =
new AlignableTableHeaderRenderer(detailsTable.getTableHeader().getDefaultRenderer());
detailsTable.getTableHeader().setDefaultRenderer(headerRenderer);
TableCellRenderer cellRenderer = new DetailsTableCellRenderer(chooser);
detailsTable.setDefaultRenderer(Object.class, cellRenderer);
// So that drag can be started on a mouse press
--- 1277,1304 ----
detailsTable.setRowSorter(getRowSorter());
detailsTable.setAutoCreateColumnsFromModel(false);
detailsTable.setComponentOrientation(chooser.getComponentOrientation());
detailsTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
detailsTable.setShowGrid(false);
+ detailsTable.putClientProperty("Table.isFileList", Boolean.TRUE);
detailsTable.putClientProperty("JTable.autoStartsEdit", Boolean.FALSE);
detailsTable.addKeyListener(detailsKeyListener);
+ if(listViewWindowsStyle) {
+ detailsTable.setSelectionBackground(WindowsFileListUI.ITEM_SELECTED_COLOR);
+ }
+ detailsTable.getSelectionModel().setSelectionMode(
+ getFileChooser().isMultiSelectionEnabled()?
+ ListSelectionModel.MULTIPLE_INTERVAL_SELECTION:
+ ListSelectionModel.SINGLE_SELECTION);
! detailsTable.setIntercellSpacing(new Dimension(0,
! listViewWindowsStyle ? -1 : 0));
TableCellRenderer headerRenderer =
new AlignableTableHeaderRenderer(detailsTable.getTableHeader().getDefaultRenderer());
+ if(listViewWindowsStyle)
+ detailsTable.getTableHeader().setBackground(Color.white);
detailsTable.getTableHeader().setDefaultRenderer(headerRenderer);
TableCellRenderer cellRenderer = new DetailsTableCellRenderer(chooser);
detailsTable.setDefaultRenderer(Object.class, cellRenderer);
// So that drag can be started on a mouse press
*** 1192,1204 ****
detailsTable.addMouseListener(getMouseHandler());
// No need to addListSelectionListener because selections are forwarded
// to our JList.
- // 4835633 : tell BasicTableUI that this is a file list
- detailsTable.putClientProperty("Table.isFileList", Boolean.TRUE);
-
if (listViewWindowsStyle) {
detailsTable.addFocusListener(repaintListener);
}
// TAB/SHIFT-TAB should transfer focus and ENTER should select an item.
--- 1307,1316 ----
*** 1213,1234 ****
detailsTable.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
null);
JScrollPane scrollpane = new JScrollPane(detailsTable);
scrollpane.setComponentOrientation(chooser.getComponentOrientation());
LookAndFeel.installColors(scrollpane.getViewport(), "Table.background", "Table.foreground");
- // Adjust width of first column so the table fills the viewport when
- // first displayed (temporary listener).
- scrollpane.addComponentListener(new ComponentAdapter() {
- public void componentResized(ComponentEvent e) {
- JScrollPane sp = (JScrollPane)e.getComponent();
- fixNameColumnWidth(sp.getViewport().getSize().width);
- sp.removeComponentListener(this);
- }
- });
-
// 4835633.
// If the mouse is pressed in the area below the Details view table, the
// event is not dispatched to the Table MouseListener but to the
// scrollpane. Listen for that here so we can clear the selection.
scrollpane.addMouseListener(new MouseAdapter() {
--- 1325,1338 ----
detailsTable.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
null);
JScrollPane scrollpane = new JScrollPane(detailsTable);
scrollpane.setComponentOrientation(chooser.getComponentOrientation());
+ if(listViewWindowsStyle)
+ scrollpane.putClientProperty("ScrollPaneLayout.vsbAtTop", "true");
LookAndFeel.installColors(scrollpane.getViewport(), "Table.background", "Table.foreground");
// 4835633.
// If the mouse is pressed in the area below the Details view table, the
// event is not dispatched to the Table MouseListener but to the
// scrollpane. Listen for that here so we can clear the selection.
scrollpane.addMouseListener(new MouseAdapter() {
*** 1244,1256 ****
}
}
}
});
- detailsTable.setForeground(list.getForeground());
- detailsTable.setBackground(list.getBackground());
-
if (listViewBorder != null) {
scrollpane.setBorder(listViewBorder);
}
p.add(scrollpane, BorderLayout.CENTER);
--- 1348,1357 ----
*** 1273,1305 ****
boolean hasFocus, int row, int column) {
Component c = wrappedRenderer.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, column);
int modelColumn = table.convertColumnIndexToModel(column);
ShellFolderColumnInfo columnInfo = detailsTableModel.getColumns()[modelColumn];
Integer alignment = columnInfo.getAlignment();
if (alignment == null) {
alignment = SwingConstants.CENTER;
}
if (c instanceof JLabel) {
((JLabel) c).setHorizontalAlignment(alignment);
}
return c;
}
}
- private void fixNameColumnWidth(int viewWidth) {
- TableColumn nameCol = detailsTable.getColumnModel().getColumn(COLUMN_FILENAME);
- int tableWidth = detailsTable.getPreferredSize().width;
-
- if (tableWidth < viewWidth) {
- nameCol.setPreferredWidth(nameCol.getPreferredWidth() + viewWidth - tableWidth);
- }
- }
private class DelayedSelectionUpdater implements Runnable {
File editFile;
DelayedSelectionUpdater() {
--- 1374,1400 ----
boolean hasFocus, int row, int column) {
Component c = wrappedRenderer.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, column);
+ if(!listViewWindowsStyle) {
int modelColumn = table.convertColumnIndexToModel(column);
ShellFolderColumnInfo columnInfo = detailsTableModel.getColumns()[modelColumn];
Integer alignment = columnInfo.getAlignment();
if (alignment == null) {
alignment = SwingConstants.CENTER;
}
if (c instanceof JLabel) {
((JLabel) c).setHorizontalAlignment(alignment);
}
+ }
return c;
}
}
private class DelayedSelectionUpdater implements Runnable {
File editFile;
DelayedSelectionUpdater() {
*** 1361,1383 ****
JTextField editCell = null;
/**
* @param index visual index of the file to be edited
*/
- @SuppressWarnings("deprecation")
private void editFileName(int index) {
JFileChooser chooser = getFileChooser();
File currentDirectory = chooser.getCurrentDirectory();
if (readOnly || !canWrite(currentDirectory)) {
return;
}
ensureIndexIsVisible(index);
! switch (viewType) {
! case VIEWTYPE_LIST:
! editFile = (File)getModel().getElementAt(getRowSorter().convertRowIndexToModel(index));
Rectangle r = list.getCellBounds(index, index);
if (editCell == null) {
editCell = new JTextField();
editCell.setName("Tree.cellEditor");
editCell.addActionListener(new EditActionListener());
--- 1456,1478 ----
JTextField editCell = null;
/**
* @param index visual index of the file to be edited
*/
private void editFileName(int index) {
JFileChooser chooser = getFileChooser();
File currentDirectory = chooser.getCurrentDirectory();
if (readOnly || !canWrite(currentDirectory)) {
return;
}
ensureIndexIsVisible(index);
! if (viewType.isTable) {
! detailsTable.editCellAt(index, COLUMN_FILENAME);
! } else {
! editFile = (File) getModel().getElementAt(getRowSorter().convertRowIndexToModel(index));
Rectangle r = list.getCellBounds(index, index);
if (editCell == null) {
editCell = new JTextField();
editCell.setName("Tree.cellEditor");
editCell.addActionListener(new EditActionListener());
*** 1399,1413 ****
} else {
editCell.setBounds(r.x, r.y, r.width - editX, r.height);
}
editCell.requestFocus();
editCell.selectAll();
- break;
-
- case VIEWTYPE_DETAILS:
- detailsTable.editCellAt(index, COLUMN_FILENAME);
- break;
}
}
class EditActionListener implements ActionListener {
--- 1494,1503 ----
*** 1464,1474 ****
cancelEdit();
}
protected Action newFolderAction;
- @SuppressWarnings("serial") // anonymous class inside
public Action getNewFolderAction() {
if (!readOnly && newFolderAction == null) {
newFolderAction = new AbstractAction(newFolderActionLabelText) {
private Action basicNewFolderAction;
--- 1554,1563 ----
*** 1497,1542 ****
};
}
return newFolderAction;
}
- @SuppressWarnings("serial") // JDK-implementation class
protected class FileRenderer extends DefaultListCellRenderer {
! public Component getListCellRendererComponent(JList<?> list, Object value,
int index, boolean isSelected,
boolean cellHasFocus) {
if (listViewWindowsStyle && !list.isFocusOwner()) {
isSelected = false;
}
! super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
File file = (File) value;
String fileName = getFileChooser().getName(file);
setText(fileName);
setFont(list.getFont());
! Icon icon = getFileChooser().getIcon(file);
! if (icon != null) {
! setIcon(icon);
} else {
! if (getFileChooser().getFileSystemView().isTraversable(file)) {
! setText(fileName+File.separator);
}
}
return this;
}
}
-
- @SuppressWarnings("deprecation")
void setFileSelected() {
if (getFileChooser().isMultiSelectionEnabled() && !isDirectorySelected()) {
File[] files = getFileChooser().getSelectedFiles(); // Should be selected
! Object[] selectedObjects = list.getSelectedValues(); // Are actually selected
listSelectionModel.setValueIsAdjusting(true);
try {
int lead = listSelectionModel.getLeadSelectionIndex();
int anchor = listSelectionModel.getAnchorSelectionIndex();
--- 1586,1711 ----
};
}
return newFolderAction;
}
protected class FileRenderer extends DefaultListCellRenderer {
! // when the user selects an item then switches window, the item should
! // appear with gray background
! private static final String LAST_SELECTED_PROPERTY = "FilePane.FileRenderer.lastSelected";
!
! // TODO az új ViewType enumot a többi lafban is használni kéne majd
!
! public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected,
boolean cellHasFocus) {
+ assert viewType != null;
if (listViewWindowsStyle && !list.isFocusOwner()) {
isSelected = false;
}
! if (listViewWindowsStyle) {
! setOpaque(true);
! setBackground(null);
! } else {
! super.getListCellRendererComponent(list, "", index, isSelected, cellHasFocus);
! }
File file = (File) value;
String fileName = getFileChooser().getName(file);
setText(fileName);
setFont(list.getFont());
! Boolean isTraversable = getFileChooser().getFileSystemView().isTraversable(file);
! setIcon(new FileIcon(file, () -> {
! Icon icon = null;
! if (viewType.largeIcons) {
! try {
! icon = new ImageIcon(ShellFolder.getShellFolder(file).getIcon(true));
! } catch (FileNotFoundException ex) {
! throw new RuntimeException(ex);
! }
! }
!
! if (icon == null) {
! icon = getFileChooser().getIcon(file);
! }
! return icon;
! }, list, viewType.largeIcons ? 24 : 16, viewType.largeIcons ? 24 : 16));
! if (isTraversable) {
! setText(fileName + File.separator);
! }
!
! if (viewType.fileMetaLines) {
! String sizeString = "";
!
! if (!isTraversable) {
! try {
! sizeString += "<br>" + ShellFolder.
! getShellFolder(file).length();
! } catch (Exception ex) {
! }
! }
!
! setText("<html>" + getText() + "<br><font color=gray>"
! + getFileChooser().getTypeDescription(file)
! + sizeString);
! }
!
! setAlignmentX(RIGHT_ALIGNMENT);
! setHorizontalAlignment(viewType.horizAlign);
!
! setHorizontalTextPosition(viewType.horizTextPos);
! setVerticalTextPosition(viewType.vertTextPos);
!
! setPreferredSize(viewType.prefSize);
!
! if (listViewWindowsStyle) {
! boolean isHovered = false;
!
! {
! Object propertyValue = list.getClientProperty(HOVER_CELL_PROPERTY);
! if (propertyValue != null) {
! int hover = (int) propertyValue;
! if (hover == index) {
! isHovered = true;
! }
! }
! }
!
! setBorder(new EmptyBorder(1, 1, 3, 1));
! if (isSelected||editFile == file) {
! setBackground(WindowsFileListUI.ITEM_SELECTED_COLOR);
! if (isHovered) {
! setBorder(new CompoundBorder(
! WindowsFileListUI.ITEM_SELECTED_BORDER,
! new EmptyBorder(0, 0, 2, 0)
! ));
! }
! list.putClientProperty(LAST_SELECTED_PROPERTY, value);
! } else if(list.getClientProperty(LAST_SELECTED_PROPERTY) == value) {
! setBackground(WindowsFileListUI.ITEM_SELECTED_UNFOCUSED_COLOR);
! }else if (isHovered) {
! setBackground(WindowsFileListUI.ITEM_HOVERED_COLOR);
} else {
! setBackground(null);
}
}
return this;
}
}
void setFileSelected() {
if (getFileChooser().isMultiSelectionEnabled() && !isDirectorySelected()) {
File[] files = getFileChooser().getSelectedFiles(); // Should be selected
! Object[] selectedObjects = getViewType().isTable?
! IntStream.of(detailsTable.getSelectedRows()).
! mapToObj(i->getModel().getElementAt(i)).
! toArray():
! list.getSelectedValues(); // Are actually selected
listSelectionModel.setValueIsAdjusting(true);
try {
int lead = listSelectionModel.getLeadSelectionIndex();
int anchor = listSelectionModel.getAnchorSelectionIndex();
*** 1686,1697 ****
/*
* Listen for filechooser property changes, such as
* the selected file changing, or the type of the dialog changing.
*/
public void propertyChange(PropertyChangeEvent e) {
! if (viewType == -1) {
! setViewType(VIEWTYPE_LIST);
}
String s = e.getPropertyName();
if (s.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
doSelectedFileChanged(e);
--- 1855,1867 ----
/*
* Listen for filechooser property changes, such as
* the selected file changing, or the type of the dialog changing.
*/
public void propertyChange(PropertyChangeEvent e) {
! if (viewType == null) {
! setViewType(ViewType.LIST); // BasicFileChooserUI.Handler needs a list to work
! setViewType(ViewType.DETAILS);
}
String s = e.getPropertyName();
if (s.equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) {
doSelectedFileChanged(e);
*** 1757,1769 ****
public JMenu getViewMenu() {
if (viewMenu == null) {
viewMenu = new JMenu(viewMenuLabelText);
ButtonGroup viewButtonGroup = new ButtonGroup();
! for (int i = 0; i < VIEWTYPE_COUNT; i++) {
! JRadioButtonMenuItem mi =
! new JRadioButtonMenuItem(new ViewTypeAction(i));
viewButtonGroup.add(mi);
viewMenu.add(mi);
}
updateViewMenu();
}
--- 1927,1939 ----
public JMenu getViewMenu() {
if (viewMenu == null) {
viewMenu = new JMenu(viewMenuLabelText);
ButtonGroup viewButtonGroup = new ButtonGroup();
! for (ViewType viewType : ViewType.values()) {
! JRadioButtonMenuItem mi
! = new JRadioButtonMenuItem(new ViewTypeAction(viewType));
viewButtonGroup.add(mi);
viewMenu.add(mi);
}
updateViewMenu();
}
*** 1931,1940 ****
--- 2101,2112 ----
}
}
public void mousePressed(MouseEvent evt) {
if (evt.getSource() instanceof JList) {
+ list.putClientProperty(FileRenderer.LAST_SELECTED_PROPERTY, null);
+
// Forward event to Basic
if (getDoubleClickListener() != null) {
getDoubleClickListener().mousePressed(evt);
}
}
*** 1949,1959 ****
}
}
private MouseListener getDoubleClickListener() {
// Lazy creation of Basic's listener
! if (doubleClickListener == null && list != null) {
doubleClickListener =
fileChooserUIAccessor.createDoubleClickListener(list);
}
return doubleClickListener;
}
--- 2121,2131 ----
}
}
private MouseListener getDoubleClickListener() {
// Lazy creation of Basic's listener
! if (doubleClickListener == null) {
doubleClickListener =
fileChooserUIAccessor.createDoubleClickListener(list);
}
return doubleClickListener;
}
*** 2030,2039 ****
--- 2202,2279 ----
return prop == null ? chooser.getFileSystemView().equals(FileSystemView.getFileSystemView())
: prop.booleanValue();
}
+ /**
+ * An Icon implementation which loads the real icon in background, so we
+ * don't need to block the EDT to load an icon of a file. After the icon
+ * is loaded, the table or list will be refreshed.
+ */
+ public static class FileIcon implements Icon {
+
+ private static final Executor BACKGROUND_LOADER_THREAD =
+ Executors.newSingleThreadExecutor(runnable->{
+ Thread result = new Thread(runnable, "File Icon Loader");
+ result.setDaemon(true);
+ return result;
+ });
+
+ private static final Map<File, Icon> CACHE = new ConcurrentHashMap<>();
+ private static final Map<Object, FileIcon> FILEICON_CACHE = new WeakHashMap<>();
+
+ private final File file;
+ private final Supplier<Icon> supplier;
+ private final Component component;
+ private final int width, height;
+
+ private volatile boolean loading;
+
+ public FileIcon(File file, Supplier<Icon> supplier, Component component,
+ int width, int height) {
+ this.file = file;
+ this.supplier = supplier;
+ this.component = component;
+ this.width = width;
+ this.height = height;
+ }
+
+ @Override
+ public void paintIcon(Component c, Graphics g, int x, int y) {
+ if (CACHE.containsKey(file) &&
+ CACHE.get(file).getIconWidth()==width&&
+ CACHE.get(file).getIconHeight() == height) {
+ CACHE.get(file).paintIcon(c, g, x, y);
+ } else if (!loading) {
+ loading = true;
+ BACKGROUND_LOADER_THREAD.execute(() -> {
+ Icon icon;
+ try {
+ icon = supplier.get();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ icon = null;
+ }
+ CACHE.put(file, icon);
+ loading = false;
+ EventQueue.invokeLater(component::repaint);
+ });
+ }
+ }
+
+ @Override
+ public int getIconWidth() {
+ return width;
+ }
+
+ @Override
+ public int getIconHeight() {
+ return height;
+ }
+
+ }
+
// This interface is used to access methods in the FileChooserUI
// that are not public.
public interface FileChooserUIAccessor {
public JFileChooser getFileChooser();
public BasicDirectoryModel getModel();
< prev index next >