帆软报表设计器源代码。
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.

560 lines
20 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.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.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 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.event.MouseAdapter;
import java.awt.event.MouseEvent;
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 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);
return headerPanel;
}
private void startDetecting() {
// 重新检测的时候需要处理一些逻辑
if (buttonStatus == EnvDetectorButtonStatus.A_NEW) {
reInit();
}
// 执行前
buttonStatus = buttonStatus.next();
UIUtil.invokeLaterIfNeeded(EnvDetectorDialog.this::refreshHeaderPanel);
detectWorker = new SwingWorker<Void, Void>() {
@Override
protected Void doInBackground() throws Exception {
List<EnvDetectorItem> items = model.getItems();
// 执行刷新
for (int i = currentDetectIndex; i < items.size(); i++) {
// 看一下是否关闭了, 有可能已经关闭了。
if (buttonStatus.isNotExecuting()) {
return null;
}
// 刷新一下面板-开始执行啦
UIUtil.invokeLaterIfNeeded(EnvDetectorDialog.this::refresh);
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::refresh);
currentDetectIndex++;
}
}
return null;
}
@Override
protected void done() {
if (buttonStatus.isExecuting()) {
// 执行结束
buttonStatus = EnvDetectorButtonStatus.A_NEW;
UIUtil.invokeLaterIfNeeded(EnvDetectorDialog.this::refreshHeaderPanel);
}
}
};
// 开始执行
detectWorker.execute();
}
private void reInit() {
currentDetectIndex = 0;
for (EnvDetectorItem e : model.getItems()) {
e.setResult(null);
}
// 刷新一下面板-开始执行啦
UIUtil.invokeLaterIfNeeded(EnvDetectorDialog.this::refresh);
}
private void stopDetecting(UIButton detectButton) {
buttonStatus = buttonStatus.next();
// 先停止
detectWorker.cancel(false);
// 更改-UI
// 执行中
UIUtil.invokeLaterIfNeeded(() -> {
// 刷新按钮
detectButton.setText(buttonStatus.getDesc());
// 刷新面板
refresh();
});
}
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.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);
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(new Color(65, 155, 249));
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 refreshHeaderPanel() {
updateHeaderPanel();
pack();
repaint();
}
private void refresh() {
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 {
}
}