Browse Source

Merge pull request #9590 in DESIGN/design from feature/10.0 to feature/big-screen

* commit '40a82abde40b0437e7abcc89f7770b6f19095329':
  REPORT-72635 - 数据连接面板为空的问题(含控制权限) 有些新类,没提交进去
  REPORT-72635 - 数据连接面板为空的问题(含控制权限) 【问题原因】同步到10.0 【改动思路】同步到10.0 【review建议】无
  REPORT-76370 提供一个数据连接前置检查接口&提交10.0
  REPORT-76370 提供一个数据连接前置检查接口&提交10.0
feature/big-screen
superman 2 years ago
parent
commit
047d1106ef
  1. 63
      designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java
  2. 57
      designer-base/src/main/java/com/fr/design/data/datapane/auth/TableDataAuthHelper.java
  3. 38
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java
  4. 18
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java
  5. 115
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java
  6. 16
      designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java
  7. 62
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java
  8. 23
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/SwitchableTableDataPane.java
  9. 54
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TableDataLoadingPane.java
  10. 45
      designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TipsPane.java

63
designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java

@ -2,6 +2,7 @@ package com.fr.design.data.datapane;
import com.fr.base.TableData; import com.fr.base.TableData;
import com.fr.data.TableDataSource; import com.fr.data.TableDataSource;
import com.fr.data.impl.DBTableData;
import com.fr.data.impl.TableDataSourceDependent; import com.fr.data.impl.TableDataSourceDependent;
import com.fr.design.DesignModelAdapter; import com.fr.design.DesignModelAdapter;
import com.fr.design.ExtraDesignClassManager; import com.fr.design.ExtraDesignClassManager;
@ -10,8 +11,10 @@ import com.fr.design.constants.UIConstants;
import com.fr.design.data.BasicTableDataTreePane; import com.fr.design.data.BasicTableDataTreePane;
import com.fr.design.data.BasicTableDataUtils; import com.fr.design.data.BasicTableDataUtils;
import com.fr.design.data.DesignTableDataManager; import com.fr.design.data.DesignTableDataManager;
import com.fr.design.data.datapane.auth.TableDataAuthHelper;
import com.fr.design.data.tabledata.StoreProcedureWorkerListener; import com.fr.design.data.tabledata.StoreProcedureWorkerListener;
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.loading.TableDataLoadingPane;
import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper; import com.fr.design.data.tabledata.wrapper.AbstractTableDataWrapper;
import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.BasicPane;
@ -31,6 +34,7 @@ import com.fr.design.menu.ToolBarDef;
import com.fr.general.ComparatorUtils; import com.fr.general.ComparatorUtils;
import com.fr.general.GeneralContext; import com.fr.general.GeneralContext;
import com.fr.general.NameObject; import com.fr.general.NameObject;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.context.PluginContext; import com.fr.plugin.context.PluginContext;
import com.fr.plugin.injectable.PluginModule; import com.fr.plugin.injectable.PluginModule;
import com.fr.plugin.manage.PluginFilter; import com.fr.plugin.manage.PluginFilter;
@ -42,6 +46,7 @@ import javax.swing.BorderFactory;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.ToolTipManager; import javax.swing.ToolTipManager;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.GridLayout; import java.awt.GridLayout;
@ -49,6 +54,7 @@ import java.awt.dnd.DnDConstants;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
@ -239,7 +245,11 @@ public class TableDataTreePane extends BasicTableDataTreePane {
doPropertyChange(dg, nPanel, oldName); doPropertyChange(dg, nPanel, oldName);
} }
}); });
dg.setVisible(true); // 有些数据集(DBTableData)面板的初始化过程中是包含了SwingWorker处理(查询数据连接、查表等)的
// 如果这里直接setVisible,可能阻塞SwingWorker的done方法,导致面板渲染出现问题
SwingUtilities.invokeLater(() -> {
dg.setVisible(true);
});
} }
private class EditAction extends UpdateAction { private class EditAction extends UpdateAction {
@ -249,13 +259,60 @@ public class TableDataTreePane extends BasicTableDataTreePane {
this.setSmallIcon("/com/fr/design/images/control/edit"); this.setSmallIcon("/com/fr/design/images/control/edit");
} }
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
final NameObject selectedNO = dataTree.getSelectedNameObject(); final NameObject selectedNO = dataTree.getSelectedNameObject();
if (selectedNO == null) { if (selectedNO == null) {
return; return;
} }
DesignTableDataManager.removeSelectedColumnNames(selectedNO.getName());
dgEdit(((AbstractTableDataWrapper) selectedNO.getObject()).creatTableDataPane(), selectedNO.getName(), false); 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(TableDataTreePane.this), null);
// 查询权限
new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() throws Exception {
// 获取无权限连接名称集合
Collection<String> 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);
} 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);
}
} }
} }

