Skip to content

Commit

Permalink
Merge pull request #12972 from riverwanderer/editor-search-regex-reva…
Browse files Browse the repository at this point in the history
…mp-radiobuttons-prev

Editor search improvements - revisions to PR #12798
  • Loading branch information
uckelman authored Dec 15, 2023
2 parents 079f96d + 09ab891 commit ff5abf5
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 44 deletions.
102 changes: 58 additions & 44 deletions vassal-app/src/main/java/VASSAL/configure/ConfigureTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
Expand All @@ -152,6 +151,7 @@
import java.util.stream.IntStream;

import static VASSAL.build.GameModule.MODULE_NAME_PROPERTY;
import static VASSAL.build.GameModule.DESCRIPTION;
import static VASSAL.build.GameModule.MODULE_DESCRIPTION_PROPERTY;
import static VASSAL.build.GameModule.MODULE_OTHER1_PROPERTY;
import static VASSAL.build.GameModule.MODULE_OTHER2_PROPERTY;
Expand All @@ -163,7 +163,6 @@
* that appears in the Configuration window when editing a VASSAL module. Each
* node in the tree structure is a {@link VASSAL.build.Configurable} object,
* whose child nodes are obtained via {@link VASSAL.build.Configurable#getConfigureComponents}.
*
* When we're running as the Extension Editor, this is subclassed by {@link ExtensionTree}, which
* overrides some methods to handle extension-specific differences.
*/
Expand Down Expand Up @@ -224,6 +223,10 @@ public class ConfigureTree extends JTree implements PropertyChangeListener, Mous
public static final Font POPUP_MENU_FONT = new Font(Font.DIALOG, Font.PLAIN, 11);
protected static final List<AdditionalComponent> additionalComponents = new ArrayList<>();

// Internal names of module classes; used where system literals are required rather than translate codes (shown in comment)
private static final String CLASS_MODULE = "Module"; // Editor.GameModule.component_type
private static final String CLASS_HELP_MENU = "Help Menu"; // Editor.Documentation.component_type

/**
* Creates new ConfigureTree
*/
Expand Down Expand Up @@ -2284,26 +2287,39 @@ public void actionPerformed(ActionEvent e21) {
});

