From ef0c09ca5bf8a45e680919fe3ffd94c99ae3f082 Mon Sep 17 00:00:00 2001 From: Mino Date: Fri, 28 Jul 2023 22:17:04 +0100 Subject: [PATCH] feat(gui): show number of search results in search bar (#1819)(PR #1964) * gui: show number of search results in search bar, closes #1819 * optimized imports * use string from resources * applied code formatting --- .../java/jadx/gui/ui/codearea/SearchBar.java | 33 ++++++++++++++++++- .../resources/i18n/Messages_de_DE.properties | 1 + .../resources/i18n/Messages_en_US.properties | 1 + .../resources/i18n/Messages_es_ES.properties | 1 + .../resources/i18n/Messages_ko_KR.properties | 1 + .../resources/i18n/Messages_pt_BR.properties | 1 + .../resources/i18n/Messages_ru_RU.properties | 1 + .../resources/i18n/Messages_zh_CN.properties | 1 + .../resources/i18n/Messages_zh_TW.properties | 1 + 9 files changed, 40 insertions(+), 1 deletion(-) diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/SearchBar.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/SearchBar.java index 3efe94e87..d00652ea3 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/SearchBar.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/SearchBar.java @@ -1,5 +1,6 @@ package jadx.gui.ui.codearea; +import java.awt.Color; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; @@ -10,6 +11,7 @@ import javax.swing.JLabel; import javax.swing.JTextField; import javax.swing.JToggleButton; import javax.swing.JToolBar; +import javax.swing.border.EmptyBorder; import javax.swing.text.BadLocationException; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; @@ -39,10 +41,12 @@ public class SearchBar extends JToolBar { private static final Icon ICON_UP = UiUtils.openSvgIcon("ui/top"); private static final Icon ICON_DOWN = UiUtils.openSvgIcon("ui/bottom"); private static final Icon ICON_CLOSE = UiUtils.openSvgIcon("ui/close"); + private static final int MAX_RESULT_COUNT = 999; private RSyntaxTextArea rTextArea; private final JTextField searchField; + private final JLabel resultCountLabel; private final JToggleButton markAllCB; private final JToggleButton regexCB; private final JToggleButton wholeWordCB; @@ -78,6 +82,12 @@ public class SearchBar extends JToolBar { ActionListener forwardListener = e -> search(1); + resultCountLabel = new JLabel(); + resultCountLabel.setBorder(new EmptyBorder(0, 10, 0, 10)); + resultCountLabel.setForeground(Color.GRAY); + add(resultCountLabel); + setResultCount(0); + matchCaseCB = new JToggleButton(); matchCaseCB.setIcon(ICON_MATCH); matchCaseCB.setSelectedIcon(ICON_MATCH_SELECTED); @@ -151,6 +161,7 @@ public class SearchBar extends JToolBar { if (searchText == null || searchText.length() == 0 || rTextArea.getText() == null) { + setResultCount(0); return; } @@ -165,7 +176,10 @@ public class SearchBar extends JToolBar { context.setRegularExpression(regex); context.setSearchForward(forward); context.setWholeWord(wholeWord); - context.setMarkAll(markAllCB.isSelected()); + + // We enable Mark All even if the corresponding toggle button is off, + // this is a bit hackish, but it's the only way to count matches through SearchEngine + context.setMarkAll(true); // TODO hack: move cursor before previous search for not jump to next occurrence if (direction == 0 && !notFound) { @@ -181,6 +195,15 @@ public class SearchBar extends JToolBar { } SearchResult result = SearchEngine.find(rTextArea, context); + + setResultCount(result.getMarkedCount()); + + // Clear the highlighted results if Mark All is disabled + if (!markAllCB.isSelected()) { + context.setMarkAll(false); + SearchEngine.markAll(rTextArea, context); + } + notFound = !result.wasFound(); if (notFound) { int pos = SearchEngine.getNextMatchPos(searchText, rTextArea.getText(), forward, matchCase, wholeWord); @@ -196,4 +219,12 @@ public class SearchBar extends JToolBar { } searchField.repaint(); } + + private void setResultCount(int count) { + boolean exceedsLimit = count > MAX_RESULT_COUNT; + String plusSign = exceedsLimit ? "+" : ""; + count = exceedsLimit ? MAX_RESULT_COUNT : count; + + resultCountLabel.setText(NLS.str("search.results", plusSign, count)); + } } diff --git a/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties b/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties index 9b8a571b1..ae682a864 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties @@ -69,6 +69,7 @@ search.regex=Regex search.match_case=Groß/Kleinschreibung beachten search.whole_word=Ganzes Wort search.find=Suchen +#search.results= tabs.copy_class_name=Klassennamen kopieren tabs.close=Schließen diff --git a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties index 62bec5a39..9b957904c 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties @@ -69,6 +69,7 @@ search.regex=Regex search.match_case=Match Case search.whole_word=Whole word search.find=Find +search.results=%s%d results tabs.copy_class_name=Copy Name tabs.close=Close diff --git a/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties b/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties index 86b702de7..b83f5ff65 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties @@ -69,6 +69,7 @@ search.regex=Regex search.match_case=Sensible a minúsculas/mayúsculas search.whole_word=Palabra entera search.find=Buscar +#search.results= tabs.copy_class_name=Copy Name tabs.close=Cerrar diff --git a/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties b/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties index 0e69cea55..4023e946d 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties @@ -69,6 +69,7 @@ search.regex=정규식 search.match_case=매치 케이스 search.whole_word=전체 단어 search.find=찾기 +#search.results= tabs.copy_class_name=이름 복사 tabs.close=닫기 diff --git a/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties b/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties index c492c2bcf..30232464e 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties @@ -69,6 +69,7 @@ search.regex=Regex search.match_case=Match Case search.whole_word=Palavra inteira search.find=Encontrar +#search.results= tabs.copy_class_name=Copiar nome tabs.close=Fechar diff --git a/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties b/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties index b18b53fbe..d59b5e04f 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties @@ -69,6 +69,7 @@ search.regex=Регулярные выражения search.match_case=Учитывать регистр search.whole_word=Поиск по словам search.find=Найти +#search.results= tabs.copy_class_name=Копировать имя tabs.close=Закрыть diff --git a/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties b/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties index 5fdab7197..d60aa1b50 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties @@ -69,6 +69,7 @@ search.regex=正则表达式 search.match_case=区分大小写 search.whole_word=全词匹配 search.find=查找 +#search.results= tabs.copy_class_name=复制名称 tabs.close=关闭 diff --git a/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties b/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties index 71303b424..3c847157a 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties @@ -69,6 +69,7 @@ search.regex=Regex search.match_case=大小寫須相符 search.whole_word=全字拼寫須相符 search.find=尋找 +#search.results= tabs.copy_class_name=複製名稱 tabs.close=關閉