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/07/13 14:17:07 UTC

[groovy] 02/03: GROOVY-10686: Additional refactoring - a few more icons and context menus for ObjectBrowser

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

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

commit 3587c64da4bb0e6ab8914e7bc78b36b7cf5dcddb
Author: Paul King <pa...@asert.com.au>
AuthorDate: Wed Jul 13 21:52:03 2022 +1000

    GROOVY-10686: Additional refactoring - a few more icons and context menus for ObjectBrowser
---
 .../groovy/groovy/console/ui/AstBrowser.groovy     |  22 +++--
 .../groovy/groovy/console/ui/ConsoleActions.groovy |  13 ++-
 .../groovy/groovy/console/ui/ObjectBrowser.groovy  | 110 ++++++++++++++++-----
 3 files changed, 111 insertions(+), 34 deletions(-)

diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstBrowser.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstBrowser.groovy
index 4bca92e09f..a73775fecb 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstBrowser.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstBrowser.groovy
@@ -154,15 +154,25 @@ class AstBrowser {
                         action(name: 'Smaller Font', closure: this.&smallerFont, mnemonic: 'S', accelerator: shortcut('shift S'))
                     }
                     menuItem {
-                        refreshAction = action(name: 'Refresh', closure: {
-                            decompile(phasePicker.selectedItem.phaseId, script())
-                            compile(jTree, script(), phasePicker.selectedItem.phaseId)
-                            initAuxViews()
-                        }, mnemonic: 'R', accelerator: KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0))
+                        refreshAction = action(
+                                name: 'Refresh',
+                                closure: {
+                                    decompile(phasePicker.selectedItem.phaseId, script())
+                                    compile(jTree, script(), phasePicker.selectedItem.phaseId)
+                                    initAuxViews()
+                                },
+                                mnemonic: 'R',
+                                smallIcon: imageIcon(resource: 'icons/page_refresh.png', class: this),
+                                accelerator: KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0))
                     }
                 }
                 menu(text: 'Help', mnemonic: 'H') {
-                    menuItem { action(name: 'About', closure: this.&showAbout, mnemonic: 'A') }
+                    menuItem { action(
+                            name: 'About',
+                            closure: this.&showAbout,
+                            smallIcon: imageIcon(resource: 'icons/information.png', class: this),
+                            mnemonic: 'A')
+                    }
                 }
             }
             panel {
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleActions.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleActions.groovy
index 5c9b52b2bc..e05ced94ce 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleActions.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ConsoleActions.groovy
@@ -68,6 +68,7 @@ printAction = action(
         name: 'Print...',
         closure: controller.&print,
         mnemonic: 'P',
+        smallIcon: imageIcon(resource: 'icons/printer.png', class: this),
         accelerator: shortcut('P')
 )
 
@@ -77,7 +78,7 @@ exitAction = action(
         mnemonic: 'X'
 // whether or not application exit should have an
 // accelerator is debatable in usability circles
-// at the very least a confirm dialog should dhow up
+// at the very least a confirm dialog should show up
 //accelerator: shortcut('Q')
 )
 
@@ -162,6 +163,7 @@ selectAllAction = action(
         name: 'Select All',
         closure: controller.&selectAll,
         mnemonic: 'A',
+        smallIcon: imageIcon(resource: 'icons/page_white_select.png', class: this),
         accelerator: shortcut('A')
 )
 
@@ -209,6 +211,7 @@ runJavaAction = action(
         closure: controller.&runJava,
         mnemonic: 'J',
         accelerator: shortcut('alt R'),
+        smallIcon: imageIcon(resource: 'icons/cup_go.png', class: this),
         shortDescription: 'Execute Java Code'
 )
 
@@ -235,12 +238,14 @@ runJavaSelectionAction = action(
 addClasspathJar = action(
         name: 'Add Jar(s) to ClassPath',
         closure: controller.&addClasspathJar,
+        smallIcon: imageIcon(resource: 'icons/package_add.png', class: this),
         mnemonic: 'J',
 )
 
 addClasspathDir = action(
         name: 'Add Directory to ClassPath',
         closure: controller.&addClasspathDir,
+        smallIcon: imageIcon(resource: 'icons/folder_add.png', class: this),
         mnemonic: 'D',
 )
 
@@ -252,6 +257,7 @@ listClasspath = action(
 clearClassloader = action(
         name: 'Clear Script Context',
         closure: controller.&clearContext,
+        smallIcon: imageIcon(resource: 'icons/script_lightning.png', class: this),
         mnemonic: 'C',
 )
 
@@ -379,6 +385,7 @@ largerFontAction = action(
         name: 'Larger Font',
         closure: controller.&largerFont,
         mnemonic: 'L',
+        smallIcon: imageIcon(resource: 'icons/font_up.png', class: this),
         accelerator: shortcut('shift L')
 )
 
@@ -386,6 +393,7 @@ smallerFontAction = action(
         name: 'Smaller Font',
         closure: controller.&smallerFont,
         mnemonic: 'S',
+        smallIcon: imageIcon(resource: 'icons/font_down.png', class: this),
         accelerator: shortcut('shift S')
 )
 
@@ -396,7 +404,8 @@ smartHighlighterAction = action(
 
 aboutAction = action(
         name: 'About',
-        closure: controller.&showAbout,
+        closure: controller.&aboutAction,
+        smallIcon: imageIcon(resource: 'icons/information.png', class: this),
         mnemonic: 'A'
 )
 
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 a73f815a7e..fefae63d20 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
@@ -20,16 +20,16 @@ package groovy.console.ui
 
 import groovy.beans.Bindable
 import groovy.inspect.Inspector
-import groovy.swing.table.TableSorter
 import groovy.swing.SwingBuilder
+import groovy.swing.table.TableSorter
 
+import javax.swing.ToolTipManager
 import javax.swing.WindowConstants
 import java.awt.FlowLayout
+import java.awt.Toolkit
+import java.awt.datatransfer.StringSelection
 import java.awt.event.MouseAdapter
 import java.awt.event.MouseEvent
-import javax.swing.ToolTipManager
-
-import static javax.swing.ListSelectionModel.SINGLE_SELECTION
 
 import static groovy.inspect.Inspector.MEMBER_DECLARER_IDX
 import static groovy.inspect.Inspector.MEMBER_EXCEPTIONS_IDX
@@ -39,6 +39,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 javax.swing.ListSelectionModel.SINGLE_SELECTION
 
 /**
  * A little GUI to show some of the Inspector capabilities.
@@ -77,7 +78,7 @@ class ObjectBrowser {
         cards.add(makeCard(swing, new Inspector(objectUnderInspection), path), pathId)
         cards.layout.show(cards, pathId)
         cards.revalidate()
-        pathMenu.add(swing.menuItem { action(name: path, enabled: bind{ tracker.current != idx }, closure: this.&switchCard.curry(idx)) })
+        pathMenu.add(swing.menuItem { action(name: path, enabled: bind{ tracker.current != idx }, closure: this.&showAction.curry(idx)) })
         mb.revalidate()
     }
 
@@ -93,11 +94,15 @@ class ObjectBrowser {
             mb = menuBar {
                 pathMenu = menu(text: 'Path') {
                     int idx = pathCount++
-                    menuItem { action(name: path.toString(), enabled: bind{ tracker.current != idx }, closure: this.&switchCard.curry(idx)) }
+                    menuItem { action(name: path.toString(), enabled: bind{ tracker.current != idx }, closure: this.&showAction.curry(idx)) }
                 }
                 menu(text: 'Help') {
-                    menuItem { action(name: 'Usage', closure: this.&showUsage) }
-                    menuItem { action(name: 'About', closure: this.&showAbout) }
+                    menuItem { action(name: 'Usage', closure: this.&usageAction) }
+                    menuItem { action(
+                            name: 'About',
+                            smallIcon: imageIcon(resource: 'icons/information.png', class: this),
+                            closure: this.&aboutAction)
+                    }
                 }
             }
             cards = panel {
@@ -152,7 +157,7 @@ class ObjectBrowser {
                             getColumn(1).preferredWidth = 400
                         }
 
-                        arrayTable.addMouseListener(makeClickAdapter(arrayTable, 2) { row ->
+                        arrayTable.addMouseListener(mouseListener(2) { row ->
                             path + "[${arrayTable.model.getValueAt(row, 0)}]"
                         })
                     }
@@ -175,7 +180,7 @@ class ObjectBrowser {
                             getColumn(0).preferredWidth = 50
                             getColumn(1).preferredWidth = 400
                         }
-                        collectionTable.addMouseListener(makeClickAdapter(collectionTable, 2) { row ->
+                        collectionTable.addMouseListener(mouseListener(2) { row ->
                             path + "[${collectionTable.model.getValueAt(row, 0)}]"
                         })
                     }
@@ -201,7 +206,7 @@ class ObjectBrowser {
                             getColumn(1).preferredWidth = 200
                             getColumn(2).preferredWidth = 400
                         }
-                        mapTable.addMouseListener(makeClickAdapter(mapTable, 2) { row ->
+                        mapTable.addMouseListener(mouseListener(2) { row ->
                             path + "[${mapTable.model.getValueAt(row, 1)}]"
                         })
                     }
@@ -224,7 +229,7 @@ class ObjectBrowser {
                         maxWidth = 0
                         width = 0
                     }
-                    fieldTable.addMouseListener(makeClickAdapter(fieldTable, 6) { row ->
+                    fieldTable.addMouseListener(mouseListener(6) { row ->
                         path + (path.size() == 0 ? '' : '.') + "${fieldTable.model.getValueAt(row, 0)}"
                     })
                 }
@@ -248,7 +253,7 @@ class ObjectBrowser {
                         maxWidth = 0
                         width = 0
                     }
-                    methodTable.addMouseListener(makeClickAdapter(methodTable, 7) { row ->
+                    methodTable.addMouseListener(mouseListener(7) { row ->
                         path + (path.size() == 0 ? '' : ".method['") + "${methodTable.model.getValueAt(row, 0)}']"
                     })
                 }
@@ -263,25 +268,67 @@ class ObjectBrowser {
         }
     }
 
-    def makeClickAdapter(table, int valueCol, Closure pathClosure) {
+    def mouseListener(int valueCol, Closure pathClosure) {
+        def outer = this
         new MouseAdapter() {
             void mouseClicked(MouseEvent e) {
                 if (e.clickCount == 2) {
-                    def selectedRow = table.selectedRow
-                    if (selectedRow != -1) {
-                        def value = table.model.getValueAt(selectedRow, valueCol)
-                        if (value != null) {
-                            if (e.shiftDown)
-                                ObjectBrowser.inspect(value, pathClosure(selectedRow))
-                            else
-                                inspectAlso(value, pathClosure(selectedRow))
-                        }
+                    launch(e.source, valueCol, e.shiftDown, pathClosure)
+                }
+            }
+
+            void mouseReleased(MouseEvent e) {
+                def table = e.source
+                int r = table.rowAtPoint(e.point)
+                if (r >= 0 && r < table.rowCount) {
+                    table.setRowSelectionInterval(r, r)
+                } else {
+                    table.clearSelection()
+                }
+
+                if (table.selectedRow < 0) return
+                if (e.isPopupTrigger()) {
+                    def popup = swing.popupMenu {
+                        menuItem(action(
+                                name: 'Copy',
+                                closure: outer.&copyAction.curry(table, e),
+                                mnemonic: 'C',
+                                accelerator: shortcut('C'),
+                                smallIcon: imageIcon(resource: 'icons/page_copy.png', class: this),
+                                shortDescription: 'Copy'
+                        ))
+                        menuItem(action(
+                                name: 'Browse',
+                                closure: outer.&launchAction.curry(table, valueCol, false, pathClosure),
+                                smallIcon: imageIcon(resource: 'icons/page_white_stack.png', class: this),
+                                shortDescription: 'Browse'
+                        ))
+                        menuItem(action(
+                                name: 'Browse in new window',
+                                closure: outer.&launchAction.curry(table, valueCol, true, pathClosure),
+                                smallIcon: imageIcon(resource: 'icons/page_white_go.png', class: this),
+                                shortDescription: 'Browse window'
+                        ))
                     }
+                    popup.show(e.component, e.x, e.y)
                 }
             }
         }
     }
 
+    void launch(table, valueCol, boolean newWindow, pathClosure) {
+        def selectedRow = table.selectedRow
+        if (selectedRow != -1) {
+            def value = table.model.getValueAt(selectedRow, valueCol)
+            if (value != null) {
+                if (newWindow)
+                    ObjectBrowser.inspect(value, pathClosure(selectedRow))
+                else
+                    inspectAlso(value, pathClosure(selectedRow))
+            }
+        }
+    }
+
     void addSorter(table) {
         if (table != null) {
             def sorter = new TableSorter(table.model)
@@ -290,13 +337,13 @@ class ObjectBrowser {
         }
     }
 
-    void switchCard(int idx, EventObject evt) {
+    void showAction(int idx, EventObject evt) {
         tracker.current = idx
         cards.layout.show(cards, 'path' + idx)
         cards.revalidate()
     }
 
-    void showUsage(EventObject evt) {
+    void usageAction(EventObject evt) {
         def pane = swing.optionPane()
         // work around GROOVY-1048
         pane.setMessage(
@@ -309,7 +356,18 @@ class ObjectBrowser {
         dialog.show()
     }
 
-    void showAbout(EventObject evt) {
+    void launchAction(table, valueCol, boolean newWindow, pathClosure, EventObject evt) {
+        launch(table, valueCol, newWindow, pathClosure)
+    }
+
+    void copyAction(table, MouseEvent me, EventObject evt) {
+        def toolTipText = table.getToolTipText(me)
+        if (toolTipText) {
+            Toolkit.defaultToolkit.systemClipboard.setContents(new StringSelection(toolTipText), null)
+        }
+    }
+
+    void aboutAction(EventObject evt) {
         def pane = swing.optionPane()
         // work around GROOVY-1048
         def version = GroovySystem.version