帆软报表设计器源代码。
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

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;
}
}