From ee0652e4eae2841f4c99d40cae1430488806ac24 Mon Sep 17 00:00:00 2001 From: yhq Date: Fri, 7 Apr 2023 06:48:10 +0800 Subject: [PATCH] create rep --- README.md | 5 + build.gradle | 126 ++ encrypt.xml | 13 + plugin.xml | 41 + .../com/fr/plugins/dsgroup/DSGroupDefine.java | 55 + .../dsgroup/GroupTableDataPaneListPane.java | 237 ++++ .../plugins/dsgroup/GroupTableDataTree.java | 774 ++++++++++ .../dsgroup/GroupTableDataTreeDragSource.java | 260 ++++ .../dsgroup/GroupTableDataTreePane.java | 1252 +++++++++++++++++ .../com/fr/plugins/dsgroup/LocaleFinder.java | 21 + .../fr/plugins/dsgroup/PaneActionType.java | 9 + .../fr/plugins/dsgroup/TableDataAware.java | 13 + .../dsgroup/TableDataPaneProcessorImpl.java | 37 + .../plugins/dsgroup/fun/DSGroupTableData.java | 172 +++ .../rpc/GroupStableKeyArgsProvider.java | 25 + .../dsgroup/rpc/GroupTableDataOperator.java | 13 + .../rpc/GroupTableDataOperatorImpl.java | 50 + .../fr/plugins/dsgroup/ui/DSGroupPane.java | 91 ++ .../plugins/dsgroup/locale/locale.properties | 9 + .../dsgroup/locale/locale_en_US.properties | 9 + .../dsgroup/locale/locale_zh_CN.properties | 9 + .../fr/plugins/dsgroup/ui/images/query.png | Bin 0 -> 215 bytes 22 files changed, 3221 insertions(+) create mode 100644 README.md create mode 100644 build.gradle create mode 100644 encrypt.xml create mode 100644 plugin.xml create mode 100644 src/main/java/com/fr/plugins/dsgroup/DSGroupDefine.java create mode 100644 src/main/java/com/fr/plugins/dsgroup/GroupTableDataPaneListPane.java create mode 100644 src/main/java/com/fr/plugins/dsgroup/GroupTableDataTree.java create mode 100644 src/main/java/com/fr/plugins/dsgroup/GroupTableDataTreeDragSource.java create mode 100644 src/main/java/com/fr/plugins/dsgroup/GroupTableDataTreePane.java create mode 100644 src/main/java/com/fr/plugins/dsgroup/LocaleFinder.java create mode 100644 src/main/java/com/fr/plugins/dsgroup/PaneActionType.java create mode 100644 src/main/java/com/fr/plugins/dsgroup/TableDataAware.java create mode 100644 src/main/java/com/fr/plugins/dsgroup/TableDataPaneProcessorImpl.java create mode 100644 src/main/java/com/fr/plugins/dsgroup/fun/DSGroupTableData.java create mode 100644 src/main/java/com/fr/plugins/dsgroup/rpc/GroupStableKeyArgsProvider.java create mode 100644 src/main/java/com/fr/plugins/dsgroup/rpc/GroupTableDataOperator.java create mode 100644 src/main/java/com/fr/plugins/dsgroup/rpc/GroupTableDataOperatorImpl.java create mode 100644 src/main/java/com/fr/plugins/dsgroup/ui/DSGroupPane.java create mode 100644 src/main/resources/com/fr/plugins/dsgroup/locale/locale.properties create mode 100644 src/main/resources/com/fr/plugins/dsgroup/locale/locale_en_US.properties create mode 100644 src/main/resources/com/fr/plugins/dsgroup/locale/locale_zh_CN.properties create mode 100644 src/main/resources/com/fr/plugins/dsgroup/ui/images/query.png diff --git a/README.md b/README.md new file mode 100644 index 0000000..8d0ea2e --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# com.fr.plugins.dsgroupForV10 + +10.0数据集分组 + +兼容11版本设计器 \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..788c47a --- /dev/null +++ b/build.gradle @@ -0,0 +1,126 @@ + +apply plugin: 'java' + + +ext { + /** + * 项目中依赖的jar的路径 + * 1.如果依赖的jar需要打包到zip中,放置在lib根目录下 + * 2.如果依赖的jar仅仅是编译时需要,防止在lib下子目录下即可 + */ + libPath = "$projectDir/../webroot/WEB-INF/lib" + + /** + * 是否对插件的class进行加密保护,防止反编译 + */ + guard = false + + def pluginInfo = getPluginInfo() + pluginPre = "fine-plugin" + pluginName = pluginInfo.id + pluginVersion = pluginInfo.version + + outputPath = "$projectDir/../webroot/WEB-INF/plugins/plugin-" + pluginName + "-"+pluginVersion+"/classes" +} + +group = 'com.fr.plugin' +version = '10.0' +sourceCompatibility = '8' + +sourceSets { + main { + java.outputDir = file(outputPath) + output.resourcesDir = file(outputPath) + } +} + +ant.importBuild("encrypt.xml") +//定义ant变量 +ant.projectDir = projectDir +ant.references["compile.classpath"] = ant.path { + fileset(dir: libPath, includes: '**/*.jar') + fileset(dir: ".",includes:"**/*.jar" ) +} + +classes.dependsOn('clean') + +task copyFiles(type: Copy,dependsOn: 'classes'){ + from outputPath + into "$projectDir/classes" +} + +task preJar(type:Copy,dependsOn: guard ? 'compile_encrypt_javas' : 'compile_plain_javas'){ + from "$projectDir/classes" + into "$projectDir/transform-classes" + include "**/*.*" +} +jar.dependsOn("preJar") + +task makeJar(type: Jar,dependsOn: preJar){ + from fileTree(dir: "$projectDir/transform-classes") + baseName pluginPre + appendix pluginName + version pluginVersion + destinationDir = file("$buildDir/libs") + + doLast(){ + delete file("$projectDir/classes") + delete file("$projectDir/transform-classes") + } +} + +task copyFile(type: Copy,dependsOn: ["makeJar"]){ + from "$buildDir/libs" + from("$projectDir/lib") { + include "*.jar" + } + from "$projectDir/plugin.xml" + into file("$buildDir/temp/plugin") +} + +task zip(type:Zip,dependsOn:["copyFile"]){ + from "$buildDir/temp/plugin" + destinationDir file("$buildDir/install") + baseName pluginPre + appendix pluginName + version pluginVersion +} + +//控制build时包含哪些文件,排除哪些文件 +processResources { +// exclude everything +// 用*.css没效果 +// exclude '**/*.css' +// except this file +// include 'xx.xml' +} + +/*读取plugin.xml中的version*/ +def getPluginInfo(){ + def xmlFile = file("plugin.xml") + if (!xmlFile.exists()) { + return ["id":"none", "version":"1.0.0"] + } + def plugin = new XmlParser().parse(xmlFile) + def version = plugin.version[0].text() + def id = plugin.id[0].text() + return ["id":id,"version":version] +} + +repositories { + mavenLocal() + maven { + url = uri('http://mvn.finedevelop.com/repository/maven-public/') + } +} + +dependencies { + //使用本地jar + implementation fileTree(dir: 'lib', include: ['**/*.jar']) + implementation fileTree(dir: libPath, include: ['**/*.jar']) +} + +tasks.withType(JavaCompile) { + options.encoding = "UTF-8" +} + diff --git a/encrypt.xml b/encrypt.xml new file mode 100644 index 0000000..1401cd1 --- /dev/null +++ b/encrypt.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..e3d056e --- /dev/null +++ b/plugin.xml @@ -0,0 +1,41 @@ + + com.fr.plugins.dsgroupForV10.v11 + + yes + 1.0.0 + 11.0 + 2022-9-8 + phetran_ye + + + [2018-08-07]开始开发

+

[2019-07-23]修复拖动字段bug

+

[2020-06-14]服务器数据集适应新版本设计器

+

[2020-09-03]根据设计器更新

+

[2020-10-16]解决分组下的数据集编辑界面是分组编辑界面bug

+

[2020-11-12]解决服务器数据集分组无效bug

+

[2021-09-14]适配11.0

+

[2022-04-14]10.0服务器数据集保存逻辑修改

+

[2022-05-14]修改适配11.0的几个问题

+

[2022-09-15]修改适配11.0新版本

+

[2023-01-16]修改bug

+

[2023-03-14]修复bug

+

[2023-04-02]拆分11设计器版本

