Skip to content

Commit

Permalink
Added support for inspect dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
hajdam committed Jul 22, 2019
1 parent 47304c5 commit 5741192
Show file tree
Hide file tree
Showing 21 changed files with 1,737 additions and 14 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ GUI Popup & Inspect - IntelliJ Plugin

Registers popup menu and inspect function for all regular components in IDE.

- Use right click or Shift-F10 to show typical popup menu on various input boxes.
- Use Alt + Shift + Ctrl/Mac + F12 to show component inspect dialog

Homepage: https://github.com/hajdam/guipopup-intellij-plugin

Published as: TODO
Published as: https://plugins.jetbrains.com/plugin/12762-gui-popup--inspect

Screenshot
----------
Expand All @@ -15,8 +18,9 @@ Screenshot
Features
--------

- Show popup menu with cut/copy/paste/delete and select all action
- Show popup menu with clipboard cut/copy/paste actions delete, select all and some utilities actions
- Supported components JTextComponent, JList, JTable
- Shows inspect dialog with values readable by reflections for component currently pointed on with mouse

Compiling
---------
Expand Down
Binary file modified images/screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
componentLabel.text=Component
closeButton.text=Close
InspectComponentPanel.showStaticFieldsCheckBox.text=Show static fields
77 changes: 77 additions & 0 deletions src/org/exbin/utils/guipopup/DialogUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright (C) ExBin Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.exbin.utils.guipopup;

import com.intellij.openapi.ui.DialogWrapper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;

/**
* Dialog utilities.
*
* @author ExBin Project (http://exbin.org)
* @version 0.2.0 2018/11/10
*/
public class DialogUtils {

public static final String DIALOG_MENUITEM_EXT = "...";

public static DialogWrapper createDialog(JComponent dialogPanel, String dialogTitle) {
return new BinEdDialogWrapper(dialogPanel, dialogTitle);
}

public static DialogWrapper createDialog(JComponent dialogPanel, String dialogTitle, JComponent focusedComponent) {
return new BinEdDialogWrapper(dialogPanel, dialogTitle, focusedComponent);
}

public static class BinEdDialogWrapper extends DialogWrapper {

private final JComponent dialogPanel;
private final JComponent focusedComponent;

public BinEdDialogWrapper(JComponent dialogPanel, String dialogTitle) {
this(dialogPanel, dialogTitle, dialogPanel);
}

public BinEdDialogWrapper(JComponent dialogPanel, String dialogTitle, JComponent focusedComponent) {
super(true);
this.dialogPanel = dialogPanel;
this.focusedComponent = focusedComponent;
setTitle(dialogTitle);
init();
}

@Nullable
@Override
public JComponent getPreferredFocusedComponent() {
return focusedComponent;
}

@Nullable
@Override
protected JComponent createCenterPanel() {
return dialogPanel;
}

@NotNull
@Override
protected Action[] createActions() {
return new Action[0];
}
}
}
142 changes: 130 additions & 12 deletions src/org/exbin/utils/guipopup/GuiPopupMenu.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,28 @@
*/
package org.exbin.utils.guipopup;

import com.intellij.ide.IdeEventQueue;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.impl.IdeGlassPaneImpl;
import org.exbin.utils.guipopup.handler.ListClipboardHandler;
import org.exbin.utils.guipopup.handler.TableClipboardHandler;
import org.exbin.utils.guipopup.handler.TextComponentClipboardHandler;
import org.exbin.utils.guipopup.panel.InspectComponentPanel;

