From 77ae394443799931f2a33f7e2e08b110766914fc Mon Sep 17 00:00:00 2001 From: Harrison Date: Fri, 15 May 2020 15:44:58 +0800 Subject: [PATCH] =?UTF-8?q?REPORT-29912=20=E7=BB=84=E4=BB=B6=E5=8A=A0?= =?UTF-8?q?=E5=AF=86=201=E3=80=81=E4=BC=98=E5=8C=96=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E6=B0=B4=E5=8D=B0=E6=8E=A5=E5=8F=A3=202=E3=80=81=E4=B8=BA?= =?UTF-8?q?=E5=A4=8D=E5=88=B6=E7=B2=98=E8=B4=B4=E5=BC=80=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=203=E3=80=81=E4=B8=BA=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=EF=BC=8C=E5=88=A0=E9=99=A4=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=E5=8A=A0=E4=BA=8B=E4=BB=B6=E7=9B=91=E5=90=AC=E7=9A=84=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../base/clipboard/ClipboardFilter.java | 53 +++++++++ .../base/clipboard/DesignerClipboard.java | 68 ++++++++++++ .../design/fun/ClipboardHandlerProvider.java | 45 ++++++++ .../AbstractClipboardHandlerProvider.java | 17 +++ .../fr/design/mainframe/DesignerContext.java | 83 ++++++++------ .../base/clipboard/ClipboardFilterTest.java | 62 +++++++++++ .../base/clipboard/DesignerClipboardTest.java | 75 +++++++++++++ .../TestClipboardHandlerProvider.java | 29 +++++ .../events/CreatorEventListenerTable.java | 13 +++ .../designer/beans/models/SelectionModel.java | 30 ++++-- .../fun/DesignerEditListenerProvider.java | 22 ++++ .../AbstractDesignerEditListenerProvider.java | 17 +++ .../beans/models/SelectionModelTest.java | 102 ++++++++++++++++++ 13 files changed, 574 insertions(+), 42 deletions(-) create mode 100644 designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardFilter.java create mode 100644 designer-base/src/main/java/com/fr/design/base/clipboard/DesignerClipboard.java create mode 100644 designer-base/src/main/java/com/fr/design/fun/ClipboardHandlerProvider.java create mode 100644 designer-base/src/main/java/com/fr/design/fun/impl/AbstractClipboardHandlerProvider.java create mode 100644 designer-base/src/test/java/com/fr/design/base/clipboard/ClipboardFilterTest.java create mode 100644 designer-base/src/test/java/com/fr/design/base/clipboard/DesignerClipboardTest.java create mode 100644 designer-base/src/test/java/com/fr/design/base/clipboard/TestClipboardHandlerProvider.java create mode 100644 designer-form/src/main/java/com/fr/design/fun/DesignerEditListenerProvider.java create mode 100644 designer-form/src/main/java/com/fr/design/fun/impl/AbstractDesignerEditListenerProvider.java create mode 100644 designer-form/src/test/java/com/fr/design/designer/beans/models/SelectionModelTest.java diff --git a/designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardFilter.java b/designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardFilter.java new file mode 100644 index 000000000..377a57e46 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardFilter.java @@ -0,0 +1,53 @@ +package com.fr.design.base.clipboard; + +import com.fr.design.fun.ClipboardHandlerProvider; +import com.fr.form.main.ExtraFormClassManager; +import com.fr.plugin.injectable.PluginModule; + +import java.util.Set; + +/** + * created by Harrison on 2020/05/14 + **/ +@SuppressWarnings({"rawtypes", "unchecked"}) +public abstract class ClipboardFilter { + + public static T cut(T selection) { + + Class clazz = selection.getClass(); + ExtraFormClassManager manager = PluginModule.getAgent(PluginModule.ExtraForm); + Set providers = manager.getArray(ClipboardHandlerProvider.XML_TAG); + for (ClipboardHandlerProvider provider : providers) { + if (provider.support(clazz)) { + selection = ((ClipboardHandlerProvider) provider).cut(selection); + } + } + return selection; + } + + public static T copy(T selection) { + + Class clazz = selection.getClass(); + ExtraFormClassManager manager = PluginModule.getAgent(PluginModule.ExtraForm); + Set providers = manager.getArray(ClipboardHandlerProvider.XML_TAG); + for (ClipboardHandlerProvider provider : providers) { + if (provider.support(clazz)) { + selection = ((ClipboardHandlerProvider) provider).copy(selection); + } + } + return selection; + } + + public static T paste(T selection) { + + Class clazz = selection.getClass(); + ExtraFormClassManager manager = PluginModule.getAgent(PluginModule.ExtraForm); + Set providers = manager.getArray(ClipboardHandlerProvider.XML_TAG); + for (ClipboardHandlerProvider provider : providers) { + if (provider.support(clazz)) { + selection = ((ClipboardHandlerProvider) provider).paste(selection); + } + } + return selection; + } +} diff --git a/designer-base/src/main/java/com/fr/design/base/clipboard/DesignerClipboard.java b/designer-base/src/main/java/com/fr/design/base/clipboard/DesignerClipboard.java new file mode 100644 index 000000000..76ae081d7 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/base/clipboard/DesignerClipboard.java @@ -0,0 +1,68 @@ +package com.fr.design.base.clipboard; + +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.FlavorListener; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; + +/** + * created by Harrison on 2020/05/11 + **/ +public class DesignerClipboard extends Clipboard { + + private Clipboard clipboard; + + public DesignerClipboard(Clipboard clipboard) { + super(clipboard.getName()); + this.clipboard = clipboard; + } + + @Override + public synchronized void setContents(Transferable contents, ClipboardOwner owner) { + //处理 contents/owner + Transferable filtered = ClipboardFilter.copy(contents); + clipboard.setContents(filtered, owner); + } + + @Override + public synchronized Transferable getContents(Object requestor) { + Transferable contents = clipboard.getContents(requestor); + //处理 contents + Transferable filtered = ClipboardFilter.paste(contents); + return filtered; + } + + @Override + public DataFlavor[] getAvailableDataFlavors() { + return clipboard.getAvailableDataFlavors(); + } + + @Override + public boolean isDataFlavorAvailable(DataFlavor flavor) { + return clipboard.isDataFlavorAvailable(flavor); + } + + @Override + public Object getData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { + return clipboard.getData(flavor); + } + + @Override + public synchronized void addFlavorListener(FlavorListener listener) { + clipboard.addFlavorListener(listener); + } + + @Override + public synchronized void removeFlavorListener(FlavorListener listener) { + clipboard.removeFlavorListener(listener); + } + + @Override + public synchronized FlavorListener[] getFlavorListeners() { + return clipboard.getFlavorListeners(); + } + +} diff --git a/designer-base/src/main/java/com/fr/design/fun/ClipboardHandlerProvider.java b/designer-base/src/main/java/com/fr/design/fun/ClipboardHandlerProvider.java new file mode 100644 index 000000000..fbbdacaad --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/ClipboardHandlerProvider.java @@ -0,0 +1,45 @@ +package com.fr.design.fun; + +import com.fr.stable.fun.mark.Mutable; + +/** + * created by Harrison on 2020/05/14 + **/ +public interface ClipboardHandlerProvider extends Mutable { + + String XML_TAG = "ClipboardHandlerProvider"; + + int CURRENT_LEVEL = 1; + + /** + * 剪切 + * + * @param selection 选中 + * @return 处理后的内容 + */ + T cut(T selection); + + /** + * 复制 + * + * @param selection 选中 + * @return 处理后的内容 + */ + T copy(T selection); + + /** + * 粘贴 + * + * @param selection 选中 + * @return 处理后的内容 + */ + T paste(T selection); + + /** + * 支持的类型 + * + * @param selection 内容 + * @return 是否 + */ + boolean support(Object selection); +} diff --git a/designer-base/src/main/java/com/fr/design/fun/impl/AbstractClipboardHandlerProvider.java b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractClipboardHandlerProvider.java new file mode 100644 index 000000000..da1861916 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/fun/impl/AbstractClipboardHandlerProvider.java @@ -0,0 +1,17 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.ClipboardHandlerProvider; +import com.fr.stable.fun.impl.AbstractProvider; +import com.fr.stable.fun.mark.API; + +/** + * created by Harrison on 2020/05/14 + **/ +@API(level = ClipboardHandlerProvider.CURRENT_LEVEL) +public abstract class AbstractClipboardHandlerProvider extends AbstractProvider implements ClipboardHandlerProvider { + + @Override + public int currentAPILevel() { + return ClipboardHandlerProvider.CURRENT_LEVEL; + } +} diff --git a/designer-base/src/main/java/com/fr/design/mainframe/DesignerContext.java b/designer-base/src/main/java/com/fr/design/mainframe/DesignerContext.java index 9362f37c5..49fffa6ce 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/DesignerContext.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/DesignerContext.java @@ -4,6 +4,7 @@ package com.fr.design.mainframe; import com.fr.base.Style; +import com.fr.design.base.clipboard.DesignerClipboard; import com.fr.design.designer.TargetComponent; import com.fr.design.dialog.BasicDialog; import com.fr.log.FineLoggerFactory; @@ -56,41 +57,53 @@ public class DesignerContext { public static DesignerBean getDesignerBean(String name) { return beans.get(name) == null ? DesignerBean.NULL : beans.get(name); } - - public static void setDesignerBean(String name, DesignerBean bean) { - beans.put(name, bean); - } - - /** - * Gets the Clipboard. - */ - public static Clipboard getClipboard(JComponent comp) { - if (DesignerContext.clipboard == null) { - try { - Action transferAction = TransferHandler.getCutAction(); - Method clipMethod = StableUtils.getDeclaredMethod(transferAction.getClass(), "getClipboard", new Class[]{JComponent.class}); - clipMethod.setAccessible(true); - - return (Clipboard) clipMethod.invoke(transferAction, new Object[]{comp}); - } catch (Exception securityException) { - FineLoggerFactory.getLogger().error(securityException.getMessage(), securityException); - //用反射机制,获得TransferHandler的getClipboard - //这样可以保证和TextField直接的copy paste - try { - //控件的Clipboard. - DesignerContext.clipboard = comp.getToolkit().getSystemClipboard(); - } catch (Exception exp) { - FineLoggerFactory.getLogger().error(exp.getMessage(), exp); - DesignerContext.clipboard = new Clipboard("FR"); - } - } - } - - return DesignerContext.clipboard; - } - - - public static void setFormatState(int setformatState) { + + public static void setDesignerBean(String name, DesignerBean bean) { + beans.put(name, bean); + } + + /** + * get this custom clipboard + */ + public static Clipboard getClipboard(JComponent comp) { + + if (DesignerContext.clipboard == null) { + + Clipboard clipboard = getClipboard0(comp); + return new DesignerClipboard(clipboard); + } + return DesignerContext.clipboard; + } + + /** + * Gets the system Clipboard. + */ + private static Clipboard getClipboard0(JComponent comp) { + + Clipboard clipboard = null; + try { + Action transferAction = TransferHandler.getCutAction(); + Method clipMethod = StableUtils.getDeclaredMethod(transferAction.getClass(), "getClipboard", new Class[]{JComponent.class}); + clipMethod.setAccessible(true); + + return (Clipboard) clipMethod.invoke(transferAction, new Object[]{comp}); + } catch (Exception securityException) { + FineLoggerFactory.getLogger().error(securityException.getMessage(), securityException); + //用反射机制,获得TransferHandler的getClipboard + //这样可以保证和TextField直接的copy paste + try { + //控件的Clipboard. + clipboard = comp.getToolkit().getSystemClipboard(); + } catch (Exception exp) { + FineLoggerFactory.getLogger().error(exp.getMessage(), exp); + clipboard = new Clipboard("FR"); + } + } + return clipboard; + } + + + public static void setFormatState(int setformatState) { formatState = setformatState; } diff --git a/designer-base/src/test/java/com/fr/design/base/clipboard/ClipboardFilterTest.java b/designer-base/src/test/java/com/fr/design/base/clipboard/ClipboardFilterTest.java new file mode 100644 index 000000000..f6b9190eb --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/base/clipboard/ClipboardFilterTest.java @@ -0,0 +1,62 @@ +package com.fr.design.base.clipboard; + +import com.fr.design.fun.ClipboardHandlerProvider; +import com.fr.form.main.ExtraFormClassManager; +import com.fr.plugin.injectable.PluginModule; +import com.fr.stable.fun.mark.Mutable; +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.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.util.HashSet; +import java.util.Set; + +@PrepareForTest(PluginModule.class) +@RunWith(PowerMockRunner.class) +public class ClipboardFilterTest { + + + @Before + public void setUp() throws Exception { + + Set providers = new HashSet<>(); + providers.add(new TestClipboardHandlerProvider()); + + ExtraFormClassManager formClassManager = EasyMock.mock(ExtraFormClassManager.class); + EasyMock.expect(formClassManager.getArray(ClipboardHandlerProvider.XML_TAG)) + .andReturn(providers) + .anyTimes(); + EasyMock.replay(formClassManager); + + PowerMock.mockStatic(PluginModule.class); + EasyMock.expect(PluginModule.getAgent(PluginModule.ExtraForm)) + .andReturn(formClassManager) + .anyTimes(); + PowerMock.replayAll(); + } + + @After + public void tearDown() throws Exception { + + PowerMock.resetAll(); + } + + @Test + public void testClipboard() { + + ClipboardFilter.cut("cut"); + String paste1 = ClipboardFilter.paste("paste"); + Assert.assertNull(paste1); + + ClipboardFilter.copy("copy"); + String paste2 = ClipboardFilter.paste("paste"); + Assert.assertNull(paste2); + } + +} \ No newline at end of file diff --git a/designer-base/src/test/java/com/fr/design/base/clipboard/DesignerClipboardTest.java b/designer-base/src/test/java/com/fr/design/base/clipboard/DesignerClipboardTest.java new file mode 100644 index 000000000..36cdc54f0 --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/base/clipboard/DesignerClipboardTest.java @@ -0,0 +1,75 @@ +package com.fr.design.base.clipboard; + +import com.fr.design.fun.ClipboardHandlerProvider; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.dnd.ArrayListTransferable; +import com.fr.form.main.ExtraFormClassManager; +import com.fr.plugin.injectable.PluginModule; +import com.fr.stable.fun.mark.Mutable; +import com.fr.third.guava.collect.Lists; +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.JPanel; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +@PrepareForTest(PluginModule.class) +@RunWith(PowerMockRunner.class) +@PowerMockIgnore("javax.swing.*") +public class DesignerClipboardTest { + + @Before + public void setUp() throws Exception { + + Set providers = new HashSet<>(); + + ExtraFormClassManager formClassManager = EasyMock.mock(ExtraFormClassManager.class); + EasyMock.expect(formClassManager.getArray(ClipboardHandlerProvider.XML_TAG)) + .andReturn(providers) + .anyTimes(); + EasyMock.replay(formClassManager); + + PowerMock.mockStatic(PluginModule.class); + EasyMock.expect(PluginModule.getAgent(PluginModule.ExtraForm)) + .andReturn(formClassManager) + .anyTimes(); + PowerMock.replayAll(); + } + + @After + public void tearDown() throws Exception { + + PowerMock.resetAll(); + } + + @Test + public void testClipboard() throws Exception { + + JPanel panel = new JPanel(); + Clipboard clipboard = DesignerContext.getClipboard(panel); + + ArrayList transferData = Lists.newArrayList("test", "test2"); + ArrayListTransferable transferable = new ArrayListTransferable(transferData); + clipboard.setContents(transferable, null); + + Transferable filterTransferable = clipboard.getContents(null); + DataFlavor[] flavors = transferable.getTransferDataFlavors(); + ArrayList transferData2 = (ArrayList) filterTransferable.getTransferData(flavors[0]); + + Assert.assertEquals(transferData.get(0), transferData2.get(0)); + } + +} \ No newline at end of file diff --git a/designer-base/src/test/java/com/fr/design/base/clipboard/TestClipboardHandlerProvider.java b/designer-base/src/test/java/com/fr/design/base/clipboard/TestClipboardHandlerProvider.java new file mode 100644 index 000000000..3282f257e --- /dev/null +++ b/designer-base/src/test/java/com/fr/design/base/clipboard/TestClipboardHandlerProvider.java @@ -0,0 +1,29 @@ +package com.fr.design.base.clipboard; + +import com.fr.design.fun.impl.AbstractClipboardHandlerProvider; + +/** + * created by Harrison on 2020/05/15 + **/ +class TestClipboardHandlerProvider extends AbstractClipboardHandlerProvider { + + @Override + public T cut(T selection) { + return selection; + } + + @Override + public T copy(T selection) { + return selection; + } + + @Override + public T paste(T selection) { + return null; + } + + @Override + public boolean support(Object selection) { + return true; + } +} diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/events/CreatorEventListenerTable.java b/designer-form/src/main/java/com/fr/design/designer/beans/events/CreatorEventListenerTable.java index 2c0c28504..aa0ea1c9a 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/events/CreatorEventListenerTable.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/events/CreatorEventListenerTable.java @@ -1,10 +1,14 @@ package com.fr.design.designer.beans.events; import com.fr.design.designer.creator.XComponent; +import com.fr.design.fun.DesignerEditListenerProvider; +import com.fr.form.main.ExtraFormClassManager; import com.fr.general.ComparatorUtils; +import com.fr.plugin.injectable.PluginModule; import javax.swing.SwingUtilities; import java.util.ArrayList; +import java.util.Set; public class CreatorEventListenerTable { @@ -28,6 +32,7 @@ public class CreatorEventListenerTable { } private void fireCreatorModified(final DesignerEvent evt) { + for (int i = 0; i < listeners.size(); i++) { final DesignerEditListener listener = listeners.get(i); SwingUtilities.invokeLater(new Runnable() { @@ -37,6 +42,14 @@ public class CreatorEventListenerTable { } }); } + + //触发插件的事件 + ExtraFormClassManager manager = PluginModule.getAgent(PluginModule.ExtraForm); + Set providers = manager.getArray(DesignerEditListenerProvider.XML_TAG); + for (DesignerEditListenerProvider provider : providers) { + provider.fireCreatorModified(evt); + } + } public void fireCreatorModified(XComponent creator, int eventID) { diff --git a/designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java b/designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java index a8adfeb27..dd964e4ab 100644 --- a/designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java +++ b/designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java @@ -1,12 +1,19 @@ package com.fr.design.designer.beans.models; import com.fr.common.inputevent.InputEventBaseOnOS; +import com.fr.design.base.clipboard.ClipboardFilter; import com.fr.design.designer.beans.AdapterBus; import com.fr.design.designer.beans.LayoutAdapter; import com.fr.design.designer.beans.events.DesignerEvent; import com.fr.design.designer.beans.location.Direction; import com.fr.design.designer.beans.location.Location; -import com.fr.design.designer.creator.*; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.designer.creator.XCreatorUtils; +import com.fr.design.designer.creator.XLayoutContainer; +import com.fr.design.designer.creator.XWAbsoluteBodyLayout; +import com.fr.design.designer.creator.XWAbsoluteLayout; +import com.fr.design.designer.creator.XWFitLayout; +import com.fr.design.designer.creator.XWParameterLayout; import com.fr.design.designer.creator.cardlayout.XWCardLayout; import com.fr.design.designer.creator.cardlayout.XWCardMainBorderLayout; import com.fr.design.designer.creator.cardlayout.XWTabFitLayout; @@ -19,7 +26,9 @@ import com.fr.design.utils.ComponentUtils; import com.fr.design.utils.gui.LayoutUtils; import com.fr.stable.ArrayUtils; -import java.awt.*; +import java.awt.LayoutManager; +import java.awt.Rectangle; +import java.awt.Toolkit; import java.awt.event.MouseEvent; import java.util.ArrayList; @@ -110,9 +119,12 @@ public class SelectionModel { */ public void cutSelectedCreator2ClipBoard() { if (hasSelectionComponent()) { - selection.cut2ClipBoard(clipboard); - designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_CUTED); - designer.repaint(); + FormSelection cutSelection = ClipboardFilter.cut(selection); + if (cutSelection != null) { + cutSelection.cut2ClipBoard(clipboard); + designer.getEditListenerTable().fireCreatorModified(DesignerEvent.CREATOR_CUTED); + designer.repaint(); + } } } @@ -121,7 +133,10 @@ public class SelectionModel { */ public void copySelectedCreator2ClipBoard() { if (!selection.isEmpty()) { - selection.copy2ClipBoard(clipboard); + FormSelection copySelection = ClipboardFilter.copy(selection); + if (copySelection != null) { + copySelection.copy2ClipBoard(clipboard); + } } } @@ -131,7 +146,8 @@ public class SelectionModel { * @return 否 */ public boolean pasteFromClipBoard() { - if (!clipboard.isEmpty()) { + FormSelection pasteSelection = ClipboardFilter.paste(clipboard); + if (pasteSelection != null && !pasteSelection.isEmpty()) { if (!hasSelectedPasteSource()) { //未选 unselectedPaste(); diff --git a/designer-form/src/main/java/com/fr/design/fun/DesignerEditListenerProvider.java b/designer-form/src/main/java/com/fr/design/fun/DesignerEditListenerProvider.java new file mode 100644 index 000000000..f7f1cbe52 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fun/DesignerEditListenerProvider.java @@ -0,0 +1,22 @@ +package com.fr.design.fun; + +import com.fr.design.designer.beans.events.DesignerEvent; +import com.fr.stable.fun.mark.Mutable; + +/** + * created by Harrison on 2020/05/14 + **/ +public interface DesignerEditListenerProvider extends Mutable { + + String XML_TAG = "DesignerEditListenerProvider"; + + int CURRENT_LEVEL = 1; + + /** + * 触发设计器事件 + * + * @param evt 事件 + */ + void fireCreatorModified(DesignerEvent evt); + +} diff --git a/designer-form/src/main/java/com/fr/design/fun/impl/AbstractDesignerEditListenerProvider.java b/designer-form/src/main/java/com/fr/design/fun/impl/AbstractDesignerEditListenerProvider.java new file mode 100644 index 000000000..c34ca98b1 --- /dev/null +++ b/designer-form/src/main/java/com/fr/design/fun/impl/AbstractDesignerEditListenerProvider.java @@ -0,0 +1,17 @@ +package com.fr.design.fun.impl; + +import com.fr.design.fun.DesignerEditListenerProvider; +import com.fr.stable.fun.impl.AbstractProvider; +import com.fr.stable.fun.mark.API; + +/** + * created by Harrison on 2020/05/14 + **/ +@API(level = DesignerEditListenerProvider.CURRENT_LEVEL) +public abstract class AbstractDesignerEditListenerProvider extends AbstractProvider implements DesignerEditListenerProvider { + + @Override + public int currentAPILevel() { + return DesignerEditListenerProvider.CURRENT_LEVEL; + } +} diff --git a/designer-form/src/test/java/com/fr/design/designer/beans/models/SelectionModelTest.java b/designer-form/src/test/java/com/fr/design/designer/beans/models/SelectionModelTest.java new file mode 100644 index 000000000..921133a21 --- /dev/null +++ b/designer-form/src/test/java/com/fr/design/designer/beans/models/SelectionModelTest.java @@ -0,0 +1,102 @@ +package com.fr.design.designer.beans.models; + +import com.fr.design.designer.beans.events.CreatorEventListenerTable; +import com.fr.design.designer.creator.XCreator; +import com.fr.design.fun.ClipboardHandlerProvider; +import com.fr.design.fun.impl.AbstractClipboardHandlerProvider; +import com.fr.design.mainframe.FormDesigner; +import com.fr.form.main.ExtraFormClassManager; +import com.fr.plugin.injectable.PluginModule; +import com.fr.stable.fun.mark.Mutable; +import org.easymock.EasyMock; +import org.easymock.IAnswer; +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.core.classloader.annotations.SuppressStaticInitializationFor; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +import java.util.HashSet; +import java.util.Set; + +@PrepareForTest(PluginModule.class) +@SuppressStaticInitializationFor({"com.fr.design.mainframe.FormDesigner"}) +@PowerMockIgnore("javax.swing.*") +@RunWith(PowerMockRunner.class) +public class SelectionModelTest { + + @Before + public void setUp() throws Exception { + + AbstractClipboardHandlerProvider provider = EasyMock.mock(AbstractClipboardHandlerProvider.class); + EasyMock.expect(provider.cut(EasyMock.anyObject())).andAnswer(new IAnswer() { + @Override + public Object answer() throws Throwable { + return null; + } + }).anyTimes(); + EasyMock.expect(provider.copy(EasyMock.anyObject())).andAnswer(new IAnswer() { + @Override + public Object answer() throws Throwable { + return EasyMock.getCurrentArguments()[0]; + } + }).anyTimes(); + EasyMock.expect(provider.support(EasyMock.anyObject())).andReturn(true).anyTimes(); + EasyMock.expect(provider.paste(EasyMock.anyObject())).andReturn(null).anyTimes(); + EasyMock.replay(provider); + + Set providers = new HashSet<>(); + providers.add(provider); + + ExtraFormClassManager formClassManager = EasyMock.mock(ExtraFormClassManager.class); + EasyMock.expect(formClassManager.getArray(ClipboardHandlerProvider.XML_TAG)) + .andReturn(providers) + .anyTimes(); + EasyMock.expect(formClassManager.getArray("DesignerEditListenerProvider")) + .andReturn(new HashSet()) + .anyTimes(); + + + EasyMock.replay(formClassManager); + + PowerMock.mockStatic(PluginModule.class); + EasyMock.expect(PluginModule.getAgent(PluginModule.ExtraForm)) + .andReturn(formClassManager) + .anyTimes(); + PowerMock.replayAll(); + } + + @After + public void tearDown() throws Exception { + + PowerMock.resetAll(); + } + + @Test + public void testPaste() { + + FormDesigner formDesigner = EasyMock.partialMockBuilder(FormDesigner.class).createMock(); + XCreator xCreator = EasyMock.mock(XCreator.class); + EasyMock.expect(xCreator.acceptType(EasyMock.anyObject(Class[].class))).andReturn(true).anyTimes(); + CreatorEventListenerTable table = new CreatorEventListenerTable(); + Whitebox.setInternalState(formDesigner, "edit", table); + EasyMock.replay(formDesigner, xCreator); + + SelectionModel model = new SelectionModel(formDesigner); + model.cutSelectedCreator2ClipBoard(); + boolean paste1 = model.pasteFromClipBoard(); + Assert.assertFalse(paste1); + + model.setSelectedCreator(xCreator); + model.copySelectedCreator2ClipBoard(); + boolean paste2 = model.pasteFromClipBoard(); + Assert.assertFalse(paste2); + } + +} \ No newline at end of file