Browse Source

Merge pull request #4429 in DESIGN/design from feature/10.0 to feature/x

* commit '4f8aa5a21c4334a944db5de9e21774ff1ab07e80':
  REPORT-53016 插件缺失提醒-设计改进-白名单和远程提醒
  REPORT-53007 组件复用-合入主版本-事件允许重命名,需要支持一下cpt单元格的控件事件@kerry
  REPORT-51683 【10.0.17】智能联动被修改位置 update
  REPORT-52819 依赖修改
  REPORT-51683 【10.0.17】智能联动被修改位置
  REPORT-51678 移植加密组件剪切复制粘贴的逻辑
research/11.0
superman 3 years ago
parent
commit
e8cc26da1c
  1. 20
      designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardFilter.java
  2. 35
      designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardHandler.java
  3. 485
      designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java
  4. 29
      designer-base/src/main/java/com/fr/design/mod/ContentChange.java
  5. 66
      designer-base/src/main/java/com/fr/design/mod/ContentObjectManager.java
  6. 20
      designer-base/src/main/java/com/fr/design/mod/ContentReplaceUtil.java
  7. 13
      designer-base/src/main/java/com/fr/design/mod/ContentReplacer.java
  8. 108
      designer-base/src/main/java/com/fr/design/mod/ContentReplacerCenter.java
  9. 33
      designer-base/src/main/java/com/fr/design/mod/ModClassFilter.java
  10. 14
      designer-base/src/main/java/com/fr/design/mod/bean/ChangeItem.java
  11. 33
      designer-base/src/main/java/com/fr/design/mod/bean/ContentChangeItem.java
  12. 13
      designer-base/src/main/java/com/fr/design/mod/event/ModifyEvent.java
  13. 12
      designer-base/src/main/java/com/fr/design/mod/event/TableDataModifyEvent.java
  14. 12
      designer-base/src/main/java/com/fr/design/mod/event/WidgetNameModifyEvent.java
  15. 16
      designer-base/src/main/java/com/fr/design/mod/impl/change/ChartHyperRelateCellLinkContentChange.java
  16. 16
      designer-base/src/main/java/com/fr/design/mod/impl/change/ChartHyperRelateFloatLinkContentChange.java
  17. 30
      designer-base/src/main/java/com/fr/design/mod/impl/change/ChartHyperRelateLinkContentChange.java
  18. 37
      designer-base/src/main/java/com/fr/design/mod/impl/change/FormulaContentChange.java
  19. 36
      designer-base/src/main/java/com/fr/design/mod/impl/change/JavaScriptContentChange.java
  20. 35
      designer-base/src/main/java/com/fr/design/mod/impl/change/VanChartHtmlLabelContentChange.java
  21. 21
      designer-base/src/main/java/com/fr/design/mod/impl/repalce/ChartHyperRelateLink4WidgetNameContentReplacer.java
  22. 22
      designer-base/src/main/java/com/fr/design/mod/impl/repalce/Formula4TableDataNameContentReplacer.java
  23. 21
      designer-base/src/main/java/com/fr/design/mod/impl/repalce/Formula4WidgetNameContentReplacer.java
  24. 22
      designer-base/src/main/java/com/fr/design/mod/impl/repalce/JavaScriptContentReplacer.java
  25. 22
      designer-base/src/main/java/com/fr/design/mod/impl/repalce/VanChartHtmlLabelContentReplacer.java
  26. 12
      designer-form/src/main/java/com/fr/design/designer/beans/models/ModelUtil.java
  27. 1
      designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java
  28. 449
      designer-form/src/main/java/com/fr/design/gui/controlpane/EventPropertyPane.java
  29. 9
      designer-form/src/main/java/com/fr/design/mainframe/FormCreatorDropTarget.java
  30. 62
      designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/AbstractCrossClipBoardState.java
  31. 79
      designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/CrossClipboardHandler.java
  32. 22
      designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/CrossClipboardState.java
  33. 72
      designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/RestrictTemplateSet.java
  34. 116
      designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/TemplateStateListenerProvider.java
  35. 86
      designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/impl/CrossLayoutClipBoardState.java
  36. 32
      designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/impl/CrossTemplateClipBoardState.java
  37. 68
      designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/impl/CrossWidgetClipBoardState.java
  38. 31
      designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/impl/EncryptSelectionClipboardHandler.java
  39. 32
      designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/impl/EncryptTransferableClipboardHandler.java
  40. 132
      designer-realize/src/main/java/com/fr/design/mainframe/app/DesignerAppUtils.java
  41. 15
      designer-realize/src/main/java/com/fr/design/mainframe/app/FormApp.java
  42. 5
      designer-realize/src/main/java/com/fr/design/share/SharableInitManager.java
  43. 75
      designer-realize/src/main/java/com/fr/design/widget/WidgetEventPane.java
  44. 2
      designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java
  45. 106
      designer-realize/src/test/java/com/fr/design/mainframe/app/DesignerAppUtilsTest.java

20
designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardFilter.java

