diff --git a/src/main/java/hae/Config.java b/src/main/java/hae/Config.java index f91bf08..70eddd7 100644 --- a/src/main/java/hae/Config.java +++ b/src/main/java/hae/Config.java @@ -60,7 +60,8 @@ public class Config { "blue", "pink", "magenta", - "gray" + "gray", + "none" }; public static Boolean proVersionStatus = true; diff --git a/src/main/java/hae/HaE.java b/src/main/java/hae/HaE.java index dbdd608..8952596 100644 --- a/src/main/java/hae/HaE.java +++ b/src/main/java/hae/HaE.java @@ -19,7 +19,7 @@ public class HaE implements BurpExtension { public void initialize(MontoyaApi api) { // 设置扩展名称 api.extension().setName("HaE - Highlighter and Extractor"); - String version = "4.3"; + String version = "4.3.1"; // 加载扩展后输出的项目信息 Logging logging = api.logging(); diff --git a/src/main/java/hae/component/Main.java b/src/main/java/hae/component/Main.java index 2bbc6b5..0e2cf25 100644 --- a/src/main/java/hae/component/Main.java +++ b/src/main/java/hae/component/Main.java @@ -5,6 +5,7 @@ import hae.component.board.Databoard; import hae.component.board.message.MessageTableModel; import hae.component.rule.Rules; import hae.utils.ConfigLoader; +import hae.utils.UIEnhancer; import javax.swing.*; import java.awt.*; @@ -36,7 +37,7 @@ public class Main extends JPanel { // 新增Logo JTabbedPane HaETabbedPane = new JTabbedPane(); - boolean isDarkBg = isDarkBg(HaETabbedPane); + boolean isDarkBg = UIEnhancer.isDarkColor(HaETabbedPane.getBackground()); HaETabbedPane.addTab("", getImageIcon(isDarkBg), mainTabbedPane); // 中文Slogan:赋能白帽,高效作战 HaETabbedPane.addTab(" Highlighter and Extractor - Empower ethical hacker for efficient operations. ", null); @@ -44,7 +45,7 @@ public class Main extends JPanel { HaETabbedPane.addPropertyChangeListener("background", new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent e) { - boolean isDarkBg = isDarkBg(HaETabbedPane); + boolean isDarkBg = UIEnhancer.isDarkColor(HaETabbedPane.getBackground()); HaETabbedPane.setIconAt(0, getImageIcon(isDarkBg)); } }); @@ -60,16 +61,6 @@ public class Main extends JPanel { mainTabbedPane.addTab("Config", new Config(api, configLoader, messageTableModel, rules)); } - private boolean isDarkBg(JTabbedPane HaETabbedPane) { - Color bg = HaETabbedPane.getBackground(); - int r = bg.getRed(); - int g = bg.getGreen(); - int b = bg.getBlue(); - int avg = (r + g + b) / 3; - - return avg < 128; - } - private ImageIcon getImageIcon(boolean isDark) { ClassLoader classLoader = getClass().getClassLoader(); URL imageURL; diff --git a/src/main/java/hae/component/board/Databoard.java b/src/main/java/hae/component/board/Databoard.java index f3f3ef1..dab7695 100644 --- a/src/main/java/hae/component/board/Databoard.java +++ b/src/main/java/hae/component/board/Databoard.java @@ -18,8 +18,9 @@ import javax.swing.table.TableModel; import javax.swing.table.TableRowSorter; import java.awt.*; import java.awt.event.*; -import java.util.List; +import java.text.Collator; import java.util.*; +import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; @@ -415,7 +416,7 @@ public class Databoard extends JPanel { String tabTitle = String.format("%s (%s)", entry.getKey(), entry.getValue().size()); Datatable datatablePanel = new Datatable(api, configLoader, entry.getKey(), entry.getValue()); datatablePanel.setTableListener(messageTableModel); - dataTabbedPane.addTab(tabTitle, datatablePanel); + insertTabSorted(dataTabbedPane, tabTitle, datatablePanel); } JSplitPane messageSplitPane = messageTableModel.getSplitPane(); @@ -438,6 +439,26 @@ public class Databoard extends JPanel { } } + public static void insertTabSorted(JTabbedPane tabbedPane, String title, Component component) { + int insertIndex = 0; + int tabCount = tabbedPane.getTabCount(); + + // 使用 Collator 实现更友好的语言排序(支持中文、特殊字符等) + Collator collator = Collator.getInstance(Locale.getDefault()); + collator.setStrength(Collator.PRIMARY); // 忽略大小写和重音 + + for (int i = 0; i < tabCount; i++) { + String existingTitle = tabbedPane.getTitleAt(i); + if (collator.compare(existingTitle, title) > 0) { + insertIndex = i; + break; + } + insertIndex = i + 1; + } + + tabbedPane.insertTab(title, null, component, null, insertIndex); + } + // 提供一个公共方法来发布进度 public void publishProgress(int progress) { publish(progress); diff --git a/src/main/java/hae/component/board/message/MessageRenderer.java b/src/main/java/hae/component/board/message/MessageRenderer.java index 23fd239..79180d0 100644 --- a/src/main/java/hae/component/board/message/MessageRenderer.java +++ b/src/main/java/hae/component/board/message/MessageRenderer.java @@ -25,6 +25,7 @@ public class MessageRenderer extends DefaultTableCellRenderer { this.colorMap.put("pink", new Color(0xFF, 0xC8, 0xC8)); this.colorMap.put("magenta", new Color(0xFF, 0x64, 0xFF)); this.colorMap.put("gray", new Color(0xB4, 0xB4, 0xB4)); + this.colorMap.put("none", new Color(0, 0, 0, 0)); this.table = table; } @@ -41,7 +42,7 @@ public class MessageRenderer extends DefaultTableCellRenderer { component.setForeground(Color.BLACK); return component; } - + MessageEntry messageEntry = log.get(modelRow); // 设置颜色 @@ -54,13 +55,8 @@ public class MessageRenderer extends DefaultTableCellRenderer { } if (isSelected) { - // 通过更改RGB颜色来达成阴影效果 - int red = Math.max(0, color.getRed() - 0x20); - int green = Math.max(0, color.getGreen() - 0x20); - int blue = Math.max(0, color.getBlue() - 0x20); - component.setBackground(new Color(red, green, blue)); + component.setBackground(UIManager.getColor("Table.selectionBackground")); } else { - // 否则使用原始颜色 component.setBackground(color); } diff --git a/src/main/java/hae/component/board/table/Datatable.java b/src/main/java/hae/component/board/table/Datatable.java index c38a914..abc3b1c 100644 --- a/src/main/java/hae/component/board/table/Datatable.java +++ b/src/main/java/hae/component/board/table/Datatable.java @@ -162,17 +162,17 @@ public class Datatable extends JPanel { } private void performSearch() { - RowFilter firstRowFilter = getObjectObjectRowFilter(searchField, true); - RowFilter secondRowFilter = getObjectObjectRowFilter(secondSearchField, false); - if (searchField.getForeground().equals(Color.BLACK)) { - sorter.setRowFilter(firstRowFilter); - if (secondSearchField.getForeground().equals(Color.BLACK)) { - List> filters = new ArrayList<>(); - filters.add(firstRowFilter); - filters.add(secondRowFilter); - sorter.setRowFilter(RowFilter.andFilter(filters)); - } + List> filters = new ArrayList<>(); + + if (UIEnhancer.hasUserInput(searchField)) { + filters.add(getObjectObjectRowFilter(searchField, true)); } + + if (UIEnhancer.hasUserInput(secondSearchField)) { + filters.add(getObjectObjectRowFilter(secondSearchField, false)); + } + + sorter.setRowFilter(filters.isEmpty() ? null : RowFilter.andFilter(filters)); } private RowFilter getObjectObjectRowFilter(JTextField searchField, boolean firstFlag) { diff --git a/src/main/java/hae/component/rule/Rule.java b/src/main/java/hae/component/rule/Rule.java index 28de2e2..85e061e 100644 --- a/src/main/java/hae/component/rule/Rule.java +++ b/src/main/java/hae/component/rule/Rule.java @@ -181,8 +181,7 @@ public class Rule extends JPanel { panel.setOpaque(true); // 复制原始组件的样式 - if (originalComponent instanceof JComponent) { - JComponent origComp = (JComponent) originalComponent; + if (originalComponent instanceof JComponent origComp) { panel.setBackground(origComp.getBackground()); panel.setBorder(origComp.getBorder()); } diff --git a/src/main/java/hae/utils/UIEnhancer.java b/src/main/java/hae/utils/UIEnhancer.java index 01e0daf..aa8b936 100644 --- a/src/main/java/hae/utils/UIEnhancer.java +++ b/src/main/java/hae/utils/UIEnhancer.java @@ -7,38 +7,75 @@ import java.awt.event.FocusListener; public class UIEnhancer { public static void setTextFieldPlaceholder(JTextField textField, String placeholderText) { - // 使用客户端属性来存储占位符文本和占位符状态 + // 存储占位符文本 textField.putClientProperty("placeholderText", placeholderText); textField.putClientProperty("isPlaceholder", true); - // 设置占位符文本和颜色 - setPlaceholderText(textField); + updatePlaceholderText(textField); + + textField.addPropertyChangeListener("background", evt -> { + updateForeground(textField); + }); textField.addFocusListener(new FocusListener() { @Override public void focusGained(FocusEvent e) { - // 当获得焦点且文本是占位符时,清除文本并更改颜色 - if ((boolean) textField.getClientProperty("isPlaceholder")) { - textField.setText(""); - textField.setForeground(Color.BLACK); + if (Boolean.TRUE.equals(textField.getClientProperty("isPlaceholder"))) { textField.putClientProperty("isPlaceholder", false); + updateForeground(textField); + + textField.setText(""); } } @Override public void focusLost(FocusEvent e) { - // 当失去焦点且文本为空时,设置占位符文本和颜色 if (textField.getText().isEmpty()) { - setPlaceholderText(textField); + updatePlaceholderText(textField); + } + } + }); + + textField.addPropertyChangeListener("text", evt -> { + if (Boolean.TRUE.equals(textField.getClientProperty("isPlaceholder"))) { + if (!textField.getText().isEmpty()) { + textField.putClientProperty("isPlaceholder", false); + updateForeground(textField); + } + } else { + if (textField.getText().isEmpty()) { + updatePlaceholderText(textField); } } }); } - private static void setPlaceholderText(JTextField textField) { + private static void updatePlaceholderText(JTextField textField) { String placeholderText = (String) textField.getClientProperty("placeholderText"); - textField.setForeground(Color.GRAY); - textField.setText(placeholderText); textField.putClientProperty("isPlaceholder", true); + textField.setText(placeholderText); + textField.setForeground(Color.GRAY); } -} + + private static void updateForeground(JTextField textField) { + Color bg = textField.getBackground(); + Color fg = isDarkColor(bg) ? Color.WHITE : Color.BLACK; + + if (!Boolean.TRUE.equals(textField.getClientProperty("isPlaceholder"))) { + textField.setForeground(fg); + textField.putClientProperty("isPlaceholder", false); + } + } + + public static boolean isDarkColor(Color color) { + double brightness = 0.299 * color.getRed() + + 0.587 * color.getGreen() + + 0.114 * color.getBlue(); + return brightness < 128; + } + + public static boolean hasUserInput(JTextField field) { + Object prop = field.getClientProperty("isPlaceholder"); + return prop instanceof Boolean && !((Boolean) prop); + } +} \ No newline at end of file