This is an automated email from the ASF dual-hosted git repository. paulk pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 202148b8c3d934399796d61a6531fdfa0b1dc9cc Author: Sandip Chitale <sandipchit...@gmail.com> AuthorDate: Thu Jun 16 14:53:36 2022 -0700 GROOVY-10661: Support launching of ObjectExplore when property rows are double clicked. Also support Array tab aside from Collection and Map Tabs. --- src/main/java/groovy/inspect/Inspector.java | 67 ++++++++++++++++++ .../groovy/groovy/console/ui/ObjectBrowser.groovy | 82 +++++++++++++++++++++- 2 files changed, 147 insertions(+), 2 deletions(-) diff --git a/src/main/java/groovy/inspect/Inspector.java b/src/main/java/groovy/inspect/Inspector.java index 6f5304cd90..8833027d4a 100644 --- a/src/main/java/groovy/inspect/Inspector.java +++ b/src/main/java/groovy/inspect/Inspector.java @@ -60,6 +60,7 @@ public class Inspector { public static final int MEMBER_PARAMS_IDX = 5; public static final int MEMBER_VALUE_IDX = 5; public static final int MEMBER_EXCEPTIONS_IDX = 6; + public static final int MEMBER_RAW_VALUE_IDX = 6; public static final String NOT_APPLICABLE = "n/a"; public static final String GROOVY = "GROOVY"; @@ -210,6 +211,36 @@ public class Inspector { return withoutNulls(result); } + public Object[] getPropertyInfoWithRawValue() { + List props = DefaultGroovyMethods.getMetaPropertyValues(objectUnderInspection); + Object[] result = new Object[props.size()]; + int i = 0; + for (Iterator iter = props.iterator(); iter.hasNext(); i++) { + PropertyValue pv = (PropertyValue) iter.next(); + result[i] = fieldInfoWithRawValue(pv); + } + return result; + } + + protected Object[] fieldInfoWithRawValue(PropertyValue pv) { + Object[] result = new Object[MEMBER_VALUE_IDX + 2]; + result[MEMBER_ORIGIN_IDX] = GROOVY; + result[MEMBER_MODIFIER_IDX] = "public"; + result[MEMBER_DECLARER_IDX] = NOT_APPLICABLE; + result[MEMBER_TYPE_IDX] = shortName(pv.getType()); + result[MEMBER_NAME_IDX] = pv.getName(); + Object rawValue = null; + try { + result[MEMBER_VALUE_IDX] = FormatHelper.inspect(pv.getValue()); + rawValue = pv.getValue(); + } catch (Exception e) { + result[MEMBER_VALUE_IDX] = NOT_APPLICABLE; + } + result = withoutNullsWithRawValue(result); + result[MEMBER_RAW_VALUE_IDX] = rawValue; + return result; + } + protected Class getClassUnderInspection() { return objectUnderInspection.getClass(); } @@ -290,6 +321,15 @@ public class Inspector { return toNormalize; } + protected Object[] withoutNullsWithRawValue(Object[] toNormalize) { + for (int i = 0; i < toNormalize.length; i++) { + if (toNormalize[i] == null) { + toNormalize[i] = NOT_APPLICABLE; + } + } + return toNormalize; + } + public static void print(Object[] memberInfo) { print(System.out, memberInfo); } @@ -331,4 +371,31 @@ public class Inspector { return result; } } + + public static Collection sortWithRawValue(List<Object> memberInfo) { + memberInfo.sort(new MemberComparatorWithRawValue()); + return memberInfo; + } + + public static class MemberComparatorWithRawValue implements Comparator<Object>, Serializable { + private static final long serialVersionUID = -7691851726606749542L; + + @Override + public int compare(Object a, Object b) { + Object[] aStr = (Object[]) a; + Object[] bStr = (Object[]) b; + int result = ((String) aStr[Inspector.MEMBER_NAME_IDX]).compareTo((String) bStr[Inspector.MEMBER_NAME_IDX]); + if (0 != result) return result; + result = ((String) aStr[Inspector.MEMBER_TYPE_IDX]).compareTo((String) bStr[Inspector.MEMBER_TYPE_IDX]); + if (0 != result) return result; + result = ((String)aStr[Inspector.MEMBER_PARAMS_IDX]).compareTo((String) bStr[Inspector.MEMBER_PARAMS_IDX]); + if (0 != result) return result; + result =((String) aStr[Inspector.MEMBER_DECLARER_IDX]).compareTo((String) bStr[Inspector.MEMBER_DECLARER_IDX]); + if (0 != result) return result; + result = ((String)aStr[Inspector.MEMBER_MODIFIER_IDX]).compareTo((String) bStr[Inspector.MEMBER_MODIFIER_IDX]); + if (0 != result) return result; + result = ((String) aStr[Inspector.MEMBER_ORIGIN_IDX]).compareTo((String) bStr[Inspector.MEMBER_ORIGIN_IDX]); + return result; + } + } } diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ObjectBrowser.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ObjectBrowser.groovy index 845d4ead94..8382ea18e6 100644 --- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ObjectBrowser.groovy +++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ObjectBrowser.groovy @@ -22,8 +22,10 @@ import groovy.inspect.Inspector import groovy.swing.table.TableSorter import groovy.swing.SwingBuilder +import javax.swing.ListSelectionModel import javax.swing.WindowConstants import java.awt.FlowLayout +import java.awt.event.* import static groovy.inspect.Inspector.MEMBER_DECLARER_IDX import static groovy.inspect.Inspector.MEMBER_EXCEPTIONS_IDX @@ -33,6 +35,7 @@ import static groovy.inspect.Inspector.MEMBER_ORIGIN_IDX import static groovy.inspect.Inspector.MEMBER_PARAMS_IDX import static groovy.inspect.Inspector.MEMBER_TYPE_IDX import static groovy.inspect.Inspector.MEMBER_VALUE_IDX +import static groovy.inspect.Inspector.MEMBER_RAW_VALUE_IDX /** * A little GUI to show some of the Inspector capabilities. @@ -81,22 +84,67 @@ class ObjectBrowser { label(classLabel) } tabbedPane(constraints: CENTER) { + if (inspector.object?.class?.array) { + scrollPane(name: ' Array data ') { + def values + itemTable = table { + def list = Arrays.asList(inspector.object) + int i = 0 + values = list + def data = list.collect { val -> [i++, val] } + tableModel(list: data) { + closureColumn(header: 'Index', read: { it[0] }) + closureColumn(header: 'Value', read: { it[1] }) + } + } + itemTable.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + def selectedRow = itemTable.selectedRow + if (selectedRow != -1) { + def value = values[selectedRow] + if (value != null) { + ObjectBrowser.inspect(value) + } + } + } + } + }) + } + } if (inspector.object instanceof Collection) { scrollPane(name: ' Collection data ') { + def values itemTable = table { int i = 0 + values = inspector.object.collect { val -> val } def data = inspector.object.collect { val -> [i++, val] } tableModel(list: data) { closureColumn(header: 'Index', read: { it[0] }) closureColumn(header: 'Value', read: { it[1] }) } } + itemTable.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + def selectedRow = itemTable.selectedRow + if (selectedRow != -1) { + def value = values[selectedRow] + if (value != null) { + ObjectBrowser.inspect(value) + } + } + } + } + }) } } if (inspector.object instanceof Map) { scrollPane(name: ' Map data ') { + def values itemTable = table { int i = 0 + values = inspector.object.collect { key, val -> val } def data = inspector.object.collect { key, val -> [i++, key, val] } tableModel(list: data) { closureColumn(header: 'Index', read: { it[0] }) @@ -104,11 +152,24 @@ class ObjectBrowser { closureColumn(header: 'Value', read: { it[2] }) } } + itemTable.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + def selectedRow = itemTable.selectedRow + if (selectedRow != -1) { + def value = values[selectedRow] + if (value != null) { + ObjectBrowser.inspect(value) + } + } + } + } + }) } } scrollPane(name: ' Properties (includes public fields) ') { + def data = Inspector.sortWithRawValue(inspector.propertyInfoWithRawValue.toList()) fieldTable = table { - def data = Inspector.sort(inspector.propertyInfo.toList()) tableModel(list: data) { closureColumn(header: 'Name', read: { it[MEMBER_NAME_IDX] }) closureColumn(header: 'Value', read: { it[MEMBER_VALUE_IDX] }) @@ -116,14 +177,31 @@ class ObjectBrowser { closureColumn(header: 'Origin', read: { it[MEMBER_ORIGIN_IDX] }) closureColumn(header: 'Modifier', read: { it[MEMBER_MODIFIER_IDX] }) closureColumn(header: 'Declarer', read: { it[MEMBER_DECLARER_IDX] }) + closureColumn(header: 'Raw Value', read: { it[MEMBER_RAW_VALUE_IDX] }) } } + fieldTable.getColumnModel().getColumn(6).setMinWidth(0); + fieldTable.getColumnModel().getColumn(6).setMaxWidth(0); + fieldTable.getColumnModel().getColumn(6).setWidth(0); + fieldTable.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + def selectedRow = fieldTable.selectedRow + if (selectedRow != -1) { + def value = fieldTable.getModel().getValueAt(selectedRow, MEMBER_RAW_VALUE_IDX) + println value + if (value != null) { + ObjectBrowser.inspect(value) + } + } + } + } + }) } scrollPane(name: ' (Meta) Methods ') { methodTable = table { def data = Inspector.sort(inspector.methods.toList()) data.addAll(Inspector.sort(inspector.metaMethods.toList())) - tableModel(list: data) { closureColumn(header: 'Name', read: { it[MEMBER_NAME_IDX] }) closureColumn(header: 'Params', read: { it[MEMBER_PARAMS_IDX] })