You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
510 lines
21 KiB
510 lines
21 KiB
package com.fr.design.file; |
|
|
|
import com.fr.base.i18n.BidiUtils; |
|
import com.fr.design.actions.UpdateAction; |
|
import com.fr.design.actions.file.DelFileAction; |
|
import com.fr.design.actions.file.LocateAction; |
|
import com.fr.design.actions.file.RenameAction; |
|
import com.fr.design.dialog.FineJOptionPane; |
|
import com.fr.design.fun.impl.AbstractTemplateTreeDefineProcessor; |
|
import com.fr.design.gui.ibutton.UIButton; |
|
import com.fr.design.gui.imenu.UIPopupMenu; |
|
import com.fr.design.gui.itree.filetree.TemplateDirTree; |
|
import com.fr.design.gui.itree.filetree.TemplateFileTree; |
|
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; |
|
import com.fr.design.i18n.Toolkit; |
|
import com.fr.design.mainframe.DesignerContext; |
|
import com.fr.design.mainframe.DesignerFrameFileDealerPane; |
|
import com.fr.design.mainframe.manager.clip.TemplateTreeClipboard; |
|
import com.fr.design.mainframe.manager.search.TemplateDirTreeSearchManager; |
|
import com.fr.design.mainframe.manager.search.TemplateTreeSearchManager; |
|
import com.fr.design.mainframe.manager.search.searcher.control.pane.TemplateDirTreeSearchPane; |
|
import com.fr.design.mainframe.toast.DesignerToastMsgUtil; |
|
import com.fr.design.mainframe.toast.ToastMsgDialog; |
|
import com.fr.design.utils.TemplateUtils; |
|
import com.fr.design.utils.gui.GUICoreUtils; |
|
import com.fr.file.filetree.FileNode; |
|
import com.fr.log.FineLoggerFactory; |
|
import com.fr.stable.StableUtils; |
|
import com.fr.stable.StringUtils; |
|
import com.fr.stable.collections.CollectionUtils; |
|
import com.fr.stable.project.ProjectConstants; |
|
|
|
import javax.swing.BorderFactory; |
|
import javax.swing.JDialog; |
|
import javax.swing.JOptionPane; |
|
import javax.swing.JPanel; |
|
import javax.swing.SwingUtilities; |
|
import java.awt.BorderLayout; |
|
import java.awt.CardLayout; |
|
import java.awt.Dimension; |
|
import java.awt.FlowLayout; |
|
import java.awt.event.ActionEvent; |
|
import java.awt.event.ActionListener; |
|
import java.awt.event.MouseEvent; |
|
import java.util.ArrayList; |
|
import java.util.List; |
|
import java.util.stream.Collectors; |
|
|
|
import static javax.swing.JOptionPane.WARNING_MESSAGE; |
|
import static javax.swing.JOptionPane.YES_NO_OPTION; |
|
|
|
/** |
|
* 默认的模板右键处理方式:包含重命名、复制、黏贴、删除、移动等功能 |
|
*/ |
|
public class DefaultTemplateTreeDefineProcessor extends AbstractTemplateTreeDefineProcessor { |
|
|
|
private UIPopupMenu popupMenu; |
|
private RenameAction renameAction; |
|
private CopyAction copyAction; |
|
private PasteAction pasteAction; |
|
private DelFileAction delFileAction; |
|
private MoveAction moveAction; |
|
private LocateAction locateAction; |
|
|
|
public static DefaultTemplateTreeDefineProcessor getInstance() { |
|
return DefaultTemplateTreeDefineProcessor.HOLDER.singleton; |
|
} |
|
|
|
private static class HOLDER { |
|
private static DefaultTemplateTreeDefineProcessor singleton = new DefaultTemplateTreeDefineProcessor(); |
|
} |
|
|
|
private DefaultTemplateTreeDefineProcessor() { |
|
initPane(); |
|
} |
|
|
|
private void initPane() { |
|
renameAction = new RenameAction(); |
|
copyAction = new CopyAction(); |
|
pasteAction = new PasteAction(); |
|
delFileAction = new DelFileAction(); |
|
moveAction = new MoveAction(); |
|
locateAction = new OpenInTemplateTreeAction(); |
|
//右键菜单 |
|
popupMenu = new UIPopupMenu(); |
|
popupMenu.add(renameAction.createMenuItem()); |
|
popupMenu.addSeparator(); |
|
popupMenu.add(copyAction.createMenuItem()); |
|
popupMenu.add(pasteAction.createMenuItem()); |
|
popupMenu.add(delFileAction.createMenuItem()); |
|
popupMenu.addSeparator(); |
|
popupMenu.add(moveAction.createMenuItem()); |
|
popupMenu.add(locateAction.createMenuItem()); |
|
} |
|
|
|
@Override |
|
public void rightClickAction(MouseEvent e) { |
|
if (SwingUtilities.isRightMouseButton(e)) { |
|
GUICoreUtils.showPopupMenu(popupMenu, e.getComponent(), e.getX(), e.getY()); |
|
checkButtonEnabled(); |
|
} |
|
} |
|
|
|
private void checkButtonEnabled() { |
|
renameAction.setEnabled(false); |
|
copyAction.setEnabled(false); |
|
pasteAction.setEnabled(false); |
|
delFileAction.setEnabled(false); |
|
moveAction.setEnabled(false); |
|
locateAction.setEnabled(false); |
|
int length = getFileTree().getSelectionCount(); |
|
if (length == 0) { |
|
//没有选中文件时,只能黏贴 |
|
if (!CollectionUtils.isEmpty(TemplateTreeClipboard.getInstance().takeFromClip())) { |
|
pasteAction.setEnabled(true); |
|
} |
|
return; |
|
} |
|
if (length == 1) { |
|
//选中一个时可以,可以重命名、黏贴 |
|
renameAction.setEnabled(true); |
|
if (TemplateTreeSearchManager.getInstance().isInSearchMode()) { |
|
//搜索模式开启定位当前模板 |
|
locateAction.setEnabled(true); |
|
} |
|
if (!CollectionUtils.isEmpty(TemplateTreeClipboard.getInstance().takeFromClip())) { |
|
pasteAction.setEnabled(true); |
|
} |
|
} |
|
moveAction.setEnabled(true); |
|
delFileAction.setEnabled(true); |
|
copyAction.setEnabled(true); |
|
} |
|
|
|
private TemplateFileTree getFileTree() { |
|
return TemplateTreePane.getInstance().getTemplateFileTree(); |
|
} |
|
|
|
private TemplateDirTree getDirTree() { |
|
return TemplateDirTreePane.getInstance().getTemplateDirTree(); |
|
} |
|
|
|
/** |
|
* 复制功能 |
|
*/ |
|
private class CopyAction extends UpdateAction { |
|
|
|
public CopyAction() { |
|
this.setName(Toolkit.i18nText("Fine-Design_Basic_Copy")); |
|
this.setMnemonic('C'); |
|
this.setSmallIcon("/com/fr/design/images/m_edit/copy"); |
|
} |
|
|
|
@Override |
|
public void actionPerformed(ActionEvent e) { |
|
FileOperations selectedOperation = DesignerFrameFileDealerPane.getInstance().getSelectedOperation(); |
|
if (!selectedOperation.access()) { |
|
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), |
|
Toolkit.i18nText("Fine-Design_Basic_Template_Permission_Denied"), |
|
Toolkit.i18nText("Fine-Design_Basic_Alert"), |
|
WARNING_MESSAGE); |
|
return; |
|
} |
|
//先记录所有的要复制的模板 |
|
List<ExpandMutableTreeNode> treeNodeList = TemplateTreeClipboard.getInstance().transferNameObjectArray2Map(getFileTree().getSelectedTreeNodes()); |
|
TemplateTreeClipboard.getInstance().addToClip(treeNodeList); |
|
} |
|
} |
|
|
|
private class OpenInTemplateTreeAction extends LocateAction { |
|
|
|
public OpenInTemplateTreeAction() { |
|
this.setName(Toolkit.i18nText("Fine-Design_Basic_Locate_Node")); |
|
} |
|
|
|
@Override |
|
public void actionPerformed(ActionEvent e) { |
|
FileNode fileNode = getFileTree().getSelectedFileNode(); |
|
if (fileNode == null) { |
|
return; |
|
} |
|
gotoEditingTemplateLeaf(fileNode.getEnvPath()); |
|
} |
|
} |
|
|
|
/** |
|
* 黏贴功能 |
|
*/ |
|
private class PasteAction extends UpdateAction { |
|
|
|
public PasteAction() { |
|
this.setName(Toolkit.i18nText("Fine-Design_Basic_Action_Paste_Name")); |
|
this.setMnemonic('P'); |
|
this.setSmallIcon("/com/fr/design/images/m_edit/paste"); |
|
} |
|
|
|
@Override |
|
public void actionPerformed(ActionEvent e) { |
|
List<ExpandMutableTreeNode> treeNodeList = TemplateTreeClipboard.getInstance().takeFromClip(); |
|
if (!canPaste(treeNodeList)) { |
|
return; |
|
} |
|
String targetDir = getTargetDir(); |
|
|
|
// 筛选可以黏贴的文件 |
|
ArrayList<ExpandMutableTreeNode> pasteNodes = new ArrayList<>(); |
|
ArrayList<ExpandMutableTreeNode> lockedNodes = new ArrayList<>(); |
|
for (ExpandMutableTreeNode treeNode : treeNodeList) { |
|
FileOperationHelper.getInstance().checkFreeOrLock(treeNode, pasteNodes, lockedNodes); |
|
} |
|
if (pasteNodes.isEmpty() || !lockedNodes.isEmpty()) { |
|
//提示:复制的文件都不能黏贴 |
|
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), |
|
Toolkit.i18nText("Fine-Design_Basic_Confirm_Paste_Unlock_File"), |
|
Toolkit.i18nText("Fine-Design_Basic_Alert"), |
|
WARNING_MESSAGE); |
|
return; |
|
} |
|
doPaste(targetDir, treeNodeList); |
|
} |
|
|
|
/** |
|
* 检测是否能够黏贴 |
|
* |
|
* @param treeNodeList |
|
* @return |
|
*/ |
|
private boolean canPaste(List<ExpandMutableTreeNode> treeNodeList) { |
|
if (CollectionUtils.isEmpty(treeNodeList)) { |
|
return false; |
|
} |
|
//确定目标目录并检查权限 |
|
FileOperations selectedOperation = DesignerFrameFileDealerPane.getInstance().getSelectedOperation(); |
|
boolean rootAuthority = true; |
|
if (selectedOperation.getFileNode() == null && selectedOperation instanceof TemplateTreePane) { |
|
//没有选中文件节点时,默认粘贴到根目录下,所以直接检测根目录是否有权限 |
|
ExpandMutableTreeNode root = (ExpandMutableTreeNode) ((TemplateTreePane) selectedOperation).getTemplateFileTree().getModel().getRoot(); |
|
rootAuthority = root.hasFullAuthority(); |
|
} |
|
if (!rootAuthority && !selectedOperation.access()) { |
|
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), |
|
Toolkit.i18nText("Fine-Design_Basic_Template_Permission_Denied"), |
|
Toolkit.i18nText("Fine-Design_Basic_Alert"), |
|
WARNING_MESSAGE); |
|
return false; |
|
} |
|
//检测之前复制的文件是否被打开 |
|
if (TemplateUtils.checkTemplateIsEditing(treeNodeList.toArray(new ExpandMutableTreeNode[0]))) { |
|
return FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), |
|
Toolkit.i18nText("Fine-Design_Basic_Template_Is_Editing"), |
|
Toolkit.i18nText("Fine-Design_Basic_Alert"), |
|
YES_NO_OPTION) == JOptionPane.YES_OPTION; |
|
} |
|
return true; |
|
} |
|
|
|
|
|
private void doPaste(String targetDir, List<ExpandMutableTreeNode> pasteNodes) { |
|
String targetFile = targetDir; |
|
try { |
|
if (StringUtils.isEmpty(targetDir) || !confirmTargetDir(targetDir, pasteNodes)) { |
|
return; |
|
} |
|
for (ExpandMutableTreeNode node : pasteNodes) { |
|
if (node.getUserObject() instanceof FileNode) { |
|
FileNode fileNode = (FileNode) node.getUserObject(); |
|
String newTargetFile = FileOperationHelper.getInstance().copyFile(fileNode, targetDir); |
|
if (StringUtils.isNotEmpty(newTargetFile)) { |
|
targetFile = newTargetFile; |
|
} |
|
FineLoggerFactory.getLogger().debug("Template: {} paste to {} success.", fileNode.getEnvPath(), targetDir); |
|
} |
|
} |
|
} catch (Exception e) { |
|
FineLoggerFactory.getLogger().error(e, "Template paste failed.", e.getMessage()); |
|
FineJOptionPane.showConfirmDialog(null, |
|
Toolkit.i18nText("Fine-Design_Basic_Paste_Failure"), |
|
Toolkit.i18nText("Fine-Design_Basic_Error"), |
|
JOptionPane.DEFAULT_OPTION, |
|
JOptionPane.ERROR_MESSAGE); |
|
} |
|
|
|
DesignerFrameFileDealerPane.getInstance().getSelectedOperation().refreshParent(); |
|
LocateAction.gotoEditingTemplateLeaf(targetFile); |
|
} |
|
|
|
/** |
|
* 确认粘贴的目标目录是否是复制文件的子目录,并确认是否继续执行粘贴任务 |
|
* |
|
* @param targetDir 目标文件夹 |
|
* @param pasteNodes 待粘贴的文件 |
|
* @return 是否继续 |
|
*/ |
|
private boolean confirmTargetDir(String targetDir, List<ExpandMutableTreeNode> pasteNodes) { |
|
List<ExpandMutableTreeNode> filterNodes = pasteNodes.stream().filter( |
|
treeNode -> targetDir.startsWith(((FileNode) (treeNode.getUserObject())).getEnvPath())).collect(Collectors.toList()); |
|
if (!CollectionUtils.isEmpty(filterNodes)) { |
|
if (FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), |
|
Toolkit.i18nText("Fine-Design_Basic_Confirm_Paste_Target_Dir"), |
|
Toolkit.i18nText("Fine-Design_Basic_Alert"), |
|
YES_NO_OPTION) != JOptionPane.YES_OPTION) { |
|
return false; |
|
} |
|
//移除待粘贴文件中目标目录的父目录 |
|
pasteNodes.removeAll(filterNodes); |
|
} |
|
return true; |
|
} |
|
} |
|
|
|
|
|
/** |
|
* 移动功能 |
|
*/ |
|
private class MoveAction extends UpdateAction { |
|
|
|
public MoveAction() { |
|
this.setName(Toolkit.i18nText("Fine-Design_Basic_Move")); |
|
this.setSmallIcon("/com/fr/design/images/m_edit/move"); |
|
} |
|
|
|
@Override |
|
public void actionPerformed(ActionEvent e) { |
|
FileOperations selectedOperation = DesignerFrameFileDealerPane.getInstance().getSelectedOperation(); |
|
if (!selectedOperation.access()) { |
|
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), |
|
Toolkit.i18nText("Fine-Design_Basic_Template_Permission_Denied"), |
|
Toolkit.i18nText("Fine-Design_Basic_Alert"), |
|
WARNING_MESSAGE); |
|
return; |
|
} |
|
// 筛选可以移动的文件 |
|
ArrayList<ExpandMutableTreeNode> moveNodes = new ArrayList<>(); |
|
ArrayList<ExpandMutableTreeNode> lockedNodes = new ArrayList<>(); |
|
for (ExpandMutableTreeNode treeNode : getFileTree().getSelectedTreeNodes()) { |
|
FileOperationHelper.getInstance().checkFreeOrLock(treeNode, moveNodes, lockedNodes); |
|
} |
|
|
|
if (!lockedNodes.isEmpty()) { |
|
// 提醒被锁定模板无法移动 |
|
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), |
|
Toolkit.i18nText("Fine-Design_Basic_Unable_Move_Locked_File"), |
|
Toolkit.i18nText("Fine-Design_Basic_Alert"), |
|
WARNING_MESSAGE); |
|
return; |
|
} |
|
|
|
new TemplateMoveDialog(); |
|
} |
|
} |
|
|
|
private class TemplateMoveDialog extends JDialog { |
|
|
|
private static final String DIR = "dir"; |
|
private TemplateDirTreeSearchPane searchPane; |
|
private TemplateDirTreePane dirTreePane; |
|
private UIButton confirmButton; |
|
private String targetFile; |
|
|
|
public TemplateMoveDialog() { |
|
super(DesignerContext.getDesignerFrame(), true); |
|
this.setLayout(new BorderLayout()); |
|
|
|
searchPane = new TemplateDirTreeSearchPane(); |
|
add(searchPane, BorderLayout.NORTH); |
|
|
|
CardLayout card; |
|
JPanel cardPane = new JPanel(card = new CardLayout()); |
|
cardPane.add(TemplateDirTreePane.getInstance(), DIR); |
|
dirTreePane = TemplateDirTreePane.getInstance(); |
|
card.show(cardPane, DIR); |
|
add(cardPane, BorderLayout.CENTER); |
|
cardPane.setBorder(BorderFactory.createEmptyBorder(10, 15, 0, 10)); |
|
dirTreePane.refresh(); |
|
|
|
// 确认按钮,默认就可用 |
|
confirmButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Confirm")); |
|
confirmButton.setPreferredSize(new Dimension(60, 25)); |
|
confirmButton.addActionListener(new ActionListener() { |
|
@Override |
|
public void actionPerformed(ActionEvent e) { |
|
confirmClose(); |
|
} |
|
}); |
|
confirmButton.setEnabled(true); |
|
|
|
// 取消按钮 |
|
UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel")); |
|
cancelButton.setPreferredSize(new Dimension(60, 25)); |
|
|
|
cancelButton.addActionListener(new ActionListener() { |
|
|
|
@Override |
|
public void actionPerformed(ActionEvent e) { |
|
dispose(); |
|
} |
|
}); |
|
|
|
JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 10, 0)); |
|
bottomPanel.setBorder(BorderFactory.createEmptyBorder(10, 15, 10, 10)); |
|
bottomPanel.add(confirmButton); |
|
bottomPanel.add(cancelButton); |
|
BidiUtils.applyOrientationByLocale(bottomPanel); |
|
this.add(bottomPanel, BorderLayout.SOUTH); |
|
|
|
this.setSize(new Dimension(600, 400)); |
|
this.setTitle(Toolkit.i18nText("Fine-Design_Basic_Move")); |
|
this.setResizable(false); |
|
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); |
|
GUICoreUtils.centerWindow(this); |
|
this.setVisible(true); |
|
} |
|
|
|
private void confirmClose() { |
|
//获取目录树中所选中的文件,并判断是否有权限 |
|
if (!checkBeforeMove()) { |
|
return; |
|
} |
|
boolean moveSuccess = doMove(); |
|
dispose(); |
|
if (moveSuccess) { |
|
ToastMsgDialog dialog = DesignerToastMsgUtil.createPromptDialog(Toolkit.i18nText("Fine-Design_Basic_Template_Moved_Success")); |
|
dialog.setVisible(true); |
|
|
|
DesignerFrameFileDealerPane.getInstance().getSelectedOperation().refresh(); |
|
SwingUtilities.invokeLater(() -> { |
|
LocateAction.gotoEditingTemplateLeaf(targetFile); |
|
}); |
|
} |
|
} |
|
|
|
private boolean checkBeforeMove() { |
|
if (getDirTree().getSelectionCount() != 0 && !TemplateDirTreePane.getInstance().selectedAccess()) { |
|
FineJOptionPane.showMessageDialog(this, |
|
Toolkit.i18nText("Fine-Design_Basic_Template_Permission_Denied"), |
|
Toolkit.i18nText("Fine-Design_Basic_Alert"), |
|
WARNING_MESSAGE); |
|
return false; |
|
} |
|
// 检查移动的源文件夹是否为目标文件夹相同文件夹或子文件夹 |
|
if (FileOperationHelper.getInstance().isSubDirectoryOrSame(getFileTree().getSelectedTreeNodes(), getTargetFileNode())) { |
|
FineJOptionPane.showMessageDialog(this, |
|
Toolkit.i18nText("Fine-Design_Basic_Move_To_SubDirectory"), |
|
Toolkit.i18nText("Fine-Design_Basic_Alert"), |
|
WARNING_MESSAGE); |
|
return false; |
|
} |
|
if (TemplateUtils.checkSelectedTemplateIsEditing()) { |
|
return FineJOptionPane.showConfirmDialog(this, |
|
Toolkit.i18nText("Fine-Design_Basic_Template_Is_Editing"), |
|
Toolkit.i18nText("Fine-Design_Basic_Alert"), |
|
YES_NO_OPTION) == JOptionPane.YES_OPTION; |
|
} |
|
return true; |
|
} |
|
|
|
private boolean doMove() { |
|
FileNode fileNode = getTargetFileNode(); |
|
boolean moveSuccess = true; |
|
try { |
|
//待移动的文件可以有多个 |
|
ExpandMutableTreeNode[] sourceSelected = getFileTree().getSelectedTreeNodes(); |
|
for (ExpandMutableTreeNode treeNode : sourceSelected) { |
|
FileNode sourceFileNode = (FileNode) treeNode.getUserObject(); |
|
targetFile = FileOperationHelper.getInstance().moveFile(sourceFileNode, fileNode.getEnvPath()); |
|
} |
|
} catch (Exception e) { |
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
|
FineJOptionPane.showMessageDialog(this, |
|
Toolkit.i18nText("Fine-Design_Basic_Template_Moved_Fail"), |
|
Toolkit.i18nText("Fine-Design_Basic_Alert"), |
|
WARNING_MESSAGE); |
|
moveSuccess = false; |
|
} |
|
return moveSuccess; |
|
} |
|
|
|
private FileNode getTargetFileNode() { |
|
FileNode fileNode = getDirTree().getSelectedFileNode(); |
|
ExpandMutableTreeNode rootTreeNode = (ExpandMutableTreeNode) getDirTree().getModel().getRoot(); |
|
return fileNode == null ? (FileNode) rootTreeNode.getUserObject() : fileNode; |
|
} |
|
|
|
@Override |
|
public void dispose() { |
|
TemplateDirTreeSearchManager.getInstance().outOfSearchMode(); |
|
super.dispose(); |
|
} |
|
} |
|
|
|
/** |
|
* 黏贴时确定黏贴的目录 |
|
* |
|
* @return |
|
*/ |
|
private String getTargetDir() { |
|
int count = getFileTree().getSelectionCount(); |
|
String targetDir; |
|
if (count == 0) { |
|
targetDir = ProjectConstants.REPORTLETS_NAME; |
|
} else { |
|
FileNode fileNode = getFileTree().getSelectedFileNode(); |
|
targetDir = fileNode.getParent(); |
|
if (fileNode.isDirectory()) { |
|
targetDir = StableUtils.pathJoin(targetDir, fileNode.getName()); |
|
} |
|
} |
|
return targetDir; |
|
} |
|
}
|
|
|