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

422 lines
14 KiB

package com.fr.design.mainframe;
import com.fr.design.constants.UIConstants;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XCreatorUtils;
import com.fr.design.designer.creator.XLayoutContainer;
import com.fr.design.designer.creator.XWAbsoluteBodyLayout;
import com.fr.design.designer.creator.XWFitLayout;
import com.fr.design.designer.creator.cardlayout.XCardSwitchButton;
import com.fr.design.designer.treeview.ComponentTreeCellRenderer;
import com.fr.design.designer.treeview.ComponentTreeModel;
import com.fr.design.gui.itree.UITreeUI;
import com.fr.design.utils.gui.GUICoreUtils;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.DropMode;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;
public class ComponentTree extends JTree {
private FormDesigner designer;
private ComponentTreeModel model;
private UITreeUI uiTreeUI = new UITreeUI();
private PopupPreviewPane previewPane;
private static final int PADDING_LEFT = 5;
private static final int PADDING_TOP = 5;
public ComponentTree(FormDesigner designer) {
this.designer = designer;
this.setBackground(UIConstants.TREE_BACKGROUND);
setRootVisible(true);
setCellRenderer(new ComponentTreeCellRenderer());
getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
this.setDragEnabled(false);
this.setDropMode(DropMode.ON_OR_INSERT);
this.setTransferHandler(new TreeTransferHandler());
this.refreshTreeRoot();
initListeners();
setEditable(true);
setUI(uiTreeUI);
setBorder(BorderFactory.createEmptyBorder(PADDING_TOP, PADDING_LEFT, 0, 0));
}
private void initListeners() {
this.addTreeSelectionListener(designer);
ComponetTreeMouseListener componetTreeMouseListener = new ComponetTreeMouseListener(this);
this.addMouseMotionListener(componetTreeMouseListener);
this.addMouseListener(componetTreeMouseListener);
}
public FormDesigner getDesigner() {
return designer;
}
/**
* 构造函数
*
* @param designer 设计界面组件
* @param model 构造JTree的model
*/
public ComponentTree(FormDesigner designer, ComponentTreeModel model) {
this(designer);
this.setModel(model);
}
public void setSelectionPath(TreePath path) {
// 不管点击哪一项,都要先退出编辑状态(图表、报表块、绝对布局、tab块)
designer.stopEditing(path);
super.setSelectionPath(path);
}
@Override
public void removeAll() {
if (previewPane != null) {
previewPane.setVisible(false);
previewPane.removeAll();
}
super.removeAll();
}
/**
* 是否可编辑
*
* @param path 树路径
* @return 是则返回true
*/
@Override
public boolean isPathEditable(TreePath path) {
return false;
}
/**
* 将值转换为文本
*
* @param value 值
* @param selected 是否选中
* @param expanded 扩展
* @param leaf 是否叶子
* @param row 行
* @param hasFocus 是否焦点
* @return 返回文本
*/
@Override
public String convertValueToText(Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
if (value != null && value instanceof XCreator) {
return ((XCreator) value).toData().getWidgetName();
} else {
return super.convertValueToText(value, selected, expanded, leaf, row, hasFocus);
}
}
public void setAndScrollSelectionPath(TreePath[] treepath) {
setSelectionPaths(treepath);
if (treepath.length > 0) {
scrollPathToVisible(treepath[0]);
//expandPath(treepath[0]);
}
}
@Override
public void paint(Graphics g) {
super.paint(g);
designer.getSelectionModel(); // 否则参数一个一个加会导致参数面板和body结构出问题
}
/**
* 刷新
*/
public void refreshUI() {
updateUI();
setUI(uiTreeUI);
}
public TreePath[] getSelectedTreePath() {
XCreator[] creators = designer.getSelectionModel().getSelection().getSelectedCreators();
TreePath[] paths = new TreePath[creators.length];
for (int i = 0; i < paths.length; i++) {
paths[i] = buildTreePath(creators[i]);
}
return paths;
}
/**
* 搜索指定名称的路径
*
* @param text 名称
* @return 树路径
*/
public TreePath[] search(String text) {
if (StringUtils.isNotEmpty(text)) {
text = text.toLowerCase();
}
ArrayList<XCreator> searchList = new ArrayList<XCreator>();
XLayoutContainer root = designer.getRootComponent();
searchFormRoot(root, searchList, text);
TreePath[] paths = new TreePath[searchList.size()];
for (int i = 0; i < paths.length; i++) {
paths[i] = buildTreePath(searchList.get(i));
}
if (paths.length > 0) {
setAndScrollSelectionPath(paths);
} else {
setSelectionPath();
}
return paths;
}
private void setSelectionPath() {
/**
* 不让传null参数,所以只有自己定义
*/
super.setSelectionPath(null);
clearSelection();
}
private void searchFormRoot(XLayoutContainer container, ArrayList<XCreator> searchList, String text) {
if (StringUtils.isEmpty(text)) {
return;
}
for (int i = 0, size = container.getXCreatorCount(); i < size; i++) {
XCreator creator = container.getXCreator(i);
String xName = creator.toData().getWidgetName();
if (xName.toLowerCase().contains(text)) {
searchList.add(creator);
}
if (creator instanceof XLayoutContainer) {
searchFormRoot((XLayoutContainer) creator, searchList, text);
}
}
}
/**
* 触发
*/
public void fireTreeChanged() {
designer.refreshDesignerUI();
}
/**
* 刷新
*/
public void refreshTreeRoot() {
model = new ComponentTreeModel(designer, designer.getTopContainer());
setModel(model);
setDragEnabled(false);
setDropMode(DropMode.ON_OR_INSERT);
setTransferHandler(new TreeTransferHandler());
repaint();
}
/**
* 获得树的展开路径
* */
public void getExpandNodes(List<TreePath> searchList) {
getExpandNodes((XLayoutContainer)designer.getTopContainer(),searchList);
}
public void getExpandNodes(XLayoutContainer container, List<TreePath> searchList) {
TreePath treePath = buildTreePath(container);
if (isExpanded(treePath)) {
searchList.add(treePath);
for (int i = 0, size = container.getXCreatorCount(); i < size; i++) {
XCreator creator = container.getXCreator(i);
if (creator.acceptType(XLayoutContainer.class) || creator.acceptType(XCardSwitchButton.class)) {
getExpandNodes((XLayoutContainer) creator.getXCreator(), searchList);
}
}
}
//对绝对布局做特殊处理
if (container.acceptType(XWFitLayout.class)) {
XWFitLayout bodyFitLayout = (XWFitLayout) container;
for (int j = 0; j < bodyFitLayout.getXCreatorCount(); j++) {
//类型是绝对布局并且还是body
if (bodyFitLayout.getXCreator(j).acceptType(XWAbsoluteBodyLayout.class)) {
container = (XLayoutContainer) bodyFitLayout.getXCreator(j);
getExpandNodes(container, searchList);
}
}
}
}
/**
* 将树按照展开路径进行展开
* */
public void expandNodes(List<TreePath> list){
for(TreePath treePath:list) {
if (treePath.getLastPathComponent() instanceof XLayoutContainer) {
XLayoutContainer creator= (XLayoutContainer) treePath.getLastPathComponent();
if (XCreatorUtils.getParentXLayoutContainer(creator) == null) {
continue;
}
expandPath(treePath);
}
}
}
private TreePath buildTreePath(Component comp) {
ArrayList<Component> path = new ArrayList<Component>();
Component parent = comp;
while (parent != null) {
XCreator creator = (XCreator) parent;
path.add(0, parent);
if (creator != comp) {
creator.notShowInComponentTree(path);
}
parent = creator.getParentShow();
}
Object[] components = path.toArray();
return new TreePath(components);
}
private void popupPreviewPane(int popupPosYOnScreen, XCreator comp) {
if (previewPane == null) {
previewPane = new PopupPreviewPane();
}
if (previewPane.isVisible() && previewPane.getLocationOnScreen().y != popupPosYOnScreen) {
previewPane.setVisible(false);
}
if (!previewPane.isVisible() && comp.getWidth() != 0 && comp.getHeight() != 0) {
previewPane.setComp(comp);
int popupPosY = popupPosYOnScreen - FormHierarchyTreePane.getInstance().getLocationOnScreen().y;
GUICoreUtils.showPopupMenu(previewPane, FormHierarchyTreePane.getInstance(), -previewPane.getPreferredSize().width, popupPosY);
}
}
private void hidePreviewPane() {
if (previewPane != null && previewPane.isVisible()) {
previewPane.setVisible(false);
}
}
private final class ComponetTreeMouseListener extends MouseAdapter {
private final JTree tree;
private ComponetTreeMouseListener(JTree tree) {
this.tree = tree;
}
@Override
public void mouseMoved(MouseEvent e) {
Point p = e.getPoint();
int selRow = tree.getRowForLocation(p.x, p.y);
TreeCellRenderer r = tree.getCellRenderer();
if (selRow != -1 && r != null) {
TreePath path = tree.getPathForRow(selRow);
Point point = tree.getPathBounds(path).getLocation();
SwingUtilities.convertPointToScreen(point, tree);
XCreator comp = (XCreator) path.getLastPathComponent();
popupPreviewPane(point.y, comp);
} else {
hidePreviewPane();
}
}
@Override
public void mouseExited(MouseEvent e) {
hidePreviewPane();
}
}
private class PopupPreviewPane extends JPopupMenu {
private Container contentPane;
private BufferedImage compImage;
private static final int MAX_WIDTH = 360;
private static final int MAX_HEIGHT = 280;
PopupPreviewPane() {
contentPane = new JPanel();
contentPane.setBackground(Color.white);
this.setLayout(new BorderLayout());
this.add(contentPane, BorderLayout.CENTER);
this.setOpaque(false);
setPreferredSize(new Dimension(MAX_WIDTH, MAX_HEIGHT));
setBorder(BorderFactory.createLineBorder(UIConstants.LINE_COLOR));
}
public void setComp(XCreator comp) {
try {
this.compImage = componentToImage(comp);
this.updateSize();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void paint(Graphics g) {
super.paint(g);
if (compImage != null) {
g.drawImage(compImage, 0, 0, getWidth(), getHeight(), null);
}
}
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
}
public void menuSelectionChanged(boolean isIncluded) {
}
public Container getContentPane() {
return contentPane;
}
private BufferedImage componentToImage(Component comp) throws IOException {
BufferedImage im = new BufferedImage(comp.getWidth(), comp.getHeight(), BufferedImage.TYPE_INT_ARGB);
comp.paint(im.getGraphics());
return im;
}
// 根据控件内容,更新弹出框大小
private void updateSize() {
int width = compImage.getWidth();
int height = compImage.getHeight();
double aspectRatio = (double) width / height;
if (width > MAX_WIDTH) {
width = MAX_WIDTH;
height = (int) (width / aspectRatio);
}
if (height > MAX_HEIGHT) {
height = MAX_HEIGHT;
width = (int) (height * aspectRatio);
}
this.setPreferredSize(new Dimension(width, height));
}
}
}