diff --git a/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java b/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java index 920ecb78c..443a55671 100644 --- a/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java +++ b/designer-base/src/main/java/com/fr/design/file/HistoryTemplateListCache.java @@ -15,7 +15,6 @@ import com.fr.design.mainframe.JVirtualTemplate; import com.fr.design.ui.util.UIUtil; import com.fr.file.FILE; import com.fr.file.FileNodeFILE; -import com.fr.file.StashedFILE; import com.fr.general.ComparatorUtils; import com.fr.invoke.ClassHelper; import com.fr.log.FineLoggerFactory; @@ -25,7 +24,7 @@ import com.fr.stable.CoreConstants; import com.fr.stable.StringUtils; import com.fr.third.org.apache.commons.io.FilenameUtils; -import java.io.ByteArrayOutputStream; +import javax.swing.SwingWorker; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -33,7 +32,6 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Set; -import javax.swing.SwingWorker; /** * 历史模板缓存 @@ -364,7 +362,7 @@ public class HistoryTemplateListCache implements CallbackEvent { int size = historyList.size(); for (int i = 0; i < size; i++) { JTemplate template = historyList.get(i); - FILE file = templateToStashFile(template); + FILE file = template.templateToStashFile(); if (file != null) { stashFILEMap.put(i, file); } @@ -372,21 +370,6 @@ public class HistoryTemplateListCache implements CallbackEvent { FineLoggerFactory.getLogger().info("Env Change Template Stashed."); } - private FILE templateToStashFile(JTemplate template) { - FILE file = template.getEditingFILE(); - try { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - BaseBook target = template.getTarget(); - if (target != null) { - target.export(outputStream); - return new StashedFILE(file, outputStream.toByteArray(), template.suffix()); - } - // 如果 target == null 那么这个模板是被模板内存优化功能处理过的,不用处理 - } catch (Exception e) { - FineLoggerFactory.getLogger().error(e.getMessage(), e); - } - return null; - } private boolean checkStash() { try { @@ -469,7 +452,7 @@ public class HistoryTemplateListCache implements CallbackEvent { FILE file = template.getEditingFILE(); boolean needReload = context == null || needReloadTemplate(context, template); if (needReload) { - FILE stashFile = templateToStashFile(template); + FILE stashFile = template.templateToStashFile(); if (stashFile != null) { FineLoggerFactory.getLogger().info("{} is being reloaded", file.getName()); template.refreshResource(stashFile); diff --git a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java index 499898bbf..f1a40ccdc 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java @@ -65,6 +65,7 @@ import com.fr.event.EventDispatcher; import com.fr.file.FILE; import com.fr.file.FILEChooserPane; import com.fr.file.MemFILE; +import com.fr.file.StashedFILE; import com.fr.form.ui.NoneWidget; import com.fr.form.ui.Widget; import com.fr.general.ComparatorUtils; @@ -104,6 +105,7 @@ import javax.swing.JOptionPane; import javax.swing.SwingConstants; import javax.swing.undo.UndoManager; import java.awt.BorderLayout; +import java.io.ByteArrayOutputStream; import java.awt.Dimension; import java.awt.FontMetrics; import java.util.Set; @@ -438,6 +440,22 @@ public abstract class JTemplate> stopListenThemeConfig(); } + public FILE templateToStashFile() { + FILE file = this.getEditingFILE(); + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + BaseBook target = this.getTarget(); + if (target != null) { + target.export(outputStream); + return new StashedFILE(file, outputStream.toByteArray(), template.suffix()); + } + // 如果 target == null 那么这个模板是被模板内存优化功能处理过的,不用处理 + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return null; + } + /** * 刷新内部资源 diff --git a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/cell/CellStyleEditPane.java b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/cell/CellStyleEditPane.java index d8a4096ce..846da2649 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/cell/CellStyleEditPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/theme/edit/cell/CellStyleEditPane.java @@ -88,13 +88,13 @@ public class CellStyleEditPane extends MultiTabPane { @Override public ThemedCellStyle updateBean() { - AbstractBasicStylePane basicStylePane = (AbstractBasicStylePane) paneList.get(tabPane.getSelectedIndex()); - Style style = basicStylePane.update(this.cellStyle.getStyle()); + Style style = this.cellStyle.getStyle(); CellBorderStyle borderStyle = createDefaultBorderStyleFromStyle(style); - - - if (ThemedFeatureController.isCellStyleSupportInnerBorder() && basicStylePane instanceof BorderPane) { - borderStyle = ((BorderPane) basicStylePane).update(); + for (BasicPane basicPane : paneList) { + style = ((AbstractBasicStylePane) basicPane).update(style); + if (ThemedFeatureController.isCellStyleSupportInnerBorder() && basicPane instanceof BorderPane) { + borderStyle = ((BorderPane) basicPane).update(); + } } this.cellStyle.setStyle(style); diff --git a/designer-base/src/main/java/com/fr/design/report/fit/FormFitConfigPane.java b/designer-base/src/main/java/com/fr/design/report/fit/FormFitConfigPane.java index 08b70cb77..d88a3a16e 100644 --- a/designer-base/src/main/java/com/fr/design/report/fit/FormFitConfigPane.java +++ b/designer-base/src/main/java/com/fr/design/report/fit/FormFitConfigPane.java @@ -1,17 +1,35 @@ package com.fr.design.report.fit; +import com.fr.base.svg.SVGLoader; +import com.fr.design.gui.ibutton.UIRadioButton; import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.imenu.UIPopupMenu; import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; +import com.fr.design.report.fit.menupane.FitRadioGroup; +import com.fr.design.utils.gui.GUICoreUtils; +import com.fr.general.ComparatorUtils; import com.fr.report.fit.ReportFitAttr; - import javax.swing.JPanel; +import javax.swing.JPopupMenu; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Rectangle; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; public class FormFitConfigPane extends ReportFitConfigPane { + private static final int ICON_OFFSET_X = 25; + private static final int ICON_OFFSET_Y = 3; + private static final int ICON_SIZE = 16; + private static final Image HOVER_IMAGE = SVGLoader.load("/com/fr/design/icon/icon_ec_default_fit.svg"); private static final int DEFAULT_ITEM = 0; + private static final int CUSTOM_ITEM = 1; public FormFitConfigPane(FitAttrModel fitAttrModel) { @@ -33,6 +51,92 @@ public class FormFitConfigPane extends ReportFitConfigPane { return jPanel; } + protected void initRadioGroup(FitRadioGroup fitRadioGroup, String name, String[] options, Component[] components) { + components[0] = new UILabel(name); + for (int i = 0; i < options.length; i++) { + if (options[i] != null) { + UIRadioButton fontFitRadio = ComparatorUtils.equals(options[i], Toolkit.i18nText("Fine-Designer_Fit-Default")) ? new UIRadioButtonWithIcon(options[i]) : new UIRadioButton(options[i]); + fitRadioGroup.add(fontFitRadio); + components[i + 1] = fontFitRadio; + } else { + components[i + 1] = null; + } + } + fitRadioGroup.addActionListener(getPreviewActionListener()); + } + + private class UIRadioButtonWithIcon extends UIRadioButton { + private final JPopupMenu popupMenu; + private NewFitPreviewPane ecFitPreviewPane; + + public UIRadioButtonWithIcon(String text) { + super(text); + popupMenu = this.createPopupMenu(); + initMouseListener(); + } + + private JPopupMenu createPopupMenu() { + UIPopupMenu uiPopupMenu = new UIPopupMenu() { + @Override + protected void paintBorder(Graphics g) { + + } + }; + uiPopupMenu.setLayout(new BorderLayout(0, 0)); + uiPopupMenu.setOpaque(false); + uiPopupMenu.add(ecFitPreviewPane = new NewFitPreviewPane(FitType.HORIZONTAL_FIT), BorderLayout.CENTER); + ecFitPreviewPane.setPreferredSize(new Dimension(300, 204)); + return uiPopupMenu; + } + + private void initMouseListener() { + this.addMouseListener(new MouseAdapter() { + @Override + public void mouseExited(MouseEvent e) { + super.mouseExited(e); + hidePreviewPane(); + } + }); + int defaultTextWidth = calculateStartX(); + this.addMouseMotionListener(new MouseAdapter() { + @Override + public void mouseMoved(MouseEvent e) { + super.mouseMoved(e); + if (new Rectangle(ICON_OFFSET_X + defaultTextWidth, ICON_OFFSET_Y, ICON_SIZE, ICON_SIZE).contains(e.getPoint())) { + showPreviewPane(e); + } else { + hidePreviewPane(); + } + + } + }); + } + + public void showPreviewPane(MouseEvent e) { + popupMenu.setVisible(true); + ecFitPreviewPane.refreshPreview(fontRadioGroup.isFontFit()); + GUICoreUtils.showPopupMenu(popupMenu, this, e.getX() + 10, e.getY() + 10); + } + + public void hidePreviewPane() { + if (popupMenu != null && popupMenu.isVisible()) { + popupMenu.setVisible(false); + } + } + + + @Override + public void paint(Graphics g) { + super.paint(g); + g.drawImage(HOVER_IMAGE, calculateStartX() + ICON_OFFSET_X, ICON_OFFSET_Y, null); + } + + private int calculateStartX() { + FontMetrics metrics = this.getFontMetrics(this.getFont()); + return metrics.stringWidth(this.getText()); + } + } + private JPanel createTipPane() { JPanel jPanel = FRGUIPaneFactory.createVerticalFlowLayout_S_Pane(true); UILabel label1 = new UILabel(Toolkit.i18nText("Fine-Design_Form_PC_FIT_Config_Tip1")); diff --git a/designer-base/src/main/java/com/fr/design/report/fit/NewFitPreviewPane.java b/designer-base/src/main/java/com/fr/design/report/fit/NewFitPreviewPane.java index 8b0710de3..2bc69cedc 100644 --- a/designer-base/src/main/java/com/fr/design/report/fit/NewFitPreviewPane.java +++ b/designer-base/src/main/java/com/fr/design/report/fit/NewFitPreviewPane.java @@ -16,8 +16,16 @@ public class NewFitPreviewPane extends JPanel { private FitType fitType = FitType.DOUBLE_FIT; private static final Color DEFAULT_PAINT_COLOR = Color.decode("#419BF9"); private static final int FIT_FONT_SIZE = 15; - private static final int NO_FIT_FONT_SIZE = 9; - private static final Dimension NO_FIT_CONTAINER_DIMENSION = new Dimension(200, 136); + private static final int NO_FIT_FONT_SIZE = 10; + private static final Dimension NO_FIT_CONTAINER_DIMENSION = new Dimension(230, 80); + + public NewFitPreviewPane(){ + + } + + public NewFitPreviewPane(FitType fitType){ + this.fitType = fitType; + } @Override public void paint(Graphics g) { diff --git a/designer-base/src/main/java/com/fr/design/report/fit/ReportFitConfigPane.java b/designer-base/src/main/java/com/fr/design/report/fit/ReportFitConfigPane.java index 399e7fef9..158089602 100644 --- a/designer-base/src/main/java/com/fr/design/report/fit/ReportFitConfigPane.java +++ b/designer-base/src/main/java/com/fr/design/report/fit/ReportFitConfigPane.java @@ -93,7 +93,7 @@ public class ReportFitConfigPane extends JPanel { fitRadioGroup.addActionListener(getPreviewActionListener()); } - private ActionListener getPreviewActionListener() { + protected ActionListener getPreviewActionListener() { return new ActionListener() { @Override public void actionPerformed(ActionEvent e) { diff --git a/designer-base/src/main/resources/com/fr/design/icon/icon_ec_default_fit.svg b/designer-base/src/main/resources/com/fr/design/icon/icon_ec_default_fit.svg new file mode 100644 index 000000000..4deb67b0d --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/icon/icon_ec_default_fit.svg @@ -0,0 +1,3 @@ + + + diff --git a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChangeConfigPane.java b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChangeConfigPane.java index 3de9aaa09..bbc923f4d 100644 --- a/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChangeConfigPane.java +++ b/designer-chart/src/main/java/com/fr/design/mainframe/chart/gui/ChangeConfigPane.java @@ -4,29 +4,42 @@ package com.fr.design.mainframe.chart.gui; * Created by hufan on 2016/10/20. */ +import com.fr.base.BaseFormula; +import com.fr.base.Utils; import com.fr.chart.base.AttrChangeConfig; import com.fr.chart.base.AttrChangeType; +import com.fr.chart.chartattr.Chart; import com.fr.chart.chartattr.ChartCollection; import com.fr.design.beans.BasicBeanPane; +import com.fr.design.foldablepane.UIExpandablePane; +import com.fr.design.formula.TinyFormulaPane; import com.fr.design.gui.ibutton.UIButtonGroup; +import com.fr.design.gui.ibutton.UIToggleButton; import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.ispinner.UISpinner; +import com.fr.design.i18n.Toolkit; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.mainframe.chart.gui.style.ChartTextAttrPane; -import com.fr.design.i18n.Toolkit; - +import com.fr.stable.StableUtils; import com.fr.van.chart.designer.TableLayout4VanChartHelper; import javax.swing.BorderFactory; +import javax.swing.BoxLayout; import javax.swing.JPanel; import javax.swing.SwingConstants; import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Component; import java.awt.Dimension; +import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.ArrayList; +import java.util.List; /** * 图表切换设置面板 @@ -40,6 +53,7 @@ public class ChangeConfigPane extends BasicBeanPane { private static final int CONSTANT_TEN = 10; private static final int CONSTANT_THIRTY = 30; private static final int CONSTANT_ZERO = 0; + private static final int COL_COUNT = 4; private JPanel contentPane; //配置方式按钮 private UIButtonGroup configStyleButton; @@ -56,6 +70,11 @@ public class ChangeConfigPane extends BasicBeanPane { private ColorSelectBoxWithOutTransparent colorSelectBox4carousel; private UIButtonGroup switchStyleGroup; + private JPanel chartTypesPane; + private List switchTitles = new ArrayList<>(); + private JPanel switchTitlePane = new JPanel(); + private List changeChartButtons = new ArrayList<>(); + private int selectedChart; // 设置面板里面选取的图表,不是真正切换的图表 public ChangeConfigPane(){ initButtonGroup(); @@ -69,10 +88,11 @@ public class ChangeConfigPane extends BasicBeanPane { double p = TableLayout.PREFERRED; double f = TableLayout.FILL; double[] columnSize = {p, f}; - double[] rowSize = {p,p}; + double[] rowSize = {p, p, p}; Component[][] components = new Component[][]{ new Component[]{new UILabel(Toolkit.i18nText("Fine-Design_Chart_Change_Style")),configStyleButton}, new Component[]{configPane, null}, + new Component[]{createButtonContentPane(), null} }; return TableLayoutHelper.createTableLayoutPane(components, rowSize, columnSize); } @@ -147,14 +167,84 @@ public class ChangeConfigPane extends BasicBeanPane { return TableLayout4VanChartHelper.createGapTableLayoutPane(Toolkit.i18nText("Fine-Design_Basic_Background"), colorSelectBox4button, EDIT_AREA_WIDTH); } + private JPanel createButtonContentPane() { + JPanel buttonContentPane = new JPanel(new BorderLayout()); + + chartTypesPane = new JPanel(); + chartTypesPane.setLayout(new BoxLayout(chartTypesPane, BoxLayout.Y_AXIS)); + switchTitlePane.setLayout(new CardLayout()); + + buttonContentPane.add(chartTypesPane, BorderLayout.NORTH); + buttonContentPane.add( + TableLayout4VanChartHelper.createGapTableLayoutPane( + Toolkit.i18nText("Fine-Design_Chart_Switch_Title_Label"), + switchTitlePane, + EDIT_AREA_WIDTH + ), + BorderLayout.CENTER + ); + + UIExpandablePane expandablePane = new UIExpandablePane(Toolkit.i18nText("Fine-Design_Chart_Button_Content"), 20, buttonContentPane) { + protected void setcontentPanelontentPanelBorder() { + + } + }; + expandablePane.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0)); + return expandablePane; + } + + private void populateButtonContentPane(ChartCollection collection) { + int count = collection.getChartCount(); + int select = collection.getSelectedIndex(); + + JPanel pane = null; + for (int i = 0; i < count; i++) { + if (i % COL_COUNT == 0) { + pane = new JPanel(new FlowLayout(FlowLayout.LEFT)); + chartTypesPane.add(pane); + } + + ChangeChartButton button = new ChangeChartButton(i, collection); + changeChartButtons.add(button); + button.setSelected(i == select); + pane.add(button); + + populateSwitchTitlePane(i, collection); + } + + chartTypesPane.revalidate(); + switchTitlePane.revalidate(); + selectedChart = select; + } + + private void populateSwitchTitlePane(int chartIndex, ChartCollection collection) { + Chart chart = collection.getChart(chartIndex, Chart.class); + Object switchTitle = chart.getSwitchTitle(); + String result; + if (switchTitle != null) { + if (switchTitle instanceof BaseFormula) { + result = ((BaseFormula) switchTitle).getContent(); + } else { + result = Utils.objectToString(switchTitle); + } + } else { + result = collection.getChartName(chartIndex); + } + + TinyFormulaPane title = new TinyFormulaPane(); + title.populateBean(result); + switchTitles.add(title); + switchTitlePane.add(title, collection.getChartName(chartIndex)); + } + private JPanel createButtonConfigPane() { double p = TableLayout.PREFERRED; double f = TableLayout.FILL; double[] columnSize = {p, f}; - double[] rowSize = {p,p}; + double[] rowSize = {p, p, p}; Component[][] components = new Component[][]{ - new Component[]{createTitleStylePane(),null}, - new Component[]{createButtonBackgroundColorPane(),null}, + new Component[]{createTitleStylePane(), null}, + new Component[]{createButtonBackgroundColorPane(), null}, }; return TableLayoutHelper.createTableLayoutPane(components, rowSize, columnSize); @@ -195,6 +285,7 @@ public class ChangeConfigPane extends BasicBeanPane { //按钮切换界面 styleAttrPane.populate(changeConfigAttr.getStyleAttr()); colorSelectBox4button.setSelectObject(changeConfigAttr.getButtonColor()); + populateButtonContentPane(ob); //轮播切换界面 timeInterval.setValue(changeConfigAttr.getTimeInterval()); @@ -224,10 +315,64 @@ public class ChangeConfigPane extends BasicBeanPane { changeConfigAttr.setTimeInterval((int) timeInterval.getValue()); changeConfigAttr.setCarouselColor(colorSelectBox4carousel.getSelectObject()); changeConfigAttr.setShowArrow(switchStyleGroup.getSelectedIndex() == 0); + + updateSwitchTitle(ob); + } + + private void updateSwitchTitle(ChartCollection collection) { + int count = collection.getChartCount(); + for (int i = 0; i < count; i++) { + String titleString = switchTitles.get(i).updateBean(); + Object titleObj; + if (StableUtils.maybeFormula(titleString)) { + titleObj = BaseFormula.createFormulaBuilder().build(titleString); + } else { + titleObj = titleString; + } + collection.getChart(i, Chart.class).setSwitchTitle(titleObj); + } } @Override protected String title4PopupWindow() { return Toolkit.i18nText("Fine-Design_Chart_Change_Config_Attributes"); } + + private class ChangeChartButton extends UIToggleButton { + private static final int BUTTON_WIDTH = 52; + private static final int BUTTON_HEIGHT = 20; + + private ChartCollection collection; + private int buttonIndex; + + public ChangeChartButton(int i, ChartCollection collection) { + super(collection.getChartName(i)); + this.collection = collection; + this.buttonIndex = i; + } + + @Override + protected MouseListener getMouseListener() { + return new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + resetChangeChartButtons(); + CardLayout cardLayout = (CardLayout) switchTitlePane.getLayout(); + cardLayout.show(switchTitlePane, collection.getChartName(buttonIndex)); + ChangeChartButton.this.setSelected(true); + selectedChart = buttonIndex; + } + }; + } + + public Dimension getPreferredSize() { + return new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT); + } + } + + private void resetChangeChartButtons() { + for (ChangeChartButton changeChartButton : changeChartButtons) { + changeChartButton.setSelected(false); + } + } } diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartGuideLinesPane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartGuideLinesPane.java new file mode 100644 index 000000000..4b7b140cd --- /dev/null +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/component/VanChartGuideLinesPane.java @@ -0,0 +1,4 @@ +package com.fr.van.chart.designer.component; + +public class VanChartGuideLinesPane { +} diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/ComponentAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/ComponentAdapter.java index 174f56ea2..b296da48b 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/ComponentAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/ComponentAdapter.java @@ -1,35 +1,24 @@ package com.fr.design.designer.beans; -import java.awt.Graphics; -import java.awt.event.MouseEvent; -import java.util.ArrayList; - -import javax.swing.JComponent; -import javax.swing.JPopupMenu; - import com.fr.design.beans.GroupModel; import com.fr.design.designer.beans.events.DesignerEditor; import com.fr.design.designer.creator.PropertyGroupPane; +import javax.swing.JComponent; +import javax.swing.JPopupMenu; +import java.awt.event.MouseEvent; +import java.util.ArrayList; + /** * 组件适配器接口 * 主要目的是为具体组件提供特殊设计行为 */ public interface ComponentAdapter { - /** - * 在组件选择面板上选择了组件类型后,在设计界面上跟随鼠标移动用来代表当前要添加组件的图形 - * 一般使用组件自身的图形代替。 - * - * @param component 要添加的组件 - * @param g 当前设计器的图形上下文对象 - */ - void paintComponentMascot(Graphics g); - /** * 当鼠标在此设计组件上右键点击时,该方法根据上下文和组件类型提供弹出响应的菜单 * - * @param 引发弹出菜单的鼠标事件 + * @param e 引发弹出菜单的鼠标事件 * * @return 弹出菜单 */ @@ -49,7 +38,7 @@ public interface ComponentAdapter { /** * 提供双击设计器的编辑器 - * @param bean 鼠标双击的被设计组件 + * * @return 被设计的编辑器 */ public DesignerEditor getDesignerEditor(); @@ -57,5 +46,5 @@ public interface ComponentAdapter { /** * 实例化组件的适配器后,在这儿进行初始化 */ - void initialize(); + void initialize(); } \ No newline at end of file diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/LayoutAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/LayoutAdapter.java index 3c0c2bd5f..bbc7670a4 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/LayoutAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/LayoutAdapter.java @@ -3,11 +3,15 @@ package com.fr.design.designer.beans; import com.fr.design.beans.GroupModel; import com.fr.design.designer.beans.adapters.layout.DefaultDesignerBaseOperate; import com.fr.design.designer.beans.adapters.layout.DesignerBaseOperate; +import com.fr.design.designer.beans.models.DraggingModel; import com.fr.design.designer.beans.models.SelectionModel; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.treeview.DefaultXCreatorTreeCellRender; import com.fr.design.designer.treeview.XCreatorTreeCellRender; +import java.awt.Dimension; +import java.awt.Graphics; + /** * 该接口是LayoutManager的BeanInfo类。标准Java平台没有提供布局管理器的BeanInfo类, * 对于界面设计工具来说还需一些特殊的行为。 @@ -135,9 +139,46 @@ public interface LayoutAdapter { return true; } + /** + * 拖拽开始 + * + * @param xCreator + * @param selectionModel + */ void dragStart(XCreator xCreator, SelectionModel selectionModel); + /** + * 拖拽经过 + * + * @param xCreator + * @param selectionModel + * @param x + * @param y + */ default void dragOver(XCreator xCreator, SelectionModel selectionModel, int x, int y) { }; + + /** + * 组件正在被拖拽时的处理逻辑 + * + * @param model + */ + void dragging(DraggingModel model); + + /** + * 绘制组件拖拽阴影 + * + * @param g 当前设计器的图形上下文对象 + * @param xCreator 被拖拽的组件 + */ + void paintComponentMascot(Graphics g, XCreator xCreator); + + /** + * 描述组件被拖拽的时候应该显示的尺寸 + * + * @param creator 被拖拽的组件 + * @return 组件大小 + */ + Dimension getDragSize(XCreator creator); } diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/component/CompositeComponentAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/component/CompositeComponentAdapter.java index cb7a7a620..d97b85c5a 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/component/CompositeComponentAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/component/CompositeComponentAdapter.java @@ -23,13 +23,9 @@ import com.fr.stable.core.PropertyChangeAdapter; import javax.swing.Action; import javax.swing.JComponent; import javax.swing.JPopupMenu; -import java.awt.AlphaComposite; import java.awt.Component; import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; import java.awt.event.MouseEvent; -import java.awt.image.BufferedImage; import java.beans.IntrospectionException; import java.util.ArrayList; import java.util.Collections; @@ -63,19 +59,6 @@ public class CompositeComponentAdapter implements ComponentAdapter { } } - @Override - public void paintComponentMascot(Graphics g) { - //自适应交叉点渲染有点问题,拖拽的控件设置成半透明 - Graphics2D g2d = (Graphics2D) g; - AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f); - g2d.setComposite(composite); - BufferedImage im = new BufferedImage(xCreator.getWidth(), xCreator.getHeight(), BufferedImage.TYPE_INT_ARGB); - xCreator.paint(im.getGraphics()); - g.drawImage(im, 0, 0, xCreator.initEditorSize().width - 1, xCreator.initEditorSize().height - 1, null); - g.setColor(XCreatorConstants.RESIZE_BOX_BORDER_COLOR); - g.drawRect(0, 0, xCreator.initEditorSize().width - 1, xCreator.initEditorSize().height - 1); - } - @Override public JPopupMenu getContextPopupMenu(MouseEvent e) { JPopupMenu popupMenu = new JPopupMenu(); diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java index 7d287e5a5..e0f79e65e 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/AbstractLayoutAdapter.java @@ -4,16 +4,23 @@ import com.fr.design.beans.GroupModel; import com.fr.design.designer.beans.ConstraintsGroupModel; import com.fr.design.designer.beans.HoverPainter; import com.fr.design.designer.beans.LayoutAdapter; +import com.fr.design.designer.beans.models.DraggingModel; import com.fr.design.designer.beans.models.SelectionModel; import com.fr.design.designer.beans.painters.NullPainter; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XLayoutContainer; import com.fr.design.designer.creator.XWidgetCreator; +import com.fr.design.form.util.XCreatorConstants; import com.fr.design.utils.ComponentUtils; import com.fr.design.utils.gui.LayoutUtils; import com.fr.general.ComparatorUtils; +import java.awt.AlphaComposite; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.LayoutManager; +import java.awt.image.BufferedImage; public abstract class AbstractLayoutAdapter implements LayoutAdapter { @@ -209,4 +216,28 @@ public abstract class AbstractLayoutAdapter implements LayoutAdapter { selectionModel.removeCreator(xCreator, xCreator.getWidth(), xCreator.getHeight()); selectionModel.setSelectedCreator(container); } + + @Override + public void dragging(DraggingModel model) { + + } + + @Override + public void paintComponentMascot(Graphics g, XCreator xCreator) { + //自适应交叉点渲染有点问题,拖拽的控件设置成半透明 + int dragWidth = this.getDragSize(xCreator).width, dragHeight = this.getDragSize(xCreator).height; + Graphics2D g2d = (Graphics2D) g; + AlphaComposite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f); + g2d.setComposite(composite); + BufferedImage im = new BufferedImage(xCreator.getWidth(), xCreator.getHeight(), BufferedImage.TYPE_INT_ARGB); + xCreator.paint(im.getGraphics()); + g.drawImage(im, 0, 0, dragWidth - 1, dragHeight - 1, null); + g.setColor(XCreatorConstants.RESIZE_BOX_BORDER_COLOR); + g.drawRect(0, 0, dragWidth - 1, dragHeight - 1); + } + + @Override + public Dimension getDragSize(XCreator xCreator) { + return xCreator.initEditorSize(); + } } diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java index e4426f61a..5bdfe3c29 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRAbsoluteLayoutAdapter.java @@ -3,10 +3,12 @@ package com.fr.design.designer.beans.adapters.layout; import com.fr.design.beans.GroupModel; import com.fr.design.designer.beans.ConstraintsGroupModel; import com.fr.design.designer.beans.HoverPainter; +import com.fr.design.designer.beans.models.DraggingModel; import com.fr.design.designer.beans.painters.FRAbsoluteLayoutPainter; import com.fr.design.designer.creator.*; import com.fr.design.designer.properties.BoundsGroupModel; import com.fr.design.designer.properties.FRAbsoluteLayoutPropertiesGroupModel; +import com.fr.design.mainframe.FormDesigner; import com.fr.design.utils.ComponentUtils; import com.fr.design.utils.gui.LayoutUtils; import com.fr.form.ui.Widget; @@ -15,6 +17,7 @@ import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; import java.awt.*; +import java.awt.event.MouseEvent; public class FRAbsoluteLayoutAdapter extends FRBodyLayoutAdapter { //是不是添加到父容器上 @@ -345,4 +348,16 @@ public class FRAbsoluteLayoutAdapter extends FRBodyLayoutAdapter { XWAbsoluteLayout xwAbsoluteLayout = (XWAbsoluteLayout) container; return new FRAbsoluteLayoutPropertiesGroupModel(xwAbsoluteLayout); } + + @Override + public void dragging(DraggingModel model) { + FormDesigner designer = model.getDesigner(); + MouseEvent dragEvent = model.getCurrentDragEvent(); + designer.getStateModel().dragging(dragEvent); + } + + @Override + public Dimension getDragSize(XCreator xCreator) { + return xCreator.getSize(); + } } diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRBodyLayoutAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRBodyLayoutAdapter.java index 5a31bab40..f4c045861 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRBodyLayoutAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRBodyLayoutAdapter.java @@ -6,12 +6,13 @@ import com.fr.design.designer.creator.XWParameterLayout; import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; import com.fr.design.utils.ComponentUtils; import com.fr.form.ui.PaddingMargin; -import com.fr.form.ui.container.WBorderLayout; import com.fr.form.ui.container.cardlayout.WCardMainBorderLayout; import com.fr.general.ComparatorUtils; -import java.awt.*; -import java.util.*; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Rectangle; +import java.util.ArrayList; /** * 这个类用作fit和absolute的父类,存放公共的方法 @@ -1182,5 +1183,4 @@ public class FRBodyLayoutAdapter extends AbstractLayoutAdapter { this.isCalculateChildPos = false; return childPosition; } - } diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java index 9871d1b32..3814dc600 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/adapters/layout/FRFitLayoutAdapter.java @@ -8,6 +8,7 @@ import com.fr.design.beans.GroupModel; import com.fr.design.designer.beans.ConstraintsGroupModel; import com.fr.design.designer.beans.HoverPainter; import com.fr.design.designer.beans.LayoutAdapter; +import com.fr.design.designer.beans.models.DraggingModel; import com.fr.design.designer.beans.models.SelectionModel; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XCreatorUtils; @@ -22,6 +23,8 @@ import com.fr.design.designer.properties.FRFitLayoutConstraints; import com.fr.design.designer.properties.FRFitLayoutPropertiesGroupModel; import com.fr.design.designer.treeview.XCreatorTreeCellRender; import com.fr.design.fun.FormWidgetOptionProvider; +import com.fr.design.mainframe.FormCreatorDropTarget; +import com.fr.design.mainframe.FormDesigner; import com.fr.design.utils.ComponentUtils; import com.fr.form.ui.LayoutBorderStyle; import com.fr.form.ui.container.WAbsoluteLayout; @@ -34,6 +37,7 @@ import com.fr.general.act.BorderPacker; import java.awt.Component; import java.awt.Dimension; import java.awt.Rectangle; +import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -1244,4 +1248,26 @@ public class FRFitLayoutAdapter extends FRBodyLayoutAdapter { public void dragOver(XCreator xCreator, SelectionModel selectionModel,int x, int y) { frLayoutState.dragOver(xCreator, selectionModel,x,y); } + + @Override + public void dragging(DraggingModel model) { + FormDesigner designer = model.getDesigner(); + MouseEvent lastPressEvent = model.getStartDragEvent(); + MouseEvent dragEvent = model.getCurrentDragEvent(); + XCreator creator = model.getCreator(); + if ((lastPressEvent == null) || (creator == null)) { + return; + } + + if (dragEvent.getPoint().distance(lastPressEvent.getPoint()) > 5) { + if (creator.isSupportDrag()) { + designer.bindTransferHandler(lastPressEvent); + designer.fireParentLayoutDragStart(creator); + designer.setDropTarget(new FormCreatorDropTarget(designer, creator)); + // 触发状态添加模式事件 + designer.repaint(); + } + dragEvent.consume(); + } + } } diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/events/AddingWidgetListener.java b/designer-form/src/main/java/com/fr/design/designer/beans/events/AddingWidgetListener.java new file mode 100644 index 000000000..04d6cd72c --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/designer/beans/events/AddingWidgetListener.java @@ -0,0 +1,9 @@ +package com.fr.design.designer.beans.events; + +import java.util.EventListener; + +public interface AddingWidgetListener extends EventListener { + void beforeAdded(); + + void afterAdded(boolean addResult); +} diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/events/AddingWidgetListenerTable.java b/designer-form/src/main/java/com/fr/design/designer/beans/events/AddingWidgetListenerTable.java new file mode 100644 index 000000000..4825e8888 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/designer/beans/events/AddingWidgetListenerTable.java @@ -0,0 +1,54 @@ +package com.fr.design.designer.beans.events; + +import com.fr.general.ComparatorUtils; + +import javax.swing.SwingUtilities; +import java.util.ArrayList; +import java.util.List; + +public class AddingWidgetListenerTable { + protected List listeners = new ArrayList<>(); + + public AddingWidgetListenerTable() { + + } + + public void addListener(AddingWidgetListener listener) { + if (listener == null) { + return; + } + for (int i = 0; i < listeners.size(); i++) { + if (ComparatorUtils.equals(listener, listeners.get(i))) { + listeners.set(i, listener); + return; + } + } + listeners.add(listener); + } + + public void beforeAdded() { + for (final AddingWidgetListener listener : listeners) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + listener.beforeAdded(); + } + }); + } + } + + public void afterAdded(boolean addResult) { + for (final AddingWidgetListener listener : listeners) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + listener.afterAdded(addResult); + } + }); + } + } + + public void clearListeners() { + listeners.clear(); + } +} diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/models/AddingModel.java b/designer-form/src/main/java/com/fr/design/designer/beans/models/AddingModel.java index ba0cf5dd0..c47188d4e 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/models/AddingModel.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/models/AddingModel.java @@ -1,17 +1,6 @@ package com.fr.design.designer.beans.models; -import com.fr.design.designer.beans.AdapterBus; -import com.fr.design.designer.beans.ComponentAdapter; -import com.fr.design.designer.beans.adapters.component.CompositeComponentAdapter; 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.XWParameterLayout; -import com.fr.design.mainframe.FormDesigner; -import com.fr.design.utils.ComponentUtils; -import com.fr.general.ComparatorUtils; - -import java.awt.Rectangle; /** * 添加状态下的model @@ -20,128 +9,16 @@ public class AddingModel { // 当前要添加的组件 private XCreator creator; - // 记录当前鼠标的位置信息 - private int currentX; - private int currentY; - private boolean added; private boolean addedIllegal = false; // 有时候是添加完成了,但是添加会造成某些控件size不合法,例如tab - public AddingModel(FormDesigner designer, XCreator xCreator) { - this.creator = xCreator; - instantiateCreator(designer); - // 初始的时候隐藏该组件的图标 - currentY = -this.creator.getWidth(); - currentX = -this.creator.getHeight(); - } - - /** - * 待说明 - * - * @param designer 设计器 - */ - public void instantiateCreator(FormDesigner designer) { - - ModelUtil.renameWidgetName(designer.getTarget(), creator); - ComponentAdapter adapter = new CompositeComponentAdapter(designer, creator); - adapter.initialize(); - creator.addNotify(); - creator.putClientProperty(AdapterBus.CLIENT_PROPERTIES, adapter); - } - - public AddingModel(XCreator xCreator, int x, int y) { + public AddingModel(XCreator xCreator) { this.creator = xCreator; - this.creator.backupCurrentSize(); - this.creator.backupParent(); - currentX = x - (xCreator.initEditorSize().width / 2); - currentY = y - (xCreator.initEditorSize().height / 2); - } - - /** - * 隐藏当前组件的图标 - */ - public void reset() { - currentX = -this.creator.getWidth(); - currentY = -this.creator.getHeight(); - } - - public String getXCreatorName(FormDesigner designer, XCreator x) { - String def = x.createDefaultName(); - if (x.acceptType(XWParameterLayout.class)) { - return def; - } - int i = 0; - while (designer.getTarget().isNameExist(def + i)) { - i++; - } - return def + i; - } - - - public int getCurrentX() { - return currentX; - } - - public int getCurrentY() { - return currentY; - } - - - /** - * 移动组件图标到鼠标事件发生的位置 - * - * @param x 坐标 - * @param y 坐标 - */ - public void moveTo(int x, int y) { - currentX = x - (this.creator.initEditorSize().width / 2); - currentY = y - (this.creator.initEditorSize().height / 2); } public XCreator getXCreator() { return this.creator; } - public boolean need2paint(){ - return currentX + this.creator.getWidth() > 0 && currentY + this.creator.getHeight() > 0; - } - - /** - * 当前组件是否已经添加到某个容器中 - * - * @return 是返回true - */ - public boolean isCreatorAdded() { - return added; - } - - /** - * 加入容器 - * - * @param designer 设计器 - * @param container 容器 - * @param x 坐标 - * @param y 坐标 - * @return 成功返回true - */ - public boolean add2Container(FormDesigner designer, XLayoutContainer container, int x, int y) { - //考虑不同布局嵌套的情况,获取顶层容器 - XLayoutContainer xLayoutContainer = XCreatorUtils.getTopEditableContainer(container); - if (xLayoutContainer != null) { - container = xLayoutContainer; - } - Rectangle rect = ComponentUtils.getRelativeBounds(container); - if (!ComparatorUtils.equals(container.getOuterLayout(), container.getBackupParent())) { - added = container.getLayoutAdapter().addBean(creator, - x + designer.getHorizontalScaleValue(), - y + designer.getVerticalScaleValue() ); - return added; - } - added = container.getLayoutAdapter().addBean(creator, - x + designer.getHorizontalScaleValue() - rect.x, - y + designer.getVerticalScaleValue() - rect.y); - return added; - } - public boolean isAddedIllegal() { return addedIllegal; } diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/models/DraggingModel.java b/designer-form/src/main/java/com/fr/design/designer/beans/models/DraggingModel.java new file mode 100644 index 000000000..6308ff70b --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/designer/beans/models/DraggingModel.java @@ -0,0 +1,98 @@ +package com.fr.design.designer.beans.models; + +import com.fr.design.designer.beans.LayoutAdapter; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.mainframe.FormDesigner; + +import java.awt.event.MouseEvent; + +public class DraggingModel { + private FormDesigner designer; + private XCreator creator; + private MouseEvent startDragEvent; + private MouseEvent currentDragEvent; + private int creatorLeftTopX = -999; // 隐藏 + private int creatorLeftTopY = -999; // 隐藏 + private boolean dragNewWidget; // 是否正在拖拽一个新的组件下来 + + public DraggingModel() { + + } + + public DraggingModel designer(FormDesigner designer) { + this.designer = designer; + return this; + } + + public DraggingModel startDragEvent(MouseEvent startDragEvent) { + this.startDragEvent = startDragEvent; + return this; + } + + public DraggingModel currentDragEvent(MouseEvent dragEvent) { + this.currentDragEvent = dragEvent; + return this; + } + + public DraggingModel creator(XCreator creator) { + this.creator = creator; + return this; + } + + public DraggingModel dragNewWidget(boolean dragNewWidget) { + this.dragNewWidget = dragNewWidget; + return this; + } + + public FormDesigner getDesigner() { + return designer; + } + + public MouseEvent getStartDragEvent() { + return startDragEvent; + } + + public MouseEvent getCurrentDragEvent() { + return currentDragEvent; + } + + public XCreator getCreator() { + return creator; + } + + /** + * 获取被拖拽组件当前随着鼠标移动时应当所在的左上角横坐标 + * + * @return + */ + public int getCreatorLeftTopX() { + return creatorLeftTopX; + } + + /** + * 获取被拖拽组件当前随着鼠标移动时应当所在的左上角纵坐标 + * + * @return + */ + public int getCreatorLeftTopY() { + return creatorLeftTopY; + } + + public boolean isDragNewWidget() { + return dragNewWidget; + } + + public void moveTo(int x, int y) { + XLayoutContainer container = designer.getDraggingHotspotLayout(); + LayoutAdapter adapter = container.getLayoutAdapter(); + + creatorLeftTopX = x - adapter.getDragSize(creator).width / 2; + creatorLeftTopY = y - adapter.getDragSize(creator).height / 2; + } + + public void reset() { + creatorLeftTopX = -creator.getWidth(); + creatorLeftTopY = -creator.getHeight(); + } +} diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/models/StateModel.java b/designer-form/src/main/java/com/fr/design/designer/beans/models/StateModel.java index 3b676921b..390c45825 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/models/StateModel.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/models/StateModel.java @@ -36,7 +36,7 @@ public class StateModel { private SelectionModel selectionModel; // 当前鼠标进入拖拽区域的位置类型 - private Direction driection; + private Direction direction; // 当前拖拽的起始位置 private int currentX; @@ -74,7 +74,7 @@ public class StateModel { * @return direction方向 */ public Direction getDirection() { - return driection; + return direction; } /** @@ -96,7 +96,7 @@ public class StateModel { * @return 非outer且选中为空 */ public boolean dragable() { - return ((driection != Location.outer) && !selecting); + return ((direction != Location.outer) && !selecting); } /** @@ -108,7 +108,7 @@ public class StateModel { addable = false; designer.setPainter(null); - if (driection != Location.inner) { + if (direction != Location.inner) { return; } @@ -283,7 +283,7 @@ public class StateModel { */ public void startResizing(MouseEvent e) { if (!selectionModel.getSelection().isEmpty()) { - driection.backupBounds(designer); + direction.backupBounds(designer); } currentX = getMouseXY(e).x; currentY = getMouseXY(e).y; @@ -409,7 +409,7 @@ public class StateModel { * 重置 */ public void reset() { - driection = Location.outer; + direction = Location.outer; aspectRatioLocked = false; dragging = false; selecting = false; @@ -429,9 +429,9 @@ public class StateModel { * @param dir 拉伸方向 */ public void setDirection(Direction dir) { - if (driection != dir) { - this.driection = dir; - driection.updateCursor(designer); + if (direction != dir) { + this.direction = dir; + direction.updateCursor(designer); } } @@ -495,7 +495,7 @@ public class StateModel { FormSelection selection = this.selectionModel.getSelection(); this.aspectRatioLocked = selection.isCreatorAspectRatioLockedInAbsLayout(designer) || (this.selectionModel.getSelection().isCreatorInAbsLayout(designer) && e.isShiftDown()); - driection.drag(getMouseXY(e).x - currentX, getMouseXY(e).y - currentY, designer); + direction.drag(getMouseXY(e).x - currentX, getMouseXY(e).y - currentY, designer); this.dragging = true; } @@ -552,4 +552,15 @@ public class StateModel { + designer.getArea().getVerticalValue()); } + public boolean isDraggingSize() { + return direction == Location.left + || direction == Location.left_top + || direction == Location.left_bottom + || direction == Location.right + || direction == Location.right_top + || direction == Location.right_bottom + || direction == Location.top + || direction == Location.bottom; + } + } \ No newline at end of file diff --git a/designer-form/src/main/java/com/fr/design/designer/creator/XLayoutContainer.java b/designer-form/src/main/java/com/fr/design/designer/creator/XLayoutContainer.java index 3d0b24847..83a4c01b0 100644 --- a/designer-form/src/main/java/com/fr/design/designer/creator/XLayoutContainer.java +++ b/designer-form/src/main/java/com/fr/design/designer/creator/XLayoutContainer.java @@ -13,9 +13,11 @@ import com.fr.design.mainframe.FormDesigner; import com.fr.design.mainframe.widget.editors.PaddingMarginEditor; import com.fr.design.mainframe.widget.editors.WLayoutBorderStyleEditor; import com.fr.design.parameter.ParameterBridge; +import com.fr.design.utils.ComponentUtils; import com.fr.form.ui.Widget; import com.fr.form.ui.container.WLayout; import com.fr.general.Background; +import com.fr.general.ComparatorUtils; import com.fr.log.FineLoggerFactory; import com.fr.stable.ArrayUtils; import com.fr.stable.core.PropertyChangeAdapter; @@ -24,6 +26,7 @@ import javax.swing.JComponent; import java.awt.Component; import java.awt.Dimension; import java.awt.LayoutManager; +import java.awt.Rectangle; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; import java.beans.IntrospectionException; @@ -609,4 +612,15 @@ public abstract class XLayoutContainer extends XBorderStyleWidgetCreator impleme public boolean isComponent() { return true; } + + public boolean addWidgetToContainer(XCreator creator, int x, int y) { + //考虑不同布局嵌套的情况,获取顶层容器 + XLayoutContainer xLayoutContainer = XCreatorUtils.getTopEditableContainer(this); + XLayoutContainer container = xLayoutContainer != null ? xLayoutContainer : this; + Rectangle rect = ComponentUtils.getRelativeBounds(container); + if (!ComparatorUtils.equals(container.getOuterLayout(), container.getBackupParent())) { + return container.getLayoutAdapter().addBean(creator, x, y); + } + return container.getLayoutAdapter().addBean(creator, x - rect.x, y - rect.y); + } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/DesignerTransferHandler.java b/designer-form/src/main/java/com/fr/design/mainframe/DesignerTransferHandler.java deleted file mode 100644 index e5b11dd9a..000000000 --- a/designer-form/src/main/java/com/fr/design/mainframe/DesignerTransferHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.fr.design.mainframe; - -import com.fr.design.designer.beans.models.AddingModel; -import com.fr.design.file.HistoryTemplateListPane; - -import javax.swing.JComponent; -import javax.swing.TransferHandler; -import java.awt.datatransfer.Transferable; - -public class DesignerTransferHandler extends TransferHandler { - - private FormDesigner designer; - private AddingModel addingModel; - - public DesignerTransferHandler(FormDesigner designer, AddingModel addingModel) { - super("rootComponent"); - this.designer = designer; - this.addingModel = addingModel; - } - - protected void exportDone(JComponent source, Transferable data, int action) { - if (!addingModel.isCreatorAdded()) { - undoWhenAddingFailed(); - } - } - - private void undoWhenAddingFailed() { - JTemplate jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); - if (jt != null) { - jt.undoToCurrent(); - } - } -} \ No newline at end of file diff --git a/designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java b/designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java index b0463a685..f48b60320 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/EditingMouseListener.java @@ -1,6 +1,5 @@ package com.fr.design.mainframe; -import com.fr.base.BaseUtils; import com.fr.base.vcs.DesignerMode; import com.fr.common.inputevent.InputEventBaseOnOS; import com.fr.design.designer.beans.AdapterBus; @@ -25,25 +24,18 @@ import com.fr.design.designer.creator.cardlayout.XCardAddButton; import com.fr.design.designer.creator.cardlayout.XCardSwitchButton; import com.fr.design.designer.creator.cardlayout.XWCardLayout; import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; -import com.fr.design.form.util.XCreatorConstants; -import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.imenu.UIPopupMenu; import com.fr.design.gui.xpane.ToolTipEditor; -import com.fr.design.icon.IconPathConstants; import com.fr.design.utils.ComponentUtils; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.design.utils.gui.LayoutUtils; import com.fr.general.ComparatorUtils; import com.fr.stable.ArrayUtils; -import com.fr.stable.Constants; -import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JPopupMenu; -import javax.swing.JWindow; import javax.swing.SwingUtilities; import javax.swing.event.MouseInputAdapter; -import java.awt.Color; import java.awt.Container; import java.awt.Cursor; import java.awt.Insets; @@ -95,9 +87,6 @@ public class EditingMouseListener extends MouseInputAdapter { private DesignerEditor currentEditor; private XCreator currentXCreator; - //备份开始拖动的位置和大小 - private Rectangle dragBackupBounds; - private int pressX; private int pressY; @@ -121,40 +110,12 @@ public class EditingMouseListener extends MouseInputAdapter { private XElementCase xElementCase; private XChartEditor xChartEditor; - private JWindow promptWindow = new JWindow(); - public EditingMouseListener(FormDesigner designer) { this.designer = designer; stateModel = designer.getStateModel(); selectionModel = designer.getSelectionModel(); - UIButton promptButton = new UIButton(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Forbid_Drag_Into_Adapt_Pane"), BaseUtils.readIcon(IconPathConstants.FORBID_ICON_PATH)); - this.promptWindow.add(promptButton); } - private void promptUser(int x, int y, XLayoutContainer container) { - if (!selectionModel.getSelection().getSelectedCreator().canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class)) { - 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 = (int) designer.getArea().getLocationOnScreen().getX(); - int screenY = (int) designer.getArea().getLocationOnScreen().getY(); - this.promptWindow.setSize(promptWindow.getPreferredSize()); - this.promptWindow.setPreferredSize(promptWindow.getPreferredSize()); - promptWindow.setLocation(screenX + x + GAP, screenY + y + GAP); - promptWindow.setVisible(true); - } - - private void cancelPromptWidgetForbidEnter() { - designer.getRootComponent().setBorder(BorderFactory.createLineBorder(XCreatorConstants.LAYOUT_SEP_COLOR, Constants.LINE_THIN)); - promptWindow.setVisible(false); - } - - /** * 按下 * @@ -181,18 +142,14 @@ public class EditingMouseListener extends MouseInputAdapter { } if (dir == Location.outer) { - if (designer.isDrawLineMode()) { - designer.updateDrawLineMode(e); + if (selectionModel.hasSelectionComponent() + && selectionModel.getSelection().getRelativeBounds().contains( + designer.getHorizontalScaleValue() + e.getX(), + designer.getVerticalScaleValue() + e.getY())) { + lastPressEvent = e; + lastXCreator = selectionModel.getSelection().getSelectedCreator(); } else { - if (selectionModel.hasSelectionComponent() - && selectionModel.getSelection().getRelativeBounds().contains( - designer.getHorizontalScaleValue() + e.getX(), - designer.getVerticalScaleValue() + e.getY())) { - lastPressEvent = e; - lastXCreator = selectionModel.getSelection().getSelectedCreator(); - } else { - stateModel.startSelecting(e); - } + stateModel.startSelecting(e); } } else { stateModel.startResizing(e); @@ -258,13 +215,6 @@ public class EditingMouseListener extends MouseInputAdapter { private void mouseDraggingRelease(MouseEvent e) { // 当前鼠标所在的组件 XCreator hoveredComponent = designer.getComponentAt(e.getX(), e.getY()); - if (designer.isWidgetsIntersect() && dragBackupBounds != null && hoveredComponent != null) { - XCreator selectionXCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); - if (selectionXCreator != null) { - selectionXCreator.setBounds(dragBackupBounds.x, dragBackupBounds.y, dragBackupBounds.width, dragBackupBounds.height); - } - } - dragBackupBounds = null; // 拉伸时鼠标拖动过快,导致所在组件获取会为空 if (hoveredComponent == null && e.getY() < 0) { // bug63538 @@ -285,7 +235,6 @@ public class EditingMouseListener extends MouseInputAdapter { selectionModel.deleteSelection(); designer.setPainter(null); } - cancelPromptWidgetForbidEnter(); } } @@ -499,61 +448,53 @@ public class EditingMouseListener extends MouseInputAdapter { if (DesignerMode.isAuthorityEditing()) { return; } - boolean shiftSelecting = e.isShiftDown(); - boolean ctrlSelecting = InputEventBaseOnOS.isControlDown(e); - int currentCursorType = this.designer.getCursor().getType(); - boolean shiftResizing = e.isShiftDown() && ( Cursor.SW_RESIZE_CURSOR <= currentCursorType && currentCursorType <= Cursor.E_RESIZE_CURSOR); - if ((shiftSelecting || ctrlSelecting) && !shiftResizing && !stateModel.isSelecting()) { + if (SwingUtilities.isRightMouseButton(e)) { + return; + } + + if (isMultiKeySelectingDrag(e)) { stateModel.startSelecting(e); } - // 如果当前是左键拖拽状态,拖拽组件 - if (stateModel.dragable()) { - if (SwingUtilities.isRightMouseButton(e)) { - return; - } else { - stateModel.dragging(e); - // 获取e所在的焦点组件 - XCreator hotspot = designer.getComponentAt(e.getX(), e.getY()); - if (dragBackupBounds == null) { - XCreator selectingXCreator = designer.getSelectionModel().getSelection().getSelectedCreator(); - if (selectingXCreator != null) { - dragBackupBounds = new Rectangle(selectingXCreator.getX(), selectingXCreator.getY(), selectingXCreator.getWidth(), selectingXCreator.getHeight()); - } - } - // 拉伸时鼠标拖动过快,导致所在组件获取会为空 - if (hotspot == null) { - return; - } - // 获取焦点组件所在的焦点容器 - XLayoutContainer container = XCreatorUtils.getHotspotContainer(hotspot); - //提示组件是否可以拖入 - promptUser(e.getX(), e.getY(), container); - } - } else if (designer.isDrawLineMode()) { - if (stateModel.prepareForDrawLining()) { - stateModel.drawLine(e); - } - } else if (stateModel.isSelecting() && (selectionModel.getHotspotBounds() != null)) { - // 如果是拖拽选择区域状态,则更新选择区域 + + if (isSelectionDrag()) { stateModel.changeSelection(e); - } else { - if ((lastPressEvent == null) || (lastXCreator == null)) { - return; - } - if (e.getPoint().distance(lastPressEvent.getPoint()) > minDragSize) { - //参数面板和自适应布局不支持拖拽 - if (lastXCreator.isSupportDrag()) { - designer.startDraggingComponent(lastXCreator, lastPressEvent, e.getX(), e.getY()); - } - e.consume(); - lastPressEvent = null; - } + return; + } + + // 调整大小这边单独提出来,不跟后面拖组件混在一起,实在不好管理 + if (stateModel.isDraggingSize()) { + stateModel.dragging(e); + return; } + + designer.startDraggingFormWidget(lastXCreator, lastPressEvent, e); e.translatePoint(oldX - e.getX(), oldY - e.getY()); designer.repaint(); } + /** + * 当前拖拽是否是正在shift或者control拖拽一个选择框 + * @param e + * @return + */ + private boolean isMultiKeySelectingDrag(MouseEvent e) { + boolean shiftSelecting = e.isShiftDown(); + boolean ctrlSelecting = InputEventBaseOnOS.isControlDown(e); + int currentCursorType = this.designer.getCursor().getType(); + boolean shiftResizing = e.isShiftDown() && ( Cursor.SW_RESIZE_CURSOR <= currentCursorType && currentCursorType <= Cursor.E_RESIZE_CURSOR); + return (shiftSelecting || ctrlSelecting) && !shiftResizing && !stateModel.isSelecting(); + } + + /** + * 是否正在拖拽选择框 + * + * @return + */ + private boolean isSelectionDrag() { + return stateModel.isSelecting() && selectionModel.getHotspotBounds() != null; + } + //当前编辑的组件是在布局中,鼠标点击布局外部,需要一次性将布局及其父布局都置为不可编辑 private void setTopLayoutUnEditable(XLayoutContainer clickedTopLayout, XLayoutContainer clickingTopLayout) { //双击的前后点击click为相同对象,过滤掉 @@ -718,7 +659,6 @@ public class EditingMouseListener extends MouseInputAdapter { if (designer.getCursor().getType() != Cursor.DEFAULT_CURSOR && !(e.isShiftDown() || InputEventBaseOnOS.isControlDown(e))) { designer.setCursor(Cursor.getDefaultCursor()); } - cancelPromptWidgetForbidEnter(); e.translatePoint(oldX - e.getX(), oldY - e.getY()); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormCreatorDropTarget.java b/designer-form/src/main/java/com/fr/design/mainframe/FormCreatorDropTarget.java index 102c5c863..aa58d713e 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormCreatorDropTarget.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormCreatorDropTarget.java @@ -1,40 +1,24 @@ 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.beans.events.AddingWidgetListener; +import com.fr.design.designer.beans.models.DraggingModel; 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.file.HistoryTemplateListPane; 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; @@ -45,15 +29,10 @@ 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; /** * 添加模式下鼠标事件处理器。 @@ -65,121 +44,56 @@ public class FormCreatorDropTarget extends DropTarget { * 当前鼠标的设计组件 */ private Component current; - /** - * 当前添加模式对应的model - */ - private AddingModel addingModel; private static final int GAP = 30; private TabDragInner tabDragInner; - + private XCreator creator; private JWindow promptWindow = new JWindow(); private UIButton promptButton = new UIButton("", BaseUtils.readIcon(IconPathConstants.FORBID_ICON_PATH)); - public FormCreatorDropTarget(FormDesigner designer) { + public FormCreatorDropTarget(FormDesigner designer, XCreator creator) { this.designer = designer; - this.addingModel = designer.getAddingModel(); + this.creator = creator; this.promptWindow.add(promptButton); this.tabDragInner = new TabDragInner(designer); + initAddingListener(); } - public void adding(int x, int y) { - // 当前鼠标所在的组件 - XCreator hoveredComponent = designer.getComponentAt(x, y); - // 获取该组件所在的焦点容器 - XLayoutContainer container = XCreatorUtils.getHotspotContainer(hoveredComponent); - boolean success = false; - if (container != null) { - // 如果是容器,则调用其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) { - tabDragInner.tryDragIn(); - success = model.add2Container(designer, container, x, y); + private void initAddingListener() { + designer.getAddingWidgetListeners().addListener(new AddingWidgetListener() { + @Override + public void beforeAdded() { + tabDragInner.setTabEditable(); } - cancelPromptWidgetForbidEnter(); - } - if (success) { - tabDragInner.reset(); - // 如果添加成功,则触发相应事件 - 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 tdNameMap = Collections.emptyMap(); - if (sharableEditor != null && bindInfo != null) { - tdNameMap = TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()).addTableData(bindInfo.getName(), sharableEditor.getTableDataSource(), true); - //合并数据集之后,可能会有数据集名称变化,做一下联动 - //共享的组件拿的时候都是克隆的,这边改拖拽中克隆的对象而非新克隆对象,上面这个新克隆的对象只是为了拿数据集 - Map map = new HashMap<>(); - for (Map.Entry entry : tdNameMap.entrySet()) { - designer.getTarget().renameTableData(widget, entry.getKey(), entry.getValue()); - map.put(entry.getKey(), entry.getValue()); - } - if (!map.isEmpty()) { - DesignTableDataManager.fireDSChanged(map); - } + @Override + public void afterAdded(boolean addResult) { + if (addResult) { + tabDragInner.reset(); + } else { + undoWhenAddingFailed(); } - 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.updateDraggingPosition(x, y); designer.repaint(); } private void exiting() { cancelPromptWidgetForbidEnter(); // 隐藏组件图标 - addingModel.reset(); + designer.resetDraggingPosition(); designer.setPainter(null); designer.repaint(); } private void hovering(int x, int y) { // 当前位置移植鼠标e所在的位置 - addingModel.moveTo(x, y); + designer.updateDraggingPosition(x, y); // 获取e所在的焦点组件 XCreator hotspot = designer.getComponentAt(x, y); // 获取焦点组件所在的焦点容器 @@ -232,15 +146,15 @@ public class FormCreatorDropTarget extends DropTarget { rect.y -= designer.getArea().getVerticalValue(); painter.setRenderingBounds(rect); painter.setHotspot(new Point(x, y)); - painter.setCreator(addingModel.getXCreator()); + painter.setCreator(creator); } } private void promptUser(int x, int y, XLayoutContainer container) { - if (!addingModel.getXCreator().canEnterIntoParaPane() && container.acceptType(XWParameterLayout.class)) { + if (!creator.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)) { + } else if (!creator.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 { @@ -286,8 +200,15 @@ public class FormCreatorDropTarget extends DropTarget { int x = designer.getRelativeX(loc.x); int y = designer.getRelativeY(loc.y); hovering(x, y); - tabDragInner.canDragIn(designer.getComponentAt(x, y), x, y); - designer.draggingComponent(x, y); + tabDragInner.setTabDragInAble(designer.getComponentAt(x, y), x, y); + + XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(creator); + if (parent!= null && parent.getLayoutAdapter()!=null){ + parent.getLayoutAdapter().dragOver(creator, designer.getSelectionModel(), x, y); + } + + // 触发状态添加模式事件 + designer.repaint(); } /** @@ -317,12 +238,11 @@ public class FormCreatorDropTarget extends DropTarget { */ @Override public synchronized void drop(DropTargetDropEvent dtde) { - try { dropXCreator(dtde); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); - if (addingModel.getXCreator().isShared()) { + if (creator.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"), @@ -332,40 +252,46 @@ public class FormCreatorDropTarget extends DropTarget { } dtde.rejectDrop(); } + designer.stopDragging(); + designer.clearDropTarget(); } 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(); - } + DraggingModel model = designer.getDraggingModel(); - private void dealChartBuryingPoint(Widget widget) { - List 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); + if (model != null) { + cancelPromptWidgetForbidEnter(); + Point loc = dtde.getLocation(); + int x = designer.getRelativeX(loc.x); + int y = designer.getRelativeY(loc.y); + if (model.isDragNewWidget()) { + designer.addNewWidget(creator, x, y); + } else { + designer.changeWidgetPlace(creator, x, y); } + // 放到事件末尾执行 + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + // 拖拽释放后标记未选中 + for (XCreator xCreator : designer.getSelectionModel().getSelection().getSelectedCreators()) { + xCreator.setSelected(true); + } + } + }); + //针对在表单中拖入一个控件直接ctrl+s无反应 + designer.requestFocus(); } } public TabDragInner getTabDragInner() { return this.tabDragInner; } + + private void undoWhenAddingFailed() { + JTemplate jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); + if (jt != null) { + jt.undoToCurrent(); + } + } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java b/designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java index adc59581a..ef1177ece 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormDesigner.java @@ -1,14 +1,21 @@ package com.fr.design.mainframe; import com.fr.base.Parameter; +import com.fr.base.chart.BaseChartCollection; import com.fr.base.vcs.DesignerMode; +import com.fr.chart.chartattr.ChartCollection; +import com.fr.chartx.attr.ChartProvider; import com.fr.design.DesignModelAdapter; import com.fr.design.DesignState; import com.fr.design.ExtraDesignClassManager; import com.fr.design.actions.UpdateAction; import com.fr.design.base.mode.DesignModeContext; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.datapane.TableDataTreePane; import com.fr.design.designer.TargetComponent; import com.fr.design.designer.beans.AdapterBus; +import com.fr.design.designer.beans.ComponentAdapter; +import com.fr.design.designer.beans.LayoutAdapter; import com.fr.design.designer.beans.Painter; import com.fr.design.designer.beans.actions.CopyAction; import com.fr.design.designer.beans.actions.CutAction; @@ -18,9 +25,11 @@ import com.fr.design.designer.beans.actions.MoveToBottomAction; import com.fr.design.designer.beans.actions.MoveToTopAction; import com.fr.design.designer.beans.actions.MoveUpAction; import com.fr.design.designer.beans.actions.PasteAction; +import com.fr.design.designer.beans.adapters.component.CompositeComponentAdapter; import com.fr.design.designer.beans.adapters.layout.DefaultDesignerBaseOperate; -import com.fr.design.designer.beans.adapters.layout.FRParameterLayoutAdapter; import com.fr.design.designer.beans.adapters.layout.DesignerBaseOperate; +import com.fr.design.designer.beans.adapters.layout.FRParameterLayoutAdapter; +import com.fr.design.designer.beans.events.AddingWidgetListenerTable; import com.fr.design.designer.beans.events.CreatorEventListenerTable; import com.fr.design.designer.beans.events.DesignerEditListener; import com.fr.design.designer.beans.events.DesignerEvent; @@ -28,6 +37,8 @@ import com.fr.design.designer.beans.location.Direction; import com.fr.design.designer.beans.location.Location; import com.fr.design.designer.beans.location.RootResizeDirection; import com.fr.design.designer.beans.models.AddingModel; +import com.fr.design.designer.beans.models.DraggingModel; +import com.fr.design.designer.beans.models.ModelUtil; import com.fr.design.designer.beans.models.SelectionModel; import com.fr.design.designer.beans.models.StateModel; import com.fr.design.designer.creator.XChartEditor; @@ -37,6 +48,7 @@ import com.fr.design.designer.creator.XLayoutContainer; import com.fr.design.designer.creator.XWAbsoluteBodyLayout; import com.fr.design.designer.creator.XWAbsoluteLayout; import com.fr.design.designer.creator.XWBorderLayout; +import com.fr.design.designer.creator.XWFitLayout; import com.fr.design.designer.creator.XWParameterLayout; import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; import com.fr.design.designer.properties.FormWidgetAuthorityEditPane; @@ -45,19 +57,27 @@ import com.fr.design.event.DesignerOpenedListener; import com.fr.design.file.HistoryTemplateListPane; import com.fr.design.form.util.XCreatorConstants; import com.fr.design.fun.RightSelectionHandlerProvider; +import com.fr.design.mainframe.chart.info.ChartInfoCollector; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; import com.fr.design.menu.MenuDef; import com.fr.design.menu.ShortCut; import com.fr.design.menu.ToolBarDef; +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.parameter.ParaDefinitePane; import com.fr.design.parameter.ParameterPropertyPane; import com.fr.design.roleAuthority.RolesAlreadyEditedPane; import com.fr.design.utils.ComponentUtils; import com.fr.design.utils.gui.LayoutUtils; +import com.fr.event.EventDispatcher; import com.fr.form.FormElementCaseContainerProvider; import com.fr.form.FormElementCaseProvider; import com.fr.form.main.Form; import com.fr.form.parameter.FormSubmitButton; +import com.fr.form.share.SharableWidgetProvider; +import com.fr.form.share.ShareLoader; +import com.fr.form.share.editor.SharableEditorProvider; import com.fr.form.ui.EditorHolder; import com.fr.form.ui.PaddingMargin; import com.fr.form.ui.Widget; @@ -91,6 +111,7 @@ import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; +import java.awt.Toolkit; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; @@ -99,7 +120,10 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Set; /** @@ -144,6 +168,7 @@ public class FormDesigner extends TargetComponent
implements TreeSelection private transient StateModel stateModel; // 添加状态下的model,存储添加状态下的临时状态,比如要添加的组件、当前鼠标位置等等 private transient AddingModel addingModel; + private transient DraggingModel draggingModel; // 当前负责额外渲染的painter,主要目的用来渲染添加组件的位置提示,它通常由外部类设置,在 // 设计器渲染时被调用渲染这些位置提示。 private transient Painter painter; @@ -170,6 +195,8 @@ public class FormDesigner extends TargetComponent implements TreeSelection private static final int H_GAP = 105; private static final int SUBMIT_BUTTON_H_LOCATION = 270; + private AddingWidgetListenerTable addingWidgetListeners; + public FormDesigner(Form form) { this(form, null); } @@ -184,6 +211,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection this.setBackground(Color.WHITE); // 初始化 edit = new CreatorEventListenerTable(); + addingWidgetListeners = new AddingWidgetListenerTable(); selectionModel = new SelectionModel(this); stateModel = new StateModel(this); desigerMode = createFormDesignerTargetMode(); @@ -201,6 +229,7 @@ public class FormDesigner extends TargetComponent implements TreeSelection populateParameterPropertyPane(); spacingLineDrawer = new FormSpacingLineDrawer(this); + clearDropTarget(); } @@ -603,6 +632,10 @@ public class FormDesigner extends TargetComponent implements TreeSelection return edit; } + public AddingWidgetListenerTable getAddingWidgetListeners() { + return addingWidgetListeners; + } + /** * 增加监听事件 * @@ -783,6 +816,35 @@ public class FormDesigner extends TargetComponent implements TreeSelection repaint(); } + /** + * 停止拖拽 + */ + public void stopDragging() { + draggingModel = null; + } + + public void clearDropTarget() { + this.setDropTarget(null); + } + + /** + * 更新拖拽model的位置 + */ + public void updateDraggingPosition(int x, int y) { + if (draggingModel != null) { + draggingModel.moveTo(x, y); + } + } + + /** + * 重置拖拽model的位置 + */ + public void resetDraggingPosition() { + if (draggingModel != null) { + draggingModel.reset(); + } + } + /** * 设置其UI类为DesignerUI,负责渲染 */ @@ -1109,8 +1171,8 @@ public class FormDesigner extends TargetComponent implements TreeSelection return addingModel; } - public void setAddingModel(AddingModel addingModel) { - this.addingModel = addingModel; + public DraggingModel getDraggingModel() { + return draggingModel; } public XCreator getComponentAt(MouseEvent e) { @@ -1179,50 +1241,84 @@ public class FormDesigner extends TargetComponent implements TreeSelection } /** - * 拖拽准备 + * 拖入新的组件 * - * @param xCreator 组件 + * @param xCreator + * @param startDragEvent + * @param currentDragEvent */ - public void startDraggingBean(XCreator xCreator) { - // 根据所选择的组件的BeanInfo生成相应的AddingModel - // AddingModel和StateModel不一样,适合当前选择的组件相关的 - addingModel = new AddingModel(this, xCreator); - this.setDropTarget(new FormCreatorDropTarget(this)); - // 触发状态添加模式事件 + public void startDraggingNewWidget(XCreator xCreator, MouseEvent startDragEvent, MouseEvent currentDragEvent) { + if (currentDragEvent == null || this.getDropTarget() != null) { + return; + } + + draggingModel = new DraggingModel() + .designer(this) + .creator(xCreator) + .startDragEvent(startDragEvent) + .currentDragEvent(currentDragEvent) + .dragNewWidget(true); + this.setDropTarget(new FormCreatorDropTarget(this, xCreator)); repaint(); } /** - * 拖拽时相关处理 + * 拖拽表单上的组件 * - * @param xCreator 组件 - * @param lastPressEvent 鼠标事件 - * @param x 坐标x - * @param y 坐标y - */ - public void startDraggingComponent(XCreator xCreator, MouseEvent lastPressEvent, int x, int y) { - // 根据所选择的组件的BeanInfo生成相应的AddingModel - // AddingModel和StateModel不一样,适合当前选择的组件相关的 - this.addingModel = new AddingModel(xCreator, x, y); - TransferHandler handler = new DesignerTransferHandler(this, addingModel); - setTransferHandler(handler); - handler.exportAsDrag(this, lastPressEvent, TransferHandler.COPY); - XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(xCreator); - parent.getLayoutAdapter().dragStart(xCreator, selectionModel); - this.setDropTarget(new FormCreatorDropTarget(this)); - // 触发状态添加模式事件 + * @param xCreator + * @param startDragEvent + * @param currentDragEvent + */ + public void startDraggingFormWidget(XCreator xCreator, MouseEvent startDragEvent, MouseEvent currentDragEvent) { + if (currentDragEvent == null || this.getDropTarget() != null) { + return; + } + draggingModel = new DraggingModel() + .designer(this) + .creator(xCreator) + .startDragEvent(startDragEvent) + .currentDragEvent(currentDragEvent) + .dragNewWidget(false); + XLayoutContainer container = this.getDraggingHotspotLayout(); + LayoutAdapter adapter = container.getLayoutAdapter(); + adapter.dragging(this.getDraggingModel()); repaint(); } - public void draggingComponent(int x, int y){ - XCreator xCreator = this.addingModel.getXCreator(); + /** + * 绑定transferHandler,貌似这边用的还是低级的DND方式绑定的鼠标手势,高级的可参考ToolBarButton那边,"rootComponent"常量是 + * 从原来的DesignerTransferHandler里面直接搬来的,目前意义还不明确 + * + * @param e + */ + public void bindTransferHandler(MouseEvent e) { + TransferHandler handler = new TransferHandler("rootComponent"); + this.setTransferHandler(handler); + handler.exportAsDrag(this, e, TransferHandler.COPY); + } + + /** + * 触发父组件布局的dragStart事件,目前只在非固定布局下有用,用来删除占位块 + * + * @param xCreator + */ + public void fireParentLayoutDragStart(XCreator xCreator) { XLayoutContainer parent = XCreatorUtils.getParentXLayoutContainer(xCreator); - if (parent!= null && parent.getLayoutAdapter()!=null){ - parent.getLayoutAdapter().dragOver(xCreator, selectionModel, x, y); + if (parent != null) { + parent.getLayoutAdapter().dragStart(xCreator, selectionModel); } + } - // 触发状态添加模式事件 - repaint(); + /** + * 获取拖拽当前鼠标所在位置的布局 + * + * @return + */ + public XLayoutContainer getDraggingHotspotLayout() { + DraggingModel model = this.draggingModel; + MouseEvent dragEvent = model.getCurrentDragEvent(); + XCreator hotspot = this.getComponentAt(dragEvent.getX(), dragEvent.getY()); + return XCreatorUtils.getHotspotContainer(hotspot); } /** @@ -1890,4 +1986,131 @@ public class FormDesigner extends TargetComponent implements TreeSelection public FormSpacingLineDrawer getSpacingLineDrawer() { return spacingLineDrawer; } + + private void instantiateCreator(XCreator creator) { + ModelUtil.renameWidgetName(this.getTarget(), creator); + creator.addNotify(); + + ComponentAdapter adapter = new CompositeComponentAdapter(this, creator); + adapter.initialize(); + creator.putClientProperty(AdapterBus.CLIENT_PROPERTIES, adapter); + } + + public void addNewWidget(XCreator creator, int x, int y) { + instantiateCreator(creator); + addWidgetToForm(creator, x, y); + } + + public void changeWidgetPlace(XCreator creator, int x, int y) { + creator.backupCurrentSize(); + creator.backupParent(); + addWidgetToForm(creator, x, y); + } + + private void addWidgetToForm(XCreator creator, int x, int y) { + if(creator == null) { + return; + } + + addingModel = new AddingModel(creator); + // 当前鼠标所在的组件 + XCreator hoveredComponent = this.getComponentAt(x, y); + // 获取该组件所在的焦点容器 + XLayoutContainer container = XCreatorUtils.getHotspotContainer(hoveredComponent); + boolean success = false; + if (container != null) { + // 如果是容器,则调用其acceptComponent接受组件 + boolean chartEnter2Para = !addingModel.getXCreator().canEnterIntoParaPane() && container.acceptType(XWParameterLayout.class); + boolean formSubmit2Adapt = !addingModel.getXCreator().canEnterIntoAdaptPane() && container.acceptType(XWFitLayout.class); + + if (!chartEnter2Para && !formSubmit2Adapt) { + getAddingWidgetListeners().beforeAdded(); + success = container.addWidgetToContainer( + creator, + x + this.getHorizontalScaleValue(), + y + this.getVerticalScaleValue() + ); + } + getAddingWidgetListeners().afterAdded(success); + defaultAfterWidgetAdded(success, container); + } + + // 取消提示 + this.setPainter(null); + // 切换添加状态到普通状态 + this.stopAddingState(); + getAddingWidgetListeners().clearListeners(); + } + + private void dealChartBuryingPoint(Widget widget) { + List 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); + } + } + } + + + + private void defaultAfterWidgetAdded(boolean addResult, XLayoutContainer container) { + if (addResult) { + // 如果添加成功,则触发相应事件 + XCreator xCreator = container.acceptType(XWParameterLayout.class) ? this.getParaComponent() : this.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 tdNameMap = Collections.emptyMap(); + if (sharableEditor != null && bindInfo != null) { + tdNameMap = TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()).addTableData(bindInfo.getName(), sharableEditor.getTableDataSource(), true); + //合并数据集之后,可能会有数据集名称变化,做一下联动 + //共享的组件拿的时候都是克隆的,这边改拖拽中克隆的对象而非新克隆对象,上面这个新克隆的对象只是为了拿数据集 + Map map = new HashMap<>(); + for (Map.Entry entry : tdNameMap.entrySet()) { + this.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)); + } + + this.getSelectionModel().setSelectedCreators( + FormSelectionUtils.rebuildSelection(xCreator, new Widget[]{widget})); + if (!addingModel.isAddedIllegal()) { + this.getEditListenerTable().fireCreatorModified(addingModel.getXCreator(), DesignerEvent.CREATOR_ADDED); + } + } else { + Toolkit.getDefaultToolkit().beep(); + // 拖入失败 取消选中 + XCreator creator = addingModel.getXCreator(); + if (creator != null) { + creator.setSelected(false); + } + } + } } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/FormDesignerUI.java b/designer-form/src/main/java/com/fr/design/mainframe/FormDesignerUI.java index aab1b27b7..1d641dece 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/FormDesignerUI.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/FormDesignerUI.java @@ -6,10 +6,9 @@ import com.fr.base.Utils; import com.fr.base.iofile.attr.WatermarkAttr; import com.fr.base.vcs.DesignerMode; import com.fr.design.constants.UIConstants; -import com.fr.design.designer.beans.AdapterBus; -import com.fr.design.designer.beans.ComponentAdapter; +import com.fr.design.designer.beans.LayoutAdapter; import com.fr.design.designer.beans.location.Direction; -import com.fr.design.designer.beans.models.AddingModel; +import com.fr.design.designer.beans.models.DraggingModel; import com.fr.design.designer.beans.models.SelectionModel; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XLayoutContainer; @@ -117,11 +116,10 @@ public class FormDesignerUI extends ComponentUI { designer.getPainter().paint(g, designer.getArea().getHorizontalValue(), designer.getArea().getVerticalValue() + designer.getParaHeight()); } - AddingModel addingModel = designer.getAddingModel(); - - if ((addingModel != null) && (addingModel.getXCreator() != null)) { + DraggingModel draggingModel = designer.getDraggingModel(); + if (draggingModel != null && draggingModel.getCreator() != null) { // 当前正在添加的组件 - paintAddingBean(g, addingModel); + paintDraggingBean(g); } designer.getSpacingLineDrawer().draw(g); @@ -196,26 +194,24 @@ public class FormDesignerUI extends ComponentUI { } /** - * 渲染当前正在添加的组件,采用Renderer原理 + * 渲染当前正在拖拽的组件,采用Renderer原理 */ - private void paintAddingBean(Graphics g, final AddingModel addingModel) { - if (!addingModel.need2paint()) { - return; - } - XCreator bean = addingModel.getXCreator(); - int x = addingModel.getCurrentX(); - int y = addingModel.getCurrentY() ; - - int width = bean.initEditorSize().width; - int height = bean.initEditorSize().height; + private void paintDraggingBean(Graphics g) { + DraggingModel model = designer.getDraggingModel(); + XCreator bean = model.getCreator(); + int x = model.getCreatorLeftTopX(); + int y = model.getCreatorLeftTopY(); + + XLayoutContainer container = designer.getDraggingHotspotLayout(); + LayoutAdapter adapter = container.getLayoutAdapter(); + int width = adapter.getDragSize(bean).width; + int height = adapter.getDragSize(bean).height; Graphics clipg = g.create(x, y, width, height); ArrayList dbcomponents = new ArrayList(); // 禁止双缓冲行为 ComponentUtils.disableBuffer(bean, dbcomponents); - ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, bean); - // 调用ComponentAdapter的paintComponentMascot方法渲染该组件添加提示 - adapter.paintComponentMascot(clipg); + adapter.paintComponentMascot(clipg, bean); clipg.dispose(); // 恢复双缓冲 ComponentUtils.resetBuffer(dbcomponents); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/TabDragInner.java b/designer-form/src/main/java/com/fr/design/mainframe/TabDragInner.java index 9b524f28e..020b65aa6 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/TabDragInner.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/TabDragInner.java @@ -30,13 +30,13 @@ public class TabDragInner { } /** - * 判断拖入 + * 鼠标拖拽组件,在tab上悬停10s,自动设置tab为可拖入状态(释放鼠标将会直接拖入tab) * * @param creator 当前拖拽的组件下方所在布局最上层的组件 * @param x * @param y */ - public void canDragIn(XCreator creator, int x, int y) { + public void setTabDragInAble(XCreator creator, int x, int y) { XLayoutContainer topLayout = XCreatorUtils.getHotspotContainer(creator).getTopLayout(); boolean dragInAble = false; if (topLayout != null && topLayout.acceptType(XWCardMainBorderLayout.class) && belowXLayoutContainer == null) { @@ -60,7 +60,7 @@ public class TabDragInner { /** * 尝试进入tab编辑 */ - public void tryDragIn() { + public void setTabEditable() { if (belowXLayoutContainer != null && belowXLayoutContainer.isDragInAble()) { belowXLayoutContainer.setEditable(true); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/ToolBarButton.java b/designer-form/src/main/java/com/fr/design/mainframe/ToolBarButton.java index 53b9c5291..6ca5b020f 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/ToolBarButton.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/ToolBarButton.java @@ -2,26 +2,31 @@ package com.fr.design.mainframe; import com.fr.base.vcs.DesignerMode; import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XCreatorUtils; import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.form.util.FormDesignerUtils; -import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.core.WidgetOption; -import com.fr.design.designer.creator.XCreatorUtils; +import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UIForbiddenButtonUI; import com.fr.form.ui.Widget; import com.fr.general.ComparatorUtils; -import java.awt.*; +import javax.swing.plaf.ButtonUI; +import java.awt.Dimension; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; -import java.awt.dnd.*; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; +import java.awt.dnd.DragSourceDragEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.io.IOException; import java.io.Serializable; -import javax.swing.plaf.ButtonUI; /* *august: 控件按钮 @@ -70,7 +75,6 @@ public class ToolBarButton extends UIButton implements MouseListener, MouseMotio } public void mouseReleased(MouseEvent e) { - } @Override @@ -100,7 +104,7 @@ public class ToolBarButton extends UIButton implements MouseListener, MouseMotio } if (creatorSource != null) { XCreator xCreator = XCreatorUtils.createThemedXCreator(creatorSource); - WidgetToolBarPane.getTarget().startDraggingBean(xCreator); + WidgetToolBarPane.getTarget().startDraggingNewWidget(xCreator, lastPressEvent, e); FormDesignerUtils.addWidgetProcessInfo(xCreator.toData()); lastPressEvent = null; this.setBorder(null); diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java index 72eb35d00..8f21bd3f2 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/LocalWidgetBlock.java @@ -16,8 +16,8 @@ import com.fr.design.mainframe.share.group.ui.GroupMoveDialog; import com.fr.design.mainframe.share.ui.actions.SharedComponentPopupAction; import com.fr.design.mainframe.share.ui.actions.SharedComponentPopupMenu; import com.fr.design.mainframe.share.ui.constants.ColorConstants; -import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoUpdater; import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane; +import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoUpdater; import com.fr.design.mainframe.share.ui.local.LocalWidgetSelectPane; import com.fr.design.mainframe.share.ui.local.WidgetSelectedManager; import com.fr.design.mainframe.share.util.ShareComponentUtils; @@ -31,7 +31,6 @@ import com.fr.form.share.record.ShareWidgetInfoManager; import com.fr.form.ui.AbstractBorderStyleWidget; import com.fr.form.ui.Widget; import com.fr.general.ComparatorUtils; -import com.fr.general.FRFont; import com.fr.general.IOUtils; import com.fr.stable.Constants; import org.jetbrains.annotations.NotNull; @@ -61,7 +60,6 @@ import java.awt.event.ActionEvent; import java.awt.event.MouseEvent; import java.awt.font.FontRenderContext; import java.awt.font.LineMetrics; -import java.awt.geom.Dimension2D; import java.awt.image.BufferedImage; import java.util.UUID; @@ -239,7 +237,7 @@ public class LocalWidgetBlock extends PreviewWidgetBlock if (xCreator == null) { return; } - WidgetToolBarPane.getTarget().startDraggingBean(xCreator); + WidgetToolBarPane.getTarget().startDraggingNewWidget(xCreator, lastPressEvent, e); lastPressEvent = null; this.setBorder(null); } diff --git a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java index 38bcd9982..7b0bf5708 100644 --- a/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java +++ b/designer-form/src/main/java/com/fr/design/mainframe/share/ui/block/OnlineWidgetBlock.java @@ -13,21 +13,21 @@ import com.fr.design.login.DesignerLoginHelper; import com.fr.design.login.DesignerLoginSource; import com.fr.design.mainframe.WidgetToolBarPane; import com.fr.design.mainframe.share.collect.ComponentCollector; +import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane; import com.fr.design.mainframe.share.ui.online.AbstractOnlineWidgetSelectPane; import com.fr.design.mainframe.share.ui.online.CarouselStateManger; -import com.fr.form.share.DefaultSharableWidget; -import com.fr.form.share.group.DefaultShareGroup; -import com.fr.design.mainframe.share.ui.local.LocalWidgetRepoPane; import com.fr.design.mainframe.share.ui.online.OnlineWidgetRepoPane; import com.fr.design.mainframe.share.util.DownloadUtils; import com.fr.design.mainframe.share.util.ShareComponentUtils; import com.fr.design.mainframe.share.util.ShareUIUtils; import com.fr.design.ui.util.UIUtil; +import com.fr.form.share.DefaultSharableWidget; +import com.fr.form.share.Group; import com.fr.form.share.SharableWidgetProvider; import com.fr.form.share.bean.OnlineShareWidget; import com.fr.form.share.constants.ShareComponentConstants; +import com.fr.form.share.group.DefaultShareGroup; import com.fr.form.share.group.DefaultShareGroupManager; -import com.fr.form.share.Group; import com.fr.form.share.utils.ShareUtils; import com.fr.form.ui.AbstractBorderStyleWidget; import com.fr.form.ui.Widget; @@ -163,6 +163,11 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock { } } + @Override + public void mouseReleased(MouseEvent e) { + super.mouseReleased(e); + } + @Override public void mouseDragged(MouseEvent e) { if (!getWidget().isCompatibleWithCurrentEnv()) { @@ -200,7 +205,7 @@ public class OnlineWidgetBlock extends AbstractOnlineWidgetBlock { } else { xCreator = ShareComponentUtils.createXCreator(creatorSource, shareId, bindInfo); } - WidgetToolBarPane.getTarget().startDraggingBean(xCreator); + WidgetToolBarPane.getTarget().startDraggingNewWidget(xCreator, lastPressEvent, e); lastPressEvent = null; this.setBorder(null); } diff --git a/designer-form/src/test/java/com/fr/design/designer/beans/models/AddingModelTest.java b/designer-form/src/test/java/com/fr/design/designer/beans/models/AddingModelTest.java deleted file mode 100644 index f7a75b029..000000000 --- a/designer-form/src/test/java/com/fr/design/designer/beans/models/AddingModelTest.java +++ /dev/null @@ -1,210 +0,0 @@ -package com.fr.design.designer.beans.models; - -import com.fr.base.chart.BaseChartCollection; -import com.fr.config.dao.DaoContext; -import com.fr.config.dao.impl.LocalClassHelperDao; -import com.fr.config.dao.impl.LocalEntityDao; -import com.fr.config.dao.impl.LocalXmlEntityDao; -import com.fr.design.designer.creator.CRPropertyDescriptor; -import com.fr.design.designer.creator.XChartEditor; -import com.fr.design.designer.creator.XCreator; -import com.fr.design.designer.creator.XLayoutContainer; -import com.fr.design.designer.creator.XWTitleLayout; -import com.fr.design.designer.creator.cardlayout.XWCardLayout; -import com.fr.design.gui.chart.MiddleChartComponent; -import com.fr.design.mainframe.FormDesigner; -import com.fr.design.module.DesignModuleFactory; -import com.fr.form.main.Form; -import com.fr.form.ui.ChartEditor; -import com.fr.form.ui.Widget; -import com.fr.form.ui.container.WAbsoluteLayout; -import com.fr.form.ui.container.WCardLayout; -import com.fr.form.ui.container.WTitleLayout; -import com.fr.stable.core.PropertyChangeListener; -import org.easymock.EasyMock; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.easymock.PowerMock; -import org.powermock.core.classloader.annotations.PowerMockIgnore; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - -import javax.swing.JComponent; -import java.awt.Dimension; -import java.awt.Rectangle; -import java.beans.IntrospectionException; - -@PrepareForTest({DesignModuleFactory.class}) -@PowerMockIgnore({"com.sun.*", "javax.*", "com.fr.jvm.assist.*"}) -@RunWith(PowerMockRunner.class) -public class AddingModelTest { - - @Before - public void setUp() { - DaoContext.setXmlEntityDao(new LocalXmlEntityDao()); - DaoContext.setClassHelperDao(new LocalClassHelperDao()); - DaoContext.setEntityDao(new LocalEntityDao()); - } - - @After - public void tearDown() { - DaoContext.setXmlEntityDao(null); - DaoContext.setClassHelperDao(null); - DaoContext.setEntityDao(null); - } - - /** - * 默认名字 + i - */ - @Test - public void testInstantiateCreator() throws Exception { - - Dimension dimension = new Dimension(20, 20); - - ChartEditor chartEditor1 = new ChartEditor(); - XCreator xCreator1 = new DemoCreator(chartEditor1, dimension, "test"); - - ChartEditor chartEditor2 = new ChartEditor(); - chartEditor2.setWidgetName("test02"); - XCreator xCreator2 = new DemoCreator(chartEditor2, dimension, "test02"); - xCreator1.add(xCreator2); - - ChartEditor chartEditor3 = new ChartEditor(); - chartEditor3.setWidgetName("test03"); - WAbsoluteLayout.BoundsWidget boundsWidget = new WAbsoluteLayout.BoundsWidget(chartEditor3, new Rectangle(dimension)); - WTitleLayout wTitleLayout03 = new WTitleLayout(); - wTitleLayout03.addWidget(boundsWidget); - //需要和内部的 widget 一样 - wTitleLayout03.setWidgetName("test03"); - XWTitleLayout xCreator3 = new XWTitleLayout(wTitleLayout03, dimension); - xCreator1.add(xCreator3); - - AddingModel addingModel = new AddingModel(xCreator1, 20, 20); - - Form form = EasyMock.mock(Form.class); - EasyMock.expect(form.isNameExist("test0")).andReturn(true).once(); - EasyMock.expect(form.isNameExist("test03")).andReturn(true).once(); - EasyMock.expect(form.isNameExist(EasyMock.anyString())).andReturn(false).anyTimes(); - EasyMock.replay(form); - - FormDesigner mock = EasyMock.mock(FormDesigner.class); - EasyMock.expect(mock.getTarget()).andReturn(form).anyTimes(); - EasyMock.replay(mock); - - addingModel.instantiateCreator(mock); - //没有默认参数, 但已经存在 test - Assert.assertEquals("test1", xCreator1.toData().getWidgetName()); - //直接返回 - Assert.assertEquals("test020", xCreator2.toData().getWidgetName()); - //已经存在,后接0 - Assert.assertEquals("test030", xCreator3.toData().getWidgetName()); - } - - @Test - public void testInstantiateCreator_cardLayout() throws Exception { - - Form form = EasyMock.mock(Form.class); - EasyMock.expect(form.isNameExist("cardlayout0")).andReturn(true).once(); - EasyMock.expect(form.isNameExist("cardlayout1")).andReturn(true).once(); - EasyMock.expect(form.isNameExist(EasyMock.anyString())).andReturn(false).anyTimes(); - EasyMock.replay(form); - - FormDesigner mock = EasyMock.mock(FormDesigner.class); - EasyMock.expect(mock.getTarget()).andReturn(form).anyTimes(); - EasyMock.replay(mock); - - WCardLayout wCardLayout = new WCardLayout(20, 20); - XWCardLayout xwCardLayout = new XWCardLayout(wCardLayout, new Dimension(40, 40)); - AddingModel addingModel = new AddingModel(mock, xwCardLayout); - Assert.assertEquals("cardlayout2", xwCardLayout.toData().getWidgetName()); - - //依赖于 cardlayout 创建 container - XLayoutContainer parentLayOut = xwCardLayout.initCreatorWrapper(80); - //组件默认名 tablelayout2 - AddingModel parentModel = new AddingModel(mock, parentLayOut); - //经过处理 tablayout20 - Assert.assertEquals("tablayout20", parentLayOut.toData().getWidgetName()); - Assert.assertEquals("tabpane20", ((XCreator) (parentLayOut.getComponent(0))).getXCreator().toData().getWidgetName()); - Assert.assertEquals("cardlayout20", xwCardLayout.toData().getWidgetName()); - - } - - @Test - public void testInstantiateCreator_containsNotXCreator() throws Exception { - - Form form = EasyMock.mock(Form.class); - EasyMock.expect(form.isNameExist(EasyMock.anyString())).andReturn(false).anyTimes(); - EasyMock.replay(form); - - FormDesigner mock = EasyMock.mock(FormDesigner.class); - EasyMock.expect(mock.getTarget()).andReturn(form).anyTimes(); - EasyMock.replay(mock); - - PowerMock.mockStaticPartial(DesignModuleFactory.class, "getChartComponent"); - EasyMock.expect(DesignModuleFactory.getChartComponent(EasyMock.anyObject(BaseChartCollection.class))).andReturn(new MiddleChartComponent() { - @Override - public void populate(BaseChartCollection cc) { - - } - - @Override - public BaseChartCollection update() { - return null; - } - - @Override - public void reset() { - - } - - @Override - public void addStopEditingListener(PropertyChangeListener list) { - - } - }).anyTimes(); - PowerMock.replayAll(); - - Dimension dimension = new Dimension(20, 20); - - ChartEditor chartEditor1 = new ChartEditor(); - XCreator xCreator1 = new XChartEditor(chartEditor1, dimension); - - - AddingModel chartModel = new AddingModel(mock, xCreator1); - Assert.assertEquals("chart0", xCreator1.toData().getWidgetName()); - } - - private static class DemoCreator extends XCreator { - - private String widgetName; - - public DemoCreator(Widget ob, Dimension initSize, String defaultName) { - super(ob, initSize); - this.widgetName = defaultName; - } - - @Override - public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException { - return new CRPropertyDescriptor[0]; - } - - @Override - protected JComponent initEditor() { - return null; - } - - @Override - protected void initXCreatorProperties() { - - } - - @Override - public String createDefaultName() { - return this.widgetName; - } - } - -} \ No newline at end of file diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/GuideCreateUtils.java b/designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/GuideCreateUtils.java index 39c6b5574..bb2120874 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/GuideCreateUtils.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/GuideCreateUtils.java @@ -1,6 +1,5 @@ package com.fr.design.mainframe.guide.creator; -import com.fr.design.designer.beans.models.AddingModel; import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XLayoutContainer; import com.fr.design.dialog.FineJOptionPane; @@ -10,7 +9,6 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.login.DesignerLoginHelper; import com.fr.design.login.DesignerLoginSource; import com.fr.design.mainframe.DesignerContext; -import com.fr.design.mainframe.FormCreatorDropTarget; import com.fr.design.mainframe.FormDesigner; import com.fr.design.mainframe.JForm; import com.fr.design.mainframe.guide.base.GuideManager; @@ -127,24 +125,17 @@ public class GuideCreateUtils { return null; } - public static void addXCreatorToXLayoutContainer(XCreator xCreator, XLayoutContainer xLayoutContainer, boolean isDragComponent) { + public static void addXCreatorToXLayoutContainer(XCreator xCreator, XLayoutContainer xLayoutContainer, boolean dragNewComponent) { if (xCreator == null) { return; } FormDesigner designer = GuideCreateUtils.getFormDesigner(); designer.getSelectionModel().selectACreator(xLayoutContainer); - - if (isDragComponent) { - designer.setAddingModel(new AddingModel(xCreator, 0,0)); - designer.setDropTarget(new FormCreatorDropTarget(designer)); - designer.repaint(); + if (dragNewComponent) { + designer.addNewWidget(xCreator, xLayoutContainer.getX(), xLayoutContainer.getY()); } else { - designer.startDraggingBean(xCreator); + designer.changeWidgetPlace(xCreator, xLayoutContainer.getX(), xLayoutContainer.getY()); } - - FormCreatorDropTarget dropTarget = (FormCreatorDropTarget) designer.getDropTarget(); - dropTarget.adding(xLayoutContainer.getX(), xLayoutContainer.getY()); - designer.getSelectionModel().selectACreator(xCreator); } diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/layout/ChangeLayoutComponentGuide.java b/designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/layout/ChangeLayoutComponentGuide.java index ae7fb8138..331841fc9 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/layout/ChangeLayoutComponentGuide.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/layout/ChangeLayoutComponentGuide.java @@ -136,8 +136,8 @@ public class ChangeLayoutComponentGuide { formDesigner.getSelectionModel().removeCreator(from, from.getWidth(), from.getHeight()); formDesigner.getSelectionModel().removeCreator(to, to.getWidth(),to.getHeight()); - GuideCreateUtils.addXCreatorToXLayoutContainer(from, (XLayoutContainer) GuideCreateUtils.getXCreatorFormDesigner("box1"), true); - GuideCreateUtils.addXCreatorToXLayoutContainer(to, (XLayoutContainer) GuideCreateUtils.getXCreatorFormDesigner("box0"), true); + GuideCreateUtils.addXCreatorToXLayoutContainer(from, (XLayoutContainer) GuideCreateUtils.getXCreatorFormDesigner("box1"), false); + GuideCreateUtils.addXCreatorToXLayoutContainer(to, (XLayoutContainer) GuideCreateUtils.getXCreatorFormDesigner("box0"), false); return true; } }); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/layout/UseLayoutAndComponentGuide.java b/designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/layout/UseLayoutAndComponentGuide.java index b4f5647c6..38539b54d 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/layout/UseLayoutAndComponentGuide.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/guide/creator/layout/UseLayoutAndComponentGuide.java @@ -246,7 +246,7 @@ public class UseLayoutAndComponentGuide { LocalWidgetBlock block = getLocalWidgetBlock(shareID); XCreator xCreator = block.transformXCreator(block); XOccupiedLayout xOccupiedLayout = getXOccupiedLayout(name); - GuideCreateUtils.addXCreatorToXLayoutContainer(xCreator, xOccupiedLayout, false); + GuideCreateUtils.addXCreatorToXLayoutContainer(xCreator, xOccupiedLayout, true); return true; } });