Browse Source

Merge pull request #10161 in DESIGN/design from final/10.0 to persist/10.0

* commit '6eb8004cd48503c33f7409bb2316758def0e783c':
  REPORT-80483 10.0linux设计器图表空数据弹窗点不开
  REPORT-80276 填报-填报属性设置-数据表搜索时概率出现多个重复的搜索结果
  REPORT-79999 填报-填报属性设置-对表的模糊搜索匹配不精确
  REPORT-79909 设计器启动失败,有模板名称叫WorkBook88888888888888.cpt导致
persist/10.0 10.0.19.2022.09.27
superman 2 years ago
parent
commit
a986864ca2
  1. 118
      designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java
  2. 2
      designer-base/src/main/java/com/fr/design/data/datapane/ChoosePaneSupportFormula.java
  3. 4
      designer-base/src/main/java/com/fr/design/gui/icombobox/FRTreeComboBox.java
  4. 77
      designer-base/src/main/java/com/fr/design/gui/icombobox/SearchPreTaskTreeComboBox.java
  5. 236
      designer-base/src/main/java/com/fr/design/gui/icombobox/TableSearchTreeComboBox.java
  6. 72
      designer-base/src/main/java/com/fr/design/mainframe/JTemplateNameHelper.java
  7. 9
      designer-base/src/main/java/com/fr/design/os/impl/SupportOSImpl.java
  8. 23
      designer-base/src/test/java/com/fr/design/mainframe/JTemplateNameHelperTest.java

118
designer-base/src/main/java/com/fr/design/data/datapane/ChoosePane.java

