package com.fr.file; import com.fr.base.BaseUtils; import com.fr.base.FRContext; import com.fr.base.extension.FileExtension; import com.fr.design.DesignerEnvManager; import com.fr.design.ExtraDesignClassManager; import com.fr.design.actions.UpdateAction; import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.FineJOptionPane; import com.fr.design.dialog.UIDialog; import com.fr.design.env.DesignerWorkspaceInfo; import com.fr.design.env.DesignerWorkspaceType; import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.file.NodeAuthProcessor; import com.fr.design.fun.ReportSupportedFileUIProvider; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UIButtonUI; import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.itextfield.DefaultCompletionFilter; import com.fr.design.gui.itextfield.UIAutoCompletionField; import com.fr.design.gui.itextfield.UITextField; import com.fr.design.gui.itree.filetree.FileTreeIcon; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.DesignerFrame; import com.fr.design.mainframe.DesignerFrameFileDealerPane; import com.fr.design.mainframe.JTemplate; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.event.Event; import com.fr.event.EventDispatcher; import com.fr.event.Listener; import com.fr.file.filetree.FileNode; import com.fr.file.filter.ChooseFileFilter; import com.fr.file.filter.FILEFilter; import com.fr.general.ComparatorUtils; import com.fr.general.GeneralContext; import com.fr.log.FineLoggerFactory; import com.fr.report.ExtraReportClassManager; import com.fr.report.fun.ReportSupportedFileProvider; import com.fr.stable.CoreConstants; import com.fr.stable.ProductConstants; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; import com.fr.stable.os.windows.WindowsDetector; import com.fr.stable.project.ProjectConstants; import com.fr.workspace.WorkContext; import com.fr.workspace.Workspace; import com.fr.workspace.WorkspaceEvent; import javax.swing.AbstractAction; import javax.swing.AbstractListModel; import javax.swing.ActionMap; import javax.swing.BorderFactory; import javax.swing.DefaultComboBoxModel; import javax.swing.DefaultListCellRenderer; import javax.swing.DefaultListModel; import javax.swing.Icon; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFileChooser; import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.KeyStroke; import javax.swing.ListModel; import javax.swing.ListSelectionModel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.filechooser.FileSystemView; import javax.swing.plaf.basic.BasicArrowButton; import javax.swing.plaf.basic.BasicButtonUI; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Insets; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.util.ArrayList; import java.util.EnumSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import static javax.swing.JOptionPane.DEFAULT_OPTION; import static javax.swing.JOptionPane.WARNING_MESSAGE; /* * FileChooserPane要高亮显示某Button,以显示当前路径 * 边距要调整 * postfix还没有处理 * 该文件选择器,整理行为如下: */ public class FILEChooserPane extends BasicPane { /** * Return value if OK is chosen. */ public static final int OK_OPTION = 0; /** * Return value if CANCEL is chosen. */ public static final int CANCEL_OPTION = 1; public static final int JOPTIONPANE_OK_OPTION = 2; public static final int JOPTIONPANE_CANCEL_OPTION = 3; public static final String SEPARATOR_STRING = "/"; public static final char SEPARATOR_CHAR = '/'; /** * alex:之所以在Pattern那里加个+,是因为有些路径会有两个甚至多个分隔符放在一起 */ private static final Pattern SEPARATOR_PATTERN = Pattern.compile("[/\\\\]+"); private static final FILEChooserPane INSTANCE = new FILEChooserPane(); private FILE currentDirectory; // 当前路径,在subFileList中显示这个路径下所有的文件 private List filterList = new ArrayList<>(); private FILEFilter filter; private LocationButtonPane locationBtnPane; // 显示location的Panel private UIButton mkdirButton; private JList placesList; // File.listRoots() + Env + Favourite private JList subFileList; // 当前选中目录下的文件夹及文件 private JScrollPane scrollPane; private UIAutoCompletionField fileNameTextField; // 文件名的文本框 private UIComboBox postfixComboBox; // 文件后缀名的下拉列表框 private UIButton okButton; protected int type; protected boolean showEnv; protected boolean showLoc; protected boolean showWebReport = false; private UIDialog dialog; private int option = CANCEL_OPTION; protected String suffix; /** * @return */ public static FILEChooserPane getInstance() { return getInstance(true, true); } /** * @param showEnv * @return */ public static FILEChooserPane getInstance(boolean showEnv) { return getInstance(showEnv, true); } /** * @param showEnv * @param showLoc * @return */ public static FILEChooserPane getInstance(boolean showEnv, boolean showLoc) { INSTANCE.showEnv = showEnv; INSTANCE.showLoc = showLoc; INSTANCE.showWebReport = false; INSTANCE.setPlaceListModel(); INSTANCE.removeAllFilter(); return INSTANCE; } public static FILEChooserPane getMultiEnvInstance(boolean showLoc, boolean showWebReport, FILEFilter filter) { INSTANCE.showEnv = true; INSTANCE.showLoc = showLoc; INSTANCE.showWebReport = showWebReport; // 替换掉 PlaceListModel INSTANCE.setMultiPlaceListModel(); INSTANCE.removeAllFilter(); INSTANCE.addChooseFILEFilter(filter, 0); return INSTANCE; } public static FILEChooserPane getInstanceWithDesignatePath(String path, FILEFilter filter, String topPath) { INSTANCE.showLoc = false; INSTANCE.showEnv = false; INSTANCE.showWebReport = false; INSTANCE.setTopPath(topPath); INSTANCE.setDesignateModel(path); INSTANCE.removeAllFilter(); INSTANCE.addChooseFILEFilter(filter, 0); return INSTANCE; } public static FILEChooserPane getMultiEnvInstance(boolean showLoc, boolean showWebReport) { INSTANCE.showEnv = true; INSTANCE.showLoc = showLoc; INSTANCE.showWebReport = showWebReport; // 替换掉 PlaceListModel INSTANCE.setMultiPlaceListModel(); INSTANCE.removeAllFilter(); return INSTANCE; } /** * @param showEnv * @param filter * @return */ public static FILEChooserPane getInstance(boolean showEnv, FILEFilter filter) { INSTANCE.showEnv = showEnv; INSTANCE.setPlaceListModel(); INSTANCE.removeAllFilter(); INSTANCE.addChooseFILEFilter(filter, 0); return INSTANCE; } /** * @param showEnv * @param showLoc * @param filter * @return */ public static FILEChooserPane getInstance(boolean showEnv, boolean showLoc, FILEFilter filter) { INSTANCE.showEnv = showEnv; INSTANCE.showLoc = showLoc; INSTANCE.showWebReport = false; INSTANCE.setPlaceListModel(); INSTANCE.removeAllFilter(); INSTANCE.addChooseFILEFilter(filter, 0); return INSTANCE; } /** * @param showEnv * @param showLoc * @param showWebReport * @param filter * @return */ public static FILEChooserPane getInstance(boolean showEnv, boolean showLoc, boolean showWebReport, FILEFilter filter) { INSTANCE.showEnv = showEnv; INSTANCE.showLoc = showLoc; INSTANCE.showWebReport = showWebReport; INSTANCE.setPlaceListModel(); INSTANCE.removeAllFilter(); INSTANCE.addChooseFILEFilterToFist(filter, 0); return INSTANCE; } private FILEChooserPane() { this.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4)); this.setLayout(FRGUIPaneFactory.createBorderLayout()); // kel:support Esc key. InputMap inputMapAncestor = this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); ActionMap actionMap = this.getActionMap(); // transfer focus to CurrentEditor inputMapAncestor.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "dialogExit"); actionMap.put("dialogExit", new AbstractAction() { @Override public void actionPerformed(ActionEvent evt) { option = CANCEL_OPTION; dialogExit(); } }); JPanel locationPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); // locationPane.setLayout(FRGUIPaneFactory.createBorderLayout()); locationPane.add(locationBtnPane = new LocationButtonPane(), BorderLayout.CENTER); mkdirButton = initMkdirButton(); locationPane.add(mkdirButton, BorderLayout.EAST); JPanel centerLeftPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); // centerLeftPanel.setLayout(FRGUIPaneFactory.createBorderLayout()); // Richie:placesList includes C,D,E,F and DeskTop etc. placesList = new JList(); centerLeftPanel.add(placesList, BorderLayout.CENTER); centerLeftPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY)); centerLeftPanel.setPreferredSize(new Dimension(120, 1)); placesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); placesList.setCellRenderer(new DefaultListCellRenderer() { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if (value instanceof FILE) { FILE dir = (FILE) value; String name = dir.getName(); if (name != null && !StringUtils.isBlank(name)) { this.setText(name); } else { this.setText(GeneralContext.getCurrentAppNameOfEnv()); } Icon icon = dir.getIcon(); if (icon != null) { this.setIcon(icon); } } return this; } }); // placeList listener placesList.addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { Object selValue = placesList.getSelectedValue(); if (selValue instanceof FILE) { setSelectedDirectory((FILE) selValue); } } }); /* * placeList mouseListener */ placesList.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { Object selValue = placesList.getSelectedValue(); if (selValue instanceof FILE) { setSelectedDirectory((FILE) selValue); } } }); // centerRightPane JPanel centerRightPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); JPanel subFilePanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); // 以后rightPanel要用JTable subFileList = new JList(new DefaultListModel<>()); /* * JList的CellRenderer */ subFileList.setCellRenderer(new DefaultListCellRenderer() { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if (value instanceof FILE) { FILE dir = (FILE) value; String name = dir.getName(); if (name != null) { this.setText(name); } Icon icon = dir.getIcon(); if (icon != null) { this.setIcon(icon); } } return this; } }); /* * 鼠标点击JList时的listener */ subFileList.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { Object source = e.getSource(); if (!(source instanceof JList)) { return; } if (e.getClickCount() < 1) { return; } JList list = (JList) source; Object selValue = list.getSelectedValue(); if (selValue instanceof FILE) { if (e.getClickCount() == 1) { fileNameTextField.removeDocumentListener(); setFileTextField((FILE) selValue); fileNameTextField.addDocumentListener(); } else { setSelectedDirectory((FILE) selValue); if (!((FILE) selValue).isDirectory()) { doOK(); } } } } }); /* * right list. */ // Richie:按下Enter的时候打开文件夹或者打开文件 subFileList.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { Object source = e.getSource(); if (!(source instanceof JList)) { return; } JList list = (JList) source; Object selValue = list.getSelectedValue(); if (selValue instanceof FILE) { setFileTextField((FILE) selValue); // if (((FILE)selValue).isDirectory()) { // fileNameTextField.setText(""); // } // Richie:按下Enter的时候打开文件夹或者打开文件 if (e.getKeyCode() == KeyEvent.VK_ENTER) { setSelectedDirectory((FILE) selValue); if (!((FILE) selValue).isDirectory()) { doOK(); } } } } }); scrollPane = new JScrollPane(subFileList); subFilePanel.add(scrollPane, BorderLayout.CENTER); centerRightPane.add(subFilePanel, BorderLayout.CENTER); // 用createTableLayoutPane布局下fileNamePane UIButton cancelButton; Component[][] coms = new Component[][]{ new Component[]{GUICoreUtils.createBorderPane(new UILabel(Toolkit.i18nText("Fine-Design_Basic_Utils_File_Name") + ":"), BorderLayout.WEST), fileNameTextField = new UIAutoCompletionField(), okButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Utils_Design_File_Open")) }, new Component[]{GUICoreUtils.createBorderPane(new UILabel(Toolkit.i18nText("Fine-Design_Report_Utils_File_Type") + ":"), BorderLayout.WEST), postfixComboBox = new UIComboBox(), cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Utils_Design_Action_Cancel")) }}; JPanel fileNamePane = TableLayoutHelper.createGapTableLayoutPane(coms, new double[]{TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED}, new double[]{TableLayout.PREFERRED, TableLayout.FILL, TableLayout.PREFERRED}, 24, 4); centerRightPane.add(fileNamePane, BorderLayout.SOUTH); Component[][] outComponents = new Component[][]{ new Component[]{GUICoreUtils.createBorderPane(new UILabel(Toolkit.i18nText("Fine-Design_Basic_App_File_Lookup_range") + ":"), BorderLayout.WEST), locationPane}, new Component[]{centerLeftPanel, centerRightPane}}; JPanel contentPane = TableLayoutHelper.createTableLayoutPane(outComponents, new double[]{TableLayout.PREFERRED, TableLayout.FILL}, new double[]{TableLayout.PREFERRED, TableLayout.FILL}); this.add(contentPane, BorderLayout.CENTER); okButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { doOK(); } }); cancelButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { option = CANCEL_OPTION; doCancel(); } }); fileNameTextField.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ENTER) { option = CANCEL_OPTION; doOK(); } } }); postfixComboBox.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { Object ss = postfixComboBox.getSelectedItem(); if (ss instanceof ChooseFileFilter) { setFILEFilter((ChooseFileFilter) ss); if (fileNameTextField.isShowing()) { fileNameTextField.setText(calProperFileName(fileNameTextField.getText(), (ChooseFileFilter) ss)); } } else { setFILEFilter(null); } } }); } private String calProperFileName(String fileName, ChooseFileFilter fileFilter) { if (fileFilter == null) { return fileName; } String filterExtension = fileFilter.getExtensionString(); int lastDotIndex = fileName.lastIndexOf(".") != -1 ? fileName.lastIndexOf(".") : fileName.length(); String fileNameWithOutExtension = fileName.substring(0, lastDotIndex); String fileNameExtension = fileName.substring(lastDotIndex); FileExtension fileExtension = FileExtension.parse(fileNameExtension); if (StringUtils.isEmpty(fileName) || StringUtils.isEmpty(filterExtension) || fileFilter.containsExtension(fileExtension.getExtension())) { return fileName; } if (!ComparatorUtils.equals(fileNameExtension, filterExtension) && !isMapping(fileNameExtension, filterExtension)) { return fileName + filterExtension; } return fileNameWithOutExtension + filterExtension; } private boolean isMapping(String fromExtension, String toExtension) { if (FileExtension.CPTX.matchExtension(fromExtension)) { return FileExtension.CPT.matchExtension(toExtension); } else if (FileExtension.CPT.matchExtension(fromExtension)) { return FileExtension.CPTX.matchExtension(toExtension); } return false; } private void doCancel() { this.locationBtnPane.setPopDir(null); dialogExit(); } /** * @param showEnv * @param showLoc */ public FILEChooserPane(boolean showEnv, boolean showLoc) { this(); this.showEnv = showEnv; this.showLoc = showLoc; this.setPlaceListModel(); } /** * 返回选中的FILE * * @return */ public FILE getSelectedFILE() { String fileName = fileNameTextField.getText().trim(); if (!fileName.endsWith(suffix) && !fileName.contains(CoreConstants.DOT)) { fileName += this.suffix; } if (currentDirectory == null) { return null; } if (currentDirectory instanceof FileFILE) { return new FileFILE((FileFILE) currentDirectory, fileName); } else { return new FileNodeFILE((FileNodeFILE) currentDirectory, fileName, false); } } protected String getEnvProjectName() { return Toolkit.i18nText("Fine-Design_Basic_Utils_Report_Env_Directory"); } /** * 增加文件过滤器 * * @param filter 过滤器 */ public void addChooseFILEFilter(FILEFilter filter) { addChooseFILEFilter(filter, filterList.size()); } /** * 在指定index增加过滤器 * * @param filter 过滤器 * @param index 序号 */ public void addChooseFILEFilter(FILEFilter filter, int index) { if (filterList.contains(filter)) { return; } this.filterList.add(index, filter); } /** * 若是已经存在,则将之删去之后,在指定的位置增加 * * @param filter 过滤 * @param index 序号 */ public void addChooseFILEFilterToFist(FILEFilter filter, int index) { if (filterList.contains(filter)) { filterList.remove(filter); filterList.add(index, filter); return; } this.filterList.add(index, filter); } /** * 删除文件过滤器 * 这命名太乱了,完全是误导 * * @param filter 过滤 */ public void removeFILEFilter(FILEFilter filter) { if (filterList.contains(filter)) { this.filterList.remove(filter); } } /** * 删掉全部的过滤器 */ public void removeAllFilter() { this.filterList.clear(); } public void removeTopPath() { this.setTopPath(StringUtils.EMPTY); } /** * 设置filter,刷新右侧subFileList中的items * * @param filter 过滤 */ public void setFILEFilter(FILEFilter filter) { this.filter = filter; refreshSubFileListModel(); } /** * richer:默认的话就使用.cpt作为后缀名 * * @param text 文本 * @param suffix 后缀 */ public void setFileNameTextField(String text, String suffix) { if (StringUtils.isEmpty(suffix)) { suffix = FileExtension.CPT.getSuffix(); } this.suffix = suffix; if (!text.endsWith(suffix)) { text = removeSuffix(text) + suffix; } fileNameTextField.removeDocumentListener(); fileNameTextField.setText(text); fileNameTextField.addDocumentListener(); if (currentDirectory == null) { return; } FILE[] files = currentDirectory.listFiles(); String[] names = new String[files.length]; for (int i = 0; i < files.length; i++) { names[i] = files[i].getName(); } fileNameTextField.setFilter(new DefaultCompletionFilter(names)); } public void disableFileNameTextFiled() { fileNameTextField.setEditable(false); fileNameTextField.setEnabled(false); } public void enableFileNameTextFiled() { fileNameTextField.setEditable(true); fileNameTextField.setEnabled(true); } /** * 移除文件后缀的方法 * 解决cptx文件的另存为操作默认会出现双后缀的bug(xxx.cptx.cpt) **/ private String removeSuffix(String text) { return FileExtension.CPTX.matchExtension(text) ? text.substring(0, text.length() - FileExtension.CPTX.getSuffix().length()) : text; } /** * 打开对话框 * * @param parent 父类 * @return 类型 */ public int showOpenDialog(Component parent) { return showOpenDialog(parent, FileExtension.CPT.getSuffix()); } /** * 打开对话框 * * @param parent 父类 * @param suffix 后缀 * @return 类型 */ public int showOpenDialog(Component parent, String suffix) { return showDialog(parent, JFileChooser.OPEN_DIALOG, suffix); } /** * 打开对话框 * * @param parent 父类 * @return 类型 */ public int showSaveDialog(Component parent) { return showSaveDialog(parent, FileExtension.CPT.getSuffix()); } /** * 打开对话框 * * @param parent 父类 * @param suffix 后缀 * @return 类型 */ public int showSaveDialog(Component parent, String suffix) { return showDialog(parent, JFileChooser.SAVE_DIALOG, suffix); } /** * august:控件的事件都在这里面添加的 那么我每次showDialog,不都要重复添加一次事件吗?无语了 * * @param parent 父类 * @param type 类型 * @param suffix 后缀 * @return 类型 */ public int showDialog(Component parent, int type, String suffix) { this.type = type; this.suffix = suffix; dialog = showWindow(parent instanceof DesignerFrame ? (Window) parent : SwingUtilities.getWindowAncestor(parent), false); JPanel contentPane = (JPanel) dialog.getContentPane(); contentPane.setLayout(FRGUIPaneFactory.createM_BorderLayout()); contentPane.add(this, BorderLayout.CENTER); okButton.setText(dialogName()); // kel:打开界面的时候让文本域获得焦点,支持enter打开或保存。 dialog.addWindowListener(new WindowAdapter() { @Override public void windowActivated(WindowEvent e) { fileNameTextField.requestFocusInWindow(); } @Override public void windowClosing(WindowEvent e) { option = CANCEL_OPTION; dialogExit(); } }); // neil:默认打开pane里显示所有支持的格式 // daniel 从templateFileTree中取 if (!showWebReport && filterList.isEmpty()) { fileType(); } chooseType(); // richer:当文件类型被选定时,显示的文件就仅仅显示被选定的类型 // 如果是保存对话框,给个默认名字 if (type != JFileChooser.SAVE_DIALOG) { fileNameTextField.removeDocumentListener(); fileNameTextField.setText(""); fileNameTextField.addDocumentListener(); } dialog.setAlwaysOnTop(true); dialog.setVisible(true); return option; } protected void fileType() { String appName = ProductConstants.APP_NAME; JTemplate editing = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); if (editing == null || !editing.isChartBook()) { if (type == JFileChooser.OPEN_DIALOG) { ChooseFileFilter supportedTypes = new ChooseFileFilter(FRContext.getFileNodes().getSupportedTypes(), appName + Toolkit.i18nText("Fine-Design_Report_Template_File")); Set providers = ExtraReportClassManager.getInstance().getArray(ReportSupportedFileProvider.XML_TAG); for (ReportSupportedFileProvider provider : providers) { for (FileExtension fileExtension : provider.getFileExtensions()) { supportedTypes.addExtension(fileExtension.getExtension()); } } this.addChooseFILEFilter(supportedTypes); } // ben:filefilter设置初值为cpt过滤 this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.CPT, appName + Toolkit.i18nText("Fine-Design_Report_Template_File"))); this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.CPTX, appName + Toolkit.i18nText("Fine-Design_Report_Template_File"))); // richer:form文件 daniel 改成三个字 this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.FRM, appName + Toolkit.i18nText("Fine-Design_Report_Template_File"))); Set providers = ExtraDesignClassManager.getInstance().getArray(ReportSupportedFileUIProvider.XML_TAG); for (ReportSupportedFileUIProvider provider : providers) { provider.addChooseFileFilter(this, StringUtils.EMPTY); } } else { if (type == JFileChooser.OPEN_DIALOG) { this.addChooseFILEFilter(new ChooseFileFilter(EnumSet.of(FileExtension.XLS, FileExtension.XLSX), Toolkit.i18nText("Fine-Design_Basic_Import_Excel_Source"))); } } // 添加 xls 文件类型过滤 kt if (WorkContext.getCurrent().isLocal()) { //本地连接 this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.XLS, Toolkit.i18nText("Fine-Design_Basic_Import_Excel_Source"))); this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.XLSX, Toolkit.i18nText("Fine-Design_Basic_Import_Excel2007_Source"))); } if (FileExtension.PNG.matchExtension(suffix)) { this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.PNG, Toolkit.i18nText("Fine-Design_Basic_App_Export_png"))); } if (type == JFileChooser.SAVE_DIALOG) { this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.PDF, Toolkit.i18nText("Fine-Design_Basic_Import_Export_PDF"))); this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.SVG, Toolkit.i18nText("Fine-Design_Basic_Import_Export_SVG"))); this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.CSV, Toolkit.i18nText("Fine-Design_Basic_Import_Export_CSV"))); this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.DOC, Toolkit.i18nText("Fine-Design_Basic_Import_Export_Word"))); this.addChooseFILEFilter(new ChooseFileFilter(FileExtension.TXT, Toolkit.i18nText("Fine-Design_Basic_Import_Export_Text"))); } } private void chooseType() { DefaultComboBoxModel defaultComboBoxModel = (DefaultComboBoxModel) postfixComboBox.getModel(); defaultComboBoxModel.removeAllElements(); for (FILEFilter filter : filterList) { defaultComboBoxModel.addElement(filter); } if (WorkContext.getCurrent().isLocal()) { //本地连接 if (!showWebReport) { defaultComboBoxModel.addElement(Toolkit.i18nText("Fine-Design_Basic_Utils_App_AllFiles") + "(*.*)"); } } // 默认选取的文件类型(.cpt)类型 if (!filterList.isEmpty()) { setFILEFilter(filterList.get(0)); defaultComboBoxModel.setSelectedItem(filterList.get(0)); } // richer:根据不同的文件类型显示不同的后缀名 EnumSet fileExtensions = EnumSet.of( FileExtension.CPT, FileExtension.CPTX, FileExtension.FRM, FileExtension.FRMX, FileExtension.XLS, FileExtension.XLSX, FileExtension.PDF, FileExtension.SVG, FileExtension.CSV, FileExtension.DOC, FileExtension.TXT, FileExtension.PNG); for (FileExtension fileExtension : fileExtensions) { if (fileExtension.matchExtension(suffix)) { postfixComboBox.setSelectedIndex(suffixIndex(fileExtension.getExtension())); break; } } //jerry 26216 只保留.cpt .frm有用的格式,并且不可编辑 postfixComboBox.setEnabled(true); //只有一个类型时不可下拉 if (filterList.size() == 1) { postfixComboBox.setEnabled(false); } } private int suffixIndex(String extension) { for (int i = 0; i < filterList.size(); i++) { FILEFilter fileFilter = filterList.get(i); if (fileFilter.containsExtension(extension)) { return i; } } return 0; } private void doOK() { // 如果没有写文件名,不允许打开 or save if (fileNameTextField.getText().length() == 0 || !validInput()) { return; } if (type == JFileChooser.OPEN_DIALOG) { if (this.subFileList.getSelectedValue() == null) { FILE file = this.getSelectedFILE(); if (file.exists()) { option = OK_OPTION; saveDictionary(); dialogExit(); } else { FineJOptionPane.showMessageDialog(this, Toolkit.i18nText("Fine-Design_Basic_App_File_Not_Exist")); return; } } // alex:NPE判断,因为可能没有选中子目录,直接在文本框中输入文件名 FILE selectedSubFile = (FILE) this.subFileList.getSelectedValue(); if (selectedSubFile != null && selectedSubFile.isDirectory()) { setSelectedDirectory((FILE) this.subFileList.getSelectedValue()); } else { option = OK_OPTION; saveDictionary(); dialogExit(); } } else if (type == JFileChooser.SAVE_DIALOG) { saveDialog(); } } private boolean validInput() { String name = fileNameTextField.getText().trim(); if (!Pattern.compile(DesignerFrameFileDealerPane.FILE_NAME_LIMIT).matcher(name).matches()) { FineJOptionPane.showConfirmDialog(this, Toolkit.i18nText("Fine-Design_Basic_Template_Name_Illegal"), Toolkit.i18nText("Fine-Design_Basic_Error"), DEFAULT_OPTION, WARNING_MESSAGE); return false; } return true; } private void saveDialog() { String filename = fileNameTextField.getText(); filename = calProperFileName(filename, (ChooseFileFilter) (postfixComboBox.getSelectedItem())); fileNameTextField.setText(filename); option = OK_OPTION; FILE selectedFile = this.getSelectedFILE(); if (access(selectedFile) && access(currentDirectory)) { if (selectedFile.exists()) { int selVal = FineJOptionPane.showConfirmDialog(dialog, Toolkit.i18nText("Fine-Design_Basic_Utils_Would_You_Like_To_Cover_The_Current_File") + " ?", Toolkit.i18nText("Fine-Design_Basic_Dialog_Prompt"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); if (selVal == JOptionPane.YES_OPTION) { option = JOPTIONPANE_OK_OPTION; saveDictionary(); dialogExit(); } else { option = JOPTIONPANE_CANCEL_OPTION; } } else { dialogExit(); saveDictionary(); } } else { FineJOptionPane.showMessageDialog(FILEChooserPane.this, Toolkit.i18nText("Fine-Design_Basic_App_Privilege_No") + "!", Toolkit.i18nText("Fine-Design_Basic_App_File_Message"), JOptionPane.WARNING_MESSAGE); } } private boolean access(FILE selectedFile) { boolean access = true; try { if (selectedFile.isEnvFile() && selectedFile instanceof FileNodeFILE) { FileNodeFILE fileNodeFILE = ((FileNodeFILE) selectedFile); access = access && fileNodeFILE.hasFullAuth() && NodeAuthProcessor.getInstance().checkFileNodeAuth(new FileNode(fileNodeFILE.getPath(), fileNodeFILE.isDirectory())); } } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } return access; } private void saveDictionary() { FILE selectedFile = this.getSelectedFILE(); if (selectedFile != null) { DesignerEnvManager designerEnvManager = DesignerEnvManager.getEnvManager(); String prefix = currentDirectory.prefix(); String path = currentDirectory.getPath(); designerEnvManager.setCurrentDirectoryPrefix(prefix); designerEnvManager.setDialogCurrentDirectory(path); designerEnvManager.saveXMLFile(); } } private void dialogExit() { if (dialog == null) { return; } dialog.setVisible(false); dialog.dispose(); dialog = null; } /* * dialog的名字 */ private String dialogName() { return type == JFileChooser.OPEN_DIALOG ? Toolkit.i18nText("Fine-Design_Basic_Utils_Design_File_Open") : Toolkit.i18nText("Fine-Design_Basic_App_Template_Save"); } /* * 在subFileList中选中文件 */ private void setSelectedFileName(String name) { if (name == null) { return; } ListModel model = subFileList.getModel(); for (int i = 0, len = model.getSize(); i < len; i++) { if (ComparatorUtils.equals(name, ((FILE) model.getElementAt(i)).getName())) { subFileList.setSelectedIndex(i); break; } } } @Override protected String title4PopupWindow() { return dialogName(); } private void setPlaceListModel(AbstractPlaceListModel model) { if (placesList == null) { return; } placesList.setModel(model); String lastDirectoryPath = DesignerEnvManager.getEnvManager().getDialogCurrentDirectory(); String prefix = DesignerEnvManager.getEnvManager().getCurrentDirectoryPrefix(); FILE lastDirectory = FILEFactory.createFolder(prefix + lastDirectoryPath); model.setCD(lastDirectory); if (currentDirectory != null) { return; } // b:这里应该是currentDirectory为空时尝试从envmanager取,最后FileSystemView,和this.env有啥关系 if (StringUtils.isNotBlank(DesignerEnvManager.getEnvManager().getDialogCurrentDirectory())) { currentDirectory = FILEFactory.createFolder(DesignerEnvManager.getEnvManager().getDialogCurrentDirectory()); } else { currentDirectory = FILEFactory.createFolder(FileSystemView.getFileSystemView().getHomeDirectory().getPath()); } if (currentDirectory != null && currentDirectory.exists()) { this.setCurrentDirectory(currentDirectory); } } private void setPlaceListModel() { if (placesList == null) { return; } setPlaceListModel(new PlaceListModel()); } private void setDesignateModel(String path) { if (placesList == null) { return; } setPlaceListModel(new DesignateRemotePlaceListModel(path)); } private void setTopPath(String path) { this.locationBtnPane.setTopPath(path); } private void setMultiPlaceListModel() { if (placesList == null) { return; } setPlaceListModel(new MultiLocalEnvPlaceListModel()); } /* * 选中文件 */ private void setFileTextField(FILE file) { if (file != null && !file.isDirectory()) { fileNameTextField.setText(file.getName()); if (file instanceof FileFILE) { fileNameTextField.setText(((FileFILE) file).getTotalName()); } } } /** * Sets the current directory. Passing in null sets the file * chooser to point to the user's default directory. * * @param dir the current directory to point to * @see #setSelectedDirectory */ public void setCurrentDirectory(FILE dir) { if (dir == null && placesList != null) { dir = (FILE) placesList.getModel().getElementAt(0); placesList.setSelectedIndex(0); } if (placesList != null) { if (ComparatorUtils.equals(dir.prefix(), FILEFactory.ENV_PREFIX) || dir.prefix().endsWith(FILEFactory.WEBREPORT_PREFIX)) { placesList.setSelectedIndex(0); } else if (ComparatorUtils.equals(dir.prefix(), FILEFactory.FILE_PREFIX)) { AbstractPlaceListModel defaultListModel = (AbstractPlaceListModel) placesList.getModel(); for (int i = 0; i < defaultListModel.getSize(); i++) { if (defaultListModel.getElementAt(i) instanceof FileFILE) { FileFILE popDir = (FileFILE) defaultListModel.getElementAt(i); if (popDir != null && dir.getPath().indexOf(popDir.getPath()) == 0) { placesList.setSelectedIndex(i); break; } } } } } setSelectedDirectory(dir); } /* * Set Selected Directory 在右侧的subFileList中显示dir下面的所有文件和文件夹 */ private void setSelectedDirectory(FILE dir) { if (ComparatorUtils.equals(currentDirectory, dir) || dir == null || !dir.isDirectory()) { return; } currentDirectory = dir; this.locationBtnPane.populate(currentDirectory); this.mkdirButton.setEnabled(currentDirectory != null); refreshSubFileListModel(); } /* * 刷新右侧的SubFileList */ private void refreshSubFileListModel() { if (currentDirectory != null) { ((DefaultListModel) subFileList.getModel()).removeAllElements(); FILE[] res_array = currentDirectory.listFiles(); ((DefaultListModel) subFileList.getModel()).removeAllElements(); for (int i = 0; i < res_array.length; i++) { if (filter == null || filter.accept(res_array[i])) { ((DefaultListModel) subFileList.getModel()).addElement(res_array[i]); } } String[] name_array = new String[res_array.length]; for (int i = 0; i < res_array.length; i++) { name_array[i] = res_array[i].getName(); } fileNameTextField.setFilter(new DefaultCompletionFilter(name_array)); subFileList.validate(); subFileList.repaint(10); } } private abstract class AbstractPlaceListModel extends AbstractListModel { private static final long serialVersionUID = 8473695327688235386L; protected List filesOfSystem = new ArrayList(); protected void processSystemFile() { if (WindowsDetector.detect(true)) { // windows下展示桌面 File[] desktop = FileSystemView.getFileSystemView().getRoots(); if (desktop != null) { for (int i = 0; i < desktop.length; i++) { if (desktop[i].exists()) { filesOfSystem.add(new FileFILE(desktop[i])); } } } } else { // *nix下展示家目录 filesOfSystem.add(new FileFILE(FileSystemView.getFileSystemView().getDefaultDirectory())); } // C, D, E等盘符 File[] roots = File.listRoots(); if (roots != null) { for (int i = 0; i < roots.length; i++) { if (roots[i].exists()) { filesOfSystem.add(new FileFILE(roots[i])); } } } } protected void setCD(final FILE lastDirectory) { for (int i = 0; i < this.getSize(); i++) { FILE file = this.getElementAt(i); //前缀相同不代表能用啊,比如说 repolets 和 resource ,都是 env下的,但就不该去显示resource下的文件呀 if (ComparatorUtils.equals(lastDirectory.prefix(), file.prefix()) && lastDirectory.getPath() != null && lastDirectory.getPath().startsWith(file.getPath())) { setCurrentDirectory(lastDirectory); return; } } setCurrentDirectory(this.getElementAt(0)); } } /** * 一个简单的指定远程目录的 placelistmodel */ private class DesignateRemotePlaceListModel extends AbstractPlaceListModel { private static final long serialVersionUID = -6340666958714469249L; private FileNodeFILE envFILE; public DesignateRemotePlaceListModel(String path) { envFILE = new DesignateFileNodeFILE(new FileNode(path, true)) { @Override public String getName() { return Toolkit.i18nText("Fine-Design_Basic_Utils_Report_Env_Directory_Designate"); } }; } @Override public FILE getElementAt(int index) { if (index < 1) { return envFILE; } throw new IndexOutOfBoundsException(); } @Override public int getSize() { return 1; } @Override protected void setCD(FILE lastDirectory) { setCurrentDirectory(envFILE); } /** * 简单的重写了标签的FileNodeFILE */ private class DesignateFileNodeFILE extends FileNodeFILE { public DesignateFileNodeFILE(FileNode node) { super(node); } @Override public Icon getIcon() { return BaseUtils.readIcon("/com/fr/base/images/oem/logo.png"); } } } private class PlaceListModel extends AbstractPlaceListModel { private static final long serialVersionUID = 6138969918807381364L; private FileNodeFILE envFILE; private FileNodeFILE webReportFILE; PlaceListModel() { if (FILEChooserPane.this.showEnv) { envFILE = new FileNodeFILE(new FileNode(ProjectConstants.REPORTLETS_NAME, true)) { @Override public String getName() { return getEnvProjectName(); } }; } if (FILEChooserPane.this.showWebReport) { webReportFILE = new FileNodeFILE(FileNodeFILE.webRootPath); } if (FILEChooserPane.this.showLoc) { processSystemFile(); } } @Override public FILE getElementAt(int index) { int n = FILEChooserPane.this.showEnv ? 1 : 0; int n2 = FILEChooserPane.this.showWebReport ? 1 : 0; if (index < n) { return envFILE; } else if (index < n + n2) { return webReportFILE; } else if (index < n + n2 + filesOfSystem.size()) { return filesOfSystem.get(index - n - n2); } throw new IndexOutOfBoundsException(); } @Override public int getSize() { if (FILEChooserPane.this.showEnv && FILEChooserPane.this.showWebReport) { return 2 + filesOfSystem.size(); } else if (FILEChooserPane.this.showEnv || FILEChooserPane.this.showWebReport) { return 1 + filesOfSystem.size(); } else { return filesOfSystem.size(); } } } private class MultiLocalEnvPlaceListModel extends AbstractPlaceListModel { private static final long serialVersionUID = 6300018896958532154L; private List envFiles = new ArrayList(); private FileNodeFILE webReportFILE; MultiLocalEnvPlaceListModel() { Iterator iterator = DesignerEnvManager.getEnvManager().getEnvNameIterator(); while (iterator.hasNext()) { final String envName = iterator.next(); DesignerWorkspaceInfo info = DesignerEnvManager.getEnvManager().getWorkspaceInfo(envName); if (info.getType() == DesignerWorkspaceType.Local) { FileFILE fileFILE = new FileFILE(new File(info.getPath() + CoreConstants.SEPARATOR + ProjectConstants.REPORTLETS_NAME)) { @Override public String getName() { return envName; } }; if (fileFILE.exists() && fileFILE.isDirectory()) { envFiles.add(fileFILE); } } } if (FILEChooserPane.this.showWebReport) { webReportFILE = new FileNodeFILE(FileNodeFILE.webRootPath); } if (FILEChooserPane.this.showLoc) { processSystemFile(); } } @Override public FILE getElementAt(int index) { int envCount = envFiles.size(); int webReportCount = FILEChooserPane.this.showWebReport ? 1 : 0; if (index < envCount) { return envFiles.get(index); } else if (index < envCount + webReportCount) { return webReportFILE; } else if (index < envCount + webReportCount + filesOfSystem.size()) { return filesOfSystem.get(index - envCount - webReportCount); } throw new IndexOutOfBoundsException(); } @Override public int getSize() { int webReportCount = FILEChooserPane.this.showWebReport ? 1 : 0; return envFiles.size() + filesOfSystem.size() + webReportCount; } private class FileFILE extends com.fr.file.FileFILE { public FileFILE(File file) { super(file); } @Override public Icon getIcon() { if (ComparatorUtils.equals(getTotalName(), ProjectConstants.REPORTLETS_NAME)) { return BaseUtils.readIcon("/com/fr/base/images/oem/logo.png"); } else { return FileTreeIcon.getIcon(new File(this.getPath()), false); } } @Override public FILE[] listFiles() { FILE[] fileFILES = super.listFiles(); List results = new ArrayList<>(); for (FILE fileFILE : fileFILES) { results.add(new FileFILE(new File(fileFILE.getPath()))); } return results.toArray(new FILE[results.size()]); } } } /* * 上面的LocationButtonPane */ private class LocationButtonPane extends JPanel { private FILE popDir; private BasicArrowButton leftArrowButton; private BasicArrowButton rightArrowButton; private List buttonList = new ArrayList<>(); private int pathIndex = 0; private int maxPathIndex = 0; // 对顶层目录进行的限制 private String topPath; public LocationButtonPane() { this.setLayout(FRGUIPaneFactory.createBoxFlowLayout()); leftArrowButton = new BasicArrowButton(BasicArrowButton.WEST) { @Override public Dimension getPreferredSize() { return new Dimension(21, 21); } }; leftArrowButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (pathIndex > 0) { pathIndex--; } LocationButtonPane.this.doLayout(); LocationButtonPane.this.repaint(10); } }); rightArrowButton = new BasicArrowButton(BasicArrowButton.EAST) { @Override public Dimension getPreferredSize() { return new Dimension(21, 21); } }; rightArrowButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (pathIndex < maxPathIndex) { pathIndex++; } LocationButtonPane.this.doLayout(); LocationButtonPane.this.repaint(10); } }); EventDispatcher.listen(WorkspaceEvent.AfterSwitch, new Listener() { @Override public void on(Event event, Workspace param) { setPopDir(null); } }); } public void setTopPath(String path) { this.topPath = path; } public void highLightButton(FILE dir) { for (int i = 0; i < this.buttonList.size(); i++) { this.buttonList.get(i).setForeground(null); if (((SetDirectoryAction) this.buttonList.get(i).getAction()).getDir() != null && this.buttonList.get(i).getAction() instanceof SetDirectoryAction) { String actionPath = ((SetDirectoryAction) this.buttonList.get(i).getAction()).getDir().getPath(); String dirPath = dir.getPath(); //如果是报表环境,button的Action最后会跟上"/",这个是特意处理的,但是对应代码没有说明原因,不做修改 //FILE的getPath不会带"/",这边针对这种情况加个处理,不建议直接改FILE if (actionPath.endsWith(SEPARATOR_STRING) && !dirPath.endsWith(SEPARATOR_STRING)) { dirPath = dirPath + SEPARATOR_STRING; } if (ComparatorUtils.equals(actionPath, dirPath)) { this.buttonList.get(i).setForeground(Color.BLUE); } } } } public void setPopDir(FILE file) { popDir = file; } public void populate(FILE dir) { if (checkOnlyHighLight(dir)) { highLightButton(dir); return; } boolean isWebAppNamePath; popDir = dir; this.buttonList.clear(); if (dir == null) { return; } String path = dir.getPath(); isWebAppNamePath = ComparatorUtils.equals(dir.prefix(), FILEFactory.WEBREPORT_PREFIX); // 确保最后一个字符是分隔符 if (!path.endsWith("/") && !path.endsWith("\\") && !StringUtils.isBlank(path)) { path = path + "/"; } String webAppName = GeneralContext.getCurrentAppNameOfEnv(); if (StringUtils.isBlank(path) && isWebAppNamePath) { this.buttonList.add(createBlankButton(new SetDirectoryAction(webAppName + '/'))); } Matcher matcher = SEPARATOR_PATTERN.matcher(path); int node_start = 0; boolean needTopPath = !StringUtils.isEmpty(topPath); while (matcher.find()) { int start = matcher.start(); String btn_text = path.substring(node_start, start); String btn_path = path.substring(0, start); if (StringUtils.isBlank(btn_text) && isWebAppNamePath) { btn_text = webAppName; } node_start = matcher.end(); if (needTopPath && topPath.equals(btn_text)) { needTopPath = false; } this.buttonList.add(createBlankButton((new SetDirectoryAction(btn_text + '/', // alex:dir.prefix不和btn_path一起参与pathJoin,因为btn_path是否以/打头在unix,linux // OS中意义很不一样 FILEFactory.createFolder(dir.prefix() + StableUtils.pathJoin(btn_path, "/")), !needTopPath)))); } maxPathIndex = calculateMaxPathIndex(); pathIndex = maxPathIndex; this.doLayout(); this.repaint(10); // 高亮显示当前目录 highLightButton(dir); } /** * 检查是不是只需要设置高亮即可 * * @param dir FILE * @return 如果还要进行别的设置就返回false,如果只需要更新下高亮(通过点击上面的路径才会只需要更新高亮),返回true */ private boolean checkOnlyHighLight(FILE dir) { if (popDir == null || dir == null) { return false; } String popDirStr = popDir.toString(); String dirStr = dir.toString(); //前缀匹配是不够的,还要看下前缀匹配的下一位是不是'/' //否则"test"和"test副本"明明不属于同个路径逻辑,也只更新高亮,应该是"test"和"test/副本"这样才可以通过 //如果通过了indexOf的检查,因为不会存在相同的路径,popDirStr只会比dirStr大,看一下前缀匹配的下一位是不是'/',如果不是就得更新路径文本,不能只设置高亮 return popDirStr.indexOf(dirStr) == 0 && popDirStr.length() > dirStr.length() && popDirStr.charAt(dirStr.length()) == SEPARATOR_CHAR; } // doLayout @Override public void doLayout() { this.removeAll(); if (popDir == null) { return; } int pathWidth = 0; // 前缀 // UILabel prefixLabel = new UILabel(popDir.prefix()); // this.add(prefixLabel); // pathWidth += prefixLabel.getPreferredSize().width; // pathWidth for (int i = 0; i < buttonList.size(); i++) { pathWidth += buttonList.get(i).getPreferredSize().width; } // 当path按钮的长度超出显示范围时,隐藏 if (this.getWidth() < pathWidth) { int tmpWidth = leftArrowButton.getPreferredSize().width + leftArrowButton.getPreferredSize().width; int oldTmpWidth = tmpWidth; for (int i = pathIndex; i < buttonList.size(); i++) { tmpWidth += buttonList.get(i).getPreferredSize().width; if (tmpWidth > this.getWidth()) { break; } this.add(buttonList.get(i)); oldTmpWidth = tmpWidth; } UILabel blankLabel = new UILabel(""); blankLabel.setPreferredSize(new Dimension(this.getWidth() - oldTmpWidth - 1, blankLabel.getPreferredSize().height)); this.add(blankLabel); // leftArrowButton this.add(leftArrowButton, 1); // rightArrowButton this.add(rightArrowButton); } else { pathIndex = 0; for (int i = 0; i < buttonList.size(); i++) { this.add(buttonList.get(i)); } } super.doLayout(); } private int calculateMaxPathIndex() { if (popDir == null) { return 0; } int pathWidth = 0; // 前缀 UILabel prefixLabel = new UILabel(popDir.prefix()); pathWidth += prefixLabel.getPreferredSize().width; for (int i = 0; i < buttonList.size(); i++) { pathWidth += buttonList.get(i).getPreferredSize().width; } if (this.getWidth() < pathWidth) { int index = 0; int tmpWidth = prefixLabel.getPreferredSize().width + leftArrowButton.getPreferredSize().width + leftArrowButton.getPreferredSize().width; for (int i = buttonList.size() - 1; i >= 0; i--) { tmpWidth += buttonList.get(i).getPreferredSize().width; if (tmpWidth > this.getWidth()) { break; } index = i; } return index; } // 当长度足够时,不出现左右的按钮,皆从0开始显示 else { return 0; } } } private class SetDirectoryAction extends UpdateAction { private FILE dir; private boolean response = true; public SetDirectoryAction(String name) { this.setName(name); // this.dir = file; } public SetDirectoryAction(String name, FILE file) { this.setName(name); this.dir = file; } public SetDirectoryAction(String name, FILE file, boolean response) { this.setName(name); this.dir = file; this.response = response; } @Override public void actionPerformed(ActionEvent evt) { if (dir != null && response) { setSelectedDirectory(dir); } } public FILE getDir() { return dir; } } private UIButton createBlankButton(SetDirectoryAction setDirectoryAction) { final Color brighter = this.getBackground().brighter(); final Color darker = this.getBackground().darker(); final UIButton blankButton = new UIButton(setDirectoryAction); blankButton.setMargin(new Insets(0, 0, 0, 0)); blankButton.setUI(new BasicButtonUI()); blankButton.setHorizontalTextPosition(SwingConstants.CENTER); blankButton.setBorderPainted(false); blankButton.setBorder(BorderFactory.createRaisedBevelBorder()); blankButton.setBackground(darker); blankButton.addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { blankButton.setBackground(brighter); blankButton.setBorderPainted(true); blankButton.repaint(); } @Override public void mouseExited(MouseEvent e) { blankButton.setBackground(darker); blankButton.setBorderPainted(false); blankButton.repaint(); } @Override public void mousePressed(MouseEvent e) { blankButton.setBackground(brighter); blankButton.setBorderPainted(false); blankButton.repaint(); } @Override public void mouseReleased(MouseEvent e) { blankButton.setBackground(darker); blankButton.setBorderPainted(true); blankButton.repaint(); } }); return blankButton; } /* * 新建文件夹的Button */ private UIButton initMkdirButton() { UIButton folderButton = new UIButton(); folderButton.setIcon(BaseUtils.readIcon("com/fr/design/images/icon_NewFolderIcon_normal.png")); folderButton.setUI(new UIButtonUI()); folderButton.setToolTipText(Toolkit.i18nText("Fine-Design_Basic_Utils_New_Folder")); folderButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { if (currentDirectory == null) { return; } if (access(currentDirectory)) { new MkdirDialog(); } else { FineJOptionPane.showMessageDialog( FILEChooserPane.this, Toolkit.i18nText("Fine-Design_Basic_App_Privilege_No") + "!", Toolkit.i18nText("Fine-Design_Basic_App_File_Message"), JOptionPane.WARNING_MESSAGE); } } }); return folderButton; } /** * 新建文件夹对话框 * 支持快捷键Enter,ESC */ private class MkdirDialog extends JDialog { private UITextField nameField; private UILabel warnLabel; private UIButton confirmButton; private MkdirDialog() { this.setLayout(new BorderLayout()); this.setModal(true); // 输入框前提示 UILabel newNameLabel = new UILabel(Toolkit.i18nText( "Fine-Design_Basic_Enter_New_Folder_Name") ); newNameLabel.setHorizontalAlignment(SwingConstants.RIGHT); newNameLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10)); newNameLabel.setPreferredSize(new Dimension(118, 15)); // 文件名输入框 nameField = new UITextField(); nameField.getDocument().addDocumentListener(new DocumentListener() { public void changedUpdate(DocumentEvent e) { validInput(); } public void insertUpdate(DocumentEvent e) { validInput(); } public void removeUpdate(DocumentEvent e) { validInput(); } }); nameField.selectAll(); nameField.setPreferredSize(new Dimension(180, 20)); JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 5)); topPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 0, 15)); topPanel.add(newNameLabel); topPanel.add(nameField); // 增加enter以及esc快捷键的支持 nameField.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { dispose(); } else if (e.getKeyCode() == KeyEvent.VK_ENTER) { if (confirmButton.isEnabled()) { confirmClose(); } } } }); // 重名提示 warnLabel = new UILabel(); warnLabel.setPreferredSize(new Dimension(300, 30)); warnLabel.setHorizontalAlignment(SwingConstants.LEFT); warnLabel.setForeground(Color.RED); warnLabel.setVisible(false); JPanel midPanel = new JPanel(new BorderLayout()); midPanel.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 15)); midPanel.add(warnLabel, BorderLayout.WEST); // 确认按钮 confirmButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Confirm")); confirmButton.setPreferredSize(new Dimension(60, 25)); confirmButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { confirmClose(); } }); // 取消按钮 UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel")); cancelButton.setPreferredSize(new Dimension(60, 25)); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { dispose(); } }); JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); bottomPanel.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 15)); bottomPanel.add(confirmButton); bottomPanel.add(cancelButton); this.add( TableLayoutHelper.createTableLayoutPane( new Component[][]{ new Component[]{topPanel}, new Component[]{midPanel}, new Component[]{bottomPanel} }, new double[]{TableLayout.FILL, TableLayout.FILL, TableLayout.FILL}, new double[]{TableLayout.FILL} ), BorderLayout.CENTER); this.setSize(340, 180); this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Mkdir")); this.setResizable(false); this.setAlwaysOnTop(true); this.setIconImage(BaseUtils.readImage("/com/fr/base/images/oem/logo.png")); this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); GUICoreUtils.centerWindow(this); this.setVisible(true); } private void confirmClose() { String userInput = nameField.getText().trim(); // 处理不合法的文件夹名称 userInput = userInput.replaceAll("[\\\\/:*?\"<>|]", StringUtils.EMPTY); if (currentDirectory.createFolder(userInput)) { refreshSubFileListModel(); setSelectedFileName(userInput); // ben:这里处理有些不妥,取文件时没有考虑filefilter,不过效果一样,取的时候应该用subfilelist得data FILE[] allFiles = currentDirectory.listFiles(); int place = 0; for (int i = 0; i < allFiles.length; i++) { if (ComparatorUtils.equals(allFiles[i].getName(), userInput) && allFiles[i].isDirectory()) { place = i; break; } } scrollPane.revalidate(); scrollPane.repaint(); int total = scrollPane.getVerticalScrollBar().getMaximum(); int value = total * place / subFileList.getModel().getSize(); scrollPane.getVerticalScrollBar().setValue(value); } else { FineJOptionPane.showConfirmDialog(FILEChooserPane.this, Toolkit.i18nText("Fine-Design_Basic_Make_Failure"), Toolkit.i18nText("Fine-Design_Basic_Error"), JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); } this.dispose(); } private void validInput() { String userInput = nameField.getText().trim(); if (StringUtils.isEmpty(userInput)) { confirmButton.setEnabled(false); } boolean duplicate = false; // ben:这里处理有些不妥,取文件时没有考虑filefilter,不过效果一样,取的时候应该用subfilelist得data FILE[] allFiles = currentDirectory.listFiles(); for (int i = 0; i < allFiles.length; i++) { if (ComparatorUtils.equals(allFiles[i].getName(), userInput) && allFiles[i].isDirectory()) { duplicate = true; break; } } if (duplicate) { nameField.selectAll(); // 如果文件名已存在,则灰掉确认按钮 warnLabel.setText( Toolkit.i18nText( "Fine-Design_Basic_Folder_Name_Duplicate", userInput)); warnLabel.setVisible(true); confirmButton.setEnabled(false); } else { warnLabel.setVisible(false); confirmButton.setEnabled(true); } } } }