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

376 lines
16 KiB

package com.fr.design.mainframe;
import com.fr.base.BaseUtils;
import com.fr.base.chart.BaseChartCollection;
import com.fr.chart.chartattr.ChartCollection;
import com.fr.chartx.attr.ChartProvider;
import com.fr.design.DesignModelAdapter;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.datapane.TableDataTreePane;
import com.fr.design.designer.beans.AdapterBus;
import com.fr.design.designer.beans.HoverPainter;
import com.fr.design.designer.beans.Painter;
import com.fr.design.designer.beans.events.DesignerEvent;
import com.fr.design.designer.beans.models.AddingModel;
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.XWAbsoluteLayout;
import com.fr.design.designer.creator.XWFitLayout;
import com.fr.design.designer.creator.XWParameterLayout;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.form.util.XCreatorConstants;
import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.icon.IconPathConstants;
import com.fr.design.mainframe.chart.info.ChartInfoCollector;
import com.fr.design.mod.bean.ChangeItem;
import com.fr.design.mod.bean.ContentChangeItem;
import com.fr.design.mod.event.TableDataModifyEvent;
import com.fr.design.utils.ComponentUtils;
import com.fr.event.EventDispatcher;
import com.fr.form.share.SharableWidgetProvider;
import com.fr.form.share.ShareLoader;
import com.fr.form.share.editor.SharableEditorProvider;
import com.fr.form.ui.Widget;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.Constants;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.JOptionPane;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import java.awt.Color;
import java.awt.Component;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 添加模式下鼠标事件处理器。
*/
public class FormCreatorDropTarget extends DropTarget {
private FormDesigner designer;
/**
* 当前鼠标的设计组件
*/
private Component current;
/**
* 当前添加模式对应的model
*/
private AddingModel addingModel;
private static final int GAP = 30;
private TabDragInner tabDragInner;
private JWindow promptWindow = new JWindow();
private UIButton promptButton = new UIButton("", BaseUtils.readIcon(IconPathConstants.FORBID_ICON_PATH));
public FormCreatorDropTarget(FormDesigner designer) {
this.designer = designer;
this.addingModel = designer.getAddingModel();
this.promptWindow.add(promptButton);
this.tabDragInner = new TabDragInner(designer);
}
private void adding(int x, int y) {
// 当前鼠标所在的组件
XCreator hoveredComponent = designer.getComponentAt(x, y);
// 获取该组件所在的焦点容器
XLayoutContainer container = XCreatorUtils.getHotspotContainer(hoveredComponent);
boolean success = false;
if (container != null) {
//XWCardTagLayout 切换添加状态到普通状态
container.stopAddingState(designer);
// 如果是容器,则调用其acceptComponent接受组件
AddingModel model = designer.getAddingModel();
boolean chartEnter2Para = !addingModel.getXCreator().canEnterIntoParaPane() && container.acceptType(XWParameterLayout.class);
boolean formSubmit2Adapt = !addingModel.getXCreator().canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class);
if (model != null && !chartEnter2Para && !formSubmit2Adapt) {
success = model.add2Container(designer, container, x, y);
}
cancelPromptWidgetForbidEnter();
}
if (success) {
// 如果添加成功,则触发相应事件
XCreator xCreator = container.acceptType(XWParameterLayout.class) ? designer.getParaComponent() : designer.getRootComponent();
//SetSelection时要确保选中的是最顶层的布局
//tab布局添加的时候是初始化了XWCardLayout,实际上最顶层的布局是XWCardMainBorderLayout
XCreator addingXCreator = addingModel.getXCreator();
Widget widget = (addingXCreator.getBackupParent() != null && addingXCreator.getTopLayout() != null) ? (addingXCreator.getTopLayout().toData()) : addingXCreator.toData();
//图表埋点
dealChartBuryingPoint(widget);
if (addingXCreator.isShared()) {
if (container.acceptType(XWAbsoluteLayout.class)) {
// 绝对布局中新添加的共享组件默认锁定尺寸比例
Rectangle bounds = new Rectangle(addingXCreator.getBounds());
Widget addingWidget = addingXCreator.toData();
if (addingWidget != null && bounds.width > 0 && bounds.height > 0) {
addingXCreator.toData().setAspectRatioLocked(true);
addingXCreator.toData().setAspectRatioBackup(1.0 * bounds.width / bounds.height);
}
}
String shareId = addingXCreator.getShareId();
SharableEditorProvider sharableEditor = ShareLoader.getLoader().getSharedElCaseEditorById(shareId);
SharableWidgetProvider bindInfo = ShareLoader.getLoader().getElCaseBindInfoById(shareId);
Map<String, String> tdNameMap = Collections.emptyMap();
if (sharableEditor != null && bindInfo != null) {
tdNameMap = TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()).addTableData(bindInfo.getName(), sharableEditor.getTableDataSource(), true);
//合并数据集之后,可能会有数据集名称变化,做一下联动
//共享的组件拿的时候都是克隆的,这边改拖拽中克隆的对象而非新克隆对象,上面这个新克隆的对象只是为了拿数据集
Map<String, String> map = new HashMap<>();
for (Map.Entry<String, String> entry : tdNameMap.entrySet()) {
designer.getTarget().renameTableData(widget, entry.getKey(), entry.getValue());
map.put(entry.getKey(), entry.getValue());
}
if (!map.isEmpty()) {
DesignTableDataManager.fireDSChanged(map);
}
}
EventDispatcher.fire(TableDataModifyEvent.INSTANCE, new ContentChangeItem(tdNameMap, widget, ChangeItem.TABLE_DATA_NAME));
}
designer.getSelectionModel().setSelectedCreators(
FormSelectionUtils.rebuildSelection(xCreator, new Widget[]{widget}));
if (!addingModel.isAddedIllegal()) {
designer.getEditListenerTable().fireCreatorModified(addingModel.getXCreator(), DesignerEvent.CREATOR_ADDED);
}
tabDragInner.tryDragIn();
} else {
Toolkit.getDefaultToolkit().beep();
// 拖入失败 取消选中
XCreator creator = addingModel.getXCreator();
if (creator != null) {
creator.setSelected(false);
}
}
// 取消提示
designer.setPainter(null);
// 切换添加状态到普通状态
designer.stopAddingState();
}
private void entering(int x, int y) {
// 将要添加的组件图标移动到鼠标下的位置
addingModel.moveTo(x, y);
designer.repaint();
}
private void exiting() {
cancelPromptWidgetForbidEnter();
// 隐藏组件图标
addingModel.reset();
designer.setPainter(null);
designer.repaint();
}
private void hovering(int x, int y) {
// 当前位置移植鼠标e所在的位置
addingModel.moveTo(x, y);
// 获取e所在的焦点组件
XCreator hotspot = designer.getComponentAt(x, y);
// 获取焦点组件所在的焦点容器
XLayoutContainer container = XCreatorUtils.getHotspotContainer(hotspot);
//提示组件是否可以拖入
promptUser(x, y, container);
if (container != null) {
dealWithContainer(x, y, container);
} else {
// 如果鼠标不在任何组件上,则取消提示器
designer.setPainter(null);
current = null;
}
designer.repaint();
}
private void dealWithContainer(int x, int y, XLayoutContainer container) {
HoverPainter painter = null;
if (container != current || designer.getPainter() == null) {
// 如果焦点容器不是当前容器
if (current != null) {
// 取消前一个焦点容器的提示渲染器
designer.setPainter(null);
}
if (container == null) {
throw new IllegalArgumentException("container can not be null!");
}
//获取painter的时候要考虑布局之间嵌套的问题
XLayoutContainer xLayoutContainer = container.getTopLayout();
if (xLayoutContainer != null && xLayoutContainer.getParent() != null
&& ((XLayoutContainer) xLayoutContainer.getParent()).acceptType(XWAbsoluteLayout.class)) {
if (!xLayoutContainer.isEditable()) {
xLayoutContainer = (XLayoutContainer) xLayoutContainer.getParent();
}
}
painter = AdapterBus.getContainerPainter(designer,
xLayoutContainer != null && xLayoutContainer.acceptType(XWAbsoluteLayout.class) ? xLayoutContainer : container);
// 为界面设计器设置提示渲染提示器
designer.setPainter(painter);
// 将当前容器更新为新的容器
current = container;
} else {
// 获取当前设计界面的提示渲染器
Painter p = designer.getPainter();
if (p instanceof HoverPainter) {
painter = (HoverPainter) p;
}
}
if (painter != null) {
// 为提示渲染器设置焦点位置、区域等渲染参数
Rectangle rect = ComponentUtils.getRelativeBounds(container);
rect.x -= designer.getArea().getHorizontalValue();
rect.y -= designer.getArea().getVerticalValue();
painter.setRenderingBounds(rect);
painter.setHotspot(new Point(x, y));
painter.setCreator(addingModel.getXCreator());
}
}
private void promptUser(int x, int y, XLayoutContainer container) {
if (!addingModel.getXCreator().canEnterIntoParaPane() && container.acceptType(XWParameterLayout.class)) {
promptButton.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Forbid_Drag_Into_Para_Pane"));
promptWidgetForbidEnter(x, y, container);
} else if (!addingModel.getXCreator().canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class)) {
promptButton.setText(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Forbid_Drag_Into_Adapt_Pane"));
promptWidgetForbidEnter(x, y, container);
} else {
cancelPromptWidgetForbidEnter();
}
}
private void promptWidgetForbidEnter(int x, int y, XLayoutContainer container) {
container.setBorder(BorderFactory.createLineBorder(Color.RED, Constants.LINE_MEDIUM));
int screenX = designer.getArea().getLocationOnScreen().x;
int screenY = designer.getArea().getLocationOnScreen().y;
promptWindow.setLocation(screenX + x + GAP, screenY + y + GAP);
promptWindow.setVisible(true);
}
private void cancelPromptWidgetForbidEnter() {
if (designer.getParaComponent() != null) {
designer.getParaComponent().setBorder(BorderFactory.createLineBorder(XCreatorConstants.LAYOUT_SEP_COLOR, Constants.LINE_THIN));
}
designer.getRootComponent().setBorder(BorderFactory.createLineBorder(XCreatorConstants.LAYOUT_SEP_COLOR, Constants.LINE_THIN));
promptWindow.setVisible(false);
}
/**
* 拖拽进入
*
* @param dtde 事件
*/
@Override
public synchronized void dragEnter(DropTargetDragEvent dtde) {
Point loc = dtde.getLocation();
this.entering(designer.getRelativeX(loc.x), designer.getRelativeY(loc.y));
}
/**
* 拖拽移动经过
*
* @param dtde 事件
*/
@Override
public synchronized void dragOver(DropTargetDragEvent dtde) {
Point loc = dtde.getLocation();
int x = designer.getRelativeX(loc.x);
int y = designer.getRelativeY(loc.y);
hovering(x, y);
tabDragInner.canDragIn(designer.getComponentAt(x, y), x, y);
}
/**
* 拖拽事件
*
* @param dtde 事件
*/
@Override
public synchronized void dropActionChanged(DropTargetDragEvent dtde) {
//do nothing
}
/**
* 拖拽离开
*
* @param dte 事件
*/
@Override
public synchronized void dragExit(DropTargetEvent dte) {
this.exiting();
}
/**
* 拖拽释放
*
* @param dtde 事件
*/
@Override
public synchronized void drop(DropTargetDropEvent dtde) {
try {
dropXCreator(dtde);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
if (addingModel.getXCreator().isShared()) {
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Share_Drag_Component_Error_Info"),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Error"),
JOptionPane.ERROR_MESSAGE,
UIManager.getIcon("OptionPane.errorIcon")
);
}
dtde.rejectDrop();
}
}
private void dropXCreator(DropTargetDropEvent dtde) {
Point loc = dtde.getLocation();
this.adding(designer.getRelativeX(loc.x), designer.getRelativeY(loc.y));
// 放到事件末尾执行
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// 拖拽释放后标记未选中
for (XCreator xCreator : designer.getSelectionModel().getSelection().getSelectedCreators()) {
xCreator.setSelected(true);
}
}
});
//针对在表单中拖入一个控件直接ctrl+s无反应
designer.requestFocus();
}
private void dealChartBuryingPoint(Widget widget) {
List<BaseChartCollection> chartCollections = widget.getChartCollections();
for (BaseChartCollection baseChartCollection : chartCollections) {
ChartCollection chartCollection = (ChartCollection) baseChartCollection;
for (int i = 0, size = chartCollection.getChartCount(); i < size; i++) {
ChartProvider chart = chartCollection.getChart(i, ChartProvider.class);
//是否是共享的复用组件
boolean isReuse = StringUtils.isNotEmpty(this.addingModel.getXCreator().getShareId());
ChartInfoCollector.getInstance().collection(chart, null, isReuse);
ChartInfoCollector.getInstance().checkTestChart(chart);
}
}
}
public TabDragInner getTabDragInner() {
return this.tabDragInner;
}
}