@ -4,6 +4,7 @@ import com.fr.design.ExtraDesignClassManager;
import com.fr.design.fun.ClipboardHandlerProvider; import com.fr.design.fun.ClipboardHandlerProvider;
import com.fr.plugin.injectable.PluginModule; import com.fr.plugin.injectable.PluginModule;
import java.util.HashSet;
import java.util.Set; import java.util.Set;
/** /**
@ -11,11 +12,25 @@ import java.util.Set;
**/ **/
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
public abstract class ClipboardFilter { public abstract class ClipboardFilter {
public static Set<ClipboardHandlerProvider> clipboardHandlerProviders = new HashSet();
public static void registerClipboardHandler(ClipboardHandlerProvider provider) {
if (!clipboardHandlerProviders.contains(provider)) {
clipboardHandlerProviders.add(provider);
}
}
public static void removeClipboardHandler(ClipboardHandlerProvider provider) {
if (clipboardHandlerProviders.contains(provider)) {
clipboardHandlerProviders.remove(provider);
}
}
public static <T> T cut(T selection) { public static <T> T cut(T selection) {
ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign); ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign);
Set<ClipboardHandlerProvider> providers = manager.getArray(ClipboardHandlerProvider.XML_TAG); Set<ClipboardHandlerProvider> providers = manager.getArray(ClipboardHandlerProvider.XML_TAG);
providers.addAll(clipboardHandlerProviders);
for (ClipboardHandlerProvider provider : providers) { for (ClipboardHandlerProvider provider : providers) {
if (provider.support(selection)) { if (provider.support(selection)) {
selection = ((ClipboardHandlerProvider<T>) provider).cut(selection); selection = ((ClipboardHandlerProvider<T>) provider).cut(selection);
@ -25,9 +40,9 @@ public abstract class ClipboardFilter {
} }
public static <T> T copy(T selection) { public static <T> T copy(T selection) {
ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign); ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign);
Set<ClipboardHandlerProvider> providers = manager.getArray(ClipboardHandlerProvider.XML_TAG); Set<ClipboardHandlerProvider> providers = manager.getArray(ClipboardHandlerProvider.XML_TAG);
providers.addAll(clipboardHandlerProviders);
for (ClipboardHandlerProvider provider : providers) { for (ClipboardHandlerProvider provider : providers) {
if (provider.support(selection)) { if (provider.support(selection)) {
selection = ((ClipboardHandlerProvider<T>) provider).copy(selection); selection = ((ClipboardHandlerProvider<T>) provider).copy(selection);
@ -37,9 +52,10 @@ public abstract class ClipboardFilter {
} }
public static <T> T paste(T selection) { public static <T> T paste(T selection) {
ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign); ExtraDesignClassManager manager = PluginModule.getAgent(PluginModule.ExtraDesign);
Set<ClipboardHandlerProvider> providers = manager.getArray(ClipboardHandlerProvider.XML_TAG); Set<ClipboardHandlerProvider> providers = manager.getArray(ClipboardHandlerProvider.XML_TAG);
providers.addAll(clipboardHandlerProviders);
for (ClipboardHandlerProvider provider : providers) { for (ClipboardHandlerProvider provider : providers) {
if (provider.support(selection)) { if (provider.support(selection)) {
selection = ((ClipboardHandlerProvider<T>) provider).paste(selection); selection = ((ClipboardHandlerProvider<T>) provider).paste(selection);

35
designer-base/src/main/java/com/fr/design/base/clipboard/ClipboardHandler.java

@ -0,0 +1,35 @@
package com.fr.design.base.clipboard;
public interface ClipboardHandler<T> {
/**
* 剪切
*
* @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);
}

485
designer-base/src/main/java/com/fr/design/gui/controlpane/UIListGroupControlPane.java

@ -0,0 +1,485 @@
package com.fr.design.gui.controlpane;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.constants.UIConstants;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ilist.JNameEdList;
import com.fr.design.gui.ilist.ListModelElement;
import com.fr.design.gui.ilist.ModNameActionListener;
import com.fr.design.gui.ilist.UINameEdList;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.widget.EventCreator;
import com.fr.form.event.Listener;
import com.fr.form.ui.Widget;
import com.fr.general.NameObject;
import com.fr.report.web.util.ReportEngineEventMapping;
import com.fr.stable.ArrayUtils;
import com.fr.stable.Nameable;
import com.fr.stable.StringUtils;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* Created by kerry on 5/31/21
*/
public abstract class UIListGroupControlPane extends UIControlPane implements ListControlPaneProvider {
private boolean isPopulating = false;
private UINameEdList selectNameEdList;
private Map<String, ListWrapperPane> nameEdListMap = new HashMap<>();
private CommonShortCutHandlers commonHandlers;
private ListControlPaneHelper helper;
private JPanel contentPane;
public JPanel getContentPane() {
return contentPane;
}
private ListControlPaneHelper getHelper() {
if (helper == null) {
helper = ListControlPaneHelper.newInstance(this);
}
return helper;
}
private CommonShortCutHandlers getCommonHandlers() {
if (commonHandlers == null) {
commonHandlers = CommonShortCutHandlers.newInstance(this);
}
return commonHandlers;
}
public boolean isPopulating() {
return isPopulating;
}
@Override
protected void initLeftPane(JPanel leftPane) {
leftPane.add(new UIScrollPane(contentPane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 0)), BorderLayout.CENTER);
}
protected void refreshPane(Widget widget, NameableCreator[] creators) {
refreshContentPane(widget.supportedEvents());
refreshNameableCreator(creators);
populateNameObjects(widget);
}
private void refreshContentPane(String[] supportedEvents) {
for (String event : supportedEvents) {
if (nameEdListMap.containsKey(event)) {
continue;
}
UINameEdList list = createJNameList(event);
ListWrapperPane wrapperPane = new ListWrapperPane(switchLang(event), list);
if (this.selectNameEdList == null) {
this.selectNameEdList = wrapperPane.getNameEdList();
}
contentPane.add(wrapperPane);
nameEdListMap.put(event, wrapperPane);
}
}
protected void populateNameObjects(Widget widget) {
ArrayList<NameObject> nameObjectList = new ArrayList<>();
for (int i = 0, size = widget.getListenerSize(); i < size; i++) {
Listener listener = widget.getListener(i);
if (!listener.isDefault()) {
nameObjectList.add(i, new NameObject(switchLang(listener.getEventName()) + (i + 1), listener));
}
}
populate(getHelper().processCatalog(nameObjectList));
checkButtonEnabled();
this.repaint();
}
private void populate(Map<String, List<NameObject>> map) {
isPopulating = true; // 加一个标识位,避免切换单元格时,触发 saveSettings
Iterator<Map.Entry<String, List<NameObject>>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, List<NameObject>> entry = iterator.next();
List<NameObject> valueList = entry.getValue();
ListWrapperPane eventListWrapperPane = nameEdListMap.get(entry.getKey());
populateChildNameList(eventListWrapperPane.getNameEdList(), valueList.toArray(new NameObject[valueList.size()]));
}
this.checkButtonEnabled();
refreshEventListWrapperPane();
isPopulating = false;
}
private void refreshEventListWrapperPane() {
Iterator<Map.Entry<String, ListWrapperPane>> iterator = nameEdListMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, ListWrapperPane> entry = iterator.next();
ListWrapperPane eventListWrapperPane = entry.getValue();
UINameEdList nameEdList = eventListWrapperPane.getNameEdList();
int listSize = nameEdList.getModel().getSize();
if (this.selectNameEdList.getModel().getSize() == 0 && listSize > 0) {
this.selectNameEdList = nameEdList;
}
eventListWrapperPane.setVisible(listSize > 0);
}
if (this.selectNameEdList != null) {
this.selectNameEdList.setSelectedIndex(0);
}
this.repaint();
}
private void populateChildNameList(UINameEdList nameableList, Nameable[] nameableArray) {
nameableList.getCellEditor().stopCellEditing();
DefaultListModel listModel = (DefaultListModel) nameableList.getModel();
listModel.removeAllElements();
if (ArrayUtils.isEmpty(nameableArray)) {
isPopulating = false;
return;
}
listModel.setSize(nameableArray.length);
for (int i = 0; i < nameableArray.length; i++) {
listModel.set(i, new ListModelElement(nameableArray[i]));
}
}
private UINameEdList createJNameList(String text) {
UINameEdList nameEdList = new UINameEdList(new DefaultListModel()) {
@Override
protected void doAfterLostFocus() {
((JControlUpdatePane) controlUpdatePane).update();
}
@Override
protected void doAfterStopEditing() {
saveSettings();
}
};
nameEdList.setCellRenderer(new UINameableListCellRenderer(true, this.creators));
nameEdList.setName(text);
nameEdList.setSelectionBackground(UIConstants.ATTRIBUTE_PRESS);
nameEdList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
nameEdList.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
selectNameEdList = nameEdList;
updateUINameListSelect();
}
});
nameEdList.addMouseListener(getHelper().getListMouseListener(nameEdList, this));
nameEdList.addModNameActionListener(new ModNameActionListener() {
@Override
public void nameModed(int index, String oldName, String newName) {
saveSettings();
}
});
nameEdList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent evt) {
// richie:避免多次update和populate大大降低效率
if (!evt.getValueIsAdjusting()) {
// shoc 切换的时候加检验
if (hasInvalid(false)) {
return;
}
((JControlUpdatePane) UIListGroupControlPane.this.controlUpdatePane).update();
((JControlUpdatePane) UIListGroupControlPane.this.controlUpdatePane).populate();
UIListGroupControlPane.this.checkButtonEnabled();
}
}
});
nameEdList.getModel().addListDataListener(new ListDataListener() {
@Override
public void intervalAdded(ListDataEvent e) {
saveSettings();
}
@Override
public void intervalRemoved(ListDataEvent e) {
saveSettings();
}
@Override
public void contentsChanged(ListDataEvent e) {
saveSettings();
}
});
return nameEdList;
}
private void updateUINameListSelect() {
Iterator<Map.Entry<String, ListWrapperPane>> iterator = nameEdListMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, ListWrapperPane> entry = iterator.next();
UINameEdList nameEdList = entry.getValue().getNameEdList();
if (nameEdList != selectNameEdList) {
nameEdList.clearSelection();
}
}
}
@Override
public void checkButtonEnabled() {
getHelper().checkButtonEnabled();
}
private String switchLang(String eventName) {
// 在 properties 文件中找到相应的 key 值
String localeKey = ReportEngineEventMapping.getLocaleName(eventName);
return com.fr.design.i18n.Toolkit.i18nText(localeKey);
}
/**
* 生成不重复的名字
*
* @param prefix 名字前缀
* @return 名字
*/
@Override
public String createUnrepeatedName(String prefix) {
return getCommonHandlers().createUnrepeatedName(prefix);
}
private void updateSelectedNameList(NameableCreator creator) {
String eventName = ((EventCreator) creator).getEventName();
ListWrapperPane wrapperPane = nameEdListMap.get(eventName);
wrapperPane.setVisible(true);
setSelectNameEdList(wrapperPane.getNameEdList());
}
private void setSelectNameEdList(UINameEdList nameEdList) {
if (this.selectNameEdList != null) {
this.selectNameEdList.clearSelection();
}
this.selectNameEdList = nameEdList;
}
@Override
public void onAddItem(NameableCreator creator) {
updateSelectedNameList(creator);
getCommonHandlers().onAddItem(creator);
}
@Override
public void onRemoveItem() {
getCommonHandlers().onRemoveItem();
refreshEventListWrapperPane();
}
@Override
public void onCopyItem() {
getCommonHandlers().onCopyItem();
}
@Override
public void onMoveUpItem() {
getCommonHandlers().onMoveUpItem();
}
@Override
public void onMoveDownItem() {
getCommonHandlers().onMoveDownItem();
}
@Override
public void onSortItem(boolean isAtoZ) {
Iterator<Map.Entry<String, ListWrapperPane>> iterator = nameEdListMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, ListWrapperPane> entry = iterator.next();
UINameEdList nameEdList = entry.getValue().getNameEdList();
getCommonHandlers().onSortItem(isAtoZ, nameEdList);
}
}
@Override
public boolean isItemSelected() {
return getModel().getSize() > 0 && getSelectedIndex() != -1;
}
@Override
protected JPanel createControlUpdatePane() {
return JControlUpdatePane.newInstance(this);
}
@Override
public Nameable[] update() {
java.util.List<Nameable> res = new java.util.ArrayList<Nameable>();
getControlUpdatePane().update();
Iterator<Map.Entry<String, ListWrapperPane>> iterator = nameEdListMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, ListWrapperPane> entry = iterator.next();
UINameEdList nameEdList = entry.getValue().getNameEdList();
DefaultListModel listModel = (DefaultListModel) nameEdList.getModel();
for (int i = 0, len = listModel.getSize(); i < len; i++) {
res.add(((ListModelElement) listModel.getElementAt(i)).wrapper);
}
}
return res.toArray(new Nameable[0]);
}
@Override
public abstract NameableCreator[] createNameableCreators();
@Override
public abstract void saveSettings();
public BasicBeanPane createPaneByCreators(NameableCreator creator) {
try {
return creator.getUpdatePane().newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public BasicBeanPane createPaneByCreators(NameableCreator creator, String string) {
Constructor constructor = null;
try {
constructor = creator.getUpdatePane().getDeclaredConstructor(new Class[]{String.class});
constructor.setAccessible(true);
return (BasicBeanPane) constructor.newInstance(string);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
@Override
public DefaultListModel getModel() {
if (this.selectNameEdList == null) {
return new DefaultListModel();
}
return (DefaultListModel) this.selectNameEdList.getModel();
}
/**
* 检查是否符合规范
*
* @throws Exception
*/
@Override
public void checkValid() throws Exception {
((JControlUpdatePane) this.controlUpdatePane).checkValid();
}
@Override
public boolean hasInvalid(boolean isAdd) {
return getHelper().hasInvalid(isAdd);
}
public void addNameable(Nameable nameable, int index) {
getHelper().addNameable(nameable, index);
popupEditDialog();
}
/**
* 设置选中项
*
* @param index 选中项的序列号
*/
public void setSelectedIndex(int index) {
if (this.selectNameEdList != null) {
this.selectNameEdList.setSelectedIndex(index);
}
}
@Override
public int getSelectedIndex() {
if (this.selectNameEdList == null) {
return -1;
}
return this.selectNameEdList.getSelectedIndex();
}
@Override
public ListModelElement getSelectedValue() {
if (this.selectNameEdList == null) {
return null;
}
return (ListModelElement) this.selectNameEdList.getSelectedValue();
}
@Override
public JControlUpdatePane getControlUpdatePane() {
return (JControlUpdatePane) controlUpdatePane;
}
@Override
public JNameEdList getNameableList() {
return this.selectNameEdList;
}
private void popupEditDialog() {
getHelper().popupEditDialog(null, this.selectNameEdList, this);
}
protected String getWrapperLabelText(){
return StringUtils.EMPTY;
}
private class ListWrapperPane extends JPanel {
private UINameEdList nameEdList;
public ListWrapperPane(String labelText, UINameEdList nameEdList) {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
UILabel label = new UILabel(labelText + getWrapperLabelText());
label.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0));
label.setBackground(Color.decode("#FFFFFF"));
label.setPreferredSize(new Dimension(224, 26));
this.nameEdList = nameEdList;
this.add(label, BorderLayout.NORTH);
this.add(this.nameEdList, BorderLayout.CENTER);
}
public UINameEdList getNameEdList() {
return this.nameEdList;
}
}
}

29
designer-base/src/main/java/com/fr/design/mod/ContentChange.java

@ -0,0 +1,29 @@
package com.fr.design.mod;
import com.fr.design.mod.bean.ChangeItem;
import java.util.Map;
/**
*
* @author hades
* @version 10.0
* Created by hades on 2021/4/27
*/
public interface ContentChange<T> {
/**
* 标识内容替换类型
*
* @return
*/
String type();
/**
* 替换详情信息
*
* @return
*/
Map<ChangeItem, ContentReplacer<T>> changeInfo();
}

66
designer-base/src/main/java/com/fr/design/mod/ContentObjectManager.java

@ -0,0 +1,66 @@
package com.fr.design.mod;
import com.fr.base.Formula;
import com.fr.chart.web.ChartHyperRelateCellLink;
import com.fr.chart.web.ChartHyperRelateFloatLink;
import com.fr.design.file.filter.ClassFilter;
import com.fr.invoke.ClassHelper;
import com.fr.js.JavaScriptImpl;
import com.fr.plugin.chart.base.VanChartHtmlLabel;
import com.fr.stable.Filter;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.jetbrains.annotations.Nullable;
/**
* 管理所有需要替换内容的对象
*
* @author hades
* @version 10.0
* Created by hades on 2021/4/28
*/
public class ContentObjectManager {
private static ContentObjectManager INSTANCE = new ContentObjectManager();
public static ContentObjectManager getInstance() {
return INSTANCE;
}
/**
* 放置所有需要替换内容的对象
*/
private Map<String, Set<Object>> objectMap;
private final Set<String> set = new HashSet<>();
private ContentObjectManager() {
set.add(Formula.class.getName());
set.add(JavaScriptImpl.class.getName());
set.add(ChartHyperRelateCellLink.class.getName());
set.add(ChartHyperRelateFloatLink.class.getName());
set.add(VanChartHtmlLabel.class.getName());
}
public void searchObject(Object ob) {
objectMap = ClassHelper.searchObject(ob, set, ModClassFilter.getInstance());
}
public void searchObject(Object ob, Filter<String> filter) {
objectMap = ClassHelper.searchObject(ob, set, filter);
}
public void searchObject(Object ob, Set<String> set, Filter<String> filter) {
objectMap = ClassHelper.searchObject(ob, set, filter);
}
public void clearObject() {
objectMap = null;
}
@Nullable
public Map<String, Set<Object>> getObjectMap() {
return objectMap;
}
}

20
designer-base/src/main/java/com/fr/design/mod/ContentReplaceUtil.java

@ -0,0 +1,20 @@
package com.fr.design.mod;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/31
*/
public class ContentReplaceUtil {
public static final String EQ_STRING = "=";
public static String replaceContent(String content, String oldName, String newName) {
return content.replaceAll(generateStr(oldName), generateStr(newName));
}
private static String generateStr(String str) {
return "\"" + str + "\"";
}
}

13
designer-base/src/main/java/com/fr/design/mod/ContentReplacer.java

@ -0,0 +1,13 @@
package com.fr.design.mod;
/**
*
* @author hades
* @version 10.0
* Created by hades on 2021/5/27
*/
public interface ContentReplacer<T> {
void replace(T t, String oldName, String newName);
}

108
designer-base/src/main/java/com/fr/design/mod/ContentReplacerCenter.java

@ -0,0 +1,108 @@
package com.fr.design.mod;
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.mod.event.WidgetNameModifyEvent;
import com.fr.design.mod.impl.change.ChartHyperRelateCellLinkContentChange;
import com.fr.design.mod.impl.change.ChartHyperRelateFloatLinkContentChange;
import com.fr.design.mod.impl.change.FormulaContentChange;
import com.fr.design.mod.impl.change.JavaScriptContentChange;
import com.fr.design.mod.impl.change.VanChartHtmlLabelContentChange;
import com.fr.event.Event;
import com.fr.event.EventDispatcher;
import com.fr.event.Listener;
import com.fr.log.FineLoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 默认联动内容替换器实现
*
* 当前替换顺序组件名-> 数据集名
*
* @author hades
* @version 10.0
* Created by hades on 2021/5/27
*/
public class ContentReplacerCenter {
private static final ContentReplacerCenter INSTANCE = new ContentReplacerCenter();
public static ContentReplacerCenter getInstance() {
return INSTANCE;
}
private List<ContentChange> contentChangeList = new ArrayList<>();
private List<ContentChangeItem> items = new ArrayList<>();
private ContentReplacerCenter() {
EventDispatcher.listen(WidgetNameModifyEvent.INSTANCE, new Listener<ContentChangeItem>() {
@Override
public void on(Event event, ContentChangeItem param) {
if (param.getChangeMap().isEmpty()) {
return;
}
items.add(param);
}
});
EventDispatcher.listen(TableDataModifyEvent.INSTANCE, new Listener<ContentChangeItem>() {
@Override
public void on(Event event, ContentChangeItem param) {
items.add(param);
long start = System.currentTimeMillis();
ContentObjectManager.getInstance().searchObject(param.getObject());
FineLoggerFactory.getLogger().debug("search object spend {} ms", (System.currentTimeMillis() - start));
FineLoggerFactory.getLogger().debug("search result: {}", ContentObjectManager.getInstance().getObjectMap() == null
? null : ContentObjectManager.getInstance().getObjectMap().keySet());
List<ContentChangeItem> itemsCopy = new ArrayList<>(items);
items.clear();
onRename(itemsCopy, contentChangeList);
}
});
}
public void register() {
contentChangeList.add(new ChartHyperRelateCellLinkContentChange());
contentChangeList.add(new ChartHyperRelateFloatLinkContentChange());
contentChangeList.add(new FormulaContentChange());
contentChangeList.add(new JavaScriptContentChange());
contentChangeList.add(new VanChartHtmlLabelContentChange());
}
private void onRename(List<ContentChangeItem> contentChangeItemList, List<ContentChange> contentChangeList) {
Map<String, Set<Object>> objectMap = ContentObjectManager.getInstance().getObjectMap();
if (objectMap != null) {
long start = System.currentTimeMillis();
for (ContentChange contentChange : contentChangeList) {
Set<Object> set = objectMap.get(contentChange.type());
// 所有需要处理的js等对象
if (set != null) {
for (Object ob : set) {
fireChange(ob, contentChange, contentChangeItemList);
}
}
}
objectMap.clear();
FineLoggerFactory.getLogger().debug("replace all content spend {} ms", (System.currentTimeMillis() - start));
}
}
private void fireChange(Object o, ContentChange contentChange, List<ContentChangeItem> itemList) {
// 当前两项存在两项: 数据集名称和组件名称
for (ContentChangeItem contentChangeItem : itemList) {
Map<ChangeItem, ContentReplacer> map = contentChange.changeInfo();
if (map.containsKey(contentChangeItem.getChangeItem())) {
// 具体重命名取决于复用组件存在多少个组件或数据集
for (Map.Entry<String, String> entry : contentChangeItem.getChangeMap().entrySet()) {
map.get(contentChangeItem.getChangeItem()).replace(o, entry.getKey(), entry.getValue());
}
}
}
}
}

33
designer-base/src/main/java/com/fr/design/mod/ModClassFilter.java

@ -0,0 +1,33 @@
package com.fr.design.mod;
import com.fr.stable.Filter;
import java.util.HashSet;
import java.util.Set;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/31
*/
public class ModClassFilter implements Filter<String> {
private static final Set<String> FILTER_SET = new HashSet<>();
private static final Filter<String> INSTANCE = new ModClassFilter();
public static Filter<String> getInstance() {
return INSTANCE;
}
static {
FILTER_SET.add("java.awt.image.BufferedImage");
FILTER_SET.add("sun.awt.AppContext");
FILTER_SET.add("com.fr.poly.creator.ECBlockCreator");
FILTER_SET.add("io.netty.channel.nio.SelectedSelectionKeySet");
}
@Override
public boolean accept(String s) {
return FILTER_SET.contains(s);
}
}

14
designer-base/src/main/java/com/fr/design/mod/bean/ChangeItem.java

@ -0,0 +1,14 @@
package com.fr.design.mod.bean;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/28
*/
public enum ChangeItem {
TABLE_DATA_NAME,
WIDGET_NAME
}

33
designer-base/src/main/java/com/fr/design/mod/bean/ContentChangeItem.java

@ -0,0 +1,33 @@
package com.fr.design.mod.bean;
import java.util.Map;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/28
*/
public class ContentChangeItem {
private final Map<String, String> changeMap;
private final ChangeItem changeItem;
private final Object object;
public ContentChangeItem(Map<String, String> changeMap,Object object, ChangeItem changeItem) {
this.changeMap = changeMap;
this.changeItem = changeItem;
this.object = object;
}
public Map<String, String> getChangeMap() {
return changeMap;
}
public ChangeItem getChangeItem() {
return changeItem;
}
public Object getObject() {
return object;
}
}

13
designer-base/src/main/java/com/fr/design/mod/event/ModifyEvent.java

@ -0,0 +1,13 @@
package com.fr.design.mod.event;
import com.fr.design.mod.bean.ContentChangeItem;
import com.fr.event.Event;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/28
*/
public class ModifyEvent implements Event<ContentChangeItem> {
}

12
designer-base/src/main/java/com/fr/design/mod/event/TableDataModifyEvent.java

@ -0,0 +1,12 @@
package com.fr.design.mod.event;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/28
*/
public class TableDataModifyEvent extends ModifyEvent {
public static final TableDataModifyEvent INSTANCE = new TableDataModifyEvent();
}

12
designer-base/src/main/java/com/fr/design/mod/event/WidgetNameModifyEvent.java

@ -0,0 +1,12 @@
package com.fr.design.mod.event;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/28
*/
public class WidgetNameModifyEvent extends ModifyEvent {
public static final WidgetNameModifyEvent INSTANCE = new WidgetNameModifyEvent();
}

16
designer-base/src/main/java/com/fr/design/mod/impl/change/ChartHyperRelateCellLinkContentChange.java

@ -0,0 +1,16 @@
package com.fr.design.mod.impl.change;
import com.fr.chart.web.ChartHyperRelateCellLink;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/28
*/
public class ChartHyperRelateCellLinkContentChange extends ChartHyperRelateLinkContentChange {
@Override
public String type() {
return ChartHyperRelateCellLink.class.getName();
}
}

16
designer-base/src/main/java/com/fr/design/mod/impl/change/ChartHyperRelateFloatLinkContentChange.java

@ -0,0 +1,16 @@
package com.fr.design.mod.impl.change;
import com.fr.chart.web.ChartHyperRelateFloatLink;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/28
*/
public class ChartHyperRelateFloatLinkContentChange extends ChartHyperRelateLinkContentChange{
@Override
public String type() {
return ChartHyperRelateFloatLink.class.getName();
}
}

30
designer-base/src/main/java/com/fr/design/mod/impl/change/ChartHyperRelateLinkContentChange.java

@ -0,0 +1,30 @@
package com.fr.design.mod.impl.change;
import com.fr.chart.web.ChartHyperRelateLink;
import com.fr.design.mod.ContentChange;
import com.fr.design.mod.ContentReplacer;
import com.fr.design.mod.bean.ChangeItem;
import com.fr.design.mod.impl.repalce.ChartHyperRelateLink4WidgetNameContentReplacer;
import java.util.HashMap;
import java.util.Map;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/27
*/
public abstract class ChartHyperRelateLinkContentChange implements ContentChange<ChartHyperRelateLink> {
private final Map<ChangeItem, ContentReplacer<ChartHyperRelateLink>> map;
public ChartHyperRelateLinkContentChange() {
this.map = new HashMap<>();
map.put(ChangeItem.WIDGET_NAME, new ChartHyperRelateLink4WidgetNameContentReplacer());
}
@Override
public Map<ChangeItem, ContentReplacer<ChartHyperRelateLink>> changeInfo() {
return map;
}
}

37
designer-base/src/main/java/com/fr/design/mod/impl/change/FormulaContentChange.java

@ -0,0 +1,37 @@
package com.fr.design.mod.impl.change;
import com.fr.base.Formula;
import com.fr.design.mod.ContentChange;
import com.fr.design.mod.ContentReplacer;
import com.fr.design.mod.bean.ChangeItem;
import com.fr.design.mod.impl.repalce.Formula4TableDataNameContentReplacer;
import com.fr.design.mod.impl.repalce.Formula4WidgetNameContentReplacer;
import java.util.HashMap;
import java.util.Map;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/27
*/
public class FormulaContentChange implements ContentChange<Formula> {
private final Map<ChangeItem, ContentReplacer<Formula>> map;
public FormulaContentChange() {
map = new HashMap<>();
map.put(ChangeItem.WIDGET_NAME, new Formula4WidgetNameContentReplacer());
map.put(ChangeItem.TABLE_DATA_NAME, new Formula4TableDataNameContentReplacer());
}
@Override
public String type() {
return Formula.class.getName();
}
@Override
public Map<ChangeItem, ContentReplacer<Formula>> changeInfo() {
return map;
}
}

36
designer-base/src/main/java/com/fr/design/mod/impl/change/JavaScriptContentChange.java

@ -0,0 +1,36 @@
package com.fr.design.mod.impl.change;
import com.fr.design.mod.ContentChange;
import com.fr.design.mod.ContentReplacer;
import com.fr.design.mod.bean.ChangeItem;
import com.fr.design.mod.impl.repalce.JavaScriptContentReplacer;
import com.fr.js.JavaScriptImpl;
import java.util.HashMap;
import java.util.Map;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/27
*/
public class JavaScriptContentChange implements ContentChange<JavaScriptImpl> {
private final Map<ChangeItem, ContentReplacer<JavaScriptImpl>> map;
public JavaScriptContentChange() {
map = new HashMap<>();
map.put(ChangeItem.WIDGET_NAME, new JavaScriptContentReplacer());
map.put(ChangeItem.TABLE_DATA_NAME, new JavaScriptContentReplacer());
}
@Override
public String type() {
return JavaScriptImpl.class.getName();
}
@Override
public Map<ChangeItem, ContentReplacer<JavaScriptImpl>> changeInfo() {
return map;
}
}

35
designer-base/src/main/java/com/fr/design/mod/impl/change/VanChartHtmlLabelContentChange.java

@ -0,0 +1,35 @@
package com.fr.design.mod.impl.change;
import com.fr.design.mod.ContentChange;
import com.fr.design.mod.ContentReplacer;
import com.fr.design.mod.bean.ChangeItem;
import com.fr.design.mod.impl.repalce.VanChartHtmlLabelContentReplacer;
import com.fr.plugin.chart.base.VanChartHtmlLabel;
import java.util.HashMap;
import java.util.Map;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/31
*/
public class VanChartHtmlLabelContentChange implements ContentChange<VanChartHtmlLabel> {
private final Map<ChangeItem, ContentReplacer<VanChartHtmlLabel>> map;
public VanChartHtmlLabelContentChange() {
map = new HashMap<>();
map.put(ChangeItem.WIDGET_NAME, new VanChartHtmlLabelContentReplacer());
map.put(ChangeItem.TABLE_DATA_NAME, new VanChartHtmlLabelContentReplacer());
}
@Override
public String type() {
return VanChartHtmlLabel.class.getName();
}
@Override
public Map<ChangeItem, ContentReplacer<VanChartHtmlLabel>> changeInfo() {
return map;
}
}

21
designer-base/src/main/java/com/fr/design/mod/impl/repalce/ChartHyperRelateLink4WidgetNameContentReplacer.java

@ -0,0 +1,21 @@
package com.fr.design.mod.impl.repalce;
import com.fr.chart.web.ChartHyperRelateLink;
import com.fr.design.mod.ContentReplacer;
import com.fr.general.ComparatorUtils;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/28
*/
public class ChartHyperRelateLink4WidgetNameContentReplacer implements ContentReplacer<ChartHyperRelateLink> {
@Override
public void replace(ChartHyperRelateLink chartHyperRelateLink, String oldName, String newName) {
if (ComparatorUtils.equals(chartHyperRelateLink.getRelateCCName(), oldName)) {
chartHyperRelateLink.setRelateCCName(newName);
}
}
}

22
designer-base/src/main/java/com/fr/design/mod/impl/repalce/Formula4TableDataNameContentReplacer.java

@ -0,0 +1,22 @@
package com.fr.design.mod.impl.repalce;
import com.fr.base.Formula;
import com.fr.design.mod.ContentReplaceUtil;
import com.fr.design.mod.ContentReplacer;
import com.fr.parser.FRFormulaTransformer;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/28
*/
public class Formula4TableDataNameContentReplacer implements ContentReplacer<Formula> {
@Override
public void replace(Formula formula, String oldName, String newName) {
FRFormulaTransformer frFormulaTransformer = new FRFormulaTransformer();
frFormulaTransformer.addRenamedDataset(oldName, newName);
formula.setContent(ContentReplaceUtil.EQ_STRING + frFormulaTransformer.transform(formula.getPureContent()));
}
}

21
designer-base/src/main/java/com/fr/design/mod/impl/repalce/Formula4WidgetNameContentReplacer.java

@ -0,0 +1,21 @@
package com.fr.design.mod.impl.repalce;
import com.fr.base.Formula;
import com.fr.design.mod.ContentReplaceUtil;
import com.fr.design.mod.ContentReplacer;
import com.fr.parser.FRFormulaTransformer;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/28
*/
public class Formula4WidgetNameContentReplacer implements ContentReplacer<Formula> {
@Override
public void replace(Formula formula, String oldName, String newName) {
FRFormulaTransformer frFormulaTransformer = new FRFormulaTransformer();
frFormulaTransformer.addRenamedWidget(oldName, newName);
formula.setContent(ContentReplaceUtil.EQ_STRING + frFormulaTransformer.transform(formula.getPureContent()));
}
}

22
designer-base/src/main/java/com/fr/design/mod/impl/repalce/JavaScriptContentReplacer.java

@ -0,0 +1,22 @@
package com.fr.design.mod.impl.repalce;
import com.fr.design.mod.ContentReplacer;
import com.fr.design.mod.ContentReplaceUtil;
import com.fr.js.JavaScriptImpl;
import com.fr.stable.StringUtils;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/28
*/
public class JavaScriptContentReplacer implements ContentReplacer<JavaScriptImpl> {
@Override
public void replace(JavaScriptImpl javaScript, String oldName, String newName) {
if (StringUtils.isNotEmpty(javaScript.getContent())) {
javaScript.setContent(ContentReplaceUtil.replaceContent(javaScript.getContent(), oldName, newName));
}
}
}

22
designer-base/src/main/java/com/fr/design/mod/impl/repalce/VanChartHtmlLabelContentReplacer.java

@ -0,0 +1,22 @@
package com.fr.design.mod.impl.repalce;
import com.fr.design.mod.ContentReplacer;
import com.fr.design.mod.ContentReplaceUtil;
import com.fr.plugin.chart.base.VanChartHtmlLabel;
import com.fr.stable.StringUtils;
/**
* @author hades
* @version 10.0
* Created by hades on 2021/5/31
*/
public class VanChartHtmlLabelContentReplacer implements ContentReplacer<VanChartHtmlLabel> {
@Override
public void replace(VanChartHtmlLabel vanChartHtmlLabel, String oldName, String newName) {
if (StringUtils.isNotEmpty(vanChartHtmlLabel.getCustomText())) {
vanChartHtmlLabel.setCustomText(
ContentReplaceUtil.replaceContent(vanChartHtmlLabel.getCustomText(), oldName, newName));
}
}
}

12
designer-form/src/main/java/com/fr/design/designer/beans/models/ModelUtil.java

@ -2,11 +2,17 @@ package com.fr.design.designer.beans.models;
import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XWParameterLayout; import com.fr.design.designer.creator.XWParameterLayout;
import com.fr.design.mod.bean.ChangeItem;
import com.fr.design.mod.bean.ContentChangeItem;
import com.fr.design.mod.event.WidgetNameModifyEvent;
import com.fr.event.EventDispatcher;
import com.fr.form.main.Form; import com.fr.form.main.Form;
import com.fr.form.ui.Widget; import com.fr.form.ui.Widget;
import com.fr.stable.StringUtils; import com.fr.stable.StringUtils;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
@ -25,10 +31,16 @@ abstract class ModelUtil {
Set<XCreator> nameRelatedCreators = new HashSet<>(); Set<XCreator> nameRelatedCreators = new HashSet<>();
//直接遍历出来目标值,然后按需处理 //直接遍历出来目标值,然后按需处理
xCreator.traversalNameRelatedXCreators(nameRelatedCreators); xCreator.traversalNameRelatedXCreators(nameRelatedCreators);
Map<String, String> renameMap = new HashMap<>();
for (XCreator target : nameRelatedCreators) { for (XCreator target : nameRelatedCreators) {
String uniqueName = uniqueName(form, target, duplicated); String uniqueName = uniqueName(form, target, duplicated);
String oldName = target.toData().getWidgetName();
if (StringUtils.isNotEmpty(oldName)) {
renameMap.put(oldName, uniqueName);
}
target.resetCreatorName(uniqueName); target.resetCreatorName(uniqueName);
} }
EventDispatcher.fire(WidgetNameModifyEvent.INSTANCE, new ContentChangeItem(renameMap, xCreator.toData(), ChangeItem.WIDGET_NAME));
} }
private static String uniqueName(Form form, XCreator xCreator, Set<String> duplicated) { private static String uniqueName(Form form, XCreator xCreator, Set<String> duplicated) {

1
designer-form/src/main/java/com/fr/design/designer/beans/models/SelectionModel.java

@ -25,6 +25,7 @@ import com.fr.design.fun.FormWidgetOptionProvider;
import com.fr.design.mainframe.FormDesigner; import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.FormSelection; import com.fr.design.mainframe.FormSelection;
import com.fr.design.mainframe.FormSelectionUtils; import com.fr.design.mainframe.FormSelectionUtils;
import com.fr.design.mainframe.share.encrypt.clipboard.impl.EncryptSelectionClipboardHandler;
import com.fr.design.utils.ComponentUtils; import com.fr.design.utils.ComponentUtils;
import com.fr.design.utils.gui.LayoutUtils; import com.fr.design.utils.gui.LayoutUtils;
import com.fr.general.ComparatorUtils; import com.fr.general.ComparatorUtils;

449
designer-form/src/main/java/com/fr/design/gui/controlpane/EventPropertyPane.java

@ -1,93 +1,30 @@
package com.fr.design.gui.controlpane; package com.fr.design.gui.controlpane;
import com.fr.design.beans.BasicBeanPane;
import com.fr.design.constants.UIConstants;
import com.fr.design.designer.creator.XCreator; import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.properties.EventPropertyTable; import com.fr.design.designer.properties.EventPropertyTable;
import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ilist.JNameEdList;
import com.fr.design.gui.ilist.ListModelElement;
import com.fr.design.gui.ilist.ModNameActionListener;
import com.fr.design.gui.ilist.UINameEdList;
import com.fr.design.i18n.Toolkit; import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.FormDesigner; import com.fr.design.mainframe.FormDesigner;
import com.fr.design.widget.EventCreator; import com.fr.design.widget.EventCreator;
import com.fr.form.event.Listener; import com.fr.form.event.Listener;
import com.fr.form.ui.Widget; import com.fr.form.ui.Widget;
import com.fr.general.NameObject; import com.fr.general.NameObject;
import com.fr.report.web.util.ReportEngineEventMapping;
import com.fr.stable.ArrayUtils;
import com.fr.stable.Nameable; import com.fr.stable.Nameable;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JPanel;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/** /**
* Created by kerry on 5/17/21 * Created by kerry on 5/17/21
*/ */
public class EventPropertyPane extends UIControlPane implements ListControlPaneProvider { public class EventPropertyPane extends UIListGroupControlPane {
private XCreator creator; private XCreator creator;
private boolean isPopulating = false;
private UINameEdList selectNameEdList;
private Map<String, EventListWrapperPane> nameEdListMap = new HashMap<>();
private CommonShortCutHandlers commonHandlers;
private ListControlPaneHelper helper;
private JPanel contentPane;
private FormDesigner designer; private FormDesigner designer;
private ListControlPaneHelper getHelper() {
if (helper == null) {
helper = ListControlPaneHelper.newInstance(this);
}
return helper;
}
private CommonShortCutHandlers getCommonHandlers() {
if (commonHandlers == null) {
commonHandlers = CommonShortCutHandlers.newInstance(this);
}
return commonHandlers;
}
public EventPropertyPane(FormDesigner designer) { public EventPropertyPane(FormDesigner designer) {
super(); super();
this.designer = designer; this.designer = designer;
} }
@Override
protected void initLeftPane(JPanel leftPane) {
leftPane.add(new UIScrollPane(contentPane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, FlowLayout.LEADING, 0, 0)), BorderLayout.CENTER);
}
/** /**
* 刷新 * 刷新
*/ */
@ -98,184 +35,19 @@ public class EventPropertyPane extends UIControlPane implements ListControlPaneP
.getSelection().getSelectedCreator(); .getSelection().getSelectedCreator();
} else { } else {
this.creator = null; this.creator = null;
contentPane.removeAll(); this.getContentPane().removeAll();
checkButtonEnabled(); checkButtonEnabled();
return; return;
} }
Widget widget = creator.toData(); Widget widget = creator.toData();
refreshPane(widget, EventCreator.createEventCreator(widget.supportedEvents(), EventPropertyTable.WidgetEventListenerUpdatePane.class));
refreshContentPane(widget.supportedEvents());
refreshNameableCreator(EventCreator.createEventCreator(widget.supportedEvents(), EventPropertyTable.WidgetEventListenerUpdatePane.class));
populateNameObjects();
} }
private void refreshContentPane(String[] supportedEvents) {
for (String event : supportedEvents) {
if (nameEdListMap.containsKey(event)) {
continue;
}
UINameEdList list = createJNameList(event);
EventListWrapperPane wrapperPane = new EventListWrapperPane(switchLang(event), list);
if (this.selectNameEdList == null) {
this.selectNameEdList = wrapperPane.getNameEdList();
}
contentPane.add(wrapperPane);
nameEdListMap.put(event, wrapperPane);
}
}
public void populateNameObjects() { public void populateNameObjects() {
Widget widget = creator.toData(); Widget widget = creator.toData();
populateNameObjects(widget);
ArrayList<NameObject> nameObjectList = new ArrayList<>();
for (int i = 0, size = widget.getListenerSize(); i < size; i++) {
Listener listener = widget.getListener(i);
if (!listener.isDefault()) {
nameObjectList.add(i, new NameObject(switchLang(listener.getEventName()) + (i + 1), listener));
}
}
populate(getHelper().processCatalog(nameObjectList));
checkButtonEnabled();
this.repaint();
}
public void populate(Map<String, List<NameObject>> map) {
isPopulating = true; // 加一个标识位,避免切换单元格时,触发 saveSettings
Iterator<Map.Entry<String, List<NameObject>>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, List<NameObject>> entry = iterator.next();
List<NameObject> valueList = entry.getValue();
EventListWrapperPane eventListWrapperPane = nameEdListMap.get(entry.getKey());
populateChildNameList(eventListWrapperPane.getNameEdList(), valueList.toArray(new NameObject[valueList.size()]));
}
this.checkButtonEnabled();
refreshEventListWrapperPane();
isPopulating = false;
}
private void refreshEventListWrapperPane() {
Iterator<Map.Entry<String, EventListWrapperPane>> iterator = nameEdListMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, EventListWrapperPane> entry = iterator.next();
EventListWrapperPane eventListWrapperPane = entry.getValue();
UINameEdList nameEdList = eventListWrapperPane.getNameEdList();
int listSize = nameEdList.getModel().getSize();
if (this.selectNameEdList.getModel().getSize() == 0 && listSize > 0) {
this.selectNameEdList = nameEdList;
}
eventListWrapperPane.setVisible(listSize > 0);
}
if (this.selectNameEdList != null) {
this.selectNameEdList.setSelectedIndex(0);
}
this.repaint();
}
private void populateChildNameList(UINameEdList nameableList, Nameable[] nameableArray) {
nameableList.getCellEditor().stopCellEditing();
DefaultListModel listModel = (DefaultListModel) nameableList.getModel();
listModel.removeAllElements();
if (ArrayUtils.isEmpty(nameableArray)) {
isPopulating = false;
return;
}
listModel.setSize(nameableArray.length);
for (int i = 0; i < nameableArray.length; i++) {
listModel.set(i, new ListModelElement(nameableArray[i]));
}
}
protected UINameEdList createJNameList(String text) {
UINameEdList nameEdList = new UINameEdList(new DefaultListModel()) {
@Override
protected void doAfterLostFocus() {
((JControlUpdatePane) controlUpdatePane).update();
}
@Override
protected void doAfterStopEditing() {
saveSettings();
}
};
nameEdList.setCellRenderer(new UINameableListCellRenderer(true, this.creators));
nameEdList.setName(text);
nameEdList.setSelectionBackground(UIConstants.ATTRIBUTE_PRESS);
nameEdList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
nameEdList.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
selectNameEdList = nameEdList;
updateUINameListSelect();
}
});
nameEdList.addMouseListener(getHelper().getListMouseListener(nameEdList, this));
nameEdList.addModNameActionListener(new ModNameActionListener() {
@Override
public void nameModed(int index, String oldName, String newName) {
saveSettings();
}
});
nameEdList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent evt) {
// richie:避免多次update和populate大大降低效率
if (!evt.getValueIsAdjusting()) {
// shoc 切换的时候加检验
if (hasInvalid(false)) {
return;
}
((JControlUpdatePane) EventPropertyPane.this.controlUpdatePane).update();
((JControlUpdatePane) EventPropertyPane.this.controlUpdatePane).populate();
EventPropertyPane.this.checkButtonEnabled();
}
}
});
nameEdList.getModel().addListDataListener(new ListDataListener() {
@Override
public void intervalAdded(ListDataEvent e) {
saveSettings();
}
@Override
public void intervalRemoved(ListDataEvent e) {
saveSettings();
}
@Override
public void contentsChanged(ListDataEvent e) {
saveSettings();
}
});
return nameEdList;
}
private void updateUINameListSelect() {
Iterator<Map.Entry<String, EventListWrapperPane>> iterator = nameEdListMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, EventListWrapperPane> entry = iterator.next();
UINameEdList nameEdList = entry.getValue().getNameEdList();
if (nameEdList != selectNameEdList) {
nameEdList.clearSelection();
}
}
}
@Override
public void checkButtonEnabled() {
getHelper().checkButtonEnabled();
}
private String switchLang(String eventName) {
// 在 properties 文件中找到相应的 key 值
String localeKey = ReportEngineEventMapping.getLocaleName(eventName);
return com.fr.design.i18n.Toolkit.i18nText(localeKey);
} }
/** /**
@ -296,98 +68,6 @@ public class EventPropertyPane extends UIControlPane implements ListControlPaneP
} }
/**
* 生成不重复的名字
*
* @param prefix 名字前缀
* @return 名字
*/
@Override
public String createUnrepeatedName(String prefix) {
return getCommonHandlers().createUnrepeatedName(prefix);
}
private void updateSelectedNameList(NameableCreator creator) {
String eventName = ((EventCreator) creator).getEventName();
EventListWrapperPane wrapperPane = nameEdListMap.get(eventName);
wrapperPane.setVisible(true);
setSelectNameEdList(wrapperPane.getNameEdList());
}
private void setSelectNameEdList(UINameEdList nameEdList) {
if (this.selectNameEdList != null) {
this.selectNameEdList.clearSelection();
}
this.selectNameEdList = nameEdList;
}
@Override
public void onAddItem(NameableCreator creator) {
updateSelectedNameList(creator);
getCommonHandlers().onAddItem(creator);
}
@Override
public void onRemoveItem() {
getCommonHandlers().onRemoveItem();
refreshEventListWrapperPane();
}
@Override
public void onCopyItem() {
getCommonHandlers().onCopyItem();
}
@Override
public void onMoveUpItem() {
getCommonHandlers().onMoveUpItem();
}
@Override
public void onMoveDownItem() {
getCommonHandlers().onMoveDownItem();
}
@Override
public void onSortItem(boolean isAtoZ) {
Iterator<Map.Entry<String, EventListWrapperPane>> iterator = nameEdListMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, EventListWrapperPane> entry = iterator.next();
UINameEdList nameEdList = entry.getValue().getNameEdList();
getCommonHandlers().onSortItem(isAtoZ, nameEdList);
}
}
@Override
public boolean isItemSelected() {
return getModel().getSize() > 0 && getSelectedIndex() != -1;
}
@Override
protected JPanel createControlUpdatePane() {
return JControlUpdatePane.newInstance(this);
}
@Override
public Nameable[] update() {
java.util.List<Nameable> res = new java.util.ArrayList<Nameable>();
getControlUpdatePane().update();
Iterator<Map.Entry<String, EventListWrapperPane>> iterator = nameEdListMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, EventListWrapperPane> entry = iterator.next();
UINameEdList nameEdList = entry.getValue().getNameEdList();
DefaultListModel listModel = (DefaultListModel) nameEdList.getModel();
for (int i = 0, len = listModel.getSize(); i < len; i++) {
res.add(((ListModelElement) listModel.getElementAt(i)).wrapper);
}
}
return res.toArray(new Nameable[0]);
}
@Override @Override
public NameableCreator[] createNameableCreators() { public NameableCreator[] createNameableCreators() {
return new NameableCreator[]{ return new NameableCreator[]{
@ -397,7 +77,7 @@ public class EventPropertyPane extends UIControlPane implements ListControlPaneP
@Override @Override
public void saveSettings() { public void saveSettings() {
if (isPopulating) { if (isPopulating()) {
return; return;
} }
updateWidgetListener(creator); updateWidgetListener(creator);
@ -413,123 +93,8 @@ public class EventPropertyPane extends UIControlPane implements ListControlPaneP
return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Add_Event"); return com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Add_Event");
} }
public BasicBeanPane createPaneByCreators(NameableCreator creator) { protected String getWrapperLabelText(){
try { return Toolkit.i18nText("Fine-Design_Report_Event");
return creator.getUpdatePane().newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public BasicBeanPane createPaneByCreators(NameableCreator creator, String string) {
Constructor constructor = null;
try {
constructor = creator.getUpdatePane().getDeclaredConstructor(new Class[]{String.class});
constructor.setAccessible(true);
return (BasicBeanPane) constructor.newInstance(string);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
@Override
public DefaultListModel getModel() {
if (this.selectNameEdList == null) {
return new DefaultListModel();
}
return (DefaultListModel) this.selectNameEdList.getModel();
}
/**
* 检查是否符合规范
*
* @throws Exception
*/
@Override
public void checkValid() throws Exception {
((JControlUpdatePane) this.controlUpdatePane).checkValid();
}
@Override
public boolean hasInvalid(boolean isAdd) {
return getHelper().hasInvalid(isAdd);
}
public void addNameable(Nameable nameable, int index) {
getHelper().addNameable(nameable, index);
popupEditDialog();
} }
/**
* 设置选中项
*
* @param index 选中项的序列号
*/
public void setSelectedIndex(int index) {
if (this.selectNameEdList != null) {
this.selectNameEdList.setSelectedIndex(index);
}
}
@Override
public int getSelectedIndex() {
if (this.selectNameEdList == null) {
return -1;
}
return this.selectNameEdList.getSelectedIndex();
}
@Override
public ListModelElement getSelectedValue() {
if (this.selectNameEdList == null) {
return null;
}
return (ListModelElement) this.selectNameEdList.getSelectedValue();
}
@Override
public JControlUpdatePane getControlUpdatePane() {
return (JControlUpdatePane) controlUpdatePane;
}
@Override
public JNameEdList getNameableList() {
return this.selectNameEdList;
}
private void popupEditDialog() {
getHelper().popupEditDialog(null, this.selectNameEdList, this);
}
private class EventListWrapperPane extends JPanel {
private UINameEdList nameEdList;
public EventListWrapperPane(String labelText, UINameEdList nameEdList) {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
UILabel label = new UILabel(labelText + Toolkit.i18nText("Fine-Design_Report_Event"));
label.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0));
label.setBackground(Color.decode("#FFFFFF"));
label.setPreferredSize(new Dimension(226, 26));
this.nameEdList = nameEdList;
this.add(label, BorderLayout.NORTH);
this.add(this.nameEdList, BorderLayout.CENTER);
}
public UINameEdList getNameEdList() {
return this.nameEdList;
}
}
} }

9
designer-form/src/main/java/com/fr/design/mainframe/FormCreatorDropTarget.java

@ -21,7 +21,11 @@ import com.fr.design.form.util.XCreatorConstants;
import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ibutton.UIButton;
import com.fr.design.icon.IconPathConstants; import com.fr.design.icon.IconPathConstants;
import com.fr.design.mainframe.chart.info.ChartInfoCollector; 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.design.utils.ComponentUtils;
import com.fr.event.EventDispatcher;
import com.fr.form.share.editor.SharableEditorProvider; import com.fr.form.share.editor.SharableEditorProvider;
import com.fr.form.share.SharableWidgetProvider; import com.fr.form.share.SharableWidgetProvider;
import com.fr.form.share.ShareLoader; import com.fr.form.share.ShareLoader;
@ -29,6 +33,7 @@ import com.fr.form.ui.Widget;
import com.fr.stable.Constants; import com.fr.stable.Constants;
import com.fr.stable.StringUtils; import com.fr.stable.StringUtils;
import java.util.Collections;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
import javax.swing.JWindow; import javax.swing.JWindow;
import java.util.List; import java.util.List;
@ -102,14 +107,16 @@ public class FormCreatorDropTarget extends DropTarget {
String shareId = addingXCreator.getShareId(); String shareId = addingXCreator.getShareId();
SharableEditorProvider sharableEditor = ShareLoader.getLoader().getSharedElCaseEditorById(shareId); SharableEditorProvider sharableEditor = ShareLoader.getLoader().getSharedElCaseEditorById(shareId);
SharableWidgetProvider bindInfo = ShareLoader.getLoader().getElCaseBindInfoById(shareId); SharableWidgetProvider bindInfo = ShareLoader.getLoader().getElCaseBindInfoById(shareId);
Map<String, String> tdNameMap = Collections.emptyMap();
if (sharableEditor != null && bindInfo != null) { if (sharableEditor != null && bindInfo != null) {
Map<String, String> tdNameMap = TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()).addTableData(bindInfo.getName(), sharableEditor.getTableDataSource(), true); tdNameMap = TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()).addTableData(bindInfo.getName(), sharableEditor.getTableDataSource(), true);
//合并数据集之后,可能会有数据集名称变化,做一下联动 //合并数据集之后,可能会有数据集名称变化,做一下联动
//共享的组件拿的时候都是克隆的,这边改拖拽中克隆的对象而非新克隆对象,上面这个新克隆的对象只是为了拿数据集 //共享的组件拿的时候都是克隆的,这边改拖拽中克隆的对象而非新克隆对象,上面这个新克隆的对象只是为了拿数据集
for (Map.Entry<String, String> entry : tdNameMap.entrySet()) { for (Map.Entry<String, String> entry : tdNameMap.entrySet()) {
designer.getTarget().renameTableData(widget, entry.getKey(), entry.getValue()); designer.getTarget().renameTableData(widget, entry.getKey(), entry.getValue());
} }
} }
EventDispatcher.fire(TableDataModifyEvent.INSTANCE, new ContentChangeItem(tdNameMap, widget, ChangeItem.TABLE_DATA_NAME));
} }
designer.getSelectionModel().setSelectedCreators( designer.getSelectionModel().setSelectedCreators(
FormSelectionUtils.rebuildSelection(xCreator, new Widget[]{widget})); FormSelectionUtils.rebuildSelection(xCreator, new Widget[]{widget}));