57
designer-base/src/main/java/com/fr/design/data/datapane/auth/TableDataAuthHelper.java

@ -0,0 +1,57 @@
package com.fr.design.data.datapane.auth;
import com.fr.base.TableData;
import com.fr.data.impl.Connection;
import com.fr.data.impl.DBTableData;
import com.fr.data.impl.NameDatabaseConnection;
import com.fr.stable.StringUtils;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.connection.DBConnectAuth;
import java.util.Collection;
import java.util.Collections;
/**
* 数据连接权限相关的工具类
* @author Yvan
*/
public class TableDataAuthHelper {
/**
* 编辑数据集时是否需要检查权限
* @param tableData
* @return
*/
public static boolean needCheckAuthWhenEdit(TableData tableData) {
// 远程设计下,编辑DBTableData时需要判断权限
return !WorkContext.getCurrent().isLocal() && tableData instanceof DBTableData;
}
/**
* 获取无权限数据连接集合
* 远程下需要调用RPC为耗时操作谨慎使用
* @return
*/
public static Collection<String> getNoAuthConnections() {
// 获取无权限连接集合
Collection<String> noAuthConnections = WorkContext.getCurrent().get(DBConnectAuth.class).getNoAuthConnections();
return noAuthConnections == null ? Collections.emptyList() : noAuthConnections;
}
/**
* 通过数据集获取其数据连接的名称
*
* 注意
* 1. Connection接口本身是不提供名称的只有我们内部为了使用方便将其包装成了NameDataBaseConnection
* 如果不是NameDataBaseConnection类型则无名称因此这里只能用判断类型的方式获取名称
* 2. 仅支持DBTableData获取连接名
* @return
*/
public static String getConnectionNameByDBTableData(DBTableData tableData) {
Connection database = tableData.getDatabase();
if (database instanceof NameDatabaseConnection) {
return ((NameDatabaseConnection) database).getName();
}
return StringUtils.EMPTY;
}
}

38
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionComboBoxPanel.java

