Browse Source

Merge branch 'release/10.0' of ssh://cloud.finedevelop.com:7999/~tommy/design into release/10.0

feature/big-screen
kuangshuai 5 years ago
parent
commit
ec01cb38e0
  1. 53
      designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardFilter.java
  2. 68
      designer-base/src/main/java/com/fr/design/base/clipboard/DesignerClipboard.java
  3. 45
      designer-base/src/main/java/com/fr/design/fun/ClipboardHandlerProvider.java
  4. 17
      designer-base/src/main/java/com/fr/design/fun/impl/AbstractClipboardHandlerProvider.java
  5. 83
      designer-base/src/main/java/com/fr/design/mainframe/DesignerContext.java
  6. 62
      designer-base/src/test/java/com/fr/design/base/clipboard/ClipboardFilterTest.java
  7. 75
      designer-base/src/test/java/com/fr/design/base/clipboard/DesignerClipboardTest.java
  8. 29
      designer-base/src/test/java/com/fr/design/base/clipboard/TestClipboardHandlerProvider.java
  9. 13
      designer-form/src/main/java/com/fr/design/designer/beans/events/CreatorEventListenerTable.java
  10. 30
      designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java
  11. 22
      designer-form/src/main/java/com/fr/design/fun/DesignerEditListenerProvider.java
  12. 17
      designer-form/src/main/java/com/fr/design/fun/impl/AbstractDesignerEditListenerProvider.java
  13. 102
      designer-form/src/test/java/com/fr/design/designer/beans/models/SelectionModelTest.java

53
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> T cut(T selection) {
Class<?> clazz = selection.getClass();
ExtraFormClassManager manager = PluginModule.getAgent(PluginModule.ExtraForm);
Set<ClipboardHandlerProvider> providers = manager.getArray(ClipboardHandlerProvider.XML_TAG);
for (ClipboardHandlerProvider provider : providers) {
if (provider.support(clazz)) {
selection = ((ClipboardHandlerProvider<T>) provider).cut(selection);
}
}
return selection;
}
public static <T> T copy(T selection) {
Class<?> clazz = selection.getClass();
ExtraFormClassManager manager = PluginModule.getAgent(PluginModule.ExtraForm);
Set<ClipboardHandlerProvider> providers = manager.getArray(ClipboardHandlerProvider.XML_TAG);
for (ClipboardHandlerProvider provider : providers) {
if (provider.support(clazz)) {
selection = ((ClipboardHandlerProvider<T>) provider).copy(selection);
}
}
return selection;
}
public static <T> T paste(T selection) {
Class<?> clazz = selection.getClass();
ExtraFormClassManager manager = PluginModule.getAgent(PluginModule.ExtraForm);
Set<ClipboardHandlerProvider> providers = manager.getArray(ClipboardHandlerProvider.XML_TAG);
for (ClipboardHandlerProvider provider : providers) {
if (provider.support(clazz)) {
selection = ((ClipboardHandlerProvider<T>) provider).paste(selection);
}
}
return selection;
}
}

68
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();
}
}

45
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<T> 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);
}

17
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<T> extends AbstractProvider implements ClipboardHandlerProvider<T> {
@Override
public int currentAPILevel() {
return ClipboardHandlerProvider.CURRENT_LEVEL;
}
}

83
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;
}

62
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<Mutable> providers = new HashSet<>();
providers.add(new TestClipboardHandlerProvider<Object>());
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);
}
}

75
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<Mutable> 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<String> transferData = Lists.newArrayList("test", "test2");
ArrayListTransferable transferable = new ArrayListTransferable(transferData);
clipboard.setContents(transferable, null);
Transferable filterTransferable = clipboard.getContents(null);
DataFlavor[] flavors = transferable.getTransferDataFlavors();
ArrayList<String> transferData2 = (ArrayList<String>) filterTransferable.getTransferData(flavors[0]);
Assert.assertEquals(transferData.get(0), transferData2.get(0));
}
}

29
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<T> extends AbstractClipboardHandlerProvider<T> {
@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;
}
}

13
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<DesignerEditListenerProvider> providers = manager.getArray(DesignerEditListenerProvider.XML_TAG);
for (DesignerEditListenerProvider provider : providers) {
provider.fireCreatorModified(evt);
}
}
public void fireCreatorModified(XComponent creator, int eventID) {

30
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();

22
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);
}

17
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;
}
}

102
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<Object>() {
@Override
public Object answer() throws Throwable {
return null;
}
}).anyTimes();
EasyMock.expect(provider.copy(EasyMock.anyObject())).andAnswer(new IAnswer<Object>() {
@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<Mutable> 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<Mutable>())
.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);
}
}
Loading…
Cancel
Save