From 15dd1340afcab0e52d688abc1623fb8b659e5d56 Mon Sep 17 00:00:00 2001 From: We-unite <3205135446@qq.com> Date: Wed, 26 Feb 2025 14:39:42 +0800 Subject: Reorganize top menu, tools in independent action The old top menu is too hard to use(it's in chaos, and tools button is dealed together with other buttons, which makes it hard to add other tools). In this commit, the top menu is reorganized, especially tool button. It's also registered by settings.xml autometically now. Besides, exec func of tool class is set protected but no longer public, to make the only aviable in the same package but not outside, so that tools could be exec only by ToolsRegister::executeTools, which will check if the tools has been registered first. --- src/cppcheckplus/control/MyContorlUtil.java | 132 ++++++++++++++----------- src/cppcheckplus/control/UIFrame.java | 148 +++++++++------------------- src/cppcheckplus/control/menubar.xml | 17 +--- src/toolsconfig/ToolsConfig.java | 4 +- src/toolsconfig/clangTidy.java | 2 +- src/toolsconfig/cppcheck.java | 8 +- src/toolsconfig/flawfinder.java | 9 +- 7 files changed, 130 insertions(+), 190 deletions(-) diff --git a/src/cppcheckplus/control/MyContorlUtil.java b/src/cppcheckplus/control/MyContorlUtil.java index a43d570..e7e3d07 100644 --- a/src/cppcheckplus/control/MyContorlUtil.java +++ b/src/cppcheckplus/control/MyContorlUtil.java @@ -35,6 +35,7 @@ import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JMenuItem; +import javax.swing.JOptionPane; import javax.swing.UIManager; import javax.swing.plaf.FontUIResource; import javax.xml.parsers.DocumentBuilder; @@ -47,6 +48,7 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import toolsconfig.ToolsConfig; import toolsconfig.ToolsRegistry; @@ -270,38 +272,43 @@ public class MyContorlUtil { public static MyMenuBar loadMenuBar(String xml, ActionListener action) { MyMenuBar menuBar = null; try { + // 初始化XML解析器 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); + // 解析XML文件 Document doc = db.parse(MyContorlUtil.getXMLFile(xml)); Element root = doc.getDocumentElement(); NodeList rootMenus = root.getChildNodes(); - if (rootMenus != null) { - menuBar = new MyMenuBar(); - for (int i = 0; i < rootMenus.getLength(); i++) { - org.w3c.dom.Node menu = rootMenus.item(i); - if (menu.getNodeType() == Node.ELEMENT_NODE) { - if (menu.getNodeName().equalsIgnoreCase("menu")) { - String text = - MyContorlUtil.getStringAttribute(menu, "text"); - MyRootMenu rootMenu = new MyRootMenu(); - rootMenu.setText(text); - menuBar.add(rootMenu); - processMenuItem(menu, rootMenu, action); - } - if (menu.getNodeName().equalsIgnoreCase("logo")) { - String tooltip = - MyContorlUtil.getStringAttribute(menu, - "tooltip"); - String imageURL = - MyContorlUtil.getStringAttribute(menu, "image"); - menuBar.add(Box.createGlue()); - JLabel label = new JLabel( - MyContorlUtil.getImageIcon(imageURL)); - label.setBorder( - BorderFactory.createEmptyBorder(0, 5, 0, 5)); - label.setToolTipText(tooltip); - menuBar.add(label); - } + if (rootMenus == null) { + return null; + } + + menuBar = new MyMenuBar(); + // 遍历 + for (int i = 0; i < rootMenus.getLength(); i++) { + org.w3c.dom.Node menu = rootMenus.item(i); + if (menu.getNodeType() == Node.ELEMENT_NODE) { + if (menu.getNodeName().equalsIgnoreCase("menu")) { + // 菜单一级节点 + String text = + MyContorlUtil.getStringAttribute(menu, "text"); + MyRootMenu rootMenu = new MyRootMenu(); + rootMenu.setText(text); // 以text作为菜单名 + menuBar.add(rootMenu); + processMenuItem(menu, rootMenu, action); + } else if (menu.getNodeName().equalsIgnoreCase("logo")) { + // 总菜单栏的logo + String tooltip = + MyContorlUtil.getStringAttribute(menu, "tooltip"); + String imageURL = + MyContorlUtil.getStringAttribute(menu, "image"); + menuBar.add(Box.createGlue()); + JLabel label = + new JLabel(MyContorlUtil.getImageIcon(imageURL)); + label.setBorder( + BorderFactory.createEmptyBorder(0, 5, 0, 5)); + label.setToolTipText(tooltip); + menuBar.add(label); } } } @@ -366,44 +373,59 @@ public class MyContorlUtil { } catch (Exception ex) { ex.printStackTrace(); } - } - public static void loadToolsRoad(String xml, UIFrame main) { + public static void loadToolsRoad(String xml, UIFrame ui, + ActionListener action) { try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(MyContorlUtil.getXMLFile(xml)); Element root = doc.getDocumentElement(); NodeList tools = root.getChildNodes(); - if (tools != null) { - for (int i = 0; i < tools.getLength(); i++) { - org.w3c.dom.Node menu = tools.item(i); - if (menu.getNodeType() == Node.ELEMENT_NODE) { - if (menu.getNodeName().equalsIgnoreCase("tool")) { - String toolName = - MyContorlUtil.getStringAttribute(menu, - "toolName"); - String filePath = - MyContorlUtil.getStringAttribute(menu, - "filePath"); - String para = - MyContorlUtil.getStringAttribute(menu, "para"); - - try { - Class clazz = - Class.forName("toolsconfig." + toolName); - Object obj = clazz.getDeclaredConstructor() - .newInstance(); - ToolsRegistry.getTool(toolName) - .init(filePath, para, main); - } catch (Exception e) { - e.printStackTrace(); - } - } - } + + MyRootMenu checkBar = new MyRootMenu(); + String toolName, filePath, para; + MyMenuItem menuItem; + if (tools == null) { + // 弹窗提示 + JOptionPane.showMessageDialog(null, "Error: 工具配置文件未找到", + "提示", 2); + return; + } + for (int i = 0; i < tools.getLength(); i++) { + org.w3c.dom.Node menu = tools.item(i); + if (menu.getNodeType() != Node.ELEMENT_NODE || + !menu.getNodeName().equalsIgnoreCase("tool")) { + continue; + } + toolName = MyContorlUtil.getStringAttribute(menu, "toolName"); + filePath = MyContorlUtil.getStringAttribute(menu, "filePath"); + para = MyContorlUtil.getStringAttribute(menu, "para"); + + ToolsConfig tool = ToolsRegistry.getTool(toolName); + if (tool != null) { + tool.init(filePath, para, ui); + continue; } + try { + Class clazz = Class.forName("toolsconfig." + toolName); + Object obj = clazz.getDeclaredConstructor().newInstance(); + ToolsRegistry.getTool(toolName).init(filePath, para, ui); + } catch (Exception e) { + e.printStackTrace(); + } + menuItem = new MyMenuItem(); + menuItem.setText(toolName); + menuItem.setToolTipText(toolName); + menuItem.setActionCommand(toolName); + + menuItem.addActionListener(action); + checkBar.add(menuItem); } + + checkBar.setText("检测工具"); + ui.mymenubar.add(checkBar, 1); } catch (Exception ex) { ex.printStackTrace(); } diff --git a/src/cppcheckplus/control/UIFrame.java b/src/cppcheckplus/control/UIFrame.java index bb15707..499d056 100644 --- a/src/cppcheckplus/control/UIFrame.java +++ b/src/cppcheckplus/control/UIFrame.java @@ -34,19 +34,19 @@ import javax.swing.JTextArea; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.plaf.TabbedPaneUI; +import toolsconfig.ToolsConfig; import toolsconfig.ToolsRegistry; - // 构造界面 public class UIFrame extends JFrame { + public final MyMenuBar mymenubar; // XML配置文件路径 - private final String menuBarXML; - private final String outlookPanelXML; - private final String settingsXML; - private final String stdclangXML; + private final String menuBarXML = "cppcheckplus/control/menubar.xml"; + private final String outlookPanelXML = "cppcheckplus/control/outlook.xml"; + private final String settingsXML = "toolsconfig/settings.xml"; + private final String stdclangXML = "cppcheckplus/control/stdclang.xml"; // 界面组件 private final MyContentPanel contentPanel; - private final MyMenuBar menubar; private final JFileChooser jfc = new JFileChooser();// 文件选择器 private final JFileChooser jfsettings = new JFileChooser();// 配置设定 private final String projectPath; @@ -57,50 +57,39 @@ public class UIFrame extends JFrame { public creatTable ct = new creatTable(); // 生成表格 public TextArea textCheck;// 显示检查进度输出 private MyOutlookPanel outlookPanel; - private MyTabPanel1 footTabPanel; + private MyTabPanel1 footTabPanel; // 底部标签页 private MyShortcutPanel shortcutPanel; private MyTree tree; private MyTextPanel1 testPanel; private ViewPanel viewPanel; - // 显示代码和检查进程的文本区域 private JTextArea textCode;// 显示代码内容 - // 文件操作相关 - private File result; // 存储打开的文件 + private File report; // 导出报告时选择的文件 - private File dir; // 存储打开的目录 - // 构造函数:初始化各个组件,加载配置文件,建立界面布局 public UIFrame() { projectPath = System.getProperty("user.dir"); // 文件选择器初始目录 jfc.setCurrentDirectory(new File("d://")); jfsettings.setCurrentDirectory(new File("d://")); - // 配置文件路径 - menuBarXML = "cppcheckplus/control/menubar.xml"; - outlookPanelXML = "cppcheckplus/control/outlook.xml"; - settingsXML = "toolsconfig/settings.xml"; - stdclangXML = "cppcheckplus/control/stdclang.xml"; - - MyContorlUtil.loadToolsRoad(settingsXML, this);// 加载工具路径设置到当前对象中 ct.initSTDClang(stdclangXML);// 设置clang配置 // 加载菜单栏,注册事件监听 - menubar = MyContorlUtil.loadMenuBar(menuBarXML, new ActionListener() { + mymenubar = MyContorlUtil.loadMenuBar(menuBarXML, new ActionListener() { public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); + File res = null; switch (command) { case "onMenuOpen": - // 打开文件 jfc.setFileSelectionMode(JFileChooser.FILES_ONLY); if (jfc.showOpenDialog(null) == JFileChooser.CANCEL_OPTION) { return; } - result = jfc.getSelectedFile();// result为选择到的文件 - src = result.getAbsolutePath(); - // 读取文件内容并显示到代码区 - textCode.setText(FileTools.readFile(result)); + res = jfc.getSelectedFile(); + src = res.getAbsolutePath(); + textCode.setText( + FileTools.readFile(res)); // 读取文件内容并显示到代码区 // 如果代码标签页不存在,则创建一个 if (!centerTabPanel.isSelectTabComponents("代码")) { centerTabPanel.addTab("代码", testCode); @@ -114,14 +103,15 @@ public class UIFrame extends JFrame { JFileChooser.CANCEL_OPTION) { return; } - dir = jfc.getSelectedFile();// 选择到的目录 - src = dir.getAbsolutePath(); - tree.setRootDir(dir);// 更新目录树 + res = jfc.getSelectedFile(); + src = res.getAbsolutePath(); + tree.setRootDir(res);// 更新目录树 break; case "onMenuSave": - // 保存文件 - if (result != null) { - FileTools.writeFile(result, textCode.getText()); + if (res != null && res.isFile()) { + FileTools.writeFile(res, textCode.getText()); + JOptionPane.showMessageDialog(null, "保存成功", + "提示", 2); } break; case "onMenuClose": @@ -148,51 +138,10 @@ public class UIFrame extends JFrame { if (r == JFileChooser.APPROVE_OPTION) { report = dialog.getSelectedFile(); FileTools.writeFile(report, ct.results); - } else { - JOptionPane.showMessageDialog(null, "路径错误", + JOptionPane.showMessageDialog(null, "导出成功", "提示", 2); - } - break; - case "onCppcheck": - // cppcheck检查 - if (src != null && src.length() != 0) { - new Thread() { - public void run() { - ToolsRegistry.executeTool("cppcheck", src); - viewResult("cppcheck"); - } - }.start(); } else { - JOptionPane.showMessageDialog(null, "目标路径错误", - "提示", 2); - } - break; - case "onClang": - // clang/clang-tidy检查 - if (src != null && src.length() != 0) { - new Thread() { - public void run() { - ToolsRegistry.executeTool("clangTidy", src); - viewResult("clangTidy"); - } - }.start(); - } else { - JOptionPane.showMessageDialog(null, "目标路径错误", - "提示", 2); - } - break; - case "onFlawfinder": - // flawfinder检查 - if (src != null && src.length() != 0) { - new Thread() { - public void run() { - ToolsRegistry.executeTool("flawfinder", - src); - viewResult("flawfinder"); - } - }.start(); - } else { - JOptionPane.showMessageDialog(null, "目标路径错误", + JOptionPane.showMessageDialog(null, "路径错误", "提示", 2); } break; @@ -240,37 +189,28 @@ public class UIFrame extends JFrame { viewPanel.update(ct.results); } break; - case "onSetCppcheckRoad": - // cppcheck路径 - jfsettings.setFileSelectionMode( - JFileChooser.FILES_ONLY); - if (jfsettings.showOpenDialog(null) == - JFileChooser.CANCEL_OPTION) { - return; - } else { - File cppcheckFile = jfsettings.getSelectedFile(); - String cppcheckPathTemp = - cppcheckFile.getAbsolutePath(); - MyContorlUtil.fixSettingPath(settingsXML, - "cppcheck", cppcheckPathTemp); -// changedpathcpp = true; - } + default: + System.out.println("未知命令"); break; - case "onSetFlawfinderRoad": - // flawfinder路径 - jfsettings.setFileSelectionMode( - JFileChooser.FILES_ONLY); - if (jfsettings.showOpenDialog(null) == - JFileChooser.CANCEL_OPTION) { - return;// 撤销则返回 + } + } + }); + + MyContorlUtil.loadToolsRoad(settingsXML, this, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + String toolName = e.getActionCommand(); + if (src != null && src.length() != 0) { + new Thread() { + public void run() { + ct.clearall(); + ToolsRegistry.executeTool(toolName, src); + viewResult(toolName); } - File flawfinderFile = jfsettings.getSelectedFile(); - String flawfinderPathTemp = - flawfinderFile.getAbsolutePath(); - MyContorlUtil.fixSettingPath(settingsXML, "flawfinder", - flawfinderPathTemp); -// changedpathflaw = true; - break; + }.start(); + } else { + JOptionPane.showMessageDialog(null, "目标路径错误", "提示", + 2); } } }); @@ -293,7 +233,7 @@ public class UIFrame extends JFrame { setIconImage(MyContorlUtil.getImage("control/images/logo2.png")); setContentPane(contentPanel); // 菜单栏在最上方 - contentPanel.add(menubar, "North"); + contentPanel.add(mymenubar, "North"); // 除却菜单栏之外的面板 //JPanel centerPane = new JPanel(new BorderLayout()); diff --git a/src/cppcheckplus/control/menubar.xml b/src/cppcheckplus/control/menubar.xml index f2d2f19..0aae26b 100644 --- a/src/cppcheckplus/control/menubar.xml +++ b/src/cppcheckplus/control/menubar.xml @@ -1,28 +1,19 @@ - + - - - - - - - + + - + - - - - diff --git a/src/toolsconfig/ToolsConfig.java b/src/toolsconfig/ToolsConfig.java index 7d55fb2..fc1b6a0 100644 --- a/src/toolsconfig/ToolsConfig.java +++ b/src/toolsconfig/ToolsConfig.java @@ -14,9 +14,9 @@ public abstract class ToolsConfig { protected String params; protected UIFrame uiFrame; protected TextArea result; - protected String name; + public String name; - public abstract void execute(String src); + protected abstract void execute(String src); public void init(String path, String params, UIFrame uiFrame) { this.path = path; diff --git a/src/toolsconfig/clangTidy.java b/src/toolsconfig/clangTidy.java index 8186603..6e3cb59 100644 --- a/src/toolsconfig/clangTidy.java +++ b/src/toolsconfig/clangTidy.java @@ -15,7 +15,7 @@ public class clangTidy extends ToolsConfig { } @Override - public void execute(String src) { + protected void execute(String src) { // clang-tidy 检查 Runtime runtime = Runtime.getRuntime(); Process p = null; diff --git a/src/toolsconfig/cppcheck.java b/src/toolsconfig/cppcheck.java index d36c11f..ca3be27 100644 --- a/src/toolsconfig/cppcheck.java +++ b/src/toolsconfig/cppcheck.java @@ -13,13 +13,7 @@ public class cppcheck extends ToolsConfig { } @Override - public void execute(String src) { - // FIXME:这段代码原因不详,十分令人疑惑 -// if (changedpathcpp) { -// MyContorlUtil.loadToolsRoad(settingsXML, this); -// changedpathcpp = false; -// } - + protected void execute(String src) { // 路径未配置,直接返回 if (path == null) { return; diff --git a/src/toolsconfig/flawfinder.java b/src/toolsconfig/flawfinder.java index 0528eb6..bb953ea 100644 --- a/src/toolsconfig/flawfinder.java +++ b/src/toolsconfig/flawfinder.java @@ -12,13 +12,7 @@ public class flawfinder extends ToolsConfig { } @Override - public void execute(String src) { - // flawfinder -// if (changedpathflaw) { -// MyContorlUtil.loadToolsRoad(settingsXML, this); -// changedpathflaw = false; -// } - + protected void execute(String src) { if (path == null) { return; } @@ -27,7 +21,6 @@ public class flawfinder extends ToolsConfig { Runtime runtime2 = Runtime.getRuntime(); Process p2 = null; try { - // 两个参数数组,一个是csv格式,一个是传入的参数 String[] arguments = new String[] {"python", path, "--csv", src}; -- cgit v1.2.3-70-g09d2