Browse Source

REPORT-6700 REPORT-8957 REPORT-8941 REPORT-7941 REPORT-8392

master
yaoh.wu 6 years ago
parent
commit
952b2c7102
  1. 65
      designer-base/src/main/java/com/fr/design/file/TemplateTreePane.java
  2. 363
      designer-base/src/main/java/com/fr/design/gui/icheckbox/UICheckBox.java
  3. 15
      designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/CheckBoxTreeCellRenderer.java
  4. 14
      designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/NullTristateCheckBox.java
  5. 201
      designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/TristateCheckBox.java
  6. 665
      designer-base/src/main/java/com/fr/design/gui/itree/filetree/EnvFileTree.java
  7. 64
      designer-base/src/main/java/com/fr/design/gui/itree/filetree/FileTreeIcon.java
  8. 29
      designer-base/src/main/java/com/fr/design/gui/itree/filetree/TemplateFileTree.java
  9. 51
      designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/ExpandMutableTreeNode.java
  10. 80
      designer-base/src/main/java/com/fr/design/gui/itree/refreshabletree/RefreshableJTree.java
  11. 4
      designer-base/src/main/java/com/fr/design/remote/ui/AuthorityEditorPane.java
  12. BIN
      designer-base/src/main/resources/com/fr/design/images/gui/filetree_folder_half_authority_normal.png

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

363
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());
}
}
}
}
}

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

14
designer-base/src/main/java/com/fr/design/gui/itree/checkboxtree/NullTristateCheckBox.java

@ -42,10 +42,7 @@ import javax.swing.Icon;
* </code></pre>
*
* @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;
}
}
}

201
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:
* <p/>
* 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.
* <p/>
* 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.
* <code><pre>
@ -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());
}
}
}
}
}

665
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<FileNode> t_list = new ArrayList<FileNode>();
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<FileNode> tList = new ArrayList<FileNode>();
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;
}
}

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

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

51
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]);
}
}
}

80
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<DefaultMutableTreeNode> childTreeNodeList = new java.util.ArrayList<DefaultMutableTreeNode>();
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);

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

BIN
designer-base/src/main/resources/com/fr/design/images/gui/filetree_folder_half_authority_normal.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Loading…
Cancel
Save