/* * JaamSim Discrete Event Simulation * Copyright (C) 2016 JaamSim Software Inc. * * 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 com.jaamsim.ui; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import javax.swing.JCheckBoxMenuItem; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.JRadioButtonMenuItem; import com.jaamsim.Graphics.DisplayEntity; import com.jaamsim.Graphics.EntityLabel; import com.jaamsim.basicsim.Entity; import com.jaamsim.basicsim.Simulation; import com.jaamsim.controllers.RenderManager; import com.jaamsim.input.InputAgent; import com.jaamsim.input.KeywordIndex; import com.jaamsim.math.Vec3d; public class ContextMenu { private static final ArrayList<ContextMenuItem> menuItems = new ArrayList<>(); private ContextMenu() {} public static final void addCustomMenuHandler(ContextMenuItem i) { synchronized (menuItems) { menuItems.add(i); } } private static class UIMenuItem extends JMenuItem implements ActionListener { final ContextMenuItem i; final Entity ent; final int x; final int y; UIMenuItem(ContextMenuItem i, Entity ent, int x, int y) { super(i.getMenuText()); this.i = i; this.ent = ent; this.x = x; this.y = y; this.addActionListener(this); } @Override public void actionPerformed(ActionEvent event) { i.performAction(ent, x, y); } } /** * Adds menu items to the right click (context) menu for the specified entity. * @param ent - entity whose context menu is to be generated * @param menu - context menu to be populated with menu items * @param x - screen coordinate for the menu * @param y - screen coordinate for the menu */ public static void populateMenu(JPopupMenu menu, final Entity ent, final int x, final int y) { // 1) Input Editor JMenuItem inputEditorMenuItem = new JMenuItem( "Input Editor" ); inputEditorMenuItem.addActionListener( new ActionListener() { @Override public void actionPerformed( ActionEvent event ) { InputAgent.applyArgs(Simulation.getInstance(), "ShowInputEditor", "TRUE"); FrameBox.setSelectedEntity(ent, false); } } ); menu.add( inputEditorMenuItem ); // 2) Output Viewer JMenuItem outputViewerMenuItem = new JMenuItem( "Output Viewer" ); outputViewerMenuItem.addActionListener( new ActionListener() { @Override public void actionPerformed( ActionEvent event ) { InputAgent.applyArgs(Simulation.getInstance(), "ShowOutputViewer", "TRUE"); FrameBox.setSelectedEntity(ent, false); } } ); menu.add( outputViewerMenuItem ); // 3) Property Viewer JMenuItem propertyViewerMenuItem = new JMenuItem( "Property Viewer" ); propertyViewerMenuItem.addActionListener( new ActionListener() { @Override public void actionPerformed( ActionEvent event ) { InputAgent.applyArgs(Simulation.getInstance(), "ShowPropertyViewer", "TRUE"); FrameBox.setSelectedEntity(ent, false); } } ); menu.add( propertyViewerMenuItem ); // 4) Duplicate JMenuItem duplicateMenuItem = new JMenuItem( "Duplicate" ); duplicateMenuItem.addActionListener( new ActionListener() { @Override public void actionPerformed( ActionEvent event ) { Entity copiedEntity = InputAgent.defineEntityWithUniqueName(ent.getClass(), ent.getName(), "_Copy", true); // Match all the inputs copiedEntity.copyInputs(ent); // Position the duplicated entity next to the original if (copiedEntity instanceof DisplayEntity) { DisplayEntity dEnt = (DisplayEntity)copiedEntity; Vec3d pos = dEnt.getPosition(); pos.x += 0.5d * dEnt.getSize().x; pos.y -= 0.5d * dEnt.getSize().y; dEnt.setPosition(pos); // Set the input for the "Position" keyword to the new value KeywordIndex kw = InputAgent.formatPointInputs("Position", pos, "m"); InputAgent.apply(dEnt, kw); } // Show the duplicated entity in the editors and viewers FrameBox.setSelectedEntity(copiedEntity, false); } } ); if (ent.testFlag(Entity.FLAG_GENERATED)) { duplicateMenuItem.setEnabled(false); } menu.add( duplicateMenuItem ); // 5) Delete JMenuItem deleteMenuItem = new JMenuItem( "Delete" ); deleteMenuItem.addActionListener( new ActionListener() { @Override public void actionPerformed( ActionEvent event ) { ent.kill(); FrameBox.setSelectedEntity(null, false); } } ); menu.add( deleteMenuItem ); // DisplayEntity menu items if (ent instanceof DisplayEntity) { ContextMenu.populateDisplayEntityMenu(menu, (DisplayEntity)ent, x, y); } synchronized (menuItems) { for (ContextMenuItem each : menuItems) { if (each.supportsEntity(ent)) menu.add(new UIMenuItem(each, ent, x, y)); } } } public static void populateDisplayEntityMenu(JPopupMenu menu, final DisplayEntity ent, final int x, final int y) { if (!RenderManager.isGood()) return; // 1) Change Graphics JMenuItem changeGraphicsMenuItem = new JMenuItem( "Change Graphics" ); changeGraphicsMenuItem.addActionListener( new ActionListener() { @Override public void actionPerformed( ActionEvent event ) { GraphicBox graphicBox = GraphicBox.getInstance(ent, x, y); graphicBox.setVisible( true ); } } ); if (ent.getDisplayModelList() == null) { changeGraphicsMenuItem.setEnabled(false); } menu.add( changeGraphicsMenuItem ); // 2) Show Label final EntityLabel label = EntityLabel.getLabel(ent); boolean bool = label != null && label.getShow(); final JMenuItem showLabelMenuItem = new JCheckBoxMenuItem( "Show Label", bool ); showLabelMenuItem.addActionListener( new ActionListener() { @Override public void actionPerformed( ActionEvent event ) { if (showLabelMenuItem.isSelected()) { // If required, create the EntityLabel object if (label == null) { EntityLabel newLabel = InputAgent.defineEntityWithUniqueName(EntityLabel.class, ent.getName() + "_Label", "", true); InputAgent.applyArgs(newLabel, "TargetEntity", ent.getName()); InputAgent.applyArgs(newLabel, "RelativeEntity", ent.getName()); if (ent.getCurrentRegion() != null) InputAgent.applyArgs(newLabel, "Region", ent.getCurrentRegion().getName()); double ypos = -0.15 - 0.5*ent.getSize().y; InputAgent.apply(newLabel, InputAgent.formatPointInputs("Position", new Vec3d(0.0, ypos, 0.0), "m")); InputAgent.applyArgs(newLabel, "TextHeight", "0.15", "m"); newLabel.resizeForText(); return; } // Show the label InputAgent.applyArgs(label, "Show", "TRUE"); } else { // Hide the label if it already exists if (label != null) InputAgent.applyArgs(label, "Show", "FALSE"); } } } ); if (ent instanceof EntityLabel || ent.testFlag(Entity.FLAG_GENERATED)) { showLabelMenuItem.setEnabled(false); } menu.add( showLabelMenuItem ); // 3) Set RelativeEntity JMenu setRelativeEntityMenu = new JMenu( "Set RelativeEntity" ); ArrayList<String> entNameList = new ArrayList<>(); entNameList.add("<None>"); entNameList.addAll(ent.getRelativeEntityOptions()); String presentEntName = "<None>"; if (ent.getRelativeEntity() != null) { presentEntName = ent.getRelativeEntity().getName(); } for (final String entName : entNameList) { JRadioButtonMenuItem item = new JRadioButtonMenuItem(entName); if (entName.equals(presentEntName)) { item.setSelected(true); } item.addActionListener( new ActionListener() { @Override public void actionPerformed( ActionEvent event ) { Vec3d pos = ent.getGlobalPosition(); if (entName.equals("<None>")) { InputAgent.applyArgs(ent, "RelativeEntity"); } else { InputAgent.applyArgs(ent, "RelativeEntity", entName); } ent.setInputForGlobalPosition(pos); } } ); setRelativeEntityMenu.add(item); } if (ent instanceof EntityLabel || ent.testFlag(Entity.FLAG_GENERATED)) { setRelativeEntityMenu.setEnabled(false); } menu.add( setRelativeEntityMenu ); // 4) Set Region JMenu setRegionMenu = new JMenu( "Set Region" ); ArrayList<String> regionNameList = new ArrayList<>(); regionNameList.add("<None>"); regionNameList.addAll(ent.getRegionOptions()); String presentRegionName = "<None>"; if (ent.getCurrentRegion() != null) { presentRegionName = ent.getCurrentRegion().getName(); } for (final String regionName : regionNameList) { JRadioButtonMenuItem item = new JRadioButtonMenuItem(regionName); if (regionName.equals(presentRegionName)) { item.setSelected(true); } item.addActionListener( new ActionListener() { @Override public void actionPerformed( ActionEvent event ) { Vec3d pos = ent.getGlobalPosition(); if (regionName.equals("<None>")) { InputAgent.applyArgs(ent, "Region"); } else { InputAgent.applyArgs(ent, "Region", regionName); } ent.setInputForGlobalPosition(pos); } } ); setRegionMenu.add(item); } if (ent instanceof EntityLabel || ent.testFlag(Entity.FLAG_GENERATED)) { setRegionMenu.setEnabled(false); } menu.add( setRegionMenu ); // 5) Centre in View JMenuItem centerInViewMenuItem = new JMenuItem( "Center in View" ); final View v = RenderManager.inst().getActiveView(); centerInViewMenuItem.addActionListener( new ActionListener() { @Override public void actionPerformed( ActionEvent event ) { // Move the camera position so that the entity is in the centre of the screen Vec3d viewPos = new Vec3d(v.getGlobalPosition()); viewPos.sub3(v.getGlobalCenter()); viewPos.add3(ent.getPosition()); v.setCenter(ent.getPosition()); v.setPosition(viewPos); } } ); if (v == null) { centerInViewMenuItem.setEnabled(false); } menu.add( centerInViewMenuItem ); } }