@ -200,18 +200,34 @@ public class ConnectionComboBoxPanel extends ItemEditableComboBoxPanel {
if (connection instanceof NameDatabaseConnection) { if (connection instanceof NameDatabaseConnection) {
this.setSelectedItem(((NameDatabaseConnection) connection).getName()); this.setSelectedItem(((NameDatabaseConnection) connection).getName());
} else { } else {
String s = DesignerEnvManager.getEnvManager().getRecentSelectedConnection(); setRecentConnection();
if (StringUtils.isNotBlank(s)) { }
// 之前的写法有多线程问题,nameList异步尚未初始化完成的时候,这里可能无法匹配设置数据连接名称,导致DBTableDataPane打开后连接面板空白 }
// 这里的需求无非是设置上一次使用的数据连接,做个简单检查这个连接是否存在即可,存在就设置
if (nameList.contains(s)) { /**
this.setSelectedItem(s); * 下拉框选项设置成最近选择的connection如果最近选择不存在则选择列表中的第一个
} */
} protected void setRecentConnection() {
// alex:如果这个ComboBox还是没有选中,那么选中第一个 String s = DesignerEnvManager.getEnvManager().getRecentSelectedConnection();
if (StringUtils.isBlank(this.getSelectedItem()) && this.getConnectionSize() > 0) { if (StringUtils.isNotBlank(s)) {
this.setSelectedItem(this.getConnection(0)); // 之前的写法有多线程问题,nameList异步尚未初始化完成的时候,这里可能无法匹配设置数据连接名称,导致DBTableDataPane打开后连接面板空白
// 这里的需求无非是设置上一次使用的数据连接,做个简单检查这个连接是否存在即可,存在就设置
if (nameList.contains(s)) {
this.setSelectedItem(s);
} }
} }
// alex:如果这个ComboBox还是没有选中,那么选中第一个
if (StringUtils.isBlank(this.getSelectedItem()) && this.getConnectionSize() > 0) {
this.setSelectedItem(this.getConnection(0));
}
}
/**
* 是否无选中状态空白item也视为无选中
* @return
*/
protected boolean isSelectedItemEmpty() {
String selectedItem = this.getSelectedItem();
return selectedItem == null || StringUtils.equals(selectedItem, EMPTY.toString());
} }
} }

18
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionListPane.java