+ ]]> +
+ com.fr.plugins.dsgroup + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/src/main/java/com/fr/plugins/dsgroup/DSGroupDefine.java b/src/main/java/com/fr/plugins/dsgroup/DSGroupDefine.java new file mode 100644 index 0000000..5a4f5ea --- /dev/null +++ b/src/main/java/com/fr/plugins/dsgroup/DSGroupDefine.java @@ -0,0 +1,55 @@ +package com.fr.plugins.dsgroup; + +import com.fr.base.TableData; +import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; +import com.fr.design.fun.ServerTableDataDefineProvider; +import com.fr.design.fun.impl.AbstractTableDataDefineProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.general.Inter; +import com.fr.plugin.transform.ExecuteFunctionRecord; +import com.fr.plugin.transform.FunctionRecorder; +import com.fr.plugins.dsgroup.fun.DSGroupTableData; +import com.fr.plugins.dsgroup.ui.DSGroupPane; + +/** + * Created by phetran_ye on 2018/9/25. + */ +@FunctionRecorder +public class DSGroupDefine extends AbstractTableDataDefineProvider implements ServerTableDataDefineProvider { + + @Override + @ExecuteFunctionRecord + public Class classForTableData() { + //return null; + return DSGroupTableData.class; + } + + @Override + public Class classForInitTableData() { + //return null; + return DSGroupTableData.class; + } + + @Override + public Class appearanceForTableData() { + return DSGroupPane.class; + } + + @Override + public String nameForTableData() { + return Toolkit.i18nText("Data_Set_Group"); + } + + @Override + public String prefixForTableData() { + return "group"; + } + + + @Override + public String iconPathForTableData() { + return "/com/fr/plugins/dsgroup/ui/images/query.png"; + } + + +} diff --git a/src/main/java/com/fr/plugins/dsgroup/GroupTableDataPaneListPane.java b/src/main/java/com/fr/plugins/dsgroup/GroupTableDataPaneListPane.java new file mode 100644 index 0000000..3af2527 --- /dev/null +++ b/src/main/java/com/fr/plugins/dsgroup/GroupTableDataPaneListPane.java @@ -0,0 +1,237 @@ +package com.fr.plugins.dsgroup; + +import com.fr.base.TableData; +import com.fr.base.TableDataBean; +import com.fr.config.RemoteConfigEvent; +import com.fr.design.data.datapane.TableDataPaneListPane; +import com.fr.esd.event.DSMapping; +import com.fr.esd.event.DsNameTarget; +import com.fr.esd.event.StrategyEventsNotifier; +import com.fr.event.EventDispatcher; +import com.fr.file.*; +import com.fr.general.NameObject; +import com.fr.log.FineLoggerFactory; +import com.fr.plugins.dsgroup.fun.DSGroupTableData; +import com.fr.plugins.dsgroup.rpc.GroupTableDataOperator; +import com.fr.stable.Nameable; +import com.fr.stable.StringUtils; +import com.fr.third.org.apache.commons.collections4.MapUtils; +import com.fr.workspace.WorkContext; + + +import javax.swing.*; +import java.util.*; + +/** + * Created by phetran_ye on 2019-03-12. + * 服务器数据集修改弹窗 + */ +public class GroupTableDataPaneListPane extends TableDataPaneListPane { + + /** + * TableDataManagerPane下面有这个pane, + * 这个managerPane初始化的时候会将pane的rename方法覆盖 + * 下面新增的部分就是覆盖逻辑 + * 参考 TableDataManagerPane的initTableDataManagerPane方法 + * @param oldName + * @param newName + */ + @Override + public void rename(String oldName, String newName) { + super.rename(oldName, newName); + (new SwingWorker() { + @Override + protected Void doInBackground() { + StrategyEventsNotifier.modifyDataSet(new DSMapping[]{DSMapping.ofServerDS(new DsNameTarget(oldName))}); + return null; + } + }).execute(); + + + } + + + @Override + public void update(TableDataConfig dataConfig){ + Nameable[] tableDataArray = this.update(); + + //增加逻辑 + this.handleUpdateRelatedWithGroup(tableDataArray); + + final List tableDatas = new ArrayList(); + Map nameChangedMap = MapUtils.invertMap(this.getDsNameChangedMap()); + for(int i=0;i oldTableDataMap=config.getTableDatas(); + Map newTableDataMap=new HashMap<>(GroupTableDataTree.TABLE_DATA_SET_INITIAL_SIZE); + for(Nameable nameable:nameables){ + NameObject no=(NameObject) nameable; + newTableDataMap.put(no.getName(),(TableData)no.getObject()); + } + Map removedNormalTableDataMap=new HashMap<>(GroupTableDataTree.TABLE_DATA_SET_INITIAL_SIZE); + Map removedGroupTableDataMap=new HashMap<>(GroupTableDataTree.TABLE_DATA_SET_INITIAL_SIZE); + for(Map.Entry entry:oldTableDataMap.entrySet()){ + String name=entry.getKey(); + if(!super.getDsNameChangedMap().containsKey(name)&&!newTableDataMap.containsKey(name)){ + TableData tableData=entry.getValue(); + if(tableData instanceof DSGroupTableData){ + removedGroupTableDataMap.put(name,(DSGroupTableData)tableData); + }else{ + removedNormalTableDataMap.put(name,tableData); + } + } + } + //deal with changing names + for(Map.Entry entry:super.getDsNameChangedMap().entrySet()){ + String newName=entry.getValue(); + String oldName=entry.getKey(); + for(Nameable nameable:nameables){ + NameObject no=(NameObject) nameable; + TableData tableData=(TableData)no.getObject(); + if(tableData instanceof DSGroupTableData){ + DSGroupTableData groupData=(DSGroupTableData) tableData; + if(groupData.hasChild(oldName)){ + groupData.changeChildName(oldName,newName); + } + if(groupData.isChildOf(oldName)){ + groupData.setParentDSName(newName); + } + } + } + } + //deal with removing normal tabledata + for(Map.Entry entry:removedNormalTableDataMap.entrySet()){ + String removedName=entry.getKey(); + for(Nameable nameable:nameables){ + NameObject no=(NameObject) nameable; + TableData tableData=(TableData)no.getObject(); + if(tableData instanceof DSGroupTableData){ + DSGroupTableData groupData=(DSGroupTableData) tableData; + if(groupData.hasChild(removedName)){ + groupData.removeChild(removedName); + } + } + } + } + //deal with removing group tabledata + this.moveChildrenOfRemovedGroupToHigherGroup(removedGroupTableDataMap,newTableDataMap); + + + + + + + /*for(Map.Entry entry:super.getDsNameChangedMap().entrySet()){ + String newName=entry.getValue(); + String oldName=entry.getKey(); + String separator= DSGroupTableData.getSeparator(); + String newNameToReplaceWith=separator+newName+separator; + String oldNameToMatchWith=separator+oldName+separator; + for(Nameable nameable:nameables){ + TableData tableData=(TableData) ((NameObject)nameable).getObject(); + if(tableData instanceof DSGroupTableData){ + DSGroupTableData dsGroupTableData=(DSGroupTableData) tableData; + String childNodes=dsGroupTableData.getChildrenDSNames(); + if(childNodes!=null){ + childNodes=separator+childNodes+separator; + if(childNodes.indexOf(oldNameToMatchWith)>-1){ + childNodes=childNodes.replace(oldNameToMatchWith,newNameToReplaceWith).replaceAll("^"+separator+"{1}","").replaceAll(separator+"${1}",""); + dsGroupTableData.setChildrenDSNames(childNodes); + } + } + + String parentNode=dsGroupTableData.getParentDSName(); + if(oldName.equals(parentNode)){ + parentNode=newName; + dsGroupTableData.setParentDSName(parentNode); + } + } + } + }*/ + + } + + private void moveChildrenOfRemovedGroupToHigherGroup(Map removedGroupDataMap,Map finalTableDatas){ + while(removedGroupDataMap.size()>0){ + Set removedNames=new HashSet<>(); + for(Map.Entry group:removedGroupDataMap.entrySet()){ + boolean hasAnyChildGroupOfThisNotBeenHandled=false; + DSGroupTableData groupData=group.getValue(); + String removedName=group.getKey(); + if(groupData.hasChildren()){ + String children=groupData.getChildrenDSNames(); + String[] childNames=children.split(DSGroupTableData.getSeparator()); + for(String childName:childNames){ + if(removedGroupDataMap.containsKey(childName)){ + hasAnyChildGroupOfThisNotBeenHandled=true; + } + } + if(hasAnyChildGroupOfThisNotBeenHandled){ + continue; + } + + if(groupData.hasParent()){ + String parentName=groupData.getParentDSName(); + if(!removedGroupDataMap.containsKey(parentName)){ + //父类没被删除 + ((DSGroupTableData)finalTableDatas.get(parentName)).changeChildName(removedName,children); + }else{ + removedGroupDataMap.get(parentName).changeChildName(removedName,children); + } + } + + } + removedNames.add(removedName); + } + for(String name:removedNames){ + removedGroupDataMap.remove(name); + } + } + + + } + + /*@Override + public void update(TableDataConfig dataConfig){ + LinkedHashMap tableDatas = new LinkedHashMap(); + Nameable[] tableDataArray = this.update(); + for (int i = 0; i < tableDataArray.length; i++) { + NameObject nameObject = (NameObject) tableDataArray[i]; + if(changedDatas.containsKey(nameObject.getName())){ + tableDatas.put(nameObject.getName(),changedDatas.get(nameObject.getName())); + }else{ + tableDatas.put(nameObject.getName(), (TableData) nameObject.getObject()); + } + + } + dataConfig.setTableDatas(tableDatas); + changedDatas.clear(); + }*/ + + + } diff --git a/src/main/java/com/fr/plugins/dsgroup/GroupTableDataTree.java b/src/main/java/com/fr/plugins/dsgroup/GroupTableDataTree.java new file mode 100644 index 0000000..4af16e3 --- /dev/null +++ b/src/main/java/com/fr/plugins/dsgroup/GroupTableDataTree.java @@ -0,0 +1,774 @@ +package com.fr.plugins.dsgroup; + + +import com.fr.base.TableData; +import com.fr.base.TableDataBean; +import com.fr.config.RemoteConfigEvent; +import com.fr.config.utils.UniqueKey; +import com.fr.design.DesignModelAdapter; + +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.datapane.TableDataSourceOP; +import com.fr.design.data.datapane.TableDataTree; +import com.fr.design.editlock.EditLockUtils; +import com.fr.event.EventDispatcher; +import com.fr.file.*; +import com.fr.general.NameObject; +import com.fr.design.data.tabledata.wrapper.TableDataWrapper; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.log.FineLoggerFactory; +import com.fr.plugins.dsgroup.fun.DSGroupTableData; +import com.fr.plugins.dsgroup.rpc.GroupTableDataOperator; +import com.fr.report.LockItem; +import com.fr.stable.StringUtils; +import com.fr.workspace.WorkContext; +import javax.swing.tree.*; +import java.util.*; +import java.util.List; + +/** + * Created by phetran_ye on 2018/8/12. + * 都是继承TableDataTree,没有多态 + */ +public class GroupTableDataTree extends TableDataTree { + private static final long serialVersionUID = 1L; + + public static final int TABLE_DATA_SET_INITIAL_SIZE=4; + + private final int TEMPLATE_TABLE_DATA=0; + private final int SERVER_TABLE_DATA=1; + + private TableDataAware pane; + public void setPane(TableDataAware p){ + this.pane=p; + } + /** + * Constructor. + */ + + // CellRenderer + /* + 该属性会在父类构造方法里完成实例化 + private DefaultTreeCellRenderer tableDataTreeCellRenderer = new DefaultTreeCellRenderer() { + private static final long serialVersionUID = 1L; + + @Override + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { + super.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); + ExpandMutableTreeNode treeNode = (ExpandMutableTreeNode) value; + Object userObj = treeNode.getUserObject(); + if (userObj instanceof String) { + // p:这个是column field. + this.setIcon(BaseUtils.readIcon("com/fr/design/images/data/field.png")); + this.setText((String) userObj); + } else if (userObj instanceof NameObject) { + NameObject nameObject = (NameObject) userObj; + this.setText(nameObject.getName()); + if (nameObject.getObject() instanceof TableDataWrapper) { + TableDataWrapper tableDataWrappe = (TableDataWrapper) nameObject.getObject(); + this.setIcon(tableDataWrappe.getIcon()); + } else if (nameObject.getObject() instanceof Integer) { + int num = (Integer) nameObject.getObject(); + if (num == TableDataSourceOP.SERVER_TABLE_DATA) { + this.setIcon(BaseUtils.readIcon(IconPathConstants.STD_SHOW_ICON_PATH)); + } else if (num == TableDataSourceOP.STORE_PRECEDURE_DATA) { + this.setIcon(BaseUtils.readIcon(IconPathConstants.SP_SHOW_ICON_PATH)); + } else { + this.setIcon(BaseUtils.readIcon(IconPathConstants.DS_QUERY_ICON_PATH)); + } + } else { + this.setIcon(BaseUtils.readIcon("/com/fr/design/images/data/store_procedure.png")); + } + } else if (userObj == PENDING) { + this.setIcon(null); + this.setText(PENDING.toString()); + } + *//* + 11版本设计器更新220325 + // 这里新建一个Label作为render是因为JTree在动态刷新的时候,节点上render画布的的宽度不会变,会使得一部分比较长的数据显示为"..." + UILabel label = new UILabel(); + label.setText(getText()); + label.setIcon(getIcon()); + Dimension dim = label.getPreferredSize(); + dim.height += 2; + this.setSize(dim); + this.setPreferredSize(dim);*//* + this.setB + this.setBackgroundNonSelectionColor(UIConstants.TREE_BACKGROUND); + this.setTextSelectionColor(Color.WHITE); + this.setBackgroundSelectionColor(UIConstants.FLESH_BLUE); + return this; + } + }; + + public DefaultTreeCellRenderer getTableDataTreeCellRenderer() { + return tableDataTreeCellRenderer; + } + + public void setTableDataTreeCellRenderer(DefaultTreeCellRenderer tableDataTreeCellRenderer) { + this.tableDataTreeCellRenderer = tableDataTreeCellRenderer; + }*/ + + /* + 删除220325 + @Override + protected void refreshTreeNode(ExpandMutableTreeNode eTreeNode, String childName) { + if (interceptRefresh(eTreeNode)) { + return; + } + boolean refreshall = childName.isEmpty(); + ExpandMutableTreeNode[] new_nodes = loadChildTreeNodes(eTreeNode); + + List childTreeNodeList = new ArrayList<>(); + for (int i = 0, len = eTreeNode.getChildCount(); i < len; i++) { + if (eTreeNode.getChildAt(i) instanceof ExpandMutableTreeNode) { + childTreeNodeList.add((ExpandMutableTreeNode) eTreeNode.getChildAt(i)); + } else { + childTreeNodeList.add((DefaultMutableTreeNode) eTreeNode.getChildAt(i)); + } + } + + eTreeNode.removeAllChildren(); + + for (int ci = 0; ci < new_nodes.length; ci++) { + Object cUserObject = new_nodes[ci].getUserObject(); + ExpandMutableTreeNode cTreeNode = null; + for (int ni = 0, nlen = childTreeNodeList.size(); ni < nlen; ni++) { + cTreeNode = (ExpandMutableTreeNode) childTreeNodeList.get(ni); + if (ComparatorUtils.equals(cTreeNode.getUserObject(), cUserObject)) { + if (!refreshall && !ComparatorUtils.equals(childName, ((NameObject) cUserObject).getName())) { + new_nodes[ci] = cTreeNode; + break; + } + new_nodes[ci].setExpanded(cTreeNode.isExpanded()); + if (cTreeNode.getChildCount()>0 && cTreeNode.getFirstChild() instanceof ExpandMutableTreeNode && cTreeNode.isExpanded()) { + checkChildNodes(cTreeNode, new_nodes[ci]); + } + break; + } + } + + //eTreeNode.add(new_nodes[ci]); + } + loadTreeNode(eTreeNode); + }*/ + + + /* + * p:获得选中的NameObject = name + tabledata. + */ + @Override + public NameObject getSelectedNameObject() { + TreePath selectedTreePath = this.getSelectionPath(); + if (selectedTreePath == null) { + return null; + } + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + Object selectedUserObject = selectedTreeNode.getUserObject(); + ExpandMutableTreeNode parentTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + if(isGroupData(parentTreeNode)){ + return (NameObject) selectedUserObject; + } + Object parentUserObject = parentTreeNode.getUserObject(); + if (parentUserObject instanceof NameObject && ((NameObject) parentUserObject).getObject() instanceof Integer) { + if (selectedUserObject instanceof NameObject) { + return (NameObject) selectedUserObject; + } + } else { + parentTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + parentUserObject = parentTreeNode.getUserObject(); + + if (parentUserObject != null) { + if (!(parentUserObject instanceof NameObject)) { + return (NameObject) selectedUserObject; + } + /*//分组数据集下的子节点返回自身 + else if(isGroupData(selectedTreeNode)){ + return (NameObject) selectedUserObject; + }*/ + else { + return (NameObject) parentUserObject; + } + } + } + return null; + + } + + /* + 待验证能否删除 + public TableDataWrapper[] getSelectedDatas() { + TreePath[] selectedTreePaths = this.getSelectionPaths(); + if (selectedTreePaths == null || selectedTreePaths.length == 0) { + return null; + } + TableDataWrapper[] nameobjs = new TableDataWrapper[selectedTreePaths.length]; + for (int i = 0; i < selectedTreePaths.length; i++) { + TreePath selectedTreePath = selectedTreePaths[i]; + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + Object selectedUserObject = selectedTreeNode.getUserObject(); + ExpandMutableTreeNode parentTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + Object parentUserObject = parentTreeNode.getUserObject(); + if (parentUserObject instanceof NameObject && ((NameObject) parentUserObject).getObject() instanceof Integer) { + if (selectedUserObject instanceof NameObject) { + Object obj = ((NameObject) selectedUserObject).getObject(); + if (obj instanceof TableDataWrapper) { + nameobjs[i] = (TableDataWrapper) obj; + } + } + } else { + return new TableDataWrapper[0]; + } + } + + return nameobjs; + }*/ + + //删除待验证 + /*public NameObject getRealSelectedNameObject() { + TreePath selectedTreePath = this.getSelectionPath(); + if (selectedTreePath == null) { + return null; + } + + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) selectedTreePath.getLastPathComponent(); + Object selectedUserObject = selectedTreeNode.getUserObject(); + if (selectedUserObject instanceof NameObject) { + return (NameObject) selectedUserObject; + } + + selectedTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + selectedUserObject = selectedTreeNode.getUserObject(); + if (selectedUserObject instanceof NameObject) { + return (NameObject) selectedUserObject; + } + return null; + }*/ + + /** + * p:添加一个NameObject节点. + */ + //删除待验证 + /*public void addNameObject(NameObject no) { + if (no == null) { + return; + } + DefaultTreeModel treeModel = (DefaultTreeModel) this.getModel(); + + // 新建一个放着NameObject的newChildTreeNode,加到Root下面 + ExpandMutableTreeNode root = (ExpandMutableTreeNode) treeModel.getRoot(); + + ExpandMutableTreeNode newChildTreeNode = new ExpandMutableTreeNode(no); + root.add(newChildTreeNode); + newChildTreeNode.add(new ExpandMutableTreeNode()); + + treeModel.reload(root); + }*/ + + /** + * 覆盖方法,如果是根节点,返回根节点直接下级节点而不是父类的所有节点 + * @param node + * @return + */ + @Override + protected ExpandMutableTreeNode[] loadChildTreeNodes(ExpandMutableTreeNode node) { + DefaultTreeModel treeModel = (DefaultTreeModel) this.getModel(); + ExpandMutableTreeNode root = (ExpandMutableTreeNode) treeModel.getRoot(); + if(root.equals(node)){ + return this.loadChildNodesOfRoot(node); + }else{ + if(isGroupData(node)){ + DSGroupTableData ds=this.getGroupData(node); + if(!ds.hasChildren()){ + return new ExpandMutableTreeNode[0]; + } + ExpandMutableTreeNode[] allNodes=super.loadChildTreeNodes(root); + Map allNodesMap=new HashMap<>(TABLE_DATA_SET_INITIAL_SIZE); + for(ExpandMutableTreeNode nd:allNodes){ + allNodesMap.put(this.getDSName(nd),nd); + } + this.loadDSGroupTreeNode(node,allNodesMap,allNodesMap); + ExpandMutableTreeNode[] childNodes=new ExpandMutableTreeNode[node.getChildCount()]; + for(int i=0;i allNodesMap=new HashMap<>(TABLE_DATA_SET_INITIAL_SIZE); + Map rootChildrenMap=new HashMap<>(TABLE_DATA_SET_INITIAL_SIZE); + ExpandMutableTreeNode[] children = super.loadChildTreeNodes(root); + for(ExpandMutableTreeNode etn:children){ + allNodesMap.put(this.getDSName(etn),etn); + rootChildrenMap.put(getDSName(etn),etn); + } + for(ExpandMutableTreeNode etn:children){ + if(!rootChildrenMap.containsKey(this.getDSName(etn))){ + continue; + } + if(isGroupData(etn)){ + //去掉"正在加载" + if(((ExpandMutableTreeNode)etn.getFirstChild()).getUserObject() == PENDING){ + etn.remove(0); + } + if(getGroupData(etn).hasChildren()){ + loadDSGroupTreeNode(etn, allNodesMap,rootChildrenMap); + } + + } + } + if(rootChildrenMap.isEmpty()){ + return new ExpandMutableTreeNode[0]; + }else{ + ExpandMutableTreeNode[] result=new ExpandMutableTreeNode[rootChildrenMap.size()]; + return rootChildrenMap.values().toArray(result); + } + } + + public String getDSName(ExpandMutableTreeNode tn){ + return ((NameObject)tn.getUserObject()).getName(); + } + + public TableData getTableData(ExpandMutableTreeNode tn){ + return ((TableDataWrapper) ((NameObject)tn.getUserObject()).getObject()).getTableData(); + } + + public DSGroupTableData getGroupData(ExpandMutableTreeNode tn){ + return (DSGroupTableData)((TableDataWrapper) ((NameObject)tn.getUserObject()).getObject()).getTableData(); + } + + public static boolean isGroupData(ExpandMutableTreeNode tn){ + if(null==tn) { + return false; + } + if(!(tn.getUserObject() instanceof NameObject)){ + return false; + } + return ((TableDataWrapper) ((NameObject)tn.getUserObject()).getObject()).getTableData() instanceof DSGroupTableData; + } + + public static boolean nodeIsTableData(ExpandMutableTreeNode node){ + return (node.getUserObject() instanceof NameObject) && ( + ((NameObject)node.getUserObject()).getObject() instanceof TableDataWrapper + ); + } + + private void loadDSGroupTreeNode(ExpandMutableTreeNode groupNode,Map nodes,Map leftNodes){ + DSGroupTableData ds=this.getGroupData(groupNode); + if(!ds.hasChildren()){ + return; + } + if(groupNode.getChildCount()>0){ + groupNode.removeAllChildren(); + } + String[] nodeNames=ds.getChildrenDSNames().split(DSGroupTableData.getSeparator()); + //groupNode.removeAllChildren(); + //有父类的且有效的进行移除,最后不显示 + if(ds.hasParent()){ + //检查parent数据是否有效 + boolean validParent=true; + String parentDSName=ds.getParentDSName(); + if(!nodes.containsKey(parentDSName)){ + validParent=false; + }else{ + ExpandMutableTreeNode parentNode=nodes.get(parentDSName); + if(!isGroupData(parentNode)){ + validParent=false; + }else{ + validParent=getGroupData(parentNode).hasChild(ds.getName()); + } + } + + //有效的parent数据才会移除 + if(validParent){ + leftNodes.remove(ds.getName()); + } + } + + for(int i=0;i parentNodes=new HashSet<>(); + List nodesToMove=new ArrayList<>(); + ExpandMutableTreeNode root=(ExpandMutableTreeNode)(this.getModel()).getRoot(); + Map changedGroupTableDataMap=null; + if(global){ + changedGroupTableDataMap=new HashMap<>(TABLE_DATA_SET_INITIAL_SIZE); + } + //将选择的节点拼成子节点数据,以防止选择了分组又选择了其下的数据集 + for(int i=0;i changedDsGroupTableDatas=null; + if(global){ + changedDsGroupTableDatas=new HashMap<>(TABLE_DATA_SET_INITIAL_SIZE); + } + //待分组的节点的父节点,用于展开 + Set parentNodes=new HashSet<>(); + ExpandMutableTreeNode root=(ExpandMutableTreeNode)(this.getModel()).getRoot(); + int nodeToMoveCnt=0; + for(int i=0;i changedGroupTableDataMap){ + //参照GlobalTableDataAction actionPerform (弹出服务器数据集编辑面板,点确认后保存) + boolean lock = EditLockUtils.lock(LockItem.SERVER_TABLE_DATA); + //!LOCK + if (!lock) { + EditLockUtils.showLockMessage(); + }else{ + Map tableDatas=TableDataConfig.getInstance().getTableDatas(); + + //Nameable[] originalDS =new Nameable[tableDataMap.size()]; + List newTDBeans = new ArrayList<>(); + //貌似没用 + //List tdNames=new ArrayList<>(); + /*for(Map.Entry entry:tableDatas.entrySet()){ + String name=((NameObject)node.getUserObject()).getName(); + tdNames.add(name); + TableData tableData=((TableDataWrapper) ((NameObject)node.getUserObject()).getObject()).getTableData(); + ((UniqueKey)tableData).setNameSpace(null); + newTDBeans.add(new TableDataBean(name,StringUtils.EMPTY,tableData)); + }*/ + for(Map.Entry entry:tableDatas.entrySet()){ + String name=entry.getKey(); + newTDBeans.add(new TableDataBean(name,StringUtils.EMPTY, + changedGroupTableDataMap.containsKey(name)? changedGroupTableDataMap.get(name) :entry.getValue() + )); + } + //changedDsGroupTableDatas.clear(); + try { + WorkContext.getCurrent().get(GroupTableDataOperator.class).saveTableData(Collections.emptyList(),newTDBeans);//new ArrayList<>(tableDataMap.keySet()) + if (!WorkContext.getCurrent().isLocal()) { + EventDispatcher.fire(RemoteConfigEvent.EDIT, TableDataConfig.getInstance().getNameSpace()); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + DesignTableDataManager.clearGlobalDs(); + //貌似沒用待验证 + /*Iterator tdIterator = tdNames.iterator(); + + while(tdIterator.hasNext()) { + String var2 = (String)tdIterator.next(); + DesignTableDataManager.removeSelectedColumnNames(var2); + }*/ + GroupTableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()); + DesignTableDataManager.fireDSChanged(new HashMap<>()); + EditLockUtils.unlock(LockItem.SERVER_TABLE_DATA); + } + } + + + //从节点的父节点移除节点,如果父节点是分组还要修改分组数据集数据 + public void moveNodeOutOfParent(ExpandMutableTreeNode parent, ExpandMutableTreeNode nodeToMove){ + parent.remove(nodeToMove); + if(isGroupData(parent)){ + this.getGroupData(parent).removeChild(this.getDSName(nodeToMove)); + } + } + + /** + * 删除一个数据集节点 + * @param nodeToRemove + */ + public void removeNode(ExpandMutableTreeNode nodeToRemove){ + ExpandMutableTreeNode parent=this.getDsGroupParentNodeIfExists(nodeToRemove); + if(parent==null){ + //无上级分组并且本身是分组 + if(isGroupData(nodeToRemove)){ + for(int i=0;i names = new ArrayList(); + TableDataTree tree = (TableDataTree)comp; + TreePath[] paths = tree.getSelectionPaths(); + if (paths == null) { + return; + } + + this.doubleArray = null; + this.setnameArray(paths, names); + this.source.startDrag(dge, DragSource.DefaultLinkDrop, new ArrayTransferable(this.doubleArray), this); + } + } + + protected void setnameArray(TreePath[] paths, List stringList) { + for (int i = 0; i < paths.length; i++) { + if ((paths[i] == null) || (paths[i].getPathCount() <= 1)) { + return;// We can't move the root node or an empty selection + } + ExpandMutableTreeNode segmentMutableTreeNode = (ExpandMutableTreeNode) paths[i].getLastPathComponent(); + Object userObj = segmentMutableTreeNode.getUserObject(); + List tableAddress = new ArrayList(); + String displayName; + StringBuffer dsNameBuf = new StringBuffer(); + if (userObj instanceof NameObject) { + continue; + } else { + if (!(userObj instanceof String)) { + continue; + } + displayName = (String) userObj; + // james 读取表名 + //分组名不加 + while (!GroupTableDataTree.isGroupData((ExpandMutableTreeNode) segmentMutableTreeNode.getParent()) && segmentMutableTreeNode.getParent().getParent() != null) { + segmentMutableTreeNode = (ExpandMutableTreeNode) segmentMutableTreeNode.getParent(); + ExpandMutableTreeNode datasheetExpandMutableTreeNode = segmentMutableTreeNode; + Object parentUserObj = datasheetExpandMutableTreeNode.getUserObject(); + if (parentUserObj instanceof NameObject && !(((NameObject) parentUserObj).getObject() instanceof Integer)) { + NameObject nameObject = (NameObject) parentUserObj; + tableAddress.add(nameObject.getName()); + } + } + } + for (int j = tableAddress.size() - 1; j > -1; j--) { + dsNameBuf.append(tableAddress.get(j)); + if (j != 0) { + dsNameBuf.append('_'); + } + } + String dsName; + if (dsNameBuf.toString() != null) { + dsName = dsNameBuf.toString(); + } else { + return; + } + String[] attributes = {dsName, displayName}; + stringList.add(attributes); + Object[] bo = stringList.toArray(); + doubleArray = new String[bo.length][]; + for (int io = 0; io < bo.length; io++) { + if (bo[io] instanceof String[]) { + doubleArray[io] = (String[]) bo[io]; + } + } + } + } + + /*@Override + public void dragOver(DragSourceDragEvent dsde) { + DragSourceContext dsc = dsde.getDragSourceContext(); + Component comp=dsc.getComponent(); + TableDataTree tree = (TableDataTree) comp; + Point p=dsde.getLocation(); + if(null==orginPointInScreen){ + orginPointInScreen=p; + } + TreePath path = tree.getPathForLocation((int)(orginPoint.getX()+p.getX()-orginPointInScreen.getX()), + (int)(orginPoint.getY()+p.getY()-orginPointInScreen.getY())) ; + TreePath pt=tree.getPathForLocation((int)(p.getX()-tree.getBounds().getX()),(int)(p.getY()-tree.getBounds().getY())); + if(pt!=null){ + System.out.println("++++"+pt.getLastPathComponent().toString()); + } + + if(null==path){ + if(null!= groupToMoveTo){ + tree.removeSelectionPath(groupToMoveTo); + groupToMoveTo=null; + } + }else{ + //移入选择的分组是之前选中的节点之一不做任何处理 + TreePath[] paths=tree.getSelectionPaths(); + for(int i=0;i tc) { + singleton.tc = tc; + singleton.op = new TableDataSourceOP(tc); + singleton.op.setDataMode(singleton.buttonGroup.getSelectedIndex() == 0 ? TEMPLATE_TABLE_DATA : SERVER_TABLE_DATA); + singleton.refreshDockingView(); + + //数据集分组扩展 + WestRegionContainerPane wp=WestRegionContainerPane.getInstance(); + JComponent downPane=wp.getDownPane(); + if(downPane!=singleton) { + wp.replaceDownPane(singleton); + } + return singleton; + } + + private TableDataSourceOP op; + private GroupTableDataTree tableDataTree; + private UIPopupMenu popupMenu; + private EditAction editAction; + private RemoveAction removeAction; + private CopyAction copyAction; + private PasteAction pasteAction; + private EsdOnAction esdAction; + private EsdOffAction esdOffAction; + private SwitchAction switchAction; + private PreviewTableDataAction previewTableDataAction; + private JPanel serverDatasetAuthTipJPanel = new JPanel(); + + private TableDataSearchRemindPane remindPane; + private TreeSearchToolbarPane toolbarPane; + + private GroupTableDataTreePane() { + initPane(); + } + + private void initPane() { + this.setLayout(new BorderLayout(4, 0)); + this.setBorder(null); + + initTableDataTree(); + toolbarPane = initToolBarPane(); + JPanel treePane = initTreePane(); + dealWithTableDataTree(); + this.add(toolbarPane, BorderLayout.NORTH); + this.add(treePane, BorderLayout.CENTER); + checkButtonEnabled(); + } + + /** + * 数据集树面板 + * + * @return + */ + private JPanel initTreePane() { + JPanel treePane = new JPanel(new BorderLayout(0, 6)); + // north + JPanel northPane = new JPanel(FRGUIPaneFactory.createBorderLayout()); + initServerDatasetAuthTipJPanel(); + initButtonGroup(); + northPane.add(buttonGroup, BorderLayout.CENTER); + northPane.add(serverDatasetAuthTipJPanel, BorderLayout.SOUTH); + // center + remindPane = new TableDataSearchRemindPane(getDataTree()); + + treePane.add(northPane, BorderLayout.NORTH); + treePane.add(remindPane, BorderLayout.CENTER); + return treePane; + } + + /** + * 初始化 TableDataTree + * 数据集扩展 + */ + private void initTableDataTree() { + tableDataTree = new GroupTableDataTree(); + } + + /** + * 工具栏面板 + * + * @return + */ + private TreeSearchToolbarPane initToolBarPane() { + // toolbar + addMenuDef = new MenuDef(Toolkit.i18nText("Fine-Design_Basic_Action_Add")); + addMenuDef.setIconPath("/com/fr/design/images/control/addPopup"); + createAddMenuDef(); + // 创建插件监听 + createPluginListener(); + + editAction = new EditAction(); + copyAction = new CopyAction(); + pasteAction = new PasteAction(); + removeAction = new RemoveAction(); + previewTableDataAction = new PreviewTableDataAction(tableDataTree); + connectionTableAction = new ConnectionTableAction(); + esdAction = new EsdOnAction(); + esdOffAction = new EsdOffAction(); + switchAction = new SwitchAction(); + + toolbarDef = new ToolBarDef(); + toolbarDef.addShortCut(addMenuDef, SeparatorDef.DEFAULT, editAction, removeAction, SeparatorDef.DEFAULT, previewTableDataAction, connectionTableAction, esdAction, esdOffAction, switchAction); + UIToolbar toolBar = ToolBarDef.createJToolBar(); + toolBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, UIConstants.TOOLBAR_BORDER_COLOR)); + toolBar.setBorderPainted(true); + toolbarDef.updateToolBar(toolBar); + + TreeSearchToolbarPane searchLayerdPane = new TreeSearchToolbarPane(toolBar); + searchLayerdPane.setPreferredSize(new Dimension(this.getWidth(), 23)); + + return searchLayerdPane; + } + + /** + * + * 分组扩展 + */ + private void createPluginListener() { + //菜单栏监听 + GeneralContext.listenPluginRunningChanged(new PluginEventListener(PLUGIN_LISTENER_PRIORITY) { + + @Override + public void on(PluginEvent event) { + WestRegionContainerPane wp=WestRegionContainerPane.getInstance(); + JComponent downPane=wp.getDownPane(); + BasicTableDataTreePane pane=TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()); + if(downPane!=pane) { + wp.replaceDownPane(pane); + } + + addMenuDef.clearShortCuts(); + createAddMenuDef(); + } + }, new PluginFilter() { + + @Override + public boolean accept(PluginContext context) { + + return context.contain(PluginModule.ExtraDesign); + } + }); + } + + @Override + public final void createAddMenuDef() { + TableDataNameObjectCreator[] creators = TableDataCreatorProducer.getInstance().createReportTableDataCreator(); + for (final TableDataNameObjectCreator creator : creators) { + if (creator.shouldInsertSeparator()) { + addMenuDef.addShortCut(new LineSeparator()); + } + + addMenuDef.addShortCut(new AddAction() { + @Override + protected String getTDName() { + return creator.menuName(); + } + + @Override + protected Icon getTDIcon() { + return creator.menuIcon(); + } + + @Override + protected String getNamePrefix() { + return creator.getPrefix(); + } + + @Override + protected TemplateTableDataWrapper getTableDataInstance() { + TableData tableData = (TableData) creator.createObject(); + + //11中所有数据集都是StrategicTableData的子类 + if (tableData instanceof StrategicTableData) { + StrategicTableData std = (StrategicTableData) tableData; + tableData = StrategicTableData.Binder + .bind(std) + .setDsName(createDsName(creator.getPrefix())) + .setScope(StrategicTableData.Scope.TEMPLATE) + .done(); + } + return new TemplateTableDataWrapper(tableData); + } + }); + } + } + + private void initServerDatasetAuthTipJPanel() { + String datasetAuthTip = Toolkit.i18nText("Fine-Design_Server_Dataset_Auth_Tip"); + List lineTips = new ArrayList(Arrays.asList(datasetAuthTip.split("\n"))); + if (datasetAuthTip.endsWith("\n")) { + lineTips.add(StringUtils.EMPTY); + } + serverDatasetAuthTipJPanel = new JPanel(); + serverDatasetAuthTipJPanel.setLayout(new GridLayout(lineTips.size(), 1)); + for (int i = 0; i < lineTips.size(); i++) { + String lineTip = lineTips.get(i); + List jLabels = new ArrayList<>(); + JLabel lineJLabel = new JLabel(lineTip); + lineJLabel.setForeground(Color.lightGray); + jLabels.add(lineJLabel); + if (i == (lineTips.size() - 1)) { + JLabel jLabel = new JLabel(Toolkit.i18nText("Fine-Design_Basic_Alphafine_No_Remind")); + jLabel.setForeground(Color.blue); + jLabel.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + DesignerEnvManager.getEnvManager().setShowServerDatasetAuthTip(false); + serverDatasetAuthTipJPanel.setVisible(false); + } + }); + jLabels.add(jLabel); + } + serverDatasetAuthTipJPanel.add(getLineTipJPanel(jLabels)); + } + } + + private JPanel getLineTipJPanel(List jLabels) { + JPanel jPanel = new JPanel(FRGUIPaneFactory.createLabelFlowLayout()); + for (JLabel jLabel : jLabels) { + jPanel.add(jLabel); + } + return jPanel; + } + + //模版数据集 + protected void initButtonGroup() { +// Icon[] iconArray = {BaseUtils.readIcon("/com/fr/design/images/data/datasource.png"), BaseUtils.readIcon("/com/fr/design/images/data/dock/serverdatabase.png")}; + final Integer[] modeArray = {TEMPLATE_TABLE_DATA, SERVER_TABLE_DATA}; + String[] textArray = {Toolkit.i18nText("Fine-Design_Basic_Tabledata_Source_Type_Template"), Toolkit.i18nText("Fine-Design_Basic_DS_Server_TableData")}; + buttonGroup = new UIHeadGroup(textArray) { + @Override + public void tabChanged(int index) { + if (isShowServerDatasetAuthTipJPanel(textArray[index])) { + serverDatasetAuthTipJPanel.setVisible(true); + } else { + serverDatasetAuthTipJPanel.setVisible(false); + } + if (op != null) { + op.setDataMode(modeArray[buttonGroup.getSelectedIndex()]); + addMenuDef.setEnabled(modeArray[buttonGroup.getSelectedIndex()] == TEMPLATE_TABLE_DATA ? true : false); + if (TableDataTreeSearchManager.getInstance().isInSearchMode()) { + TableDataTreeSearchManager.getInstance().outOfSearchMode(); + } + refreshDockingView(); + } + } + + private boolean isShowServerDatasetAuthTipJPanel(String name) { + if (ComparatorUtils.equals(name, Toolkit.i18nText("Fine-Design_Basic_DS_Server_TableData")) + && DesignerEnvManager.getEnvManager().isShowServerDatasetAuthTip() + && !WorkContext.getCurrent().isLocal()) { + return true; + } + return false; + } + + }; + buttonGroup.setNeedLeftRightOutLine(false); + } + + /** + * 处理TableDataTree的监听等 + */ + private void dealWithTableDataTree() { + // tooltip + ToolTipManager.sharedInstance().registerComponent(tableDataTree); + ToolTipManager.sharedInstance().setDismissDelay(3000); + ToolTipManager.sharedInstance().setInitialDelay(0); + // 右键菜单 + popupMenu = new UIPopupMenu(); + popupMenu.add(editAction.createMenuItem()); + popupMenu.add(previewTableDataAction.createMenuItem()); + popupMenu.addSeparator(); + popupMenu.add(copyAction.createMenuItem()); + popupMenu.add(pasteAction.createMenuItem()); + popupMenu.add(removeAction.createMenuItem()); + popupMenu.addSeparator(); + // 监听 + tableDataTree.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + // 服务器暂不支持右键菜单 + if (SwingUtilities.isRightMouseButton(e) && op.getDataMode() != TableDataSourceOP.SERVER_TABLE_DATA) { + GUICoreUtils.showPopupMenu(popupMenu, e.getComponent(), e.getX(), e.getY()); + } + checkButtonEnabled(); + } + }); + tableDataTree.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + //F2重命名先屏蔽了, 有bug没时间弄 + if (e.getKeyCode() == KeyEvent.VK_F2) { + return; + } + + super.keyPressed(e); + checkButtonEnabled(); + } + + @Override + public void keyReleased(KeyEvent e) { + super.keyReleased(e); + checkButtonEnabled(); + } + }); + // TreeCellEditor + tableDataTree.setEditable(true); + TableDataTreeCellEditor treeCellEditor = new TableDataTreeCellEditor(new UITextField(), tableDataTree, this); + treeCellEditor.addCellEditorListener(treeCellEditor); + tableDataTree.setCellEditor(treeCellEditor); + //数据集分组扩展 + tableDataTree.setPane(this); + new GroupTableDataTreeDragSource(tableDataTree, DnDConstants.ACTION_COPY); + } + + private void checkButtonEnabled() { + // 检查添加与定义数据连接操作 + this.checkAddAndConnectionEnabled(); + // 检查编辑、预览、复制、粘贴、删除等基本操作 + this.checkBasicButtonEnabled(); + // 检查esd相关操作 + this.checkESDComponentsEnabled(); + } + + private void checkAddAndConnectionEnabled() { + connectionTableAction.setEnabled(WorkContext.getCurrent() != null && WorkContext.getCurrent().isRoot()); + addMenuDef.setEnabled(!(op == null || op.interceptButtonEnabled() || op.getDataMode() == SERVER_TABLE_DATA)); + } + + private void checkBasicButtonEnabled() { + // 设置下各个button的基本状态,避免代码重复 + editAction.setEnabled(false); + copyAction.setEnabled(false); + pasteAction.setEnabled(false); + removeAction.setEnabled(false); + previewTableDataAction.setEnabled(false); + if (op == null || op.interceptButtonEnabled()) { + // 保持false状态 + return; + } + // 获取选中的数据集数量 + int selectioncount = getDataTree().getSelectedTableDataCounts(); + if (op.getDataMode() == SERVER_TABLE_DATA) { + // 服务器数据集下,选中数据集数量为1时,可以预览 + if (selectioncount == 1 && !getDataTree().hasSelectedIndependentColumns()) { + previewTableDataAction.setEnabled(true); + } + // 其它保持false状态 + return; + } + // 模板数据集时,粘贴可用 + pasteAction.setEnabled(true); + if (selectioncount == 0 || getDataTree().hasSelectedIndependentColumns()) { + // 未选中数据集,或存在单独选中的数据列时,其它保持false状态 + return; + } + if (selectioncount == 1) { + // 仅选中单个数据集时,才可以编译、预览 + editAction.setEnabled(true); + previewTableDataAction.setEnabled(true); + } + removeAction.setEnabled(true); + copyAction.setEnabled(true); + } + + + private void checkESDComponentsEnabled() { + if (buttonGroup.getSelectedIndex() == 1) { + //切换到服务器数据集的tab,禁用 + esdAction.setEnabled(false); + esdOffAction.setEnabled(false); + return; + } + + new SwingWorker() { + @Override + protected ButtonStatus doInBackground() throws Exception { + ButtonStatus btnStatus = new ButtonStatus(); + Map statusMap = checkCanBeEsdBatchEnableStatus(); + if (statusMap.size() == 0) { + //没有db数据集 + return btnStatus; + } else { + int canTurnOnCount = 0; + int canTurnOffCount = 0; + for (ESDStatus status : statusMap.values()) { + switch (status) { + case GLOBAL_ON: + case GLOBAL_OFF: + case SINGLE_OFF: + canTurnOnCount++; + break; + case SINGLE_ON: + canTurnOffCount++; + break; + default: + break; + } + } + btnStatus.setOnStatus(canTurnOnCount > 0); + btnStatus.setOffStatus(canTurnOffCount > 0); + } + return btnStatus; + } + + @Override + protected void done() { + try { + ButtonStatus buttonStatus = get(); + esdAction.setEnabled(buttonStatus.isOnStatus()); + esdOffAction.setEnabled(buttonStatus.isOffStatus()); + } catch (InterruptedException | ExecutionException e) { + FineLoggerFactory.getLogger().error("get esd status of ds error for " + e.getMessage(), e); + } + } + }.execute(); + } + + /** + * 刷新 + */ + @Override + public void refreshDockingView() { + populate(new TableDataSourceOP(tc)); + this.checkButtonEnabled(); + } + + /** + * 编辑面板 + * + * @param tableDataPane 面板 + * @param originalName 原始名字 + */ + @Override + public void dgEdit(final AbstractTableDataPane tableDataPane, String originalName, boolean isUpdate){ + dgEdit(tableDataPane,originalName,isUpdate,null); + } + /** + * 编辑面板 + * + * @param tableDataPane 面板 + * @param originalName 原始名字 + */ + public void dgEdit(final AbstractTableDataPane tableDataPane, String originalName, boolean isUpdate,PaneActionType paneActionType) { + // 编辑时如果正在搜索,跳回原树 + if (TableDataTreeSearchManager.getInstance().isInSearchMode()) { + TableDataTreeSearchManager.getInstance().outOfSearchMode(); + } + tableDataPane.addStoreProcedureWorkerListener(new StoreProcedureWorkerListener() { + public void fireDoneAction() { + if (tableDataTree.getSelectionPath() == null) { + tableDataTree.refresh(); + } else { + Object object = tableDataTree.getSelectionPath().getLastPathComponent(); + int[] rows = tableDataTree.getSelectionRows(); + tableDataTree.refreshChildByName(object.toString()); + tableDataTree.setSelectionRows(rows); + } + } + }); + final NamePane tdNamePanel = tableDataPane.asNamePane(); + tdNamePanel.setObjectName(originalName); + + final String oldName = originalName; + allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); + + final BasicDialog dg = tdNamePanel.showLargeWindow(SwingUtilities.getWindowAncestor(this), new DialogActionAdapter() { + @Override + public void doOk() { + DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER); + tc.renameTableData(oldName, tdNamePanel.getObjectName(), false); + TableDataSource tds = tc.getBook(); + TableData td = tableDataPane.updateBean(); + if (td instanceof TableDataSourceDependent) { + ((TableDataSourceDependent) td).setTableDataSource(tds); + } + String tdName = tdNamePanel.getObjectName(); + + + //模版还没保存的时候不知道后缀,不能设置到策略配置里面 + if (tableDataPane instanceof DBTableDataPane) { + StrategyConfig editingConfig = ((DBTableDataPane) tableDataPane).updateStrategyConfig(); + if (editingConfig != null) { + editingConfig.setDsName(tdName); + if (!ComparatorUtils.equals(oldName, tdName)) { + //重命名 + StrategyConfigAttrUtils.removeStrategyConfig(oldName); + } + + StrategyConfigAttrUtils.addStrategyConfig(editingConfig); + } + ((DBTableData) td).setDsName(tdName); + } + + tds.putTableData(tdName, td); + Map map = new HashMap(); + if (!ComparatorUtils.equals(oldName, tdName)) { + map.put(oldName, tdName); + } + fireDSChanged(map); + tc.fireTargetModified(); + tc.parameterChanged(); + int[] rows = tableDataTree.getSelectionRows(); + /*tableDataTree.refreshChildByName(tdName); + tableDataTree.setSelectionRows(rows);*/ + //数据集分组扩展 + if(PaneActionType.EDIT==paneActionType){ + //更新数据集 + tableDataTree.updateTableDataNodeName(oldName,tdName); + tableDataTree.setSelectionRows(rows); + }else if(PaneActionType.ADD==paneActionType){ + //选择了一个分组后新增数据集 + if(tableDataTree.getSelectionPaths()!=null&& tableDataTree.getSelectionPaths().length==1){ + + ExpandMutableTreeNode tn=(ExpandMutableTreeNode) tableDataTree.getSelectionPaths()[0].getLastPathComponent(); + if(GroupTableDataTree.isGroupData(tn)){ + //在分组下新增分组 + + //新增的是分组 + if(td instanceof DSGroupTableData){ + //修改当前分组的父分组 + ((DSGroupTableData) td).setParentDSName(tableDataTree.getDSName(tn)); + } + tableDataTree.addTableDataToGroup(tn,tdName); + }else{ + tableDataTree.refreshChildByName(tdName); + tableDataTree.setSelectionRows(rows); + } + }else{ + tableDataTree.refreshChildByName(tdName); + tableDataTree.setSelectionRows(rows); + } + } + + + //单独编辑数据集关闭,修改缓存配置状态,刷新下一键开启/关闭按钮 + checkButtonEnabled(); + + if (listener != null) { + listener.doOk(); + } + } + + @Override + public void doCancel() { + super.doCancel(); + if (listener != null) { + listener.doCancel(); + } + } + }); + tdNamePanel.addPropertyChangeListener(new PropertyChangeAdapter() { + @Override + public void propertyChange() { + doPropertyChange(dg, tdNamePanel, oldName); + } + }); + // 有些数据集(DBTableData)面板的初始化过程中是包含了SwingWorker处理(查询数据连接、查表等)的 + // 如果这里直接setVisible,可能阻塞SwingWorker的done方法,导致面板渲染出现问题 + SwingUtilities.invokeLater(() -> { + dg.setVisible(true); + }); + } + + + + private boolean isIncludeUnderline(String name) { + return !ComparatorUtils.equals(name.indexOf(MultiResultTableData.GROUP_MARKER), -1); + } + + @Override + public void removeTableData(String sourceName) { + TableDataSource tds = this.tc.getBook(); + tds.removeTableData(sourceName); + this.tableDataTree.refresh(); + } + + /** + * 合并数据集 + * + * @param srcName 数据集来源(比如报表块,就是报表块的名称) + * @param tableDataSource 数据集 + */ + @Override + public Map addTableData(String srcName, TableDataSource tableDataSource, boolean isCover) { + Map tdNameMap = new HashMap<>(); + allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); + DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER); + TableDataSource tds = tc.getBook(); + Iterator tdIterator = tableDataSource.getTableDataNameIterator(); + while (tdIterator.hasNext()) { + String tdName = (String) tdIterator.next(); + String oldName = tdName; + TableData td = tableDataSource.getTableData(tdName); + boolean isDsNameRepeated = isDsNameRepeaded(tdName); + tdName = BasicTableDataUtils.getTableDataName(isCover, tds, tdName, srcName, isDsNameRepeated); + tds.putTableData(tdName, td); + if (!ComparatorUtils.equals(oldName, tdName)) { + tdNameMap.put(oldName, tdName); + } + } + tc.parameterChanged(); + tableDataTree.refresh(); + return Collections.unmodifiableMap(tdNameMap); + } + + /** + * 合并数据集 + * + * @param srcName 数据集来源(比如报表块,就是报表块的名称) + * @param tableDataSource 数据集 + */ + @Override + public Map addTableData(String srcName, TableDataSource tableDataSource) { + Map tdNameMap = new HashMap<>(); + allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); + DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER); + TableDataSource tds = tc.getBook(); + Iterator tdIterator = tableDataSource.getTableDataNameIterator(); + while (tdIterator.hasNext()) { + String tdName = tdIterator.next(); + String oldName = tdName; + TableData td = tableDataSource.getTableData(tdName); + if (tds.getTableData(tdName) != null || isDsNameRepeaded(tdName)) { + //如果有同名的就拼上来源名称 + tdName = srcName + tdName; + } + int i = 0; + while (tds.getTableData(tdName) != null) { + i++;//如果拼上名字后依然已经存在就加编号 + tdName += i; + } + tds.putTableData(tdName, td); + if (!ComparatorUtils.equals(oldName, tdName)) { + tdNameMap.put(oldName, tdName); + } + } + tc.parameterChanged(); + tableDataTree.refresh(); + return Collections.unmodifiableMap(tdNameMap); + } + + @Override + public void addDataPane(final AbstractTableDataPane uPanel, String paneName) { + final NamePane nPanel = uPanel.asNamePane(); + nPanel.setObjectName(paneName); + + allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); + + DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER); + tc.renameTableData(paneName, nPanel.getObjectName(), false); + TableDataSource tds = tc.getBook(); + TableData td = uPanel.updateBean(); + if (td instanceof TableDataSourceDependent) { + ((TableDataSourceDependent) td).setTableDataSource(tds); + } + String tdName = nPanel.getObjectName(); + + //处理缓存策略配置 + if (uPanel instanceof DBTableDataPane) { + StrategyConfig editingConfig = ((DBTableDataPane) uPanel).updateStrategyConfig(); + if (editingConfig != null) { + editingConfig.setDsName(tdName); + StrategyConfigAttrUtils.addStrategyConfig(editingConfig); + } + ((DBTableData) td).setDsName(tdName); + } + + tds.putTableData(tdName, td); + Map map = new HashMap(); + if (!ComparatorUtils.equals(paneName, tdName)) { + map.put(paneName, tdName); + } + fireDSChanged(map); + tc.fireTargetModified(); + tc.parameterChanged(); + int[] rows = tableDataTree.getSelectionRows(); + tableDataTree.refreshChildByName(tdName); + tableDataTree.setSelectionRows(rows); + FineLoggerFactory.getLogger().info("add table data succeeded for {}", tdName); + } + + @Override + public TableDataTree getDataTree() { + return this.tableDataTree; + } + + private void populate(TableDataSourceOP op) { + this.op = op; + tableDataTree.populate(op); + checkButtonEnabled(); + } + + + private void resetAddMenuDef() { + this.addMenuDef.clearShortCuts(); + this.createAddMenuDef(); + } + + private String createDsName(String prefix) { + int count = 1; + allDSNames = DesignTableDataManager.getAllDSNames(tc.getBook()); + while (isDsNameRepeaded(prefix + count)) { + count++; + } + return prefix + count; + } + + private static class ButtonStatus { + private boolean onStatus = false; + private boolean offStatus = false; + + public boolean isOnStatus() { + return onStatus; + } + + public void setOnStatus(boolean onStatus) { + this.onStatus = onStatus; + } + + public boolean isOffStatus() { + return offStatus; + } + + public void setOffStatus(boolean offStatus) { + this.offStatus = offStatus; + } + } + + private TableDataWrapper findTableDataWrapper(TreePath treePath) { + if (treePath != null) { + ExpandMutableTreeNode selectedTreeNode = (ExpandMutableTreeNode) treePath.getLastPathComponent(); + Object selectedUserObject = selectedTreeNode.getUserObject(); + NameObject nameObject = null; + if (selectedUserObject instanceof NameObject) { + nameObject = (NameObject) selectedUserObject; + } else { + selectedTreeNode = (ExpandMutableTreeNode) selectedTreeNode.getParent(); + selectedUserObject = selectedTreeNode.getUserObject(); + if (selectedUserObject instanceof NameObject) { + nameObject = (NameObject) selectedUserObject; + } + } + if (nameObject != null && nameObject.getObject() instanceof TableDataWrapper) { + return (TableDataWrapper) nameObject.getObject(); + } + } + + return null; + } + + private String getTplPath() { + return HistoryTemplateListCache.getInstance().getCurrentEditingTemplate().getPath(); + } + + enum ESDStatus { + GLOBAL_ON, + GLOBAL_OFF, + SINGLE_ON, + SINGLE_OFF; + } + + + private Map checkCanBeEsdBatchEnableStatus() { + //<数据集, 是否可以被单独开启> + Map result = new HashMap<>(); + for (int i = 0; i < tableDataTree.getRowCount(); i++) { + TreePath treePath = tableDataTree.getPathForRow(i); + + TableDataWrapper wrapper = findTableDataWrapper(treePath); + if (wrapper.getTableData() instanceof DBTableData) { + DBTableData td = (DBTableData) wrapper.getTableData(); + + StrategyConfig config = StrategyConfigAttrUtils.getStrategyConfig(wrapper.getTableDataName()); + if (config == null) { + result.put(td, td.isShare() ? ESDStatus.SINGLE_ON : ESDStatus.SINGLE_OFF); + } else { + if (config.isUseGlobal()) { + if (StrategyConfigHelper.recommended(getTplPath())) { + result.put(td, ESDStatus.GLOBAL_ON); + } else { + result.put(td, ESDStatus.GLOBAL_OFF); + } + } else { + if (config.enabled()) { + result.put(td, ESDStatus.SINGLE_ON); + } else { + result.put(td, ESDStatus.SINGLE_OFF); + } + } + } + } + } + + return result; + } + + @Override + public TableDataSourceOP getOp(){ + return op; + } + + @Override + public DesignModelAdapter getTC(){ + return tc; + } + + private abstract class AbstractESDAction extends UpdateAction { + + @Override + public abstract String getName(); + + public abstract String getIconResource(); + + public abstract void doWithTableDataWrapper(TableDataWrapper tableDataWrapper); + + public AbstractESDAction() { + this.setName(getName()); + this.setMnemonic('R'); + this.setSmallIcon(getIconResource()); + } + + @Override + public void actionPerformed(ActionEvent e) { + List tableDataWrapperList = new ArrayList<>(); + + for (int i = 0; i < tableDataTree.getRowCount(); i++) { + TreePath treePath = tableDataTree.getPathForRow(i); + TableDataWrapper wrapper = findTableDataWrapper(treePath); + if (wrapper != null) { + tableDataWrapperList.add(wrapper); + } + } + if (tableDataWrapperList.isEmpty()) { + return; + } + new SwingWorker() { + @Override + protected Void doInBackground() throws Exception { + for (TableDataWrapper tableDataWrapper : tableDataWrapperList) { + doWithTableDataWrapper(tableDataWrapper); + } + return null; + } + + @Override + protected void done() { + refreshDockingView(); + } + }.execute(); + } + } + + private class EsdOnAction extends AbstractESDAction { + + @Override + public String getName() { + return Toolkit.i18nText("Fine-Design_ESD_Batch_Enable"); + } + + @Override + public String getIconResource() { + return "/com/fr/design/images/control/batch_esd_on"; + } + + @Override + public void doWithTableDataWrapper(TableDataWrapper wrapper) { + String dsName = wrapper.getTableDataName(); + if (wrapper.getTableData() instanceof DBTableData) { + StrategyConfig strategyConfig = getOrCreateStrategyConfig(dsName); + strategyConfig.setEnable(true); + strategyConfig.setUseGlobal(false); + StrategyConfigAttrUtils.addStrategyConfig(strategyConfig); + DesignerContext.getDesignerFrame().getSelectedJTemplate().fireTargetModified(); + } + } + } + + private class EsdOffAction extends AbstractESDAction { + + @Override + public String getName() { + return Toolkit.i18nText("Fine-Design_ESD_Batch_Disable"); + } + + @Override + public String getIconResource() { + return "/com/fr/design/images/control/batch_esd_off"; + } + + @Override + public void doWithTableDataWrapper(TableDataWrapper wrapper) { + String dsName = wrapper.getTableDataName(); + if (wrapper.getTableData() instanceof DBTableData) { + ((DBTableData) wrapper.getTableData()).setShare(false); + StrategyConfig strategyConfig = getOrCreateStrategyConfig(dsName); + strategyConfig.setEnable(false); + strategyConfig.setUseGlobal(false); + StrategyConfigAttrUtils.addStrategyConfig(strategyConfig); + DesignerContext.getDesignerFrame().getSelectedJTemplate().fireTargetModified(); + } + } + } + + private @NotNull StrategyConfig getOrCreateStrategyConfig(String dsName) { + StrategyConfig config = StrategyConfigAttrUtils.getStrategyConfig(dsName); + + if (config == null) { + config = StrategyConfigHelper.createStrategyConfig(true); + config.setDsName(dsName); + } + + return config; + } + + /** + * 新建数据集 + *

+ * 抽象化,支持不同类型数据集创建 + */ + private abstract class AddAction extends UpdateAction { + + protected abstract String getTDName(); + + protected abstract Icon getTDIcon(); + + protected abstract String getNamePrefix(); + + protected abstract TemplateTableDataWrapper getTableDataInstance(); + + private PaneActionType paneActionType=PaneActionType.ADD; + + public AddAction() { + this.setName(this.getTDName()); + this.setSmallIcon(this.getTDIcon()); + } + + @Override + public void actionPerformed(ActionEvent e) { + dgEdit(getTableDataInstance().creatTableDataPane(), createDsName(getNamePrefix()), false,paneActionType); + } + } + + + private class EditAction extends UpdateAction { + private PaneActionType paneActionType=PaneActionType.EDIT; + public EditAction() { + this.setName(Toolkit.i18nText("Fine-Design_Basic_Edit")); + this.setMnemonic('E'); + this.setSmallIcon("/com/fr/design/images/control/edit"); + } + + @Override + public void actionPerformed(ActionEvent e) { + final NameObject selectedNO = tableDataTree.getSelectedNameObject(); + if (selectedNO == null) { + return; + } + //final boolean group= ((TableDataWrapper) selectedNO.getObject()).getTableData() instanceof DSGroupTableData; + + String dsName = selectedNO.getName(); + DesignTableDataManager.removeSelectedColumnNames(dsName); + + AbstractTableDataWrapper wrapper = (AbstractTableDataWrapper) selectedNO.getObject(); + + AbstractTableDataPane tableDataPane = wrapper.creatTableDataPane(); + + if (TableDataAuthHelper.needCheckAuthWhenEdit(wrapper.getTableData())) { + // 先打开一个Loading面板 + TableDataLoadingPane loadingPane = new TableDataLoadingPane(); + BasicDialog loadingDialog = loadingPane.showLargeWindow(SwingUtilities.getWindowAncestor(GroupTableDataTreePane.this), null); + // 查询权限 + new SwingWorker() { + @Override + protected Boolean doInBackground() throws Exception { + // 获取无权限连接名称集合 + Collection noAuthConnections = TableDataAuthHelper.getNoAuthConnections(); + // 获取当前数据集对应的数据连接名称 + String connectionName = TableDataAuthHelper.getConnectionNameByDBTableData((DBTableData) wrapper.getTableData()); + return !noAuthConnections.contains(connectionName); + } + + @Override + protected void done() { + try { + Boolean hasAuth = get(); + if (hasAuth) { + // 有权限时,关闭Loading面板,打开编辑面板 + loadingDialog.setVisible(false); + dgEdit(tableDataPane, dsName, false,paneActionType); + } else { + // 无权限时,给出无权限提示 + loadingPane.switchTo(TableDataLoadingPane.NO_AUTH_PANE_NAME); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error("loading connection error in remote design", e.getMessage()); + // 查询权限失败时,给出报错提示 + loadingPane.switchTo(TableDataLoadingPane.ERROR_NAME); + } + } + }.execute(); + loadingDialog.setVisible(true); + } else { + // 无需检查权限时,直接打开数据库查询编辑面板 + //下面创建creatTableDataPane后会直接populate,所以populate时不能用后设置的一些参数,比如name + dgEdit(tableDataPane, dsName, false,paneActionType); + } + } + } + + private class RemoveAction extends UpdateAction { + + public RemoveAction() { + this.setName(Toolkit.i18nText("Fine-Design_Basic_Remove")); + this.setMnemonic('R'); + this.setSmallIcon("/com/fr/design/images/control/remove"); + } + + @Override + public void actionPerformed(ActionEvent e) { + NameObject[] selectedNameObjects = tableDataTree.getSelectedTableDataNameObjects(); + if (selectedNameObjects == null || selectedNameObjects.length == 0) { + FineLoggerFactory.getLogger().error("Table Data to remove is null or not selected"); + return; + } + // 可以半选的CheckBoxList + CheckBoxListWithPartialSelect tableDataCheckBoxPane = new CheckBoxListWithPartialSelect(selectedNameObjects); + UIScrollPane scrollPane = new UIScrollPane(tableDataCheckBoxPane); + UILabel tips = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Select_Source_To_Remove")); + BasicPane basicPane = new BasicPane() { + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Fine-Design_Basic_Remove"); + } + }; + basicPane.setLayout(new BorderLayout()); + basicPane.add(tips, BorderLayout.NORTH); + basicPane.add(scrollPane, BorderLayout.CENTER); + BasicDialog basicDialog = basicPane.showSmallWindow(SwingUtilities.getWindowAncestor(GroupTableDataTreePane.this), new DialogActionAdapter() { + @Override + public void doOk() { + List selectedValues = tableDataCheckBoxPane.getSelectedObjects(); + // 删除时如果正在搜索,跳回原树 + if (TableDataTreeSearchManager.getInstance().isInSearchMode()) { + TableDataTreeSearchManager.getInstance().outOfSearchMode(); + } + for (Object toRemove : selectedValues) { + try { + doRemove((String) toRemove); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e, "remove table data failed for {}", toRemove); + } + } + } + + @Override + public void doCancel() { + super.doCancel(); + } + }); + basicDialog.setVisible(true); + } + + private void doRemove(String toRemove) throws Exception { + // richer:这个地方为什么要在DataSourceTree里面去remove呢?多此一举吧 + op.removeAction(toRemove); + tableDataTree.refresh(); + // Richie:默认最后一行获得焦点. + tableDataTree.requestFocus(); + tableDataTree.setSelectionRow(tableDataTree.getRowCount() - 1); + fireDSChanged(); + checkButtonEnabled(); + + //删掉缓存配置 + StrategyConfigAttrUtils.removeStrategyConfig(toRemove); + + // 如果一个模版是平台开启,这个数据集的配置不会存xml,预览模版时直接从全局配置copy,这样 + // 导致删除的时候StrategyConfigsAttrSavedHook没有通过前后配置比较感知数据集被删除,因此不会发出事件让其失效 + // 这里额外发出一次数据集修改事件 + StrategyEventsNotifier.modifyDataSet(new DSMapping(getTplPath(), new DsNameTarget(toRemove))); + DesignTableDataManager.removeSelectedColumnNames(toRemove); + DesignModelAdapter.getCurrentModelAdapter().removeTableDataParameters(toRemove); + FineLoggerFactory.getLogger().info("remove table data succeeded for {}", toRemove); + } + } + + private class CopyAction extends UpdateAction { + + public CopyAction() { + this.setName(Toolkit.i18nText("Fine-Design_Basic_Copy")); + this.setMnemonic('C'); + this.setSmallIcon("/com/fr/design/images/m_edit/copy"); + } + + @Override + public void actionPerformed(ActionEvent e) { + NameObject[] selectedNameObjects = tableDataTree.getSelectedTableDataNameObjects(); + Map dataWrapperMap = TableDataTreeClipboard.getInstance().transferNameObjectArray2Map(selectedNameObjects); + TableDataTreeClipboard.getInstance().addToClip(dataWrapperMap); + } + } + + private class PasteAction extends UpdateAction { + + public PasteAction() { + this.setName(Toolkit.i18nText("Fine-Design_Basic_Action_Paste_Name")); + this.setMnemonic('P'); + this.setSmallIcon("/com/fr/design/images/m_edit/paste"); + } + + @Override + public void actionPerformed(ActionEvent e) { + FineLoggerFactory.getLogger().info("ds-group:开始粘贴"); + // 粘贴时如果正在搜索,跳回原树 + if (TableDataTreeSearchManager.getInstance().isInSearchMode()) { + TableDataTreeSearchManager.getInstance().outOfSearchMode(); + } + Map dataWrapperMap = TableDataTreeClipboard.getInstance().takeFromClip(); + for (Map.Entry dataWrapperEntry : dataWrapperMap.entrySet()) { + // 处理数据集名称 + String dsName = getNoRepeatedDsName4Paste(dataWrapperEntry.getKey()); + AbstractTableDataWrapper wrapper = dataWrapperEntry.getValue(); + AbstractTableDataPane tableDataPane = TableDataFollowingPasteUtils.generateTableDataPaneWhenPaste(wrapper); + if (tableDataPane != null) { + FineLoggerFactory.getLogger().info("ds-group:开始粘贴:"+dsName); + addDataPane(tableDataPane, dsName); + } + } + FineLoggerFactory.getLogger().info("ds-group:结束粘贴"); + } + } + + public String getNoRepeatedDsName4Paste(String oldName) { + while (isDsNameRepeaded(oldName)) { + oldName = oldName + Toolkit.i18nText("Fine-Design_Table_Data_Copy_Of_Table_Data"); + } + return oldName; + } + + private class SwitchAction extends UpdateAction { + + public SwitchAction() { + this.setName(Toolkit.i18nText("Fine-Design_Basic_Search")); + this.setMnemonic('S'); + this.setSmallIcon("/com/fr/design/images/data/search"); + } + + @Override + public void actionPerformed(ActionEvent e) { + // 交换层级 + toolbarPane.switchPane(TreeSearchToolbarPane.SEARCH_PANE); + TableDataTreeSearchManager.getInstance().switchToSearch(TableDataSearchMode.match(buttonGroup.getSelectedIndex()), DesignTableDataManager.getEditingTableDataSource()); + } + } + + @Override + public void checkEnable() { + this.checkButtonEnabled(); + } + + +} diff --git a/src/main/java/com/fr/plugins/dsgroup/LocaleFinder.java b/src/main/java/com/fr/plugins/dsgroup/LocaleFinder.java new file mode 100644 index 0000000..674f418 --- /dev/null +++ b/src/main/java/com/fr/plugins/dsgroup/LocaleFinder.java @@ -0,0 +1,21 @@ +package com.fr.plugins.dsgroup; + +import com.fr.stable.fun.impl.AbstractLocaleFinder; + +/** + * Created by phetran_ye on 2018/8/7. + */ +public class LocaleFinder extends AbstractLocaleFinder { + @Override + + public int currentAPILevel() { + return CURRENT_LEVEL; + } + + @Override + + public String find() { + return "com/fr/plugins/dsgroup/locale/locale"; + } + +} diff --git a/src/main/java/com/fr/plugins/dsgroup/PaneActionType.java b/src/main/java/com/fr/plugins/dsgroup/PaneActionType.java new file mode 100644 index 0000000..1d49300 --- /dev/null +++ b/src/main/java/com/fr/plugins/dsgroup/PaneActionType.java @@ -0,0 +1,9 @@ +package com.fr.plugins.dsgroup; + +/** + * @author phetran_ye + * 2023-03-18 + */ +public enum PaneActionType { + ADD,EDIT; +} diff --git a/src/main/java/com/fr/plugins/dsgroup/TableDataAware.java b/src/main/java/com/fr/plugins/dsgroup/TableDataAware.java new file mode 100644 index 0000000..92a95ef --- /dev/null +++ b/src/main/java/com/fr/plugins/dsgroup/TableDataAware.java @@ -0,0 +1,13 @@ +package com.fr.plugins.dsgroup; + +import com.fr.design.DesignModelAdapter; +import com.fr.design.data.datapane.TableDataSourceOP; + +/** + * @author phetran_ye + * 2022-09-12 + */ +public interface TableDataAware { + DesignModelAdapter getTC(); + TableDataSourceOP getOp(); +} diff --git a/src/main/java/com/fr/plugins/dsgroup/TableDataPaneProcessorImpl.java b/src/main/java/com/fr/plugins/dsgroup/TableDataPaneProcessorImpl.java new file mode 100644 index 0000000..6b93093 --- /dev/null +++ b/src/main/java/com/fr/plugins/dsgroup/TableDataPaneProcessorImpl.java @@ -0,0 +1,37 @@ +package com.fr.plugins.dsgroup; + +import com.fr.design.DesignModelAdapter; +import com.fr.design.actions.server.GlobalTableDataAction; +import com.fr.design.data.BasicTableDataTreePane; +import com.fr.design.data.datapane.TableDataPaneController; +import com.fr.design.fun.impl.AbstractTDPaneProcessor; +import com.fr.design.menu.ShortCut; +import com.fr.general.GeneralUtils; +import com.fr.stable.ProductConstants; + + +/** + * Created by phetran_ye on 2018/8/8. + */ +public class TableDataPaneProcessorImpl extends AbstractTDPaneProcessor { + @Override + public BasicTableDataTreePane createTableDataTreePane(DesignModelAdapter tc) { + return GroupTableDataTreePane.getInstance(tc); + } + + @Override + public TableDataPaneController createServerTableDataPane(DesignModelAdapter tc) { + return new GroupTableDataPaneListPane(); + } + + @Override + public ShortCut createServerTDAction() { + return new GlobalTableDataAction(); + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } + +} diff --git a/src/main/java/com/fr/plugins/dsgroup/fun/DSGroupTableData.java b/src/main/java/com/fr/plugins/dsgroup/fun/DSGroupTableData.java new file mode 100644 index 0000000..6b1f98a --- /dev/null +++ b/src/main/java/com/fr/plugins/dsgroup/fun/DSGroupTableData.java @@ -0,0 +1,172 @@ +package com.fr.plugins.dsgroup.fun; + + +import com.fr.config.holder.Conf; +import com.fr.config.holder.impl.SimConf; +import com.fr.data.AbstractParameterTableData; +import com.fr.design.mainframe.WestRegionContainerPane; +import com.fr.general.data.DataModel; +import com.fr.script.Calculator; +import com.fr.stable.StringUtils; +import com.fr.stable.xml.XMLPrintWriter; +import com.fr.stable.xml.XMLableReader; + +/** + * Created by richie on 2016/10/8. + */ +public class DSGroupTableData extends AbstractParameterTableData { + + private static final String XML_ATTR_TAG = "QueryTableDataAttr"; + + private static final String separator="&;"; + private static final String childrenAttrName="children_DS_names"; + private static final String parentAttrName="parent_DS_name"; + private Conf attrParentDSName=new SimConf<>(null); + private Conf attrChildrenDSNames=new SimConf<>(null); + + public Conf getAttrParentDSName() { + return attrParentDSName; + } + + public void setAttrParentDSName(Conf attrParentDSName) { + this.attrParentDSName = attrParentDSName; + } + + public Conf getAttrChildrenDSNames() { + return attrChildrenDSNames; + } + + public void setAttrChildrenDSNames(Conf attrChildrenDSNames) { + this.attrChildrenDSNames = attrChildrenDSNames; + } + + public static String getSeparator() { + return separator; + } + + public String getChildrenDSNames() { + return attrChildrenDSNames.get(); + } + + public boolean hasChildren(){ + return attrChildrenDSNames.get()!=null; + } + + public boolean hasParent(){ + return attrParentDSName.get()!=null; + } + + public void setChildrenDSNames(String childrenDSNames) { + this.attrChildrenDSNames.set(childrenDSNames); + } + + public String getParentDSName() { + return attrParentDSName.get(); + } + + public void setParentDSName(String parentDSName) { + this.attrParentDSName.set(parentDSName); + } + + public void addChildren(String children){ + if(StringUtils.isEmpty(children)){ + return; + } + if(this.hasChildren()){ + this.setChildrenDSNames(this.getChildrenDSNames()+separator+children); + }else{ + this.setChildrenDSNames(children); + } + } + + public void removeParent(){ + this.setParentDSName(null); + } + + public void removeChild(String childName){ + if(!hasChildren()){ + return; + } + String children=this.getChildrenDSNames(); + children=wrapDsName(children); + childName=wrapDsName(childName); + children=children.replace(childName,separator).replaceAll("^"+separator+"{1}","").replaceAll(separator+"${1}",""); + if(children.length()==0){ + children=null; + } + this.setChildrenDSNames(children); + } + + public boolean hasChild(String childName){ + if(!hasChildren()){ + return false; + }else{ + childName=wrapDsName(childName); + String myChildren=wrapDsName(this.getChildrenDSNames()); + return myChildren.indexOf(childName)>-1; + } + } + + public boolean isChildOf(String parentName){ + return parentName.equals(this.getParentDSName()); + } + + public void changeChildName(String oldChildName,String newChildName){ + if(!hasChildren()||StringUtils.isEmpty(newChildName)){ + return; + } + String children=this.getChildrenDSNames(); + children=wrapDsName(children); + oldChildName=wrapDsName(oldChildName); + newChildName=wrapDsName(newChildName); + children=children.replace(oldChildName,newChildName).replaceAll("^"+separator+"{1}","").replaceAll(separator+"${1}",""); + this.setChildrenDSNames(children); + } + + private String wrapDsName(String name){ + return separator+name+separator; + } + + @Override + public DataModel createDataModel(Calculator calculator) { + //return new QueryDataModel(processParameters(calculator)); + return null; + } + + @Override + public void readXML(XMLableReader reader) { + super.readXML(reader); + if (reader.isChildNode()) { + String tagName = reader.getTagName(); + if (tagName.equals(XML_ATTR_TAG)) { + attrParentDSName = new SimConf<>(reader.getAttrAsString(parentAttrName, null)); + attrChildrenDSNames = new SimConf<>(reader.getAttrAsString(childrenAttrName, null)); + } + } + } + + @Override + public void writeXML(XMLPrintWriter writer) { + super.writeXML(writer); + writer.startTAG(XML_ATTR_TAG); + writer.attr(parentAttrName, attrParentDSName.get()); + writer.attr(childrenAttrName, attrChildrenDSNames.get()); + writer.end(); + } + + @Override + public Object clone() throws CloneNotSupportedException { + DSGroupTableData cloned = (DSGroupTableData)super.clone(); + cloned.attrParentDSName=(SimConf)this.attrParentDSName.clone(); + cloned.attrChildrenDSNames=(SimConf)this.attrChildrenDSNames.clone(); + return cloned; + } + + public DSGroupTableData newData(){ + try{ + return (DSGroupTableData)this.clone(); + }catch (CloneNotSupportedException e){ + return null; + } + } +} diff --git a/src/main/java/com/fr/plugins/dsgroup/rpc/GroupStableKeyArgsProvider.java b/src/main/java/com/fr/plugins/dsgroup/rpc/GroupStableKeyArgsProvider.java new file mode 100644 index 0000000..ee396d7 --- /dev/null +++ b/src/main/java/com/fr/plugins/dsgroup/rpc/GroupStableKeyArgsProvider.java @@ -0,0 +1,25 @@ +package com.fr.plugins.dsgroup.rpc; + +import com.fr.module.StableKey; +import com.fr.stable.fun.impl.AbstractStableKeyArgsProvider; +import com.fr.workspace.base.WorkspaceKey; +import com.fr.workspace.pool.WorkRPCRegister; + +import java.util.Arrays; +import java.util.List; + +/** + * @author phetran_ye + * 2022-04-20 + */ +public class GroupStableKeyArgsProvider extends AbstractStableKeyArgsProvider>{ + @Override + protected List> createArgs() { + return Arrays.asList( WorkRPCRegister.wrap(GroupTableDataOperator.class, GroupTableDataOperatorImpl.getInstance()) ); + } + + @Override + public StableKey> getKey() { + return WorkspaceKey.RPC; + } +} diff --git a/src/main/java/com/fr/plugins/dsgroup/rpc/GroupTableDataOperator.java b/src/main/java/com/fr/plugins/dsgroup/rpc/GroupTableDataOperator.java new file mode 100644 index 0000000..df071d4 --- /dev/null +++ b/src/main/java/com/fr/plugins/dsgroup/rpc/GroupTableDataOperator.java @@ -0,0 +1,13 @@ +package com.fr.plugins.dsgroup.rpc; + +import com.fr.base.TableDataBean; + +import java.util.List; + +/** + * @author phetran_ye + * 2022-04-20 + */ +public interface GroupTableDataOperator { + boolean saveTableData(List toDeleted, List tableDataBeanList) throws Exception; +} diff --git a/src/main/java/com/fr/plugins/dsgroup/rpc/GroupTableDataOperatorImpl.java b/src/main/java/com/fr/plugins/dsgroup/rpc/GroupTableDataOperatorImpl.java new file mode 100644 index 0000000..f5da326 --- /dev/null +++ b/src/main/java/com/fr/plugins/dsgroup/rpc/GroupTableDataOperatorImpl.java @@ -0,0 +1,50 @@ +package com.fr.plugins.dsgroup.rpc; + +import com.fr.base.TableDataBean; +import com.fr.file.ConfigChangeProcessor; +import com.fr.file.TableDataConfig; +import com.fr.transaction.Configurations; +import com.fr.transaction.WorkerFacade; + +import java.util.List; + +/** + * @author phetran_ye + * 2022-04-20 + */ +public class GroupTableDataOperatorImpl implements GroupTableDataOperator{ + private static final GroupTableDataOperator INSTANCE = new GroupTableDataOperatorImpl(); + + public static GroupTableDataOperator getInstance() { + return INSTANCE; + } + + @Override + public boolean saveTableData(List toDeleted, List tableDataBeanList) throws Exception { + return save(tableDataBeanList, new Runnable() { + @Override + public void run() { + removeDeleted(toDeleted); + } + }); + } + + private boolean save(List tableDataBeanList, Runnable deleteAction) { + ConfigChangeProcessor.getInstance().applyForTableData(tableDataBeanList); + return Configurations.modify(new WorkerFacade(TableDataConfig.class) { + @Override + public void run() { + deleteAction.run(); + for (TableDataBean tableDataBean : tableDataBeanList) { + TableDataConfig.getInstance().addTableData(tableDataBean.getName(), tableDataBean.getTableData()); + } + } + }); + } + + private void removeDeleted(List toDeleted) { + for (String name : toDeleted) { + TableDataConfig.getInstance().removeTableData(name); + } + } +} diff --git a/src/main/java/com/fr/plugins/dsgroup/ui/DSGroupPane.java b/src/main/java/com/fr/plugins/dsgroup/ui/DSGroupPane.java new file mode 100644 index 0000000..1d0c85d --- /dev/null +++ b/src/main/java/com/fr/plugins/dsgroup/ui/DSGroupPane.java @@ -0,0 +1,91 @@ +package com.fr.plugins.dsgroup.ui; + +/** + * Created by phetran_ye on 2018/8/7. + */ +import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; +import com.fr.design.gui.itextfield.UITextField; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.WestRegionContainerPane; +import com.fr.plugins.dsgroup.fun.DSGroupTableData; +import javax.swing.*; +import java.awt.*; + +public class DSGroupPane extends AbstractTableDataPane { + + //private static final String PREVIEW_BUTTON = Inter.getLocText("Preview"); + + + private UITextField contentTextField; + private DSGroupTableData tableData; + + + public DSGroupPane() { + WestRegionContainerPane wp=WestRegionContainerPane.getInstance(); + setLayout(new BorderLayout()); + //add(createToolBar(), BorderLayout.NORTH); + JPanel contentPane = new JPanel(); + JLabel infoLbl=new JLabel(); + String info="提示:
"; + info+="1.选中分组,然后添加数据集即可在该分组下添加数据集。
"; + info+="2.拖动数据集到某分组上即可将数据集添加到该分组下。
"; + info+="3.拖动数据集到数据集面板空白处即可将该数据集移到最外部。
 "; + infoLbl.setText(info); + contentPane.setLayout(new BorderLayout()); + contentPane.add(infoLbl, BorderLayout.NORTH); + add(contentPane, BorderLayout.CENTER); + } + + /*private JToolBar createToolBar() { + ToolBarDef toolBarDef = new ToolBarDef(); + //toolBarDef.addShortCut(new PreviewQueryTableDataAction()); + UIToolbar editToolBar = ToolBarDef.createJToolBar(); + toolBarDef.updateToolBar(editToolBar); + return editToolBar; + }*/ + + /* private void addChildrenToParent(JPanel contentPane) { + double p = TableLayout.PREFERRED; + double f = TableLayout.FILL; + double[] rowSize = {p}; + double[] columnSize = {p, f}; + + JPanel panel = TableLayoutHelper.createTableLayoutPane(new Component[][]{ + {new UILabel("名字"), contentTextField = new UITextField()} + }, rowSize, columnSize); + contentPane.add(panel, BorderLayout.CENTER); + }*/ + + @Override + public void populateBean(DSGroupTableData ob) { + /*if (ob != null) { + contentTextField.setText(ob.getText()); + }*/ + tableData=ob; + } + + @Override + public DSGroupTableData updateBean() { + //DSGroupTableData tableData = new DSGroupTableData(); + //tableData.setText(contentTextField.getText()); + return tableData; + } + + @Override + protected String title4PopupWindow() { + return Toolkit.i18nText("Data_Set_Group"); + } + + /*private class PreviewQueryTableDataAction extends UpdateAction { + public PreviewQueryTableDataAction() { + this.setName(PREVIEW_BUTTON); + this.setMnemonic('P'); + this.setSmallIcon(BaseUtils.readIcon("/com/fr/design/images/m_file/preview.png")); + } + + public void actionPerformed(ActionEvent evt) { + PreviewTablePane.previewTableData(DSGroupPane.this.updateBean()); + } + }*/ +} + diff --git a/src/main/resources/com/fr/plugins/dsgroup/locale/locale.properties b/src/main/resources/com/fr/plugins/dsgroup/locale/locale.properties new file mode 100644 index 0000000..2d29a66 --- /dev/null +++ b/src/main/resources/com/fr/plugins/dsgroup/locale/locale.properties @@ -0,0 +1,9 @@ +Plugin-Data_Set_Group=Data Set Group +Data_Set_Group=Data Set Group +Default_Group_Name=unnamed group +Template=Template +DS-TableData=DS-TableData +DS-Server_TableData=DS-Server_TableData +FR-Designer_Edit=FR-Designer_Edit +FR-Designer_Remove=FR-Designer_Remove +Utils-Are_you_sure_to_remove_the_selected_item=Are you sure to remove the selected item \ No newline at end of file diff --git a/src/main/resources/com/fr/plugins/dsgroup/locale/locale_en_US.properties b/src/main/resources/com/fr/plugins/dsgroup/locale/locale_en_US.properties new file mode 100644 index 0000000..2d29a66 --- /dev/null +++ b/src/main/resources/com/fr/plugins/dsgroup/locale/locale_en_US.properties @@ -0,0 +1,9 @@ +Plugin-Data_Set_Group=Data Set Group +Data_Set_Group=Data Set Group +Default_Group_Name=unnamed group +Template=Template +DS-TableData=DS-TableData +DS-Server_TableData=DS-Server_TableData +FR-Designer_Edit=FR-Designer_Edit +FR-Designer_Remove=FR-Designer_Remove +Utils-Are_you_sure_to_remove_the_selected_item=Are you sure to remove the selected item \ No newline at end of file diff --git a/src/main/resources/com/fr/plugins/dsgroup/locale/locale_zh_CN.properties b/src/main/resources/com/fr/plugins/dsgroup/locale/locale_zh_CN.properties new file mode 100644 index 0000000..c310ca3 --- /dev/null +++ b/src/main/resources/com/fr/plugins/dsgroup/locale/locale_zh_CN.properties @@ -0,0 +1,9 @@ +Plugin-Data_Set_Group=\u6570\u636e\u96c6\u5206\u7ec4 +Data_Set_Group=\u6570\u636e\u96c6\u5206\u7ec4 +Default_Group_Name=\u672a\u547d\u540d\u5206\u7ec4 +Template=\u6a21\u677f +DS-TableData=\u6570\u636e\u96c6 +DS-Server_TableData=\u670d\u52a1\u5668\u6570\u636e\u96c6 +FR-Designer_Edit=\u7f16\u8f91 +FR-Designer_Remove=\u5220\u9664 +Utils-Are_you_sure_to_remove_the_selected_item=\u4f60\u786e\u5b9e\u51b3\u5b9a\u5220\u9664\u9009\u4e2d\u7684\u9879 \ No newline at end of file diff --git a/src/main/resources/com/fr/plugins/dsgroup/ui/images/query.png b/src/main/resources/com/fr/plugins/dsgroup/ui/images/query.png new file mode 100644 index 0000000000000000000000000000000000000000..a186bdee8fd20cbc36493b23f1590752e2851055 GIT binary patch literal 215 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`^E_P~Ln>}1CoEulp!-inDdzj` zpe66hZLP#~{-5{1!0>R_{;7*f_y12mtYo_X^~Wr+l|LW0pG|wX%l@Cz*8Sg@Z@%An zve_^|pLxPZ;nimydYK%Y3wH9XdZx}C$GUa@_2kWwE1s3FEqHsrY=YDtwg-n5oDZ-) z_#&?u^ZWKZCGiFxNj5ft9=9g8D}Rp7oxqV8aPQ#kDIb9pW2(cdCn*dM1)c@;JeOJx PbSZ