@ -2,17 +2,16 @@ package com.fr.design.data.datapane;
import com.fr.base.TableData; import com.fr.base.TableData;
import com.fr.common.listener.ManageDsListenerRegisterListener; import com.fr.common.listener.ManageDsListenerRegisterListener;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.data.core.DataCoreUtils; import com.fr.data.core.DataCoreUtils;
import com.fr.data.core.db.DBUtils; import com.fr.data.core.db.DBUtils;
import com.fr.data.core.db.TableProcedure; import com.fr.data.core.db.TableProcedure;
import com.fr.data.core.db.dialect.Dialect; import com.fr.data.core.db.dialect.Dialect;
import com.fr.data.core.db.dialect.DialectFactory; import com.fr.data.core.db.dialect.DialectFactory;
import com.fr.data.impl.Connection;
import com.fr.data.impl.DBTableData; import com.fr.data.impl.DBTableData;
import com.fr.data.operator.DataOperator; import com.fr.data.operator.DataOperator;
import com.fr.design.DesignerEnvManager; import com.fr.design.DesignerEnvManager;
import com.fr.design.beans.BasicBeanPane; import com.fr.design.beans.BasicBeanPane;
import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.datapane.RefreshLabel.Refreshable; import com.fr.design.data.datapane.RefreshLabel.Refreshable;
import com.fr.design.data.datapane.preview.PreviewLabel; import com.fr.design.data.datapane.preview.PreviewLabel;
import com.fr.design.data.datapane.preview.PreviewLabel.Previewable; import com.fr.design.data.datapane.preview.PreviewLabel.Previewable;
@ -20,7 +19,7 @@ import com.fr.design.data.datapane.preview.PreviewTablePane;
import com.fr.design.data.tabledata.Prepare4DataSourceChange; import com.fr.design.data.tabledata.Prepare4DataSourceChange;
import com.fr.design.dialog.FineJOptionPane; import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.gui.icombobox.FilterableComboBoxModel; import com.fr.design.gui.icombobox.FilterableComboBoxModel;
import com.fr.design.gui.icombobox.SearchPreTaskTreeComboBox; import com.fr.design.gui.icombobox.TableSearchTreeComboBox;
import com.fr.design.gui.icombobox.UIComboBox; import com.fr.design.gui.icombobox.UIComboBox;
import com.fr.design.gui.icombobox.UIComboBoxEditor; import com.fr.design.gui.icombobox.UIComboBoxEditor;
import com.fr.design.gui.icombobox.UIComboBoxRenderer; import com.fr.design.gui.icombobox.UIComboBoxRenderer;
@ -41,11 +40,6 @@ import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext; import com.fr.workspace.WorkContext;
import com.fr.workspace.server.connection.DBConnectAuth; import com.fr.workspace.server.connection.DBConnectAuth;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.util.Collections;
import java.util.concurrent.CancellationException;
import javax.swing.JList; import javax.swing.JList;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
@ -59,21 +53,20 @@ import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer; import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer; import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath; import javax.swing.tree.TreePath;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.FocusAdapter; import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent; import java.awt.event.FocusEvent;
import java.awt.event.ItemEvent; import java.awt.event.ItemEvent;
import java.awt.event.ItemListener; import java.awt.event.ItemListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Enumeration; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
/** /**
* @author zhou * @author zhou
@ -98,41 +91,12 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
/** /**
* 表名 * 表名
*/ */
protected SearchPreTaskTreeComboBox tableNameComboBox; protected TableSearchTreeComboBox tableNameComboBox;
private static final ExecutorService SERVICE = Executors.newSingleThreadExecutor(new NamedThreadFactory("ChoosePane"));
private SwingWorker populateWorker; private SwingWorker populateWorker;
private SwingWorker<List<String>, Void> initWorker; private SwingWorker<List<String>, Void> initWorker;
private PopupMenuListener popupMenuListener = new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
FutureTask<Void> task = new FutureTask<Void>(new Callable<Void>() {
@Override
public Void call() throws Exception {
calculateTableDataNames();
return null;
}
});
tableNameComboBox.setPreSearchTask(task);
SERVICE.submit(task);
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
// Do nothing
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
// Do nothing
}
};
private PopupMenuListener listener = new PopupMenuListener() { private PopupMenuListener listener = new PopupMenuListener() {
@Override @Override
public void popupMenuCanceled(PopupMenuEvent e) { public void popupMenuCanceled(PopupMenuEvent e) {
@ -182,7 +146,7 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
schemaBox = new StringUIComboBox(); schemaBox = new StringUIComboBox();
schemaBox.setEditor(new ComboBoxEditor()); schemaBox.setEditor(new ComboBoxEditor());
tableNameComboBox = new SearchPreTaskTreeComboBox(new JTree(new DefaultMutableTreeNode()), tableNameTreeRenderer, false); tableNameComboBox = new TableSearchTreeComboBox(this, new JTree(new DefaultMutableTreeNode()), tableNameTreeRenderer);
tableNameComboBox.setEditable(true); tableNameComboBox.setEditable(true);
tableNameComboBox.setRenderer(listCellRenderer); tableNameComboBox.setRenderer(listCellRenderer);
registerDSChangeListener(); registerDSChangeListener();
@ -199,7 +163,6 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
}); });
schemaBox.addPopupMenuListener(listener); schemaBox.addPopupMenuListener(listener);
addFocusListener(); addFocusListener();
this.tableNameComboBox.addPopupMenuListener(popupMenuListener);
} }
protected void addDSBoxListener() { protected void addDSBoxListener() {
@ -356,7 +319,7 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
GUICoreUtils.setSelectedItemQuietly(tableNameComboBox, -1); GUICoreUtils.setSelectedItemQuietly(tableNameComboBox, -1);
} }
protected com.fr.data.impl.Connection getConnection() { public Connection getConnection() {
String selectedDSName = this.getDSName(); String selectedDSName = this.getDSName();
if (StringUtils.isEmpty(selectedDSName)) { if (StringUtils.isEmpty(selectedDSName)) {
return null; // peter:选中了当前的零长度的节点,直接返回. return null; // peter:选中了当前的零长度的节点,直接返回.
@ -456,56 +419,6 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
return "choosepane"; return "choosepane";
} }
protected void calculateTableDataNames() {
JTree tree = tableNameComboBox.getTree();
if (tree == null) {
return;
}
DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) tree.getModel().getRoot();
rootTreeNode.removeAllChildren();
String selectedDSName = this.getDSName();
com.fr.data.impl.Connection selectedDatabase = this.getConnection();
if (selectedDatabase == null) {
return;
}
try {
String schema = StringUtils.isEmpty(this.schemaBox.getSelectedItem()) ? null : this.schemaBox.getSelectedItem();
TableProcedure[] sqlTableArray = DataCoreUtils.getTables(selectedDatabase, TableProcedure.TABLE, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace());
if (sqlTableArray.length > 0) {
ExpandMutableTreeNode tableTreeNode = new ExpandMutableTreeNode(selectedDSName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_Table"));
rootTreeNode.add(tableTreeNode);
for (int i = 0; i < sqlTableArray.length; i++) {
ExpandMutableTreeNode tableChildTreeNode = new ExpandMutableTreeNode(sqlTableArray[i]);
tableTreeNode.add(tableChildTreeNode);
}
}
TableProcedure[] sqlViewArray = DataCoreUtils.getTables(selectedDatabase, TableProcedure.VIEW, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace());
if (sqlViewArray.length > 0) {
ExpandMutableTreeNode viewTreeNode = new ExpandMutableTreeNode(selectedDSName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_View"));
rootTreeNode.add(viewTreeNode);
for (int i = 0; i < sqlViewArray.length; i++) {
ExpandMutableTreeNode viewChildTreeNode = new ExpandMutableTreeNode(sqlViewArray[i]);
viewTreeNode.add(viewChildTreeNode);
}
}
((DefaultTreeModel) tree.getModel()).reload();
// daniel 展开所有tree
TreeNode root = (TreeNode) tree.getModel().getRoot();
TreePath parent = new TreePath(root);
TreeNode node = (TreeNode) parent.getLastPathComponent();
for (Enumeration e = node.children(); e.hasMoreElements(); ) {
TreeNode n = (TreeNode) e.nextElement();
TreePath path = parent.pathByAddingChild(n);
tree.expandPath(path);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Failed"),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Failed"), JOptionPane.ERROR_MESSAGE);
}
}
/** /**
* 创建选中的数据集数据 * 创建选中的数据集数据
* *
@ -559,23 +472,24 @@ public class ChoosePane extends BasicBeanPane<DataBaseItems> implements Refresha
return tableData; return tableData;
} }
protected String getDSName() { public String getDSName() {
return this.dsNameComboBox.getSelectedItem(); return this.dsNameComboBox.getSelectedItem();
} }
public String getSchema() {
return this.schemaBox.getSelectedItem();
}
protected void failedToFindTable() { protected void failedToFindTable() {
// Do nothing // Do nothing
} }
protected String getTableName() { protected String getTableName() {
String tableName = ""; String tableName = "";
Object obj = this.tableNameComboBox.getSelectedItemObject(); Object obj = this.tableNameComboBox.getSelectedItem();
if (obj == null) {
obj = this.tableNameComboBox.getSelectedItem();
if (obj == null) { if (obj == null) {
obj = this.tableNameComboBox.getEditor().getItem(); obj = this.tableNameComboBox.getEditor().getItem();
} }
}
if (obj instanceof TreePath) { if (obj instanceof TreePath) {
Object tp = ((ExpandMutableTreeNode) ((TreePath) obj).getLastPathComponent()).getUserObject(); Object tp = ((ExpandMutableTreeNode) ((TreePath) obj).getLastPathComponent()).getUserObject();
if (tp instanceof TableProcedure) { if (tp instanceof TableProcedure) {

2
designer-base/src/main/java/com/fr/design/data/datapane/ChoosePaneSupportFormula.java

@ -83,7 +83,7 @@ public class ChoosePaneSupportFormula extends ChoosePane {
* *
* @return * @return
*/ */
protected String getDSName() { public String getDSName() {
String selectedDSName = null; String selectedDSName = null;
String item = Utils.objectToString(this.dsNameComboBox.getEditor().getItem()); String item = Utils.objectToString(this.dsNameComboBox.getEditor().getItem());
// 没有选中的列表项 那么看看是不是手输值 // 没有选中的列表项 那么看看是不是手输值

4
designer-base/src/main/java/com/fr/design/gui/icombobox/FRTreeComboBox.java

@ -248,7 +248,7 @@ public class FRTreeComboBox extends UIComboBox {
private static TreePopup treePopup; private static TreePopup treePopup;
private static class FRTreeComboBoxUI extends BasicComboBoxUI implements MouseListener{ protected static class FRTreeComboBoxUI extends BasicComboBoxUI implements MouseListener{
private boolean isRollover = false; private boolean isRollover = false;
public FRTreeComboBoxUI() { public FRTreeComboBoxUI() {
@ -535,7 +535,7 @@ public class FRTreeComboBox extends UIComboBox {
public class FrTreeSearchComboBoxEditor extends UIComboBoxEditor implements DocumentListener { public class FrTreeSearchComboBoxEditor extends UIComboBoxEditor implements DocumentListener {
private volatile boolean setting = false; private volatile boolean setting = false;
private FRTreeComboBox comboBox; private FRTreeComboBox comboBox;
private Object item; protected Object item;
public FrTreeSearchComboBoxEditor(FRTreeComboBox comboBox) { public FrTreeSearchComboBoxEditor(FRTreeComboBox comboBox) {
super(); super();

77
designer-base/src/main/java/com/fr/design/gui/icombobox/SearchPreTaskTreeComboBox.java

@ -1,77 +0,0 @@
package com.fr.design.gui.icombobox;
import com.fr.log.FineLoggerFactory;
import javax.swing.JTree;
import javax.swing.SwingWorker;
import javax.swing.tree.TreeCellRenderer;
import java.util.concurrent.FutureTask;
/**
* 模糊搜索前需执行完前置任务的TreeComboBox
* @author Lucian.Chen
* @version 10.0
* Created by Lucian.Chen on 2021/4/14
*/
public class SearchPreTaskTreeComboBox extends FRTreeComboBox {
/**
* 模糊搜索前任务
*/
private FutureTask<Void> preSearchTask;
public SearchPreTaskTreeComboBox(JTree tree, TreeCellRenderer renderer, boolean editable) {
super(tree, renderer, editable);
}
public FutureTask<Void> getPreSearchTask() {
return preSearchTask;
}
public void setPreSearchTask(FutureTask<Void> preSearchTask) {
this.preSearchTask = preSearchTask;
}
protected UIComboBoxEditor createEditor() {
return new SearchPreTaskComboBoxEditor(this);
}
private class SearchPreTaskComboBoxEditor extends FrTreeSearchComboBoxEditor {
public SearchPreTaskComboBoxEditor(FRTreeComboBox comboBox) {
super(comboBox);
}
protected void changeHandler() {
if (isSetting()) {
return;
}
setPopupVisible(true);
new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() {
FutureTask<Void> task = getPreSearchTask();
try {
// 确保模糊搜索前任务执行完成后,再进行模糊搜索
if (task != null) {
task.get();
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
if (task != null) {
// 任务执行后置空,否则会被别的操作重复触发
setPreSearchTask(null);
}
return null;
}
@Override
protected void done() {
// 模糊搜索
search();
}
}.execute();
}
}
}

236
designer-base/src/main/java/com/fr/design/gui/icombobox/TableSearchTreeComboBox.java

@ -0,0 +1,236 @@
package com.fr.design.gui.icombobox;
import com.fr.concurrent.NamedThreadFactory;
import com.fr.data.core.DataCoreUtils;
import com.fr.data.core.db.TableProcedure;
import com.fr.data.impl.Connection;
import com.fr.design.DesignerEnvManager;
import com.fr.design.data.datapane.ChoosePane;
import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode;
import com.fr.design.mainframe.DesignerContext;
import com.fr.log.FineLoggerFactory;
import com.fr.module.ModuleContext;
import com.fr.stable.ArrayUtils;
import com.fr.stable.Filter;
import com.fr.stable.StringUtils;
import javax.swing.JOptionPane;
import javax.swing.JTree;
import javax.swing.SwingWorker;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeCellRenderer;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.util.Enumeration;
import java.util.concurrent.ExecutorService;
/**
* 实现模糊搜索表名的FRTreeComboBox
* FRTreeComboBox搜索后滚动到首个匹配节点
* SearchFRTreeComboBox显示所有匹配的节点
*
* @author Lucian.Chen
* @version 10.0
* Created by Lucian.Chen on 2021/4/14
*/
public class TableSearchTreeComboBox extends FRTreeComboBox {
// 持有父容器,需要实时获取其他组件值
private final ChoosePane parent;
/**
* 保证模糊搜索的原子性操作
*/
private final ExecutorService singleExecutor = ModuleContext.getExecutor().newSingleThreadScheduledExecutor(new NamedThreadFactory("TableSearchTreeComboBox"));
public TableSearchTreeComboBox(ChoosePane parent, JTree tree, TreeCellRenderer renderer) {
super(tree, renderer);
this.parent = parent;
initPopupListener();
}
protected UIComboBoxEditor createEditor() {
return new TableSearchComboBoxEditor(this);
}
@Override
protected String pathToString(TreePath path) {
Object obj = ((DefaultMutableTreeNode) path.getLastPathComponent()).getUserObject();
if (obj instanceof TableProcedure) {
return ((TableProcedure) obj).getName();
}
return super.pathToString(path);
}
@Override
public void setSelectedItemString(String _name) {
super.setSelectedItemString(_name);
// 会因为连续两次选中的值一致,导致未触发编辑框联动
this.getEditor().setItem(_name);
}
/**
* 执行模糊搜索
*/
private void searchExecute() {
UIComboBoxEditor searchEditor = (UIComboBoxEditor) this.getEditor();
String searchText = (String) searchEditor.getItem();
singleExecutor.execute(new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() {
processTableDataNames(
parent.getDSName(),
parent.getConnection(),
parent.getSchema(),
createFilter(searchText));
return null;
}
@Override
protected void done() {
expandTree();
// 输入框获取焦点
searchEditor.getEditorComponent().requestFocus();
}
});
}
private TableNameFilter createFilter(String text) {
return StringUtils.isEmpty(text) ? EMPTY_FILTER : new TableNameFilter(text);
}
/**
* 查询数据库表并构建节点目录
*
* @param databaseName 数据库名
* @param connection 数据连接
* @param schema 模式
* @param filter 模糊搜索过滤器
*/
private void processTableDataNames(String databaseName, Connection connection, String schema, TableNameFilter filter) {
if (tree == null) {
return;
}
DefaultMutableTreeNode rootTreeNode = (DefaultMutableTreeNode) tree.getModel().getRoot();
rootTreeNode.removeAllChildren();
if (connection == null) {
return;
}
try {
schema = StringUtils.isEmpty(schema) ? null : schema;
TableProcedure[] sqlTableArray = DataCoreUtils.getTables(connection, TableProcedure.TABLE, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace());
if (ArrayUtils.isNotEmpty(sqlTableArray)) {
ExpandMutableTreeNode tableTreeNode = new ExpandMutableTreeNode(databaseName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_Table"));
rootTreeNode.add(tableTreeNode);
addArrayNode(tableTreeNode, sqlTableArray, filter);
}
TableProcedure[] sqlViewArray = DataCoreUtils.getTables(connection, TableProcedure.VIEW, schema, DesignerEnvManager.getEnvManager().isOracleSystemSpace());
if (ArrayUtils.isNotEmpty(sqlViewArray)) {
ExpandMutableTreeNode viewTreeNode = new ExpandMutableTreeNode(databaseName + "-" + com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_SQL_View"));
rootTreeNode.add(viewTreeNode);
addArrayNode(viewTreeNode, sqlViewArray, filter);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
FineJOptionPane.showMessageDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Failed"),
com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Failed"), JOptionPane.ERROR_MESSAGE);
}
}
private void addArrayNode(ExpandMutableTreeNode rootNode, TableProcedure[] sqlArray, TableNameFilter filter) {
if (sqlArray != null) {
for (TableProcedure procedure : sqlArray) {
if (filter.accept(procedure)) {
ExpandMutableTreeNode viewChildTreeNode = new ExpandMutableTreeNode(procedure);
rootNode.add(viewChildTreeNode);
}
}
}
}
/**
* 展开节点
*/
private void expandTree() {
((DefaultTreeModel) tree.getModel()).reload();
// daniel 展开所有tree
TreeNode root = (TreeNode) tree.getModel().getRoot();
TreePath parent = new TreePath(root);
TreeNode node = (TreeNode) parent.getLastPathComponent();
for (Enumeration e = node.children(); e.hasMoreElements(); ) {
TreeNode n = (TreeNode) e.nextElement();
TreePath path = parent.pathByAddingChild(n);
tree.expandPath(path);
}
}
/**
* 表名模糊搜索实现
*/
private static class TableNameFilter implements Filter<TableProcedure> {
private String searchFilter;
public TableNameFilter() {
}
public TableNameFilter(String searchFilter) {
this.searchFilter = searchFilter.toLowerCase().trim();
}
// 表名匹配
@Override
public boolean accept(TableProcedure procedure) {
return procedure.getName().toLowerCase().contains(searchFilter);
}
}
private static final TableNameFilter EMPTY_FILTER = new TableNameFilter() {
public boolean accept(TableProcedure procedure) {
return true;
}
};
private void initPopupListener() {
// 点击下拉时触发模糊搜索
this.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
searchExecute();
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
});
}
/**
* 重写输入框编辑器实现输入框模糊搜索逻辑
*/
private class TableSearchComboBoxEditor extends FrTreeSearchComboBoxEditor {
public TableSearchComboBoxEditor(FRTreeComboBox comboBox) {
super(comboBox);
}
@Override
protected void changeHandler() {
if (isSetting()) {
return;
}
setPopupVisible(true);
this.item = textField.getText();
searchExecute();
}
}
}

72
designer-base/src/main/java/com/fr/design/mainframe/JTemplateNameHelper.java

@ -3,8 +3,10 @@ package com.fr.design.mainframe;
import com.fr.design.file.TemplateTreePane; import com.fr.design.file.TemplateTreePane;
import com.fr.design.gui.itree.filetree.TemplateFileTree; import com.fr.design.gui.itree.filetree.TemplateFileTree;
import com.fr.stable.StringUtils; import com.fr.stable.StringUtils;
import org.jetbrains.annotations.Nullable;
import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultMutableTreeNode;
import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -27,19 +29,18 @@ public class JTemplateNameHelper {
DefaultMutableTreeNode gen = (DefaultMutableTreeNode) tt.getModel().getRoot(); DefaultMutableTreeNode gen = (DefaultMutableTreeNode) tt.getModel().getRoot();
String[] str = new String[gen.getChildCount()]; String[] str = new String[gen.getChildCount()];
List<Integer> reportNum = new ArrayList<>(); List<BigInteger> reportNum = new ArrayList<>();
for (int j = 0; j < gen.getChildCount(); j++) { for (int j = 0; j < gen.getChildCount(); j++) {
str[j] = gen.getChildAt(j).toString(); str[j] = gen.getChildAt(j).toString();
//返回文件名中的index(算法中没有再匹配文件后缀了,因为DefaultMutableTreeNode中已经匹配过了) //返回文件名中的index(算法中没有再匹配文件后缀了,因为DefaultMutableTreeNode中已经匹配过了)
Integer index = getFileNameIndex(prefix, str[j]); BigInteger index = getFileNameIndex(prefix, str[j]);
if (index != null) { if (index != null) {
reportNum.add(index); reportNum.add(index);
} }
} }
Collections.sort(reportNum); Collections.sort(reportNum);
int idx = reportNum.size() > 0 ? reportNum.get(reportNum.size() - 1) + 1 : 1; BigInteger idx = reportNum.size() > 0 ? reportNum.get(reportNum.size() - 1).add(BigInteger.valueOf(1)) : BigInteger.valueOf(1);
idx = idx.add(BigInteger.valueOf(currentIndex));
idx = idx + currentIndex;
currentIndex++; currentIndex++;
return prefix + idx; return prefix + idx;
} }
@ -52,35 +53,58 @@ public class JTemplateNameHelper {
* @Author Henry.Wang * @Author Henry.Wang
* @Date 2021/4/9 11:13 * @Date 2021/4/9 11:13
**/ **/
private static Integer getFileNameIndex(String prefix, String fileName) { @Nullable
if (fileName.length() <= prefix.length()) { private static BigInteger getFileNameIndex(String prefix, String fileName) {
//如果文件名长度小于等于前缀长度或者匹配前缀失败,直接返回就可以了
if ((prefix.length() >= fileName.length()) || (!StringUtils.equals(prefix, fileName.substring(0, prefix.length())))) {
return null; return null;
} }
char[] chars = new char[fileName.length()]; BigInteger integer = null;
int i = 0; integer = matchFileNameIndex(prefix, fileName);
for (; i < fileName.length(); i++) { return integer;
char c = fileName.charAt(i);
//匹配前缀
if (i < prefix.length()) {
if (c != prefix.charAt(i)) {
return null;
} }
} else {
if (c == '.') { /**
* 匹配文件名称的数字后缀Index
* @param prefix 前缀
* @param fileName 文件名称全名
* @return 返回对应的数字后缀Index
*/
@Nullable
private static BigInteger matchFileNameIndex(String prefix, String fileName) {
StringBuilder result = new StringBuilder();
for (int i = prefix.length(); i < fileName.length(); i++) {
char c = fileName.charAt(i);
if (isDot(c)) {
break; break;
} else { } else {
//匹配0~9 if (isNotNumber(c)) {
if (c < 48 || c > 57) {
return null; return null;
} }
chars[i - prefix.length()] = c; result.append(c);
}
} }
} }
String s = new String(chars).substring(0, i - prefix.length()); if (StringUtils.isBlank(result.toString())) {
if (StringUtils.isBlank(s)) {
return null; return null;
} }
return Integer.valueOf(s); return new BigInteger(result.toString(), 10);
}
/**
* 是否不属于数字0-9
* @param c 用于判断的char
* @return 返回对应判断结果
*/
private static boolean isNotNumber(char c) {
return c < 48 || c > 57;
}
/**
* 是否属于'.'
* @param c 用于判断的char
* @return 返回对应判断结果
*/
private static boolean isDot(char c) {
return c == '.';
} }
} }

9
designer-base/src/main/java/com/fr/design/os/impl/SupportOSImpl.java

@ -148,10 +148,15 @@ public enum SupportOSImpl implements SupportOS {
}, },
OLD_STYLE_CHOOSER { OLD_STYLE_CHOOSER {
@Override @Override
public boolean support() { public boolean support() {
return (OperatingSystem.isLinux() && Arch.getArch() == Arch.ARM) || MACOS_12_VERSION_ADAPTER.support(); boolean javafxExist = true;
try {
Class.forName("javafx.stage.FileChooser");
} catch (ClassNotFoundException e) {
javafxExist = false;
}
return !javafxExist || (OperatingSystem.isLinux() && Arch.getArch() == Arch.ARM) || MACOS_12_VERSION_ADAPTER.support();
} }
}, },

23
designer-base/src/test/java/com/fr/design/mainframe/JTemplateNameHelperTest.java

@ -1,5 +1,6 @@
package com.fr.design.mainframe; package com.fr.design.mainframe;
import com.fr.invoke.Reflect;
import junit.framework.TestCase; import junit.framework.TestCase;
/** /**
@ -20,4 +21,26 @@ public class JTemplateNameHelperTest extends TestCase {
assertEquals("TEST2", name1); assertEquals("TEST2", name1);
} }
public void testGetFileNameIndex() {
//正常情况
assertEquals("1", Reflect.on(JTemplateNameHelper.class).call("getFileNameIndex", "WorkBook", "WorkBook1").toString());
//正常情况
assertEquals("8888888888", Reflect.on(JTemplateNameHelper.class).call("getFileNameIndex", "WorkBook", "WorkBook8888888888").toString());
//正常情况
assertEquals("88812214128888881231238123123", Reflect.on(JTemplateNameHelper.class).call("getFileNameIndex", "WorkBook", "WorkBook88812214128888881231238123123").toString());
//前缀不匹配
assertNull(Reflect.on(JTemplateNameHelper.class).call("getFileNameIndex", "Work123", "WorkBook8888888888").get());
//前缀为空
assertNull(Reflect.on(JTemplateNameHelper.class).call("getFileNameIndex", "", "WorkBook8888888888").get());
//文件长度小于前缀
assertNull(Reflect.on(JTemplateNameHelper.class).call("getFileNameIndex", "WorkBook", "").get());
}
} }

Loading…
Cancel
Save