@ -1,10 +1,9 @@
package com.fr.design.data.datapane.connect; package com.fr.design.data.datapane.connect;
import com.fr.base.TemplateUtils;
import com.fr.data.core.db.JDBCSecurityChecker;
import com.fr.data.impl.Connection; import com.fr.data.impl.Connection;
import com.fr.data.impl.JDBCDatabaseConnection; import com.fr.data.impl.JDBCDatabaseConnection;
import com.fr.data.impl.JNDIDatabaseConnection; import com.fr.data.impl.JNDIDatabaseConnection;
import com.fr.data.operator.DataOperator;
import com.fr.design.ExtraDesignClassManager; import com.fr.design.ExtraDesignClassManager;
import com.fr.design.data.MapCompareUtils; import com.fr.design.data.MapCompareUtils;
import com.fr.design.dialog.FineJOptionPane; import com.fr.design.dialog.FineJOptionPane;
@ -181,7 +180,7 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh
} }
}); });
this.checkSecurity(addedOrUpdatedConnections); this.validateConnections(addedOrUpdatedConnections);
alterConnections(removedConnNames, addedOrUpdatedConnections); alterConnections(removedConnNames, addedOrUpdatedConnections);
} }
@ -190,17 +189,14 @@ public class ConnectionListPane extends JListControlPane implements ConnectionSh
addedOrUpdatedConnections.forEach((name, conn) -> ConnectionConfig.getInstance().addConnection(name, conn)); addedOrUpdatedConnections.forEach((name, conn) -> ConnectionConfig.getInstance().addConnection(name, conn));
} }
private void checkSecurity(Map<String, Connection> addedOrUpdatedConnections) throws Exception { private void validateConnections(Map<String, Connection> addedOrUpdatedConnections) throws Exception {
for (Map.Entry<String, Connection> entry : addedOrUpdatedConnections.entrySet()) { for (Map.Entry<String, Connection> entry : addedOrUpdatedConnections.entrySet()) {
Connection connection = entry.getValue(); Connection connection = entry.getValue();
if (connection instanceof JDBCDatabaseConnection) { try {
try { DataOperator.getInstance().validateConnectionSettings(connection);
JDBCSecurityChecker.checkURL(TemplateUtils.render(((JDBCDatabaseConnection) connection).getURL())); } catch (SQLException e) {
JDBCSecurityChecker.checkValidationQuery(((JDBCDatabaseConnection) connection).getDbcpAttr().getValidationQuery()); throw new SQLException(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Invalid_Config", entry.getKey()) + ", " + e.getMessage(), e.getCause());
} catch (SQLException e) {
throw new SQLException(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Invalid_Config", entry.getKey()) + ", " + e.getMessage(), e.getCause());
}
} }
} }
} }

115
designer-base/src/main/java/com/fr/design/data/datapane/connect/ConnectionTableProcedurePane.java

@ -1,26 +1,32 @@
package com.fr.design.data.datapane.connect; package com.fr.design.data.datapane.connect;
import com.fr.base.BaseUtils; import com.fr.base.BaseUtils;
import com.fr.base.svg.IconUtils;
import com.fr.data.core.db.TableProcedure; import com.fr.data.core.db.TableProcedure;
import com.fr.data.impl.AbstractDatabaseConnection; import com.fr.data.impl.AbstractDatabaseConnection;
import com.fr.data.impl.Connection; import com.fr.data.impl.Connection;
import com.fr.design.border.UIRoundedBorder; import com.fr.design.border.UIRoundedBorder;
import com.fr.design.constants.UIConstants; import com.fr.design.constants.UIConstants;
import com.fr.design.data.tabledata.tabledatapane.DBTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.loading.SwitchableTableDataPane;
import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.BasicPane;
import com.fr.design.gui.icheckbox.UICheckBox; import com.fr.design.gui.icheckbox.UICheckBox;
import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.icontainer.UIScrollPane;
import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.ilable.UILabel;
import com.fr.design.gui.ilist.TableViewList; import com.fr.design.gui.ilist.TableViewList;
import com.fr.design.gui.itextfield.UITextField; import com.fr.design.gui.itextfield.UITextField;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.general.GeneralContext; import com.fr.general.GeneralContext;
import com.fr.stable.ArrayUtils; import com.fr.stable.ArrayUtils;
import javax.swing.BorderFactory;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.ToolTipManager; import javax.swing.ToolTipManager;
import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener; import javax.swing.event.DocumentListener;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
@ -45,7 +51,39 @@ public class ConnectionTableProcedurePane extends BasicPane {
private java.util.List<DoubleClickSelectedNodeOnTreeListener> listeners = new java.util.ArrayList<DoubleClickSelectedNodeOnTreeListener>(); private java.util.List<DoubleClickSelectedNodeOnTreeListener> listeners = new java.util.ArrayList<DoubleClickSelectedNodeOnTreeListener>();
public ConnectionTableProcedurePane() { public ConnectionTableProcedurePane() {
init(null);
}
/**
* 传入父容器
* @param parent
*/
public ConnectionTableProcedurePane(SwitchableTableDataPane parent) {
init(parent);
}
private void init(SwitchableTableDataPane parent) {
this.setLayout(new BorderLayout(4, 4)); this.setLayout(new BorderLayout(4, 4));
// 初始化数据连接下拉框
initConnectionComboBox(parent);
// 初始化中间的面板
JPanel centerPane = initCenterPane();
this.add(connectionComboBox, BorderLayout.NORTH);
this.add(centerPane, BorderLayout.CENTER);
this.setPreferredSize(new Dimension(WIDTH, getPreferredSize().height));
addKeyMonitor();
}
private JPanel initCenterPane() {
JPanel centerPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
// 搜索面板
centerPane.add(createSearchPane(), BorderLayout.NORTH);
// 数据库表视图面板
centerPane.add(createTableViewBorderPane(), BorderLayout.CENTER);
return centerPane;
}
private void initConnectionComboBox(SwitchableTableDataPane parent) {
connectionComboBox = new ConnectionComboBoxPanel(com.fr.data.impl.Connection.class) { connectionComboBox = new ConnectionComboBoxPanel(com.fr.data.impl.Connection.class) {
@Override @Override
@ -60,10 +98,34 @@ public class ConnectionTableProcedurePane extends BasicPane {
search(true); search(true);
} }
} }
@Override
protected void afterRefreshItems() {
// 刷新完成后,如果未选中(在nameList初始化完成之前可能会出现),则尝试再次设置
if (isSelectedItemEmpty()) {
setRecentConnection();
}
// 获取数据连接之后,让父容器切换面板
if (parent != null) {
parent.switchTo(SwitchableTableDataPane.CONTENT_PANE_NAME);
}
}
@Override
protected void refreshItemsError() {
// 获取数据连接出现错误时,也让父容器从Loading面板切换至内容面板
if (parent != null) {
parent.switchTo(SwitchableTableDataPane.CONTENT_PANE_NAME);
}
}
}; };
connectionComboBox.addComboBoxActionListener(filter);
}
private JPanel createTableViewBorderPane() {
tableViewList = new TableViewList(); tableViewList = new TableViewList();
ToolTipManager.sharedInstance().registerComponent(tableViewList); ToolTipManager.sharedInstance().registerComponent(tableViewList);
connectionComboBox.addComboBoxActionListener(filter);
tableViewList.addMouseListener(new MouseAdapter() { tableViewList.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) { public void mouseClicked(MouseEvent evt) {
if (evt.getClickCount() >= 2) { if (evt.getClickCount() >= 2) {
@ -80,23 +142,50 @@ public class ConnectionTableProcedurePane extends BasicPane {
} }
} }
}); });
JPanel filterPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); UIScrollPane tableViewListPane = new UIScrollPane(tableViewList);
tableViewListPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC));
JPanel tableViewBorderPane = FRGUIPaneFactory.createBorderLayout_S_Pane();
tableViewBorderPane.add(tableViewListPane, BorderLayout.CENTER);
JPanel checkBoxgroupPane = createCheckBoxgroupPane(); JPanel checkBoxgroupPane = createCheckBoxgroupPane();
if (checkBoxgroupPane != null) { if (checkBoxgroupPane != null) {
filterPane.add(createCheckBoxgroupPane(), BorderLayout.NORTH); tableViewBorderPane.add(createCheckBoxgroupPane(), BorderLayout.SOUTH);
} }
return tableViewBorderPane;
}
/**
* 创建搜索Panel用于搜索表或视图
* @return
*/
private JPanel createSearchPane() {
JPanel panel = FRGUIPaneFactory.createBorderLayout_S_Pane();
JPanel searchPane = new JPanel(new BorderLayout(10, 0)); JPanel searchPane = new JPanel(new BorderLayout(10, 0));
searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR));
searchPane.setBackground(Color.WHITE);
searchField = new UITextField(); searchField = new UITextField();
searchPane.add(searchField, BorderLayout.CENTER); searchField.setBorderPainted(false);
searchField.setPlaceholder(Toolkit.i18nText("Fine-Design_Basic_Table_Search"));
searchField.getDocument().addDocumentListener(searchListener); searchField.getDocument().addDocumentListener(searchListener);
filterPane.add(searchPane, BorderLayout.CENTER); searchField.addMouseListener(new MouseAdapter() {
UIScrollPane tableViewListPane = new UIScrollPane(tableViewList); @Override
tableViewListPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); public void mouseEntered(MouseEvent e) {
this.add(connectionComboBox, BorderLayout.NORTH); super.mouseEntered(e);
this.add(tableViewListPane, BorderLayout.CENTER); searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.CHECKBOX_HOVER_SELECTED));
this.add(filterPane, BorderLayout.SOUTH); }
this.setPreferredSize(new Dimension(WIDTH, getPreferredSize().height));
addKeyMonitor(); @Override
public void mouseExited(MouseEvent e) {
super.mouseExited(e);
searchPane.setBorder(BorderFactory.createLineBorder(UIConstants.TOOLBAR_BORDER_COLOR));
}
});
// 搜索图标
UILabel searchLabel = new UILabel(IconUtils.readIcon("/com/fr/design/images/data/search"));
searchLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 5));
searchPane.add(searchField, BorderLayout.CENTER);
searchPane.add(searchLabel, BorderLayout.EAST);
panel.add(searchPane, BorderLayout.CENTER);
return panel;
} }
protected void filter(Connection connection, String conName, List<String> nameList) { protected void filter(Connection connection, String conName, List<String> nameList) {
@ -224,4 +313,4 @@ public class ConnectionTableProcedurePane extends BasicPane {
*/ */
public void actionPerformed(TableProcedure target); public void actionPerformed(TableProcedure target);
} }
} }