prev.addActionListener(ePrev -> {
// in event of a cursor move, breadCrumbs list may need culling before backward step...
if (newNodeSelected && !breadCrumbs.isEmpty()) {
while (nodeListIndex > 0 && breadCrumbs.get(nodeListIndex - 1) >= selectedNodeIndex) {
breadCrumbs.remove(--nodeListIndex);
}
final SearchParameters parametersSetInDialog =
new SearchParameters(search.getText(), normal.isSelected(), word.isSelected(), regex.isSelected(), sensitive.isSelected(), names.isSelected(), types.isSelected(),
simple.isSelected(), full.isSelected(), filters.isSelected(),
traits.isSelected(), expressions.isSelected(), properties.isSelected(), keys.isSelected(), menus.isSelected(), messages.isSelected());

if (!searchParameters.equals(parametersSetInDialog)) {
// previous relies on a prior forward search - search setting changes will block the Prev button but this is to catch the search string itself
prev.setEnabled(false);
chat("~" + Resources.getString("Editor.search_prev_invalid"));
}
else {
if (nodeListIndex > 0) breadCrumbs.remove(--nodeListIndex);
}
// in event of a cursor move, breadCrumbs list may need culling before backward step...
if (newNodeSelected && !breadCrumbs.isEmpty()) {
while (nodeListIndex > 0 && breadCrumbs.get(nodeListIndex - 1) >= selectedNodeIndex) {
breadCrumbs.remove(--nodeListIndex);
}
}
else {
if (nodeListIndex > 0)
breadCrumbs.remove(--nodeListIndex);
}

// stop once we get to the first item
if (nodeListIndex > 0) {
// Rewind to previous match, and move the pointer back
final DefaultMutableTreeNode node = setNode(breadCrumbs.get(nodeListIndex - 1));
if (node != null) {
selectPath(node);
showHitList(node, regexPattern);
// stop once we get to the first item
if (nodeListIndex > 0) {
// Rewind to previous match, and move the pointer back
final DefaultMutableTreeNode node = setNode(breadCrumbs.get(nodeListIndex - 1));
if (node != null) {
selectPath(node);
showHitList(node, regexPattern);
}
}
prev.setEnabled(nodeListIndex > 1); // disable button once at start
}
prev.setEnabled(nodeListIndex > 1); // disable button once at start
});

// Any search option changes immediately disables prev (invalidates backtracking). A renewed search will enable it.
Expand Down Expand Up @@ -2393,7 +2409,10 @@ public void actionPerformed(ActionEvent e22) {
chatter.show(!searchParameters.isOptRegex() ? Resources.getString((searchParameters.isOptNormal() ? "Editor.search_count" : "Editor.search_countWord"), matches, noHTML(searchParameters.getSearchString())) :
regexPattern == null ? "" : Resources.getString("Editor.search_countRegex", matches, noHTML(regexPattern.toString())));

resetPath(); // Search needs to start from current position
if (matches > 0) {
resetPath(); // Search needs to start from current position; if nothing found, cursor stays where it was
}

}

final DefaultMutableTreeNode node = findNode(regexPattern);
Expand Down Expand Up @@ -2476,8 +2495,6 @@ public void actionPerformed(ActionEvent e22) {
filtersTop.add(names);

final JPanel filterList = new JPanel(new MigLayout("hidemode 3,wrap 1," + ConfigurerLayout.STANDARD_INSETS_GAPY, "push[]")); // NON-NLS
//filterList.add(filtersPrompt);
//filterList.add(names);
filterList.add(filtersTop);
filterList.add(types);
filterList.add(traits);
Expand Down Expand Up @@ -2756,10 +2773,9 @@ private boolean checkNode(DefaultMutableTreeNode node, Pattern regexPattern) {

// Special processing to include select items in full search despite not being a SearchTarget

// FIXME: Name check is internal - comparison should ideally be on raw data, not translated
// FIXME: How about extensions ?
// FIXME: How about extensions ?
// Is module descriptor ?
if (getConfigureName(c.getClass()).equals(Resources.getString("Editor.GameModule.component_type"))) {
if (getConfigureName(c.getClass()).equals(CLASS_MODULE)) {
// [Module] - Name, Description & Additional infos fields within the Module component
if (searchParameters.isMatchFull() || searchParameters.isMatchMenus()) {
// check UI content
Expand All @@ -2770,7 +2786,7 @@ private boolean checkNode(DefaultMutableTreeNode node, Pattern regexPattern) {
return true;
}

final String desc = c.getAttributeValueString(MODULE_DESCRIPTION_PROPERTY);
final String desc = c.getAttributeValueString(DESCRIPTION);
if (desc != null && checkString(desc, regexPattern))
return true;

Expand All @@ -2784,13 +2800,15 @@ private boolean checkNode(DefaultMutableTreeNode node, Pattern regexPattern) {
}
}
else {
if (getConfigureName(c.getClass()).equals(Resources.getString("Editor.Documentation.component_type"))) {
final DefaultMutableTreeNode pNode = (DefaultMutableTreeNode) node.getParent();
final Configurable p = (Configurable) pNode.getUserObject();

if (getConfigureName(p.getClass()).equals(CLASS_HELP_MENU)) {
// [Help Menu]
// Menu is also the Name, so only catch here if not already caught as Name

// FIXME: This next section needs to read through the buildComponents. At present this code can't find anything.
if (!showName && (searchParameters.isMatchFull() || searchParameters.isMatchMenus())) {
return checkString(c.getConfigureName(), regexPattern);
return checkString(getConfigureName(c), regexPattern);
}

if (searchParameters.isMatchFull() || searchParameters.isMatchExpressions()) {
Expand Down Expand Up @@ -2970,16 +2988,17 @@ private void showConfigurableHitList(DefaultMutableTreeNode node, Pattern regexP

// FIXME: Name check is internal - comparison should ideally be on raw data, not translated
// FIXME: How about extensions ?
if (getConfigureName(c.getClass()).equals(Resources.getString("Editor.GameModule.component_type"))) {

if (getConfigureName(c.getClass()).equals(CLASS_MODULE)) {
// [Module] - Name, Description & Additional infos fields within the Module component
if (searchParameters.isMatchFull() || searchParameters.isMatchMenus()) {
// display matched UI content

if (!showName) { // not if already captured by name
stringListHits(true, Collections.singletonList(c.getConfigureName()), regexPattern, matchString, item, "", MODULE_NAME_PROPERTY, progress); //NON-NLS
stringListHits(true, Collections.singletonList(getConfigureName(c)), regexPattern, matchString, item, "", MODULE_NAME_PROPERTY, progress); //NON-NLS
}

final String desc = c.getAttributeValueString(MODULE_DESCRIPTION_PROPERTY);
final String desc = c.getAttributeValueString(DESCRIPTION);
final String moduleOther1 = c.getAttributeValueString(MODULE_OTHER1_PROPERTY);
final String moduleOther2 = c.getAttributeValueString(MODULE_OTHER2_PROPERTY);
stringListHits(true, Collections.singletonList(desc), regexPattern, matchString, item, "", MODULE_DESCRIPTION_PROPERTY, progress); //NON-NLS
Expand All @@ -2989,14 +3008,15 @@ private void showConfigurableHitList(DefaultMutableTreeNode node, Pattern regexP
}
else {
// Help ?
// FIXME: Name check is internal - comparison should ideally be on raw data, not translated
if (getConfigureName(c.getClass()).equals(Resources.getString("Editor.Documentation.component_type"))) {
final DefaultMutableTreeNode pNode = (DefaultMutableTreeNode) node.getParent();
final Configurable p = (Configurable) pNode.getUserObject();

if (getConfigureName(p.getClass()).equals(CLASS_HELP_MENU)) {
// Help - special processing to include in full search despite not being a SearchTarget
// Menu is also the Name, so only display here if not already reported as Name

// FIXME: see earlier comment re matching on buildComponents - applies here for output
if (!showName && (searchParameters.isMatchFull() || searchParameters.isMatchMenus())) {
stringListHits(true, Arrays.asList(c.getConfigureName()), regexPattern, matchString, item, "", "UI Text", progress); //NON-NLS
stringListHits(true, Collections.singletonList(getConfigureName(c)), regexPattern, matchString, item, "", "UI Text", progress); //NON-NLS
}
if (searchParameters.isMatchFull() || searchParameters.isMatchExpressions()) {
// content refs will be categorised as Expressions
Expand Down Expand Up @@ -3036,29 +3056,23 @@ private void showConfigurableHitList(DefaultMutableTreeNode node, Pattern regexP
private void showHitList(DefaultMutableTreeNode node, Pattern regexPattern) {
final Configurable c = (Configurable) node.getUserObject();
final String item = getConfigureName(c.getClass());
final String name = StringUtils.defaultString(c.getConfigureName());
final String name = StringUtils.defaultString(getConfigureName(c));
final TargetProgress progress = new TargetProgress();

// name & type (class) are default search categories and only excluded via Advanced Filters
final boolean showName = searchParameters.isMatchNames() || !searchParameters.isMatchAdvanced();
final boolean showTypes = searchParameters.isMatchTypes() || !searchParameters.isMatchAdvanced();

/* Highlighting matches in the headings is possible but not so useful whilst the matches are shown in the detailed output.
final String matchString = Resources.getString("Editor.search_matches", nodeListIndex) + "<b>"
+ (showName ? highlightFinds(noHTML(name), regexPattern) : noHTML(name))
+ " [" + (showTypes ? highlightFinds(noHTML(item), regexPattern) : noHTML(item)) + "]"
+ "</b>: ";
*/
// Heading without highlighting matches
final String matchString = Resources.getString("Editor.search_matches", nodeListIndex)
+ "<b>" + noHTML(name) + " [" + noHTML(item) + "]" + "</b>: ";

stringListHits(showName, Arrays.asList(c.getConfigureName()), regexPattern, matchString, item, "", "Name", progress); //NON-NLS
stringListHits(showTypes, Arrays.asList(item), regexPattern, matchString, item, "", "Type", progress); //NON-NLS
stringListHits(showName, Collections.singletonList(getConfigureName(c)), regexPattern, matchString, item, "", "Name", progress); //NON-NLS
stringListHits(showTypes, List.of(item), regexPattern, matchString, item, "", "Type", progress); //NON-NLS

// Component description is displayed in Simple mode searches or when Name is selected
if (c instanceof ComponentDescription) {
stringListHits(showName, Arrays.asList(((ComponentDescription) c).getDescription()), regexPattern, matchString, item, "", "Description", progress); //NON-NLS
stringListHits(showName, Collections.singletonList(((ComponentDescription) c).getDescription()), regexPattern, matchString, item, "", "Description", progress); //NON-NLS
}

if (searchParameters.isMatchSimple()) return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ Editor.search=Search...
Editor.search_string=String to find
Editor.search_prev=Prev
Editor.search_prevTip=PgUp
Editor.search_prev_invalid=A new search must be initiated with the "Next" button before "Prev" can be used.
Editor.search_next=Next
Editor.search_nextTip=PgDn
Editor.search_case=Exact case
Expand Down

0 comments on commit ff5abf5

Please sign in to comment.