帆软报表设计器源代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

621 lines
22 KiB

package com.fr.design.gui.icombobox;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.IllegalComponentStateException;
import java.awt.RenderingHints;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.util.Enumeration;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.MenuSelectionManager;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.PopupMenuListener;
import javax.swing.plaf.basic.BasicComboBoxUI;
import javax.swing.plaf.basic.ComboPopup;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import com.fr.design.constants.UIConstants;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.general.ComparatorUtils;
import com.fr.general.NameObject;
import com.fr.stable.Constants;
import com.fr.stable.StringUtils;
public class FRTreeComboBox extends UIComboBox {
private static final int PAGE_DIFF = 5;
private static final int DEFAULT_HEIGHT = 120;
// richer:下拉展示用的tree
protected JTree tree;
private boolean onlyLeafSelectable = true;
public FRTreeComboBox() {
this(new JTree());
}
public FRTreeComboBox(JTree tree) {
this(tree, null);
}
public FRTreeComboBox(JTree tree, TreeCellRenderer renderer) {
this(tree, renderer, false);
}
public FRTreeComboBox(JTree tree, TreeCellRenderer renderer, boolean editable) {
this(tree, renderer, false, editable);
}
public FRTreeComboBox(JTree tree, TreeCellRenderer renderer,
boolean showRoot, boolean editable) {
this.setTree(tree);
this.tree.setCellRenderer(renderer);
this.setEditor(new FrTreeSearchComboBoxEditor(this));
if (!showRoot) {
tree.expandPath(new TreePath(tree.getModel().getRoot()));
tree.setRootVisible(false);
}
this.setEditable(editable);
setUI(new FRTreeComboBoxUI());
}
public JTree getTree() {
return this.tree;
}
/**
* 自定义那些那些node可以选中,默认情况下所有node节点都可以选中
* @param node
* @return
*/
protected boolean customSelectable(DefaultMutableTreeNode node){
return true;
}
public void setTree(JTree tree) {
this.tree = tree;
if (tree != null) {
this.setSelectedItem(tree.getSelectionPath());
this.setRenderer(new TreeComboBoxRenderer());
}
}
public void setOnlyLeafSelectable(boolean onlyLeafSelectable) {
this.onlyLeafSelectable = onlyLeafSelectable;
}
/**
* 获得FRTreeComboBox的返回值
*
* @return Object
*/
public Object getSelectedObject() {
if (!(this.getSelectedItem() instanceof TreePath)) {
return this.getSelectedItem();
}
TreePath treePath = (TreePath) this.getSelectedItem();
if (treePath == null) {
return null;
}
DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath.getLastPathComponent();
return node.getUserObject();
}
public String getProcedureSelectName() {
DefaultMutableTreeNode node = (DefaultMutableTreeNode) ((TreePath) this.getSelectedItem()).getLastPathComponent();
NameObject no = (NameObject) node.getUserObject();
String ds2 = no.getName();
node = (DefaultMutableTreeNode) node.getParent();
no = (NameObject) node.getUserObject();
String ds1 = no.getName();
return ds1 + "." + ds2;
}
protected void dealSamePath(TreePath parent,TreeNode node,UITextField textField){
boolean isBreak = false;
for (Enumeration e = node.children(); e.hasMoreElements(); ) {
TreeNode n = (TreeNode) e.nextElement();
TreePath path = parent.pathByAddingChild(n);
TreeNode pathnode = (TreeNode) path.getLastPathComponent();
for (Enumeration e2 = pathnode.children(); e2.hasMoreElements(); ) {
TreeNode n2 = (TreeNode) e2.nextElement();
TreePath path2 = path.pathByAddingChild(n2);
if (pathToString(path2).toUpperCase().startsWith(textField.getText().toUpperCase())) {
tree.scrollPathToVisible(path2);
tree.setSelectionPath(path2);
isBreak = true;
break;
}
}
if (isBreak) {
break;
}
}
}
public void setSelectedItem(Object o) {
if (o instanceof String) {
this.setSelectedItemString((String) o);
return;
}
this.tree.setSelectionPath((TreePath) o);
if (this.isEditable && o != null) {
this.setSelectedItemString(pathToString((TreePath) o));
} else {
this.getModel().setSelectedItem(o);
}
}
private boolean validTreePath(String treePath){
return StringUtils.isNotEmpty(treePath) && treePath.charAt(0) == '[' && treePath.endsWith("]");
}
protected String pathToString(TreePath path) {
String temp = path.toString();
if (validTreePath(temp)) {
temp = temp.substring(2, temp.length() - 1);
String[] selectedtable = temp.split(",");
String table = selectedtable[selectedtable.length - 1].trim();
if (table.contains(".")) {
String[] temp2 = table.split("\\.");
table = temp2[temp2.length - 1].trim();
}
return table;
}
return "";
}
/*
* richer:根据NameObject的名字来选取
*/
public void setSelectedItemString(String _name) {
if (StringUtils.isBlank(_name)) {
this.setSelectedIndex(-1);
return;
}
DefaultTreeModel model = (DefaultTreeModel) this.tree.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
DefaultMutableTreeNode leaf = root.getFirstLeaf();
do {
Object userObj = leaf.getUserObject();
if (userObj instanceof NameObject) {
if (ComparatorUtils.equals(_name, ((NameObject) userObj).getName())) {
TreePath path = new TreePath(model.getPathToRoot(leaf));
this.tree.setSelectionPath(path);
this.setSelectedItem(path);
break;
}
}
} while ((leaf = leaf.getNextLeaf()) != null);
if (leaf == null) {
this.getModel().setSelectedItem(_name);
}
}
public void setSelectedFirst() {
DefaultTreeModel model = (DefaultTreeModel) this.tree.getModel();
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
if (root == null) {
return;
}
DefaultMutableTreeNode leaf = root.getFirstLeaf();
if (leaf == null) {
return;
}
if (leaf.getUserObject() instanceof NameObject) {
TreePath path = new TreePath(model.getPathToRoot(leaf));
this.tree.setSelectionPath(path);
this.setSelectedItem(path);
}
}
public void setPopSize(int width, int height) {
treePopup.setPopSize(width, height);
}
private static TreePopup treePopup;
private static class FRTreeComboBoxUI extends BasicComboBoxUI implements MouseListener{
private boolean isRollover = false;
public FRTreeComboBoxUI() {
super();
}
protected ComboPopup createPopup() {
treePopup = new TreePopup(comboBox);
return treePopup;
}
@Override
protected UIButton createArrowButton() {
arrowButton = new UIButton(UIConstants.ARROW_DOWN_ICON){
/**
* 组件是否需要响应添加的观察者事件
*
* @return 如果需要响应观察者事件则返回true,否则返回false
*/
@Override
public boolean shouldResponseChangeListener() {
return false;
}
};
((UIButton) arrowButton).setRoundBorder(true, Constants.LEFT);
arrowButton.addMouseListener(this);
comboBox.addMouseListener(this);
return (UIButton) arrowButton;
}
public void paint(Graphics g, JComponent c) {
super.paint(g, c);
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color linecolor = null;
if (comboBox.isPopupVisible()) {
linecolor = UIConstants.LINE_COLOR;
arrowButton.setSelected(true);
} else if (isRollover) {
linecolor = UIConstants.LIGHT_BLUE;
} else {
linecolor = UIConstants.LINE_COLOR;
arrowButton.setSelected(false);
}
g2d.setColor(linecolor);
if (!comboBox.isPopupVisible()) {
g2d.drawRoundRect(0, 0, c.getWidth() - arrowButton.getWidth() + 3, c.getHeight() - 1, UIConstants.LARGEARC, UIConstants.LARGEARC);
} else {
g2d.drawRoundRect(0, 0, c.getWidth() , c.getHeight() + 3, UIConstants.LARGEARC, UIConstants.LARGEARC );
g2d.drawLine(0, c.getHeight()-1, c.getWidth(), c.getHeight()-1);
}
}
private void setRollover(boolean isRollover) {
if (this.isRollover != isRollover) {
this.isRollover = isRollover;
comboBox.repaint();
}
}
@Override
public void mouseEntered(MouseEvent e) {
setRollover(true);
}
@Override
public void mouseExited(MouseEvent e) {
setRollover(false);
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
}
/**
* 添加弹出菜单监听
*
* @param l 监听事件
*
* @date 2015-1-22-下午5:04:00
*
*/
public void addPopupMenuListener(PopupMenuListener l) {
treePopup.addPopupMenuListener(l);
}
private class TreeComboBoxRenderer extends DefaultListCellRenderer {
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
if (value != null) {
TreePath path = (TreePath) value;
TreeNode node = (TreeNode) path.getLastPathComponent();
value = node;
TreeCellRenderer treeCellRenderer = tree.getCellRenderer();
UILabel lb = (UILabel) treeCellRenderer.getTreeCellRendererComponent(tree, value, isSelected,
false, node.isLeaf(), index, cellHasFocus);
return lb;
}
return super.getListCellRendererComponent(list, value, index,
isSelected, cellHasFocus);
}
}
/*
* richer:弹出部分
*/
private static class TreePopup extends JPopupMenu implements ComboPopup {
/**
*
*/
private static final long serialVersionUID = 1L;
private int defaultWidth = 0;
private int defaultHeight = 0;
protected FRTreeComboBox comboBox;
protected JScrollPane scrollPane;
protected JTree tree;
protected MouseMotionListener mouseMotionListener;
protected MouseListener mouseListener;
private MouseListener treeSelectListener = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
JTree tree = (JTree) e.getSource();
TreePath treePath = tree.getPathForLocation(e.getPoint().x, e
.getPoint().y);
if (treePath == null) {
return;
}
DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath
.getLastPathComponent();
selectTreeItem(node, treePath);
}
};
//samuel:相应首字母导航的键盘确定
private KeyListener treeKeyListener = new KeyAdapter() {
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_ENTER) {
TreePath treePath = tree.getSelectionPath();
if (treePath == null) {
return;
}
DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath
.getLastPathComponent();
selectTreeItem(node, treePath);
}
}
};
private void selectTreeItem(DefaultMutableTreeNode node, TreePath treePath) {
if (node.isRoot()) {
return;
}
if (comboBox.onlyLeafSelectable && !node.isLeaf()) {
return;
}
//自定义node是否可选择
if (!comboBox.customSelectable(node)){
return;
}
comboBox.setSelectedItem(treePath);
togglePopup();
MenuSelectionManager.defaultManager().clearSelectedPath();
}
public TreePopup(JComboBox comboBox) {
this.comboBox = (FRTreeComboBox) comboBox;
this.setBorder(BorderFactory.createLineBorder(Color.black));
this.setLayout(FRGUIPaneFactory.createBorderLayout());
this.setLightWeightPopupEnabled(comboBox
.isLightWeightPopupEnabled());
tree = this.comboBox.getTree();
if (tree != null) {
this.scrollPane = new JScrollPane(tree);
this.scrollPane.setBorder(null);
this.add(this.scrollPane, BorderLayout.CENTER);
tree.addMouseListener(this.treeSelectListener);
tree.addKeyListener(this.treeKeyListener);
}
}
public void show() {
this.updatePopup();
try {
/*
* 这里有个问题,可能是哪里的listenerr有冲突将这个JPopMenu show的X设置为70时
* 正好可以脱离DBManipulationPane,此时可以正确相应鼠标点击事件,否则由于焦点不在JPopmenu
* 上点击,树时将导致窗口销毁,无法正确相应点击事件
*/
this.show(comboBox, 0, comboBox.getHeight());
} catch (IllegalComponentStateException e) {
// richer:这里有可能会抛出一个异常,可以不用处理
}
}
public void hide() {
this.setVisible(false);
}
public JList getList() {
return new JList();
}
public MouseMotionListener getMouseMotionListener() {
if (mouseMotionListener == null) {
mouseMotionListener = new MouseMotionAdapter() {
};
}
return mouseMotionListener;
}
public KeyListener getKeyListener() {
return null;
}
public void uninstallingUI() {
}
public MouseListener getMouseListener() {
if (mouseListener == null) {
mouseListener = new InvocationMouseHandler();
}
return mouseListener;
}
protected void togglePopup() {
if (this.isVisible()) {
this.hide();
} else {
this.show();
}
}
protected void updatePopup() {
int width = defaultWidth == 0 ? this.comboBox.getSize().width : defaultWidth;
int height = defaultHeight == 0 ? DEFAULT_HEIGHT : defaultHeight;
this.setPreferredSize(new Dimension(width, height));
Object selectedObj = this.comboBox.getSelectedItem();
if (selectedObj instanceof TreePath) {
TreePath tp = (TreePath) selectedObj;
(this.comboBox).getTree().setSelectionPath(tp);
}
}
public void setPopSize(int width, int height) {
this.defaultWidth = width;
this.defaultHeight = height;
}
protected class InvocationMouseHandler extends MouseAdapter {
public void mousePressed(MouseEvent e) {
if (!SwingUtilities.isLeftMouseButton(e)
|| !comboBox.isEnabled()) {
return;
}
if (comboBox.isEditable()) {
Component comp = comboBox.getEditor().getEditorComponent();
if ((!(comp instanceof JComponent))
|| ((JComponent) comp).isRequestFocusEnabled()) {
comp.requestFocus();
}
} else if (comboBox.isRequestFocusEnabled()) {
comboBox.requestFocus();
}
togglePopup();
}
}
}
class FrTreeSearchComboBoxEditor extends UIComboBoxEditor implements DocumentListener {
private volatile boolean setting = false;
private FRTreeComboBox comboBox;
private Object item;
public FrTreeSearchComboBoxEditor(FRTreeComboBox comboBox) {
super();
this.comboBox = comboBox;
textField.getDocument().addDocumentListener(this);
textField.addKeyListener(this.treeKeyListener);
}
private KeyListener treeKeyListener = new KeyAdapter() {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_DOWN) {
int row = tree.getRowForPath(tree.getSelectionPath()) + 1;
tree.setSelectionRow(row);
tree.scrollRowToVisible(row);
} else if (key == KeyEvent.VK_UP) {
int row = tree.getRowForPath(tree.getSelectionPath()) - 1;
tree.setSelectionRow(row);
tree.scrollRowToVisible(row);
} else if (key == KeyEvent.VK_PAGE_DOWN) {
int row = tree.getRowForPath(tree.getSelectionPath()) + PAGE_DIFF;
tree.setSelectionRow(row);
tree.scrollRowToVisible(row);
} else if (key == KeyEvent.VK_PAGE_UP) {
int row = tree.getRowForPath(tree.getSelectionPath()) - PAGE_DIFF;
tree.setSelectionRow(row);
tree.scrollRowToVisible(row);
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_ENTER) {
TreePath treePath = tree.getSelectionPath();
if (treePath == null) {
return;
}
DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath
.getLastPathComponent();
if (node.isLeaf()) {
comboBox.setSelectedItem(treePath);
textField.setText(pathToString(treePath));
MenuSelectionManager.defaultManager().clearSelectedPath();
}
}
}
};
public void setItem(Object item) {
this.item = item;
this.setting = true;
textField.setText((item == null) ? "" : item.toString());
this.setting = false;
}
public Object getItem() {
return this.item;
}
public void insertUpdate(DocumentEvent e) {
changeHandler();
}
public void removeUpdate(DocumentEvent e) {
changeHandler();
}
public void changedUpdate(DocumentEvent e) {
changeHandler();
}
protected void changeHandler() {
if (setting) {
return;
}
setPopupVisible(true);
this.item = textField.getText();
TreeNode root = (TreeNode) tree.getModel().getRoot();
TreePath parent = new TreePath(root);
TreeNode node = (TreeNode) parent.getLastPathComponent();
dealSamePath(parent,node,textField);
this.getEditorComponent().requestFocus();
}
}
}