From ccc13cf1dace3de24d30f5b75a93772c2b700ccb Mon Sep 17 00:00:00 2001 From: Yvan Date: Mon, 11 Apr 2022 16:47:14 +0800 Subject: [PATCH] =?UTF-8?q?REPORT-69422=20&&=20REPORT-69426=20=E4=BA=A7?= =?UTF-8?q?=E5=93=81=E8=B0=83=E6=95=B4=E9=83=A8=E5=88=86UI=20&&=20?= =?UTF-8?q?=E5=A4=8D=E5=88=B6=E5=8D=95=E5=85=83=E6=A0=BC=E4=BC=9A=E5=BD=B1?= =?UTF-8?q?=E5=93=8D=E6=95=B0=E6=8D=AE=E9=9B=86=E7=9A=84=E5=B1=95=E5=BC=80?= =?UTF-8?q?/=E6=94=B6=E8=B5=B7=E7=8A=B6=E6=80=81=20=E3=80=90=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E5=8E=9F=E5=9B=A0=E3=80=911.=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E9=AA=8C=E6=94=B6=E5=8A=9F=E8=83=BD=E7=9A=84=E6=97=B6=E5=80=99?= =?UTF-8?q?=E6=94=B9=E4=BA=86=E4=B8=80=E4=BA=9BUI=EF=BC=9B2.=E5=9B=A0?= =?UTF-8?q?=E4=B8=BA=E7=B2=98=E8=B4=B4=E5=8D=95=E5=85=83=E6=A0=BC=E7=9A=84?= =?UTF-8?q?=E6=97=B6=E5=80=99=E4=BC=9A=E8=8E=B7=E5=8F=96=E5=BD=93=E5=89=8D?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E9=9B=86=E9=9D=A2=E6=9D=BF=EF=BC=8CgetInstan?= =?UTF-8?q?ce=E6=96=B9=E6=B3=95=E9=87=8C=E4=BC=9Arefresh=E4=B8=80=E6=AC=A1?= =?UTF-8?q?=E6=95=B4=E4=B8=AA=E6=95=B0=E6=8D=AE=E9=9B=86=E6=A0=91=EF=BC=8C?= =?UTF-8?q?=E7=84=B6=E5=90=8E=E5=B0=86=E6=89=80=E6=9C=89=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E9=87=8D=E7=BD=AE=E5=88=B0=E6=94=B6=E8=B5=B7=E7=8A=B6=E6=80=81?= =?UTF-8?q?=20=E3=80=90=E6=94=B9=E5=8A=A8=E6=80=9D=E8=B7=AF=E3=80=911.?= =?UTF-8?q?=E8=B0=83=E6=95=B4UI=EF=BC=9B2.=E6=8F=90=E4=BE=9B=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E8=8E=B7=E5=8F=96=E6=95=B0=E6=8D=AE=E9=9B=86=E6=A0=91?= =?UTF-8?q?=E9=9D=A2=E6=9D=BF=E5=8D=95=E4=BE=8B=E4=B8=8D=E5=88=B7=E6=96=B0?= =?UTF-8?q?=E8=87=AA=E5=B7=B1=E7=9A=84=E6=96=B9=E6=B3=95=EF=BC=8C=E7=B2=98?= =?UTF-8?q?=E8=B4=B4=E6=97=B6=E4=BD=BF=E7=94=A8=20=E3=80=90review=E5=BB=BA?= =?UTF-8?q?=E8=AE=AE=E3=80=91=E6=97=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/datapane/TableDataTreePane.java | 45 +++-- .../pane/TableDataSearchRemindPane.java | 4 +- .../search/pane/TreeSearchToolbarPane.java | 13 +- .../search/view/TreeSearchRendererHelper.java | 2 +- .../paste/TableDataFollowingPasteUtils.java | 2 +- .../ilist/CheckBoxListWithPartialSelect.java | 162 ++++++++++++++++++ .../images/control/batch_esd_off_disabled.svg | 5 + .../images/control/batch_esd_off_normal.svg | 3 + .../images/control/batch_esd_on_disabled.svg | 5 + .../images/control/batch_esd_on_normal.svg | 3 + 10 files changed, 224 insertions(+), 20 deletions(-) create mode 100644 designer-base/src/main/java/com/fr/design/gui/ilist/CheckBoxListWithPartialSelect.java create mode 100644 designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off_disabled.svg create mode 100644 designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off_normal.svg create mode 100644 designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on_disabled.svg create mode 100644 designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on_normal.svg diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java index 06d086aef..739cbdeee 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/TableDataTreePane.java @@ -31,7 +31,8 @@ import com.fr.design.file.HistoryTemplateListCache; import com.fr.design.fun.TableDataPaneProcessor; import com.fr.design.gui.ibutton.UIHeadGroup; import com.fr.design.gui.icontainer.UIScrollPane; -import com.fr.design.gui.ilist.CheckBoxList; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.gui.ilist.CheckBoxListWithPartialSelect; import com.fr.design.gui.imenu.UIPopupMenu; import com.fr.design.gui.itextfield.UITextField; import com.fr.design.gui.itoolbar.UIToolbar; @@ -53,7 +54,6 @@ import com.fr.esd.event.StrategyEventsNotifier; import com.fr.esd.query.StrategicTableData; import com.fr.general.ComparatorUtils; import com.fr.general.GeneralContext; -import com.fr.general.IOUtils; import com.fr.general.NameObject; import com.fr.log.FineLoggerFactory; import com.fr.plugin.context.PluginContext; @@ -115,6 +115,20 @@ public class TableDataTreePane extends BasicTableDataTreePane { return singleton; } + /** + * 获取不必每次都refreshDockingView的数据集树面板 + * 不会主动替换DesignModelAdapter,需要保证使用时没有跨模板动作,谨慎使用 + * @param tc + * @return + */ + public synchronized static BasicTableDataTreePane getInstanceWithoutRefreshEverytime(DesignModelAdapter tc) { + TableDataPaneProcessor treePaneProcessor = ExtraDesignClassManager.getInstance().getSingle(TableDataPaneProcessor.XML_TAG); + if (treePaneProcessor != null) { + return treePaneProcessor.createTableDataTreePane(tc); + } + return singleton.tc == null ? getInstance(tc) : singleton; + } + private TableDataSourceOP op; private TableDataTree tableDataTree; private UIPopupMenu popupMenu; @@ -210,7 +224,7 @@ public class TableDataTreePane extends BasicTableDataTreePane { private TreeSearchToolbarPane initToolBarPane() { // toolbar addMenuDef = new MenuDef(Toolkit.i18nText("Fine-Design_Basic_Action_Add")); - addMenuDef.setIconPath(IconPathConstants.ADD_POPMENU_ICON_PATH); + addMenuDef.setIconPath("/com/fr/design/images/control/addPopup"); createAddMenuDef(); // 创建插件监听 createPluginListener(); @@ -842,8 +856,8 @@ public class TableDataTreePane extends BasicTableDataTreePane { } @Override - public Icon getIcon() { - return IOUtils.readIcon("/com/fr/design/images/control/batch_esd_on.png"); + public String getIconResource() { + return "/com/fr/design/images/control/batch_esd_on"; } @Override @@ -889,8 +903,8 @@ public class TableDataTreePane extends BasicTableDataTreePane { } @Override - public Icon getIcon() { - return IOUtils.readIcon("/com/fr/design/images/control/batch_esd_off.png"); + public String getIconResource() { + return "/com/fr/design/images/control/batch_esd_off"; } @Override @@ -911,14 +925,14 @@ public class TableDataTreePane extends BasicTableDataTreePane { public abstract String getName(); - public abstract Icon getIcon(); + public abstract String getIconResource(); public abstract void doWithTableDataWrapper(TableDataWrapper tableDataWrapper); public AbstractESDAction() { this.setName(getName()); this.setMnemonic('R'); - this.setSmallIcon(getIcon()); + this.setSmallIcon(getIconResource()); } @Override @@ -984,7 +998,7 @@ public class TableDataTreePane extends BasicTableDataTreePane { public EditAction() { this.setName(Toolkit.i18nText("Fine-Design_Basic_Edit")); this.setMnemonic('E'); - this.setSmallIcon(IOUtils.readIcon(IconPathConstants.TD_EDIT_ICON_PATH)); + this.setSmallIcon("/com/fr/design/images/control/edit"); } @Override @@ -1011,7 +1025,7 @@ public class TableDataTreePane extends BasicTableDataTreePane { public RemoveAction() { this.setName(Toolkit.i18nText("Fine-Design_Basic_Remove")); this.setMnemonic('R'); - this.setSmallIcon(IOUtils.readIcon(IconPathConstants.TD_REMOVE_ICON_PATH)); + this.setSmallIcon("/com/fr/design/images/control/remove"); } @Override @@ -1021,8 +1035,10 @@ public class TableDataTreePane extends BasicTableDataTreePane { FineLoggerFactory.getLogger().error("Table Data to remove is null or not selected"); return; } - CheckBoxList checkBoxList = new CheckBoxList(selectedNameObjects, CheckBoxList.SelectedState.ALL, Toolkit.i18nText("Fine-Design_Basic_Remove_All_Selected")); - UIScrollPane scrollPane = new UIScrollPane(checkBoxList); + // 可以半选的CheckBoxList + CheckBoxListWithPartialSelect tableDataCheckBoxPane = new CheckBoxListWithPartialSelect(selectedNameObjects); + UIScrollPane scrollPane = new UIScrollPane(tableDataCheckBoxPane); + UILabel tips = new UILabel("Fine-Design_Basic_Select_Source_To_Remove"); BasicPane basicPane = new BasicPane() { @Override protected String title4PopupWindow() { @@ -1030,11 +1046,12 @@ public class TableDataTreePane extends BasicTableDataTreePane { } }; basicPane.setLayout(new BorderLayout()); + basicPane.add(tips, BorderLayout.NORTH); basicPane.add(scrollPane, BorderLayout.CENTER); BasicDialog basicDialog = basicPane.showSmallWindow(SwingUtilities.getWindowAncestor(TableDataTreePane.this), new DialogActionAdapter() { @Override public void doOk() { - Object[] selectedValues = checkBoxList.getSelectedValues(); + List selectedValues = tableDataCheckBoxPane.getSelectedObjects(); // 删除时如果正在搜索,跳回原树 if (TableDataTreeSearchManager.getInstance().isInSearchMode()) { TableDataTreeSearchManager.getInstance().outOfSearchMode(); diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TableDataSearchRemindPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TableDataSearchRemindPane.java index 23738338b..01b767623 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TableDataSearchRemindPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TableDataSearchRemindPane.java @@ -190,7 +190,7 @@ public class TableDataSearchRemindPane extends JPanel implements TreeSearchStatu @Override public void onInSearching() { - this.textLabel.setText(IN_SEARCHING); + this.textLabel.setVisible(false); this.stopLabel.setText(STOP_SEARCHING); this.stopLabel.setVisible(true); this.setVisible(true); @@ -199,6 +199,7 @@ public class TableDataSearchRemindPane extends JPanel implements TreeSearchStatu @Override public void onStoppedSearching() { this.textLabel.setText(SEARCHING_STOPPED); + this.textLabel.setVisible(true); this.stopLabel.setVisible(false); this.setVisible(true); } @@ -206,6 +207,7 @@ public class TableDataSearchRemindPane extends JPanel implements TreeSearchStatu @Override public void onDoneSearching(boolean matchSetsEmpty) { this.textLabel.setText(DONE_SEARCHING); + this.textLabel.setVisible(true); this.stopLabel.setVisible(false); this.setVisible(true); } diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TreeSearchToolbarPane.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TreeSearchToolbarPane.java index ecabc02b3..ea51e1a82 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TreeSearchToolbarPane.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/pane/TreeSearchToolbarPane.java @@ -16,6 +16,7 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.stable.StringUtils; import javax.swing.BorderFactory; +import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; @@ -23,6 +24,7 @@ import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Color; import java.awt.Dimension; +import java.awt.Insets; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyAdapter; @@ -103,7 +105,7 @@ public class TreeSearchToolbarPane extends JPanel implements TreeSearchStatusCha searchPane.setBackground(Color.WHITE); // 左侧搜索图标 UILabel searchLabel = new UILabel(IconUtils.readIcon("/com/fr/design/images/data/search")); - searchLabel.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0)); + searchLabel.setBorder(BorderFactory.createEmptyBorder(0, 12, 0, 0)); searchLabel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { @@ -111,7 +113,12 @@ public class TreeSearchToolbarPane extends JPanel implements TreeSearchStatusCha } }); // 中间输入框 - searchTextField = new UITextField(); + searchTextField = new UITextField(){ + @Override + public Insets getInsets() { + return new Insets(2, 4, 0, 4); + } + }; searchTextField.setBorderPainted(false); searchTextField.setPlaceholder(Toolkit.i18nText("Fine-Design_Tree_Search_Press_Enter_For_Search")); searchTextField.addFocusListener(new FocusListener() { @@ -145,7 +152,7 @@ public class TreeSearchToolbarPane extends JPanel implements TreeSearchStatusCha // 右侧返回图标 UILabel returnLabel = new UILabel(IconUtils.readIcon("/com/fr/design/images/data/clear")); returnLabel.setToolTipText(Toolkit.i18nText("Fine-Design_Tree_Search_Return")); - returnLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + returnLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 11)); returnLabel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/view/TreeSearchRendererHelper.java b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/view/TreeSearchRendererHelper.java index cf348f128..fa445b7fb 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/management/search/view/TreeSearchRendererHelper.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/management/search/view/TreeSearchRendererHelper.java @@ -67,7 +67,7 @@ public class TreeSearchRendererHelper { } private String getHighlightText(String text, String textToHighlight) { - String highLightTemplate = "$1"; + String highLightTemplate = "$1"; if (textToHighlight.length() == 0) { return text; } diff --git a/designer-base/src/main/java/com/fr/design/data/tabledata/paste/TableDataFollowingPasteUtils.java b/designer-base/src/main/java/com/fr/design/data/tabledata/paste/TableDataFollowingPasteUtils.java index 5884bcbbc..f69312d47 100644 --- a/designer-base/src/main/java/com/fr/design/data/tabledata/paste/TableDataFollowingPasteUtils.java +++ b/designer-base/src/main/java/com/fr/design/data/tabledata/paste/TableDataFollowingPasteUtils.java @@ -54,7 +54,7 @@ public class TableDataFollowingPasteUtils { } // 获取当前的TableDataTreePane DesignModelAdapter currentModelAdapter = DesignModelAdapter.getCurrentModelAdapter(); - TableDataTreePane tableDataTreePane = (TableDataTreePane) TableDataTreePane.getInstance(currentModelAdapter); + TableDataTreePane tableDataTreePane = (TableDataTreePane) TableDataTreePane.getInstanceWithoutRefreshEverytime(currentModelAdapter); // 粘贴(添加)数据集 for (Map.Entry dataWrapperEntry : tableDataWrapperMap.entrySet()) { String dsName = dataWrapperEntry.getKey(); diff --git a/designer-base/src/main/java/com/fr/design/gui/ilist/CheckBoxListWithPartialSelect.java b/designer-base/src/main/java/com/fr/design/gui/ilist/CheckBoxListWithPartialSelect.java new file mode 100644 index 000000000..3304073df --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/gui/ilist/CheckBoxListWithPartialSelect.java @@ -0,0 +1,162 @@ +package com.fr.design.gui.ilist; + +import com.fr.design.event.StateChangeListener; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.gui.itree.checkboxtree.TristateCheckBox; +import com.fr.design.i18n.Toolkit; +import com.fr.design.layout.FRGUIPaneFactory; + +import javax.swing.AbstractListModel; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.util.List; + +/** + * 支持全选、全不选、半选的CheckBoxList面板 + * @author Yvan + */ +public class CheckBoxListWithPartialSelect extends JPanel { + + private UICheckBox[] dataCheckBoxes; + + private TristateCheckBox chooseAllCheckBox; + + private UIList dataList; + + public CheckBoxListWithPartialSelect (Object[] data) { + this.setLayout(FRGUIPaneFactory.createBorderLayout()); + init(data); + this.add(chooseAllCheckBox, BorderLayout.NORTH); + this.add(dataList, BorderLayout.CENTER); + } + + private void init(Object[] data) { + // 复选框组 + dataCheckBoxes = new UICheckBox[data.length]; + for (int i = 0; i < dataCheckBoxes.length; i++) { + dataCheckBoxes[i] = new UICheckBox(transferDataValue2Show(data[i])); + dataCheckBoxes[i].setSelected(true); + } + + // UIList + dataList = new UIList(dataCheckBoxes); + dataList.setModel(getListModel()); + dataList.setCellRenderer(getListCellRenderer()); + + // 全选框 + chooseAllCheckBox = new TristateCheckBox(Toolkit.i18nText("Fine-Design_Basic_Remove_All_Selected")); + chooseAllCheckBox.setState(TristateCheckBox.SELECTED); + chooseAllCheckBox.setFocusable(false); + chooseAllCheckBox.addStateChangeListener(getChooseAllCheckBoxStateChangeListener()); + dataList.addMouseListener(getDataListMouseListener()); + } + + public List getSelectedObjects() { + return dataList.getSelectedValuesList(); + } + + protected MouseListener getDataListMouseListener() { + return new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + super.mousePressed(e); + int index = dataList.getSelectedIndex(); + if (index < 0) { + return; + } + UICheckBox checkBox = (UICheckBox) dataList.getModel().getElementAt(index); + checkBox.setSelected(!checkBox.isSelected()); + //根据CheckBoxes中的选择情况来更新全选框的状态 + int selectedCount = calculateSelectedNum(); + if (selectedCount == 0) { + chooseAllCheckBox.setState(TristateCheckBox.NOT_SELECTED); + } else if (selectedCount == dataCheckBoxes.length) { + chooseAllCheckBox.setState(TristateCheckBox.SELECTED); + } else { + chooseAllCheckBox.setState(TristateCheckBox.DO_NOT_CARE); + } + dataList.repaint(); + } + }; + } + + /** + * 获取全选框状态改变监听 + * @return + */ + protected StateChangeListener getChooseAllCheckBoxStateChangeListener() { + return () -> { + if (chooseAllCheckBox.getState() == TristateCheckBox.DO_NOT_CARE) { + return; + } + boolean isSelected = chooseAllCheckBox.isSelected(); + for (int i = 0; i < dataList.getModel().getSize(); i++) { + UICheckBox checkBox = (UICheckBox) dataList.getModel().getElementAt(i); + checkBox.setSelected(isSelected); + } + dataList.repaint(); + }; + } + + /** + * 计算CheckBox的选中情况,用来更新全选框的状态 + * @return + */ + protected int calculateSelectedNum() { + int count = 0; + for (UICheckBox dataCheckBox : dataCheckBoxes) { + if (dataCheckBox.isSelected()) { + count++; + } + } + return count; + } + + /** + * 将传入的Object转化为字符串展示,默认调用toString方法 + * @param object + * @return + */ + protected String transferDataValue2Show(Object object) { + return object.toString(); + } + + protected AbstractListModel getListModel() { + return new SelectedListDataModel(); + } + + protected ListCellRenderer getListCellRenderer() { + return new SelectedListCellRender(); + } + + private class SelectedListCellRender extends DefaultListCellRenderer { + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, final boolean isSelected, boolean cellHasFocus) { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + dataCheckBoxes[index] = (UICheckBox) value; + dataCheckBoxes[index].setBackground(list.getBackground()); + return dataCheckBoxes[index]; + } + + } + + private class SelectedListDataModel extends AbstractListModel { + @Override + public int getSize() { + return dataCheckBoxes.length; + } + + @Override + public Object getElementAt(int index) { + return (index > getSize() - 1 || index < 0) ? null : dataCheckBoxes[index]; + } + } +} diff --git a/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off_disabled.svg b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off_disabled.svg new file mode 100644 index 000000000..ed225a99b --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off_disabled.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off_normal.svg b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off_normal.svg new file mode 100644 index 000000000..c81b5419a --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_off_normal.svg @@ -0,0 +1,3 @@ + + + diff --git a/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on_disabled.svg b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on_disabled.svg new file mode 100644 index 000000000..23d8c5da5 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on_disabled.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on_normal.svg b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on_normal.svg new file mode 100644 index 000000000..13f924d88 --- /dev/null +++ b/designer-base/src/main/resources/com/fr/design/images/control/batch_esd_on_normal.svg @@ -0,0 +1,3 @@ + + +