001/* An abstract menu factory that creates context menus using item factories 002 003 Copyright (c) 2003-2016 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.vergil.tree; 029 030import java.awt.event.MouseAdapter; 031import java.awt.event.MouseEvent; 032import java.util.Collections; 033import java.util.Iterator; 034import java.util.LinkedList; 035import java.util.List; 036 037import javax.swing.tree.TreePath; 038 039import diva.gui.toolbox.JContextMenu; 040import ptolemy.kernel.util.NamedObj; 041import ptolemy.vergil.toolbox.MenuItemFactory; 042 043/////////////////////////////////////////////////////////////////// 044//// PTreeMenuCreator 045 046/** 047 A mouse listener that creates context menus for a PTree using menu 048 item factories. When asked to create a context menu, This class 049 determines the ptolemy object associated with the point in the tree 050 that was clicked on. Then it passes the ptolemy object to each menu 051 item factory that it contains to add the menu items. Lastly, it pops 052 up the resulting menu. 053 054 @author Steve Neuendorffer 055 @version $Id$ 056 @since Ptolemy II 4.0 057 @Pt.ProposedRating Red (eal) 058 @Pt.AcceptedRating Red (johnr) 059 */ 060public class PTreeMenuCreator extends MouseAdapter { 061 /** Create a new menu factory that contains no menu item factories. 062 */ 063 public PTreeMenuCreator() { 064 _factoryList = new LinkedList(); 065 } 066 067 /////////////////////////////////////////////////////////////////// 068 //// public methods //// 069 070 /** Add a menu item factory to this creator. 071 * @param factory The menu item factory to add. 072 */ 073 public void addMenuItemFactory(MenuItemFactory factory) { 074 _factoryList.add(factory); 075 } 076 077 /** Create an instance of the menu associated with this factory. 078 * @param e The mouse event. If the mouse event is 079 * a popup event, then menu is created and shown. 080 */ 081 @Override 082 public void mousePressed(MouseEvent e) { 083 _doEvent(e); 084 } 085 086 /** Create an instance of the menu associated with this factory. 087 * @param e The mouse event. If the mouse event is 088 * a popup event, then menu is created and shown. 089 */ 090 @Override 091 public void mouseReleased(MouseEvent e) { 092 _doEvent(e); 093 } 094 095 /** Return the list of menu item factories. 096 * @return An unmodifiable list. 097 */ 098 public List menuItemFactoryList() { 099 return Collections.unmodifiableList(_factoryList); 100 } 101 102 /** Remove the given menu item factory from the factory list. 103 * @param factory The factory to be removed. 104 */ 105 public void removeMenuItemFactory(MenuItemFactory factory) { 106 _factoryList.remove(factory); 107 } 108 109 /** Remove all MenuItemFactories from the factory list. 110 */ 111 public void clear() { 112 _factoryList.clear(); 113 } 114 115 /////////////////////////////////////////////////////////////////// 116 //// private methods //// 117 118 /** Process a mousePressed or mouseReleased event. 119 */ 120 private void _doEvent(MouseEvent e) { 121 if (!e.isPopupTrigger()) { 122 return; 123 } 124 125 PTree tree = (PTree) e.getComponent(); 126 TreePath treePath = tree.getPathForLocation(e.getX(), e.getY()); 127 if (treePath == null) { 128 // On the Mac under Java 1.5.0_22, treePath can be null. 129 // 1) Start vergil 130 // 2) Open Actors -> Sources -> GenericSources 131 // 3) Drag a Const into the canvas 132 // 4) Place the mouse over the Const actor and quickly 133 // use two finger to signal a right click. 134 135 // An exception appears: 136 // Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 137 // at ptolemy.vergil.tree.PTreeMenuCreator._doEvent(PTreeMenuCreator.java:119) 138 // at ptolemy.vergil.tree.PTreeMenuCreator.mousePressed(PTreeMenuCreator.java:82) 139 // at java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:222) 140 // at java.awt.Component.processMouseEvent(Component.java:5599) 141 // at javax.swing.JComponent.processMouseEvent(JComponent.java:3129) 142 // at java.awt.Component.processEvent(Component.java:5367) 143 // at java.awt.Container.processEvent(Container.java:2010) 144 // at java.awt.Component.dispatchEventImpl(Component.java:4068) 145 // at java.awt.Container.dispatchEventImpl(Container.java:2068) 146 // at java.awt.Component.dispatchEvent(Component.java:3903) 147 // at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4256) 148 // at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3933) 149 // at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3866) 150 // at java.awt.Container.dispatchEventImpl(Container.java:2054) 151 // at java.awt.Window.dispatchEventImpl(Window.java:1801) 152 // at java.awt.Component.dispatchEvent(Component.java:3903) 153 // at java.awt.EventQueue.dispatchEvent(EventQueue.java:463) 154 // at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:269) 155 // at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190) 156 // at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:184) 157 // at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:176) 158 // at java.awt.EventDispatchThread.run(EventDispatchThread.java:110) 159 160 // I think the problem here is that the actor pane has the focus when 161 // the mouse click occurs. 162 return; 163 } 164 Object object = treePath.getLastPathComponent(); 165 166 if (object instanceof NamedObj) { 167 NamedObj namedObj = (NamedObj) object; 168 JContextMenu menu = new JContextMenu(namedObj, 169 namedObj.getFullName()); 170 Iterator i = menuItemFactoryList().iterator(); 171 172 while (i.hasNext()) { 173 MenuItemFactory factory = (MenuItemFactory) i.next(); 174 factory.create(menu, namedObj); 175 } 176 177 menu.show(tree, e.getX(), e.getY()); 178 e.consume(); 179 } 180 } 181 182 /////////////////////////////////////////////////////////////////// 183 //// private members //// 184 185 /** The menu item factories. 186 */ 187 private List _factoryList; 188}