62
designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/AbstractCrossClipBoardState.java

@ -0,0 +1,62 @@
package com.fr.design.mainframe.share.encrypt.clipboard;
import com.fr.stable.StringUtils;
import java.util.concurrent.atomic.AtomicReference;
/**
* 跨模版禁用
* <p>
* created by Harrison on 2020/05/14
**/
public abstract class AbstractCrossClipBoardState implements CrossClipboardState {
private final AtomicReference<String> sourceId = new AtomicReference<>();
@Override
public synchronized boolean isBan() {
String sourceId = this.sourceId.get();
if (StringUtils.isEmpty(sourceId)) {
return false;
}
//这里只获取新的,不能更新
//因为新的模板可能不是限制模板,然而剪贴板中的内容没有清空。
//所以,直接在新的模板中再一次粘贴,就可以避过限制
String targetId = get();
return isCross(sourceId, targetId) && isRestrict(sourceId);
}
protected boolean isRestrict(String sourceId) {
return true;
}
@Override
public synchronized void mark() {
update();
}
private String get() {
return currentId();
}
private void update() {
String templateId = currentId();
sourceId.set(templateId);
}
private boolean isCross(String sourceId, String targetId) {
//源 id 不等于 null
//如果源 id 等于 null , 两种情况
//1-之前没有
//2-是从其他地方,复制过来,这样的话,直接通过就好了。
return StringUtils.isNotEmpty(sourceId)
&& !StringUtils.equals(sourceId, targetId);
}
protected abstract String currentId();
}

