Browse Source
Merge in DESIGN/design from ~LUCIAN.CHEN/design:feature/x to feature/x * commit 'd075335787fa68cfaf133a9711036b2928091c8a': REPORT-62876 填报配置时支持表的精确搜索feature/x
Lucian.Chen
3 years ago
5 changed files with 218 additions and 177 deletions
@ -0,0 +1,200 @@ |
|||||||
|
package com.fr.design.gui.icombobox; |
||||||
|
|
||||||
|
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.stable.ArrayUtils; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import javax.swing.JOptionPane; |
||||||
|
import javax.swing.JTree; |
||||||
|
import javax.swing.SwingWorker; |
||||||
|
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.awt.event.MouseEvent; |
||||||
|
import java.util.Enumeration; |
||||||
|
|
||||||
|
/** |
||||||
|
* 实现模糊搜索的FRTreeComboBox |
||||||
|
* FRTreeComboBox:搜索后滚动到首个匹配节点 |
||||||
|
* SearchFRTreeComboBox:显示所有匹配的节点 |
||||||
|
* |
||||||
|
* @author Lucian.Chen |
||||||
|
* @version 10.0 |
||||||
|
* Created by Lucian.Chen on 2021/4/14 |
||||||
|
*/ |
||||||
|
public class SearchFRTreeComboBox extends FRTreeComboBox { |
||||||
|
|
||||||
|
// 持有父容器,需要实时获取其他组件值
|
||||||
|
private final ChoosePane parent; |
||||||
|
|
||||||
|
public SearchFRTreeComboBox(ChoosePane parent, JTree tree, TreeCellRenderer renderer) { |
||||||
|
super(tree, renderer); |
||||||
|
this.parent = parent; |
||||||
|
setUI(new SearchFRTreeComboBoxUI()); |
||||||
|
} |
||||||
|
|
||||||
|
protected UIComboBoxEditor createEditor() { |
||||||
|
return new SearchFRComboBoxEditor(this); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 执行模糊搜索 |
||||||
|
*/ |
||||||
|
private void searchExecute() { |
||||||
|
UIComboBoxEditor searchEditor = (UIComboBoxEditor) this.getEditor(); |
||||||
|
new SwingWorker<Void, Void>() { |
||||||
|
@Override |
||||||
|
protected Void doInBackground() { |
||||||
|
processTableDataNames( |
||||||
|
parent.getDSName(), |
||||||
|
parent.getConnection(), |
||||||
|
parent.getSchema(), |
||||||
|
createFilter((String) searchEditor.getItem())); |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void done() { |
||||||
|
expandTree(); |
||||||
|
// 输入框获取焦点
|
||||||
|
searchEditor.getEditorComponent().requestFocus(); |
||||||
|
} |
||||||
|
}.execute(); |
||||||
|
} |
||||||
|
|
||||||
|
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 class SearchFRComboBoxEditor extends FrTreeSearchComboBoxEditor { |
||||||
|
|
||||||
|
public SearchFRComboBoxEditor(FRTreeComboBox comboBox) { |
||||||
|
super(comboBox); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void changeHandler() { |
||||||
|
if (isSetting()) { |
||||||
|
return; |
||||||
|
} |
||||||
|
setPopupVisible(true); |
||||||
|
this.item = textField.getText(); |
||||||
|
searchExecute(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static final TableNameFilter EMPTY_FILTER = new TableNameFilter(StringUtils.EMPTY) { |
||||||
|
public boolean accept(TableProcedure procedure) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* 表名模糊搜索实现 |
||||||
|
*/ |
||||||
|
private static class TableNameFilter { |
||||||
|
private final String searchFilter; |
||||||
|
|
||||||
|
public TableNameFilter(String searchFilter) { |
||||||
|
if (StringUtils.isNotEmpty(searchFilter)) { |
||||||
|
searchFilter = searchFilter.toLowerCase().trim(); |
||||||
|
} |
||||||
|
this.searchFilter = searchFilter; |
||||||
|
} |
||||||
|
|
||||||
|
// 字符串匹配
|
||||||
|
public boolean accept(TableProcedure procedure) { |
||||||
|
return procedure.getName().toLowerCase().contains(searchFilter); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 重写FRTreeComboBoxUI,实现点击下拉时触发模糊搜索 |
||||||
|
*/ |
||||||
|
private class SearchFRTreeComboBoxUI extends FRTreeComboBoxUI { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void mouseClicked(MouseEvent e) { |
||||||
|
searchExecute(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue