You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2022/06/21 07:04:46 UTC

[groovy] branch GROOVY_3_0_X updated (ef324616e2 -> c7ae59e208)

This is an automated email from the ASF dual-hosted git repository.

paulk pushed a change to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git


    from ef324616e2 GROOVY-10436: STC: closure parameter as type witness for SAM-type target
     new 42f634ae3a GROOVY-10661: Support launching of ObjectExplore when property rows are double clicked. Also support Array tab aside from Collection and Map Tabs. (port to 3_0_X)
     new 78f75bffbe GROOVY-10661: Support column sorting by storing raw values in a hidden table column and other optimization.
     new c7ae59e208 GROOVY-10661: additional refactoring

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/main/java/groovy/inspect/Inspector.java        |  67 +++++++++++
 .../groovy/groovy/console/ui/ObjectBrowser.groovy  | 123 +++++++++++++++++----
 2 files changed, 171 insertions(+), 19 deletions(-)


[groovy] 02/03: GROOVY-10661: Support column sorting by storing raw values in a hidden table column and other optimization.

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 78f75bffbe02e0482936b047fa6aaef249188626
Author: Sandip Chitale <sa...@gmail.com>
AuthorDate: Fri Jun 17 16:50:27 2022 -0700

    GROOVY-10661: Support column sorting by storing raw values in a hidden table column and other optimization.
---
 .../groovy/groovy/console/ui/ObjectBrowser.groovy  | 51 ++++++++++++----------
 1 file changed, 29 insertions(+), 22 deletions(-)

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 ff8605d35e..262ac54909 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
@@ -48,7 +48,7 @@ import static groovy.inspect.Inspector.MEMBER_RAW_VALUE_IDX
 class ObjectBrowser {
 
     def inspector
-    def swing, frame, fieldTable, methodTable, itemTable, mapTable
+    def swing, frame, fieldTable, methodTable, arrayTable, collectionTable, mapTable
 
     static void main(args) {
         inspect('some String')
@@ -86,23 +86,25 @@ class ObjectBrowser {
                 tabbedPane(constraints: CENTER) {
                     if (inspector.object?.class?.array) {
                         scrollPane(name: ' Array data ') {
-                            def values
-                            itemTable = table {
-                                def list = Arrays.asList(inspector.object)
+                            arrayTable = table {
                                 int i = 0
-                                values = list
+                                def list = Arrays.asList(inspector.object)
                                 def data = list.collect { val -> [i++, val] }
                                 tableModel(list: data) {
                                     closureColumn(header: 'Index', read: { it[0] })
                                     closureColumn(header: 'Value', read: { it[1] })
+                                    closureColumn(header: 'Raw Value', read: { it[1] }) // to support sorting
                                 }
                             }
-                            itemTable.addMouseListener(new MouseAdapter() {
+                            arrayTable.getColumnModel().getColumn(2).setMinWidth(0);
+                            arrayTable.getColumnModel().getColumn(2).setMaxWidth(0);
+                            arrayTable.getColumnModel().getColumn(2).setWidth(0);
+                            arrayTable.addMouseListener(new MouseAdapter() {
                                 public void mouseClicked(MouseEvent e) {
                                     if (e.getClickCount() == 2) {
-                                        def selectedRow = itemTable.selectedRow
+                                        def selectedRow = arrayTable.selectedRow
                                         if (selectedRow != -1) {
-                                            def value = values[selectedRow]
+                                            def value = arrayTable.getModel().getValueAt(selectedRow, 2)
                                             if (value != null) {
                                                 ObjectBrowser.inspect(value)
                                             }
@@ -114,22 +116,24 @@ class ObjectBrowser {
                     }
                     if (inspector.object instanceof Collection) {
                         scrollPane(name: ' Collection data ') {
-                            def values
-                            itemTable = table {
+                            collectionTable = 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] })
+                                    closureColumn(header: 'Raw Value', read: { it[1] }) // to support sorting
                                 }
                             }
-                            itemTable.addMouseListener(new MouseAdapter() {
+                            collectionTable.getColumnModel().getColumn(2).setMinWidth(0);
+                            collectionTable.getColumnModel().getColumn(2).setMaxWidth(0);
+                            collectionTable.getColumnModel().getColumn(2).setWidth(0);
+                            collectionTable.addMouseListener(new MouseAdapter() {
                                 public void mouseClicked(MouseEvent e) {
                                     if (e.getClickCount() == 2) {
-                                        def selectedRow = itemTable.selectedRow
+                                        def selectedRow = collectionTable.selectedRow
                                         if (selectedRow != -1) {
-                                            def value = values[selectedRow]
+                                            def value = collectionTable.getModel().getValueAt(selectedRow, 2)
                                             if (value != null) {
                                                 ObjectBrowser.inspect(value)
                                             }
@@ -141,23 +145,25 @@ class ObjectBrowser {
                     }
                     if (inspector.object instanceof Map) {
                         scrollPane(name: ' Map data ') {
-                            def values
-                            itemTable = table {
+                            mapTable = 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] })
                                     closureColumn(header: 'Key', read: { it[1] })
                                     closureColumn(header: 'Value', read: { it[2] })
+                                    closureColumn(header: 'Raw Value', read: { it[2] }) // to support sorting
                                 }
                             }
-                            itemTable.addMouseListener(new MouseAdapter() {
+                            mapTable.getColumnModel().getColumn(3).setMinWidth(0);
+                            mapTable.getColumnModel().getColumn(3).setMaxWidth(0);
+                            mapTable.getColumnModel().getColumn(3).setWidth(0);
+                            mapTable.addMouseListener(new MouseAdapter() {
                                 public void mouseClicked(MouseEvent e) {
                                     if (e.getClickCount() == 2) {
-                                        def selectedRow = itemTable.selectedRow
+                                        def selectedRow = mapTable.selectedRow
                                         if (selectedRow != -1) {
-                                            def value = values[selectedRow]
+                                            def value = mapTable.getModel().getValueAt(selectedRow, 2)
                                             if (value != null) {
                                                 ObjectBrowser.inspect(value)
                                             }
@@ -180,7 +186,7 @@ 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] })
+                                closureColumn(header: 'Raw Value', read: { it[MEMBER_RAW_VALUE_IDX] }) // to support sorting
                             }
                         }
                         fieldTable.getColumnModel().getColumn(6).setMinWidth(0);
@@ -221,7 +227,8 @@ class ObjectBrowser {
         }
 
         // Add a bit of formatting
-        addSorter(itemTable)
+        addSorter(arrayTable)
+        addSorter(collectionTable)
         addSorter(mapTable)
         addSorter(fieldTable)
         addSorter(methodTable)


[groovy] 03/03: GROOVY-10661: additional refactoring

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit c7ae59e2084b1fd2129807b6a33ddd79bd1d138d
Author: Paul King <pa...@asert.com.au>
AuthorDate: Mon Jun 20 23:11:56 2022 +1000

    GROOVY-10661: additional refactoring
---
 .../groovy/groovy/console/ui/ObjectBrowser.groovy  | 100 ++++++++++-----------
 1 file changed, 49 insertions(+), 51 deletions(-)

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 262ac54909..a02cc46501 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,10 +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 java.awt.event.MouseAdapter
+import java.awt.event.MouseEvent
 
 import static groovy.inspect.Inspector.MEMBER_DECLARER_IDX
 import static groovy.inspect.Inspector.MEMBER_EXCEPTIONS_IDX
@@ -87,24 +87,23 @@ class ObjectBrowser {
                     if (inspector.object?.class?.array) {
                         scrollPane(name: ' Array data ') {
                             arrayTable = table {
-                                int i = 0
-                                def list = Arrays.asList(inspector.object)
-                                def data = list.collect { val -> [i++, val] }
-                                tableModel(list: data) {
-                                    closureColumn(header: 'Index', read: { it[0] })
-                                    closureColumn(header: 'Value', read: { it[1] })
-                                    closureColumn(header: 'Raw Value', read: { it[1] }) // to support sorting
+                                tableModel(list: inspector.object.toList().withIndex()) {
+                                    closureColumn(header: 'Index', read: { it[1] })
+                                    closureColumn(header: 'Value', read: { it[0] })
+                                    closureColumn(header: 'Raw Value', read: { it[0] }) // to support sorting
                                 }
                             }
-                            arrayTable.getColumnModel().getColumn(2).setMinWidth(0);
-                            arrayTable.getColumnModel().getColumn(2).setMaxWidth(0);
-                            arrayTable.getColumnModel().getColumn(2).setWidth(0);
+                            arrayTable.columnModel.getColumn(2).with {
+                                minWidth = 0
+                                maxWidth = 0
+                                width = 0
+                            }
                             arrayTable.addMouseListener(new MouseAdapter() {
-                                public void mouseClicked(MouseEvent e) {
-                                    if (e.getClickCount() == 2) {
+                                void mouseClicked(MouseEvent e) {
+                                    if (e.clickCount == 2) {
                                         def selectedRow = arrayTable.selectedRow
                                         if (selectedRow != -1) {
-                                            def value = arrayTable.getModel().getValueAt(selectedRow, 2)
+                                            def value = arrayTable.model.getValueAt(selectedRow, 2)
                                             if (value != null) {
                                                 ObjectBrowser.inspect(value)
                                             }
@@ -113,27 +112,26 @@ class ObjectBrowser {
                                 }
                             })
                         }
-                    }
-                    if (inspector.object instanceof Collection) {
+                    } else if (inspector.object instanceof Collection) {
                         scrollPane(name: ' Collection data ') {
                             collectionTable = table {
-                                int i = 0
-                                def data = inspector.object.collect { val -> [i++, val] }
-                                tableModel(list: data) {
-                                    closureColumn(header: 'Index', read: { it[0] })
-                                    closureColumn(header: 'Value', read: { it[1] })
-                                    closureColumn(header: 'Raw Value', read: { it[1] }) // to support sorting
+                                tableModel(list: inspector.object.withIndex()) {
+                                    closureColumn(header: 'Index', read: { it[1] })
+                                    closureColumn(header: 'Value', read: { it[0] })
+                                    closureColumn(header: 'Raw Value', read: { it[0] }) // to support sorting
                                 }
                             }
-                            collectionTable.getColumnModel().getColumn(2).setMinWidth(0);
-                            collectionTable.getColumnModel().getColumn(2).setMaxWidth(0);
-                            collectionTable.getColumnModel().getColumn(2).setWidth(0);
+                            collectionTable.columnModel.getColumn(2).with {
+                                minWidth = 0
+                                maxWidth = 0
+                                width = 0
+                            }
                             collectionTable.addMouseListener(new MouseAdapter() {
-                                public void mouseClicked(MouseEvent e) {
-                                    if (e.getClickCount() == 2) {
+                                void mouseClicked(MouseEvent e) {
+                                    if (e.clickCount == 2) {
                                         def selectedRow = collectionTable.selectedRow
                                         if (selectedRow != -1) {
-                                            def value = collectionTable.getModel().getValueAt(selectedRow, 2)
+                                            def value = collectionTable.model.getValueAt(selectedRow, 2)
                                             if (value != null) {
                                                 ObjectBrowser.inspect(value)
                                             }
@@ -142,28 +140,27 @@ class ObjectBrowser {
                                 }
                             })
                         }
-                    }
-                    if (inspector.object instanceof Map) {
+                    } else if (inspector.object instanceof Map) {
                         scrollPane(name: ' Map data ') {
                             mapTable = table {
-                                int i = 0
-                                def data = inspector.object.collect { key, val -> [i++, key, val] }
-                                tableModel(list: data) {
-                                    closureColumn(header: 'Index', read: { it[0] })
-                                    closureColumn(header: 'Key', read: { it[1] })
-                                    closureColumn(header: 'Value', read: { it[2] })
-                                    closureColumn(header: 'Raw Value', read: { it[2] }) // to support sorting
+                                tableModel(list: inspector.object.entrySet().withIndex()) {
+                                    closureColumn(header: 'Index', read: { it[1] })
+                                    closureColumn(header: 'Key', read: { it[0].key })
+                                    closureColumn(header: 'Value', read: { it[0].value })
+                                    closureColumn(header: 'Raw Value', read: { it[0].value }) // to support sorting
                                 }
                             }
-                            mapTable.getColumnModel().getColumn(3).setMinWidth(0);
-                            mapTable.getColumnModel().getColumn(3).setMaxWidth(0);
-                            mapTable.getColumnModel().getColumn(3).setWidth(0);
+                            mapTable.columnModel.getColumn(3).with {
+                                minWidth = 0
+                                maxWidth = 0
+                                width = 0
+                            }
                             mapTable.addMouseListener(new MouseAdapter() {
-                                public void mouseClicked(MouseEvent e) {
-                                    if (e.getClickCount() == 2) {
+                                void mouseClicked(MouseEvent e) {
+                                    if (e.clickCount == 2) {
                                         def selectedRow = mapTable.selectedRow
                                         if (selectedRow != -1) {
-                                            def value = mapTable.getModel().getValueAt(selectedRow, 2)
+                                            def value = mapTable.model.getValueAt(selectedRow, 2)
                                             if (value != null) {
                                                 ObjectBrowser.inspect(value)
                                             }
@@ -189,16 +186,17 @@ class ObjectBrowser {
                                 closureColumn(header: 'Raw Value', read: { it[MEMBER_RAW_VALUE_IDX] }) // to support sorting
                             }
                         }
-                        fieldTable.getColumnModel().getColumn(6).setMinWidth(0);
-                        fieldTable.getColumnModel().getColumn(6).setMaxWidth(0);
-                        fieldTable.getColumnModel().getColumn(6).setWidth(0);
+                        fieldTable.columnModel.getColumn(6).with {
+                            minWidth = 0
+                            maxWidth = 0
+                            width = 0
+                        }
                         fieldTable.addMouseListener(new MouseAdapter() {
-                            public void mouseClicked(MouseEvent e) {
-                                if (e.getClickCount() == 2) {
+                            void mouseClicked(MouseEvent e) {
+                                if (e.clickCount == 2) {
                                     def selectedRow = fieldTable.selectedRow
                                     if (selectedRow != -1) {
-                                        def value = fieldTable.getModel().getValueAt(selectedRow, MEMBER_RAW_VALUE_IDX)
-                                        println value
+                                        def value = fieldTable.model.getValueAt(selectedRow, MEMBER_RAW_VALUE_IDX)
                                         if (value != null) {
                                             ObjectBrowser.inspect(value)
                                         }


[groovy] 01/03: GROOVY-10661: Support launching of ObjectExplore when property rows are double clicked. Also support Array tab aside from Collection and Map Tabs. (port to 3_0_X)

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 42f634ae3a2b392353a01f155c58a064e6af00bd
Author: Sandip Chitale <sa...@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. (port to 3_0_X)
---
 src/main/java/groovy/inspect/Inspector.java        | 67 ++++++++++++++++++
 .../groovy/groovy/console/ui/ObjectBrowser.groovy  | 82 +++++++++++++++++++++-
 2 files changed, 148 insertions(+), 1 deletion(-)

diff --git a/src/main/java/groovy/inspect/Inspector.java b/src/main/java/groovy/inspect/Inspector.java
index 12fce8bcd7..8f60e32320 100644
--- a/src/main/java/groovy/inspect/Inspector.java
+++ b/src/main/java/groovy/inspect/Inspector.java
@@ -59,6 +59,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";
@@ -209,6 +210,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();
     }
@@ -289,6 +320,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);
     }
@@ -329,4 +369,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 2ac21c1124..ff8605d35e 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,12 +152,27 @@ 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: ' Public Fields and Properties ') {
                         fieldTable = table {
                             def data = Inspector.sort(inspector.publicFields.toList())
                             data.addAll(Inspector.sort(inspector.propertyInfo.toList()))
+                        def data = Inspector.sortWithRawValue(inspector.propertyInfoWithRawValue.toList())
+                        fieldTable = table {
                             tableModel(list: data) {
                                 closureColumn(header: 'Name', read: { it[MEMBER_NAME_IDX] })
                                 closureColumn(header: 'Value', read: { it[MEMBER_VALUE_IDX] })
@@ -117,14 +180,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] })