79
designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/CrossClipboardHandler.java

@ -0,0 +1,79 @@
package com.fr.design.mainframe.share.encrypt.clipboard;
import com.fr.design.fun.impl.AbstractClipboardHandlerProvider;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* created by Harrison on 2020/05/14
**/
public abstract class CrossClipboardHandler<T> extends AbstractClipboardHandlerProvider<T> {
private List<CrossClipboardState> states = new ArrayList<>(8);
public CrossClipboardHandler(CrossClipboardState... states) {
init(states);
}
private void init(CrossClipboardState... states) {
if (states == null) {
return;
}
Collections.addAll(this.states, states);
}
@Override
public T cut(T selection) {
mark();
return cut0(selection);
}
protected T cut0(T selection) {
return selection;
}
@Override
public T copy(T selection) {
mark();
return copy0(selection);
}
protected T copy0(T selection) {
return selection;
}
@Override
public T paste(T selection) {
return isBan() ? null : paste0(selection);
}
protected T paste0(T selection) {
return selection;
}
private void mark() {
for (CrossClipboardState state : states) {
state.mark();
}
}
private boolean isBan() {
boolean isBan = false;
for (CrossClipboardState state : states) {
isBan |= state.isBan();
}
return isBan;
}
}

22
designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/CrossClipboardState.java

