From 075bfaff61b8b9cdd5bd03e18d7d638fc185017f Mon Sep 17 00:00:00 2001 From: "yaoh.wu" Date: Mon, 9 Jul 2018 01:31:11 +0800 Subject: [PATCH 1/8] =?UTF-8?q?REPORT-8941=20=E3=80=9010.0=E8=BF=9C?= =?UTF-8?q?=E7=A8=8B=E8=AE=BE=E8=AE=A1=E6=9D=83=E9=99=90=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E3=80=91=E5=86=B3=E7=AD=96=E7=B3=BB=E7=BB=9F=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E4=B8=8D=E5=85=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fr/design/remote/ui/list/AddedMemberList.java | 2 +- .../remote/ui/list/AddedMemberListCellRender.java | 2 +- .../fr/design/remote/ui/list/AddingMemberList.java | 2 +- .../remote/ui/list/AddingMemberListCellRender.java | 13 ++++++++++--- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/designer-base/src/com/fr/design/remote/ui/list/AddedMemberList.java b/designer-base/src/com/fr/design/remote/ui/list/AddedMemberList.java index a2631d66f5..f1133a6088 100644 --- a/designer-base/src/com/fr/design/remote/ui/list/AddedMemberList.java +++ b/designer-base/src/com/fr/design/remote/ui/list/AddedMemberList.java @@ -32,7 +32,7 @@ public class AddedMemberList extends MemberList { int rX = point.x; int rY = point.y; int index = this.getSelectedIndex(); - int x = 280; + int x = 270; int y = 25 * index; int width = 20; int height = 25; diff --git a/designer-base/src/com/fr/design/remote/ui/list/AddedMemberListCellRender.java b/designer-base/src/com/fr/design/remote/ui/list/AddedMemberListCellRender.java index 39dd08fb0f..6bc8949255 100644 --- a/designer-base/src/com/fr/design/remote/ui/list/AddedMemberListCellRender.java +++ b/designer-base/src/com/fr/design/remote/ui/list/AddedMemberListCellRender.java @@ -24,7 +24,7 @@ public class AddedMemberListCellRender extends JPanel implements ListCellRendere label = new UILabel(); label.setIcon(BaseUtils.readIcon("com/fr/design/remote/images/icon_Member_normal@1x.png")); - label.setPreferredSize(new Dimension(270, 20)); + label.setPreferredSize(new Dimension(260, 20)); this.setPreferredSize(new Dimension(this.getPreferredSize().width, 25)); this.add(label); diff --git a/designer-base/src/com/fr/design/remote/ui/list/AddingMemberList.java b/designer-base/src/com/fr/design/remote/ui/list/AddingMemberList.java index 136d77cc11..6bcbf83547 100644 --- a/designer-base/src/com/fr/design/remote/ui/list/AddingMemberList.java +++ b/designer-base/src/com/fr/design/remote/ui/list/AddingMemberList.java @@ -43,7 +43,7 @@ public class AddingMemberList extends MemberList { int rX = point.x; int rY = point.y; int index = this.getSelectedIndex(); - int x = 280; + int x = 270; int y = 25 * index; int width = 25; int height = 25; diff --git a/designer-base/src/com/fr/design/remote/ui/list/AddingMemberListCellRender.java b/designer-base/src/com/fr/design/remote/ui/list/AddingMemberListCellRender.java index 0668d67f1b..6900289a1a 100644 --- a/designer-base/src/com/fr/design/remote/ui/list/AddingMemberListCellRender.java +++ b/designer-base/src/com/fr/design/remote/ui/list/AddingMemberListCellRender.java @@ -24,7 +24,7 @@ public class AddingMemberListCellRender extends JPanel implements ListCellRender this.setLayout(new FlowLayout(FlowLayout.LEFT)); label = new UILabel(); - label.setPreferredSize(new Dimension(270, 20)); + label.setPreferredSize(new Dimension(260, 20)); this.setPreferredSize(new Dimension(this.getPreferredSize().width, 25)); label.setIcon(BaseUtils.readIcon("com/fr/design/remote/images/icon_Member_normal@1x.png")); @@ -39,8 +39,15 @@ public class AddingMemberListCellRender extends JPanel implements ListCellRender @Override public Component getListCellRendererComponent(JList list, RemoteDesignMember member, int index, boolean isSelected, boolean cellHasFocus) { - this.setLabelText(member.getRealName() + "(" + member.getUsername() + ")"); - check.setSelected(member.isSelected()); + + if (member.equals(RemoteDesignMember.DEFAULT_MEMBER)) { + this.setLabelText(member.getUsername()); + check.setVisible(false); + } else { + this.setLabelText(member.getRealName() + "(" + member.getUsername() + ")"); + check.setVisible(true); + check.setSelected(member.isSelected()); + } return this; } From d879b29b887f7eea30c9d7f26367aae046026933 Mon Sep 17 00:00:00 2001 From: "yaoh.wu" Date: Sat, 21 Jul 2018 11:09:45 +0800 Subject: [PATCH 2/8] =?UTF-8?q?=E6=97=A0=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fr/design/beans/FurtherBasicBeanPane.java | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/designer-base/src/main/java/com/fr/design/beans/FurtherBasicBeanPane.java b/designer-base/src/main/java/com/fr/design/beans/FurtherBasicBeanPane.java index 78305c3758..adec741c2f 100644 --- a/designer-base/src/main/java/com/fr/design/beans/FurtherBasicBeanPane.java +++ b/designer-base/src/main/java/com/fr/design/beans/FurtherBasicBeanPane.java @@ -3,30 +3,31 @@ package com.fr.design.beans; import com.fr.stable.StringUtils; /** - * * @author zhou * @since 2012-5-30下午12:12:42 */ public abstract class FurtherBasicBeanPane extends BasicBeanPane { - /** - * 是否是指定类型 - * @param ob 对象 - * @return 是否是指定类型 - */ - public abstract boolean accept(Object ob); + /** + * 是否是指定类型 + * + * @param ob 对象 + * @return 是否是指定类型 + */ + public abstract boolean accept(Object ob); - /** - * title应该是一个属性,不只是对话框的标题时用到,与其他组件结合时,也会用得到 - * @return 绥化狂标题 - */ - @Deprecated - public String title4PopupWindow(){ - return StringUtils.EMPTY; - } + /** + * title应该是一个属性,不只是对话框的标题时用到,与其他组件结合时,也会用得到 + * + * @return 对话框标题 + */ + @Override + public String title4PopupWindow() { + return StringUtils.EMPTY; + } + + /** + * 重置 + */ + public abstract void reset(); - /** - * 重置 - */ - public abstract void reset(); - } \ No newline at end of file From 5cd584fead94383e18d5c0afe4422546ac975231 Mon Sep 17 00:00:00 2001 From: "yaoh.wu" Date: Mon, 23 Jul 2018 10:44:13 +0800 Subject: [PATCH 3/8] =?UTF-8?q?REPORT-3961=20=E6=95=B0=E6=8D=AE=E5=88=97?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E5=88=86=E7=BB=84=E6=96=B0=E5=A2=9E=E7=9A=84?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E5=8F=B3=E4=BE=A7=E9=9D=A2=E6=9D=BF=E4=B8=8D?= =?UTF-8?q?=E5=88=B7=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/fr/design/condition/LiteConditionPane.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/designer-base/src/main/java/com/fr/design/condition/LiteConditionPane.java b/designer-base/src/main/java/com/fr/design/condition/LiteConditionPane.java index 5efa85dc5e..a85099c61c 100644 --- a/designer-base/src/main/java/com/fr/design/condition/LiteConditionPane.java +++ b/designer-base/src/main/java/com/fr/design/condition/LiteConditionPane.java @@ -857,9 +857,10 @@ public abstract class LiteConditionPane extends BasicBeanPa */ @Override public void populateBean(Condition liteCondition) { - if (liteCondition == null){ - return; - } + // liteCondition = null 时清空显示 +// if (liteCondition == null){ +// return; +// } // peter: 先删除所有的节点 DefaultTreeModel defaultTreeModel = (DefaultTreeModel) this.conditionsTree.getModel(); ExpandMutableTreeNode rootTreeNode = (ExpandMutableTreeNode) defaultTreeModel.getRoot(); @@ -900,7 +901,8 @@ public abstract class LiteConditionPane extends BasicBeanPa if (liteCondition == null) { try { defaultConditionPane.checkValid(); - } catch (Exception e) {//not need + } catch (Exception ignored) { + //not need } } } From a590853cf2e5832264ffbbeba83c8827f200c095 Mon Sep 17 00:00:00 2001 From: "yaoh.wu" Date: Mon, 23 Jul 2018 15:39:29 +0800 Subject: [PATCH 4/8] =?UTF-8?q?REPORT-8941=E3=80=9010.0=E8=BF=9C=E7=A8=8B?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1=E6=9D=83=E9=99=90=E7=AE=A1=E7=90=86=E3=80=91?= =?UTF-8?q?=E5=86=B3=E7=AD=96=E7=B3=BB=E7=BB=9F=E7=94=A8=E6=88=B7=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E4=B8=8D=E5=85=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fr/design/remote/ui/UserManagerPane.java | 126 ++++++++++++++++-- 1 file changed, 112 insertions(+), 14 deletions(-) diff --git a/designer-base/src/main/java/com/fr/design/remote/ui/UserManagerPane.java b/designer-base/src/main/java/com/fr/design/remote/ui/UserManagerPane.java index 97ffdd3b62..89fe84b63a 100644 --- a/designer-base/src/main/java/com/fr/design/remote/ui/UserManagerPane.java +++ b/designer-base/src/main/java/com/fr/design/remote/ui/UserManagerPane.java @@ -13,7 +13,7 @@ import com.fr.design.remote.ui.list.AddedMemberListCellRender; import com.fr.design.remote.ui.list.AddingMemberList; import com.fr.design.remote.ui.list.AddingMemberListCellRender; import com.fr.design.remote.ui.list.MemberListSelectedChangeListener; -import com.fr.general.Inter; +import com.fr.locale.InterProviderFactory; import com.fr.stable.StringUtils; import com.fr.third.guava.collect.ImmutableList; import com.fr.workspace.WorkContext; @@ -23,9 +23,12 @@ import com.fr.workspace.server.authority.decision.DecisionOperator; import javax.swing.BorderFactory; import javax.swing.DefaultListModel; import javax.swing.JPanel; +import javax.swing.JViewport; import javax.swing.ListSelectionModel; import javax.swing.SwingWorker; import javax.swing.border.EmptyBorder; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; @@ -33,10 +36,15 @@ import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.List; @@ -45,10 +53,15 @@ import java.util.List; */ public class UserManagerPane extends BasicPane { + /** + * 每页个数 + */ + private final int DEFAULT_NUM_EACH_PAGE = 50; + /** * 获取的决策平台成员 */ - private List addingMembers = new ArrayList<>(); + private final List addingMembers = new ArrayList<>(); /** * 添加到设计的决策平台成员 */ @@ -73,7 +86,7 @@ public class UserManagerPane extends BasicPane { private ActionListener keyButtonActionListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - searchAddingMembers(keyField.getText()); + searchAddingMembers(keyWord); } }; @@ -84,9 +97,9 @@ public class UserManagerPane extends BasicPane { @Override public void keyReleased(KeyEvent e) { // 判断按下的键是否是回车键 - // todo 对话框回车键绑定的是对话框的确定按钮 + // 对话框回车键绑定的是对话框的确定按钮,因此按确定没有办法搜索 if (e.getKeyCode() == KeyEvent.VK_ENTER) { - searchAddingMembers(keyField.getText()); + searchAddingMembers(keyWord); } } }; @@ -125,7 +138,7 @@ public class UserManagerPane extends BasicPane { sync2AddedMembersFormAdded(); // 不需要重复更新右侧列表显示 但是更新一下计数显示 countLabel.setText( - Inter.getLocText("Fine-Designer_Remote_Design_Selected_Member_Count", + InterProviderFactory.getProvider().getLocText("Fine-Designer_Remote_Design_Selected_Member_Count", String.valueOf(addedMembers.size()) ) ); @@ -134,9 +147,47 @@ public class UserManagerPane extends BasicPane { } }; + + + /** + * 已经添加的成员列表 + */ private AddedMemberList addedList; + /** + * 待添加的成员列表 + */ private AddingMemberList addingList; + /** + * 搜索关键字 + */ + private String keyWord; + + /** + * 搜索关键词变更监听 + */ + private DocumentListener documentListener = new DocumentListener() { + @Override + public void insertUpdate(DocumentEvent e) { + keyWord = keyField.getText(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + keyWord = keyField.getText(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + keyWord = keyField.getText(); + } + }; + + /** + * 当前分页计数 + */ + private int pageNum = 1; + public UserManagerPane() { this.setBorder(BorderFactory.createEmptyBorder()); @@ -155,7 +206,7 @@ public class UserManagerPane extends BasicPane { @Override protected String title4PopupWindow() { - return Inter.getLocText("Fine-Designer_Remote_Design_Add_Member"); + return InterProviderFactory.getProvider().getLocText("Fine-Designer_Remote_Design_Add_Member"); } private JPanel createLeftPanel() { @@ -165,7 +216,7 @@ public class UserManagerPane extends BasicPane { BorderFactory.createCompoundBorder( new EmptyBorder(6, 0, 0, 0), UITitledBorder.createBorderWithTitle( - Inter.getLocText("Fine-Designer_Remote_Design_Decision_Member") + InterProviderFactory.getProvider().getLocText("Fine-Designer_Remote_Design_Decision_Member") ) ) ); @@ -176,7 +227,8 @@ public class UserManagerPane extends BasicPane { keyField.setPreferredSize(new Dimension(250, 20)); keyField.requestFocus(); keyField.addKeyListener(keyFieldKeyListener); - keyButton.setText(Inter.getLocText("Fine-Designer_Remote_Design_Search")); + keyField.getDocument().addDocumentListener(documentListener); + keyButton.setText(InterProviderFactory.getProvider().getLocText("Fine-Designer_Remote_Design_Search")); keyButton.addActionListener(keyButtonActionListener); searchPanel.add(keyField); searchPanel.add(keyButton); @@ -189,7 +241,25 @@ public class UserManagerPane extends BasicPane { resetMembers(); addToMemberList(); searchAddingMembers(StringUtils.EMPTY); - UIScrollPane listPane = new UIScrollPane(addingList); + final UIScrollPane listPane = new UIScrollPane(addingList); + listPane.addMouseWheelListener(new MouseWheelListener() { + @Override + public void mouseWheelMoved(MouseWheelEvent e) { + JViewport vp = listPane.getViewport(); + if (vp.getView().getHeight() <= vp.getHeight() + vp.getViewPosition().y) { + loadMoreAddingMembers(keyWord, DEFAULT_NUM_EACH_PAGE); + } + } + }); + listPane.getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() { + @Override + public void adjustmentValueChanged(AdjustmentEvent e) { + JViewport vp = listPane.getViewport(); + if (vp.getView().getHeight() <= vp.getHeight() + vp.getViewPosition().y && e.getValueIsAdjusting()) { + loadMoreAddingMembers(keyWord, DEFAULT_NUM_EACH_PAGE); + } + } + }); listPane.setBorder(BorderFactory.createEmptyBorder()); content.add(searchPanel, BorderLayout.NORTH); @@ -205,14 +275,14 @@ public class UserManagerPane extends BasicPane { BorderFactory.createCompoundBorder( new EmptyBorder(6, 0, 0, 0), UITitledBorder.createBorderWithTitle( - Inter.getLocText("Fine-Designer_Remote_Design_Selected_Member") + InterProviderFactory.getProvider().getLocText("Fine-Designer_Remote_Design_Selected_Member") ) ) ); // 计数 countLabel.setText( - Inter.getLocText("Fine-Designer_Remote_Design_Selected_Member_Count", + InterProviderFactory.getProvider().getLocText("Fine-Designer_Remote_Design_Selected_Member_Count", String.valueOf(addedMembers.size())) ); countLabel.setBorder(BorderFactory.createEmptyBorder(7, 12, 8, 0)); @@ -258,7 +328,7 @@ public class UserManagerPane extends BasicPane { addedList.revalidate(); addedList.repaint(); countLabel.setText( - Inter.getLocText("Fine-Designer_Remote_Design_Selected_Member_Count", + InterProviderFactory.getProvider().getLocText("Fine-Designer_Remote_Design_Selected_Member_Count", String.valueOf(addedMembers.size()) )); } @@ -280,7 +350,10 @@ public class UserManagerPane extends BasicPane { protected List doInBackground() { addingMembers.clear(); String username = WorkContext.getConnector().currentUser(); - addingMembers.addAll(WorkContext.getCurrent().get(DecisionOperator.class).getMembers(username, keyword)); + synchronized (addingMembers) { + addingMembers.addAll(WorkContext.getCurrent().get(DecisionOperator.class).getMembers(username, keyword)); + pageNum = 1; + } return addingMembers; } @@ -292,6 +365,31 @@ public class UserManagerPane extends BasicPane { getMemberWorker.execute(); } + private void loadMoreAddingMembers(final String keyword, final int count) { + + final SwingWorker loadMoreWorker = new SwingWorker, Void>() { + @Override + protected List doInBackground() { + String username = WorkContext.getConnector().currentUser(); + synchronized (addingMembers) { + Collection more = + WorkContext.getCurrent().get(DecisionOperator.class).getMembers(username, keyword, pageNum + 1, count); + if (!more.isEmpty()) { + pageNum += 1; + } + addingMembers.addAll(more); + } + return addingMembers; + } + + @Override + protected void done() { + addToMemberList(); + } + }; + loadMoreWorker.execute(); + } + private void sync2AddedMembersFromAdding() { RemoteDesignMember[] members = new RemoteDesignMember[addingListModel.getSize()]; From 952b2c71029afdbc7cc46361ce97796abff2d803 Mon Sep 17 00:00:00 2001 From: "yaoh.wu" Date: Mon, 23 Jul 2018 21:20:12 +0800 Subject: [PATCH 5/8] REPORT-6700 REPORT-8957 REPORT-8941 REPORT-7941 REPORT-8392 --- .../com/fr/design/file/TemplateTreePane.java | 65 +- .../fr/design/gui/icheckbox/UICheckBox.java | 363 +++++----- .../CheckBoxTreeCellRenderer.java | 15 +- .../checkboxtree/NullTristateCheckBox.java | 14 +- .../itree/checkboxtree/TristateCheckBox.java | 201 ++++-- .../gui/itree/filetree/EnvFileTree.java | 665 +++++++++--------- .../gui/itree/filetree/FileTreeIcon.java | 64 +- .../gui/itree/filetree/TemplateFileTree.java | 29 +- .../ExpandMutableTreeNode.java | 51 +- .../refreshabletree/RefreshableJTree.java | 80 ++- .../design/remote/ui/AuthorityEditorPane.java | 4 +- .../filetree_folder_half_authority_normal.png | Bin 0 -> 337 bytes 12 files changed, 875 insertions(+), 676 deletions(-) create mode 100644 designer-base/src/main/resources/com/fr/design/images/gui/filetree_folder_half_authority_normal.png diff --git a/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java b/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java index 5deef13df7..1f4630cc24 100644 --- a/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java +++ b/designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java @@ -23,9 +23,13 @@ import com.fr.stable.StableUtils; import com.fr.stable.project.ProjectConstants; import com.fr.workspace.WorkContext; -import javax.swing.*; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.ToolTipManager; import javax.swing.tree.DefaultMutableTreeNode; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Desktop; +import java.awt.Dimension; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseAdapter; @@ -59,9 +63,27 @@ public class TemplateTreePane extends JPanel implements FileOperations { scrollPane.setBorder(null); contentPane.add(scrollPane, BorderLayout.CENTER); - this.reportletsTree.addMouseListener(mouseFileTreeListener);// lx: add - // mouse - // listener + /* + * Tree.MouseAdapter + */ + MouseListener mouseFileTreeListener = new MouseAdapter() { + + @Override + public void mousePressed(MouseEvent evt) { + if (evt.getClickCount() == 2) { + openSelectedReport(); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + if (toobarStateChangeListener != null) { + toobarStateChangeListener.stateChange(); + } + } + }; + // lx: add mouse listener + this.reportletsTree.addMouseListener(mouseFileTreeListener); this.reportletsTree.addKeyListener(new KeyListener() { @Override @@ -102,42 +124,21 @@ public class TemplateTreePane extends JPanel implements FileOperations { reportletsTree.refreshEnv(); } - /* - * Tree.MouseAdapter - */ - MouseListener mouseFileTreeListener = new MouseAdapter() { - - @Override - public void mousePressed(MouseEvent evt) { - if (SwingUtilities.isRightMouseButton(evt)) { - return; - } else if (evt.getClickCount() == 2) { - openSelectedReport(); - } - - - } - - public void mouseReleased(MouseEvent e) { - if (toobarStateChangeListener != null) { - toobarStateChangeListener.stateChange(); - } - } - }; - /** * 打开选中的报表文件 */ + @Override public void openSelectedReport() { String reportPath = reportletsTree.getSelectedTemplatePath(); - final String selectedFilePath = StableUtils.pathJoin(new String[]{ProjectConstants.REPORTLETS_NAME, reportPath}); + final String selectedFilePath = StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, reportPath); DesignerContext.getDesignerFrame().openTemplate(new FileNodeFILE(new FileNode(selectedFilePath, false))); } /** * 打开文件夹 */ + @Override public void openContainerFolder() { FileNode fn = TemplateTreePane.this.reportletsTree.getSelectedFileNode(); String filePath = StableUtils.pathJoin(WorkContext.getCurrent().getPath(), fn.getEnvPath()); @@ -152,6 +153,7 @@ public class TemplateTreePane extends JPanel implements FileOperations { /** * 刷新 */ + @Override public void refresh() { reportletsTree.refresh(); FineLoggerFactory.getLogger().info(Inter.getLocText(new String[]{"File-tree", "Refresh_Successfully"}) + "!"); @@ -160,6 +162,7 @@ public class TemplateTreePane extends JPanel implements FileOperations { /** * 删除文件 */ + @Override public void deleteFile() { String[] reportPaths = reportletsTree.getSelectedTemplatePaths(); if (reportPaths.length == 0) { @@ -169,7 +172,7 @@ public class TemplateTreePane extends JPanel implements FileOperations { return; } for (String reportPath : reportPaths) { - FileNodeFILE nodeFile = new FileNodeFILE(new FileNode(StableUtils.pathJoin(new String[]{ProjectConstants.REPORTLETS_NAME, reportPath}), false)); + FileNodeFILE nodeFile = new FileNodeFILE(new FileNode(StableUtils.pathJoin(ProjectConstants.REPORTLETS_NAME, reportPath), false)); if (nodeFile.isLocked()) { if (JOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), Inter.getLocText("fileLocked_undeleted"), @@ -226,6 +229,7 @@ public class TemplateTreePane extends JPanel implements FileOperations { } + @Override public String getSelectedTemplatePath() { return reportletsTree.getSelectedTemplatePath(); } @@ -242,6 +246,7 @@ public class TemplateTreePane extends JPanel implements FileOperations { * @param suffix 后缀名 * @return 是否存在 */ + @Override public boolean isNameAlreadyExist(String newName, String oldName, String suffix) { boolean isNameAlreadyExist = false; diff --git a/designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBox.java b/designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBox.java index 9d49bd06ec..825dfc629f 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBox.java +++ b/designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBox.java @@ -5,199 +5,198 @@ import com.fr.design.event.GlobalNameListener; import com.fr.design.event.GlobalNameObserver; import com.fr.design.event.UIObserver; import com.fr.design.event.UIObserverListener; -import com.fr.design.utils.gui.GUICoreUtils; import com.fr.design.utils.gui.GUIPaintUtils; import com.fr.stable.Constants; import sun.swing.SwingUtilities2; -import javax.swing.*; +import javax.swing.AbstractButton; +import javax.swing.ButtonModel; +import javax.swing.Icon; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; import javax.swing.plaf.basic.BasicHTML; import javax.swing.plaf.metal.MetalCheckBoxUI; import javax.swing.text.View; -import java.awt.*; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.RenderingHints; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; public class UICheckBox extends JCheckBox implements UIObserver, GlobalNameObserver { - private UIObserverListener uiObserverListener; - private GlobalNameListener globalNameListener = null; - private String checkboxName = ""; - - public UICheckBox(String string) { - super(string); - setUI(new UICheckBoxUI()); - initListener(); - } - - public UICheckBox() { - super(); - setUI(new UICheckBoxUI()); - initListener(); - } - - public UICheckBox(String locText, boolean b) { - super(locText, b); - setUI(new UICheckBoxUI()); - initListener(); - } - - public UICheckBox(String text, Icon icon) { - super(text, icon); - setUI(new UICheckBoxUI()); - initListener(); - } - - private void initListener() { - if (shouldResponseChangeListener()) { - this.addItemListener(new ItemListener() { - - @Override - public void itemStateChanged(ItemEvent e) { - if (uiObserverListener == null) { - return; - } - if (globalNameListener != null && shouldResponseNameListener()) { - globalNameListener.setGlobalName(checkboxName); - } - uiObserverListener.doChange(); - } - }); - } - } - - /** - * 给组件登记一个观察者监听事件 - * - * @param listener 观察者监听事件 - */ - public void registerChangeListener(UIObserverListener listener) { - this.uiObserverListener = listener; - } - - - public void setGlobalName(String name) { - checkboxName = name; - } - - /** - * 组件是否需要响应添加的观察者事件 - * - * @return 如果需要响应观察者事件则返回true,否则返回false - */ - public boolean shouldResponseChangeListener() { - return true; - } - - /** - * 注册观察者监听事件 - * @param listener 观察者监听事件 - */ - public void registerNameListener(GlobalNameListener listener) { - globalNameListener = listener; - } - - /** - * 组件是否需要响应观察者事件 - * @return 如果需要响应观察者事件则返回true,否则返回false - */ - public boolean shouldResponseNameListener() { - return true; - } - - private class UICheckBoxUI extends MetalCheckBoxUI { - public void paint(Graphics g, JComponent c) { - synchronized (this) { - AbstractButton b = (AbstractButton) c; - ButtonModel model = b.getModel(); - Dimension size = c.getSize(); - Font f = c.getFont(); - g.setFont(f); - FontMetrics fm = SwingUtilities2.getFontMetrics(c, g, f); - - Rectangle viewRect = new Rectangle(size); - Rectangle iconRect = new Rectangle(); - Rectangle textRect = new Rectangle(); - - Insets i = c.getInsets(); - viewRect.x += i.left; - viewRect.y += i.top; - viewRect.width -= (i.right + viewRect.x); - viewRect.height -= (i.bottom + viewRect.y); - - Icon altIcon = b.getIcon(); - - String text = SwingUtilities.layoutCompoundLabel( - c, fm, b.getText(), altIcon != null ? altIcon : getDefaultIcon(), - b.getVerticalAlignment(), b.getHorizontalAlignment(), - b.getVerticalTextPosition(), b.getHorizontalTextPosition(), - viewRect, iconRect, textRect, b.getIconTextGap()); - - // fill background - if (c.isOpaque()) { - g.setColor(b.getBackground()); - g.fillRect(0, 0, size.width, size.height); - } - - Graphics2D g2d = (Graphics2D) g; - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - if ( model.isSelected()) { - GUIPaintUtils.fillPaint(g2d, iconRect.x, iconRect.y, iconRect.width, iconRect.height,false, Constants.NULL, - model.isEnabled() ? UIConstants.CHECKBOX_HOVER_SELECTED : UIConstants.DISABLED_ICON_COLOR, 0); - } else if (model.isRollover() && ! model.isSelected()) { + private UIObserverListener uiObserverListener; + private GlobalNameListener globalNameListener = null; + private String checkboxName = ""; + + public UICheckBox(String string) { + super(string); + setUI(new UICheckBoxUI()); + initListener(); + } + + public UICheckBox() { + super(); + setUI(new UICheckBoxUI()); + initListener(); + } + + public UICheckBox(String locText, boolean b) { + super(locText, b); + setUI(new UICheckBoxUI()); + initListener(); + } + + public UICheckBox(String text, Icon icon) { + super(text, icon); + setUI(new UICheckBoxUI()); + initListener(); + } + + private void initListener() { + if (shouldResponseChangeListener()) { + this.addItemListener(new ItemListener() { + + @Override + public void itemStateChanged(ItemEvent e) { + if (uiObserverListener == null) { + return; + } + if (globalNameListener != null && shouldResponseNameListener()) { + globalNameListener.setGlobalName(checkboxName); + } + uiObserverListener.doChange(); + } + }); + } + } + + /** + * 给组件登记一个观察者监听事件 + * + * @param listener 观察者监听事件 + */ + @Override + public void registerChangeListener(UIObserverListener listener) { + this.uiObserverListener = listener; + } + + + @Override + public void setGlobalName(String name) { + checkboxName = name; + } + + /** + * 组件是否需要响应添加的观察者事件 + * + * @return 如果需要响应观察者事件则返回true,否则返回false + */ + @Override + public boolean shouldResponseChangeListener() { + return true; + } + + /** + * 注册观察者监听事件 + * + * @param listener 观察者监听事件 + */ + @Override + public void registerNameListener(GlobalNameListener listener) { + globalNameListener = listener; + } + + /** + * 组件是否需要响应观察者事件 + * + * @return 如果需要响应观察者事件则返回true,否则返回false + */ + @Override + public boolean shouldResponseNameListener() { + return true; + } + + private class UICheckBoxUI extends MetalCheckBoxUI { + @Override + public void paint(Graphics g, JComponent c) { + synchronized (this) { + AbstractButton b = (AbstractButton) c; + ButtonModel model = b.getModel(); + Dimension size = c.getSize(); + Font f = c.getFont(); + g.setFont(f); + FontMetrics fm = SwingUtilities2.getFontMetrics(c, g, f); + + Rectangle viewRect = new Rectangle(size); + Rectangle iconRect = new Rectangle(); + Rectangle textRect = new Rectangle(); + + Insets i = c.getInsets(); + viewRect.x += i.left; + viewRect.y += i.top; + viewRect.width -= (i.right + viewRect.x); + viewRect.height -= (i.bottom + viewRect.y); + + Icon altIcon = b.getIcon(); + + String text = SwingUtilities.layoutCompoundLabel( + c, fm, b.getText(), altIcon != null ? altIcon : getDefaultIcon(), + b.getVerticalAlignment(), b.getHorizontalAlignment(), + b.getVerticalTextPosition(), b.getHorizontalTextPosition(), + viewRect, iconRect, textRect, b.getIconTextGap()); + + // fill background + if (c.isOpaque()) { + g.setColor(b.getBackground()); + g.fillRect(0, 0, size.width, size.height); + } + + Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + if (model.isSelected()) { + GUIPaintUtils.fillPaint(g2d, iconRect.x, iconRect.y, iconRect.width, iconRect.height, false, Constants.NULL, + model.isEnabled() ? UIConstants.CHECKBOX_HOVER_SELECTED : UIConstants.DISABLED_ICON_COLOR, 0); + } else if (model.isRollover() && !model.isSelected()) { g.setColor(UIConstants.CHECKBOX_HOVER_SELECTED); g2d.drawRoundRect(iconRect.x, iconRect.y, iconRect.width - 1, iconRect.height - 1, UIConstants.ARC, UIConstants.ARC); - }else{ - g.setColor(UIConstants.LINE_COLOR); - g2d.drawRoundRect(iconRect.x, iconRect.y, iconRect.width - 1, iconRect.height - 1, UIConstants.ARC, UIConstants.ARC); - } - - if (model.isSelected()) { - UIConstants.YES_ICON.paintIcon(c, g, iconRect.x + 2, iconRect.y + 2); - } - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - - // Draw the Text - drawLine(text, g, b, c, textRect, fm); - } - } - - private void drawLine(String text, Graphics g, AbstractButton b, JComponent c, Rectangle textRect, FontMetrics fm) { - if (text != null) { - View v = (View) c.getClientProperty(BasicHTML.propertyKey); - if (v != null) { - v.paint(g, textRect); - } else { - int mnemIndex = b.getDisplayedMnemonicIndex(); - if (model.isEnabled()) { - g.setColor(b.getForeground()); - } else { - g.setColor(getDisabledTextColor()); - } - SwingUtilities2.drawStringUnderlineCharAt(c, g, text, - mnemIndex, textRect.x, textRect.y + fm.getAscent()); - } - } - } - - } - - /** - * 测试 - * @param args 参数 - */ - public static void main(String... args) { - LayoutManager layoutManager = null; - JFrame jf = new JFrame("test"); - jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - JPanel content = (JPanel) jf.getContentPane(); - content.setLayout(layoutManager); - - UICheckBox bb = new UICheckBox("sdf"); - bb.setEnabled(false); - bb.setBounds(20, 20, bb.getPreferredSize().width, bb.getPreferredSize().height); - content.add(bb); - GUICoreUtils.centerWindow(jf); - jf.setSize(400, 400); - jf.setVisible(true); - } + } else { + g.setColor(UIConstants.LINE_COLOR); + g2d.drawRoundRect(iconRect.x, iconRect.y, iconRect.width - 1, iconRect.height - 1, UIConstants.ARC, UIConstants.ARC); + } + + if (model.isSelected()) { + UIConstants.YES_ICON.paintIcon(c, g, iconRect.x + 2, iconRect.y + 2); + } + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + + // Draw the Text + drawLine(text, g, b, c, textRect, fm); + } + } + + private void drawLine(String text, Graphics g, AbstractButton b, JComponent c, Rectangle textRect, FontMetrics fm) { + if (text != null) { + View v = (View) c.getClientProperty(BasicHTML.propertyKey); + if (v != null) { + v.paint(g, textRect); + } else { + int mnemIndex = b.getDisplayedMnemonicIndex(); + if (model.isEnabled()) { + g.setColor(b.getForeground()); + } else { + g.setColor(getDisabledTextColor()); + } + SwingUtilities2.drawStringUnderlineCharAt(c, g, text, + mnemIndex, textRect.x, textRect.y + fm.getAscent()); + } + } + } + + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/CheckBoxTreeCellRenderer.java b/designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/CheckBoxTreeCellRenderer.java index 9684d39478..769ff4a60d 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/CheckBoxTreeCellRenderer.java +++ b/designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/CheckBoxTreeCellRenderer.java @@ -10,12 +10,17 @@ import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.ilable.UILabel; import com.fr.design.layout.FRGUIPaneFactory; -import javax.swing.*; +import javax.swing.BorderFactory; +import javax.swing.JComponent; +import javax.swing.JTree; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.tree.TreeCellRenderer; import javax.swing.tree.TreePath; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Point; import java.awt.event.MouseEvent; import java.io.Serializable; @@ -77,10 +82,10 @@ public class CheckBoxTreeCellRenderer extends NullPanel implements TreeCellRende _checkBox.setEnabled(((CheckBoxTree) tree).isCheckBoxEnabled() && ((CheckBoxTree) tree).isCheckBoxEnabled(path)); if (selectionModel.isPathSelected(path, selectionModel.isDigIn())) { _checkBox.setState(TristateCheckBox.SELECTED); - _checkBox.setSelected(true); + } else if (selectionModel.isDigIn() && selectionModel.isPartiallySelected(path)) { + _checkBox.setState(TristateCheckBox.DO_NOT_CARE); } else { - _checkBox.setState(selectionModel.isDigIn() && selectionModel.isPartiallySelected(path) ? null : TristateCheckBox.NOT_SELECTED); - _checkBox.setSelected(false); + _checkBox.setState(TristateCheckBox.NOT_SELECTED); } } } diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/NullTristateCheckBox.java b/designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/NullTristateCheckBox.java index 4e10b1a97f..2d742165c3 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/NullTristateCheckBox.java +++ b/designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/NullTristateCheckBox.java @@ -42,10 +42,7 @@ import javax.swing.Icon; * * * @see NullPanel - * @see NullButton - * @see NullJideButton * @see NullLabel - * @see NullRadioButton */ public class NullTristateCheckBox extends TristateCheckBox { public NullTristateCheckBox() { @@ -63,7 +60,7 @@ public class NullTristateCheckBox extends TristateCheckBox { super(text, icon, initial); } -// @Override + @Override public void updateUI() { clearAttribute(); } @@ -73,4 +70,13 @@ public class NullTristateCheckBox extends TristateCheckBox { setBackground(null); setForeground(null); } + + @Override + protected State getNextState(State current) { + if (SELECTED.equals(current)) { + return NOT_SELECTED; + } else { + return SELECTED; + } + } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/TristateCheckBox.java b/designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/TristateCheckBox.java index 1cdbd77efa..ad9d7e8221 100644 --- a/designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/TristateCheckBox.java +++ b/designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/TristateCheckBox.java @@ -1,28 +1,44 @@ package com.fr.design.gui.itree.checkboxtree; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.ItemListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; +import com.fr.design.constants.UIConstants; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.utils.gui.GUIPaintUtils; +import com.fr.stable.Constants; +import sun.swing.SwingUtilities2; import javax.swing.AbstractAction; +import javax.swing.AbstractButton; import javax.swing.ActionMap; import javax.swing.ButtonGroup; import javax.swing.ButtonModel; import javax.swing.Icon; +import javax.swing.JComponent; import javax.swing.SwingUtilities; import javax.swing.event.ChangeListener; import javax.swing.plaf.ActionMapUIResource; - -import com.fr.design.gui.icheckbox.UICheckBox; +import javax.swing.plaf.basic.BasicHTML; +import javax.swing.plaf.metal.MetalCheckBoxUI; +import javax.swing.text.View; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; /** * Maintenance tip - There were some tricks to getting this code * working: *

- * 1. You have to overwite addMouseListener() to do nothing + * 1. You have to overwrite addMouseListener() to do nothing * 2. You have to add a mouse event on mousePressed by calling * super.addMouseListener() * 3. You have to replace the UIActionMap for the keyboard event @@ -41,21 +57,30 @@ public class TristateCheckBox extends UICheckBox { * This is a type-safe enumerated type */ public static class State { - private State() { + private String type; + + private State(String type) { + this.type = type; + } + + @Override + public String toString() { + return this.type; } } - public static final State NOT_SELECTED = new State(); - public static final State SELECTED = new State(); - public static final State DONT_CARE = new State(); + public static final State NOT_SELECTED = new State("NOT_SELECTED"); + public static final State SELECTED = new State("SELECTED"); + public static final State DO_NOT_CARE = new State("DO_NOT_CARE"); private final TristateDecorator model; public TristateCheckBox(String text, Icon icon, State initial) { super(text, icon); + setUI(new TristateUICheckBoxUI()); // Add a listener for when the mouse is pressed super.addMouseListener(new MouseAdapter() { -// @Override + @Override public void mousePressed(MouseEvent e) { grabFocus(); model.setState(getNextState(model.getState())); @@ -64,6 +89,7 @@ public class TristateCheckBox extends UICheckBox { // Reset the keyboard action map ActionMap map = new ActionMapUIResource(); map.put("pressed", new AbstractAction() { + @Override public void actionPerformed(ActionEvent e) { grabFocus(); model.setState(getNextState(model.getState())); @@ -79,26 +105,29 @@ public class TristateCheckBox extends UICheckBox { public TristateCheckBox(String text, State initial) { this(text, null, initial); + setUI(new TristateUICheckBoxUI()); } public TristateCheckBox(String text) { - this(text, DONT_CARE); + this(text, DO_NOT_CARE); + setUI(new TristateUICheckBoxUI()); } public TristateCheckBox() { this(null); + setUI(new TristateUICheckBoxUI()); } /** * No one may add mouse listeners, not even Swing! */ -// @Override + @Override public void addMouseListener(MouseListener l) { } /** * Set the new state to either SELECTED, NOT_SELECTED or - * DONT_CARE. If state == null, it is treated as DONT_CARE. + * DO_NOT_CARE. If state == null, it is treated as DO_NOT_CARE. */ public void setState(State state) { model.setState(state); @@ -112,15 +141,6 @@ public class TristateCheckBox extends UICheckBox { return model.getState(); } -// @Override - public void setSelected(boolean b) { - if (b) { - setState(SELECTED); - } - else { - setState(NOT_SELECTED); - } - } /** * Exactly which Design Pattern is this? Is it an Adapter, @@ -140,13 +160,13 @@ public class TristateCheckBox extends UICheckBox { other.setArmed(false); setPressed(false); setSelected(false); - } - else if (state == SELECTED) { + } else if (state == SELECTED) { other.setArmed(false); setPressed(false); setSelected(true); } - else { // either "null" or DONT_CARE + // either "null" or DO_NOT_CARE + else { other.setArmed(true); setPressed(true); setSelected(true); @@ -158,7 +178,7 @@ public class TristateCheckBox extends UICheckBox { * state of the model. *

* We return the SELECTED state when the checkbox is selected - * but not armed, DONT_CARE state when the checkbox is + * but not armed, DO_NOT_CARE state when the checkbox is * selected and armed (grey) and NOT_SELECTED when the * checkbox is deselected. */ @@ -166,12 +186,10 @@ public class TristateCheckBox extends UICheckBox { if (isSelected() && !isArmed()) { // normal black tick return SELECTED; - } - else if (isSelected() && isArmed()) { + } else if (isSelected() && isArmed()) { // don't care grey tick - return DONT_CARE; - } - else { + return DO_NOT_CARE; + } else { // normal deselected return NOT_SELECTED; } @@ -180,6 +198,7 @@ public class TristateCheckBox extends UICheckBox { /** * Filter: No one may change the armed status except us. */ + @Override public void setArmed(boolean b) { } @@ -187,6 +206,7 @@ public class TristateCheckBox extends UICheckBox { * We disable focusing on the component when it is not * enabled. */ + @Override public void setEnabled(boolean b) { setFocusable(b); other.setEnabled(b); @@ -196,89 +216,109 @@ public class TristateCheckBox extends UICheckBox { * All these methods simply delegate to the "other" model * that is being decorated. */ + @Override public boolean isArmed() { return other.isArmed(); } + @Override public boolean isSelected() { return other.isSelected(); } + @Override public boolean isEnabled() { return other.isEnabled(); } + @Override public boolean isPressed() { return other.isPressed(); } + @Override public boolean isRollover() { return other.isRollover(); } + @Override public void setSelected(boolean b) { other.setSelected(b); } + @Override public void setPressed(boolean b) { other.setPressed(b); } + @Override public void setRollover(boolean b) { other.setRollover(b); } + @Override public void setMnemonic(int key) { other.setMnemonic(key); } + @Override public int getMnemonic() { return other.getMnemonic(); } + @Override public void setActionCommand(String s) { other.setActionCommand(s); } + @Override public String getActionCommand() { return other.getActionCommand(); } + @Override public void setGroup(ButtonGroup group) { other.setGroup(group); } + @Override public void addActionListener(ActionListener l) { other.addActionListener(l); } + @Override public void removeActionListener(ActionListener l) { other.removeActionListener(l); } + @Override public void addItemListener(ItemListener l) { other.addItemListener(l); } + @Override public void removeItemListener(ItemListener l) { other.removeItemListener(l); } + @Override public void addChangeListener(ChangeListener l) { other.addChangeListener(l); } + @Override public void removeChangeListener(ChangeListener l) { other.removeChangeListener(l); } + @Override public Object[] getSelectedObjects() { return other.getSelectedObjects(); } } /** - * We rotate between NOT_SELECTED, SELECTED and DONT_CARE. Subclass can + * We rotate between NOT_SELECTED, SELECTED and DO_NOT_CARE. Subclass can * override this method to tell the check box what next state is. Here is * the default implementation. *

@@ -286,7 +326,7 @@ public class TristateCheckBox extends UICheckBox {
      *       return SELECTED;
      *   }
      *   else if (current == SELECTED) {
-     *       return DONT_CARE;
+     *       return DO_NOT_CARE;
      *   }
      *   else {
      *       return NOT_SELECTED;
@@ -296,12 +336,91 @@ public class TristateCheckBox extends UICheckBox {
     protected State getNextState(State current) {
         if (current == NOT_SELECTED) {
             return SELECTED;
+        } else if (current == SELECTED) {
+            return DO_NOT_CARE;
+        } else {
+            return NOT_SELECTED;
         }
-        else if (current == SELECTED) {
-            return DONT_CARE;
+    }
+
+    private class TristateUICheckBoxUI extends MetalCheckBoxUI {
+        @Override
+        public void paint(Graphics g, JComponent c) {
+            synchronized (this) {
+                AbstractButton b = (AbstractButton) c;
+                ButtonModel model = b.getModel();
+                Dimension size = c.getSize();
+                Font f = c.getFont();
+                g.setFont(f);
+                FontMetrics fm = SwingUtilities2.getFontMetrics(c, g, f);
+
+                Rectangle viewRect = new Rectangle(size);
+                Rectangle iconRect = new Rectangle();
+                Rectangle textRect = new Rectangle();
+
+                Insets i = c.getInsets();
+                viewRect.x += i.left;
+                viewRect.y += i.top;
+                viewRect.width -= (i.right + viewRect.x);
+                viewRect.height -= (i.bottom + viewRect.y);
+
+                Icon altIcon = b.getIcon();
+
+                String text = SwingUtilities.layoutCompoundLabel(
+                        c, fm, b.getText(), altIcon != null ? altIcon : getDefaultIcon(),
+                        b.getVerticalAlignment(), b.getHorizontalAlignment(),
+                        b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
+                        viewRect, iconRect, textRect, b.getIconTextGap());
+
+                // fill background
+                if (c.isOpaque()) {
+                    g.setColor(b.getBackground());
+                    g.fillRect(0, 0, size.width, size.height);
+                }
+
+                Graphics2D g2d = (Graphics2D) g;
+                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+                if (SELECTED.equals(getState())) {
+                    GUIPaintUtils.fillPaint(g2d, iconRect.x, iconRect.y, iconRect.width, iconRect.height, false, Constants.NULL,
+                            model.isEnabled() ? UIConstants.CHECKBOX_HOVER_SELECTED : UIConstants.DISABLED_ICON_COLOR, 0);
+                } else if (model.isRollover() && !SELECTED.equals(getState())) {
+                    g.setColor(UIConstants.CHECKBOX_HOVER_SELECTED);
+                    g2d.drawRoundRect(iconRect.x, iconRect.y, iconRect.width - 1, iconRect.height - 1, UIConstants.ARC, UIConstants.ARC);
+                } else {
+                    g.setColor(UIConstants.LINE_COLOR);
+                    g2d.drawRoundRect(iconRect.x, iconRect.y, iconRect.width - 1, iconRect.height - 1, UIConstants.ARC, UIConstants.ARC);
+                }
+
+                if (SELECTED.equals(getState())) {
+                    UIConstants.YES_ICON.paintIcon(c, g, iconRect.x + 2, iconRect.y + 2);
+                } else if (DO_NOT_CARE.equals(getState())) {
+                    g.setColor(UIConstants.CHECKBOX_HOVER_SELECTED);
+                    g2d.fillRoundRect(iconRect.x + 2, iconRect.y + 2, iconRect.width - 4, iconRect.height - 4, UIConstants.ARC, UIConstants.ARC);
+                }
+                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
+
+                // Draw the Text
+                drawLine(text, g, b, c, textRect, fm);
+            }
         }
-        else /*if (current == DONT_CARE)*/ {
-            return NOT_SELECTED;
+
+        private void drawLine(String text, Graphics g, AbstractButton b, JComponent c, Rectangle textRect, FontMetrics fm) {
+            if (text != null) {
+                View v = (View) c.getClientProperty(BasicHTML.propertyKey);
+                if (v != null) {
+                    v.paint(g, textRect);
+                } else {
+                    int mnemIndex = b.getDisplayedMnemonicIndex();
+                    if (model.isEnabled()) {
+                        g.setColor(b.getForeground());
+                    } else {
+                        g.setColor(getDisabledTextColor());
+                    }
+                    SwingUtilities2.drawStringUnderlineCharAt(c, g, text,
+                            mnemIndex, textRect.x, textRect.y + fm.getAscent());
+                }
+            }
         }
+
     }
 }
\ No newline at end of file
diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/EnvFileTree.java b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/EnvFileTree.java
index 125c3a4c6b..af6822c952 100644
--- a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/EnvFileTree.java
+++ b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/EnvFileTree.java
@@ -8,16 +8,19 @@ import com.fr.design.gui.itree.refreshabletree.RefreshableJTree;
 import com.fr.file.filetree.FileNode;
 import com.fr.file.filetree.FileNodeFilter;
 import com.fr.general.ComparatorUtils;
-import com.fr.general.Inter;
+import com.fr.locale.InterProviderFactory;
+import com.fr.log.FineLoggerFactory;
 import com.fr.stable.CoreConstants;
 import com.fr.stable.StableUtils;
 import com.fr.workspace.WorkContext;
 
-import javax.swing.*;
+import javax.swing.JTree;
 import javax.swing.tree.DefaultTreeCellRenderer;
 import javax.swing.tree.DefaultTreeModel;
 import javax.swing.tree.TreePath;
-import java.awt.*;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -27,330 +30,334 @@ import java.util.Arrays;
  */
 public class EnvFileTree extends RefreshableJTree {
 
-	protected FileNodeFilter filter;
-	protected String treeRootPath = "";
-	protected String[] subPathes;
-
-	public EnvFileTree() {
-		this(null, null);
-	}
-
-	public EnvFileTree(String[] subPathes, FileNodeFilter filter) {
-		this("", subPathes, filter);
-	}
-
-	public EnvFileTree(String treeRootPath, String[] subPathes, FileNodeFilter filter) {
-		super(new FileNode(treeRootPath, true));
-
-		this.setTreeRootPath(treeRootPath);
-		this.setFileNodeFilter(filter);
-		this.setSubPathes(subPathes);
-
-		/*一些自己的 init 放在这里,防止直接错误重写了父类的 init 方法导致子类不能使用 CheckBoxTree 的一些特性。*/
-		this.putClientProperty("JTree.lineStyle", "Angled");
-
-		this.setCellRenderer(fileTreeCellRenderer);
-
-		this.setRootVisible(false);
-		this.setShowsRootHandles(true);
-		this.setEditable(false);
-	}
-
-	private void setTreeRootPath(String path) {
-		if (path == null) {
-			path = "";
-		}
-
-		this.treeRootPath = path;
-	}
-
-	public void setFileNodeFilter(FileNodeFilter filter) {
-		this.filter = filter;
-	}
-
-	// CellRenderer
-	private DefaultTreeCellRenderer fileTreeCellRenderer = new DefaultTreeCellRenderer() {
-
-		@Override
-		public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row,
-				boolean hasFocus) {
-			super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
-			ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) value;
-			Object userObj = treeNode.getUserObject();
-			if (userObj instanceof FileNode) {
-				FileNode node = (FileNode) userObj;
-				String lock = node.getLock();
-				String name = node.getName();
-				if (lock != null && !node.getUserID().equals(lock)) {
-					name = name + Inter.getLocText("Locked");
-					this.setIcon(FileTreeIcon.getIcon(node));
-				}else {
-					this.setIcon(FileTreeIcon.getIcon(node, false));
-				}
-				this.setText(name);
-			} else if (userObj == PENDING) {
-				this.setIcon(null);
-				this.setText(PENDING.toString());
-			}
-			// 这里新建一个Label作为render是因为JTree在动态刷新的时候,节点上render画布的的宽度不会变,会使得一部分比较长的数据显示为"..."
-			UILabel label = new UILabel();
-			label.setText(getText());
-			label.setIcon(getIcon());
-			this.setSize(label.getPreferredSize());
-			Dimension dim = label.getPreferredSize();
-			dim.height += 2;
-			this.setPreferredSize(dim);
-			this.setBackgroundNonSelectionColor(UIConstants.TREE_BACKGROUND);
-			this.setTextSelectionColor(Color.WHITE);
-			this.setBackgroundSelectionColor(UIConstants.FLESH_BLUE);
-			return this;
-		}
-	};
-
-	/*
-	 * 在当前tree中选中currentPath
-	 */
-	public void selectPath(String currentPath) {
-		if (currentPath == null) {
-			return;
-		}
-
-		DefaultTreeModel m_model = (DefaultTreeModel) this.getModel();
-		ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) m_model.getRoot();
-		for (int i = 0, len = treeNode.getChildCount(); i < len; i++) {
-			// 取出当前的childTreeNode,并append到searchingPath后面
-			ExpandMutableTreeNode childTreeNode = (ExpandMutableTreeNode) treeNode.getChildAt(i);
-
-			if (selectFilePath(childTreeNode, "", currentPath, m_model)) {
-				break;
-			}
-		}
-
-		TreePath selectedTreePath = this.getSelectionPath();
-		if (selectedTreePath != null) {
-			this.scrollPathToVisible(selectedTreePath);
-		}
-	}
-
-	/*
-	 * 在currentTreeNode下找寻filePath
-	 * 
-	 * prefix + currentTreeNode.getName() = currentTreeNode所对应的Path
-	 * 
-	 * 返回currentTreeNode下是否找到了filePath
-	 */
-	private boolean selectFilePath(ExpandMutableTreeNode currentTreeNode, String prefix, String filePath, DefaultTreeModel m_model) {
-		FileNode fileNode = (FileNode) currentTreeNode.getUserObject();
-		String nodePath = fileNode.getName();
-		String currentTreePath = prefix + nodePath;
-
-		// 如果equals,说明找到了,不必再找下去了
-		if (ComparatorUtils.equals(new File(currentTreePath), new File(filePath))) {
-			this.setSelectionPath(new TreePath(m_model.getPathToRoot(currentTreeNode)));
-			return true;
-		} // 如果当前路径是currentFilePath的ParnetFile,则expandTreeNode,并继续往下找
-		else if (EnvFileTree.isParentFile(currentTreePath, filePath)) {
-			this.loadPendingChildTreeNode(currentTreeNode);
-
-			prefix = currentTreePath + CoreConstants.SEPARATOR;
-			for (int i = 0, len = currentTreeNode.getChildCount(); i < len; i++) {
-				ExpandMutableTreeNode childTreeNode = (ExpandMutableTreeNode) currentTreeNode.getChildAt(i);
-
-				if (selectFilePath(childTreeNode, prefix, filePath, m_model)) {
-					return true;
-				}
-			}
-			return false;
-		}
-
-		return false;
-	}
-
-	/*
-	 * 求当前TreeNode下所有的FileNode.
-	 */
-	private FileNode[] listFileNodes(ExpandMutableTreeNode currentTreeNode) {
-		if (currentTreeNode == null) {
-			return new FileNode[0];
-		}
-
-		Object object = currentTreeNode.getUserObject();
-
-		if (object instanceof FileNode) {
-			return this.listFileNodes(((FileNode) object).getEnvPath());
-		}
-
-		return new FileNode[0];
-	}
-
-	/*
-	 * 求filePath这个String,求其路径下面的所有的FileNode
-	 */
-	private FileNode[] listFileNodes(String filePath) {
-		FileNode[] res_fns = null;
-
-		try {
-			res_fns = WorkContext.getCurrent() == null ? new FileNode[0] : FRContext.getFileNodes().list(filePath);
-		} catch (Exception e) {
-			FRContext.getLogger().error(e.getMessage(), e);
-		}
-
-		if (res_fns == null) {
-			res_fns = new FileNode[0];
-		}
-
-		// 用FileNodeFilter过滤一下
-		if (filter != null) {
-			java.util.List t_list = new ArrayList();
-			for (int i = 0; i < res_fns.length; i++) {
-				if (filter.accept(res_fns[i])) {
-					t_list.add(res_fns[i]);
-				}
-			}
-
-			res_fns = t_list.toArray(new FileNode[t_list.size()]);
-		}
-
-		Arrays.sort(res_fns, new FileNodeComparator());
-
-		return res_fns;
-	}
-
-	/*
-	 * 获取当前选中的FilePath的String,这个FilePath是需要拼起来的
-	 */
-	public FileNode getSelectedFileNode() {
-		TreePath selectedTreePath = this.getSelectionPath();
-		if (selectedTreePath == null) {
-			return null;
-		}
-
-		ExpandMutableTreeNode currentTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent();
-		Object userObject = currentTreeNode.getUserObject();
-
-		if (userObject instanceof FileNode) {
-			return (FileNode) userObject;
-		}
-
-		return null;
-	}
-
-	/*
-	 * 改变Env后,根据构造函数时设置的RootPathes,重新加载
-	 */
-	public void refreshEnv() {
-
-		DefaultTreeModel m_model = (DefaultTreeModel) this.getModel();
-		ExpandMutableTreeNode rootTreeNode = (ExpandMutableTreeNode) m_model.getRoot();
-		rootTreeNode.removeAllChildren();
-
-		FileNode[] fns;
-
-		// 如果rootPaths是null的话列出所有文件
-		if (subPathes == null) {
-			fns = listFileNodes(this.treeRootPath);
-		} else {
-			// 重新加载新的FileDirectoryNode
-			fns = new FileNode[subPathes.length];
-			for (int i = 0; i < subPathes.length; i++) {
-				fns[i] = new FileNode(StableUtils.pathJoin(new String[]{this.treeRootPath, subPathes[i]}), true);
-			}
-		}
-
-
-		ExpandMutableTreeNode[] sub_tree_node_array = fileNodeArray2TreeNodeArray(fns);
-
-		for (int i = 0; i < sub_tree_node_array.length; i++) {
-			ExpandMutableTreeNode node = sub_tree_node_array[i];
-			rootTreeNode.add(node);
-		}
-
-		m_model.reload(rootTreeNode);
-	}
-
-	/*
-	 * 设置当前Tree的rootPathes
-	 */
-	private void setSubPathes(String[] subPathes) {
-		this.subPathes = subPathes;
-	}
-
-	/**
-	 * currentTreeNode下面如果是PENDING的节点,加载之...
-	 */
-	protected void loadPendingChildTreeNode(ExpandMutableTreeNode currentTreeNode) {
-		if (currentTreeNode.isLeaf()) {
-			return;
-		}
-
-		// 判断第一个孩子节点.UserObject是不是PENDING,如果是PENDING的话,需要重新加载这个TreeNode
-		ExpandMutableTreeNode flag = (ExpandMutableTreeNode) currentTreeNode.getFirstChild();
-		if (flag == null || flag.getUserObject() != PENDING) {
-			return;
-		}
-		currentTreeNode.removeAllChildren(); // 删除所有的节点.
-
-		ExpandMutableTreeNode[] children = loadChildTreeNodes(currentTreeNode);
-		for (ExpandMutableTreeNode c : children) {
-			currentTreeNode.add(c);
-		}
-	}
-
-	/*
-	 * 判断eTreeNode是否需要Refresh,可提前中止,返回true则表示提前中止,不需要Refresh
-	 */
-	protected boolean interceptRefresh(ExpandMutableTreeNode eTreeNode) {
-		Object userObject = eTreeNode.getUserObject();
-		if (userObject instanceof FileNode && !((FileNode) userObject).isDirectory()) {
-			return true;
-		}
-
-		return eTreeNode.getChildCount() == 1 && ((ExpandMutableTreeNode) eTreeNode.getFirstChild()).getUserObject() == PENDING;
-	}
-
-	/*
-	 * 得到treeNode的子节点ExpandMutableTreeNode的数组
-	 */
-	protected ExpandMutableTreeNode[] loadChildTreeNodes(ExpandMutableTreeNode treeNode) {
-		FileNode[] fn_array = listFileNodes(treeNode);
-
-		return fileNodeArray2TreeNodeArray(fn_array);
-	}
-
-	/*
-	 * 把FileNode[]转成ExpandMutableTreeNode[]
-	 */
-		private ExpandMutableTreeNode[] fileNodeArray2TreeNodeArray(FileNode[] fn_array) {
-			ExpandMutableTreeNode[] res = new ExpandMutableTreeNode[fn_array.length];
-			for (int i = 0; i < res.length; i++) {
-				FileNode fn = fn_array[i];
-				res[i] = new ExpandMutableTreeNode(fn);
-				if (fn.isDirectory()) {
-					res[i].add(new ExpandMutableTreeNode());
-				}
-			}
-
-			return res;
-		}
-
-	/*
-	 * 是否是父子关系的文件.
-	 */
-	protected static boolean isParentFile(String parentFilePath, String childFilePath) {
-		File parentFile = new File(parentFilePath);
-		File childFile = new File(childFilePath);
-
-		while (true) {
-			if (ComparatorUtils.equals(parentFile, childFile)) {
-				return true;
-			}
-
-			childFile = childFile.getParentFile();
-			if (childFile == null) {
-				break;
-			}
-		}
-
-		return false;
-	}
+    protected FileNodeFilter filter;
+    protected String treeRootPath = "";
+    protected String[] subPaths;
+
+    public EnvFileTree() {
+        this(null, null);
+    }
+
+    public EnvFileTree(String[] subPaths, FileNodeFilter filter) {
+        this("", subPaths, filter);
+    }
+
+    public EnvFileTree(String treeRootPath, String[] subPaths, FileNodeFilter filter) {
+        super(new FileNode(treeRootPath, true));
+
+        this.setTreeRootPath(treeRootPath);
+        this.setFileNodeFilter(filter);
+        this.setSubPaths(subPaths);
+
+        /*一些自己的 init 放在这里,防止直接错误重写了父类的 init 方法导致子类不能使用 CheckBoxTree 的一些特性。*/
+        this.putClientProperty("JTree.lineStyle", "Angled");
+
+        // CellRenderer
+        // 这里新建一个Label作为render是因为JTree在动态刷新的时候,节点上render画布的的宽度不会变,会使得一部分比较长的数据显示为
+        DefaultTreeCellRenderer fileTreeCellRenderer = new DefaultTreeCellRenderer() {
+
+            @Override
+            public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row,
+                                                          boolean hasFocus) {
+                super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
+                ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) value;
+                Object userObj = treeNode.getUserObject();
+                if (userObj instanceof FileNode) {
+                    FileNode node = (FileNode) userObj;
+                    String lock = node.getLock();
+                    String name = node.getName();
+                    if (treeNode.hasFullAuthority()) {
+                        if (lock != null && !node.getUserID().equals(lock)) {
+                            name = name + InterProviderFactory.getProvider().getLocText("Locked");
+                            this.setIcon(FileTreeIcon.getIcon(node));
+                        } else {
+                            this.setIcon(FileTreeIcon.getIcon(node, false));
+                        }
+                    } else {
+                        this.setIcon(FileTreeIcon.getFolderHalfImageIcon());
+                    }
+                    this.setText(name);
+                } else if (userObj == PENDING) {
+                    this.setIcon(null);
+                    this.setText(PENDING.toString());
+                }
+                // 这里新建一个Label作为render是因为JTree在动态刷新的时候,节点上render画布的的宽度不会变,会使得一部分比较长的数据显示为"..."
+                UILabel label = new UILabel();
+                label.setText(getText());
+                label.setIcon(getIcon());
+                this.setSize(label.getPreferredSize());
+                Dimension dim = label.getPreferredSize();
+                dim.height += 2;
+                this.setPreferredSize(dim);
+                this.setBackgroundNonSelectionColor(UIConstants.TREE_BACKGROUND);
+                this.setTextSelectionColor(Color.WHITE);
+                this.setBackgroundSelectionColor(UIConstants.FLESH_BLUE);
+                return this;
+            }
+        };
+        this.setCellRenderer(fileTreeCellRenderer);
+
+        this.setRootVisible(false);
+        this.setShowsRootHandles(true);
+        this.setEditable(false);
+    }
+
+    private void setTreeRootPath(String path) {
+        if (path == null) {
+            path = "";
+        }
+
+        this.treeRootPath = path;
+    }
+
+    public void setFileNodeFilter(FileNodeFilter filter) {
+        this.filter = filter;
+    }
+
+    /*
+     * 在当前tree中选中currentPath
+     */
+    public void selectPath(String currentPath) {
+        if (currentPath == null) {
+            return;
+        }
+
+        DefaultTreeModel m_model = (DefaultTreeModel) this.getModel();
+        ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) m_model.getRoot();
+        for (int i = 0, len = treeNode.getChildCount(); i < len; i++) {
+            // 取出当前的childTreeNode,并append到searchingPath后面
+            ExpandMutableTreeNode childTreeNode = (ExpandMutableTreeNode) treeNode.getChildAt(i);
+
+            if (selectFilePath(childTreeNode, "", currentPath, m_model)) {
+                break;
+            }
+        }
+
+        TreePath selectedTreePath = this.getSelectionPath();
+        if (selectedTreePath != null) {
+            this.scrollPathToVisible(selectedTreePath);
+        }
+    }
+
+    /*
+     * 在currentTreeNode下找寻filePath
+     *
+     * prefix + currentTreeNode.getName() = currentTreeNode所对应的Path
+     *
+     * 返回currentTreeNode下是否找到了filePath
+     */
+    private boolean selectFilePath(ExpandMutableTreeNode currentTreeNode, String prefix, String filePath, DefaultTreeModel m_model) {
+        FileNode fileNode = (FileNode) currentTreeNode.getUserObject();
+        String nodePath = fileNode.getName();
+        String currentTreePath = prefix + nodePath;
+
+        // 如果equals,说明找到了,不必再找下去了
+        if (ComparatorUtils.equals(new File(currentTreePath), new File(filePath))) {
+            this.setSelectionPath(new TreePath(m_model.getPathToRoot(currentTreeNode)));
+            return true;
+        }
+        // 如果当前路径是currentFilePath的ParentFile,则expandTreeNode,并继续往下找
+        else if (EnvFileTree.isParentFile(currentTreePath, filePath)) {
+            this.loadPendingChildTreeNode(currentTreeNode);
+
+            prefix = currentTreePath + CoreConstants.SEPARATOR;
+            for (int i = 0, len = currentTreeNode.getChildCount(); i < len; i++) {
+                ExpandMutableTreeNode childTreeNode = (ExpandMutableTreeNode) currentTreeNode.getChildAt(i);
+
+                if (selectFilePath(childTreeNode, prefix, filePath, m_model)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        return false;
+    }
+
+    /*
+     * 求当前TreeNode下所有的FileNode.
+     */
+    private FileNode[] listFileNodes(ExpandMutableTreeNode currentTreeNode) {
+        if (currentTreeNode == null) {
+            return new FileNode[0];
+        }
+
+        Object object = currentTreeNode.getUserObject();
+
+        if (object instanceof FileNode) {
+            return this.listFileNodes(((FileNode) object).getEnvPath());
+        }
+
+        return new FileNode[0];
+    }
+
+    /*
+     * 求filePath这个String,求其路径下面的所有的FileNode
+     */
+    private FileNode[] listFileNodes(String filePath) {
+        FileNode[] resFns = null;
+
+        try {
+            resFns = WorkContext.getCurrent() == null ? new FileNode[0] : FRContext.getFileNodes().list(filePath);
+        } catch (Exception e) {
+            FineLoggerFactory.getLogger().error(e.getMessage(), e);
+        }
+
+        if (resFns == null) {
+            resFns = new FileNode[0];
+        }
+
+        // 用FileNodeFilter过滤一下
+        if (filter != null) {
+            java.util.List tList = new ArrayList();
+            for (int i = 0; i < resFns.length; i++) {
+                if (filter.accept(resFns[i])) {
+                    tList.add(resFns[i]);
+                }
+            }
+
+            resFns = tList.toArray(new FileNode[tList.size()]);
+        }
+
+        Arrays.sort(resFns, new FileNodeComparator());
+
+        return resFns;
+    }
+
+    /*
+     * 获取当前选中的FilePath的String,这个FilePath是需要拼起来的
+     */
+    public FileNode getSelectedFileNode() {
+        TreePath selectedTreePath = this.getSelectionPath();
+        if (selectedTreePath == null) {
+            return null;
+        }
+
+        ExpandMutableTreeNode currentTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent();
+        Object userObject = currentTreeNode.getUserObject();
+
+        if (userObject instanceof FileNode) {
+            return (FileNode) userObject;
+        }
+
+        return null;
+    }
+
+    /*
+     * 改变Env后,根据构造函数时设置的RootPaths,重新加载
+     */
+    public void refreshEnv() {
+
+        DefaultTreeModel m_model = (DefaultTreeModel) this.getModel();
+        ExpandMutableTreeNode rootTreeNode = (ExpandMutableTreeNode) m_model.getRoot();
+        rootTreeNode.removeAllChildren();
+
+        FileNode[] fns;
+
+        // 如果rootPaths是null的话列出所有文件
+        if (subPaths == null) {
+            fns = listFileNodes(this.treeRootPath);
+        } else {
+            // 重新加载新的FileDirectoryNode
+            fns = new FileNode[subPaths.length];
+            for (int i = 0; i < subPaths.length; i++) {
+                fns[i] = new FileNode(StableUtils.pathJoin(this.treeRootPath, subPaths[i]), true);
+            }
+        }
+
+
+        ExpandMutableTreeNode[] subTreeNodeArray = fileNodeArray2TreeNodeArray(fns);
+
+        for (int i = 0; i < subTreeNodeArray.length; i++) {
+            ExpandMutableTreeNode node = subTreeNodeArray[i];
+            rootTreeNode.add(node);
+        }
+
+        m_model.reload(rootTreeNode);
+    }
+
+    /*
+     * 设置当前Tree的rootPaths
+     */
+    private void setSubPaths(String[] subPaths) {
+        this.subPaths = subPaths;
+    }
+
+    /**
+     * currentTreeNode下面如果是PENDING的节点,加载之...
+     */
+    protected void loadPendingChildTreeNode(ExpandMutableTreeNode currentTreeNode) {
+        if (currentTreeNode.isLeaf()) {
+            return;
+        }
+
+        // 判断第一个孩子节点.UserObject是不是PENDING,如果是PENDING的话,需要重新加载这个TreeNode
+        ExpandMutableTreeNode flag = (ExpandMutableTreeNode) currentTreeNode.getFirstChild();
+        if (flag == null || flag.getUserObject() != PENDING) {
+            return;
+        }
+        // 删除所有的节点.
+        currentTreeNode.removeAllChildren();
+
+        ExpandMutableTreeNode[] children = loadChildTreeNodes(currentTreeNode);
+        for (ExpandMutableTreeNode c : children) {
+            currentTreeNode.add(c);
+        }
+    }
+
+    /*
+     * 判断eTreeNode是否需要Refresh,可提前中止,返回true则表示提前中止,不需要Refresh
+     */
+    @Override
+    protected boolean interceptRefresh(ExpandMutableTreeNode eTreeNode) {
+        Object userObject = eTreeNode.getUserObject();
+        if (userObject instanceof FileNode && !((FileNode) userObject).isDirectory()) {
+            return true;
+        }
+
+        return eTreeNode.getChildCount() == 1 && ((ExpandMutableTreeNode) eTreeNode.getFirstChild()).getUserObject() == PENDING;
+    }
+
+    /*
+     * 得到treeNode的子节点ExpandMutableTreeNode的数组
+     */
+    @Override
+    protected ExpandMutableTreeNode[] loadChildTreeNodes(ExpandMutableTreeNode treeNode) {
+        FileNode[] fnArray = listFileNodes(treeNode);
+
+        return fileNodeArray2TreeNodeArray(fnArray);
+    }
+
+    /*
+     * 把FileNode[]转成ExpandMutableTreeNode[]
+     */
+    private ExpandMutableTreeNode[] fileNodeArray2TreeNodeArray(FileNode[] fn_array) {
+        ExpandMutableTreeNode[] res = new ExpandMutableTreeNode[fn_array.length];
+        for (int i = 0; i < res.length; i++) {
+            FileNode fn = fn_array[i];
+            res[i] = new ExpandMutableTreeNode(fn);
+            if (fn.isDirectory()) {
+                res[i].add(new ExpandMutableTreeNode());
+            }
+        }
+
+        return res;
+    }
+
+    /*
+     * 是否是父子关系的文件.
+     */
+    protected static boolean isParentFile(String parentFilePath, String childFilePath) {
+        File parentFile = new File(parentFilePath);
+        File childFile = new File(childFilePath);
+
+        do {
+            if (ComparatorUtils.equals(parentFile, childFile)) {
+                return true;
+            }
+            childFile = childFile.getParentFile();
+        } while (childFile != null);
+
+        return false;
+    }
 }
\ No newline at end of file
diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java
index 3d459ceccd..5647033ccd 100644
--- a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java
+++ b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java
@@ -1,22 +1,26 @@
 package com.fr.design.gui.itree.filetree;
 
 import com.fr.base.BaseUtils;
-import com.fr.base.FRContext;
 import com.fr.design.icon.LockIcon;
 import com.fr.file.filetree.FileNode;
 import com.fr.stable.StableUtils;
 import com.fr.workspace.WorkContext;
 
-import javax.swing.*;
+import javax.swing.Icon;
+import javax.swing.UIManager;
 import javax.swing.filechooser.FileSystemView;
 import java.io.File;
 
 public class FileTreeIcon {
-	private FileTreeIcon() {}
-	
+    private FileTreeIcon() {
+    }
+
     public static final Icon BLANK_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/blank.gif");
 
-    public static final Icon FOLDER_IMAGE_ICON =  BaseUtils.readIcon("/com/fr/design/images/gui/folder.png");
+    public static final Icon FOLDER_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/folder.png");
+    public static final Icon FOLDER_HALF_IMAGE_ICON =
+            BaseUtils.readIcon("/com/fr/design/images/gui/filetree_folder_half_authority_normal.png");
+
     public static final Icon FILE_IMAGE_ICON = UIManager.getIcon("FileView.fileIcon");
 
     public static final Icon JAVA_FILE_IMAGE_ICON = BaseUtils.readIcon("/com/fr/design/images/gui/javaFile.gif");
@@ -63,9 +67,9 @@ public class FileTreeIcon {
     public static final LockIcon CPT_FILE_LOCK_ICON =
             new LockIcon(BaseUtils.readImage("/com/fr/base/images/oem/cptlocked.png"));
     public static final LockIcon FRM_FILE_LOCK_ICON =
-        new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/frmlocked.png"));
+            new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/frmlocked.png"));
     public static final LockIcon CHT_FILE_LOCK_ICON =
-        new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/frmlocked.png"));
+            new LockIcon(BaseUtils.readImage("/com/fr/design/images/gui/frmlocked.png"));
     /**
      * file types
      */
@@ -109,27 +113,31 @@ public class FileTreeIcon {
 
         return FileTreeIcon.getIcon(FileTreeIcon.getFileType(file.getName()), isLocked);
     }
-    
-    public static Icon getIcon(FileNode node) {    
-    	return getIcon(node, node.getLock() != null);
+
+    public static Icon getFolderHalfImageIcon() {
+        return FOLDER_HALF_IMAGE_ICON;
+    }
+
+    public static Icon getIcon(FileNode node) {
+        return getIcon(node, node.getLock() != null);
     }
-    
+
     public static Icon getIcon(FileNode node, boolean isShowLock) {
-        String path = StableUtils.pathJoin(new String[]{WorkContext.getCurrent().getPath(), node.getEnvPath()});
+        String path = StableUtils.pathJoin(WorkContext.getCurrent().getPath(), node.getEnvPath());
         if (WorkContext.getCurrent().isLocal()) {
             File ff = new File(path);
             if (ff.exists()) {
-                if(node.isDirectory()){
+                if (node.isDirectory()) {
                     return FileTreeIcon.FOLDER_IMAGE_ICON;
                 }
                 return FileSystemView.getFileSystemView().getSystemIcon(new File(path));
             }
         }
-    	if(node.isDirectory()) {
-    		return FileTreeIcon.FOLDER_IMAGE_ICON;
-    	} else {
-    		return FileTreeIcon.getIcon(FileTreeIcon.getFileType(node.getName()), isShowLock);
-    	}
+        if (node.isDirectory()) {
+            return FileTreeIcon.FOLDER_IMAGE_ICON;
+        } else {
+            return FileTreeIcon.getIcon(FileTreeIcon.getFileType(node.getName()), isShowLock);
+        }
     }
 
     private static Icon getIcon(int fileType, boolean isLocked) {
@@ -200,13 +208,13 @@ public class FileTreeIcon {
                 return FileTreeIcon.CPT_FILE_IMAGE_ICON;
             }
         } else if (fileType == FRM_FILE) { //form frm
-        	if (isLocked) {
+            if (isLocked) {
                 return FileTreeIcon.FRM_FILE_LOCK_ICON;
             } else {
                 return FileTreeIcon.FRM_FILE_IMAGE_ICON;
             }
         } else if (fileType == CHT_FILE) { //chart cht
-        	if (isLocked) {
+            if (isLocked) {
                 return FileTreeIcon.CHT_FILE_LOCK_ICON;
             } else {
                 return FileTreeIcon.CHT_FILE_IMAGE_ICON;
@@ -249,22 +257,22 @@ public class FileTreeIcon {
             return CLASS_FILE;
         } else if (fileName.endsWith(".jar") || fileName.endsWith(".zip")) {
             return ZIP_FILE;
-        } else if( fileName.endsWith(".ear") || fileName.endsWith(".war")){
+        } else if (fileName.endsWith(".ear") || fileName.endsWith(".war")) {
             return ZIP_FILE;
-        }else if (fileName.endsWith(".gif")) {
+        } else if (fileName.endsWith(".gif")) {
             return GIF_FILE;
         } else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpe")) {
             return JPG_FILE;
-        } else if( fileName.endsWith(".jpeg")){
+        } else if (fileName.endsWith(".jpeg")) {
             return JPG_FILE;
-        }else if (fileName.endsWith(".bmp")) {
+        } else if (fileName.endsWith(".bmp")) {
             return BMP_FILE;
         } else if (fileName.endsWith(".cpt")) {
             return CPT_FILE;
-        } else if (fileName.endsWith(".frm") || fileName.endsWith(".form")){
-        	return FRM_FILE;
-        } else if (fileName.endsWith(".cht") || fileName.endsWith(".chart")){
-        	return CHT_FILE;
+        } else if (fileName.endsWith(".frm") || fileName.endsWith(".form")) {
+            return FRM_FILE;
+        } else if (fileName.endsWith(".cht") || fileName.endsWith(".chart")) {
+            return CHT_FILE;
         } else {
             return TEXT_FILE;
         }
diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/TemplateFileTree.java b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/TemplateFileTree.java
index 0f61f40c35..ae5e176e06 100644
--- a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/TemplateFileTree.java
+++ b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/TemplateFileTree.java
@@ -8,6 +8,7 @@ import com.fr.log.FineLoggerFactory;
 import com.fr.stable.ArrayUtils;
 import com.fr.stable.StableUtils;
 import com.fr.stable.project.ProjectConstants;
+import com.fr.workspace.WorkContext;
 
 import javax.swing.text.Position;
 import javax.swing.tree.DefaultTreeModel;
@@ -73,6 +74,7 @@ public class TemplateFileTree extends EnvFileTree {
         return selectedPathList.toArray(new String[0]);
     }
 
+    @Override
     public TreePath getNextMatch(String prefix, int startingRow, Position.Bias bias) {
 
         int max = getRowCount();
@@ -100,15 +102,16 @@ public class TemplateFileTree extends EnvFileTree {
         return null;
     }
 
-    public FileNode[] listFile(String path) throws Exception {
+    public FileNode[] listFile(String path) {
         return FRContext.getFileNodes().list(
                 path,
-                new FileExtension[]{FileExtension.CPT, FileExtension.FRM, FileExtension.CHT,FileExtension.XLS,FileExtension.XLSX});
+                new FileExtension[]{FileExtension.CPT, FileExtension.FRM, FileExtension.CHT, FileExtension.XLS, FileExtension.XLSX});
     }
 
     /*
      * 改变Env后,根据构造函数时设置的RootPaths,重新加载
      */
+    @Override
     public void refreshEnv() {
 
         DefaultTreeModel defaultTreeModel = (DefaultTreeModel) this.getModel();
@@ -118,13 +121,13 @@ public class TemplateFileTree extends EnvFileTree {
         FileNode[] fns;
 
         // 如果rootPaths是null的话列出所有文件
-        if (subPathes == null) {
+        if (subPaths == null) {
             fns = listFileNodes(this.treeRootPath);
         } else {
             // 重新加载新的FileDirectoryNode
-            fns = new FileNode[subPathes.length];
-            for (int i = 0; i < subPathes.length; i++) {
-                fns[i] = new FileNode(StableUtils.pathJoin(this.treeRootPath, subPathes[i]), true);
+            fns = new FileNode[subPaths.length];
+            for (int i = 0; i < subPaths.length; i++) {
+                fns[i] = new FileNode(StableUtils.pathJoin(this.treeRootPath, subPaths[i]), true);
             }
         }
 
@@ -137,22 +140,32 @@ public class TemplateFileTree extends EnvFileTree {
         defaultTreeModel.reload(rootTreeNode);
     }
 
+    @Override
     protected ExpandMutableTreeNode[] loadChildTreeNodes(ExpandMutableTreeNode treeNode) {
-        FileNode[] fn_array = listFileNodes(treeNode);
+        FileNode[] fnArray = listFileNodes(treeNode);
 
-        return fileNodeArray2TreeNodeArray(fn_array);
+        return fileNodeArray2TreeNodeArray(fnArray);
     }
 
     /*
      * 把FileNode[]转成ExpandMutableTreeNode[]
      */
     private ExpandMutableTreeNode[] fileNodeArray2TreeNodeArray(FileNode[] fileNodes) {
+        boolean isLocal = WorkContext.getCurrent().isLocal();
+        String username = WorkContext.getConnector().currentUser();
         ExpandMutableTreeNode[] res = new ExpandMutableTreeNode[fileNodes.length];
         for (int i = 0; i < res.length; i++) {
             FileNode fn = fileNodes[i];
             res[i] = new ExpandMutableTreeNode(fn);
             if (fn.isDirectory()) {
                 res[i].add(new ExpandMutableTreeNode());
+                if (isLocal) {
+                    res[i].setFullAuthority(true);
+                } else {
+                    // todo 判断权限
+                    boolean hasFullAuthority = false;
+                    res[i].setFullAuthority(hasFullAuthority);
+                }
             }
         }
 
diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/ExpandMutableTreeNode.java b/designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/ExpandMutableTreeNode.java
index bb7912517c..48a4d933bb 100644
--- a/designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/ExpandMutableTreeNode.java
+++ b/designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/ExpandMutableTreeNode.java
@@ -1,29 +1,46 @@
 package com.fr.design.gui.itree.refreshabletree;
 
+import com.fr.design.utils.gui.GUICoreUtils;
+
 import javax.swing.JTree;
 import javax.swing.tree.DefaultMutableTreeNode;
 
-import com.fr.design.utils.gui.GUICoreUtils;
-
 /**
  * Enhanced, expand state and get treepath from node.
  */
 public class ExpandMutableTreeNode extends DefaultMutableTreeNode {
-    private boolean isExpanded = false; //the expend state
-    
-    //默认显示:“正在加载”,如需要显示tree,则传入相应userobject
+    /**
+     * the expend state
+     */
+    private boolean isExpanded = false;
+
+
+    private boolean hasFullAuthority = true;
+
+    /**
+     * 默认显示:“正在加载”,如需要显示tree,则传入相应userobject
+     */
     public ExpandMutableTreeNode() {
-    	this(RefreshableJTree.PENDING);
+        this(RefreshableJTree.PENDING);
     }
 
     public ExpandMutableTreeNode(Object userObject) {
         this(userObject, false);
     }
-    
+
     public ExpandMutableTreeNode(Object userObject, boolean isExpanded) {
-    	super(userObject);
-    	this.setExpanded(isExpanded);
+        super(userObject);
+        this.setExpanded(isExpanded);
+    }
+
+    public boolean hasFullAuthority() {
+        return hasFullAuthority;
+    }
+
+    public void setFullAuthority(boolean hasFullAuthority) {
+        this.hasFullAuthority = hasFullAuthority;
     }
+
     public boolean isExpanded() {
         return this.isExpanded;
     }
@@ -36,12 +53,12 @@ public class ExpandMutableTreeNode extends DefaultMutableTreeNode {
      * 展开所有Expanded为true的TreeNode
      */
     public void expandCurrentTreeNode(JTree tree) {
-    	if (this.isExpanded) {
-        	tree.expandPath(GUICoreUtils.getTreePath(this));
+        if (this.isExpanded) {
+            tree.expandPath(GUICoreUtils.getTreePath(this));
             this.setExpanded(true);
-            
+
             this.expandSubTreeNodes(tree);
-    	}
+        }
     }
 
     /**
@@ -69,10 +86,10 @@ public class ExpandMutableTreeNode extends DefaultMutableTreeNode {
             }
         }
     }
-    
+
     public void addChildTreeNodes(ExpandMutableTreeNode[] newChildNodes) {
-    	for (int i = 0; i < newChildNodes.length; i ++) {
-			this.add(newChildNodes[i]);
-		}
+        for (int i = 0; i < newChildNodes.length; i++) {
+            this.add(newChildNodes[i]);
+        }
     }
 }
\ No newline at end of file
diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/RefreshableJTree.java b/designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/RefreshableJTree.java
index 841a25d26f..760bbe77c3 100644
--- a/designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/RefreshableJTree.java
+++ b/designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/RefreshableJTree.java
@@ -4,16 +4,28 @@ import com.fr.design.constants.UIConstants;
 import com.fr.design.gui.itooltip.UIToolTip;
 import com.fr.design.gui.itree.checkboxtree.CheckBoxTree;
 import com.fr.general.ComparatorUtils;
-import com.fr.general.Inter;
 import com.fr.general.NameObject;
+import com.fr.locale.InterProviderFactory;
 import com.fr.stable.StringUtils;
 
-import javax.swing.*;
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+import javax.swing.JToolTip;
+import javax.swing.SwingWorker;
 import javax.swing.event.TreeExpansionEvent;
 import javax.swing.event.TreeExpansionListener;
 import javax.swing.event.TreeWillExpandListener;
-import javax.swing.tree.*;
-import java.awt.*;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeCellRenderer;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.ExpandVetoException;
+import javax.swing.tree.TreeCellRenderer;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.Rectangle;
 import java.awt.event.MouseEvent;
 
 public abstract class RefreshableJTree extends CheckBoxTree {
@@ -24,16 +36,19 @@ public abstract class RefreshableJTree extends CheckBoxTree {
 
         @Override
         public String toString() {
-            return Inter.getLocText("Loading") + "...";
+            return InterProviderFactory.getProvider().getLocText("Loading") + "...";
         }
     };
 
     public RefreshableJTree() {
         this(null);
     }
+
+    @Override
     public boolean isCheckBoxVisible(TreePath path) {
         return false;
     }
+
     public RefreshableJTree(Object rootObj) {
         super(new DefaultTreeModel(new ExpandMutableTreeNode(rootObj)));
         DefaultTreeModel model = (DefaultTreeModel) getModel();
@@ -101,8 +116,7 @@ public abstract class RefreshableJTree extends CheckBoxTree {
                             treeNode.remove(0);
                         }
                         treeModel.nodeStructureChanged(treeNode);
-                        long usedTime = System.currentTimeMillis() - startTime;
-                        return usedTime;
+                        return System.currentTimeMillis() - startTime;
                     }
 
                     @Override
@@ -118,15 +132,15 @@ public abstract class RefreshableJTree extends CheckBoxTree {
     };
 
     /**
-     * @return
+     * @return is template showing
      */
     public boolean isTemplateShowing() {
-        return ((ExpandMutableTreeNode) this.getModel().getRoot()).getChildCount() == 0 ? false : true;
+        return ((ExpandMutableTreeNode) this.getModel().getRoot()).getChildCount() != 0;
     }
 
     /*
-      * 刷新
-      */
+     * 刷新
+     */
     public void refresh() {
         refresh((ExpandMutableTreeNode) this.getModel().getRoot(), StringUtils.EMPTY);
     }
@@ -136,8 +150,8 @@ public abstract class RefreshableJTree extends CheckBoxTree {
     }
 
     /*
-      * 刷新expandRoot节点下所有已打开的节点的UserObject,并打开isExpanded为true的TreeNode
-      */
+     * 刷新expandRoot节点下所有已打开的节点的UserObject,并打开isExpanded为true的TreeNode
+     */
     private void refresh(ExpandMutableTreeNode expandRoot, String childName) {
         if (expandRoot == null) {
             return;
@@ -152,8 +166,8 @@ public abstract class RefreshableJTree extends CheckBoxTree {
     }
 
     /*
-      * 刷新eTreeNode下面所有的已完成过取数的非叶子节点的子叶内容UserObject
-      */
+     * 刷新eTreeNode下面所有的已完成过取数的非叶子节点的子叶内容UserObject
+     */
     protected void refreshTreeNode(ExpandMutableTreeNode eTreeNode, String childName) {
         // 如果eTreeNode是未取数状态,不用expand
         if (interceptRefresh(eTreeNode)) {
@@ -161,12 +175,12 @@ public abstract class RefreshableJTree extends CheckBoxTree {
         }
 
         // 刷新当前eTreeNode下面的子节点的UserObject的数组
-        ExpandMutableTreeNode[] new_nodes = loadChildTreeNodes(eTreeNode);
+        ExpandMutableTreeNode[] newNodes = loadChildTreeNodes(eTreeNode);
 
         /*
-           * 保存下当前eTreeNode下的ChildTreeNode于childTreeNodeList 移除所有ChildTreeNode
-           * 根据childUserObjects与childTreeNodeList的比对,重新构建eTreeNode
-           */
+         * 保存下当前eTreeNode下的ChildTreeNode于childTreeNodeList 移除所有ChildTreeNode
+         * 根据childUserObjects与childTreeNodeList的比对,重新构建eTreeNode
+         */
         java.util.List childTreeNodeList = new java.util.ArrayList();
         for (int i = 0, len = eTreeNode.getChildCount(); i < len; i++) {
             if (eTreeNode.getChildAt(i) instanceof ExpandMutableTreeNode) {
@@ -178,29 +192,29 @@ public abstract class RefreshableJTree extends CheckBoxTree {
 
         eTreeNode.removeAllChildren();
 
-        for (int ci = 0; ci < new_nodes.length; ci++) {
-            Object cUserObject = new_nodes[ci].getUserObject();
+        for (int ci = 0; ci < newNodes.length; ci++) {
+            Object cUserObject = newNodes[ci].getUserObject();
 
-            for (int ni = 0, nlen = childTreeNodeList.size(); ni < nlen; ni++) {
+            for (int ni = 0, len = childTreeNodeList.size(); ni < len; ni++) {
                 ExpandMutableTreeNode cTreeNode = (ExpandMutableTreeNode) childTreeNodeList.get(ni);
                 if (ComparatorUtils.equals(cTreeNode.getUserObject(), cUserObject)) {
-                    new_nodes[ci].setExpanded(cTreeNode.isExpanded());
+                    newNodes[ci].setExpanded(cTreeNode.isExpanded());
                     break;
                 }
             }
 
-            eTreeNode.add(new_nodes[ci]);
+            eTreeNode.add(newNodes[ci]);
         }
     }
 
     /*
-      * 判断eTreeNode是否需要Refresh,可提前中止,返回true则表示提前中止,不需要Refresh
-      */
+     * 判断eTreeNode是否需要Refresh,可提前中止,返回true则表示提前中止,不需要Refresh
+     */
     protected abstract boolean interceptRefresh(ExpandMutableTreeNode eTreeNode);
 
     /*
-      * 得到treeNode的子节点ExpandMutableTreeNode的数组
-      */
+     * 得到treeNode的子节点ExpandMutableTreeNode的数组
+     */
     protected abstract ExpandMutableTreeNode[] loadChildTreeNodes(ExpandMutableTreeNode treeNode);
 
     public NameObject getSelectedNameObject() {
@@ -223,6 +237,7 @@ public abstract class RefreshableJTree extends CheckBoxTree {
         return null;
     }
 
+    @Override
     public String getToolTipText(MouseEvent event) {
         String tip = null;
         icon = new ImageIcon();
@@ -238,7 +253,7 @@ public abstract class RefreshableJTree extends CheckBoxTree {
                 Object lastPath = path.getLastPathComponent();
                 if (lastPath instanceof TreeNode) {
                     TreeNode treeNode = (TreeNode) lastPath;
-                    while (treeNode.getParent() instanceof TreeNode) {
+                    while (treeNode.getParent() != null) {
                         i++;
                         treeNode = treeNode.getParent();
                     }
@@ -260,6 +275,7 @@ public abstract class RefreshableJTree extends CheckBoxTree {
         return tip;
     }
 
+    @Override
     public Point getToolTipLocation(MouseEvent event) {
         if (event != null) {
             Point p = event.getPoint();
@@ -268,12 +284,16 @@ public abstract class RefreshableJTree extends CheckBoxTree {
             if (selRow != -1 && r != null) {
                 TreePath path = getPathForRow(selRow);
                 Rectangle pathBounds = getPathBounds(path);
-                return new Point(pathBounds.x - 2, pathBounds.y - 1);
+                if (pathBounds != null) {
+                    return new Point(pathBounds.x - 2, pathBounds.y - 1);
+                }
+                return null;
             }
         }
         return null;
     }
 
+    @Override
     public JToolTip createToolTip() {
         UIToolTip tip = new UIToolTip(icon);
         tip.setComponent(this);
diff --git a/designer-base/src/main/java/com/fr/design/remote/ui/AuthorityEditorPane.java b/designer-base/src/main/java/com/fr/design/remote/ui/AuthorityEditorPane.java
index f43b5e881d..7564ae35e4 100644
--- a/designer-base/src/main/java/com/fr/design/remote/ui/AuthorityEditorPane.java
+++ b/designer-base/src/main/java/com/fr/design/remote/ui/AuthorityEditorPane.java
@@ -12,10 +12,10 @@ import com.fr.general.Inter;
 import com.fr.report.DesignAuthority;
 import com.fr.stable.CoreConstants;
 
-import javax.swing.*;
+import javax.swing.BorderFactory;
 import javax.swing.border.EmptyBorder;
 import javax.swing.tree.TreePath;
-import java.awt.*;
+import java.awt.BorderLayout;
 import java.util.ArrayList;
 import java.util.List;
 
diff --git a/designer-base/src/main/resources/com/fr/design/images/gui/filetree_folder_half_authority_normal.png b/designer-base/src/main/resources/com/fr/design/images/gui/filetree_folder_half_authority_normal.png
new file mode 100644
index 0000000000000000000000000000000000000000..8aed7d12de0e6afdb4f897a705ac08c27b69d6c3
GIT binary patch
literal 337
zcmV-X0j~auP)Px$3rR#lR5%f1U>In?h|2+!PWpq}*ZTGA-$rH@rl2Z2
z#zc@9GH5^iUkSvA8GtN@#Qv}T_s`#}Ko=s3L6|^skgI)|Fl2}nK=H!&-wX_Q-u`3w
z_~SnV129Uim5~7$`V2pTJ_5;u0N4Oz%?M*a0m;Dd?)!f*MixhA6L281Qta$OVgNrU<16eA
j#4XCt$@CJpEInlaSPfRO^z0Qw00000NkvXXu0mjfXU&$y

literal 0
HcmV?d00001


From ed285f4947d3f007ed479a82f09b65f3cf7245f5 Mon Sep 17 00:00:00 2001
From: "yaoh.wu" 
Date: Mon, 23 Jul 2018 22:07:32 +0800
Subject: [PATCH 6/8] =?UTF-8?q?REPORT-7941=20=E7=9B=AE=E5=BD=95=E6=A0=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../gui/itree/filetree/TemplateFileTree.java  | 77 ++++++++++++++++++-
 1 file changed, 73 insertions(+), 4 deletions(-)

diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/TemplateFileTree.java b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/TemplateFileTree.java
index ae5e176e06..70f29e48eb 100644
--- a/designer-base/src/main/java/com/fr/design/gui/itree/filetree/TemplateFileTree.java
+++ b/designer-base/src/main/java/com/fr/design/gui/itree/filetree/TemplateFileTree.java
@@ -4,11 +4,15 @@ import com.fr.base.FRContext;
 import com.fr.base.extension.FileExtension;
 import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
 import com.fr.file.filetree.FileNode;
+import com.fr.general.ComparatorUtils;
 import com.fr.log.FineLoggerFactory;
+import com.fr.report.DesignAuthority;
 import com.fr.stable.ArrayUtils;
+import com.fr.stable.CoreConstants;
 import com.fr.stable.StableUtils;
 import com.fr.stable.project.ProjectConstants;
 import com.fr.workspace.WorkContext;
+import com.fr.workspace.server.authority.AuthorityOperator;
 
 import javax.swing.text.Position;
 import javax.swing.tree.DefaultTreeModel;
@@ -23,6 +27,11 @@ import java.util.List;
 public class TemplateFileTree extends EnvFileTree {
 
 
+    /**
+     * 远程设计拥有全部权限的文件夹路径
+     */
+    private ArrayList paths = new ArrayList<>();
+
     public TemplateFileTree() {
         super(ProjectConstants.REPORTLETS_NAME, null, null);
     }
@@ -113,6 +122,34 @@ public class TemplateFileTree extends EnvFileTree {
      */
     @Override
     public void refreshEnv() {
+        paths.clear();
+
+        if (!WorkContext.getCurrent().isLocal()) {
+            try {
+                String username = WorkContext.getConnector().currentUser();
+                // 远程设计获取全部设计成员的权限列表
+                DesignAuthority[] authorities = WorkContext.getCurrent().get(AuthorityOperator.class).getAuthorities();
+                DesignAuthority authority = null;
+
+                if (authorities != null) {
+                    for (DesignAuthority designAuthority : authorities) {
+                        if (ComparatorUtils.equals(designAuthority.getUsername(), username)) {
+                            authority = designAuthority;
+                        }
+                    }
+                }
+                if (authority != null) {
+                    for (DesignAuthority.Item item : authority.getItems()) {
+                        if (item.getType()) {
+                            paths.add(item.getPath());
+                        }
+                    }
+                }
+            } catch (Exception exception) {
+                FineLoggerFactory.getLogger().error(exception.getMessage(), exception);
+            }
+        }
+
 
         DefaultTreeModel defaultTreeModel = (DefaultTreeModel) this.getModel();
         ExpandMutableTreeNode rootTreeNode = (ExpandMutableTreeNode) defaultTreeModel.getRoot();
@@ -152,18 +189,16 @@ public class TemplateFileTree extends EnvFileTree {
      */
     private ExpandMutableTreeNode[] fileNodeArray2TreeNodeArray(FileNode[] fileNodes) {
         boolean isLocal = WorkContext.getCurrent().isLocal();
-        String username = WorkContext.getConnector().currentUser();
         ExpandMutableTreeNode[] res = new ExpandMutableTreeNode[fileNodes.length];
         for (int i = 0; i < res.length; i++) {
             FileNode fn = fileNodes[i];
             res[i] = new ExpandMutableTreeNode(fn);
             if (fn.isDirectory()) {
                 res[i].add(new ExpandMutableTreeNode());
-                if (isLocal) {
+                if (isLocal || WorkContext.getCurrent().isRoot()) {
                     res[i].setFullAuthority(true);
                 } else {
-                    // todo 判断权限
-                    boolean hasFullAuthority = false;
+                    boolean hasFullAuthority = isContained(fn);
                     res[i].setFullAuthority(hasFullAuthority);
                 }
             }
@@ -172,6 +207,40 @@ public class TemplateFileTree extends EnvFileTree {
         return res;
     }
 
+    private boolean isContained(FileNode fileNode) {
+
+        for (String auPath : paths) {
+            if (isContained(auPath, fileNode)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isContained(String auPath, FileNode fileNode) {
+        auPath = ProjectConstants.REPORTLETS_NAME + CoreConstants.SEPARATOR + auPath;
+        String fileName = fileNode.getEnvPath();
+        String[] auPaths = auPath.split(CoreConstants.SEPARATOR);
+        String[] nodePaths = fileName.split(CoreConstants.SEPARATOR);
+
+        if (auPaths.length == nodePaths.length) {
+            for (int i = 0; i < auPaths.length; i++) {
+                if (!auPaths[i].equals(nodePaths[i])) {
+                    return false;
+                }
+            }
+            return fileNode.isDirectory();
+        } else {
+            int len = Math.min(auPaths.length, nodePaths.length);
+            for (int i = 0; i < len; i++) {
+                if (!auPaths[i].equals(nodePaths[i])) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
 
     private FileNode[] listFileNodes(String filePath) {
         FileNode[] fileNodes = null;

From c2de996fe11daa514046c3f80f9fd08585617b31 Mon Sep 17 00:00:00 2001
From: "yaoh.wu" 
Date: Tue, 24 Jul 2018 09:13:49 +0800
Subject: [PATCH 7/8] =?UTF-8?q?=E5=A4=8D=E7=94=A8=E4=BB=A3=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../remote/ui/list/AddedMemberList.java       | 16 ----------------
 .../remote/ui/list/AddingMemberList.java      | 15 ---------------
 .../fr/design/remote/ui/list/MemberList.java  | 19 ++++++++++++++++---
 3 files changed, 16 insertions(+), 34 deletions(-)

diff --git a/designer-base/src/main/java/com/fr/design/remote/ui/list/AddedMemberList.java b/designer-base/src/main/java/com/fr/design/remote/ui/list/AddedMemberList.java
index ad4d880d99..2d95dce4b3 100644
--- a/designer-base/src/main/java/com/fr/design/remote/ui/list/AddedMemberList.java
+++ b/designer-base/src/main/java/com/fr/design/remote/ui/list/AddedMemberList.java
@@ -3,8 +3,6 @@ package com.fr.design.remote.ui.list;
 import com.fr.workspace.server.authority.RemoteDesignMember;
 
 import javax.swing.DefaultListModel;
-import java.awt.Point;
-import java.awt.event.MouseEvent;
 import java.util.Vector;
 
 public class AddedMemberList extends MemberList {
@@ -25,20 +23,6 @@ public class AddedMemberList extends MemberList {
         super(listData);
     }
 
-
-    @Override
-    protected boolean shouldDisplaySelected(MouseEvent e) {
-        Point point = e.getPoint();
-        int rX = point.x;
-        int rY = point.y;
-        int index = this.getSelectedIndex();
-        int x = 270;
-        int y = 25 * index;
-        int width = 20;
-        int height = 25;
-        return x <= rX && rX <= x + width && y <= rY && rY <= y + height;
-    }
-
     @Override
     protected void displaySelected() {
         RemoteDesignMember member = getSelectedValue();
diff --git a/designer-base/src/main/java/com/fr/design/remote/ui/list/AddingMemberList.java b/designer-base/src/main/java/com/fr/design/remote/ui/list/AddingMemberList.java
index bcd42d5c9f..649907d052 100644
--- a/designer-base/src/main/java/com/fr/design/remote/ui/list/AddingMemberList.java
+++ b/designer-base/src/main/java/com/fr/design/remote/ui/list/AddingMemberList.java
@@ -3,8 +3,6 @@ package com.fr.design.remote.ui.list;
 import com.fr.workspace.server.authority.RemoteDesignMember;
 
 import javax.swing.DefaultListModel;
-import java.awt.Point;
-import java.awt.event.MouseEvent;
 import java.util.Vector;
 
 public class AddingMemberList extends MemberList {
@@ -36,19 +34,6 @@ public class AddingMemberList extends MemberList {
         repaint();
         fireSelectedChange();
     }
-
-    @Override
-    protected boolean shouldDisplaySelected(MouseEvent e) {
-        Point point = e.getPoint();
-        int rX = point.x;
-        int rY = point.y;
-        int index = this.getSelectedIndex();
-        int x = 270;
-        int y = 25 * index;
-        int width = 25;
-        int height = 25;
-        return x <= rX && rX <= x + width && y <= rY && rY <= y + height;
-    }
 }
 
 
diff --git a/designer-base/src/main/java/com/fr/design/remote/ui/list/MemberList.java b/designer-base/src/main/java/com/fr/design/remote/ui/list/MemberList.java
index 60e44af998..10e99f0e32 100644
--- a/designer-base/src/main/java/com/fr/design/remote/ui/list/MemberList.java
+++ b/designer-base/src/main/java/com/fr/design/remote/ui/list/MemberList.java
@@ -7,6 +7,7 @@ import javax.swing.DefaultListModel;
 import javax.swing.JList;
 import javax.swing.ListSelectionModel;
 import java.awt.Color;
+import java.awt.Point;
 import java.awt.event.KeyAdapter;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseAdapter;
@@ -14,6 +15,12 @@ import java.awt.event.MouseEvent;
 import java.util.Vector;
 
 public abstract class MemberList extends JList {
+    static final int TRIGGER_AREA_X = 270;
+    static final int TRIGGER_AREA_Y_EACH = 25;
+
+    static final int TRIGGER_AREA_WIDTH = 25;
+    static final int TRIGGER_AREA_HEIGHT = 25;
+
 
     public MemberList(DefaultListModel dataModel) {
         super(dataModel);
@@ -79,7 +86,13 @@ public abstract class MemberList extends JList {
 
     abstract protected void displaySelected();
 
-    abstract protected boolean shouldDisplaySelected(MouseEvent e);
-
-
+    protected boolean shouldDisplaySelected(MouseEvent e) {
+        Point point = e.getPoint();
+        int rX = point.x;
+        int rY = point.y;
+        int index = this.getSelectedIndex();
+        int x = TRIGGER_AREA_X;
+        int y = TRIGGER_AREA_Y_EACH * index;
+        return x <= rX && rX <= x + TRIGGER_AREA_WIDTH && y <= rY && rY <= y + TRIGGER_AREA_HEIGHT;
+    }
 }

From acb1248c82375f9bdc755661f5369a4f722255b9 Mon Sep 17 00:00:00 2001
From: "yaoh.wu" 
Date: Tue, 24 Jul 2018 09:16:49 +0800
Subject: [PATCH 8/8] rename

---
 .../gui/itree/checkboxtree/TristateCheckBox.java       | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/TristateCheckBox.java b/designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/TristateCheckBox.java
index ad9d7e8221..a4a59ade24 100644
--- a/designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/TristateCheckBox.java
+++ b/designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/TristateCheckBox.java
@@ -77,7 +77,7 @@ public class TristateCheckBox extends UICheckBox {
 
     public TristateCheckBox(String text, Icon icon, State initial) {
         super(text, icon);
-        setUI(new TristateUICheckBoxUI());
+        setUI(new TristateCheckBoxUI());
         // Add a listener for when the mouse is pressed
         super.addMouseListener(new MouseAdapter() {
             @Override
@@ -105,17 +105,17 @@ public class TristateCheckBox extends UICheckBox {
 
     public TristateCheckBox(String text, State initial) {
         this(text, null, initial);
-        setUI(new TristateUICheckBoxUI());
+        setUI(new TristateCheckBoxUI());
     }
 
     public TristateCheckBox(String text) {
         this(text, DO_NOT_CARE);
-        setUI(new TristateUICheckBoxUI());
+        setUI(new TristateCheckBoxUI());
     }
 
     public TristateCheckBox() {
         this(null);
-        setUI(new TristateUICheckBoxUI());
+        setUI(new TristateCheckBoxUI());
     }
 
     /**
@@ -343,7 +343,7 @@ public class TristateCheckBox extends UICheckBox {
         }
     }
 
-    private class TristateUICheckBoxUI extends MetalCheckBoxUI {
+    private class TristateCheckBoxUI extends MetalCheckBoxUI {
         @Override
         public void paint(Graphics g, JComponent c) {
             synchronized (this) {