You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
596 lines
21 KiB
596 lines
21 KiB
package com.fr.env.detect.ui; |
|
|
|
import com.fr.base.svg.IconUtils; |
|
import com.fr.design.components.notification.NotificationDialog; |
|
import com.fr.design.components.notification.NotificationDialogProperties; |
|
import com.fr.design.components.notification.NotificationModel; |
|
import com.fr.design.components.table.TablePanel; |
|
import com.fr.design.constants.DesignerColor; |
|
import com.fr.design.constants.UIConstants; |
|
import com.fr.design.gui.ibutton.UIButton; |
|
import com.fr.design.gui.ibutton.UIButtonUI; |
|
import com.fr.design.gui.icheckbox.UICheckBox; |
|
import com.fr.design.gui.ilable.UILabel; |
|
import com.fr.design.i18n.Toolkit; |
|
import com.fr.design.layout.FRGUIPaneFactory; |
|
import com.fr.design.mainframe.DesignerContext; |
|
import com.fr.design.ui.util.UIUtil; |
|
import com.fr.design.utils.gui.GUICoreUtils; |
|
import com.fr.design.utils.gui.GUIPaintUtils; |
|
import com.fr.env.detect.base.DetectorBridge; |
|
import com.fr.env.detect.base.DetectorUtil; |
|
import com.fr.env.detect.base.EnvDetectorConfig; |
|
import com.fr.env.detect.bean.DetectorResult; |
|
import com.fr.env.detect.bean.DetectorStatus; |
|
import com.fr.env.detect.bean.DetectorType; |
|
import com.fr.log.FineLoggerFactory; |
|
import com.fr.design.carton.FeedbackToolboxDialog; |
|
import com.fr.stable.ProductConstantsBase; |
|
import com.fr.stable.StableUtils; |
|
import org.jetbrains.annotations.NotNull; |
|
|
|
import javax.swing.BorderFactory; |
|
import javax.swing.ImageIcon; |
|
import javax.swing.JDialog; |
|
import javax.swing.JPanel; |
|
import javax.swing.SwingWorker; |
|
import javax.swing.plaf.ButtonUI; |
|
import java.awt.BorderLayout; |
|
import java.awt.Color; |
|
import java.awt.Component; |
|
import java.awt.Dimension; |
|
import java.awt.Frame; |
|
import java.awt.Graphics2D; |
|
import java.awt.Image; |
|
import java.awt.Cursor; |
|
import java.awt.event.MouseAdapter; |
|
import java.awt.event.MouseEvent; |
|
import java.io.File; |
|
import java.net.URL; |
|
import java.util.List; |
|
import java.util.Map; |
|
import java.util.Objects; |
|
import java.util.concurrent.TimeUnit; |
|
import java.util.stream.Collectors; |
|
import java.util.stream.Stream; |
|
|
|
/** |
|
* created by Harrison on 2022/05/26 |
|
**/ |
|
public class EnvDetectorDialog extends JDialog { |
|
|
|
private static final ImageIcon LOADING_ICON = getLoadingIcon(); |
|
private static final int TIMEOUT = 1000; |
|
|
|
private static final Color SUCCESS_COLOR = new Color(22, 193, 83); |
|
private static final Color DETAIL_FONT_COLOR = new Color(65, 155, 249); |
|
|
|
private final JPanel body; |
|
|
|
private final JPanel headerPanel; |
|
private UIButton detectButton; |
|
private JPanel resultSummaryPane; |
|
|
|
private final TablePanel tablePanel; |
|
|
|
private final JPanel tailPanel; |
|
|
|
/* 数据 model */ |
|
|
|
private EnvDetectorModel model; |
|
|
|
/* 流程 model */ |
|
|
|
/** |
|
* 默认是第一个要检测 |
|
*/ |
|
private int currentDetectIndex = 0; |
|
|
|
private EnvDetectorButtonStatus buttonStatus = EnvDetectorButtonStatus.START; |
|
|
|
private SwingWorker<Void, Void> detectWorker = null; |
|
|
|
/* config model */ |
|
|
|
private boolean detectOpen = EnvDetectorConfig.getInstance().isEnabled(); |
|
|
|
public EnvDetectorDialog(Frame owner) { |
|
this(owner, null); |
|
} |
|
|
|
public EnvDetectorDialog(Frame owner, EnvDetectorModel model) { |
|
super(owner); |
|
|
|
configProperties(); |
|
|
|
if (model == null) { |
|
this.model = new EnvDetectorModel(); |
|
} else { |
|
this.model = model; |
|
} |
|
|
|
this.body = FRGUIPaneFactory.createBorderLayout_L_Pane(); |
|
Color backgroundColor = new Color(240, 240, 243, 1); |
|
this.body.setBackground( backgroundColor); |
|
|
|
this.headerPanel = createHeaderPanel(); |
|
body.add(headerPanel, BorderLayout.NORTH); |
|
|
|
this.tablePanel = createTablePanel(); |
|
body.add(tablePanel, BorderLayout.CENTER); |
|
|
|
/* tailPanel*/ |
|
this.tailPanel = createTailPanel(); |
|
body.add(tailPanel, BorderLayout.SOUTH); |
|
|
|
add(body); |
|
|
|
|
|
Dimension preferredSize = body.getPreferredSize(); |
|
setSize(preferredSize); |
|
|
|
repaint(); |
|
pack(); |
|
GUICoreUtils.centerWindow(this); |
|
} |
|
|
|
/* header */ |
|
|
|
@NotNull |
|
private JPanel createHeaderPanel() { |
|
|
|
JPanel headerPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
|
headerPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 12, 0)); |
|
this.detectButton = new UIButton(buttonStatus.getDesc()) { |
|
@Override |
|
public ButtonUI getUI() { |
|
|
|
return new UIButtonUI() { |
|
@Override |
|
protected void doExtraPainting(UIButton b, Graphics2D g2d, int w, int h, String selectedRoles) { |
|
if (isPressed(b) && b.isPressedPainted()) { |
|
GUIPaintUtils.fillPressed(g2d, 0, 0, w, h, b.isRoundBorder(), b.getRectDirection(), b.isDoneAuthorityEdited(selectedRoles), |
|
DesignerColor.Button.Primary.PRESSED); |
|
} else if (isRollOver(b)) { |
|
GUIPaintUtils.fillRollOver(g2d, 0, 0, w, h, b.isRoundBorder(), b.getRectDirection(), b.isDoneAuthorityEdited(selectedRoles), b.isPressedPainted(), |
|
DesignerColor.Button.Primary.HOVER); |
|
} else if (b.isNormalPainted()) { |
|
GUIPaintUtils.fillNormal(g2d, 0, 0, w, h, b.isRoundBorder(), b.getRectDirection(), b.isDoneAuthorityEdited(selectedRoles), b.isPressedPainted(), |
|
DesignerColor.Button.Primary.NORMAL); |
|
} |
|
} |
|
}; |
|
} |
|
}; |
|
detectButton.setForeground(Color.WHITE); |
|
detectButton.addActionListener(event -> { |
|
if (buttonStatus.isNotExecuting()) { |
|
startDetecting(); |
|
} else { |
|
stopDetecting(detectButton); |
|
} |
|
}); |
|
detectButton.setPreferredSize(new Dimension(68, 20)); |
|
detectButton.setBorderPainted(false); |
|
detectButton.setContentAreaFilled(false); |
|
headerPanel.add(detectButton, BorderLayout.WEST); |
|
|
|
UILabel openUtilBoxLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Carton_Feedback_ToolBox")); |
|
openUtilBoxLabel.setForeground(UIConstants.FLESH_BLUE); |
|
|
|
openUtilBoxLabel.addMouseListener(new MouseAdapter() { |
|
@Override |
|
public void mousePressed(MouseEvent e) { |
|
setVisible(false); |
|
FeedbackToolboxDialog myDialog = new FeedbackToolboxDialog(DesignerContext.getDesignerFrame()); |
|
myDialog.setVisible(true); |
|
dispose(); |
|
} |
|
public void mouseEntered(MouseEvent evt) { |
|
Object source = evt.getSource(); |
|
|
|
if (source instanceof UILabel) { |
|
((UILabel) source).setCursor(new Cursor(Cursor.HAND_CURSOR)); |
|
} |
|
} |
|
}); |
|
headerPanel.add(openUtilBoxLabel, BorderLayout.EAST); |
|
return headerPanel; |
|
} |
|
|
|
private void startDetecting() { |
|
|
|
// 重新检测的时候需要处理一些逻辑 |
|
if (buttonStatus == EnvDetectorButtonStatus.A_NEW) { |
|
reInit(); |
|
} |
|
// 执行前 |
|
buttonStatus = buttonStatus.next(); |
|
UIUtil.invokeLaterIfNeeded(EnvDetectorDialog.this::refreshHeader); |
|
detectWorker = new SwingWorker<Void, Void>() { |
|
|
|
@Override |
|
protected Void doInBackground() { |
|
List<EnvDetectorItem> items = model.getItems(); |
|
// 执行刷新 |
|
for (int i = currentDetectIndex; i < items.size(); i++) { |
|
|
|
// 看一下是否关闭了, 有可能已经关闭了。 |
|
if (buttonStatus.isNotExecuting()) { |
|
return null; |
|
} |
|
|
|
// 刷新一下面板-开始执行啦 |
|
UIUtil.invokeLaterIfNeeded(EnvDetectorDialog.this::refreshBody); |
|
|
|
EnvDetectorItem item = items.get(i); |
|
DetectorType type = item.getType(); |
|
|
|
// 执行检测, UI-当前在检测中 |
|
DetectorResult result = UIUtil.waitUntil( |
|
() -> DetectorBridge.getInstance().detect(type), |
|
TIMEOUT, TimeUnit.MILLISECONDS); |
|
// 获取结果 |
|
item.setResult(result); |
|
|
|
// 更新UI |
|
// 只有还在运行中,才会真正的刷新面板 |
|
if (buttonStatus.isExecuting()) { |
|
// 在刷新一下面板 |
|
UIUtil.invokeLaterIfNeeded(EnvDetectorDialog.this::refreshBody); |
|
currentDetectIndex++; |
|
} |
|
|
|
} |
|
return null; |
|
} |
|
|
|
@Override |
|
protected void done() { |
|
|
|
try { |
|
this.get(); |
|
if (buttonStatus.isExecuting()) { |
|
// 执行结束 |
|
buttonStatus = EnvDetectorButtonStatus.A_NEW; |
|
UIUtil.invokeLaterIfNeeded(EnvDetectorDialog.this::refreshHeader); |
|
} |
|
} catch (Exception e) { |
|
FineLoggerFactory.getLogger().error("detect failed", e); |
|
} |
|
} |
|
}; |
|
// 开始执行 |
|
detectWorker.execute(); |
|
} |
|
|
|
private void reInit() { |
|
currentDetectIndex = 0; |
|
for (EnvDetectorItem e : model.getItems()) { |
|
e.setResult(null); |
|
} |
|
// 刷新一下面板-开始执行啦 |
|
UIUtil.invokeLaterIfNeeded(EnvDetectorDialog.this::refreshBody); |
|
} |
|
|
|
private void stopDetecting(UIButton detectButton) { |
|
|
|
buttonStatus = buttonStatus.next(); |
|
|
|
// 先停止 |
|
detectWorker.cancel(false); |
|
// 更改-UI |
|
// 执行中 |
|
UIUtil.invokeLaterIfNeeded(() -> { |
|
// 刷新按钮 |
|
detectButton.setText(buttonStatus.getDesc()); |
|
// 刷新面板 |
|
refreshBody(); |
|
}); |
|
} |
|
|
|
private void updateHeaderPanel() { |
|
|
|
// 刷新按钮 |
|
detectButton.setText(buttonStatus.getDesc()); |
|
if (buttonStatus == EnvDetectorButtonStatus.A_NEW) { |
|
this.resultSummaryPane = new JPanel(); |
|
this.resultSummaryPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); |
|
this.resultSummaryPane.setLayout(new BorderLayout(5, 0)); |
|
Boolean success = model.getResults() |
|
.map((e) -> { |
|
if (e != null && e.getStatus() == DetectorStatus.NORMAL) { |
|
return Boolean.TRUE; |
|
} |
|
return Boolean.FALSE; |
|
}).reduce((a, b) -> a && b) |
|
.orElse(Boolean.FALSE); |
|
|
|
if (success) { |
|
resultSummaryPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Basic_Detect_Result_Label")), BorderLayout.WEST); |
|
UILabel successLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Detect_Result_Success")); |
|
successLabel.setForeground(SUCCESS_COLOR); |
|
resultSummaryPane.add(successLabel, BorderLayout.CENTER); |
|
} else { |
|
resultSummaryPane.add(new UILabel(Toolkit.i18nText("Fine-Design_Basic_Detect_Result_Label")), BorderLayout.WEST); |
|
UILabel resultLabel = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Detect_Result_Error")); |
|
resultLabel.setForeground(Color.RED); |
|
resultSummaryPane.add(resultLabel, BorderLayout.CENTER); |
|
} |
|
this.headerPanel.add(BorderLayout.CENTER, resultSummaryPane); |
|
} else { |
|
if (resultSummaryPane != null) { |
|
this.headerPanel.remove(resultSummaryPane); |
|
} |
|
} |
|
} |
|
|
|
/* table */ |
|
|
|
|
|
@NotNull |
|
private TablePanel createTablePanel() { |
|
|
|
TablePanel tablePanel = new TablePanel(18, 3); |
|
tablePanel.updateHeaders(new String[] { |
|
Toolkit.i18nText("Fine-Design_Basic_Detect_Kind"), |
|
Toolkit.i18nText("Fine-Design_Basic_Detect_Item"), |
|
Toolkit.i18nText("Fine-Design_Basic_Detect_Result")}); |
|
|
|
updateTable(tablePanel); |
|
|
|
return tablePanel; |
|
} |
|
|
|
private void updateTable(TablePanel tablePanel) { |
|
|
|
Map<DetectorType.Kind, List<EnvDetectorItem>> itemMap = model.getItemMap(); |
|
|
|
// 行号, 这边更新是通过 行/列 。 不是索引 |
|
int row = 1; |
|
for (Map.Entry<DetectorType.Kind, List<EnvDetectorItem>> entry : itemMap.entrySet()) { |
|
|
|
DetectorType.Kind kind = entry.getKey(); |
|
List<EnvDetectorItem> items = entry.getValue(); |
|
for (int i = 0; i < items.size(); i++) { |
|
if (i == 0) { |
|
tablePanel.updateCell(row, 1, kind.getDescription()); |
|
} |
|
EnvDetectorItem item = items.get(i); |
|
tablePanel.updateCell(row, 2, new UILabel(item.getDescription())); |
|
DetectorResult result = item.getResult(); |
|
|
|
int detectRow = currentDetectIndex + 1; |
|
|
|
if (result == null) { |
|
// 处于非正在检测状态 或者 索引不等于当前行号的时候 |
|
UILabel label; |
|
if (buttonStatus.isExecuting() && detectRow == row) { |
|
// 正在检测索引 |
|
label = new UILabel(LOADING_ICON, UILabel.LEADING); |
|
} else { |
|
label = new UILabel("-"); |
|
} |
|
tablePanel.updateCell(row, 3, label); |
|
} else { |
|
Component resultComponent = createResultComponent(result); |
|
tablePanel.updateCell(row, 3, resultComponent); |
|
} |
|
row++; |
|
} |
|
} |
|
} |
|
|
|
private Component createResultComponent(DetectorResult result) { |
|
|
|
JPanel statusPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
|
if (result.getStatus() == DetectorStatus.NORMAL) { |
|
statusPanel.add(new UILabel(IconUtils.readIcon("/com/fr/design/standard/reminder/reminder_success.svg")), BorderLayout.WEST); |
|
statusPanel.add(new UILabel(Toolkit.i18nText("Fine-Design_Basic_Normal")), BorderLayout.CENTER); |
|
} else { |
|
JPanel infoPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
|
{ |
|
infoPanel.add(new UILabel(IconUtils.readIcon("/com/fr/design/standard/reminder/reminder_error.svg")), BorderLayout.WEST); |
|
infoPanel.add(new UILabel(Toolkit.i18nText("Fine-Design_Basic_Exception")), BorderLayout.CENTER); |
|
} |
|
statusPanel.add(infoPanel, BorderLayout.WEST); |
|
|
|
// 如果结果是检测出的异常,则出现详细信息。 |
|
if (result.getStatus() == DetectorStatus.EXCEPTION) { |
|
JPanel detailPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
|
{ |
|
detailPanel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0)); |
|
UILabel detailLabel = new UILabel(Toolkit.i18nText("Fine_Designer_Look_Detail")); |
|
detailLabel.setForeground(DETAIL_FONT_COLOR); |
|
detailLabel.addMouseListener(new MouseAdapter() { |
|
@Override |
|
public void mouseClicked(MouseEvent mouseEvent) { |
|
NotificationDialogProperties properties = new NotificationDialogProperties((Frame) EnvDetectorDialog.this.getOwner(), Toolkit.i18nText("Fine-Design_Basic_Detect_Notification_Title")); |
|
Stream<DetectorResult> results = model.getResults(); |
|
List<NotificationModel> notificationModels = results |
|
.filter(Objects::nonNull) |
|
.filter((e) -> e.getStatus() == DetectorStatus.EXCEPTION) |
|
.map(DetectorUtil::convert2Notification) |
|
.collect(Collectors.toList()); |
|
|
|
NotificationDialog dialog = new NotificationDialog(properties, notificationModels); |
|
dialog.open(); |
|
} |
|
}); |
|
detailPanel.add(detailLabel, BorderLayout.CENTER); |
|
} |
|
statusPanel.add(detailPanel, BorderLayout.CENTER); |
|
} |
|
|
|
} |
|
return statusPanel; |
|
} |
|
|
|
/* tail */ |
|
|
|
@NotNull |
|
private JPanel createTailPanel() { |
|
|
|
JPanel tailPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
|
tailPanel.setBorder(BorderFactory.createEmptyBorder(20, 0, 0, 0)); |
|
|
|
JPanel configPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
|
{ |
|
UICheckBox checkBox = new UICheckBox(); |
|
checkBox.setSelected(this.detectOpen); |
|
checkBox.addChangeListener(e -> { |
|
UICheckBox source = (UICheckBox) e.getSource(); |
|
EnvDetectorDialog.this.detectOpen = source.isSelected(); |
|
}); |
|
configPanel.add(checkBox, BorderLayout.WEST); |
|
UILabel description = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Detect_Switch")); |
|
configPanel.add(description, BorderLayout.EAST); |
|
} |
|
tailPanel.add(configPanel, BorderLayout.WEST); |
|
|
|
JPanel actionsPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
|
actionsPanel.setLayout(FRGUIPaneFactory.createM_BorderLayout()); |
|
{ |
|
UIButton confirmButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Confirm")); |
|
confirmButton.addActionListener((e) -> { |
|
setVisible(false); |
|
dispose(); |
|
// 配置处理 |
|
EnvDetectorConfig.getInstance().setEnabled(this.detectOpen); |
|
}); |
|
actionsPanel.add(confirmButton, BorderLayout.WEST); |
|
|
|
UIButton cancelButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Cancel")); |
|
cancelButton.addActionListener((e) -> { |
|
setVisible(false); |
|
dispose(); |
|
}); |
|
actionsPanel.add(cancelButton, BorderLayout.EAST); |
|
} |
|
tailPanel.add(actionsPanel, BorderLayout.EAST); |
|
return tailPanel; |
|
} |
|
|
|
private void refreshHeader() { |
|
|
|
updateHeaderPanel(); |
|
pack(); |
|
repaint(); |
|
} |
|
|
|
private void refreshBody() { |
|
|
|
updateTable(this.tablePanel); |
|
pack(); |
|
repaint(); |
|
} |
|
|
|
private static ImageIcon getLoadingIcon() { |
|
|
|
URL resource = EnvDetectorDialog.class.getResource("/com/fr/design/standard/loading/loading-120.gif"); |
|
if (resource == null) { |
|
return null; |
|
} |
|
ImageIcon loadingIcon = new ImageIcon(resource); |
|
int width = 16; |
|
int height = 16; |
|
loadingIcon.setImage(loadingIcon.getImage().getScaledInstance(width, height, Image.SCALE_DEFAULT)); |
|
return loadingIcon; |
|
} |
|
|
|
private void configProperties() { |
|
|
|
setTitle(Toolkit.i18nText("Fine-Design_Basic_Detect_Title")); |
|
setModal(false); |
|
setFocusable(false); |
|
setAutoRequestFocus(false); |
|
setResizable(false); |
|
} |
|
|
|
/** |
|
* 按钮的当前状态 |
|
*/ |
|
private enum EnvDetectorButtonStatus { |
|
|
|
/** |
|
* 开始 -> 停止 |
|
*/ |
|
START("Fine-Design_Basic_Detect_Start") { |
|
@Override |
|
public EnvDetectorButtonStatus next() { |
|
return STOP; |
|
} |
|
}, |
|
|
|
/** |
|
* 停止 -> 继续 |
|
*/ |
|
STOP("Fine-Design_Basic_Detect_Stop") { |
|
@Override |
|
public EnvDetectorButtonStatus next() { |
|
return CONTINUE; |
|
} |
|
}, |
|
|
|
/** |
|
* 继续 -> 停止 |
|
*/ |
|
CONTINUE("Fine-Design_Basic_Detect_Continue") { |
|
@Override |
|
public EnvDetectorButtonStatus next() { |
|
return STOP; |
|
} |
|
}, |
|
|
|
/** |
|
* 重新 -> 停止 |
|
*/ |
|
A_NEW("Fine-Design_Basic_Detect_A_New") { |
|
@Override |
|
public EnvDetectorButtonStatus next() { |
|
return STOP; |
|
} |
|
} |
|
|
|
; |
|
|
|
private String descLocale; |
|
|
|
EnvDetectorButtonStatus(String descLocale) { |
|
|
|
this.descLocale = descLocale; |
|
} |
|
|
|
public String getDesc() { |
|
|
|
return Toolkit.i18nText(descLocale); |
|
} |
|
|
|
/** |
|
* 在执行中 |
|
* |
|
* @return 是/否 |
|
*/ |
|
public boolean isExecuting() { |
|
|
|
return this == EnvDetectorButtonStatus.STOP; |
|
}; |
|
|
|
/** |
|
* 不在执行中 |
|
* |
|
* @return 是/否 |
|
*/ |
|
public boolean isNotExecuting() { |
|
|
|
return !isExecuting(); |
|
} |
|
|
|
public abstract EnvDetectorButtonStatus next(); |
|
} |
|
|
|
private class EnvDetectorHeaderPanel extends JPanel { |
|
|
|
|
|
} |
|
}
|
|
|