@ -0,0 +1,22 @@
package com.fr.design.mainframe.share.encrypt.clipboard;
/**
* created by Harrison on 2020/05/18
**/
public interface CrossClipboardState {
/**
* 是否禁用
*
* @return y/n
*/
boolean isBan();
/**
* 标记状态
*/
void mark();
}

72
designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/RestrictTemplateSet.java

@ -0,0 +1,72 @@
package com.fr.design.mainframe.share.encrypt.clipboard;
import com.fr.form.main.Form;
import com.fr.form.main.WidgetUtil;
import com.fr.base.iofile.attr.EncryptSharableAttrMark;
import com.fr.form.ui.AbstractBorderStyleWidget;
import com.fr.form.ui.container.WLayout;
import com.fr.stable.fun.IOFileAttrMark;
import java.util.HashMap;
import java.util.Map;
/**
* created by Harrison on 2020/05/14
**/
public abstract class RestrictTemplateSet {
private static Map<String, Boolean> restrictMap = new HashMap<>(8);
public static void monitorGracefully(Form form) {
monitor(form, true);
}
public static void monitorForcefully(Form form) {
monitor(form, false);
}
private static void monitor(Form form, boolean useCache) {
String templateID = form.getTemplateID();
if (useCache) {
if (restrictMap.containsKey(templateID)) {
return;
}
}
//检测 + 缓存
monitor0(form);
}
private static void monitor0(Form form) {
final String templateID = form.getTemplateID();
WLayout container = form.getContainer();
WidgetUtil.bfsTraversalWidget(container, new WidgetUtil.BfsWidgetGather<AbstractBorderStyleWidget>() {
@Override
public boolean dealWith(AbstractBorderStyleWidget widget) {
IOFileAttrMark mark = widget.getWidgetAttrMark(EncryptSharableAttrMark.XML_TAG);
boolean existEncrypt = mark != null;
if (existEncrypt) {
restrictMap.put(templateID, existEncrypt);
}
return existEncrypt;
}
}, AbstractBorderStyleWidget.class);
initIfAbsent(templateID);
}
private static void initIfAbsent(String templateID) {
if (!restrictMap.containsKey(templateID)) {
restrictMap.put(templateID, false);
}
}
public static boolean isRestrict(String templateId) {
Boolean restrict = restrictMap.get(templateId);
return restrict == null ? false : restrict;
}
}