16
designer-base/src/main/java/com/fr/design/data/datapane/connect/ItemEditableComboBoxPanel.java

@ -127,10 +127,12 @@ public abstract class ItemEditableComboBoxPanel extends JPanel {
itemComboBox.setMaximumRowCount(itemComboBox.getMaximumRowCount() + 1); itemComboBox.setMaximumRowCount(itemComboBox.getMaximumRowCount() + 1);
itemComboBox.setMaximumRowCount(itemComboBox.getMaximumRowCount() - 1); itemComboBox.setMaximumRowCount(itemComboBox.getMaximumRowCount() - 1);
} }
afterRefreshItems();
} catch (Exception e) { } catch (Exception e) {
if (!(e instanceof CancellationException)) { if (!(e instanceof CancellationException)) {
FineLoggerFactory.getLogger().error(e.getMessage(), e); FineLoggerFactory.getLogger().error(e.getMessage(), e);
} }
refreshItemsError();
} }
} }
@ -160,6 +162,20 @@ public abstract class ItemEditableComboBoxPanel extends JPanel {
*/ */
protected abstract java.util.Iterator<String> items(); protected abstract java.util.Iterator<String> items();
/**
* 刷新ComboBox.items之后
*/
protected void afterRefreshItems() {
// 空实现,供子类重写
}
/**
* 刷新ComboBox.items时出现异常
*/
protected void refreshItemsError() {
// 空实现,供子类重写
}
/* /*
* 弹出对话框编辑Items * 弹出对话框编辑Items
*/ */

62
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/DBTableDataPane.java

@ -18,6 +18,8 @@ import com.fr.design.data.datapane.connect.ConnectionTableProcedurePane.DoubleCl
import com.fr.design.data.datapane.preview.PreviewTablePane; import com.fr.design.data.datapane.preview.PreviewTablePane;
import com.fr.design.data.datapane.preview.sql.PreviewPerformedSqlPane; import com.fr.design.data.datapane.preview.sql.PreviewPerformedSqlPane;
import com.fr.design.data.datapane.sqlpane.SQLEditPane; import com.fr.design.data.datapane.sqlpane.SQLEditPane;
import com.fr.design.data.tabledata.tabledatapane.loading.SwitchableTableDataPane;
import com.fr.design.data.tabledata.tabledatapane.loading.TipsPane;
import com.fr.design.dialog.BasicDialog; import com.fr.design.dialog.BasicDialog;
import com.fr.design.dialog.BasicPane; import com.fr.design.dialog.BasicPane;
import com.fr.design.dialog.DialogActionAdapter; import com.fr.design.dialog.DialogActionAdapter;
@ -30,6 +32,7 @@ import com.fr.design.gui.itableeditorpane.UITableEditorPane;
import com.fr.design.gui.itoolbar.UIToolbar; import com.fr.design.gui.itoolbar.UIToolbar;
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants; import com.fr.design.gui.syntax.ui.rsyntaxtextarea.SyntaxConstants;
import com.fr.design.gui.syntax.ui.rtextarea.RTextScrollPane; import com.fr.design.gui.syntax.ui.rtextarea.RTextScrollPane;
import com.fr.design.layout.FRGUIPaneFactory;
import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.DesignerContext;
import com.fr.design.menu.SeparatorDef; import com.fr.design.menu.SeparatorDef;
import com.fr.design.menu.ToolBarDef; import com.fr.design.menu.ToolBarDef;
@ -54,6 +57,7 @@ import javax.swing.JToolBar;
import javax.swing.text.BadLocationException; import javax.swing.text.BadLocationException;
import javax.swing.text.Document; import javax.swing.text.Document;
import java.awt.BorderLayout; import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
@ -64,7 +68,7 @@ import java.awt.event.KeyListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class DBTableDataPane extends AbstractTableDataPane<DBTableData> { public class DBTableDataPane extends AbstractTableDataPane<DBTableData> implements SwitchableTableDataPane {
private static final int BOTTOM = 6; private static final int BOTTOM = 6;
private static final String PREVIEW_BUTTON = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview"); private static final String PREVIEW_BUTTON = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Preview");
private static final String REFRESH_BUTTON = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Refresh"); private static final String REFRESH_BUTTON = com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Refresh");
@ -78,8 +82,42 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
private String pageQuery = null; private String pageQuery = null;
private DBTableData dbTableData; private DBTableData dbTableData;
private CardLayout card;
/** 数据库查询面板真正的内容面板 */
private JPanel contentPane;
/** 加载中面板 */
private JPanel loadingPane;
public DBTableDataPane() {
initCards();
initContentPane();
}
/**
* 初始化cardLayout以及LoadingPane等并且布局切到LoadingPane
*/
protected void initCards() {
card = new CardLayout();
setLayout(card);
loadingPane = new TipsPane(true);
contentPane = FRGUIPaneFactory.createNormalFlowInnerContainer_S_Pane();
add(LOADING_PANE_NAME, loadingPane);
add(CONTENT_PANE_NAME, contentPane);
switchTo(LOADING_PANE_NAME);
}
/**
* 初始化内容面板
*/
protected void initContentPane() {
init();
initMainSplitPane();
}
private void init() { private void init() {
this.setLayout(new BorderLayout(4, 4)); contentPane.setLayout(new BorderLayout(4, 4));
sqlTextPane = new SQLEditPane(); sqlTextPane = new SQLEditPane();
sqlTextPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL); sqlTextPane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_SQL);
@ -93,7 +131,7 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
editorPane = new UITableEditorPane<ParameterProvider>(model); editorPane = new UITableEditorPane<ParameterProvider>(model);
// 左边的Panel,上面是选择DatabaseConnection的ComboBox,下面DatabaseConnection对应的Table // 左边的Panel,上面是选择DatabaseConnection的ComboBox,下面DatabaseConnection对应的Table
connectionTableProcedurePane = new ConnectionTableProcedurePane() { connectionTableProcedurePane = new ConnectionTableProcedurePane(this) {
@Override @Override
protected void filter(Connection connection, String conName, List<String> nameList) { protected void filter(Connection connection, String conName, List<String> nameList) {
@ -194,15 +232,23 @@ public class DBTableDataPane extends AbstractTableDataPane<DBTableData> {
JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, connectionTableProcedurePane, sqlSplitPane); JSplitPane mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, connectionTableProcedurePane, sqlSplitPane);
mainSplitPane.setBorder(BorderFactory.createLineBorder(GUICoreUtils.getTitleLineBorderColor())); mainSplitPane.setBorder(BorderFactory.createLineBorder(GUICoreUtils.getTitleLineBorderColor()));
mainSplitPane.setOneTouchExpandable(true); mainSplitPane.setOneTouchExpandable(true);
this.add(mainSplitPane, BorderLayout.CENTER); contentPane.add(mainSplitPane, BorderLayout.CENTER);
} }
public DBTableDataPane() { @Override
init(); public void switchTo(String panelName) {
initMainSplitPane(); try {
if (panelName != null) {
card.show(this, panelName);
}
} catch (IllegalArgumentException ingore) {
// 有些直接继承此面板或者替换掉此面板的插件,在未适配此功能时会出现报错,因为不是CardLayout,无法切换,这里处理下
FineLoggerFactory.getLogger().info("cannot switch pane by {}", this.getClass().getName());
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
} }
private boolean isPreviewOrRefreshButton(FocusEvent e) { private boolean isPreviewOrRefreshButton(FocusEvent e) {
if (e.getOppositeComponent() != null) { if (e.getOppositeComponent() != null) {
String name = e.getOppositeComponent().getName(); String name = e.getOppositeComponent().getName();

23
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/SwitchableTableDataPane.java

@ -0,0 +1,23 @@
package com.fr.design.data.tabledata.tabledatapane.loading;
/**
* 可切换的DBTableData对应的数据集面板需要使用CardLayout布局
* 主要是给插件适配用的
* @author Yvan
*/
public interface SwitchableTableDataPane {
/** Loading面板 */
String LOADING_PANE_NAME = "Loading";
/** 内容面板 */
String CONTENT_PANE_NAME = "Content";
/**
* 根据面板名称切换面板
* @param paneName 面板名称
*/
void switchTo(String paneName);
}

54
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TableDataLoadingPane.java

@ -0,0 +1,54 @@
package com.fr.design.data.tabledata.tabledatapane.loading;
import com.fr.design.dialog.BasicPane;
import com.fr.design.i18n.Toolkit;
import javax.swing.JPanel;
import java.awt.CardLayout;
/**
* @author Yvan
*/
public class TableDataLoadingPane extends BasicPane {
/** Loading面板 */
public static final String LOADING_PANE_NAME = "Loading";
/** 无权限提示面板 */
public static final String NO_AUTH_PANE_NAME = "NoAuthority";
/** 错误提示面板 */
public static final String ERROR_NAME = "Error";
private CardLayout card;
/** 加载中面板 */
private JPanel loadingPane;
/** 错误提示面板 */
private JPanel errorPane;
/** 数据连接无权限面板 */
private JPanel noAuthorityPane;
public TableDataLoadingPane() {
initPanes();
}
private void initPanes() {
card = new CardLayout();
this.setLayout(card);
loadingPane = new TipsPane(true);
errorPane = new TipsPane(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_Error"));
noAuthorityPane = new TipsPane(Toolkit.i18nText("Fine-Design_Basic_Database_Connection_No_Auth"));
add(LOADING_PANE_NAME, loadingPane);
add(NO_AUTH_PANE_NAME, noAuthorityPane);
add(ERROR_NAME, errorPane);
switchTo(LOADING_PANE_NAME);
}
public void switchTo(String panelName) {
card.show(this, panelName);
}
@Override
protected String title4PopupWindow() {
return Toolkit.i18nText("Fine-Design_Basic_DS-Database_Query");
}
}

45
designer-base/src/main/java/com/fr/design/data/tabledata/tabledatapane/loading/TipsPane.java

@ -0,0 +1,45 @@
package com.fr.design.data.tabledata.tabledatapane.loading;
import com.fr.design.gui.ilable.UILabel;
import com.fr.design.i18n.Toolkit;
import com.fr.design.layout.FRGUIPaneFactory;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;
import java.awt.BorderLayout;
/**
* 提示面板支持自定义提示支持进度条配置可选
* @author Yvan
*/
public class TipsPane extends JPanel {
/**
* 默认提示
*/
private static final String LOADING = Toolkit.i18nText("Fine-Design_Basic_Loading_And_Waiting");
public TipsPane () {
this(LOADING, false);
}
public TipsPane (String tip) {
this(tip, false);
}
public TipsPane (boolean needProgressBar) {
this(LOADING, needProgressBar);
}
public TipsPane (String tips, boolean needProgressBar) {
this.setLayout(FRGUIPaneFactory.createBorderLayout());
UILabel tipsLabel = new UILabel(tips, SwingConstants.CENTER);
this.add(tipsLabel, BorderLayout.CENTER);
if (needProgressBar) {
JProgressBar progressBar = new JProgressBar();
progressBar.setIndeterminate(true);
this.add(progressBar, BorderLayout.SOUTH);
}
}
}
Loading…
Cancel
Save