import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.JTextComponent;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.lang.reflect.Field;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Utilities for default menu generation.
Expand All @@ -50,6 +59,11 @@ public class GuiPopupMenu {
private DefaultPopupClipboardAction[] defaultTextActions;

private static GuiPopupMenu instance = null;
private boolean registered = false;
private boolean inspectMode = false;
// private EventQueue systemEventQueue;
private IdeEventQueue.EventDispatcher overriddenQueue;
private IdeEventQueue.EventDispatcher overriddenPostQueue;

private GuiPopupMenu() {
}
Expand All @@ -66,9 +80,11 @@ public static synchronized GuiPopupMenu getInstance() {
* Registers default popup menu to AWT.
*/
public static void register() {
GuiPopupMenu guiPopupMenu = getInstance();
guiPopupMenu.initDefaultPopupMenu();
guiPopupMenu.registerToEventQueue();
GuiPopupMenu defaultPopupMenu = getInstance();
if (!defaultPopupMenu.registered) {
defaultPopupMenu.initDefaultPopupMenu();
defaultPopupMenu.registerToEventQueue();
}
}

/**
Expand All @@ -84,7 +100,29 @@ public static void register(ResourceBundle resourceBundle, Class resourceClass)
}

private void registerToEventQueue() {
Toolkit.getDefaultToolkit().getSystemEventQueue().push(new PopupEventQueue());
overriddenQueue = new PopupEventQueue();
overriddenPostQueue = new PopupEventPostQueue();
// systemEventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
// systemEventQueue.push(overriddenQueue);
IdeEventQueue instance = IdeEventQueue.getInstance();
instance.addDispatcher(overriddenQueue, null);
instance.addPostprocessor(overriddenPostQueue, null);
registered = true;
}

public static void unregister() {
GuiPopupMenu defaultPopupMenu = getInstance();
if (defaultPopupMenu.registered) {
defaultPopupMenu.unregisterQueue();
}
}

private void unregisterQueue() {
IdeEventQueue instance = IdeEventQueue.getInstance();
instance.removeDispatcher(overriddenQueue);
instance.removePostprocessor(overriddenPostQueue);
// overriddenQueue.push(systemEventQueue);
registered = false;
}

private void initDefaultPopupMenu() {
Expand Down Expand Up @@ -248,19 +286,45 @@ public void fillDefaultEditPopupMenu(JPopupMenu popupMenu, int position) {
}
}

public class PopupEventQueue extends EventQueue {
public class PopupEventQueue implements IdeEventQueue.EventDispatcher {

@Override
public boolean dispatch(AWTEvent event) {
if (event.getID() == MouseEvent.MOUSE_MOVED && inspectMode) {
inspectMode = false;
MouseEvent mouseEvent = (MouseEvent) event;
Component component = getSource(mouseEvent);
InspectComponentPanel inspectComponentPanel = new InspectComponentPanel();
inspectComponentPanel.setComponent(component, null);
Frame mainWindow = WindowManager.getInstance().getFrame(ProjectManager.getInstance().getDefaultProject());
final WindowUtils.DialogWrapper dialog = WindowUtils.createDialog(inspectComponentPanel, mainWindow, "Inspect Component", Dialog.ModalityType.MODELESS);
inspectComponentPanel.setCloseActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dialog.close();
}
});
dialog.show();
return true;
}

return false;
}
}

public class PopupEventPostQueue implements IdeEventQueue.EventDispatcher {

@Override
protected void dispatchEvent(AWTEvent event) {
super.dispatchEvent(event);
public boolean dispatch(AWTEvent event) {
// super.dispatchEvent(event);

if (event.getID() == MouseEvent.MOUSE_RELEASED || event.getID() == MouseEvent.MOUSE_PRESSED) {
MouseEvent mouseEvent = (MouseEvent) event;

if (mouseEvent.isPopupTrigger()) {
if (MenuSelectionManager.defaultManager().getSelectedPath().length > 0) {
// Menu was already created
return;
return false;
}

Component component = getSource(mouseEvent);
Expand All @@ -278,10 +342,20 @@ protected void dispatchEvent(AWTEvent event) {
}
} else if (event.getID() == KeyEvent.KEY_PRESSED) {
KeyEvent keyEvent = (KeyEvent) event;
if (keyEvent.getKeyCode() == KeyEvent.VK_CONTEXT_MENU || (keyEvent.getKeyCode() == KeyEvent.VK_F10 && keyEvent.isShiftDown())) {
if (keyEvent.getKeyCode() == KeyEvent.VK_F12 && keyEvent.isShiftDown() && keyEvent.isAltDown() && (keyEvent.isControlDown() || keyEvent.isMetaDown())) {
// Unable to infer component from mouse position, so simulate click instead
inspectMode = true;
try {
Robot robot = new Robot();
Point location = MouseInfo.getPointerInfo().getLocation();
robot.mouseMove(location.x, location.y);
} catch (AWTException ex) {
Logger.getLogger(GuiPopupMenu.class.getName()).log(Level.SEVERE, null, ex);
}
} else if (keyEvent.getKeyCode() == KeyEvent.VK_CONTEXT_MENU || (keyEvent.getKeyCode() == KeyEvent.VK_F10 && keyEvent.isShiftDown())) {
if (MenuSelectionManager.defaultManager().getSelectedPath().length > 0) {
// Menu was already created
return;
return false;
}

Component component = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
Expand Down Expand Up @@ -318,8 +392,23 @@ protected void dispatchEvent(AWTEvent event) {
}
}
}

return false;
}

// private Component findComponentByMousePosition() {
// SwingUtilities.getDeepestComponentAt(mainWindow, mouseLocation.x, mouseLocation.y);
// Point mouseLocation = MouseInfo.getPointerInfo().getLocation();
//// Frame mainWindow = WindowManager.getDefault().getMainWindow();
// Frame mainWindow = WindowManager.getDefault().getMainWindow();
// Component.findUnderMouseInWindow
// List<Window> windows = Window.getWindows();
// for (Window window : windows) {
// Window owner = window.getOwner();
// SwingUtilities.getDeepestComponentAt(window., mouseLocation.x, mouseLocation.y);
// }
//
// }
private void activateMousePopup(MouseEvent mouseEvent, Component component, ClipboardActionsHandler clipboardHandler) {
for (Object action : defaultTextActions) {
((DefaultPopupClipboardAction) action).setClipboardHandler(clipboardHandler);
Expand Down Expand Up @@ -357,9 +446,38 @@ private void showPopupMenu(Component component, Point point, boolean editable) {
}
}

private Component getSource(MouseEvent e) {
return SwingUtilities.getDeepestComponentAt(e.getComponent(), e.getX(), e.getY());
}

private static Component getSource(MouseEvent e) {
return getDeepestComponent(e.getComponent(), e.getX(), e.getY());
}

private static Component getDeepestComponent(Component parentComponent, int x, int y) {
Component component = SwingUtilities.getDeepestComponentAt(parentComponent, x, y);

// Workaround for buggy panel
if (component instanceof IdeGlassPaneImpl) {
try {
Field myRootPane = component.getClass().getDeclaredField("myRootPane");
myRootPane.setAccessible(true);
JRootPane rootPane = (JRootPane) myRootPane.get(component);
final Point lpPoint = SwingUtilities.convertPoint(parentComponent, new Point(x, y), component);
return getDeepestComponent(rootPane.getContentPane(), lpPoint.x, lpPoint.y);
} catch (NoSuchFieldException | IllegalAccessException e1) {
// Cannot serve
}
// final Point lpPoint = SwingUtilities.convertPoint(parentComponent, e.getPoint(), component);

// int componentCount = ((IdeGlassPaneEx) component).getComponentCount();
// for (int i = 0; i < componentCount; i++) {
// Component subComponent = ((IdeGlassPaneEx) component).getComponent(i);
// if (subComponent.contains(e.getX(), e.getY())) {
// return getDeepestComponent(subComponent, e);
// }
// }
// component = SwingUtilities.getDeepestComponentAt(component, lpPoint.x, lpPoint.y);
}
return component;
}

/**
Expand Down
Loading

0 comments on commit 5741192

Please sign in to comment.