116
designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/TemplateStateListenerProvider.java

@ -0,0 +1,116 @@
package com.fr.design.mainframe.share.encrypt.clipboard;
import com.fr.base.io.BaseBook;
import com.fr.base.iofile.attr.ExtendSharableAttrMark;
import com.fr.design.DesignModelAdapter;
import com.fr.design.data.datapane.TableDataTreePane;
import com.fr.design.designer.beans.events.DesignerEvent;
import com.fr.design.designer.creator.XCreator;
import com.fr.design.designer.creator.XWTitleLayout;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.fun.impl.AbstractDesignerEditListenerProvider;
import com.fr.design.mainframe.JTemplate;
import com.fr.form.main.Form;
import com.fr.form.main.WidgetGatherAdapter;
import com.fr.form.share.SharableWidgetProvider;
import com.fr.form.share.editor.SharableEditorProvider;
import com.fr.form.share.utils.ShareUtils;
import com.fr.form.ui.AbstractBorderStyleWidget;
import com.fr.form.ui.Widget;
import com.fr.form.ui.container.WLayout;
import com.fr.general.ComparatorUtils;
import com.fr.stable.StringUtils;
import java.util.Iterator;
/**
* 创建删除的时候要初始化部分状态
* <p>
* created by Harrison on 2020/05/19
**/
public class TemplateStateListenerProvider extends AbstractDesignerEditListenerProvider {
public static final int CREATOR_ADDED = 1;
public static final int CREATOR_DELETED = 2;
private static final String SEPARATOR = "-";
private String lastAffectedCreatorShareID;
@Override
public void fireCreatorModified(DesignerEvent evt) {
int eventId = evt.getCreatorEventID();
if (eventId == CREATOR_ADDED || eventId == CREATOR_DELETED) {
JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
BaseBook book = template.getTarget();
if (book instanceof Form) {
Form form = (Form) book;
RestrictTemplateSet.monitorForcefully(form);
refreshTableDataTree(form, evt);
}
}
if (eventId == DesignerEvent.CREATOR_SELECTED) {
XCreator lastAffectedCreator = (XCreator) evt.getAffectedCreator();
if (lastAffectedCreator == null) {
return;
}
lastAffectedCreatorShareID = lastAffectedCreator.getShareId();
//做下兼容处理,有标题的老的组件其外层的creator上是没有shareID的,新生成的组件是有的
if (!lastAffectedCreator.acceptType(XWTitleLayout.class) || StringUtils.isNotEmpty(lastAffectedCreatorShareID)) {
return;
}
XCreator body = getBodyCreator((XWTitleLayout) lastAffectedCreator);
if (body != null) {
lastAffectedCreatorShareID = body.getShareId();
}
}
}
private XCreator getBodyCreator(XWTitleLayout titleLayout) {
for (int i = 0; i < titleLayout.getXCreatorCount(); i++) {
XCreator creator = titleLayout.getXCreator(i);
if (creator.hasTitleStyle()) {
return creator;
}
}
return null;
}
private void refreshTableDataTree(Form form, DesignerEvent evt) {
if (evt.getCreatorEventID() == DesignerEvent.CREATOR_DELETED && StringUtils.isNotEmpty(lastAffectedCreatorShareID)) {
if (!needDeleteTableData(form.getContainer(), lastAffectedCreatorShareID)) {
return;
}
//TODO 目前组件没版本号,可以直接遍历,之后可能还是要改的
SharableWidgetProvider bindInfo = ShareUtils.getElCaseBindInfoById(lastAffectedCreatorShareID);
SharableEditorProvider sharableEditor = ShareUtils.getSharedElCaseEditorById(lastAffectedCreatorShareID);
if (sharableEditor == null || bindInfo == null) {
return;
}
Iterator tdIterator = sharableEditor.getTableDataSource().getTableDataNameIterator();
while (tdIterator.hasNext()) {
String tdName = bindInfo.getName() + SEPARATOR + tdIterator.next();
TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()).removeTableData(tdName);
}
}
}
private boolean needDeleteTableData(WLayout widget, final String shareId) {
final boolean[] needDeleteTableData = {true};
Form.traversalWidget(widget, new WidgetGatherAdapter() {
@Override
public void dealWith(Widget widget) {
AbstractBorderStyleWidget borderStyleWidget = (AbstractBorderStyleWidget) widget;
ExtendSharableAttrMark attrMark = borderStyleWidget.getWidgetAttrMark(ExtendSharableAttrMark.XML_TAG);
if (attrMark != null) {
needDeleteTableData[0] &= !ComparatorUtils.equals(shareId, attrMark.getShareId());
}
}
}, AbstractBorderStyleWidget.class);
return needDeleteTableData[0];
}
}

86
designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/impl/CrossLayoutClipBoardState.java

@ -0,0 +1,86 @@
package com.fr.design.mainframe.share.encrypt.clipboard.impl;
import com.fr.base.io.BaseBook;
import com.fr.base.iofile.attr.ExtendSharableAttrMark;
import com.fr.design.designer.beans.models.SelectionModel;
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.file.HistoryTemplateListCache;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.FormSelection;
import com.fr.design.mainframe.WidgetPropertyPane;
import com.fr.form.main.Form;
import com.fr.design.mainframe.share.encrypt.clipboard.AbstractCrossClipBoardState;
import com.fr.base.iofile.attr.EncryptSharableAttrMark;
import com.fr.form.ui.AbstractBorderStyleWidget;
import com.fr.form.ui.container.WLayout;
import com.fr.stable.StringUtils;
import com.fr.stable.fun.IOFileAttrMark;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.atomic.AtomicReference;
/**
* 只需要看是否跨布局去粘贴
* <p>
* created by Harrison on 2020/06/04
**/
public class CrossLayoutClipBoardState extends AbstractCrossClipBoardState {
@Override
protected String currentId() {
//默认id
final AtomicReference<String> finalId = new AtomicReference<>(StringUtils.EMPTY);
WidgetPropertyPane pane = WidgetPropertyPane.getInstance();
FormDesigner designer = pane.getEditingFormDesigner();
if (designer == null) {
return null;
}
Form target = designer.getTarget();
BaseBook current = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getTarget();
//如果不是同一个
if (!StringUtils.equals(target.getTemplateID(), current.getTemplateID())) {
return null;
}
SelectionModel selectionModel = designer.getSelectionModel();
if (selectionModel == null) {
return null;
}
FormSelection selection = selectionModel.getSelection();
if (selection == null) {
return null;
}
XCreator[] xCreators = selection.getSelectedCreators();
if (xCreators != null) {
XCreator xCreator = xCreators[0];
if (StringUtils.isEmpty(finalId.get())) {
XLayoutContainer layout = XCreatorUtils.getParentXLayoutContainer(xCreator);
if (layout != null) {
WLayout wLayout = layout.toData();
String encryptWidgetId = findEncryptWidgetId(wLayout);
boolean hasId = StringUtils.isNotEmpty(encryptWidgetId);
if (hasId) {
finalId.set(encryptWidgetId);
}
}
}
}
return finalId.get();
}
@Nullable
private String findEncryptWidgetId(AbstractBorderStyleWidget widget) {
IOFileAttrMark widgetAttrMark = widget.getWidgetAttrMark(EncryptSharableAttrMark.XML_TAG);
boolean isEncrypt = widgetAttrMark != null;
if (isEncrypt) {
ExtendSharableAttrMark sharableAttrMark = widget.getWidgetAttrMark(ExtendSharableAttrMark.XML_TAG);
if (sharableAttrMark != null) {
return (sharableAttrMark.getShareId());
}
}
return null;
}
}

32
designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/impl/CrossTemplateClipBoardState.java

@ -0,0 +1,32 @@
package com.fr.design.mainframe.share.encrypt.clipboard.impl;
import com.fr.base.io.BaseBook;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mainframe.share.encrypt.clipboard.AbstractCrossClipBoardState;
import com.fr.design.mainframe.share.encrypt.clipboard.RestrictTemplateSet;
import com.fr.form.main.Form;
/**
* created by Harrison on 2020/05/18
**/
public class CrossTemplateClipBoardState extends AbstractCrossClipBoardState {
@Override
protected String currentId() {
JTemplate<?, ?> template = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate();
BaseBook book = template.getTarget();
if (book instanceof Form) {
Form form = (Form) book;
RestrictTemplateSet.monitorGracefully(form);
}
return book.getTemplateID();
}
@Override
protected boolean isRestrict(String sourceId) {
return RestrictTemplateSet.isRestrict(sourceId);
}
}

68
designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/impl/CrossWidgetClipBoardState.java

@ -0,0 +1,68 @@
package com.fr.design.mainframe.share.encrypt.clipboard.impl;
import com.fr.base.io.BaseBook;
import com.fr.base.iofile.attr.ExtendSharableAttrMark;
import com.fr.design.designer.beans.models.SelectionModel;
import com.fr.design.file.HistoryTemplateListCache;
import com.fr.design.mainframe.FormDesigner;
import com.fr.design.mainframe.FormSelection;
import com.fr.design.mainframe.WidgetPropertyPane;
import com.fr.design.mainframe.share.encrypt.clipboard.AbstractCrossClipBoardState;
import com.fr.form.main.Form;
import com.fr.form.main.WidgetUtil;
import com.fr.base.iofile.attr.EncryptSharableAttrMark;
import com.fr.form.ui.AbstractBorderStyleWidget;
import com.fr.form.ui.Widget;
import com.fr.stable.StringUtils;
import com.fr.stable.fun.IOFileAttrMark;
/**
* created by Harrison on 2020/05/18
**/
public class CrossWidgetClipBoardState extends AbstractCrossClipBoardState {
@Override
protected String currentId() {
final String[] finalIds = new String[]{null};
WidgetPropertyPane pane = WidgetPropertyPane.getInstance();
FormDesigner designer = pane.getEditingFormDesigner();
if (designer == null) {
return null;
}
Form target = designer.getTarget();
BaseBook current = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getTarget();
//如果不是同一个
if (!StringUtils.equals(target.getTemplateID(), current.getTemplateID())) {
return null;
}
SelectionModel selectionModel = designer.getSelectionModel();
if (selectionModel == null) {
return null;
}
FormSelection selection = selectionModel.getSelection();
if (selection == null) {
return null;
}
Widget[] selectedWidgets = selection.getSelectedWidgets();
if (selectedWidgets != null && selectedWidgets.length == 1) {
final Widget selectedWidget = selectedWidgets[0];
WidgetUtil.bfsTraversalWidget(selectedWidget, new WidgetUtil.BfsWidgetGather<AbstractBorderStyleWidget>() {
@Override
public boolean dealWith(AbstractBorderStyleWidget widget) {
IOFileAttrMark widgetAttrMark = widget.getWidgetAttrMark(EncryptSharableAttrMark.XML_TAG);
boolean isEncrypt = widgetAttrMark != null;
if (isEncrypt) {
ExtendSharableAttrMark sharableAttrMark = widget.getWidgetAttrMark(ExtendSharableAttrMark.XML_TAG);
if (sharableAttrMark != null) {
finalIds[0] = sharableAttrMark.getShareId();
}
}
return isEncrypt;
}
}, AbstractBorderStyleWidget.class);
}
return finalIds[0];
}
}

31
designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/impl/EncryptSelectionClipboardHandler.java

@ -0,0 +1,31 @@
package com.fr.design.mainframe.share.encrypt.clipboard.impl;
import com.fr.design.mainframe.FormSelection;
import com.fr.design.mainframe.share.encrypt.clipboard.CrossClipboardHandler;
/**
* 组件选择
* <p>
* created by Harrison on 2020/05/18
**/
public class EncryptSelectionClipboardHandler extends CrossClipboardHandler<FormSelection> {
private static EncryptSelectionClipboardHandler selectionClipboardHandler;
public static EncryptSelectionClipboardHandler getInstance() {
if (selectionClipboardHandler == null) {
selectionClipboardHandler = new EncryptSelectionClipboardHandler();
}
return selectionClipboardHandler;
}
public EncryptSelectionClipboardHandler() {
super(new CrossTemplateClipBoardState(), new CrossLayoutClipBoardState());
}
@Override
public boolean support(Object selection) {
return selection instanceof FormSelection;
}
}

32
designer-form/src/main/java/com/fr/design/mainframe/share/encrypt/clipboard/impl/EncryptTransferableClipboardHandler.java

