From 487d3d3800c4ba3b14bc58b2538795bbfe621488 Mon Sep 17 00:00:00 2001 From: bobbylight Date: Fri, 30 Dec 2022 19:02:22 -0500 Subject: [PATCH] Add utility method to find all descendant components of a particular type. This is useful for custom serach fialogs, e.g. FindInFilesDialog, in applications --- RSTAUI/build.gradle | 2 - .../org/fife/rsta/ui/DecorativeIconPanel.java | 2 +- .../main/java/org/fife/rsta/ui/UIUtil.java | 34 +++++++- .../java/org/fife/rsta/ui/UIUtilTest.java | 82 +++++++++++++++++++ build.gradle | 9 ++ 5 files changed, 122 insertions(+), 7 deletions(-) create mode 100644 RSTAUI/src/test/java/org/fife/rsta/ui/UIUtilTest.java diff --git a/RSTAUI/build.gradle b/RSTAUI/build.gradle index 21b5ddc..54bd97e 100644 --- a/RSTAUI/build.gradle +++ b/RSTAUI/build.gradle @@ -11,8 +11,6 @@ archivesBaseName = 'rstaui' dependencies { api 'com.fifesoft:rsyntaxtextarea:3.3.1' api 'com.fifesoft:autocomplete:3.3.1-SNAPSHOT' - testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.1' - testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.1' } ext.isReleaseVersion = !project.version.endsWith('SNAPSHOT') diff --git a/RSTAUI/src/main/java/org/fife/rsta/ui/DecorativeIconPanel.java b/RSTAUI/src/main/java/org/fife/rsta/ui/DecorativeIconPanel.java index d9cc6dc..9d9e90b 100644 --- a/RSTAUI/src/main/java/org/fife/rsta/ui/DecorativeIconPanel.java +++ b/RSTAUI/src/main/java/org/fife/rsta/ui/DecorativeIconPanel.java @@ -36,7 +36,7 @@ public class DecorativeIconPanel extends JPanel { * listening to with other combo boxes or text fields without a * DecorativeIconPanel. */ - private static final int DEFAULT_WIDTH = 8; + public static final int DEFAULT_WIDTH = 8; private JLabel iconLabel; private boolean showIcon; diff --git a/RSTAUI/src/main/java/org/fife/rsta/ui/UIUtil.java b/RSTAUI/src/main/java/org/fife/rsta/ui/UIUtil.java index bef0785..c340da2 100644 --- a/RSTAUI/src/main/java/org/fife/rsta/ui/UIUtil.java +++ b/RSTAUI/src/main/java/org/fife/rsta/ui/UIUtil.java @@ -14,9 +14,7 @@ import java.lang.reflect.Method; import java.net.URI; import java.net.URISyntaxException; -import java.util.Locale; -import java.util.MissingResourceException; -import java.util.ResourceBundle; +import java.util.*; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComboBox; @@ -144,6 +142,34 @@ private static SpringLayout.Constraints getConstraintsForCell( } + /** + * Returns all components that are ancestors of {@code comp} that are of the + * specified class (or a subclass of it). + * + * @param comp The parent component. + * @param clazz The class of children to look for. + * @param The type of children to look for. + * @return The matching children. This will be an empty list if none are found. + */ + @SuppressWarnings("unchecked") + public static List getDescendantsOfType(Container comp, Class clazz) { + List result = new ArrayList<>(); + Stack stack = new Stack<>(); + stack.add(comp); + while (!stack.isEmpty()) { + Component current = stack.pop(); + if (clazz.isAssignableFrom(current.getClass())) { + result.add((T)current); + } + if (current instanceof Container) { + Container container = (Container)current; + stack.addAll(Arrays.asList(container.getComponents())); + } + } + return result; + } + + /** * Returns the singleton java.awt.Desktop instance, or * null if it is unsupported on this platform (or the JRE @@ -209,7 +235,7 @@ public static Color getErrorTextForeground() { defaultFG.getBlue()>=160) { return new Color(255, 160, 160); } - return Color.red; + return Color.RED; } diff --git a/RSTAUI/src/test/java/org/fife/rsta/ui/UIUtilTest.java b/RSTAUI/src/test/java/org/fife/rsta/ui/UIUtilTest.java new file mode 100644 index 0000000..6c39460 --- /dev/null +++ b/RSTAUI/src/test/java/org/fife/rsta/ui/UIUtilTest.java @@ -0,0 +1,82 @@ +/* + * Licensed under a modified BSD license. + * See the included license file for details. + */ +package org.fife.rsta.ui; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import javax.swing.*; +import java.util.List; + + +/** + * Unit tests for the {@code UIUtil} class. + * + * @author Robert Futrell + * @version 1.0 + */ +class UIUtilTest { + + @Test + void testGetDescendantsOfType_topLevelMatch() { + JLabel label = new JLabel(); + List result = UIUtil.getDescendantsOfType(label, JLabel.class); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(label, result.get(0)); + } + + @Test + void testGetDescendantsOfType_nestedMatch() { + JPanel panel = new JPanel(); + JLabel label = new JLabel(); + panel.add(label); + List result = UIUtil.getDescendantsOfType(panel, JLabel.class); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(label, result.get(0)); + } + + @Test + void testGetDescendantsOfType_nestedTwoDeepMatch() { + JPanel panel = new JPanel(); + JPanel nestedPanel = new JPanel(); + panel.add(nestedPanel); + JLabel label = new JLabel(); + nestedPanel.add(label); + List result = UIUtil.getDescendantsOfType(panel, JLabel.class); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(label, result.get(0)); + } + + @Test + void testGetDescendantsOfType_subclass() { + JPanel panel = new JPanel(); + SubclassedJLabel label = new SubclassedJLabel(); + panel.add(label); + List result = UIUtil.getDescendantsOfType(panel, JLabel.class); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals(label, result.get(0)); + } + + @Test + void testGetDescendantsOfType_multiple() { + JPanel panel = new JPanel(); + JPanel nestedPanel = new JPanel(); + panel.add(nestedPanel); + JLabel label = new JLabel(); + nestedPanel.add(label); + SubclassedJLabel label2 = new SubclassedJLabel(); + panel.add(label2); + List result = UIUtil.getDescendantsOfType(panel, JLabel.class); + Assertions.assertEquals(2, result.size()); + Assertions.assertEquals(label2, result.get(0)); + Assertions.assertEquals(label, result.get(1)); + } + + /** + * A dummy subclass used for unit testing purposes. + */ + private static class SubclassedJLabel extends JLabel { + } +} diff --git a/build.gradle b/build.gradle index ea7e797..c093a43 100644 --- a/build.gradle +++ b/build.gradle @@ -26,6 +26,10 @@ subprojects { apply plugin: 'checkstyle' apply plugin: 'com.github.spotbugs' + test { + useJUnitPlatform() + } + checkstyle { toolVersion = '9.3' } @@ -56,6 +60,11 @@ subprojects { } } + dependencies { + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.1' + } + compileJava { sourceCompatibility javaVersion.toString() targetCompatibility javaVersion.toString()