lucian
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