@ -0,0 +1,32 @@
package com.fr.design.mainframe.share.encrypt.clipboard.impl;
import com.fr.design.mainframe.share.encrypt.clipboard.CrossClipboardHandler;
import java.awt.datatransfer.Transferable;
/**
* 单元格
* <p>
* created by Harrison on 2020/05/18
**/
public class EncryptTransferableClipboardHandler extends CrossClipboardHandler<Transferable> {
private static EncryptTransferableClipboardHandler transferableClipboardHandler;
public static EncryptTransferableClipboardHandler getInstance() {
if (transferableClipboardHandler == null) {
transferableClipboardHandler = new EncryptTransferableClipboardHandler();
}
return transferableClipboardHandler;
}
public EncryptTransferableClipboardHandler() {
super(new CrossTemplateClipBoardState(), new CrossWidgetClipBoardState());
}
@Override
public boolean support(Object selection) {
return selection instanceof Transferable;
}
}

132
designer-realize/src/main/java/com/fr/design/mainframe/app/DesignerAppUtils.java

@ -7,16 +7,24 @@ import com.fr.design.extra.exe.callback.ModifyStatusCallback;
import com.fr.design.i18n.Toolkit; import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerContext;
import com.fr.design.ui.util.UIUtil; import com.fr.design.ui.util.UIUtil;
import com.fr.io.TemplateIOErrorUtils; import com.fr.locale.InterProviderFactory;
import com.fr.plugin.context.PluginMarker; import com.fr.plugin.context.PluginMarker;
import com.fr.plugin.context.PluginMarkerAdapter; import com.fr.plugin.context.PluginMarkerAdapter;
import com.fr.plugin.engine.remote.PluginRemoteSync;
import com.fr.plugin.manage.PluginManager; import com.fr.plugin.manage.PluginManager;
import com.fr.plugin.manage.control.PluginControllerHelper; import com.fr.plugin.manage.control.PluginControllerHelper;
import com.fr.plugin.manage.control.PluginTask; import com.fr.plugin.manage.control.PluginTask;
import com.fr.stable.StringUtils;
import com.fr.stable.TemplateIOErrorContextHolder;
import com.fr.third.guava.cache.Cache;
import com.fr.third.guava.cache.CacheBuilder;
import com.fr.third.guava.collect.Multimap; import com.fr.third.guava.collect.Multimap;
import com.fr.workspace.WorkContext; import com.fr.workspace.WorkContext;
import java.time.Duration;
import java.util.Collection; import java.util.Collection;
import java.util.Map;
import java.util.stream.Collectors;
/** /**
* 设计器app共用工具类 * 设计器app共用工具类
@ -26,6 +34,118 @@ import java.util.Collection;
* Created by vito on 2021/5/27 * Created by vito on 2021/5/27
*/ */
public class DesignerAppUtils { public class DesignerAppUtils {
private static final int DEFAULT_MAX_CACHE_SIZE = 50;
private static final int DEFAULT_CONCURRENCY_LEVEL = 8;
private static final long DEFAULT_EXPIRE_HOURS = 1;
private static final Cache<String, Multimap<String, PluginMarkerAdapter>> ERROR_CACHE = CacheBuilder.newBuilder()
.maximumSize(DEFAULT_MAX_CACHE_SIZE)
.expireAfterAccess(Duration.ofHours(DEFAULT_EXPIRE_HOURS))
.concurrencyLevel(DEFAULT_CONCURRENCY_LEVEL)
.build();
/**
* 弹出指定的插件信息
* 并失效缓存
*
* @param key 指定key
* @return 插件安装信息
*/
public static Multimap<String, PluginMarkerAdapter> popPluginInfoMap(String key) {
Multimap<String, PluginMarkerAdapter> ifPresent = ERROR_CACHE.getIfPresent(key);
ERROR_CACHE.invalidate(key);
return ifPresent;
}
/**
* 失效指定的插件信息缓存
*
* @param key 指定key
*/
public static void invalidatePlugins(String key) {
ERROR_CACHE.invalidate(key);
}
/**
* 格式化多行插件错误信息详情并缓存
* 用于界面展示
*
* @param key 缓存key
* @return 格式化后的多行插件错误信息详情
*/
public static String dealWithErrorDetailMultiLineAndCache(String key) {
Multimap<String, PluginMarkerAdapter> pendingPlugins = TemplateIOErrorContextHolder.getPendingPlugin();
if (pendingPlugins.isEmpty()) {
return StringUtils.EMPTY;
}
dealWithRemote(pendingPlugins);
StringBuilder sb = new StringBuilder();
if (WorkContext.getCurrent().isLocal()) {
// 缓存等待后续处理
ERROR_CACHE.put(key, pendingPlugins);
}
Collection<PluginMarkerAdapter> unknownPlugins = pendingPlugins.get(TemplateIOErrorContextHolder.UNKNOWN_PLUGIN);
if (!unknownPlugins.isEmpty()) {
sb.append(InterProviderFactory.getProvider().getLocText("Fine-Core_Plugin_Error_UnknownPlugin")).append(":\n");
for (PluginMarkerAdapter pluginMarker : unknownPlugins) {
sb.append("\"").append(pluginMarker.getPluginID()).append("\"")
.append(InterProviderFactory.getProvider().getLocText("Fine-Dec_Platform_Plugin")).append('\n');
}
}
Collection<PluginMarkerAdapter> notInstalledPlugins = pendingPlugins.get(TemplateIOErrorContextHolder.NOT_INSTALLED_PLUGIN);
if (!notInstalledPlugins.isEmpty()) {
sb.append(InterProviderFactory.getProvider().getLocText("Fine-Core_Plugin_Error_UninstalledPlugins")).append(":\n");
for (PluginMarkerAdapter pluginMarker : notInstalledPlugins) {
sb.append("\"").append(pluginMarker.getPluginName()).append("\"")
.append(InterProviderFactory.getProvider().getLocText("Fine-Dec_Platform_Plugin")).append('\n');
}
}
Collection<PluginMarkerAdapter> disablePlugins = pendingPlugins.get(TemplateIOErrorContextHolder.DISABLE_PLUGIN);
if (!disablePlugins.isEmpty()) {
sb.append(InterProviderFactory.getProvider().getLocText("Fine-Core_Plugin_Error_InactivePlugins")).append(":\n");
for (PluginMarkerAdapter pluginMarker : disablePlugins) {
sb.append("\"").append(pluginMarker.getPluginName()).append("\"")
.append(InterProviderFactory.getProvider().getLocText("Fine-Dec_Platform_Plugin")).append('\n');
}
}
return sb.toString();
}
/**
* 远程环境下需要特殊处理远程服务器尚未安装的插件
*
* @param pendingPlugins 待处理插件
*/
private static void dealWithRemote(Multimap<String, PluginMarkerAdapter> pendingPlugins) {
if (!WorkContext.getCurrent().isLocal()) {
rearrange(pendingPlugins);
}
}
/**
* 远程设计重新整理下列表
*
* @param pendingPlugins 待处理列表
*/
public static void rearrange(Multimap<String, PluginMarkerAdapter> pendingPlugins) {
Map<String, PluginRemoteSync.PluginStatus> pluginRemoteStatusByIdIndex = PluginRemoteSync.getInstance().getPluginRemoteStatusByIdIndex();
Collection<PluginMarkerAdapter> unknownPlugins = pendingPlugins.get(TemplateIOErrorContextHolder.UNKNOWN_PLUGIN);
Collection<PluginMarkerAdapter> notInstall = pendingPlugins.get(TemplateIOErrorContextHolder.NOT_INSTALLED_PLUGIN);
Collection<PluginMarkerAdapter> disable = pendingPlugins.get(TemplateIOErrorContextHolder.DISABLE_PLUGIN);
unknownPlugins.removeIf(adapter -> pluginRemoteStatusByIdIndex.containsKey(adapter.getPluginID()));
// 本地未启用名单不准确添加到一起之后重新分配
notInstall.addAll(disable);
disable.clear();
// 从所有未安装中过滤远程未启用的,添加到未启用列表
disable.addAll(notInstall.stream().filter(plugin ->
pluginRemoteStatusByIdIndex.containsKey(plugin.getPluginID())
&& !pluginRemoteStatusByIdIndex.get(plugin.getPluginID()).isRunning())
.collect(Collectors.toList()));
// 清理未安装中所有远程安装过的插件(包含启用和未启用)
notInstall.removeIf(adapter -> pluginRemoteStatusByIdIndex.containsKey(adapter.getPluginID()));
}
/** /**
* 处理模板读取时的异常 * 处理模板读取时的异常
@ -34,7 +154,7 @@ public class DesignerAppUtils {
*/ */
public static void dealWithTemplateIOError(String path) { public static void dealWithTemplateIOError(String path) {
// 试图获取多行读取错误提示并缓存待处理列表 // 试图获取多行读取错误提示并缓存待处理列表
String detail = TemplateIOErrorUtils.dealWithErrorDetailMultiLineAndCache(path); String detail = dealWithErrorDetailMultiLineAndCache(path);
if (detail.length() > 0) { if (detail.length() > 0) {
UIUtil.invokeLaterIfNeeded(() -> { UIUtil.invokeLaterIfNeeded(() -> {
if (WorkContext.getCurrent().isLocal()) { if (WorkContext.getCurrent().isLocal()) {
@ -52,7 +172,7 @@ public class DesignerAppUtils {
@Override @Override
public void doCancel() { public void doCancel() {
TemplateIOErrorUtils.invalidatePlugins(path); invalidatePlugins(path);
} }
}).build().setVisible(true); }).build().setVisible(true);
} else { } else {
@ -68,13 +188,13 @@ public class DesignerAppUtils {
} }
private static void installAndEnablePlugin(String key) { private static void installAndEnablePlugin(String key) {
Multimap<String, PluginMarkerAdapter> stringPluginMarkerAdapterMultimap = TemplateIOErrorUtils.popPluginInfoMap(key); Multimap<String, PluginMarkerAdapter> stringPluginMarkerAdapterMultimap = popPluginInfoMap(key);
Collection<PluginMarkerAdapter> disablePlugins = stringPluginMarkerAdapterMultimap.get(TemplateIOErrorUtils.DISABLE_PLUGIN); Collection<PluginMarkerAdapter> disablePlugins = stringPluginMarkerAdapterMultimap.get(TemplateIOErrorContextHolder.DISABLE_PLUGIN);
for (PluginMarkerAdapter disablePlugin : disablePlugins) { for (PluginMarkerAdapter disablePlugin : disablePlugins) {
PluginManager.getController().enable(disablePlugin, new ModifyStatusCallback(false)); PluginManager.getController().enable(disablePlugin, new ModifyStatusCallback(false));
} }
Collection<PluginMarkerAdapter> uninstallPlugins = stringPluginMarkerAdapterMultimap.get(TemplateIOErrorUtils.NOT_INSTALLED_PLUGIN); Collection<PluginMarkerAdapter> uninstallPlugins = stringPluginMarkerAdapterMultimap.get(TemplateIOErrorContextHolder.NOT_INSTALLED_PLUGIN);
for (PluginMarker uninstallPlugin : uninstallPlugins) { for (PluginMarker uninstallPlugin : uninstallPlugins) {
PluginTask pluginTask = PluginTask.installTask(uninstallPlugin); PluginTask pluginTask = PluginTask.installTask(uninstallPlugin);
PluginControllerHelper.installOnline(uninstallPlugin, new InstallOnlineCallback(pluginTask)); PluginControllerHelper.installOnline(uninstallPlugin, new InstallOnlineCallback(pluginTask));

15
designer-realize/src/main/java/com/fr/design/mainframe/app/FormApp.java

@ -23,6 +23,7 @@ import com.fr.general.ComparatorUtils;
import com.fr.log.FineLoggerFactory; import com.fr.log.FineLoggerFactory;
import com.fr.stable.Constants; import com.fr.stable.Constants;
import com.fr.stable.bridge.StableFactory; import com.fr.stable.bridge.StableFactory;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap; import java.util.HashMap;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
@ -62,8 +63,7 @@ class FormApp extends AbstractAppProvider {
new Callable<OpenResult<Form, Parameter[]>>() { new Callable<OpenResult<Form, Parameter[]>>() {
@Override @Override
public OpenResult<Form, Parameter[]> call() throws Exception { public OpenResult<Form, Parameter[]> call() throws Exception {
Form form = asIOFile(tplFile); Form form = getForm(tplFile);
DesignerAppUtils.dealWithTemplateIOError(tplFile.getPath());
return new OpenResult<>(form, form.getParameters()); return new OpenResult<>(form, form.getParameters());
} }
}, emptyForm); }, emptyForm);
@ -84,8 +84,17 @@ class FormApp extends AbstractAppProvider {
return emptyForm; return emptyForm;
} else { } else {
return (JTemplate<Form, ?>) StableFactory.getMarkedInstanceObjectFromClass(BaseJForm.XML_TAG, return (JTemplate<Form, ?>) StableFactory.getMarkedInstanceObjectFromClass(BaseJForm.XML_TAG,
new Object[]{asIOFile(tplFile), tplFile}, classType, BaseJForm.class); new Object[]{getForm(tplFile), tplFile}, classType, BaseJForm.class);
}
}
@Nullable
private Form getForm(FILE tplFile) {
Form form = asIOFile(tplFile);
if (form != null) {
DesignerAppUtils.dealWithTemplateIOError(tplFile.getPath());
} }
return form;
} }
@Override @Override

5
designer-realize/src/main/java/com/fr/design/share/SharableInitManager.java

@ -1,11 +1,16 @@
package com.fr.design.share; package com.fr.design.share;
import com.fr.design.base.clipboard.ClipboardFilter;
import com.fr.design.mainframe.share.collect.SharableCollectorManager; import com.fr.design.mainframe.share.collect.SharableCollectorManager;
import com.fr.design.mainframe.share.encrypt.clipboard.impl.EncryptSelectionClipboardHandler;
import com.fr.design.mainframe.share.encrypt.clipboard.impl.EncryptTransferableClipboardHandler;
import com.fr.design.mainframe.share.util.SharableXMLUtils; import com.fr.design.mainframe.share.util.SharableXMLUtils;
public class SharableInitManager { public class SharableInitManager {
public static void start() { public static void start() {
SharableXMLUtils.registerSharableReadHelper(); SharableXMLUtils.registerSharableReadHelper();
SharableCollectorManager.getInstance().execute(); SharableCollectorManager.getInstance().execute();
ClipboardFilter.registerClipboardHandler(EncryptSelectionClipboardHandler.getInstance());
ClipboardFilter.registerClipboardHandler(EncryptTransferableClipboardHandler.getInstance());
} }
} }

75
designer-realize/src/main/java/com/fr/design/widget/WidgetEventPane.java

@ -1,10 +1,10 @@
package com.fr.design.widget; package com.fr.design.widget;
import java.util.ArrayList; import java.lang.reflect.Constructor;
import java.util.List; import com.fr.design.beans.BasicBeanPane;
import com.fr.design.gui.controlpane.UIListGroupControlPane;
import com.fr.design.gui.controlpane.ObjectUIControlPane; import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.CellWidgetPropertyPane; import com.fr.design.mainframe.CellWidgetPropertyPane;
import com.fr.design.write.submit.DBManipulationPane; import com.fr.design.write.submit.DBManipulationPane;
import com.fr.design.write.submit.SmartInsertDBManipulationInWidgetEventPane; import com.fr.design.write.submit.SmartInsertDBManipulationInWidgetEventPane;
@ -20,18 +20,20 @@ import com.fr.grid.selection.Selection;
import com.fr.general.NameObject; import com.fr.general.NameObject;
import com.fr.grid.selection.CellSelection; import com.fr.grid.selection.CellSelection;
import com.fr.stable.AssistUtils;
import com.fr.stable.Nameable; import com.fr.stable.Nameable;
import javax.swing.*; import javax.swing.*;
public class WidgetEventPane extends ObjectUIControlPane { public class WidgetEventPane extends UIListGroupControlPane {
private static final Selection NO_SELECTION = new CellSelection(-1, -1, -1, -1); private static final Selection NO_SELECTION = new CellSelection(-1, -1, -1, -1);
private Selection selection = NO_SELECTION; private Selection selection = NO_SELECTION;
private ElementCasePane object;
public WidgetEventPane(ElementCasePane pane) { public WidgetEventPane(ElementCasePane pane) {
super(pane); this.object = pane;
this.setNameListEditable(false);
if(pane != null){ if(pane != null){
selection = pane.getSelection(); selection = pane.getSelection();
} }
@ -123,19 +125,7 @@ public class WidgetEventPane extends ObjectUIControlPane {
if (widget == null) { if (widget == null) {
return; return;
} }
refreshPane(widget, EventCreator.createEventCreator(widget.supportedEvents(), WidgetEventListenerUpdatePane.class));
this.refreshNameableCreator(EventCreator.createEventCreator(widget.supportedEvents(), WidgetEventListenerUpdatePane.class));
List<NameObject> list = new ArrayList<NameObject>();
Listener listener;
for (int i = 0, size = widget.getListenerSize(); i < size; i++) {
listener = widget.getListener(i);
if (!listener.isDefault()) //name+(i+1)需要确保名字不重复
{
list.add(new NameObject(EventCreator.switchLang(listener.getEventName()) + (i + 1), listener));
}
}
this.populate(list.toArray(new NameObject[list.size()]));
} }
/** /**
@ -150,4 +140,49 @@ public class WidgetEventPane extends ObjectUIControlPane {
} }
return res_array; return res_array;
} }
@Override
public BasicBeanPane createPaneByCreators(NameableCreator creator) {
try {
if (object == null) {
return super.createPaneByCreators(creator);
} else if (object.getClass().isArray()) {
return creator.getUpdatePane().getConstructor(object.getClass()).newInstance(object);
} else {
Constructor<? extends BasicBeanPane> constructor = getConstructor(creator.getUpdatePane(), object.getClass());
return constructor == null ? super.createPaneByCreators(creator) : constructor.newInstance(object);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 传进BasicBeanPane的构造函数的参数可能是
*
* @param clazz
* @param cls
* @return
*/
private Constructor<? extends BasicBeanPane> getConstructor(Class<? extends BasicBeanPane> clazz, Class<?> cls) {
Constructor<? extends BasicBeanPane> constructor = null;
try {
constructor = clazz.getConstructor(cls);
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
}
if (constructor != null) {
return constructor;
} else {
if (AssistUtils.equals(cls.getName(),Object.class.getName())) {
return null;
}
return getConstructor(clazz, cls.getSuperclass());
}
}
protected String getWrapperLabelText(){
return Toolkit.i18nText("Fine-Design_Report_Event");
}
} }

2
designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java

@ -57,6 +57,7 @@ import com.fr.design.mainframe.form.FormReportComponentComposite;
import com.fr.design.mainframe.loghandler.DesignerLogAppender; import com.fr.design.mainframe.loghandler.DesignerLogAppender;
import com.fr.design.mainframe.share.constants.ShareEntryKey; import com.fr.design.mainframe.share.constants.ShareEntryKey;
import com.fr.design.mainframe.socketio.DesignerSocketIO; import com.fr.design.mainframe.socketio.DesignerSocketIO;
import com.fr.design.mod.ContentReplacerCenter;
import com.fr.design.module.DesignModuleFactory; import com.fr.design.module.DesignModuleFactory;
import com.fr.design.os.impl.SupportOSImpl; import com.fr.design.os.impl.SupportOSImpl;
import com.fr.design.parameter.FormParameterReader; import com.fr.design.parameter.FormParameterReader;
@ -162,6 +163,7 @@ public class DesignerActivator extends Activator {
storePassport(); storePassport();
AlphaFineHelper.switchConfig4Locale(); AlphaFineHelper.switchConfig4Locale();
RecoverManager.register(new RecoverForDesigner()); RecoverManager.register(new RecoverForDesigner());
ContentReplacerCenter.getInstance().register();
pushUpdateTask.run(); pushUpdateTask.run();
} }

106
designer-realize/src/test/java/com/fr/design/mainframe/app/DesignerAppUtilsTest.java

@ -0,0 +1,106 @@
package com.fr.design.mainframe.app;
import com.fr.invoke.Reflect;
import com.fr.plugin.context.PluginMarker;
import com.fr.plugin.context.PluginMarkerAdapter;
import com.fr.plugin.engine.remote.PluginRemoteSync;
import com.fr.stable.TemplateIOErrorContextHolder;
import com.fr.third.guava.collect.Multimap;
import org.easymock.EasyMock;
import org.junit.Assert;
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.Collection;
import java.util.HashMap;
import java.util.HashSet;
/**
* @author vito
* @version 10.0
* Created by vito on 2021/5/31
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({PluginRemoteSync.class})
public class DesignerAppUtilsTest {
@Test
public void testDealWithErrorDetailMultiLineAndCache() {
TemplateIOErrorContextHolder.registerPluginNameMap(new HashMap<String, String>() {{
put("2", "好用的插件");
}},new HashSet<>());
TemplateIOErrorContextHolder.addNeedEnablePlugin(PluginMarkerAdapter.create("1", "1.0", "1插件"));
TemplateIOErrorContextHolder.addNeedInstallPlugin(PluginMarker.create("2", "1.0"));
TemplateIOErrorContextHolder.addNeedInstallPlugin(PluginMarker.create("3", "1.0"));
String log = DesignerAppUtils.dealWithErrorDetailMultiLineAndCache("template1");
Assert.assertTrue(log.contains("1插件"));
Assert.assertTrue(log.contains("好用的插件"));
Assert.assertTrue(log.contains("3"));
Multimap<String, PluginMarkerAdapter> map = DesignerAppUtils.popPluginInfoMap("template1");
Assert.assertEquals(3, map.size());
Assert.assertNull(DesignerAppUtils.popPluginInfoMap("template1"));
}
@Test
public void testInvalidatePlugins() {
TemplateIOErrorContextHolder.registerPluginNameMap(new HashMap<String, String>() {{
put("2", "好用的插件");
}},new HashSet<>());
TemplateIOErrorContextHolder.addNeedEnablePlugin(PluginMarkerAdapter.create("1", "1.0", "1插件"));
TemplateIOErrorContextHolder.addNeedInstallPlugin(PluginMarker.create("2", "1.0"));
TemplateIOErrorContextHolder.addNeedInstallPlugin(PluginMarker.create("3", "1.0"));
String log = DesignerAppUtils.dealWithErrorDetailMultiLineAndCache("template1");
Assert.assertTrue(log.contains("1插件"));
Assert.assertTrue(log.contains("好用的插件"));
Assert.assertTrue(log.contains("3"));
DesignerAppUtils.invalidatePlugins("template1");
Assert.assertNull(DesignerAppUtils.popPluginInfoMap("template1"));
}
@Test
public void testRearrange(){
// 远程插件模拟注册
PluginRemoteSync pluginRemoteSync = EasyMock.createMock(PluginRemoteSync.class);
EasyMock.expect(pluginRemoteSync.getPluginRemoteStatusByIdIndex()).andReturn(new HashMap<String, PluginRemoteSync.PluginStatus>(){{
put("com.fr.plugin1", Reflect.on(PluginRemoteSync.PluginStatus.class).call("create","com.fr.plugin1","1",true).get());
put("com.fr.plugin2", Reflect.on(PluginRemoteSync.PluginStatus.class).call("create","com.fr.plugin2","1",true).get());
put("com.fr.plugin3", Reflect.on(PluginRemoteSync.PluginStatus.class).call("create","com.fr.plugin3","1",false).get());
put("com.fr.plugin4", Reflect.on(PluginRemoteSync.PluginStatus.class).call("create","com.fr.plugin4","1",false).get());
}}).anyTimes();
EasyMock.replay(pluginRemoteSync);
PowerMock.mockStaticPartial(PluginRemoteSync.class, "getInstance");
EasyMock.expect(PluginRemoteSync.getInstance()).andReturn(pluginRemoteSync).anyTimes();
PowerMock.replay(PluginRemoteSync.class);
// 本地插件模拟检查
TemplateIOErrorContextHolder.registerPluginNameMap(new HashMap<String, String>() {{
put("com.fr.plugin1", "好用的插件1");
put("com.fr.plugin2", "好用的插件2");
put("com.fr.plugin3", "好用的插件3");
put("com.fr.plugin4", "好用的插件4");
put("com.fr.plugin5", "好用的插件5");
}},new HashSet<>());
// unknown
TemplateIOErrorContextHolder.addNeedInstallPlugin(PluginMarker.create("com.fr.plugin7", "1"));
// disable
TemplateIOErrorContextHolder.addNeedEnablePlugin(PluginMarkerAdapter.create("com.fr.plugin5", "1", "plugin5"));
TemplateIOErrorContextHolder.addNeedInstallPlugin(PluginMarker.create("com.fr.plugin3", "1"));
// not install
TemplateIOErrorContextHolder.addNeedInstallPlugin(PluginMarker.create("com.fr.plugin1", "1"));
TemplateIOErrorContextHolder.addNeedInstallPlugin(PluginMarker.create("com.fr.plugin4", "1"));
Multimap<String, PluginMarkerAdapter> pendingPlugins = TemplateIOErrorContextHolder.getPendingPlugin();
Reflect.on(DesignerAppUtils.class).call("rearrange",pendingPlugins).get();
Assert.assertEquals(1,pendingPlugins.get(TemplateIOErrorContextHolder.UNKNOWN_PLUGIN).size());
Collection<PluginMarkerAdapter> pluginMarkerAdapters = pendingPlugins.get(TemplateIOErrorContextHolder.DISABLE_PLUGIN);
Assert.assertEquals(2, pluginMarkerAdapters.size());
pluginMarkerAdapters.contains(PluginMarker.create("com.fr.plugin3", "1"));
pluginMarkerAdapters.contains(PluginMarker.create("com.fr.plugin4", "1"));
Collection<PluginMarkerAdapter> pluginMarkerAdapters1 = pendingPlugins.get(TemplateIOErrorContextHolder.NOT_INSTALLED_PLUGIN);
Assert.assertEquals(1, pluginMarkerAdapters1.size());
pluginMarkerAdapters1.contains(PluginMarker.create("com.fr.plugin5","1"));
}
}
Loading…
Cancel
Save