diff --git a/designer-base/src/main/java/com/fine/theme/light/ui/FineHeaderPaneUI.java b/designer-base/src/main/java/com/fine/theme/light/ui/FineHeaderPaneUI.java index ea07516938..1b13ce22a6 100644 --- a/designer-base/src/main/java/com/fine/theme/light/ui/FineHeaderPaneUI.java +++ b/designer-base/src/main/java/com/fine/theme/light/ui/FineHeaderPaneUI.java @@ -101,6 +101,13 @@ public class FineHeaderPaneUI extends PanelUI implements AnimatedPainter { + FineUIScale.scale(UIManager.getInt("ExpandablePane.HeaderPane.hGap")); float titleY = (headerPane.getHeight() - (ascent + descent)) / 2.0f + ascent; FlatUIUtils.setRenderingHints(g2d); + + Icon icon = headerPane.getIcon(); + if (icon != null) { + icon.paintIcon(c, g2d, (int) titleX, iconY); + titleX += icon.getIconWidth() + FineUIScale.scale(UIManager.getInt("ExpandablePane.HeaderPane.hGap") + UIManager.getInt("ExpandablePane.HeaderPane.iconGap")); + } + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); g2d.drawString(headerPane.getTitle(), titleX, titleY); diff --git a/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/setting/TableDataDesensitizationTableModel.java b/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/setting/TableDataDesensitizationTableModel.java index 2196b58eea..e892320804 100644 --- a/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/setting/TableDataDesensitizationTableModel.java +++ b/designer-base/src/main/java/com/fr/design/data/datapane/preview/desensitization/view/setting/TableDataDesensitizationTableModel.java @@ -21,7 +21,6 @@ import com.fr.design.gui.itableeditorpane.UITableEditAction; import com.fr.design.gui.itableeditorpane.UITableModelAdapter; import com.fr.design.gui.itextfield.UITextField; import com.fr.design.i18n.Toolkit; -import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.stable.StringUtils; @@ -37,7 +36,6 @@ import javax.swing.UIManager; import javax.swing.event.CellEditorListener; import javax.swing.event.ChangeEvent; import javax.swing.table.TableCellEditor; -import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.event.ActionEvent; diff --git a/designer-base/src/main/java/com/fr/design/foldablepane/HeaderPane.java b/designer-base/src/main/java/com/fr/design/foldablepane/HeaderPane.java index 461aa3bccd..f4d3fba3f7 100644 --- a/designer-base/src/main/java/com/fr/design/foldablepane/HeaderPane.java +++ b/designer-base/src/main/java/com/fr/design/foldablepane/HeaderPane.java @@ -2,6 +2,7 @@ package com.fr.design.foldablepane; import com.formdev.flatlaf.util.ScaledEmptyBorder; +import javax.swing.Icon; import javax.swing.JPanel; import javax.swing.UIManager; @@ -15,6 +16,7 @@ public class HeaderPane extends JPanel { private boolean isShow; private boolean isPressed = false; private String title; + private Icon icon; @Override public String getUIClassID() { @@ -46,15 +48,24 @@ public class HeaderPane extends JPanel { return title; } - public HeaderPane() { + public HeaderPane(String title) { this.isShow = true; this.setForeground(UIManager.getColor("ExpandablePane.HeaderPane.foreground")); this.setBorder(new ScaledEmptyBorder(17, 0, 17, 0)); } - public HeaderPane(String title) { - this(); + public HeaderPane(String title, Icon icon) { + this(title); this.title = title; + this.icon = icon; + } + + public Icon getIcon() { + return icon; + } + + public void setIcon(Icon icon) { + this.icon = icon; } } diff --git a/designer-base/src/main/java/com/fr/design/foldablepane/UIExpandablePane.java b/designer-base/src/main/java/com/fr/design/foldablepane/UIExpandablePane.java index 355c95ab6d..f076ed10c0 100644 --- a/designer-base/src/main/java/com/fr/design/foldablepane/UIExpandablePane.java +++ b/designer-base/src/main/java/com/fr/design/foldablepane/UIExpandablePane.java @@ -4,6 +4,7 @@ import com.formdev.flatlaf.util.Animator; import com.formdev.flatlaf.util.ScaledEmptyBorder; import com.fr.design.border.FineBorderFactory; +import javax.swing.Icon; import javax.swing.JPanel; import java.awt.BorderLayout; import java.awt.Dimension; @@ -29,6 +30,7 @@ public class UIExpandablePane extends JPanel { private int fullHeight; private final JPanel contentPanel; private final String title; + private Icon icon; public JPanel getContentPanel() { return contentPanel; @@ -45,16 +47,25 @@ public class UIExpandablePane extends JPanel { this(title, contentPanel, false); } + public UIExpandablePane(String title, Icon icon, JPanel contentPanel) { + this(title, icon, contentPanel, false); + } + public UIExpandablePane(String title, JPanel contentPanel, boolean withUnderline) { + this(title, null, contentPanel, withUnderline); + } + + public UIExpandablePane(String title, Icon icon, JPanel contentPanel, boolean withUnderline) { super(); this.title = title; this.contentPanel = contentPanel; + this.icon = icon; initComponents(withUnderline); } private void initComponents(boolean withUnderline) { this.setLayout(new BorderLayout()); - HeaderPane headerPanel = new HeaderPane(title); + HeaderPane headerPanel = new HeaderPane(title, icon); headerPanel.addMouseListener(new PanelAction()); setcontentPanelontentPanelBorder(); if (withUnderline) { diff --git a/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UIComboCheckBox.java b/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UIComboCheckBox.java index 7c710badea..311233faa0 100644 --- a/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UIComboCheckBox.java +++ b/designer-base/src/main/java/com/fr/design/gui/icombocheckbox/UIComboCheckBox.java @@ -15,7 +15,6 @@ import com.fr.stable.StringUtils; import javax.swing.Icon; import javax.swing.JComboBox; import javax.swing.JComponent; -import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.event.PopupMenuEvent; diff --git a/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java b/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java index 74d285b992..838fabadc9 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/CenterRegionContainerPane.java @@ -155,12 +155,29 @@ public class CenterRegionContainerPane extends JPanel { //添加检测按钮 addCheckButton(); } + // 添加模板助手检测按钮 + addShadowButton(); //添加分享按钮 addShareButton(); //添加插件中的按钮 addExtraButtons(); } + private void addShadowButton() { + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (!JTemplate.isValid(jt)) { + return; + } + Component[] shadowButton = jt.createShadowButton(); + if (shadowButton == null || shadowButton.length == 0) { + return; + } + combineUp.addSeparator(new Dimension(2, 16)); + for (Component checkButton : shadowButton) { + combineUp.add(checkButton); + } + } + private void addExtraButtons() { diff --git a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java index 6bf3d466ee..2ac4e1439a 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java @@ -51,6 +51,7 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.authority.JTemplateAuthorityChecker; import com.fr.design.mainframe.chart.info.ChartInfoCollector; import com.fr.design.mainframe.check.CheckButton; +import com.fr.design.mainframe.shadow.SCBridge4Designer; import com.fr.design.mainframe.template.info.TemplateProcessInfo; import com.fr.design.mainframe.template.info.TimeConsumeTimer; import com.fr.design.mainframe.toolbar.ToolBarMenuDockPlus; @@ -103,9 +104,14 @@ import com.fr.widgettheme.designer.WidgetThemeDisplayAction; import com.fr.workspace.WorkContext; import com.fr.workspace.server.repository.connection.ConnectionRepository; -import javax.swing.*; +import javax.swing.BorderFactory; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JOptionPane; +import javax.swing.SwingConstants; import javax.swing.undo.UndoManager; -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Component; import java.io.ByteArrayOutputStream; import java.nio.file.Paths; import java.util.Arrays; @@ -1601,6 +1607,14 @@ public abstract class JTemplate> return new UIButton[]{new CheckButton()}; } + /** + * 创建模板助手组件按钮 + */ + public Component[] createShadowButton() { + return new Component[]{}; + } + + protected UIButton createTemplateThemeButton() { UIButton button = new UIButton(new LazyIcon("template_theme")); button.setToolTipText(getTemplateTheme().getName()); @@ -1738,6 +1752,7 @@ public abstract class JTemplate> checkBeforeSave(); export(); this.editingFILE = editingFILE; + SCBridge4Designer.handleTemplateSave(this); return true; } else { return false; diff --git a/designer-base/src/main/java/com/fr/design/mainframe/shadow/SCBridge4Designer.java b/designer-base/src/main/java/com/fr/design/mainframe/shadow/SCBridge4Designer.java new file mode 100644 index 0000000000..e950fc882a --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/shadow/SCBridge4Designer.java @@ -0,0 +1,79 @@ +package com.fr.design.mainframe.shadow; + +import com.fr.base.extension.FileExtension; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.log.FineLoggerFactory; +import com.fr.nx.analyze.shadow.manager.SCManager; +import com.fr.nx.analyze.shadow.manager.SCManagerFactory; +import com.fr.nx.analyze.shadow.metric.recorder.impl.SCDesignerMetricRecorder; +import com.fr.nx.analyze.shadow.template.SCTemplateHolder; +import com.fr.stable.project.ProjectConstants; +import org.jetbrains.annotations.NotNull; + +import javax.swing.SwingWorker; + +/** + *

监听器桥接类(用于设计器环境) + * + * @author Leo.Qin + * @since 10.0 + * Created on 2021/8/24. + */ +public class SCBridge4Designer { + + private SCBridge4Designer() { + } + + /** + * 接受设计器中模版保存事件 + * + * @param jTemplate 模版对象 + */ + public static void handleTemplateSave(JTemplate jTemplate) { + Object tpl = jTemplate.getTarget(); + SCTemplateHolder tplHolder = SCTemplateHolder.parse(tpl); + if (tplHolder == null) { + return; + } + String path = jTemplate.getPath(); + if (path.startsWith(ProjectConstants.REPORTLETS_NAME)) { + path = path.substring(ProjectConstants.REPORTLETS_NAME.length() + 1); + final String workbookPath = path; + if (workbookPath.endsWith(FileExtension.CPTX.getExtension())) { + return; + } + // 另开线程执行编译优化(这是一个一次性线程,只会存在很短时间,是为了不阻塞设计器 UI) + SwingWorker swingWorker = createSwingWorker(jTemplate, workbookPath, tplHolder); + swingWorker.execute(); + } + } + + private static @NotNull SwingWorker createSwingWorker(JTemplate jTemplate, String workbookPath, SCTemplateHolder tplHolder) { + return new SwingWorker() { + @Override + protected Boolean doInBackground() throws Exception { + SCManager scManager = SCManagerFactory.sharedManager(); + boolean existHistory = !scManager.hasHistoryShadowTemplate(workbookPath); + scManager.acquireShadowTemplate( + workbookPath, + tplHolder, + SCDesignerMetricRecorder.createOnSaveRecorder() + ).get(); + return existHistory; + } + + @Override + protected void done() { + try { + //返回值代表是否是首次保存,目前没有用到,先记录一下,以免误解 + get(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + //在新的Thread线程中,refreshToolArea操作不能在edt线程中执行,会出现未知的错误。 + DesignerContext.getDesignerFrame().resetToolkitByPlus(jTemplate); + } + }; + } +} diff --git a/designer-base/src/main/resources/com/fine/theme/icon/shadow/detect.svg b/designer-base/src/main/resources/com/fine/theme/icon/shadow/detect.svg new file mode 100755 index 0000000000..a30a834694 --- /dev/null +++ b/designer-base/src/main/resources/com/fine/theme/icon/shadow/detect.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + diff --git a/designer-base/src/main/resources/com/fine/theme/icon/shadow/error.svg b/designer-base/src/main/resources/com/fine/theme/icon/shadow/error.svg new file mode 100755 index 0000000000..18938cf163 --- /dev/null +++ b/designer-base/src/main/resources/com/fine/theme/icon/shadow/error.svg @@ -0,0 +1,8 @@ + + + + diff --git a/designer-base/src/main/resources/com/fine/theme/icon/shadow/risk.svg b/designer-base/src/main/resources/com/fine/theme/icon/shadow/risk.svg new file mode 100755 index 0000000000..52f99522d1 --- /dev/null +++ b/designer-base/src/main/resources/com/fine/theme/icon/shadow/risk.svg @@ -0,0 +1,13 @@ + + + + + + + diff --git a/designer-base/src/main/resources/com/fine/theme/icon/shadow/success.svg b/designer-base/src/main/resources/com/fine/theme/icon/shadow/success.svg new file mode 100755 index 0000000000..f1c419e65a --- /dev/null +++ b/designer-base/src/main/resources/com/fine/theme/icon/shadow/success.svg @@ -0,0 +1,5 @@ + + + diff --git a/designer-base/src/main/resources/com/fine/theme/icon/shadow/suggestion.svg b/designer-base/src/main/resources/com/fine/theme/icon/shadow/suggestion.svg new file mode 100755 index 0000000000..faab853b0f --- /dev/null +++ b/designer-base/src/main/resources/com/fine/theme/icon/shadow/suggestion.svg @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/designer-base/src/main/resources/com/fine/theme/light/ui/fine_light.icon.json b/designer-base/src/main/resources/com/fine/theme/light/ui/fine_light.icon.json index cce6c03234..01bc9db398 100644 --- a/designer-base/src/main/resources/com/fine/theme/light/ui/fine_light.icon.json +++ b/designer-base/src/main/resources/com/fine/theme/light/ui/fine_light.icon.json @@ -515,6 +515,11 @@ "auto_chart": { "normal": "insert/auto_chart_normal.svg", "disable": "insert/auto_chart_disabled.svg" - } + }, + "shadow_detect": "shadow/detect.svg", + "shadow_success": "shadow/success.svg", + "shadow_error": "shadow/error.svg", + "shadow_risk": "shadow/risk.svg", + "shadow_suggestion": "shadow/suggestion.svg" } } diff --git a/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLightLaf.properties b/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLightLaf.properties index df47e34cf2..b96dffea06 100644 --- a/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLightLaf.properties +++ b/designer-base/src/main/resources/com/fine/theme/light/ui/laf/FineLightLaf.properties @@ -1185,6 +1185,7 @@ West.border = $defaultBorderColor #---- ExpandablePane ---- ExpandablePane.HeaderPane.borderInsets=0, 6, 0, 6 ExpandablePane.HeaderPane.hGap=0 +ExpandablePane.HeaderPane.iconGap=4 ExpandablePane.vGap=5 HeaderPane.width=248 HeaderPane.height=$Component.defaultHeight diff --git a/designer-base/src/test/java/com/fr/design/gui/storybook/components/ComboCheckBoxStoryBoard.java b/designer-base/src/test/java/com/fr/design/gui/storybook/components/ComboCheckBoxStoryBoard.java index 7b51ff8710..7ee4139add 100644 --- a/designer-base/src/test/java/com/fr/design/gui/storybook/components/ComboCheckBoxStoryBoard.java +++ b/designer-base/src/test/java/com/fr/design/gui/storybook/components/ComboCheckBoxStoryBoard.java @@ -5,7 +5,6 @@ import com.fr.design.gui.ilable.UILabel; import com.fr.design.gui.storybook.StoryBoard; import com.fr.stable.ArrayUtils; - import static com.fine.swing.ui.layout.Layouts.cell; import static com.fine.swing.ui.layout.Layouts.flex; diff --git a/designer-base/src/test/java/com/fr/design/gui/storybook/components/ExpandablePaneStoryBoard.java b/designer-base/src/test/java/com/fr/design/gui/storybook/components/ExpandablePaneStoryBoard.java index cd3c3e3ae1..f683e16068 100644 --- a/designer-base/src/test/java/com/fr/design/gui/storybook/components/ExpandablePaneStoryBoard.java +++ b/designer-base/src/test/java/com/fr/design/gui/storybook/components/ExpandablePaneStoryBoard.java @@ -1,5 +1,6 @@ package com.fr.design.gui.storybook.components; +import com.fine.theme.icon.LazyIcon; import com.fr.design.foldablepane.UIExpandablePane; import com.fr.design.gui.ibutton.UIButton; import com.fr.design.gui.ilable.UILabel; @@ -8,7 +9,7 @@ import com.fr.design.gui.storybook.StoryBoard; import javax.swing.JPanel; import java.awt.BorderLayout; -import static com.fine.swing.ui.layout.Layouts.*; +import static com.fine.swing.ui.layout.Layouts.cell; /** * 扩展面板 @@ -22,6 +23,7 @@ public class ExpandablePaneStoryBoard extends StoryBoard { super("扩展面板"); add(cell(new UIExpandablePane("扩展", createContentPane()))); add(cell(new UIExpandablePane("扩展2", createContentPane2()))); + add(cell(new UIExpandablePane("带图标的扩展", new LazyIcon("logo"), createContentPane2()))); } diff --git a/designer-chart/src/main/java/com/fr/design/chart/AutoChartTypePane.java b/designer-chart/src/main/java/com/fr/design/chart/AutoChartTypePane.java index 2e07a6e1ae..418816b999 100644 --- a/designer-chart/src/main/java/com/fr/design/chart/AutoChartTypePane.java +++ b/designer-chart/src/main/java/com/fr/design/chart/AutoChartTypePane.java @@ -1,6 +1,7 @@ package com.fr.design.chart; import com.fine.theme.utils.FineUIStyle; +import com.formdev.flatlaf.util.ScaledEmptyBorder; import com.fr.base.chart.chartdata.CallbackEvent; import com.fr.chart.chartattr.ChartCollection; import com.fr.design.chart.auto.AutoTypeCalculate; @@ -18,7 +19,6 @@ import com.fr.design.utils.gui.GUICoreUtils; import com.fr.general.GeneralUtils; import com.fr.log.FineLoggerFactory; import com.fr.plugin.chart.vanchart.VanChart; -import com.formdev.flatlaf.util.ScaledEmptyBorder; import javax.swing.BorderFactory; import javax.swing.DefaultListCellRenderer; @@ -34,24 +34,23 @@ import javax.swing.UIManager; import javax.swing.event.ListSelectionListener; import javax.swing.plaf.SplitPaneUI; import javax.swing.plaf.basic.BasicSplitPaneUI; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CancellationException; -import java.awt.Color; import java.awt.BorderLayout; +import java.awt.Color; import java.awt.Component; -import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CancellationException; import static com.fine.swing.ui.layout.Layouts.cell; -import static com.fine.swing.ui.layout.Layouts.row; -import static com.fine.swing.ui.layout.Layouts.flex; import static com.fine.swing.ui.layout.Layouts.column; +import static com.fine.swing.ui.layout.Layouts.flex; +import static com.fine.swing.ui.layout.Layouts.row; /** * @author Bjorn diff --git a/designer-chart/src/main/java/com/fr/van/chart/designer/type/AbstractVanChartTypePane.java b/designer-chart/src/main/java/com/fr/van/chart/designer/type/AbstractVanChartTypePane.java index 61668a9278..c52c60ba37 100644 --- a/designer-chart/src/main/java/com/fr/van/chart/designer/type/AbstractVanChartTypePane.java +++ b/designer-chart/src/main/java/com/fr/van/chart/designer/type/AbstractVanChartTypePane.java @@ -1,9 +1,7 @@ package com.fr.van.chart.designer.type; import com.fine.theme.icon.LazyIcon; -import com.fr.base.BaseUtils; import com.fr.base.chart.chartdata.TopDefinitionProvider; -import com.fr.base.svg.IconUtils; import com.fr.chart.base.AttrFillStyle; import com.fr.chart.chartattr.Chart; import com.fr.chart.chartattr.Legend; diff --git a/designer-realize/src/main/java/com/fanruan/boot/init/DesignWorkContextComponent.java b/designer-realize/src/main/java/com/fanruan/boot/init/DesignWorkContextComponent.java index 3a54a73f6d..be1cf60393 100644 --- a/designer-realize/src/main/java/com/fanruan/boot/init/DesignWorkContextComponent.java +++ b/designer-realize/src/main/java/com/fanruan/boot/init/DesignWorkContextComponent.java @@ -8,6 +8,7 @@ import com.fanruan.carina.annotions.Start; import com.fanruan.carina.annotions.Stop; import com.fanruan.carina.annotions.Supplemental; import com.fanruan.plugin.autonomy.AutonomyClassManagerGroup; +import com.fanruan.repository.ConfigRepository; import com.fanruan.repository.TemplateRepository; import com.fanruan.workplace.conetxt.CompatiblePool; import com.fanruan.workplace.http.HttpConstants; @@ -35,6 +36,7 @@ import com.fr.file.filetree.FileNodes; import com.fr.file.filetree.LocalFileNodes; import com.fr.general.build.BuildInfoOperator; import com.fr.general.build.impl.BuildInfoOperatorImpl; +import com.fr.nx.analyze.shadow.workspace.repository.ShadowRepository; import com.fr.report.UnLockedHandler; import com.fr.security.encryption.storage.StorageEncryptors; import com.fr.security.encryption.storage.StorageTransfer; @@ -62,7 +64,6 @@ import com.fr.workspace.pool.WorkRPCType; import com.fr.workspace.resource.WorkResource; import com.fr.workspace.server.repository.authority.RemoteAuthorityRepository; import com.fr.workspace.server.repository.compatible.register.CompatibleRegister; -import com.fanruan.repository.ConfigRepository; import com.fr.workspace.server.repository.connection.ConnectionRepository; import com.fr.workspace.server.repository.map.MapRepository; import com.fr.workspace.server.repository.plugin.PluginRepository; @@ -119,6 +120,7 @@ public class DesignWorkContextComponent { RepositoryManager.getInstance().pureRegisterRepo4Start(ConfigRepository.getInstance()); RepositoryManager.getInstance().pureRegisterRepo4Start(PluginRepository.getInstance()); RepositoryManager.getInstance().pureRegisterRepo4Start(MapRepository.getInstance()); + RepositoryManager.getInstance().pureRegisterRepo4Start(ShadowRepository.getInstance()); RepositoryManager.getInstance().initLocalRepository(); CompatibleRegister.registerCompatibleEnv(); for (WorkRPCRegister workRPCRegister : ServiceContext.group(WorkspaceKey.class).getAll()) { diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java b/designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java index 639d7d656e..e4cf1b1cd3 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/JWorkBook.java @@ -1,5 +1,6 @@ package com.fr.design.mainframe; +import com.fanruan.product.ProductConstants; import com.fine.theme.icon.LazyIcon; import com.fr.base.DynamicUnitList; import com.fr.base.Parameter; @@ -50,6 +51,8 @@ import com.fr.design.gui.icontainer.UIModeControlContainer; import com.fr.design.gui.imenu.UIMenuItem; import com.fr.design.i18n.Toolkit; import com.fr.design.mainframe.cell.QuickEditorRegion; +import com.fr.design.mainframe.shadow.action.DetectErrorShowAction; +import com.fr.design.mainframe.shadow.action.TemplateHelperAction; import com.fr.design.mainframe.template.info.JWorkBookProcessInfo; import com.fr.design.mainframe.template.info.TemplateProcessInfo; import com.fr.design.mainframe.theme.dialog.TemplateThemeUsingDialog; @@ -103,7 +106,6 @@ import com.fr.report.poly.PolyWorkSheet; import com.fr.report.worksheet.WorkSheet; import com.fr.stable.ArrayUtils; import com.fr.stable.AssistUtils; -import com.fanruan.product.ProductConstants; import com.fr.stable.StableUtils; import com.fr.stable.StringUtils; import com.fr.stable.module.Module; @@ -115,6 +117,7 @@ import com.fr.workspace.WorkContext; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JPanel; +import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.FileOutputStream; @@ -1229,6 +1232,15 @@ public class JWorkBook extends JTemplate { // return new UIButton[]{new ShareButton()}; } + @Override + public Component[] createShadowButton() { + TemplateHelperAction templateHelperAction = new TemplateHelperAction(); + UIButton templateHelperUIButton = (UIButton) templateHelperAction.createToolBarComponent(); + DetectErrorShowAction detectErrorShowAction = new DetectErrorShowAction(); + UIButton errorComponents = (UIButton) detectErrorShowAction.createToolBarComponent(); + return new Component[]{templateHelperUIButton, errorComponents}; + } + @Override public String route() { return ViewRequestConstants.REPORT_VIEW_PATH; diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellPane.java index 843168091f..f6c978cf65 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellPane.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/cell/settingpane/desensitization/model/DesensitizationCellPane.java @@ -38,8 +38,8 @@ import java.util.Set; import static com.fine.swing.ui.layout.Layouts.cell; import static com.fine.swing.ui.layout.Layouts.column; -import static com.fine.swing.ui.layout.Layouts.row; import static com.fine.swing.ui.layout.Layouts.fix; +import static com.fine.swing.ui.layout.Layouts.row; import static com.fine.theme.utils.FineUIStyle.PLAIN_BUTTON; import static com.fine.theme.utils.FineUIStyle.TRANSPARENT_TEXT_FIELD; import static com.fine.theme.utils.FineUIStyle.setStyle; diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/action/DetectErrorShowAction.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/action/DetectErrorShowAction.java new file mode 100644 index 0000000000..b762f31a56 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/action/DetectErrorShowAction.java @@ -0,0 +1,116 @@ +package com.fr.design.mainframe.shadow.action; + +import com.fine.theme.icon.LazyIcon; +import com.fr.base.extension.FileExtension; +import com.fr.design.actions.UpdateAction; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.shadow.ui.detect.SCDefaultSCTemplateHelper; +import com.fr.design.mainframe.shadow.ui.detect.SCDefaultSCTemplateHelperDetect; +import com.fr.design.menu.MenuKeySet; +import com.fr.log.FineLoggerFactory; + +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.KeyStroke; +import javax.swing.SwingWorker; +import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +import static com.fr.design.gui.syntax.ui.rtextarea.RTADefaultInputMap.DEFAULT_MODIFIER; + +/** + * 检测错误action + * + * @author fly.li + * @since 10.0 + * Created on 2021/8/14 + */ +public class DetectErrorShowAction extends UpdateAction { + + private static final MenuKeySet DETECT_ATTR = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'E'; + } + + @Override + public String getMenuName() { + return Toolkit.i18nText("Fine-Design_Template_Assistant_Detect_Error_Tip"); + } + + @Override + public KeyStroke getKeyStroke() { + return KeyStroke.getKeyStroke(KeyEvent.VK_T, DEFAULT_MODIFIER); + } + }; + + public DetectErrorShowAction() { + init(); + } + + @Override + public void actionPerformed(ActionEvent e) { + SCDefaultSCTemplateHelper.getInstance().startShow(false); + } + + private void init() { + this.setMenuKeySet(DETECT_ATTR); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setAccelerator(getMenuKeySet().getKeyStroke()); + } + + @Override + public boolean isEnabled() { + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + String path = jt.getEditingFILE().getPath(); + return FileExtension.CPT.matchExtension(path) || FileExtension.FRM.matchExtension(path); + } + + @Override + public JComponent createToolBarComponent() { + UIButton transBtn = (UIButton) super.createToolBarComponent(); + transBtn.set4ToolbarButton(); + transBtn.setForeground(Color.RED); + transBtn.setToolTipText(Toolkit.i18nText("Fine-Design_Template_Assistant_Detect_Error_Tip")); + SwingWorker worker = new SwingWorker() { + @Override + protected Integer doInBackground() { + return SCDefaultSCTemplateHelperDetect.getInstance().errorCount(HistoryTemplateListCache.getInstance().getCurrentEditingTemplate()); + } + + @Override + protected void done() { + int errorCount = 0; + try { + errorCount = get(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e, e.getMessage()); + } + transBtn.setIcon(getIcon(errorCount)); + if (errorCount > 0) { + transBtn.setText(String.valueOf(errorCount)); + } + } + }; + worker.execute(); + return transBtn; + } + + + private Icon getIcon(int errorCount) { + Icon icon = null; + + if (errorCount == 0) { + icon = new LazyIcon("shadow_success"); + } else if (errorCount > 0) { + icon = new LazyIcon("shadow_error"); + } + + return icon; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/action/TemplateHelperAction.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/action/TemplateHelperAction.java new file mode 100644 index 0000000000..5292f4dc3d --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/action/TemplateHelperAction.java @@ -0,0 +1,82 @@ +package com.fr.design.mainframe.shadow.action; + +import com.fine.theme.icon.LazyIcon; +import com.fr.base.extension.FileExtension; +import com.fr.design.actions.UpdateAction; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.shadow.ui.detect.SCDefaultSCTemplateHelper; +import com.fr.design.menu.MenuKeySet; + +import javax.swing.JComponent; +import javax.swing.KeyStroke; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +import static com.fr.design.gui.syntax.ui.rtextarea.RTADefaultInputMap.DEFAULT_MODIFIER; + +/** + * 模板助手检测action + * + * @author fly.li + * @since 10.0 + * Created on 2021/8/5 + */ +public class TemplateHelperAction extends UpdateAction { + + private static final MenuKeySet DETECT_ATTR = new MenuKeySet() { + @Override + public char getMnemonic() { + return 'D'; + } + + @Override + public String getMenuName() { + return Toolkit.i18nText("Fine-Design_Template_Assistant_Template_Detect_Helper"); + } + + @Override + public KeyStroke getKeyStroke() { + return KeyStroke.getKeyStroke(KeyEvent.VK_T, DEFAULT_MODIFIER); + } + }; + + public TemplateHelperAction() { + init(); + } + + private void init() { + this.setMenuKeySet(DETECT_ATTR); + this.setSmallIcon(new LazyIcon("shadow_detect")); + this.setMnemonic(getMenuKeySet().getMnemonic()); + this.setName(getMenuKeySet().getMenuKeySetName()); + this.setAccelerator(getMenuKeySet().getKeyStroke()); + } + + @Override + public void actionPerformed(ActionEvent e) { + SCDefaultSCTemplateHelper.getInstance().startAndShow(); + } + + @Override + public boolean isEnabled() { + JTemplate jt = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + String path = jt.getEditingFILE().getPath(); + // 不在当前工作目录下,不启用模板助手 + if (!jt.getEditingFILE().isEnvFile()) { + return false; + } + return FileExtension.CPT.matchExtension(path) || FileExtension.FRM.matchExtension(path); + } + + + @Override + public JComponent createToolBarComponent() { + UIButton transBtn = (UIButton) super.createToolBarComponent(); + transBtn.set4ToolbarButton(); + transBtn.setToolTipText(Toolkit.i18nText("Fine-Design_Template_Assistant_Template_Detect_Helper")); + return transBtn; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/SCJumpHandler.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/SCJumpHandler.java new file mode 100644 index 0000000000..1cf34b94d8 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/SCJumpHandler.java @@ -0,0 +1,19 @@ +package com.fr.design.mainframe.shadow.handler; + +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; + +/** + * @author fly.li + * @since 10.0 + * Created on 2021/7/21 + * 跳转界面处理接口 + */ +public interface SCJumpHandler { + + /** + * 根据传入的参数信息,来具体的跳转进行处理,为总的流程 + */ + void handle(SCRecordJumper scRecordJumper, int sheetIndex); + + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/SCJumpHandlerProvider.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/SCJumpHandlerProvider.java new file mode 100644 index 0000000000..8e90bf4c99 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/SCJumpHandlerProvider.java @@ -0,0 +1,71 @@ +package com.fr.design.mainframe.shadow.handler; + +import com.fr.design.mainframe.shadow.handler.impl.DefaultSCJumpHandler; +import com.fr.design.mainframe.shadow.handler.impl.SCCellSCJumpHandler; +import com.fr.design.mainframe.shadow.handler.impl.SCDataSourceRecordHandler; +import com.fr.design.mainframe.shadow.handler.impl.SCGlobalParameterJumpHandler; +import com.fr.design.mainframe.shadow.handler.impl.SCNxCompileJumperHandler; +import com.fr.design.mainframe.shadow.handler.impl.SCWatermarkJumpHandler; +import com.fr.design.mainframe.shadow.handler.impl.SCWebLinkJumpHandler; +import com.fr.nx.analyze.shadow.metric.recorder.SCMetricRecorder; +import com.fr.nx.analyze.shadow.metric.recorder.impl.SCDesignerMetricRecorder; +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; +import com.fr.nx.analyze.shadow.record.jumper.impl.SCCellJumper; +import com.fr.nx.analyze.shadow.record.jumper.impl.SCGlobalParameterJumper; +import com.fr.nx.analyze.shadow.record.jumper.impl.SCNxCompileJumper; +import com.fr.nx.analyze.shadow.record.jumper.impl.SCTableDataJumper; +import com.fr.nx.analyze.shadow.record.jumper.impl.SCWatermarkJumper; +import com.fr.nx.analyze.shadow.record.jumper.impl.SCWebLinkJumper; + +import java.util.Collections; +import java.util.HashMap; + +/** + * <>跳转到设计器相应界面的接口 + * + * @author fly.li + * @since 10.0 + * Created on 2021/8/7 + */ +public class SCJumpHandlerProvider { + + private static HashMap handlers; + private static ThreadLocal recorder = ThreadLocal.withInitial(SCDesignerMetricRecorder::createOnJumpRecorder); + + static { + handlers = new HashMap<>(); + handlers.put(SCCellJumper.class.getName(), new SCCellSCJumpHandler()); + handlers.put(SCTableDataJumper.class.getName(), new SCDataSourceRecordHandler()); + handlers.put(SCWebLinkJumper.class.getName(), new SCWebLinkJumpHandler()); + handlers.put(SCNxCompileJumper.class.getName(), new SCNxCompileJumperHandler()); + handlers.put(SCGlobalParameterJumper.class.getName(), new SCGlobalParameterJumpHandler()); + handlers.put(SCWatermarkJumper.class.getName(), new SCWatermarkJumpHandler()); + } + + + private SCJumpHandlerProvider() { + } + + /** + * 添加handler + * + * @param key key + * @param handler handler + */ + public static void addHandler(String key, SCJumpHandler handler) { + handlers.put(key, handler); + } + + + /** + * 这里根据传入的信息不同,调用不同的handler进行处理(需要传入相关的信息参数) + */ + public static void jumpToTarget(SCRecordJumper scRecordJumper, int sheetIndex) { + handlers.getOrDefault(scRecordJumper.getClass().getName(), new DefaultSCJumpHandler()).handle(scRecordJumper, sheetIndex); + + // 记录跳转埋点 + if (scRecordJumper.getMetricType() != null) { + recorder.get().record(Collections.singleton(scRecordJumper.getMetricType())); + } + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/DefaultSCJumpHandler.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/DefaultSCJumpHandler.java new file mode 100644 index 0000000000..bd5bbf304b --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/DefaultSCJumpHandler.java @@ -0,0 +1,19 @@ +package com.fr.design.mainframe.shadow.handler.impl; + +import com.fr.design.mainframe.shadow.handler.SCJumpHandler; +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; + + +/** + * 跳转界面处理接口 + * + * @author fly.li + * @since 10.0 + * Created on 2021/7/21 + */ +public class DefaultSCJumpHandler implements SCJumpHandler { + @Override + public void handle(SCRecordJumper scRecordJumper, int sheetIndex) { + + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCCellSCJumpHandler.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCCellSCJumpHandler.java new file mode 100644 index 0000000000..00f513b5f5 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCCellSCJumpHandler.java @@ -0,0 +1,172 @@ +package com.fr.design.mainframe.shadow.handler.impl; + +import com.fr.base.BaseFormula; +import com.fr.design.cell.editor.CellEditor; +import com.fr.design.dscolumn.DSColumnPane; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.frpane.UITabbedPane; +import com.fr.design.mainframe.ElementCasePane; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.ReportComponent; +import com.fr.design.mainframe.ReportComponentCardPane; +import com.fr.design.mainframe.shadow.handler.SCJumpHandler; +import com.fr.design.mainframe.shadow.utils.DesignerPaneUtil; +import com.fr.grid.Grid; +import com.fr.grid.selection.CellSelection; +import com.fr.grid.selection.Selection; +import com.fr.invoke.Reflect; +import com.fr.main.impl.WorkBook; +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; +import com.fr.nx.analyze.shadow.record.jumper.impl.SCCellJumper; +import com.fr.nx.analyze.shadow.record.jumper.type.CellAttrType; +import com.fr.report.block.ElementCaseBlockImplement; +import com.fr.report.cell.CellElement; +import com.fr.report.cell.TemplateCellElement; +import com.fr.report.cell.cellattr.core.group.DSColumn; +import com.fr.report.elementcase.TemplateElementCase; +import com.fr.report.worksheet.WorkSheet; +import com.fr.stable.ColumnRow; + +import java.awt.Component; +import java.awt.Window; + +/** + * 单元格跳转handler + * + * @author fly.li + * @since 10.0 + * Created on 2021/09/18 + */ +public class SCCellSCJumpHandler implements SCJumpHandler { + @Override + public void handle(SCRecordJumper scRecordJumper, int sheetIndex) { + ColumnRow columnRow = ((SCCellJumper) scRecordJumper).getColumnRow(); + ElementCasePane elementCasePane = getElementCasePane(columnRow, sheetIndex); + handle0(elementCasePane, ((SCCellJumper) scRecordJumper).getCellAttrType()); + } + + /** + * 先使用if else实现 + */ + private void handle0(ElementCasePane elementCasePane, CellAttrType cellAttrType) { + //进行公式界面或者条件过滤面板的跳转 + Grid grid = elementCasePane.getGrid(); + switch (cellAttrType) { + case FORMULA: + startEditing(grid, BaseFormula.class); + break; + case DATA_COlUMN: + startEditing(grid, DSColumn.class); + break; + default: + + } + } + + + private ElementCasePane getElementCasePane(ColumnRow columnRow, int sheetIndex) { + JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + WorkBook workBook = (WorkBook) currentEditingTemplate.getTarget(); + WorkSheet workSheet = (WorkSheet) workBook.getTemplateReport(sheetIndex); + ReportComponentCardPane reportComponentCardPane = DesignerPaneUtil.getCurrentReportComponentCardPane(); + changeCurrentSheet(reportComponentCardPane, workSheet); + ElementCasePane elementCasePane = getEditingElementCasePane(reportComponentCardPane); + ElementCaseBlockImplement block = workSheet.getBlock(); + CellElement cellElement = block.getCellElement(columnRow.getColumn(), columnRow.getRow()); + int columnSpan = cellElement.getColumnSpan(); + int rowSpan = cellElement.getRowSpan(); + elementCasePane.setSelection(new CellSelection(cellElement.getColumn(), cellElement.getRow(), columnSpan, rowSpan)); + return elementCasePane; + } + + private ElementCasePane getEditingElementCasePane(ReportComponentCardPane reportComponentCardPane) { + ReportComponent reportComponent = Reflect.on(reportComponentCardPane).get("editingComponet"); + ElementCasePane editingElementCasePane = reportComponent.getEditingElementCasePane(); + return editingElementCasePane; + } + + private void changeCurrentSheet(ReportComponentCardPane reportComponentCardPane, WorkSheet workSheet) { + Reflect.on(reportComponentCardPane).call("showJWorkSheet", workSheet); + } + + private void startEditing(Grid grid, Class type) { + gridAttributesSetting(grid, type); + Component editorComponent = grid.getEditorComponent(); + if (editorComponent instanceof Window) { + //如果是数据列,需要设置默认tab为"过滤" + if (type == DSColumn.class) { + CellEditor cellEditor = grid.getCellEditor(); + setDefaultTab(cellEditor); + } + showPaneOnTop((Window) editorComponent); + } + } + + /** + * 标注一下复用的是Grid#startCellEditingAt_DEC()的代码 + * (复用的原因是需要将数据列设置的默认选项卡设置为“过滤”tab,以及在mac中需要将面板显示在最顶层) + */ + private void gridAttributesSetting(Grid grid, Class type) { + if (grid.isEditing()) { + grid.stopEditing(); + } + if (!grid.isEditable()) { + return; + } + ElementCasePane reportPane = grid.getElementCasePane(); + TemplateElementCase report = reportPane.getEditingElementCase(); + Selection s = reportPane.getSelection(); + int row = -1; + int column = -1; + if (s instanceof CellSelection) { + CellSelection selection = (CellSelection) s; + row = selection.getRow(); + column = selection.getColumn(); + } + if (row < 0 || column < 0) { + return; + } + grid.setEditingColumn(column); + grid.setEditingRow(row); + modifyGridAttr(grid, type, report, column, row); + } + + private static void modifyGridAttr(Grid grid, Class type, TemplateElementCase report, int column, int row) { + TemplateCellElement editingCellElement = report.getTemplateCellElement(column, row); + if (editingCellElement == null) { + //为null返回,在fr11中有另外的处理,需要注意 + return; + } + Reflect.on(grid).set("editingCellElement", editingCellElement); + CellEditor cellEditor = grid.getDefaultCellEditor(type); + if (cellEditor == null) { + return; + } + grid.setCellEditor(cellEditor); + //在这个地方将数据列设置面板放在了cellEditor的属性中,但是返回的只是一个dialog,后面要拿到面板,需要从cellEditor中拿 + Component editorComponent = Reflect.on(grid).call("getCellEditingComp").get(); + if (editorComponent == null) { + return; + } + Reflect.on(grid).set("editorComponent", editorComponent); + } + + /** + * 设置默认选项卡为"过滤" + */ + private void setDefaultTab(CellEditor cellEditor) { + DSColumnPane dsColumnPane = Reflect.on(cellEditor).get("dsColumnPane"); + //根据tab标题找到index,不能写死为1 + UITabbedPane tabbedPane = Reflect.on(dsColumnPane).get("tabbedPane"); + int index = tabbedPane.indexOfTab(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Report_Filter")); + tabbedPane.setSelectedIndex(index); + } + + /** + * 在最顶层显示面板 + */ + private void showPaneOnTop(Window window) { + window.setAlwaysOnTop(true); + window.setVisible(true); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCDataSourceRecordHandler.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCDataSourceRecordHandler.java new file mode 100644 index 0000000000..e4c63dcd19 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCDataSourceRecordHandler.java @@ -0,0 +1,133 @@ +package com.fr.design.mainframe.shadow.handler.impl; + +import com.fr.base.TableData; +import com.fr.data.TableDataSource; +import com.fr.data.impl.TableDataSourceDependent; +import com.fr.design.DesignModelAdapter; +import com.fr.design.data.BasicTableDataTreePane; +import com.fr.design.data.DesignTableDataManager; +import com.fr.design.data.datapane.TableDataTree; +import com.fr.design.data.datapane.TableDataTreePane; +import com.fr.design.data.tabledata.StoreProcedureWorkerListener; +import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane; +import com.fr.design.data.tabledata.wrapper.TemplateTableDataWrapper; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.gui.itree.refreshabletree.ExpandMutableTreeNode; +import com.fr.design.mainframe.shadow.handler.SCJumpHandler; +import com.fr.general.ComparatorUtils; +import com.fr.general.NameObject; +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; +import com.fr.nx.analyze.shadow.record.jumper.impl.SCTableDataJumper; +import com.fr.stable.core.PropertyChangeAdapter; +import org.jetbrains.annotations.NotNull; +import org.jooq.tools.reflect.Reflect; + +import javax.swing.SwingUtilities; +import java.util.HashMap; +import java.util.Map; + +/** + * @author fly.li + * @since 10.0 + * Created on 2021/8/7 + * <>跳转到数据集界面 + */ +public class SCDataSourceRecordHandler implements SCJumpHandler { + + @Override + public void handle(SCRecordJumper scRecordJumper, int sheetIndex) { + String dsName = ((SCTableDataJumper) scRecordJumper).getDsName(); + TemplateTableDataWrapper ds = findDS(dsName); + if (ds != null) { + TableDataTreePane tableDataTreePane = (TableDataTreePane) TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()); + showTableDataPane(ds.creatTableDataPane(), dsName, tableDataTreePane); + } + } + + + private TemplateTableDataWrapper findDS(String DSName) { + BasicTableDataTreePane instance = TableDataTreePane.getInstance(DesignModelAdapter.getCurrentModelAdapter()); + TableDataTree dataTree = instance.getDataTree(); + ExpandMutableTreeNode root = (ExpandMutableTreeNode) dataTree.getModel().getRoot(); + int childCount = root.getChildCount(); + for (int i = 0; i < childCount; i++) { + ExpandMutableTreeNode child = (ExpandMutableTreeNode) root.getChildAt(i); + NameObject userObject = (NameObject) child.getUserObject(); + TemplateTableDataWrapper templateTableDataWrapper = (TemplateTableDataWrapper) userObject.getObject(); + + if (DSName.equals(templateTableDataWrapper.getTableDataName())) { + return templateTableDataWrapper; + } + } + return null; + } + + /** + * 标识一下复用了TableDataTreePane#dgEdit方法(目的是为了mac中数据集设置面板弹窗默认在最顶层) + * 改行为新添加非复用代码:dg.setAlwaysOnTop(true) + */ + private void showTableDataPane(final AbstractTableDataPane tableDataPane, String originalName, TableDataTreePane tableDataTreePane) { + tableDataPane.addStoreProcedureWorkerListener(createStoreProcedureWorkerListener(tableDataTreePane)); + + final BasicPane.NamePane namePane = tableDataPane.asNamePane(); + namePane.setObjectName(originalName); + DesignModelAdapter tc = Reflect.on(tableDataTreePane).get("tc"); + Reflect.on(tableDataTreePane).set("allDSNames", DesignTableDataManager.getAllDSNames(tc.getBook())); + + final BasicDialog dg = namePane.showLargeWindow(SwingUtilities.getWindowAncestor(tableDataTreePane), createActionAdapter(tableDataPane, originalName, tableDataTreePane, tc, namePane)); + namePane.addPropertyChangeListener(new PropertyChangeAdapter() { + public void propertyChange() { + Reflect.on(tableDataTreePane).call("doPropertyChange", dg, namePane, originalName); + } + }); + dg.setAlwaysOnTop(true); + dg.setVisible(true); + } + + private static @NotNull DialogActionAdapter createActionAdapter(AbstractTableDataPane tableDataPane, String originalName, TableDataTreePane tableDataTreePane, DesignModelAdapter tc, BasicPane.NamePane namePane) { + return new DialogActionAdapter() { + @Override + public void doOk() { + DesignTableDataManager.setThreadLocal(DesignTableDataManager.NO_PARAMETER); + tc.renameTableData(originalName, namePane.getObjectName(), false); + TableDataSource tds = tc.getBook(); + TableData td = tableDataPane.updateBean(); + if (td instanceof TableDataSourceDependent) { + ((TableDataSourceDependent) td).setTableDataSource(tds); + } + + String tdName = namePane.getObjectName(); + tds.putTableData(tdName, td); + Map map = new HashMap(); + if (!ComparatorUtils.equals(originalName, tdName)) { + map.put(originalName, tdName); + } + + tableDataTreePane.fireDSChanged(map); + tc.fireTargetModified(); + tc.tableDataParametersChanged(originalName, tdName, td); + TableDataTree dataTree = tableDataTreePane.getDataTree(); + int[] rows = dataTree.getSelectionRows(); + dataTree.refreshChildByName(tdName); + dataTree.setSelectionRows(rows); + } + }; + } + + private static @NotNull StoreProcedureWorkerListener createStoreProcedureWorkerListener(TableDataTreePane tableDataTreePane) { + return () -> { + TableDataTree dataTree = tableDataTreePane.getDataTree(); + if (dataTree.getSelectionPath() == null) { + dataTree.refresh(); + } else { + Object object = dataTree.getSelectionPath().getLastPathComponent(); + int[] rows = dataTree.getSelectionRows(); + dataTree.refreshChildByName(object.toString()); + dataTree.setSelectionRows(rows); + } + + }; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCGlobalParameterJumpHandler.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCGlobalParameterJumpHandler.java new file mode 100644 index 0000000000..8550c165fa --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCGlobalParameterJumpHandler.java @@ -0,0 +1,84 @@ +package com.fr.design.mainframe.shadow.handler.impl; + +import com.fr.base.ParameterConfig; +import com.fr.config.ServerPreferenceConfig; +import com.fr.design.DesignModelAdapter; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.DesignerFrame; +import com.fr.design.mainframe.shadow.handler.SCJumpHandler; +import com.fr.design.parameter.ParameterManagerPane; +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; +import com.fr.transaction.CallBackAdaptor; +import com.fr.transaction.Configurations; +import com.fr.transaction.WorkerFacade; +import com.fr.workspace.WorkContext; +import org.jetbrains.annotations.NotNull; + +import javax.swing.JOptionPane; +import javax.swing.UIManager; + +/** + * 全局参数跳转handler + * + * @author fly.li + * @since 10.0 + * Created on 2021/12/22 + */ +public class SCGlobalParameterJumpHandler implements SCJumpHandler { + @Override + public void handle(SCRecordJumper scRecordJumper, int sheetIndex) { + DesignerFrame designerFrame = DesignerContext.getDesignerFrame(); + if (notJump()) { + FineJOptionPane.showMessageDialog( + designerFrame, + Toolkit.i18nText("Fine-Design_Template_Assistant_Jump_No_Auth"), + Toolkit.i18nText("Fine-Design_Basic_Error"), + JOptionPane.ERROR_MESSAGE, + UIManager.getIcon("OptionPane.errorIcon")); + return; + } + ParameterManagerPane parameterManagerPane = new ParameterManagerPane(); + BasicDialog parameterManagerDialog = parameterManagerPane.showWindow(designerFrame); + //marks:读取服务器配置信息 + parameterManagerPane.populate(ParameterConfig.getInstance().getGlobalParameters()); + parameterManagerDialog.addDialogActionListener(createActionListener(parameterManagerPane, parameterManagerDialog)); + parameterManagerDialog.setModal(true); + parameterManagerDialog.setAlwaysOnTop(true); + parameterManagerDialog.setVisible(true); + } + + private static @NotNull DialogActionAdapter createActionListener(ParameterManagerPane parameterManagerPane, BasicDialog parameterManagerDialog) { + return new DialogActionAdapter() { + public void doOk() { + Configurations.modify(new WorkerFacade(ServerPreferenceConfig.class) { + @Override + public void run() { + parameterManagerPane.update(); + } + }.addCallBack(new CallBackAdaptor() { + @Override + public void afterCommit() { + DesignModelAdapter model = DesignModelAdapter.getCurrentModelAdapter(); + if (model != null) { + model.parameterChanged(); + } + parameterManagerDialog.setDoOKSucceed(!parameterManagerPane.isContainsRename()); + } + })); + + } + }; + } + + /** + * 判断是否屏蔽全局参数配置界面 + * 如果当前环境是远程环境,并且登录用户为非管理员,则不跳转;其他情况都跳转 + */ + private boolean notJump() { + return WorkContext.getCurrent() != null && !WorkContext.getCurrent().isLocal() && !WorkContext.getCurrent().isRoot(); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCNxCompileJumperHandler.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCNxCompileJumperHandler.java new file mode 100644 index 0000000000..8ad477c0ac --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCNxCompileJumperHandler.java @@ -0,0 +1,29 @@ +package com.fr.design.mainframe.shadow.handler.impl; + +import com.fr.design.mainframe.shadow.handler.SCJumpHandler; +import com.fr.design.mainframe.shadow.ui.detect.SCDefaultSCTemplateHelper; +import com.fr.invoke.Reflect; +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; +import com.fr.stable.StringUtils; + +import java.awt.event.ActionEvent; + +/** + * @author Leo.Qin + * @since 10.0 + * Created on 2021/10/8. + * + *

新引擎预编译的跳转处理器 + */ +public class SCNxCompileJumperHandler implements SCJumpHandler { + @Override + public void handle(SCRecordJumper scRecordJumper, int sheetIndex) { + // 由于模块依赖问题,暂时先用反射了 + Reflect.on("com.fr.plugin.designer.toolbar.CompileAction", this.getClass().getClassLoader()) + .create() + .call("actionPerformed", new ActionEvent(this, ActionEvent.ACTION_FIRST, StringUtils.EMPTY)); + + // 关掉当前面板 + SCDefaultSCTemplateHelper.getInstance().close(); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCWatermarkJumpHandler.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCWatermarkJumpHandler.java new file mode 100644 index 0000000000..1f35798670 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCWatermarkJumpHandler.java @@ -0,0 +1,54 @@ +package com.fr.design.mainframe.shadow.handler.impl; + +import com.fr.base.iofile.attr.WatermarkAttr; +import com.fr.design.dialog.BasicDialog; +import com.fr.design.dialog.DialogActionAdapter; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.shadow.handler.SCJumpHandler; +import com.fr.design.report.WatermarkSettingPane; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.Original; +import com.fr.main.impl.WorkBook; +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; +import com.fr.report.core.ReportUtils; + +/** + * 水印跳转handler + * + * @author fly.li + * @since 10.0 + * Created on 2021/12/23 + */ +public class SCWatermarkJumpHandler implements SCJumpHandler { + @Override + public void handle(SCRecordJumper scRecordJumper, int sheetIndex) { + JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + Object target = currentEditingTemplate.getTarget(); + if (target instanceof WorkBook) { + WorkBook workBook = (WorkBook) target; + WatermarkAttr watermarkAttr = ReportUtils.getWatermarkAttrFromServerConfig(); + WatermarkSettingPane watermarkPane = new WatermarkSettingPane(); + watermarkPane.populate(watermarkAttr); + BasicDialog dialog = watermarkPane.showWindow(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { + public void doOk() { + workBook.addAttrMark(watermarkPane.update()); + currentEditingTemplate.fireTargetModified(); + SCWatermarkJumpHandler.this.recordFunction(); + } + }); + dialog.setAlwaysOnTop(true); + dialog.setVisible(true); + } + + } + + @Focus( + id = "com.fr.watermark", + text = "Fine-Design_Form_WaterMark", + source = Original.EMBED + ) + private void recordFunction() { + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCWebLinkJumpHandler.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCWebLinkJumpHandler.java new file mode 100644 index 0000000000..a7774cf958 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/handler/impl/SCWebLinkJumpHandler.java @@ -0,0 +1,28 @@ +package com.fr.design.mainframe.shadow.handler.impl; + +import com.fr.design.mainframe.shadow.handler.SCJumpHandler; +import com.fr.log.FineLoggerFactory; +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; +import com.fr.nx.analyze.shadow.record.jumper.impl.SCWebLinkJumper; + +import java.awt.Desktop; +import java.net.URI; + +/** + * @author Leo.Qin + * @since 10.0 + * Created on 2021/9/29. + * + *

打开网页链接的跳转处理器 + */ +public class SCWebLinkJumpHandler implements SCJumpHandler { + @Override + public void handle(SCRecordJumper scRecordJumper, int sheetIndex) { + SCWebLinkJumper j = (SCWebLinkJumper) scRecordJumper; + try { + Desktop.getDesktop().browse(new URI(j.getUrl())); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("open url failed: " + e.getMessage(), e); + } + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/listener/AbstractSCJumperListener.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/listener/AbstractSCJumperListener.java new file mode 100644 index 0000000000..125caf33db --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/listener/AbstractSCJumperListener.java @@ -0,0 +1,13 @@ +package com.fr.design.mainframe.shadow.listener; + +import java.awt.event.MouseAdapter; + +/** + * 跳转Listener抽象类 + * + * @author fly.li + * @since 10.0 + * Created on 2021/11/12 + */ +public class AbstractSCJumperListener extends MouseAdapter { +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/listener/SCDefaultJumpListener.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/listener/SCDefaultJumpListener.java new file mode 100644 index 0000000000..774294c6f6 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/listener/SCDefaultJumpListener.java @@ -0,0 +1,11 @@ +package com.fr.design.mainframe.shadow.listener; + +/** + * 默认跳转Listener + * + * @author fly.li + * @since 10.0 + * Created on 2021/09/23 + */ +public class SCDefaultJumpListener extends AbstractSCJumperListener { +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/listener/SCJumperListener.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/listener/SCJumperListener.java new file mode 100644 index 0000000000..f398da5338 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/listener/SCJumperListener.java @@ -0,0 +1,30 @@ +package com.fr.design.mainframe.shadow.listener; + +import com.fr.design.mainframe.shadow.handler.SCJumpHandlerProvider; +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; + +import java.awt.event.MouseEvent; + +/** + * 跳转Listener + * + * @author fly.li + * @since 10.0 + * Created on 2021/09/23 + */ +public class SCJumperListener extends AbstractSCJumperListener { + private SCRecordJumper scJumper; + private int sheetIndex; + + public SCJumperListener(SCRecordJumper scJumper, int sheetIndex) { + this.scJumper = scJumper; + this.sheetIndex = sheetIndex; + } + + @Override + public void mouseClicked(MouseEvent e) { + if (sheetIndex > -1) { + SCJumpHandlerProvider.jumpToTarget(scJumper, sheetIndex); + } + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/DetectFailedPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/DetectFailedPane.java new file mode 100644 index 0000000000..9a96f6c04a --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/DetectFailedPane.java @@ -0,0 +1,46 @@ +package com.fr.design.mainframe.shadow.ui; + +import com.fine.theme.icon.LazyIcon; +import com.fine.theme.utils.FineUIScale; +import com.fine.theme.utils.FineUIStyle; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.Toolkit; + +import javax.swing.JPanel; +import java.awt.BorderLayout; + +import static com.fine.swing.ui.layout.Layouts.cell; +import static com.fine.swing.ui.layout.Layouts.column; +import static com.fine.swing.ui.layout.Layouts.fix; +import static com.fine.swing.ui.layout.Layouts.flex; +import static com.fine.swing.ui.layout.Layouts.row; + +/** + * 检测失败面板 + * + * @author fly.li + * @since 10.0 + * Created on 2021/08/23 + */ +public class DetectFailedPane extends JPanel { + public DetectFailedPane() { + init(); + } + + private void init() { + this.setLayout(new BorderLayout()); + + UILabel image = new UILabel(); + image.setPreferredSize(FineUIScale.createScaleDimension(110, 110)); + image.setIcon(new LazyIcon("shadow_error", 110)); + + + add(column( + flex(), + row(flex(), cell(image), flex()), + fix(4), + row(flex(), cell(new UILabel(Toolkit.i18nText("Fine-Design_Template_Assistant_Detect_Failed_Tip"), FineUIStyle.LABEL_DISABLED)), flex()), + flex() + ).getComponent()); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/DetectNoErrorPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/DetectNoErrorPane.java new file mode 100644 index 0000000000..8200ab98f0 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/DetectNoErrorPane.java @@ -0,0 +1,81 @@ +package com.fr.design.mainframe.shadow.ui; + +import com.fine.theme.icon.LazyIcon; +import com.fine.theme.utils.FineUIScale; +import com.fine.theme.utils.FineUIStyle; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.LocaleLinkProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.log.FineLoggerFactory; + +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Cursor; +import java.awt.Desktop; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import static com.fine.swing.ui.layout.Layouts.cell; +import static com.fine.swing.ui.layout.Layouts.column; +import static com.fine.swing.ui.layout.Layouts.fix; +import static com.fine.swing.ui.layout.Layouts.flex; +import static com.fine.swing.ui.layout.Layouts.row; + + +/** + * 没有检测出错误的提示界面 + * + * @author fly.li + * @since 10.0 + * Created on 2021/8/7 + */ +public class DetectNoErrorPane extends JPanel { + + /** + * 云中心模版检测助手链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design_Template_Assistant__Help"; + + /** + * 云中心模版检测助手默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design_Template_Assistant__Help_Default"; + + public DetectNoErrorPane() { + init(); + } + + private void init() { + this.setLayout(new BorderLayout()); + + UILabel image = new UILabel(); + image.setPreferredSize(FineUIScale.createScaleDimension(110, 110)); + image.setIcon(new LazyIcon("shadow_success", 110)); + + UILabel secondLineLeft = new UILabel("" + Toolkit.i18nText("Fine-Design_Template_Assistant_No_Error_Result_Tipb") + ""); + secondLineLeft.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + try { + Desktop.getDesktop().browse(new URI(LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT))); + } catch (IOException | URISyntaxException ex) { + FineLoggerFactory.getLogger().error("io exception or not find website", ex); + } + } + }); + secondLineLeft.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); + + add(column( + flex(), + row(flex(), cell(image), flex()), + fix(4), + row(flex(), cell(new UILabel(Toolkit.i18nText("Fine-Design_Template_Assistant_No_Error_Result_Tipa"), FineUIStyle.LABEL_DISABLED)), flex()), + fix(10), + row(flex(), cell(secondLineLeft), cell(new UILabel(Toolkit.i18nText("Fine-Design_Template_Assistant_No_Error_Result_Tipc"), FineUIStyle.LABEL_DISABLED)), flex()), + flex() + ).getComponent()); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/OptimizationProgressPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/OptimizationProgressPane.java new file mode 100644 index 0000000000..0f91b66644 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/OptimizationProgressPane.java @@ -0,0 +1,35 @@ +package com.fr.design.mainframe.shadow.ui; + +import com.fr.design.i18n.Toolkit; +import com.fr.general.IOUtils; + +import javax.swing.Icon; +import javax.swing.JLabel; +import javax.swing.JPanel; + + +/** + * @author fly.li + * @since 10.0 + * Created on 2021/8/7 + * <>优化进行中的画面 + */ +public class OptimizationProgressPane extends JPanel { + + public static final Icon DETECT_PROCESS_ICON = IOUtils.readIcon("/com/fr/nx/analyze/shadow/detecting.png"); + + public OptimizationProgressPane() { + init(); + } + + protected void init() { + JLabel label = new JLabel(); + this.add(label); + label.setIcon(DETECT_PROCESS_ICON); + + label.setText(Toolkit.i18nText("Fine-Design_Template_Assistant_Loading_Tip")); + label.setVerticalTextPosition(JLabel.BOTTOM); + label.setHorizontalTextPosition(JLabel.CENTER); + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/TemplateHelperShowPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/TemplateHelperShowPane.java new file mode 100644 index 0000000000..eb8cb6b3c8 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/TemplateHelperShowPane.java @@ -0,0 +1,69 @@ +package com.fr.design.mainframe.shadow.ui.component; + +import com.fr.design.gui.frpane.FineTabbedPane; +import com.fr.design.gui.icontainer.UIScrollPane; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.shadow.ui.component.table.AutoOptimizeDetectMultiTablePane; +import com.fr.design.mainframe.shadow.ui.component.table.DetectMultiTablePane; +import com.fr.design.mainframe.shadow.ui.data.DetectMutiTableData; +import com.fr.design.mainframe.shadow.ui.data.TemplateDetectResultData; + +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import java.awt.BorderLayout; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * 模版检测助手展示面板 + * + * @author fly.li + * @since 10.0 + * Created on 2021/09/15 + */ +public class TemplateHelperShowPane extends JPanel { + public static final List SORTED_TAB_STRS = new ArrayList<>(); + + static { + SORTED_TAB_STRS.add(Toolkit.i18nText("Fine-Design_Template_Assistant_Manual_Optimize")); + SORTED_TAB_STRS.add(Toolkit.i18nText("Fine-Design_Template_Assistant_Auto_Optimize")); + SORTED_TAB_STRS.add(Toolkit.i18nText("Fine-Design_Template_Assistant_SQL_Tuning_Tips_Pane_Title")); + SORTED_TAB_STRS.add(Toolkit.i18nText("Fine-Design_Template_Assistant_Function_Guide")); + } + + private AutoOptimizeDetectMultiTablePane autoOptimizeDetectMultiTablePane; + + public TemplateHelperShowPane(TemplateDetectResultData templateDetectResultData) { + init(templateDetectResultData); + } + + + private void init(TemplateDetectResultData templateDetectResultData) { + + this.setLayout(new BorderLayout()); + FineTabbedPane.TabPaneBuilder builder = FineTabbedPane.builder(); + + for (String tabStr : SORTED_TAB_STRS) { + //创建相应的面板 + DetectMutiTableData detectMutiTableData = templateDetectResultData.getDetectMutiTableData(tabStr); + if (detectMutiTableData != null) { + DetectMultiTablePane detectMultiTablePane; + if (Objects.equals(Toolkit.i18nText("Fine-Design_Template_Assistant_Auto_Optimize"), tabStr)) { + autoOptimizeDetectMultiTablePane = new AutoOptimizeDetectMultiTablePane(detectMutiTableData); + detectMultiTablePane = autoOptimizeDetectMultiTablePane; + } else { + detectMultiTablePane = new DetectMultiTablePane(detectMutiTableData); + } + UIScrollPane uiScrollPane = new UIScrollPane(detectMultiTablePane); + uiScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + builder = builder.addTab(tabStr, uiScrollPane); + } + } + add(builder.withAdaptiveFit().build()); + } + + public AutoOptimizeDetectMultiTablePane getAutoOptimizeDetectMultiTablePane() { + return autoOptimizeDetectMultiTablePane; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/AbstractSCRecordItemPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/AbstractSCRecordItemPane.java new file mode 100644 index 0000000000..4eb299a08f --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/AbstractSCRecordItemPane.java @@ -0,0 +1,105 @@ +package com.fr.design.mainframe.shadow.ui.component.item; + +import com.fr.design.gui.ibutton.UIButton; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.shadow.listener.AbstractSCJumperListener; +import com.fr.design.mainframe.shadow.ui.data.SheetIndexToName; +import com.fr.nx.analyze.shadow.record.item.SCRecordItem; +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; +import com.fr.stable.StringUtils; + +import javax.swing.JLabel; +import javax.swing.JPanel; +import java.awt.BorderLayout; + +import static com.fine.swing.ui.layout.Layouts.cell; +import static com.fine.swing.ui.layout.Layouts.flex; +import static com.fine.swing.ui.layout.Layouts.row; + +/** + * 设置一些统一的面板布局 + * + * @author fly.li + * @since 10.0 + * Created on 2021/09/16 + */ +public abstract class AbstractSCRecordItemPane extends JPanel { + + + public AbstractSCRecordItemPane(SCRecordItem scRecordItem, Object extra) { + init(scRecordItem, extra); + } + + /** + * 初始化 + */ + public void init(SCRecordItem scRecordItem, Object extra) { + this.setLayout(new BorderLayout()); + + JLabel advicePositionLabel = createAdvicePositionLabel(scRecordItem, extra); + advicePositionLabel.setVerticalAlignment(JLabel.CENTER); + this.add(advicePositionLabel, BorderLayout.WEST); + this.add(advicePositionLabel); + UIButton jumperButton = createJumperButton(scRecordItem.getJumper(), extra); + if (jumperButton != null) { + add(row( + cell(advicePositionLabel), + flex(), + cell(jumperButton) + ).getComponent()); + } else { + add(row( + cell(advicePositionLabel), + flex() + ).getComponent()); + } + } + + /** + * 创建建议等级的label + */ + public abstract JLabel createAdvicePositionLabel(SCRecordItem scRecordItem, Object extra); + + /** + * 创建跳转按钮 + */ + public UIButton createJumperButton(SCRecordJumper scRecordJumper, Object extra) { + if (!isJumper(scRecordJumper)) { + return null; + } + AbstractSCJumperListener scJumperListener = createSCJumperListener(scRecordJumper, extra); + UIButton button = new UIButton(Toolkit.i18nText("Fine-Design_Template_Assistant_Jump")); + button.addMouseListener(scJumperListener); + return button; + } + + /** + * 决定是否创建跳转按钮,返回true则创建,返回false不创建 + */ + protected abstract boolean isJumper(SCRecordJumper scRecordJumper); + + /** + * 创建跳转按钮的监听器 + */ + public abstract AbstractSCJumperListener createSCJumperListener(SCRecordJumper scRecordJumper, Object SheetIndex); + + /** + * 根据extra获取sheetName + */ + public String convertToSheetName(Object extra) { + int sheetIndex = extra instanceof Integer ? (Integer) extra : -1; + if (sheetIndex > -1 || sheetIndex < SheetIndexToName.getInstance().getSheetCount()) { + return sheetIndex > -1 ? SheetIndexToName.getInstance().getSheetName(sheetIndex) : StringUtils.EMPTY; + } else { + throw new SheetIndexNotFindException(); + } + + } + + static class SheetIndexNotFindException extends RuntimeException { + @Override + public String getMessage() { + return "sheetIndex not find"; + } + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/AbstractSCRecordItemPaneFactory.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/AbstractSCRecordItemPaneFactory.java new file mode 100644 index 0000000000..af237223ea --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/AbstractSCRecordItemPaneFactory.java @@ -0,0 +1,106 @@ +package com.fr.design.mainframe.shadow.ui.component.item; + +import com.fr.log.FineLoggerFactory; +import com.fr.nx.analyze.shadow.record.item.SCRecordItem; +import com.fr.nx.analyze.shadow.record.item.impl.SCCellRecordItem; +import com.fr.nx.analyze.shadow.record.item.impl.SCColumnRecordItem; +import com.fr.nx.analyze.shadow.record.item.impl.SCDataSourceRecordItem; +import com.fr.nx.analyze.shadow.record.item.impl.SCMessageRecordItem; +import com.fr.nx.analyze.shadow.record.item.impl.SCRowRecordItem; +import com.fr.nx.analyze.shadow.record.item.impl.SCWidgetRecordItem; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + +/** + * 检测item面板工厂 + * + * @author fly.li + * @since 10.0 + * Created on 2021/09/16 + */ +public abstract class AbstractSCRecordItemPaneFactory { + + private static Map> map = new HashMap(); + + static { + map.put(SCCellRecordItem.class.getName(), AbstractSCRecordItemPaneFactory::createSCCellRecordItemPane); + map.put(SCRowRecordItem.class.getName(), AbstractSCRecordItemPaneFactory::createSCRowRecordItemPane); + map.put(SCDataSourceRecordItem.class.getName(), AbstractSCRecordItemPaneFactory::createSCDataSourceRecordItemPane); + map.put(SCColumnRecordItem.class.getName(), AbstractSCRecordItemPaneFactory::createSCColumnRecordItemPane); + map.put(SCWidgetRecordItem.class.getName(), AbstractSCRecordItemPaneFactory::createSCWidgetRecordItemPane); + map.put(SCMessageRecordItem.class.getName(), AbstractSCRecordItemPaneFactory::createSCMessageRecordItemPane); + } + + /** + * 注册SCRecordItemPane的创建方法 + * + * @param className SCRecordItem的类名 + * @param function SCRecordItemPane的创建方法 + */ + public static void register(String className, Function function) { + map.put(className, function); + } + + /** + * 根据不同的SCRecordItem创建相应的面板 + * 改变面板的创建方式之后,每次创建一个新类型的面板都需要增加一个creator过于浪费(所有的creator类被删除了) + * 直接使用switch来创建也不会造成更多的维护困难,这里感觉使用if也是一样 + * 因为这里没有复杂的判断逻辑,每个if只是判断类型相等而已,if并不存在难以维护的问题 + * (离散值适合switch,switch可能时间效率更好一点,空间效率稍差) + * <>final String cell = SCRowRecordItem.class.getName().intern()不能作为case常量来处理; + * 其他的转化为hashCode(可能存在碰撞)和直接使用包全名(包名可能会变化),也不合适 + * 因此最后使用map的方式,用Function接口来创建面板 + */ + public static AbstractSCRecordItemPane createSCRecordItemPane(SCRecordItem scRecordItem, Object extra) { + Function function = map.get(scRecordItem.getClass().getName()); + if (function != null) { + return function.apply(new SCRecordItemExtra(scRecordItem, extra)); + } else { + FineLoggerFactory.getLogger().error("Corresponding SCRecordItemPane Create Method not exist: {}", scRecordItem.getClass().getName()); + throw new TypeException("Corresponding SCRecordItemPane Create Method not exist"); + } + } + + private static SCCellRecordItemPane createSCCellRecordItemPane(SCRecordItemExtra scRecordItemExtra) { + return new SCCellRecordItemPane((SCCellRecordItem) scRecordItemExtra.scRecordItem, scRecordItemExtra.extra); + } + + private static SCRowRecordItemPane createSCRowRecordItemPane(SCRecordItemExtra scRecordItemExtra) { + return new SCRowRecordItemPane((SCRowRecordItem) scRecordItemExtra.scRecordItem, scRecordItemExtra.extra); + } + + private static SCDataSourceRecordItemPane createSCDataSourceRecordItemPane(SCRecordItemExtra scRecordItemExtra) { + return new SCDataSourceRecordItemPane((SCDataSourceRecordItem) scRecordItemExtra.scRecordItem, scRecordItemExtra.extra); + } + + private static SCColumnRecordItemPane createSCColumnRecordItemPane(SCRecordItemExtra scRecordItemExtra) { + return new SCColumnRecordItemPane((SCColumnRecordItem) scRecordItemExtra.scRecordItem, scRecordItemExtra.extra); + } + + private static SCWidgetRecordItemPane createSCWidgetRecordItemPane(SCRecordItemExtra scRecordItemExtra) { + return new SCWidgetRecordItemPane((SCWidgetRecordItem) scRecordItemExtra.scRecordItem, scRecordItemExtra.extra); + } + + private static SCMessageRecordItemPane createSCMessageRecordItemPane(SCRecordItemExtra scRecordItemExtra) { + return new SCMessageRecordItemPane((SCMessageRecordItem) scRecordItemExtra.scRecordItem, scRecordItemExtra.extra); + } + + static class SCRecordItemExtra { + SCRecordItem scRecordItem; + Object extra; + + SCRecordItemExtra(SCRecordItem scRecordItem, Object extra) { + this.scRecordItem = scRecordItem; + this.extra = extra; + } + } + + private static class TypeException extends RuntimeException { + private TypeException(String message) { + super(message); + } + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCCellRecordItemPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCCellRecordItemPane.java new file mode 100644 index 0000000000..a7d18d83e9 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCCellRecordItemPane.java @@ -0,0 +1,55 @@ +package com.fr.design.mainframe.shadow.ui.component.item; + +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.shadow.listener.SCJumperListener; +import com.fr.main.impl.WorkBook; +import com.fr.nx.analyze.shadow.record.item.SCRecordItem; +import com.fr.nx.analyze.shadow.record.item.impl.SCCellRecordItem; +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; +import com.fr.nx.analyze.shadow.record.jumper.impl.SCCellJumper; +import com.fr.nx.analyze.shadow.record.jumper.type.CellAttrType; +import com.fr.stable.ColumnRow; + +import javax.swing.JLabel; + +/** + * 单元格检测item + * + * @author fly.li + * @since 10.0 + * Created on 2021/09/16 + */ +public class SCCellRecordItemPane extends AbstractSCRecordItemPane { + + public SCCellRecordItemPane(SCCellRecordItem scCellRecordItem, Object extraData) { + super(scCellRecordItem, extraData); + } + + @Override + public JLabel createAdvicePositionLabel(SCRecordItem scRecordItem, Object extra) { + SCCellRecordItem scCellRecordItem = (SCCellRecordItem) scRecordItem; + ColumnRow columnRow = scCellRecordItem.getColumnRow(); + String sheetName = convertToSheetName(extra); + JLabel advicePositionLabel = new JLabel(sheetName + "/" + columnRow.toString()); + return advicePositionLabel; + } + + @Override + protected boolean isJumper(SCRecordJumper scRecordJumper) { + CellAttrType cellAttrType = ((SCCellJumper) scRecordJumper).getCellAttrType(); + return (cellAttrType == CellAttrType.FORMULA || cellAttrType == CellAttrType.DATA_COlUMN) && isWorkBook(); + } + + @Override + public SCJumperListener createSCJumperListener(SCRecordJumper scRecordJumper, Object extra) { + int sheetIndex = extra instanceof Integer ? (Integer) extra : -1; + SCJumperListener scJumperListener = new SCJumperListener(scRecordJumper, sheetIndex); + return scJumperListener; + } + + private boolean isWorkBook() { + JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + return currentEditingTemplate.getTarget() instanceof WorkBook; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCColumnRecordItemPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCColumnRecordItemPane.java new file mode 100644 index 0000000000..da65edaf79 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCColumnRecordItemPane.java @@ -0,0 +1,43 @@ +package com.fr.design.mainframe.shadow.ui.component.item; + + +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.shadow.listener.AbstractSCJumperListener; +import com.fr.design.mainframe.shadow.listener.SCDefaultJumpListener; +import com.fr.nx.analyze.shadow.record.item.SCRecordItem; +import com.fr.nx.analyze.shadow.record.item.impl.SCColumnRecordItem; +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; + +import javax.swing.JLabel; + +/** + * 检测结果item pane + * + * @author fly.li + * @since 10.0 + * Created on 2021/10/11 + */ +public class SCColumnRecordItemPane extends AbstractSCRecordItemPane { + + public SCColumnRecordItemPane(SCColumnRecordItem scColumnRecordItem, Object extra) { + super(scColumnRecordItem, extra); + } + + @Override + public JLabel createAdvicePositionLabel(SCRecordItem scRecordItem, Object extra) { + SCColumnRecordItem scColumnRecordItem = (SCColumnRecordItem) scRecordItem; + int column = scColumnRecordItem.getColumn() + 1; + String sheetName = convertToSheetName(extra); + return new JLabel(sheetName + "/" + Toolkit.i18nText("Fine-Design_Template_Assistant_First") + column + Toolkit.i18nText("Fine-Design_Template_Assistant_Column")); + } + + @Override + protected boolean isJumper(SCRecordJumper scRecordJumper) { + return false; + } + + @Override + public AbstractSCJumperListener createSCJumperListener(SCRecordJumper scRecordJumper, Object SheetIndex) { + return new SCDefaultJumpListener(); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCDataSourceRecordItemPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCDataSourceRecordItemPane.java new file mode 100644 index 0000000000..813a69d8b4 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCDataSourceRecordItemPane.java @@ -0,0 +1,43 @@ +package com.fr.design.mainframe.shadow.ui.component.item; + +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.shadow.listener.AbstractSCJumperListener; +import com.fr.design.mainframe.shadow.listener.SCJumperListener; +import com.fr.nx.analyze.shadow.record.item.SCRecordItem; +import com.fr.nx.analyze.shadow.record.item.impl.SCDataSourceRecordItem; +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; + +import javax.swing.JLabel; + +/** + * 数据源记录项面板 + * + * @author fly.li + * @since 10.0 + * Created on 2021/09/16 + */ +public class SCDataSourceRecordItemPane extends AbstractSCRecordItemPane { + private final int NONE = 1; + + public SCDataSourceRecordItemPane(SCDataSourceRecordItem scDataSourceRecordItem, Object object) { + super(scDataSourceRecordItem, object); + } + + @Override + public JLabel createAdvicePositionLabel(SCRecordItem scRecordItem, Object extra) { + SCDataSourceRecordItem scDataSourceRecordItem = (SCDataSourceRecordItem) scRecordItem; + String dsName = scDataSourceRecordItem.getDsName(); + JLabel advicePositionLabel = new JLabel(Toolkit.i18nText("Fine-Design_Template_Assistant_DS") + dsName); + return advicePositionLabel; + } + + @Override + protected boolean isJumper(SCRecordJumper scRecordJumper) { + return true; + } + + @Override + public AbstractSCJumperListener createSCJumperListener(SCRecordJumper scRecordJumper, Object SheetIndex) { + return new SCJumperListener(scRecordJumper, NONE); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCMessageRecordItemPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCMessageRecordItemPane.java new file mode 100644 index 0000000000..c3c7ed3148 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCMessageRecordItemPane.java @@ -0,0 +1,57 @@ +package com.fr.design.mainframe.shadow.ui.component.item; + +import com.fr.design.mainframe.shadow.listener.AbstractSCJumperListener; +import com.fr.design.mainframe.shadow.listener.SCJumperListener; +import com.fr.locale.InterProvider; +import com.fr.locale.InterProviderFactory; +import com.fr.nx.analyze.shadow.record.item.SCRecordItem; +import com.fr.nx.analyze.shadow.record.item.impl.SCMessageRecordItem; +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; +import com.fr.stable.StringUtils; + +import javax.swing.JLabel; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Leo.Qin + * @since 10.0 + * Created on 2021/9/29. + * + *

处理 SCMessageRecordItem 的面板 + */ +public class SCMessageRecordItemPane extends AbstractSCRecordItemPane { + private static Map map = new HashMap<>(); + + static { + InterProvider provider = InterProviderFactory.getProvider(); + map.put(provider.getLocText("Fine-Design_Template_Assistant_Shadow_Runtime_Record_Driver_Recommend_Mysql"), provider.getLocText("Fine-Design_Template_Assistant_Click_Obtain_Driver")); + map.put(provider.getLocText("Fine-Design_Template_Assistant_Shadow_Runtime_Record_Driver_Recommend_Sqlserver"), provider.getLocText("Fine-Design_Template_Assistant_Click_Obtain_Driver")); + map.put(provider.getLocText("Fine-Design_Template_Assistant_Shadow_Runtime_Record_Use_Ds_Cache_Message"), provider.getLocText("Fine-Design_Template_Assistant_Click_Know")); + map.put(provider.getLocText("Fine-Design_Template_Assistant_Shadow_Record_Nx_Message"), provider.getLocText("Fine-Design_Template_Assistant_Open_New_Engine_Paging")); + } + + public SCMessageRecordItemPane(SCMessageRecordItem item, Object extraData) { + super(item, extraData); + } + + /** + * + */ + @Override + public JLabel createAdvicePositionLabel(SCRecordItem scRecordItem, Object extra) { + String message = ((SCMessageRecordItem) scRecordItem).getMessage(); + JLabel advicePositionLabel = new JLabel(StringUtils.isEmpty(map.get(message)) ? message : map.get(message)); + return advicePositionLabel; + } + + @Override + protected boolean isJumper(SCRecordJumper scRecordJumper) { + return scRecordJumper != SCRecordJumper.NOOP; + } + + @Override + public AbstractSCJumperListener createSCJumperListener(SCRecordJumper scRecordJumper, Object SheetIndex) { + return new SCJumperListener(scRecordJumper, 0); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCRowRecordItemPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCRowRecordItemPane.java new file mode 100644 index 0000000000..0e6ffeab26 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCRowRecordItemPane.java @@ -0,0 +1,42 @@ +package com.fr.design.mainframe.shadow.ui.component.item; + +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.shadow.listener.AbstractSCJumperListener; +import com.fr.design.mainframe.shadow.listener.SCDefaultJumpListener; +import com.fr.nx.analyze.shadow.record.item.SCRecordItem; +import com.fr.nx.analyze.shadow.record.item.impl.SCRowRecordItem; +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; + +import javax.swing.JLabel; + + +/** + * 行结果item面板 + * + * @author fly.li + * @since 10.0 + * Created on 2021/09/16 + */ +public class SCRowRecordItemPane extends AbstractSCRecordItemPane { + public SCRowRecordItemPane(SCRowRecordItem scRowRecordItem, Object extraData) { + super(scRowRecordItem, extraData); + } + + @Override + public JLabel createAdvicePositionLabel(SCRecordItem scRecordItem, Object extra) { + String sheetName = convertToSheetName(extra); + int row = ((SCRowRecordItem) scRecordItem).getRow() + 1; + JLabel advicePositionLabel = new JLabel(sheetName + "/" + Toolkit.i18nText("Fine-Design_Template_Assistant_First") + row + Toolkit.i18nText("Fine-Design_Template_Assistant_Line")); + return advicePositionLabel; + } + + @Override + protected boolean isJumper(SCRecordJumper scRecordJumper) { + return false; + } + + @Override + public AbstractSCJumperListener createSCJumperListener(SCRecordJumper scRecordJumper, Object SheetIndex) { + return new SCDefaultJumpListener(); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCWidgetRecordItemPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCWidgetRecordItemPane.java new file mode 100644 index 0000000000..7d033dc32a --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/item/SCWidgetRecordItemPane.java @@ -0,0 +1,40 @@ +package com.fr.design.mainframe.shadow.ui.component.item; + +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.shadow.listener.AbstractSCJumperListener; +import com.fr.design.mainframe.shadow.listener.SCDefaultJumpListener; +import com.fr.nx.analyze.shadow.record.item.SCRecordItem; +import com.fr.nx.analyze.shadow.record.item.impl.SCWidgetRecordItem; +import com.fr.nx.analyze.shadow.record.jumper.SCRecordJumper; + +import javax.swing.JLabel; + +/** + * 控件检测列表项面板 + * + * @author fly.li + * @since 10.0 + * Created on 2021/10/11 + */ +public class SCWidgetRecordItemPane extends AbstractSCRecordItemPane { + public SCWidgetRecordItemPane(SCWidgetRecordItem scWidgetRecordItem, Object extra) { + super(scWidgetRecordItem, extra); + } + + @Override + public JLabel createAdvicePositionLabel(SCRecordItem scRecordItem, Object extra) { + SCWidgetRecordItem scWidgetRecordItem = (SCWidgetRecordItem) scRecordItem; + String widgetName = scWidgetRecordItem.getWidgetName(); + return new JLabel(Toolkit.i18nText("Fine-Design_Template_Assistant_Widget") + widgetName); + } + + @Override + protected boolean isJumper(SCRecordJumper scRecordJumper) { + return false; + } + + @Override + public AbstractSCJumperListener createSCJumperListener(SCRecordJumper scRecordJumper, Object SheetIndex) { + return new SCDefaultJumpListener(); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/table/AutoOptimizeDetectMultiTablePane.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/table/AutoOptimizeDetectMultiTablePane.java new file mode 100644 index 0000000000..60728d5761 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/table/AutoOptimizeDetectMultiTablePane.java @@ -0,0 +1,57 @@ +package com.fr.design.mainframe.shadow.ui.component.table; + + +import com.fr.base.io.IOFile; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.gui.icheckbox.UICheckBox; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.shadow.ui.data.DetectMutiTableData; +import com.fr.nx.analyze.shadow.attr.SCOptionAttrMark; + +import java.awt.BorderLayout; + +import static com.fine.swing.ui.layout.Layouts.cell; +import static com.fine.swing.ui.layout.Layouts.flex; +import static com.fine.swing.ui.layout.Layouts.row; + + +/** + * 自动优化面板 + * + * @author fly.li + * @since 10.0 + * Created on 2021/11/18 + */ +public class AutoOptimizeDetectMultiTablePane extends DetectMultiTablePane { + private UICheckBox skipAutoOptimizeSwitchCheckBox; + + public AutoOptimizeDetectMultiTablePane(DetectMutiTableData detectMutiTableData) { + super(detectMutiTableData); + init(); + } + + private void init() { + addSkipAutoOptimizeSwitch(); + } + + private void addSkipAutoOptimizeSwitch() { + skipAutoOptimizeSwitchCheckBox = new UICheckBox(Toolkit.i18nText("Fine-Design_Template_Assistant_Not_Auto_Optimize")); + JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + Object target = currentEditingTemplate.getTarget(); + if (target instanceof IOFile) { + IOFile ioFile = (IOFile) target; + SCOptionAttrMark attrMark = ioFile.getAttrMark(SCOptionAttrMark.MARK); + skipAutoOptimizeSwitchCheckBox.setSelected(attrMark != null && attrMark.isSkipAutoTask()); + } + this.add(row( + cell(skipAutoOptimizeSwitchCheckBox), + flex() + ).getComponent(), BorderLayout.SOUTH); + } + + public boolean isSkipAutoOptimize() { + return skipAutoOptimizeSwitchCheckBox.isSelected(); + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/table/DetectMultiTablePane.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/table/DetectMultiTablePane.java new file mode 100644 index 0000000000..b85378219c --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/table/DetectMultiTablePane.java @@ -0,0 +1,96 @@ +package com.fr.design.mainframe.shadow.ui.component.table; + +import com.fine.theme.utils.FineLayoutBuilder; +import com.fr.design.gui.ilable.UILabel; +import com.fr.design.i18n.LocaleLinkProvider; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.shadow.ui.data.DetectMutiTableData; +import com.fr.design.mainframe.shadow.ui.data.DetectSingleTableData; +import com.fr.log.FineLoggerFactory; + +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Desktop; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.List; + +import static com.fine.swing.ui.layout.Layouts.cell; +import static com.fine.swing.ui.layout.Layouts.column; +import static com.fine.swing.ui.layout.Layouts.flex; +import static com.fine.swing.ui.layout.Layouts.row; + +/** + * 检测结果面板 + * + * @author fly.li + * @since 10.0 + * Created on 2021/09/15 + */ +public class DetectMultiTablePane extends JPanel { + + /** + * 云中心模版检测助手链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY = "Fine-Design_Template_Assistant__Help"; + + /** + * 云中心模版检测助手默认链接在配置文件中对应的配置文件key + */ + private static final String PROPS_LINK_KEY_DEFAULT = "Fine-Design_Template_Assistant__Help_Default"; + + public DetectMultiTablePane(DetectMutiTableData detectMutiTableData) { + init(detectMutiTableData); + } + + private void init(DetectMutiTableData detectMutiTableData) { + addDetectSingleTablePanes(detectMutiTableData); + } + + protected void addDetectSingleTablePanes(DetectMutiTableData detectMutiTableData) { + this.setLayout(new BorderLayout()); + + List components = new ArrayList<>(); + for (String key : detectMutiTableData.keys()) { + DetectSingleTableData detectSingleTableData = detectMutiTableData.getDetectSingleTableData(key); + int scRecordItemsCount = detectSingleTableData.getSCRecordItemsCount(); + if (scRecordItemsCount > 0) { + DetectSingleTablePane scRecordItemPane = new DetectSingleTablePane(detectSingleTableData); + components.add(scRecordItemPane); + } + } + + + add( + column( + row(flex(), cell(createHelperPane())), + cell(FineLayoutBuilder.createVerticalLayout(10, components.toArray(new Component[0]))) + ).getComponent() + ); + + } + + private UILabel createHelperPane() { + UILabel helper = new UILabel("" + Toolkit.i18nText("Fine-Design_Template_Assistant_Helper_Doc") + ""); + + helper.setCursor(new Cursor(Cursor.HAND_CURSOR)); + helper.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + try { + Desktop.getDesktop().browse(new URI(LocaleLinkProvider.getInstance().getLink(PROPS_LINK_KEY, PROPS_LINK_KEY_DEFAULT))); + } catch (IOException | URISyntaxException ex) { + FineLoggerFactory.getLogger().error("io exception or not find website", ex); + } + } + }); + return helper; + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/table/DetectSingleTablePane.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/table/DetectSingleTablePane.java new file mode 100644 index 0000000000..79857b7797 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/table/DetectSingleTablePane.java @@ -0,0 +1,61 @@ +package com.fr.design.mainframe.shadow.ui.component.table; + +import com.fine.theme.icon.LazyIcon; +import com.fine.theme.utils.FineUIUtils; +import com.fr.design.foldablepane.UIExpandablePane; +import com.fr.design.gui.ilable.MultilineLabel; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.shadow.ui.data.DetectSingleTableData; +import com.fr.nx.analyze.shadow.record.SCRecordLevel; + +import javax.swing.Icon; +import javax.swing.JPanel; +import java.awt.BorderLayout; + +import static com.fine.swing.ui.layout.Layouts.cell; +import static com.fine.swing.ui.layout.Layouts.column; + +/** + * 单个检测结果面板 + * + * @author fly.li + * @since 10.0 + * Created on 2021/09/16 + */ +public class DetectSingleTablePane extends JPanel { + + public DetectSingleTablePane(DetectSingleTableData detectSingleTableData) { + init(detectSingleTableData); + } + + private void init(DetectSingleTableData detectSingleTableData) { + this.setLayout(new BorderLayout()); + + Icon icon = getIcon(detectSingleTableData.getLevel()); + + add(new UIExpandablePane(detectSingleTableData.getTitle(), icon, + column( + 20, + cell(FineUIUtils.wrapComponentWithTitle(new MultilineLabel(detectSingleTableData.getProblemDescription()), Toolkit.i18nText("Fine-Design_Template_Assistant_Problem_Description"))), + cell(FineUIUtils.wrapComponentWithTitle(new MultilineLabel(detectSingleTableData.getAdvice()), Toolkit.i18nText("Fine-Design_Template_Assistant_Problem_Advice"))), + cell(FineUIUtils.wrapComponentWithTitle(new ProblemPositionPane(detectSingleTableData), Toolkit.i18nText("Fine-Design_Template_Assistant_Problem_Position"))) + ).getComponent() + )); + } + + private Icon getIcon(SCRecordLevel level) { + if (level == null) { + return new LazyIcon("shadow_error"); + } + + switch (level) { + case RISK: + return new LazyIcon("shadow_risk"); + case SUGGESTION: + return new LazyIcon("shadow_suggestion"); + default: + return new LazyIcon("shadow_error"); + } + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/table/ProblemPositionPane.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/table/ProblemPositionPane.java new file mode 100644 index 0000000000..9833bb7eab --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/component/table/ProblemPositionPane.java @@ -0,0 +1,39 @@ +package com.fr.design.mainframe.shadow.ui.component.table; + +import com.fine.theme.utils.FineLayoutBuilder; +import com.fr.design.mainframe.shadow.ui.component.item.AbstractSCRecordItemPane; +import com.fr.design.mainframe.shadow.ui.component.item.AbstractSCRecordItemPaneFactory; +import com.fr.design.mainframe.shadow.ui.data.DetectSingleTableData; + +import javax.swing.JPanel; +import java.awt.BorderLayout; +import java.awt.Component; +import java.util.ArrayList; +import java.util.List; + +/** + * @author fly.li + * @since 10.0 + * Created on 2021/11/11 + * 问题位置面板 + */ +public class ProblemPositionPane extends JPanel { + + public ProblemPositionPane(DetectSingleTableData detectSingleTableData) { + + this.setLayout(new BorderLayout()); + + List components = new ArrayList<>(); + for (int i = 0; i < detectSingleTableData.getSCRecordItemsCount() - 1; i++) { + AbstractSCRecordItemPane problemPositionPane = AbstractSCRecordItemPaneFactory.createSCRecordItemPane(detectSingleTableData.getSCRecordItem(i), detectSingleTableData.getExtraData(i)); + components.add(problemPositionPane); + } + int lastIndex = detectSingleTableData.getSCRecordItemsCount() - 1; + AbstractSCRecordItemPane problemPositionPane = AbstractSCRecordItemPaneFactory.createSCRecordItemPane(detectSingleTableData.getSCRecordItem(lastIndex), detectSingleTableData.getExtraData(lastIndex)); + components.add(problemPositionPane); + + add(FineLayoutBuilder.createVerticalLayout(14, components.toArray(new Component[0]))); + + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/DetectMutiTableData.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/DetectMutiTableData.java new file mode 100644 index 0000000000..92d9674196 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/DetectMutiTableData.java @@ -0,0 +1,32 @@ +package com.fr.design.mainframe.shadow.ui.data; + +import java.util.Set; + +/** + * @author fly.li + * @since 10.0 + * Created on 2021/09/14 + * <>对应是检测类型--自动类、建议类、优化类数据对象,里面又包含对应的问题类型数据对象 + */ +public interface DetectMutiTableData { + + /** + * 添加单个检测类型(这里的类型指的是“修改建议、自动优化、sql自动优化建议等”)对应的某个问题类型(“冗余取数、计算性能等”)的数据对象 + */ + void putDetectSingleTableData(String key, DetectSingleTableData detectSingleTableData); + + + /** + * 是否包含某个问题类型 + */ + boolean containsKey(String key); + + DetectSingleTableData getDetectSingleTableData(String key); + + /** + * 获取所有的问题类型 + */ + Set keys(); + + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/DetectSingleTableData.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/DetectSingleTableData.java new file mode 100644 index 0000000000..e49599b50f --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/DetectSingleTableData.java @@ -0,0 +1,51 @@ +package com.fr.design.mainframe.shadow.ui.data; + +import com.fr.nx.analyze.shadow.record.SCRecordLevel; +import com.fr.nx.analyze.shadow.record.item.SCRecordItem; + +import java.util.List; + +/** + * @author fly.li + * @since 10.0 + * Created on 2021/09/14 + * <>每个检测类型的数据类,里面包含检测类代表的每行数据,最终如果想实现一个新的ui数据类,也可以以SCRecordItem为准即可 + */ +public interface DetectSingleTableData { + + String getTitle(); + + String getAdvice(); + + String getProblemDescription(); + + SCRecordLevel getLevel(); + + /** + * 添加检测记录item + */ + void addSCRecordItem(SCRecordItem scRecordItem); + + /** + * 添加检测记录item + */ + void addSCRecordItems(List scRecordItems); + + int getColumnCount(); + + int getSCRecordItemsCount(); + + SCRecordItem getSCRecordItem(int i); + + Object getExtraData(int i); + + /** + * 检查extra是否存在 + */ + boolean checkExtraExist(Object object); + + /** + * 构建问题描述 + */ + void constructProblemDescription(); +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/ProblemInformation.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/ProblemInformation.java new file mode 100644 index 0000000000..5b9024ab98 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/ProblemInformation.java @@ -0,0 +1,21 @@ +package com.fr.design.mainframe.shadow.ui.data; + +/** + * @author fly.li + * @since 10.0 + * Created on 2021/11/16 + * 每个检测任务对应的面板信息 + */ +public interface ProblemInformation { + + String getTitle(); + + String getAdvice(); + + /** + * 与记录相关,因此需要相应的处理方法 + */ + String getProblemDescription(); + + void setProblemDescription(String problemDescription); +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/ProblemInformationFactory.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/ProblemInformationFactory.java new file mode 100644 index 0000000000..7aea33d9ad --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/ProblemInformationFactory.java @@ -0,0 +1,71 @@ +package com.fr.design.mainframe.shadow.ui.data; + +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.shadow.ui.data.impl.DefaultProblemInformation; +import com.fr.nx.analyze.shadow.metric.type.impl.SCCalculationErrorMetricType; +import com.fr.nx.analyze.shadow.metric.type.impl.SCCalculationPerformanceMetricType; +import com.fr.nx.analyze.shadow.metric.type.impl.SCCellRelationMetricType; +import com.fr.nx.analyze.shadow.metric.type.impl.SCDataSourcePerformanceMetricType; +import com.fr.nx.analyze.shadow.metric.type.impl.SCFilterPerformanceMetricType; +import com.fr.nx.analyze.shadow.metric.type.impl.SCFormBackGroundImageOversizeMetricType; +import com.fr.nx.analyze.shadow.metric.type.impl.SCFormComponentTroppoMetricType; +import com.fr.nx.analyze.shadow.metric.type.impl.SCGlobalParameterMetricType; +import com.fr.nx.analyze.shadow.metric.type.impl.SCGlobalWatermarkMetricType; +import com.fr.nx.analyze.shadow.metric.type.impl.SCRecommendMetricType; +import com.fr.nx.analyze.shadow.metric.type.impl.SCRedundantCalculateMetricType; +import com.fr.nx.analyze.shadow.metric.type.impl.SCRedundantDataMetricType; +import com.fr.nx.analyze.shadow.metric.type.impl.SCWidgetMetricType; + +import java.util.HashMap; + +/** + * 异常信息工厂 + * + * @author fly.li + * @since 10.0 + * Created on 2021/11/16 + */ +public class ProblemInformationFactory { + public static final String NONE = "00000"; + private static HashMap problemInformations = new HashMap<>(); + + static { + //这里添加一些信息相关的信息 + String redundantCalculator = Toolkit.i18nText("Fine-Design_Template_Assistant_Redundant_Calculator"); + String filterPerformance = Toolkit.i18nText("Fine-Design_Template_Assistant_Filter_Performance"); + String calculatePerformance = Toolkit.i18nText("Fine-Design_Template_Assistant_Calculate_Performance"); + String globalSettingAbnormal = Toolkit.i18nText("Fine-Design_Template_Assistant_Global_Setting_Abnormal"); + //静态检测 + problemInformations.put(SCCalculationErrorMetricType.DIVISION_BY_ZERO.value(), new DefaultProblemInformation(Toolkit.i18nText("Fine-Design_Template_Assistant_Calculator_Error"), Toolkit.i18nText("Fine-Design_Template_Assistant_Calculator_Error_Dividion_Zero_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Calculator_Error_Dividion_Zero_Description"))); + problemInformations.put(SCCellRelationMetricType.LONG_CHAIN.value(), new DefaultProblemInformation(Toolkit.i18nText("Fine-Design_Template_Assistant_Cell_Relation_Optimize_For_List_Expanding"), Toolkit.i18nText("Fine-Design_Template_Assistant_Cell_Relation_Optimize_For_List_Expanding_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Cell_Relation_Optimize_For_List_Expanding_Description"))); + problemInformations.put(SCRedundantCalculateMetricType.DS_FILTER.value(), new DefaultProblemInformation(redundantCalculator, Toolkit.i18nText("Fine-Design_Template_Assistant_Redundant_Condition_Filter_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Redundant_Condition_Filter_Description"))); + problemInformations.put(SCFilterPerformanceMetricType.FILTER_CONDITION.value(), new DefaultProblemInformation(filterPerformance, Toolkit.i18nText("Fine-Design_Template_Assistant_Filter_Performance_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Filter_Performance_Description"))); + problemInformations.put(SCCalculationPerformanceMetricType.FUN_EXTEND.value(), new DefaultProblemInformation(calculatePerformance, Toolkit.i18nText("Fine-Design_Template_Assistant_Calculate_Performance_Fun_Extend_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Calculate_Performance_Fun_Extend_Description"))); + problemInformations.put(SCRedundantCalculateMetricType.HIDE_ATTR_CR.value(), new DefaultProblemInformation(redundantCalculator, Toolkit.i18nText("Fine-Design_Template_Assistant_Redundant_Calculator_Hide_Column_Row_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Redundant_Calculator_Hide_Column_Row_Description"))); + problemInformations.put(SCCalculationPerformanceMetricType.IF_REPEAT_CAL.value(), new DefaultProblemInformation(calculatePerformance, Toolkit.i18nText("Fine-Design_Template_Assistant_IF_Function_Calculate_Performance_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_IF_Function_Calculate_Performance_Description"))); + problemInformations.put(SCCalculationPerformanceMetricType.LAYER_EXTEND.value(), new DefaultProblemInformation(calculatePerformance, Toolkit.i18nText("Fine-Design_Template_Assistant_Calculate_Performance_Layer_Coordinates_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Calculate_Performance_Layer_Coordinates_Description"))); + problemInformations.put(SCRecommendMetricType.NX.value(), new DefaultProblemInformation(Toolkit.i18nText("Fine-Design_Template_Assistant_Shadow_Record_Nx"), Toolkit.i18nText("Fine-Design_Template_Assistant_Shadow_Record_Nx_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Shadow_Record_Nx_Description"))); + problemInformations.put(SCRedundantCalculateMetricType.CONDITION.value(), new DefaultProblemInformation(redundantCalculator, Toolkit.i18nText("Fine-Design_Template_Assistant_Redundant_Calculator_Condition_Attr_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Redundant_Calculator_Condition_Attr_Description"))); + problemInformations.put(SCRedundantDataMetricType.DATA_FETCH.value(), new DefaultProblemInformation(Toolkit.i18nText("Fine-Design_Template_Assistant_Redundant_Data_Fetch"), Toolkit.i18nText("Fine-Design_Template_Assistant_Redundant_Data_Fetch_Advice"), null)); + problemInformations.put(SCWidgetMetricType.WIDGET_SQL.value(), new DefaultProblemInformation(Toolkit.i18nText("Fine-Design_Template_Assistant_Widget_Performance"), Toolkit.i18nText("Fine-Design_Template_Assistant_Widget_Performance_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Widget_Performance_Description"))); + //动态检测 + problemInformations.put(SCRecommendMetricType.CACHE.value(), new DefaultProblemInformation(Toolkit.i18nText("Fine-Design_Template_Assistant_Shadow_Runtime_Record_Use_Ds_Cache"), Toolkit.i18nText("Fine-Design_Template_Assistant_Shadow_Runtime_Record_Use_Ds_Cache_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Shadow_Runtime_Record_Use_Ds_Cache_Description"))); + problemInformations.put(SCDataSourcePerformanceMetricType.TOO_MANY.value(), new DefaultProblemInformation(Toolkit.i18nText("Fine-Design_Template_Assistant_Shadow_Runtime_Record_Ds_Row_Too_Many"), Toolkit.i18nText("Fine-Design_Template_Assistant_Shadow_Runtime_Record_Ds_Row_Too_Many_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Shadow_Runtime_Record_Ds_Row_Too_Many_Description"))); + problemInformations.put(SCRecommendMetricType.DRIVER.value(), new DefaultProblemInformation(Toolkit.i18nText("Fine-Design_Template_Assistant_Shadow_Runtime_Record_Driver_Recommend"), Toolkit.i18nText("Fine-Design_Template_Assistant_Shadow_Runtime_Record_Driver_Recommend_Advice"), null)); + problemInformations.put(SCCalculationPerformanceMetricType.GROUP_TO_LIST.value(), new DefaultProblemInformation(calculatePerformance, Toolkit.i18nText("Fine-Design_Template_Assistant_Shadow_Runtime_Record_Group_To_List_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Shadow_Runtime_Record_Group_To_List_Description"))); + + problemInformations.put(SCCalculationPerformanceMetricType.GROUP_TO_LIST_AUTO.value(), new DefaultProblemInformation(calculatePerformance, Toolkit.i18nText("Fine-Design_Template_Assistant_Shadow_Runtime_Record_Group_To_List_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Shadow_Runtime_Record_Group_To_List_Description"))); + problemInformations.put(SCFormBackGroundImageOversizeMetricType.IMAGE_OVERSIZE.value(), new DefaultProblemInformation(Toolkit.i18nText("Fine-Design_Template_Assistant_File_Oversize_Problem_Title"), Toolkit.i18nText("Fine-Design_Template_Assistant_File_Oversize_Problem_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_File_Oversize_Problem_Description"))); + problemInformations.put(SCFormComponentTroppoMetricType.COMPONENT_TROPPO.value(), new DefaultProblemInformation(Toolkit.i18nText("Fine-Design_Template_Assistant_Component_Troppo_Problem_Title"), Toolkit.i18nText("Fine-Design_Template_Assistant_Component_Troppo_Problem_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Component_Troppo_Problem_Description"))); + problemInformations.put(SCFormComponentTroppoMetricType.EC_SIMPLIFICATION.value(), new DefaultProblemInformation(Toolkit.i18nText("Fine-Design_Template_Assistant_EC_Simplification_Problem_Title"), Toolkit.i18nText("Fine-Design_Template_Assistant_EC_Simplification_Problem_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_EC_Simplification_Problem_Description"))); + problemInformations.put(SCGlobalParameterMetricType.PARA_SQL.value(), new DefaultProblemInformation(globalSettingAbnormal, Toolkit.i18nText("Fine-Design_Template_Assistant_Global_Parameter_Sql_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Global_Parameter_Sql_Description"))); + problemInformations.put(SCGlobalWatermarkMetricType.WATERMARK_SQL.value(), new DefaultProblemInformation(globalSettingAbnormal, Toolkit.i18nText("Fine-Design_Template_Assistant_Global_Watermark_Sql_Advice"), Toolkit.i18nText("Fine-Design_Template_Assistant_Global_Watermark_Sql_Description"))); + } + + /** + * 获取问题信息 + */ + public static ProblemInformation getProblemInformation(String id) { + return problemInformations.get(id); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/SheetIndexToName.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/SheetIndexToName.java new file mode 100644 index 0000000000..cccad5ff2e --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/SheetIndexToName.java @@ -0,0 +1,48 @@ +package com.fr.design.mainframe.shadow.ui.data; + +import java.util.ArrayList; +import java.util.List; + +/** + * sheet索引转名字 + * + * @author fly.li + * @since 10.0 + * Created on 2021/09/17 + */ +public class SheetIndexToName { + + private final static SheetIndexToName SHEET_INDEX_TO_NAME = new SheetIndexToName(); + private static List sheetNames = new ArrayList<>(); + + public static SheetIndexToName getInstance() { + return SHEET_INDEX_TO_NAME; + } + + public String getSheetName(int index) { + return sheetNames.get(index); + } + + /** + * 添加sheet名字 + * + * @param index sheet索引 + * @param sheetName sheet名字 + */ + public void addSheetName(int index, String sheetName) { + sheetNames.add(index, sheetName); + } + + public int getSheetIndex(String sheetName) { + for (int index = 0; index < sheetNames.size(); index++) { + if (sheetNames.get(index).equals(sheetName)) { + return index; + } + } + return -1; + } + + public int getSheetCount() { + return sheetNames.size(); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/TemplateDetectResultData.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/TemplateDetectResultData.java new file mode 100644 index 0000000000..421eafa719 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/TemplateDetectResultData.java @@ -0,0 +1,40 @@ +package com.fr.design.mainframe.shadow.ui.data; + +import java.util.Set; + +/** + * @author fly.li + * @since 10.0 + * Created on 2021/09/14 + * <>展示面板的总数据类 + */ +public interface TemplateDetectResultData { + /** + * 获取某个检测类型的数据 + * + * @return DetectMutiTableData单个检测类型对应的数据对象 + */ + DetectMutiTableData getDetectMutiTableData(String key); + + /** + * 模板中是否检测出有问题的地方 + * + * @return true代表检测出了错误,false代表没有检测出错误 + */ + boolean isNoError(); + + /** + * 是否包含某个检测类型的问题 + */ + boolean containsKey(String key); + + /** + * 添加某个检测类型的数据 + */ + void putDetectMutiTableData(String key, DetectMutiTableData detectMutiTableData); + + /** + * 获取所有检测类型的key + */ + Set keys(); +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/impl/DefaultDetectMutiTableData.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/impl/DefaultDetectMutiTableData.java new file mode 100644 index 0000000000..89d0e50a7a --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/impl/DefaultDetectMutiTableData.java @@ -0,0 +1,40 @@ +package com.fr.design.mainframe.shadow.ui.data.impl; + +import com.fr.design.mainframe.shadow.ui.data.DetectMutiTableData; +import com.fr.design.mainframe.shadow.ui.data.DetectSingleTableData; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * @author fly.li + * @since 10.0 + * Created on 2021/09/14 + * <>一般没有特别的结构都使用默认的就够用了,区别比较大的是SCDetectSingleTableData中,扩展也是以这个为基本扩展的,主要是里面的数组结构需要改变 + */ +public class DefaultDetectMutiTableData implements DetectMutiTableData { + + private Map detectSingleTableDatas = new HashMap<>(); + + @Override + public boolean containsKey(String key) { + return detectSingleTableDatas.containsKey(key); + } + + @Override + public DetectSingleTableData getDetectSingleTableData(String key) { + return detectSingleTableDatas.get(key); + } + + @Override + public void putDetectSingleTableData(String key, DetectSingleTableData detectSingleTableData) { + detectSingleTableDatas.put(key, detectSingleTableData); + } + + @Override + public Set keys() { + return detectSingleTableDatas.keySet(); + } + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/impl/DefaultDetectSingleTableData.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/impl/DefaultDetectSingleTableData.java new file mode 100644 index 0000000000..d69ef219b9 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/impl/DefaultDetectSingleTableData.java @@ -0,0 +1,149 @@ +package com.fr.design.mainframe.shadow.ui.data.impl; + +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.shadow.ui.data.DetectSingleTableData; +import com.fr.nx.analyze.shadow.record.SCRecordLevel; +import com.fr.nx.analyze.shadow.record.item.SCRecordItem; +import com.fr.nx.analyze.shadow.record.item.impl.SCDataSourceRecordItem; +import com.fr.nx.analyze.shadow.record.item.impl.SCMessageRecordItem; + +import java.util.ArrayList; +import java.util.List; + +/** + * 每个检测类型的数据类 + * + * @author fly.li + * @since 10.0 + * Created on 2021/09/14 + * <> + */ +public class DefaultDetectSingleTableData implements DetectSingleTableData { + private String typeId; + private String title; + private String advice; + private String problemDescription; + private SCRecordLevel level; + //在某个地方放置相应的sheetName和sheetIndex的映射,这个一定会用的 + private List sheetIndexs = new ArrayList<>(); + //每个scReordItem代表每行数据,根据行数据生成相应的ui界面 + private List scRecordItems = new ArrayList<>(); + + public DefaultDetectSingleTableData(String typeId) { + this.typeId = typeId; + } + + public DefaultDetectSingleTableData(String typeId, String title, String advice, String problemDescription, SCRecordLevel level) { + this.typeId = typeId; + this.title = title; + this.advice = advice; + this.problemDescription = problemDescription; + this.level = level; + } + + @Override + public String getTitle() { + return title; + } + + @Override + public String getAdvice() { + return advice; + } + + @Override + public String getProblemDescription() { + return problemDescription; + } + + @Override + public SCRecordLevel getLevel() { + return level; + } + + @Override + public void addSCRecordItem(SCRecordItem scRecordItem) { + scRecordItems.add(scRecordItem); + } + + @Override + public void addSCRecordItems(List scRecordItems) { + this.scRecordItems.addAll(scRecordItems); + } + + @Override + public int getColumnCount() { + return scRecordItems.size(); + } + + /** + * 添加sheetIndex + */ + public void addIndexs(int sheetIndex, int n) { + for (int i = 0; i < n; i++) { + sheetIndexs.add(sheetIndex); + } + } + + @Override + public int getSCRecordItemsCount() { + return scRecordItems.size(); + } + + @Override + public SCRecordItem getSCRecordItem(int i) { + return scRecordItems.get(i); + } + + @Override + public Object getExtraData(int index) { + if (checkExtraExist(index)) { + return sheetIndexs.get(index); + } else { + return null; + } + } + + @Override + public boolean checkExtraExist(Object index) { + return (int) index < sheetIndexs.size(); + } + + + /** + * 因为是按照某个类型分的类,所以这里的SCRecordItem为同一个类型 + */ + + @Override + public void constructProblemDescription() { + StringBuilder stringBuilder = new StringBuilder(); + //在这里构建 + switch (typeId) { + case "01001": + for (SCRecordItem item : + scRecordItems) { + SCDataSourceRecordItem scDataSourceRecordItem = (SCDataSourceRecordItem) item; + String dsName = scDataSourceRecordItem.getDsName(); + String message = scDataSourceRecordItem.getMessage(); + stringBuilder.append(Toolkit.i18nText("Fine-Design_Template_Assistant_Problem_Description_Redundant_Data_Fetch_DS")) + .append(dsName) + .append(Toolkit.i18nText("Fine-Design_Template_Assistant_Problem_Description_Redundant_Data_Fetch_Redundant_Detect")) + .append(message) + .append(Toolkit.i18nText("Fine-Design_Template_Assistant_Problem_Description_Redundant_Data_Fetch_Actual_Used")) + .append('\n'); + + } + break; + //驱动检测的描述信息 + case "30003": + for (SCRecordItem item : + scRecordItems) { + stringBuilder.append(((SCMessageRecordItem) item).getMessage()) + .append('\n'); + } + break; + default: + } + problemDescription = stringBuilder.toString(); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/impl/DefaultProblemInformation.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/impl/DefaultProblemInformation.java new file mode 100644 index 0000000000..aace7b6f8c --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/impl/DefaultProblemInformation.java @@ -0,0 +1,58 @@ +package com.fr.design.mainframe.shadow.ui.data.impl; + +import com.fr.design.mainframe.shadow.ui.data.ProblemInformation; + +/** + * 默认异常信息 + * + * @author fly.li + * @since 10.0 + * Created on 2021/11/16 + */ +public class DefaultProblemInformation implements ProblemInformation { + + /** + * 标题 + */ + private String title; + /** + * 建议 + */ + private String advice; + + /** + * 问题描述 + */ + private String problemDescription; + + public DefaultProblemInformation(String title, String advice) { + this.title = title; + this.advice = advice; + } + + public DefaultProblemInformation(String title, String advice, String problemDescription) { + this.title = title; + this.advice = advice; + this.problemDescription = problemDescription; + } + + @Override + public String getTitle() { + return title; + } + + @Override + public String getAdvice() { + return advice; + } + + @Override + public String getProblemDescription() { + return problemDescription; + } + + @Override + public void setProblemDescription(String problemDescription) { + this.problemDescription = problemDescription; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/impl/DefaultTemplateDetectResultData.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/impl/DefaultTemplateDetectResultData.java new file mode 100644 index 0000000000..2c9e65a058 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/data/impl/DefaultTemplateDetectResultData.java @@ -0,0 +1,50 @@ +package com.fr.design.mainframe.shadow.ui.data.impl; + +import com.fr.design.mainframe.shadow.ui.data.DetectMutiTableData; +import com.fr.design.mainframe.shadow.ui.data.TemplateDetectResultData; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * 展示面板的总数据类实现 + * + * @author fly.li + * @since 10.0 + * Created on 2021/09/14 + */ +public class DefaultTemplateDetectResultData implements TemplateDetectResultData { + //标签,用来对应显示的标签顺序,以此为“修改建议”、“自动优化”和“sql优化建议” + private int dataStatus; + private Map detectMutiTableDatas = new HashMap<>(); + + @Override + public DetectMutiTableData getDetectMutiTableData(String key) { + return detectMutiTableDatas.get(key); + } + + @Override + public void putDetectMutiTableData(String key, DetectMutiTableData detectMutiTableData) { + detectMutiTableDatas.put(key, detectMutiTableData); + } + + public int getDataStatus() { + return dataStatus; + } + + @Override + public boolean isNoError() { + return detectMutiTableDatas.size() == 0; + } + + @Override + public boolean containsKey(String key) { + return detectMutiTableDatas.containsKey(key); + } + + @Override + public Set keys() { + return detectMutiTableDatas.keySet(); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/SCDefaultSCTemplateHelper.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/SCDefaultSCTemplateHelper.java new file mode 100644 index 0000000000..d74bd17445 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/SCDefaultSCTemplateHelper.java @@ -0,0 +1,357 @@ +package com.fr.design.mainframe.shadow.ui.detect; + +import com.fr.base.io.IOFile; +import com.fr.base.vcs.DesignerMode; +import com.fr.design.dialog.BasicPane; +import com.fr.design.dialog.FineJOptionPane; +import com.fr.design.dialog.UIDialog; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.DesignerContext; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.shadow.ui.DetectFailedPane; +import com.fr.design.mainframe.shadow.ui.DetectNoErrorPane; +import com.fr.design.mainframe.shadow.ui.OptimizationProgressPane; +import com.fr.design.mainframe.shadow.ui.component.TemplateHelperShowPane; +import com.fr.design.mainframe.shadow.ui.component.table.AutoOptimizeDetectMultiTablePane; +import com.fr.design.mainframe.shadow.ui.data.TemplateDetectResultData; +import com.fr.invoke.Reflect; +import com.fr.log.FineLoggerFactory; +import com.fr.nx.analyze.shadow.attr.SCOptionAttrMark; +import com.fr.nx.analyze.shadow.metric.SCMetricHelper; + +import javax.swing.BoxLayout; +import javax.swing.JComponent; +import javax.swing.JLayeredPane; +import javax.swing.SwingWorker; +import java.awt.Component; +import java.awt.Rectangle; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.concurrent.ExecutionException; + +/** + * @author fly.li + * @since 10.0 + * Created on 2021/09/15 + * <>交互的需求,需要在检测过程开始前先显示“检测中的界面”,在检测完成后,显示结果界面,(检测前和检测后页面在同一个面板中)决定了检测(SCTemplateHelperDetect)和展示(内部类ShowPane)不可能分开,因此创建一个类来实现完成这两部分 + */ +public class SCDefaultSCTemplateHelper implements SCTemplateHelper { + private static final SCDefaultSCTemplateHelper INSTANCE = new SCDefaultSCTemplateHelper(); + private boolean skipAutoOptimize; + private ShowPane showPane; + + private SCDefaultSCTemplateHelper() { + showPane = new ShowPane(); + } + + public static SCDefaultSCTemplateHelper getInstance() { + return INSTANCE; + } + + /** + * 点击主动检测图标的流程 + */ + public void startAndShow() { + //每次开始之前都清空一下组件,否则不同层级的组件可能会相互影响 + showPane.clearComponent(); + JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + skipAutoOptimize = isSkipAutoOptimize(currentEditingTemplate); + if (!confirmSaveFile(currentEditingTemplate)) { + return; + } + SCTemplateHelperDetect scTemplateHelperDetect = SCDefaultSCTemplateHelperDetect.getInstance(); + SwingWorker resultDealWith = new SwingWorker() { + @Override + protected TemplateDetectResultData doInBackground() { + //做检测 + return scTemplateHelperDetect.detect(); + } + + @Override + protected void done() { + //检测完成后,切换界面显示真正的面板 + TemplateDetectResultData templateDetectResultData = null; + try { + templateDetectResultData = get(); + } catch (InterruptedException | ExecutionException e) { + FineLoggerFactory.getLogger().error("pane repaint error", e); + } + //检测结果出来后,显示结果面板,并且刷新错误显示工具栏 + showPane.showResultPane(scTemplateHelperDetect.getDetectStatus(), templateDetectResultData); + DesignerContext.getDesignerFrame().resetToolkitByPlus(currentEditingTemplate); + } + }; + resultDealWith.execute(); + showPane.startShow(); + } + + /** + * 保存检测和点击错误图标显示检测结果流程 + * + * @param isSaveDetect 其是用来区分保存显示和点击错误图标显示的,该参数目前没有用(保存检测目前被屏蔽) + */ + public void startShow(boolean isSaveDetect) { + showPane.clearComponent(); + skipAutoOptimize = isSkipAutoOptimize(HistoryTemplateListCache.getInstance().getCurrentEditingTemplate()); + SCTemplateHelperDetect scTemplateHelperDetect = SCDefaultSCTemplateHelperDetect.getInstance(); + SwingWorker resultDealWith = new SwingWorker() { + @Override + protected TemplateDetectResultData doInBackground() { + //做检测 + return scTemplateHelperDetect.detect(); + } + + @Override + protected void done() { + TemplateDetectResultData templateDetectResultData = null; + try { + templateDetectResultData = get(); + } catch (InterruptedException | ExecutionException e) { + FineLoggerFactory.getLogger().error("pane repaint error", e); + } + //检测结果出来后,显示结果面板 + if (isSaveDetect) { + //保存检测应该加一个刷新错误数字的操作,记录一下 + SCDefaultSCTemplateHelper.this.showPane.showResultPaneInSave(scTemplateHelperDetect.getDetectStatus(), templateDetectResultData); + } else { + SCDefaultSCTemplateHelper.this.showPane.showResultPane(scTemplateHelperDetect.getDetectStatus(), templateDetectResultData); + } + } + }; + resultDealWith.execute(); + } + + /** + * 关闭检测界面 + */ + public void close() { + showPane.hideDialog(); + } + + /** + * 判断检测状态,从而显示不同的面板。 + */ + private Status judgeCondition(boolean detectStatus, TemplateDetectResultData templateDetectResultData) { + //检测状态为SUCCESS的情况下检测结果也可能为null(还没找出来原因,日志显示并发取消异常) + if (templateDetectResultData == null) { + return Status.FAILURE; + } + if (!detectStatus) { + return Status.FAILURE; + } else if (templateDetectResultData.isNoError()) { + return Status.CORRECT; + } else { + return Status.ERROR; + } + } + + /** + * 检测过程中,如果文件未保存,需要提示保存文件 + * 如果点击不保存返回false(不进行检测并且不显示检测界面),保存返回true(进行检测并且显示检测界面) + */ + private boolean confirmSaveFile(JTemplate currentEditingTemplate) { + boolean confirmSave = true; + if (!currentEditingTemplate.isALLSaved() && !DesignerMode.isVcsMode()) { + currentEditingTemplate.stopEditing(); + confirmSave = FineJOptionPane.showConfirmDialog(DesignerContext.getDesignerFrame(), com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Utils_Would_You_Like_To_Save") + " \"" + currentEditingTemplate.getEditingFILE() + "\" ?", com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Basic_Confirm"), 1, 3) == 0; + if (confirmSave) { + /* + * 最近的保存流程时间是2021.4.15,该流程也没有复用之前的检测流程,即使使用反射也是使用新的流程 + * 如果合并到fr11,可以直接使用saveDirectly方法 + * */ + currentEditingTemplate.saveTemplate(); + currentEditingTemplate.requestFocus(); + try { + // 这个类老jar里没有,兼容一下 + // 看里下 saveTemplate 里面的逻辑好像只是记录埋点之类的信息,如果调不到就不管了 + Reflect.on("com.fr.design.share.SharableManager").call("saveTemplate", currentEditingTemplate); + } catch (Exception e) { + // ignore + } + //在主动检测时,遇到未保存且是首次保存时,会触发首次保存的展示结果流程,主动检测后面的展示流程应该略过,这里记录一下(现在是屏蔽的) + } + } + return confirmSave; + } + + private boolean isSkipAutoOptimize(JTemplate currentEditingTemplate) { + SCOptionAttrMark scOptionAttrMark = getSCOptionAttrMark(currentEditingTemplate); + if (scOptionAttrMark != null && scOptionAttrMark.isSkipAutoTask()) { + return true; + } else { + return false; + } + } + + private SCOptionAttrMark getSCOptionAttrMark(JTemplate currentEditingTemplate) { + IOFile ioFile = getIOFile(currentEditingTemplate); + if (ioFile != null) { + return ioFile.getAttrMark(SCOptionAttrMark.MARK); + } else { + return null; + } + } + + private IOFile getIOFile(JTemplate currentEditingTemplate) { + Object target = currentEditingTemplate.getTarget(); + if (target instanceof IOFile) { + return (IOFile) target; + } + return null; + } + + private enum Status { + + /** + * 检测失败状态 + */ + FAILURE, + + /** + * 没有需要优化的状态 + */ + CORRECT, + + /** + * 包含手动优化项 + */ + ERROR + + } + + /** + * 该面板是显示界面入口类 + */ + private class ShowPane extends BasicPane { + // private ReportComponentCardPane reportComponentCardPane; + private final int WIDTH = 660; + private final int HEIGHT = 600; + /** + * JLayeredPane,用于不同界面之间的切换 + * 只能使用绝对布局的方式导致不同计算机之间显示存在差距 + * 后面使用自定义代码的方式实现界面的切换尝试一下,先记录一下 + */ + JLayeredPane layeredPane; + private UIDialog dialog; + private Rectangle rectangle = new Rectangle(0, 0, 640, 556); + + public ShowPane() { + init(); + } + + /** + * 初始化面板,并显示面板 + */ + private void init() { + this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + dialog = showWindow(DesignerContext.getDesignerFrame(), false); + Rectangle frameBounds = DesignerContext.getDesignerFrame().getBounds(); + dialog.setBounds((int) (frameBounds.getWidth() / 2) - WIDTH / 2, (int) frameBounds.height / 2 - HEIGHT / 2, WIDTH, HEIGHT); + layeredPane = new JLayeredPane(); + layeredPane.setBounds(rectangle); + this.add(layeredPane); + dialog.setTitle(Toolkit.i18nText("Fine-Design_Template_Assistant_Result_Pane_Title")); + dialog.setModal(false); + //在退出结果面板后再刷新一下主面板 + dialog.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + super.windowClosing(e); + JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + if (isChangeWithAutoOptimizeSwitch()) { + currentEditingTemplate.fireTargetModified(); + SCOptionAttrMark scOptionAttrMark = getSCOptionAttrMark(currentEditingTemplate); + if (scOptionAttrMark == null) { + scOptionAttrMark = new SCOptionAttrMark(); + IOFile ioFile = getIOFile(currentEditingTemplate); + ioFile.addAttrMark(scOptionAttrMark); + } + //保存自动优化规则开启状态并记录一下开启自动优化规则的埋点 + scOptionAttrMark.setSkipAutoTask(!skipAutoOptimize); + SCMetricHelper.submitF6013(currentEditingTemplate.getEditingFILE().getPath(), !skipAutoOptimize ? 0 : 1); + } + } + }); + } + + private void showPane(JComponent jComponent) { + layeredPane.add(jComponent, JLayeredPane.DEFAULT_LAYER); + jComponent.setBounds(rectangle); + layeredPane.moveToFront(jComponent); + //这里需要重新showDialog,不然会出现排版错误 + showDialog(); + } + + private void showResultPane(boolean detectStatus, TemplateDetectResultData templateDetectResultData) { + Status status = judgeCondition(detectStatus, templateDetectResultData); + //在这里决定创建哪个对象并显示结果 + switch (status) { + case CORRECT: + DetectNoErrorPane detectNoErrorPane = new DetectNoErrorPane(); + showPane(detectNoErrorPane); + break; + case ERROR: + TemplateHelperShowPane templateHelperShowPane = new TemplateHelperShowPane(templateDetectResultData); + showPane(templateHelperShowPane); + break; + default: + DetectFailedPane detectFailedPane = new DetectFailedPane(); + showPane(detectFailedPane); + } + } + + private void showResultPaneInSave(boolean detectStatus, TemplateDetectResultData templateDetectResultData) { + Status status = judgeCondition(detectStatus, templateDetectResultData); + if (status.equals(Status.ERROR)) { + TemplateHelperShowPane templateHelperShowPane = new TemplateHelperShowPane(templateDetectResultData); + showPane(templateHelperShowPane); + } + } + + private void clearComponent() { + layeredPane.removeAll(); + } + + + private void showDialog() { + dialog.setVisible(true); + } + + private void hideDialog() { + dialog.setVisible(false); + } + + private void startShow() { + //在需要时候才会创建面板对象并且放进layeredPane中 + OptimizationProgressPane optimizationProgressPane = new OptimizationProgressPane(); + optimizationProgressPane.setBounds(rectangle); + layeredPane.add(optimizationProgressPane, JLayeredPane.DEFAULT_LAYER); + layeredPane.moveToFront(optimizationProgressPane); + showDialog(); + } + + public void setDialog(UIDialog dialog) { + this.dialog = dialog; + } + + @Override + protected String title4PopupWindow() { + return null; + } + + + private boolean isChangeWithAutoOptimizeSwitch() { + Component[] components = layeredPane.getComponents(); + for (Component component : components) { + if (component instanceof TemplateHelperShowPane) { + AutoOptimizeDetectMultiTablePane autoOptimizeDetectMultiTablePane = ((TemplateHelperShowPane) component).getAutoOptimizeDetectMultiTablePane(); + if (autoOptimizeDetectMultiTablePane != null && skipAutoOptimize ^ autoOptimizeDetectMultiTablePane.isSkipAutoOptimize()) { + return true; + } + } + } + return false; + } + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/SCDefaultSCTemplateHelperDetect.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/SCDefaultSCTemplateHelperDetect.java new file mode 100644 index 0000000000..4161c90a37 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/SCDefaultSCTemplateHelperDetect.java @@ -0,0 +1,115 @@ +package com.fr.design.mainframe.shadow.ui.detect; + +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.shadow.ui.data.SheetIndexToName; +import com.fr.design.mainframe.shadow.ui.data.TemplateDetectResultData; +import com.fr.design.mainframe.shadow.ui.data.impl.DefaultTemplateDetectResultData; +import com.fr.design.mainframe.shadow.ui.detect.adapter.SCDetectAdapter; +import com.fr.design.mainframe.shadow.ui.detect.adapter.impl.SCDefaultSCDetectAdapter; +import com.fr.design.mainframe.shadow.ui.detect.filter.impl.SCWatermarkFilter; +import com.fr.form.main.Form; +import com.fr.form.ui.ElementCaseEditorProvider; +import com.fr.main.AbstractFineBook; +import com.fr.nx.analyze.shadow.manager.SCManagerFactory; +import com.fr.nx.analyze.shadow.utils.TemplatePathUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author fly.li + * @since 10.0 + * Created on 2021/09/16 + * <> + */ +public class SCDefaultSCTemplateHelperDetect implements SCTemplateHelperDetect { + private static final List SC_DETECT_ADAPTERS = new ArrayList<>(); + private static SCDefaultSCTemplateHelperDetect instance = new SCDefaultSCTemplateHelperDetect(SC_DETECT_ADAPTERS); + + static { + SC_DETECT_ADAPTERS.add(new SCDefaultSCDetectAdapter(new SCWatermarkFilter())); + } + + /** + * 所有检测流程需要实现的适配器 + */ + private List scDetectAdapters = new ArrayList<>(); + private boolean detectStatus; + + private SCDefaultSCTemplateHelperDetect(List scDetectAdapters) { + this.scDetectAdapters = scDetectAdapters; + } + + /** + * 整个设计器执行期间,单个类执行注册一次,因此该注册方法最好在类加载时候执行 + */ + public static void register(SCDetectAdapter scDetectAdapter) { + SC_DETECT_ADAPTERS.add(scDetectAdapter); + } + + public static SCTemplateHelperDetect getInstance() { + return instance; + } + + @Override + public TemplateDetectResultData detect() { + TemplateDetectResultData templateDetectResultData = new DefaultTemplateDetectResultData(); + JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + dataPrepareBeforeDetect(currentEditingTemplate); + int status = 1; + for (SCDetectAdapter scDetectAdapter : scDetectAdapters) { + status &= scDetectAdapter.detectAndAddResult2Data(templateDetectResultData, currentEditingTemplate); + } + detectStatus = status == SCDetectAdapter.SUCCESS; + return templateDetectResultData; + } + + @Override + public int errorCount(JTemplate jTemplate) { + // 模板是否保存在当前工作目录 + if (!jTemplate.getEditingFILE().isEnvFile()) { + return -1; + } + if (isFirstSave(jTemplate)) { + return -1; + } + int errorCount = 0; + for (SCDetectAdapter scDetectAdapter : + scDetectAdapters) { + errorCount += scDetectAdapter.errorCount(jTemplate); + } + return errorCount; + } + + private void dataPrepareBeforeDetect(JTemplate jTemplate) { + Object target = jTemplate.getTarget(); + SheetIndexToName sheetIndexToName = SheetIndexToName.getInstance(); + if (target instanceof AbstractFineBook) { + AbstractFineBook abstractFineBook = (AbstractFineBook) target; + for (int index = 0; index < abstractFineBook.getReportCount(); index++) { + sheetIndexToName.addSheetName(index, abstractFineBook.getReportName(index)); + } + } + //如果是form的话需要,准备一下控件名称和控件索引的对应关系 + if (target instanceof Form) { + Form form = (Form) target; + ElementCaseEditorProvider[] elementCases = form.getElementCases(); + for (int index = 0; index < elementCases.length; index++) { + sheetIndexToName.addSheetName(index, elementCases[index].getWidgetName()); + } + } + + } + + @Override + public boolean isFirstSave(JTemplate jTemplate) { + //初次保存的判断也放在这里,暂时先不管sql优化建议是否是初次保存 + return !SCManagerFactory.sharedManager().hasHistoryShadowTemplate(TemplatePathUtils.trimPrefix(jTemplate.getPath())); + } + + @Override + public boolean getDetectStatus() { + return detectStatus; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/SCTemplateHelper.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/SCTemplateHelper.java new file mode 100644 index 0000000000..a3e4a74dea --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/SCTemplateHelper.java @@ -0,0 +1,11 @@ +package com.fr.design.mainframe.shadow.ui.detect; + +/** + * @author fly.li + * @since 10.0 + * Created on 2021/09/15 + * <>感觉没有必要定义一个接口,以防万一,还是定义一个接口,真正的实现在DefaultTemplateHelper中 + */ +public interface SCTemplateHelper { + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/SCTemplateHelperDetect.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/SCTemplateHelperDetect.java new file mode 100644 index 0000000000..6714027133 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/SCTemplateHelperDetect.java @@ -0,0 +1,39 @@ +package com.fr.design.mainframe.shadow.ui.detect; + +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.shadow.ui.data.TemplateDetectResultData; + +/** + * @author fly.li + * @since 10.0 + * Created on 2021/09/16 + * <>检测流程接口 + */ +public interface SCTemplateHelperDetect { + /** + * 检测流程入口 + * + * @return, TemplateHelperShowData代表所有检测流程检测出的结果(转换成指定接口的形式) + */ + TemplateDetectResultData detect(); + + /** + * 检测流程最终的状态, + * + * @return boolean,true代表成功,false代表失败,只有所有流程都检测成功才会返回true + */ + boolean getDetectStatus(); + + /** + * 是否是第一次保存检测 + */ + boolean isFirstSave(JTemplate jTemplate); + + /** + * 检测出的所有错误问题数 + * + * @return int 检测出的所有问题数 + */ + int errorCount(JTemplate jTemplate); + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/adapter/SCDetectAdapter.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/adapter/SCDetectAdapter.java new file mode 100644 index 0000000000..56e51d16f2 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/adapter/SCDetectAdapter.java @@ -0,0 +1,33 @@ +package com.fr.design.mainframe.shadow.ui.detect.adapter; + +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.shadow.ui.data.TemplateDetectResultData; + +/** + * @author fly.li + * @since 10.0 + * Created on 2021/09/14 + * <>检测流程的适配器接口 + */ +public interface SCDetectAdapter { + int FAILURE = 0; + int SUCCESS = 1; + + /** + * 检测并将结果添加到templateHelperShowData中(需要转换成固定的格式) + * + * @param templateDetectResultData, 检测出的结果转换成固定格式放在添加到TemplateHelperShowData中 + * @param jTemplate, 当前模板 + * @return, int, 当前检测流程检测状态,返回0代表检测失败,返回1代表检测成功 + */ + int detectAndAddResult2Data(TemplateDetectResultData templateDetectResultData, JTemplate jTemplate); + + /** + * 返回检测出的问题数,面板中的显示错误数字 + * + * @param jTemplate, 当前模板 + * @return, int, 当前检测流程检测出来的错误问题数 + */ + int errorCount(JTemplate jTemplate); + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/adapter/impl/SCDefaultSCDetectAdapter.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/adapter/impl/SCDefaultSCDetectAdapter.java new file mode 100644 index 0000000000..b010bba9cb --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/adapter/impl/SCDefaultSCDetectAdapter.java @@ -0,0 +1,248 @@ +package com.fr.design.mainframe.shadow.ui.detect.adapter.impl; + +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.shadow.ui.data.DetectMutiTableData; +import com.fr.design.mainframe.shadow.ui.data.DetectSingleTableData; +import com.fr.design.mainframe.shadow.ui.data.ProblemInformation; +import com.fr.design.mainframe.shadow.ui.data.ProblemInformationFactory; +import com.fr.design.mainframe.shadow.ui.data.TemplateDetectResultData; +import com.fr.design.mainframe.shadow.ui.data.impl.DefaultDetectMutiTableData; +import com.fr.design.mainframe.shadow.ui.data.impl.DefaultDetectSingleTableData; +import com.fr.design.mainframe.shadow.ui.detect.adapter.SCDetectAdapter; +import com.fr.design.mainframe.shadow.ui.detect.filter.SCRecordFilter; +import com.fr.form.main.Form; +import com.fr.form.ui.ElementCaseEditorProvider; +import com.fr.log.FineLoggerFactory; +import com.fr.main.impl.WorkBook; +import com.fr.nx.analyze.shadow.entity.result.SCResult; +import com.fr.nx.analyze.shadow.entity.result.SCResultStatus; +import com.fr.nx.analyze.shadow.manager.SCManager; +import com.fr.nx.analyze.shadow.manager.SCManagerFactory; +import com.fr.nx.analyze.shadow.metric.recorder.impl.SCDesignerMetricRecorder; +import com.fr.nx.analyze.shadow.record.SCRecord; +import com.fr.nx.analyze.shadow.record.SCRecordType; +import com.fr.nx.analyze.shadow.record.impl.SCRecordImpl; +import com.fr.nx.analyze.shadow.record.item.SCRecordItem; +import com.fr.nx.analyze.shadow.runtime.SCRuntimeFactory; +import com.fr.nx.analyze.shadow.template.SCTemplateHolder; +import com.fr.nx.analyze.shadow.utils.TemplatePathUtils; +import com.fr.stable.StringUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; + +/** + * 对ScManager进行包装,SCManage对“修改建议”和“自动优化”两类进行检测 + * + * @author fly.li + * @since 10.0 + * Created on 2021/09/14, + */ +public class SCDefaultSCDetectAdapter implements SCDetectAdapter { + private SCResultStatus status = SCResultStatus.FAILURE; + private SCRecordFilter filter; + + public SCDefaultSCDetectAdapter() { + + } + + public SCDefaultSCDetectAdapter(SCRecordFilter filter) { + this.filter = filter; + } + + @Override + public int detectAndAddResult2Data(TemplateDetectResultData templateDetectResultData, JTemplate jTemplate) { + //动态检测没有检测信息(失败还是成功),以静态检测为准 + List optimizeRecords = detectAndFilter0(jTemplate); + if (!optimizeRecords.isEmpty()) { + for (SCRecord scRecord : + optimizeRecords) { + SCRecordType type = scRecord.getType(); + String typeStr = StringUtils.EMPTY; + switch (type) { + case INFO: + typeStr = Toolkit.i18nText("Fine-Design_Template_Assistant_Manual_Optimize"); + break; + case AUTO: + typeStr = Toolkit.i18nText("Fine-Design_Template_Assistant_Auto_Optimize"); + break; + case RECOMMEND: + typeStr = Toolkit.i18nText("Fine-Design_Template_Assistant_Function_Guide"); + break; + default: + FineLoggerFactory.getLogger().error("unknown type"); + } + fillSCTemplateHelperShowData(scRecord, templateDetectResultData, jTemplate, typeStr); + } + afterFillSCTemplateHelperShowData(templateDetectResultData); + } + return status.equals(SCResultStatus.SUCCEED) ? SUCCESS : FAILURE; + } + + private void afterFillSCTemplateHelperShowData(TemplateDetectResultData templateDetectResultData) { + // 在这里完成未完成的填充,比如有些描述信息不是固定的,在这里需要生成并进行填充,多sheet的描述信息必须在按照id分完类之后进行描述。 + for (String keyMu : + templateDetectResultData.keys()) { + DetectMutiTableData detectMutiTableData = templateDetectResultData.getDetectMutiTableData(keyMu); + for (String keySin : + detectMutiTableData.keys()) { + DetectSingleTableData detectSingleTableData = detectMutiTableData.getDetectSingleTableData(keySin); + if (StringUtils.isEmpty(detectSingleTableData.getProblemDescription())) { + detectSingleTableData.constructProblemDescription(); + } + } + } + } + + @Override + public int errorCount(JTemplate jTemplate) { + int count = 0; + List scRecords = detectAndFilter0(jTemplate); + if (scRecords != null && scRecords.size() > 0) { + for (SCRecord scRecord : scRecords) { + if (!scRecord.getType().equals(SCRecordType.AUTO)) { + count += scRecord.getItems().size(); + } + } + } + return count; + } + + private List detectAndFilter0(JTemplate jTemplate) { + List records = detect0(jTemplate); + return filter0(records); + } + + private List detect0(JTemplate jTemplate) { + SCResult staticSCResult = staticDetect0(jTemplate); + List records = runTimeDetect0(jTemplate); + if (staticSCResult != null) { + List staticOptimizeRecords = staticSCResult.getOptimizeRecords(); + records.addAll(staticOptimizeRecords); + } + return records; + } + + private SCResult staticDetect0(JTemplate jTemplate) { + SCManager scManager = SCManagerFactory.sharedManager(); + SCResult scResult = null; + try { + SCTemplateHolder tplHolder = SCTemplateHolder.parse(jTemplate.getTarget()); + if (tplHolder != null) { + scResult = scManager.acquireShadowTemplate( + TemplatePathUtils.trimPrefix(jTemplate.getPath()), + tplHolder, + SCDesignerMetricRecorder.createManualOperateRecorder() + ).get(); + } + if (scResult != null) { + status = scResult.getStatus(); + } + } catch (InterruptedException | ExecutionException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return scResult; + } + + + private List runTimeDetect0(JTemplate jTemplate) { + List records = new ArrayList<>(); + records.addAll(SCRuntimeFactory.sharedManager().getOptimizeRecords(TemplatePathUtils.trimPrefix(jTemplate.getPath()))); + records.addAll(SCRuntimeFactory.sharedManager().getGlobalOptimizeRecords()); + return records; + } + + private List filter0(List records) { + List remainingRecords = new ArrayList<>(); + for (SCRecord record : records) { + SCRecord scRecord = filterAndGetSCRecord(record); + if (!scRecord.getItems().isEmpty()) { + remainingRecords.add(scRecord); + } + + } + return remainingRecords; + } + + + private void fillSCTemplateHelperShowData(SCRecord scRecord, TemplateDetectResultData templateDetectResultData, JTemplate jTemplate, String type) { + if (StringUtils.isEmpty(type)) { + return; + } + if (!templateDetectResultData.containsKey(type)) { + templateDetectResultData.putDetectMutiTableData(type, new DefaultDetectMutiTableData()); + } + DetectMutiTableData detectMutiTableData = templateDetectResultData.getDetectMutiTableData(type); + String id = scRecord.getId(); + if (StringUtils.isEmpty(id)) { + //可能某个检测任务忘记设置了id + id = ProblemInformationFactory.NONE; + } + if (!detectMutiTableData.containsKey(id)) { + ProblemInformation problemInformation = ProblemInformationFactory.getProblemInformation(scRecord.getId()); + if (problemInformation == null) { + //可能相应检测任务没有设置相应的问题描述、建议、优化类型等 + detectMutiTableData.putDetectSingleTableData(id, new DefaultDetectSingleTableData(id)); + } else { + detectMutiTableData.putDetectSingleTableData(id, new DefaultDetectSingleTableData(id, problemInformation.getTitle(), problemInformation.getAdvice(), problemInformation.getProblemDescription(), scRecord.getLevel())); + } + } + DetectSingleTableData detectSingleTableData = detectMutiTableData.getDetectSingleTableData(scRecord.getId()); + String sheetName = scRecord.getSheetName(); + List items = scRecord.getItems(); + detectSingleTableData.addSCRecordItems(items); + if (!StringUtils.isEmpty(sheetName)) { + int sheetIndex = getSheetIndex(jTemplate, sheetName); + //item的索引对应的是sheetIndex,每次查找item的时候都可以找到对应的sheetIndex. + ((DefaultDetectSingleTableData) detectSingleTableData).addIndexs(sheetIndex, items.size()); + } + } + + private int getSheetIndex(JTemplate jTemplate, String sheetName) { + Object target = jTemplate.getTarget(); + if (target instanceof WorkBook) { + WorkBook workBook = (WorkBook) target; + for (int i = 0; i < workBook.getReportCount(); i++) { + if (sheetName.equals(workBook.getReportName(i))) { + return i; + } + } + } + //兼容一下Form + if (target instanceof Form) { + Form form = (Form) target; + ElementCaseEditorProvider[] elementCases = form.getElementCases(); + for (int i = 0; i < elementCases.length; i++) { + if (sheetName.equals(elementCases[i].getWidgetName())) { + return i; + } + } + } + return -1; + } + + private SCRecord filterAndGetSCRecord(SCRecord record) { + if (record instanceof SCRecordImpl) { + SCRecordImpl scRecord = null; + try { + scRecord = (SCRecordImpl) record.clone(); + } catch (CloneNotSupportedException e) { + FineLoggerFactory.getLogger().error(e, e.getMessage()); + } + if (scRecord == null) { + return record; + } + //因为items是不可修改列表,因此这里删除元素,需要转换一下list的类型 + List items = scRecord.getItems(); + List remainingItems = new ArrayList<>(items); + scRecord.setItems(remainingItems); + if (filter != null) { + filter.filter(remainingItems); + } + return scRecord; + } + return record; + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/filter/SCRecordFilter.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/filter/SCRecordFilter.java new file mode 100644 index 0000000000..2d2b2b1546 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/filter/SCRecordFilter.java @@ -0,0 +1,18 @@ +package com.fr.design.mainframe.shadow.ui.detect.filter; + +import com.fr.nx.analyze.shadow.record.item.SCRecordItem; + +import java.util.List; + +/** + * @author fly.li + * @since 10.0 + * Created on 2022/01/06 + * <>对最终检测到的结果进行过滤 + */ +public interface SCRecordFilter { + /** + * 对已经检测到的数据进行过滤 + */ + void filter(List items); +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/filter/impl/SCWatermarkFilter.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/filter/impl/SCWatermarkFilter.java new file mode 100644 index 0000000000..d41a33ba37 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/detect/filter/impl/SCWatermarkFilter.java @@ -0,0 +1,50 @@ +package com.fr.design.mainframe.shadow.ui.detect.filter.impl; + +import com.fr.base.iofile.attr.WatermarkAttr; +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.i18n.Toolkit; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.shadow.ui.detect.filter.SCRecordFilter; +import com.fr.main.impl.WorkBook; +import com.fr.nx.analyze.shadow.record.item.SCRecordItem; +import com.fr.nx.analyze.shadow.record.item.impl.SCMessageRecordItem; + +import java.util.List; + +/** + * @author fly.li + * @since 10.0 + * Created on 2022/01/06 + * <>水印设置为“当前模板单独设置”的时候,需要将检测到的全局水印结果过滤掉 + */ +public class SCWatermarkFilter implements SCRecordFilter { + @Override + public void filter(List items) { + JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + Object object = currentEditingTemplate.getTarget(); + //这里items不能进行修改,并且 + SCRecordItem scRecordItem = null; + if (object instanceof WorkBook && isWaterMarkValid((WorkBook) object)) { + for (SCRecordItem item : items) { + if (isMeetFilterCondition(item)) { + scRecordItem = item; + } + } + } + if (scRecordItem != null) { + items.remove(scRecordItem); + } + } + + private boolean isMeetFilterCondition(SCRecordItem item) { + if (item instanceof SCMessageRecordItem) { + //暂时只能用message来判断是否是要过滤的item + return ((SCMessageRecordItem) item).getMessage().equals(Toolkit.i18nText("Fine-Design_Template_Assistant_Global_Watermark")); + } + return false; + } + + private boolean isWaterMarkValid(WorkBook workBook) { + return workBook != null && workBook.getAttrMark("WatermarkAttr") != null && ((WatermarkAttr) workBook.getAttrMark("WatermarkAttr")).isValid(); + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/icon/CountIcon.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/icon/CountIcon.java new file mode 100644 index 0000000000..9191278bcd --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/ui/icon/CountIcon.java @@ -0,0 +1,60 @@ +package com.fr.design.mainframe.shadow.ui.icon; + +import com.fr.general.FRFont; + +import javax.swing.ImageIcon; +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Image; + +/** + * 可以显示不同数字的图标 + * + * @author rinoux + * @since 10.0 + * Created on 2021/10/22 + */ +public class CountIcon extends ImageIcon { + + private final static String FONT_NAME = "Microsoft YaHei"; + private final static int FONT_SIZE = 8; + private final static String MAX = "99+"; + private final static int Y_OFFSET = 13; + + private final int count; + + public CountIcon(Image backgroundImage, int count) { + super(backgroundImage); + this.count = count; + } + + @Override + public synchronized final void paintIcon(Component c, Graphics g, int x, int y) { + super.paintIcon(c, g, x, y); + if (count > 0) { + g.setFont(FRFont.getInstance(FONT_NAME, Font.BOLD, FONT_SIZE)); + g.setColor(Color.WHITE); + //根据这个字体不同位数的数字,摸索了一下位置 + String text = String.valueOf(count); + int xOffset; + switch (text.length()) { + case 0: + case 1: + xOffset = 9; + break; + case 2: + xOffset = 6; + break; + case 3: + default: + text = MAX; + xOffset = 3; + break; + } + + g.drawString(text, xOffset, Y_OFFSET); + } + } +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/shadow/utils/DesignerPaneUtil.java b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/utils/DesignerPaneUtil.java new file mode 100644 index 0000000000..3f33645888 --- /dev/null +++ b/designer-realize/src/main/java/com/fr/design/mainframe/shadow/utils/DesignerPaneUtil.java @@ -0,0 +1,33 @@ +package com.fr.design.mainframe.shadow.utils; + +import com.fr.design.file.HistoryTemplateListCache; +import com.fr.design.mainframe.JTemplate; +import com.fr.design.mainframe.ReportComponentCardPane; +import com.fr.invoke.Reflect; + +import javax.swing.JComponent; + +/** + * @author fly.li + * @since 10.0 + * Created on 2021/8/5 + * 获取设计器界面的工具类 + */ +public class DesignerPaneUtil { + + /** + * 获取当前编辑的模板的ReportComponentCardPane + */ + public static ReportComponentCardPane getReportComponentCardPane(JTemplate jTemplate) { + JComponent currentReportComponentPane = jTemplate.getCurrentReportComponentPane(); + return Reflect.on(currentReportComponentPane).get("centerCardPane"); + } + + /** + * 获取当前编辑的模板的ReportComponentCardPane + */ + public static ReportComponentCardPane getCurrentReportComponentCardPane() { + JTemplate currentEditingTemplate = HistoryTemplateListCache.getInstance().getCurrentEditingTemplate(); + return getReportComponentCardPane(currentEditingTemplate); + } +} diff --git a/designer-realize/src/test/java/com/fr/design/shadow/SCDesignerMetricRecorderTest.java b/designer-realize/src/test/java/com/fr/design/shadow/SCDesignerMetricRecorderTest.java new file mode 100644 index 0000000000..b8c12bec1a --- /dev/null +++ b/designer-realize/src/test/java/com/fr/design/shadow/SCDesignerMetricRecorderTest.java @@ -0,0 +1,90 @@ +package com.fr.design.shadow; + +import com.fr.design.DesignerEnvManager; +import com.fr.nx.analyze.shadow.metric.SCMetric; +import com.fr.nx.analyze.shadow.metric.recorder.impl.SCDesignerMetricRecorder; +import com.fr.nx.analyze.shadow.metric.utils.DesignerFileWriter; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.easymock.EasyMock.anyString; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; +import static org.easymock.EasyMock.getCurrentArguments; +import static org.easymock.EasyMock.mock; +import static org.easymock.EasyMock.replay; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Created by loy on 2021/8/25. + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({DesignerEnvManager.class, DesignerFileWriter.class}) +public class SCDesignerMetricRecorderTest { + + @Before + public void setUp() throws Exception { + DesignerEnvManager manager = mock(DesignerEnvManager.class); + expect(manager.getUUID()).andReturn("1234-5678-aaaa-bbbb").anyTimes(); + replay(manager); + PowerMock.mockStatic(DesignerEnvManager.class); + expect(DesignerEnvManager.getEnvManager()).andReturn(manager).anyTimes(); + PowerMock.replay(DesignerEnvManager.class); + } + + @Test + public void recordManualOperate() { + List args = new ArrayList<>(); + + PowerMock.mockStatic(DesignerFileWriter.class); + DesignerFileWriter.appendLine(anyString(), anyString(), anyString()); + expectLastCall().andAnswer(() -> { + args.addAll(Arrays.asList(getCurrentArguments())); + return null; + }).once(); + PowerMock.replay(DesignerFileWriter.class); + + SCDesignerMetricRecorder + .createManualOperateRecorder() + .record(Collections.singletonList(new SCMetric("01", "001", 1))); + + PowerMock.verify(DesignerFileWriter.class); + + assertEquals(3, args.size()); + assertTrue(((String) args.get(0)).startsWith("F0010")); + assertTrue(((String) args.get(1)).startsWith("designerAssistant")); + } + + @Test + public void recordOnSave() { + List args = new ArrayList<>(); + + PowerMock.mockStatic(DesignerFileWriter.class); + DesignerFileWriter.appendLine(anyString(), anyString(), anyString()); + expectLastCall().andAnswer(() -> { + args.addAll(Arrays.asList(getCurrentArguments())); + return null; + }).once(); + PowerMock.replay(DesignerFileWriter.class); + + SCDesignerMetricRecorder + .createOnSaveRecorder() + .record(Collections.singletonList(new SCMetric("02", "001", 2))); + + PowerMock.verify(DesignerFileWriter.class); + + assertEquals(3, args.size()); + assertTrue(((String) args.get(0)).startsWith("F0011")); + assertTrue(((String) args.get(1)).startsWith("designerAssistant")); + } +} \ No newline at end of file