This package contains the implementation of classes used to describe the nifty GUI components displayed in the 3D visualizer.
1. Implementing the “VehicleModificationDialogDefinition” class
The “VehicleModificationDialogDefinition” class defines and registers a new control (i.e., GUI window) with Nifty that is used to present and modify vehicle agent propoerties. This gives us later an appropriate ControlBuilder to actual construct the Dialog (as a control) with the given name. To implement this class:
- Inside the package “edu.utdallas.mavs.traffic.visualization.vis3D.dialog.vehicleModification”, create a class named “VehicleModificationDialogDefinition”.
- This class defines a Nifty GUI component used to modify a vehicle agent’s properties. The class implementation defines the list of fields displayed in this GUI.
The following code provides a full implementation of this class:
package edu.utdallas.mavs.traffic.visualization.vis3D.dialog.vehicleModification; import de.lessvoid.nifty.Nifty; import de.lessvoid.nifty.builder.ControlDefinitionBuilder; import de.lessvoid.nifty.builder.PanelBuilder; import de.lessvoid.nifty.controls.DefaultController; import de.lessvoid.nifty.controls.checkbox.builder.CheckboxBuilder; import de.lessvoid.nifty.controls.label.builder.LabelBuilder; import de.lessvoid.nifty.tools.Color; import edu.utdallas.mavs.divas.visualization.vis3D.dialog.utils.CommonBuilders; /** * The {@link VehicleModificationDialogDefinition} registers a new control with Nifty that * represents the whole {@link VehicleModificationDialogDefinition}. This gives us later an * appropriate ControlBuilder to actual construct the Dialog (as a control) with * the given NAME. */ public class VehicleModificationDialogDefinition { /** * The name of the control {@link AgentPropertyDialogDefinition}. */ public static final String NAME = VehicleModificationDialogDefinition.class.getName(); /** * The id for the label containing the heading of the agent. */ public static final String HEADING_LABEL = "#heading"; /** * The id for the label containing the acceleration of the agent. */ public static final String ACCELERATION_LABEL = "#acceleration"; /** * The id for the label containing the velocity of the agent. */ public static final String VELOCITY_LABEL = "#velocity"; /** * The id for the label containing the position of the agent. */ public static final String POSITION_LABEL = "#position"; /** * The id for the label containing the scale of the agent. */ public static final String SCALE_LABEL = "#scale"; /** * The id for the label containing planning details of the agent. */ public static final String PLANNING_DETAILS_LABEL = "#planningDetails"; /** * The id of the panel for the agent control (i.e. autonomous, keyboard) of the agent. */ public static final String AGENT_CONTROL_PANEL = "#agentControlPanel"; /** * The id for the checkbox containing whether the agent camera is enabled or not. */ public static final String AGENT_CAM_CHECKBOX = "#agentCamEnabled"; /** * The id for the textfield containing the maximum speed of the agent. */ public static final String MAX_SPEED_TEXTFIELD = "#maxSpeed"; /** * The id for the panel containing the maximum speed of the agent. */ public static final String MAX_SPEED_PANEL = "#maxSpeedPanel"; /** * The id for the textfield containing the desired speed of the agent. */ public static final String DESIRED_SPEED_TEXTFIELD = "#desiredSpeed"; /** * The id for the panel containing the desired speed of the agent. */ public static final String DESIRED_SPEED_PANEL = "#desiredSpeedPanel"; private static CommonBuilders builders = new CommonBuilders(); /** * This registers the dialog as a new ControlDefintion with Nifty so that we can * later create the dialog dynamically. * * @param nifty * The Nifty instance */ public static void register(final Nifty nifty) { new ControlDefinitionBuilder(NAME) { { controller(new DefaultController()); panel(new PanelBuilder() { { padding("5px,20px,0px,19px"); // top, right, bottom, left backgroundColor(new Color(0.0f, 0.0f, 0.0f, 0.4f)); // width("100%"); childLayoutVertical(); panel(new PanelBuilder() { { childLayoutVertical(); panel(new PanelBuilder() { { childLayoutHorizontal(); control(builders.createLabel("Position: ", "80px")); panel(builders.hspacer("0px")); control(new LabelBuilder(POSITION_LABEL) { { width("*"); alignLeft(); textVAlignCenter(); textHAlignLeft(); } }); } }); panel(builders.vspacer()); panel(new PanelBuilder() { { childLayoutHorizontal(); control(builders.createLabel("Velocity: ", "80px")); panel(builders.hspacer("0px")); control(new LabelBuilder(VELOCITY_LABEL) { { width("*"); alignLeft(); textVAlignCenter(); textHAlignLeft(); } }); } }); panel(builders.vspacer()); panel(new PanelBuilder() { { childLayoutHorizontal(); control(builders.createLabel("Acceleration: ", "80px")); panel(builders.hspacer("0px")); control(new LabelBuilder(ACCELERATION_LABEL) { { width("*"); alignLeft(); textVAlignCenter(); textHAlignLeft(); } }); } }); panel(builders.vspacer()); panel(new PanelBuilder() { { childLayoutHorizontal(); control(builders.createLabel("Heading: ", "80px")); panel(builders.hspacer("0px")); control(new LabelBuilder(HEADING_LABEL) { { width("*"); alignLeft(); textVAlignCenter(); textHAlignLeft(); } }); } }); panel(builders.vspacer()); panel(new PanelBuilder() { { childLayoutHorizontal(); control(builders.createLabel("Scale: ", "80px")); panel(builders.hspacer("0px")); control(new LabelBuilder(SCALE_LABEL) { { width("*"); alignLeft(); textVAlignCenter(); textHAlignLeft(); } }); } }); panel(builders.vspacer()); panel(new PanelBuilder(DESIRED_SPEED_PANEL) { { childLayoutHorizontal(); } }); panel(builders.vspacer()); panel(new PanelBuilder(MAX_SPEED_PANEL) { { childLayoutHorizontal(); } }); } }); panel(builders.vspacer("5px")); panel(new PanelBuilder() { { childLayoutVertical(); panel(builders.vspacer()); panel(new PanelBuilder(AGENT_CONTROL_PANEL) { { childLayoutHorizontal(); } }); } }); panel(builders.vspacer("5px")); panel(new PanelBuilder() { { childLayoutVertical(); panel(builders.vspacer()); panel(new PanelBuilder() { { childLayoutHorizontal(); control(builders.createLabel("Agent Camera")); panel(builders.hspacer("10px")); control(new CheckboxBuilder(AGENT_CAM_CHECKBOX) { { } }); } }); panel(builders.vspacer()); } }); panel(builders.vspacer("5px")); panel(new PanelBuilder() { { childLayoutHorizontal(); control(builders.createLabel("Planning information: ", "120px")); panel(builders.hspacer("0px")); control(new LabelBuilder(PLANNING_DETAILS_LABEL) { { width("*"); alignLeft(); textVAlignCenter(); textHAlignLeft(); } }); } }); } }); } }.registerControlDefintion(nifty); } }
2. Implementing the “VehicleModificationDialogController” class
The “VehicleModificationDialogController” class handles the events generated by the vehicle agent’s modification dialogue. To implement this class:
- Inside the package “edu.utdallas.mavs.traffic.visualization.vis3D.dialog.vehicleModification”, create a class named “VehicleModificationDialogController” that extends the class “AbstractPropertyDialogController” defined in the package “edu.utdallas.mavs.evacuation.visualization.vis3D.dialog.vehicleModification”.
- This class handles events generated by interacting with the Nifty GUI vehicle modification dialogue elements.
The following code provides a full implementation of this class:
package edu.utdallas.mavs.traffic.visualization.vis3D.dialog.vehicleModification; import org.bushe.swing.event.EventTopicSubscriber; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import de.lessvoid.nifty.controls.CheckBox; import de.lessvoid.nifty.controls.CheckBoxStateChangedEvent; import de.lessvoid.nifty.controls.DropDown; import de.lessvoid.nifty.controls.DropDownSelectionChangedEvent; import de.lessvoid.nifty.elements.Element; import de.lessvoid.nifty.elements.render.TextRenderer; import edu.utdallas.mavs.divas.core.msg.RuntimeAgentCommandMsg.RuntimeAgentCommand; import edu.utdallas.mavs.divas.core.sim.common.state.AgentControlType; import edu.utdallas.mavs.divas.visualization.vis3D.dialog.customControls.voModification.AbstractPropertyDialogController; import edu.utdallas.mavs.traffic.simulation.sim.common.state.VehicleAgentState; import edu.utdallas.mavs.traffic.visualization.vis3D.vo.VehicleAgentVO; /** * The VehicleModificationDialogController contains all the events that the VehicleModificationDialogDefinition element generates. */ public class VehicleModificationDialogController extends AbstractPropertyDialogController<VehicleAgentVO> { @SuppressWarnings("unused") private final static Logger logger = LoggerFactory.getLogger(VehicleModificationDialogController.class); private VehicleAgentState agent; // Agent Properties private Element position; private Element velocity; private Element acceleration; private Element heading; private Element scale; private CheckBox cameraEnabled; private DropDown<AgentControlType> agentControlType; /** * Constructs a new agent properties dialog controller */ public VehicleModificationDialogController() {} @Override public void init() { if(entityVO != null) { agent = (VehicleAgentState) entityVO.getState(); super.init(); } } @Override public void bindNiftyElements() { // Agent Properties setupLabels(); setupCheckBoxes(); setupDropDowns(); setupSpinners(); } private void setupLabels() { position = getElement(VehicleModificationDialogDefinition.POSITION_LABEL); velocity = getElement(VehicleModificationDialogDefinition.VELOCITY_LABEL); acceleration = getElement(VehicleModificationDialogDefinition.ACCELERATION_LABEL); heading = getElement(VehicleModificationDialogDefinition.HEADING_LABEL); scale = getElement(VehicleModificationDialogDefinition.SCALE_LABEL); getElement(VehicleModificationDialogDefinition.PLANNING_DETAILS_LABEL); } private void setupCheckBoxes() { cameraEnabled = getNiftyControl(VehicleModificationDialogDefinition.AGENT_CAM_CHECKBOX, CheckBox.class); } @SuppressWarnings("unchecked") private void setupDropDowns() { agentControlType = (DropDown<AgentControlType>) createDropDownControl("agentControlType", VehicleModificationDialogDefinition.AGENT_CONTROL_PANEL); } private void setupSpinners() { } @Override public void populatePanel() { // Populate dropdowns populateDropDown(agentControlType, AgentControlType.class); // Update agent properties updatePanel(); // Select dropdown item agentControlType.selectItem(agent.getControlType()); // Set checkbox controls cameraEnabled.setChecked(entityVO.isCamModeOn()); } @Override public void subscriptions() { /* * Subscriptions for DropDown Controls */ nifty.subscribe(screen, getAgentControlType().getId(), DropDownSelectionChangedEvent.class, new EventTopicSubscriber<DropDownSelectionChangedEvent<AgentControlType>>() { @Override public void onEvent(final String id, DropDownSelectionChangedEvent<AgentControlType> event) { simCommander.sendRuntimeAgentCommand(agent.getID(), RuntimeAgentCommand.SET_CONTROL_TYPE, event.getSelection().toString()); } }); /* * Subscriptions for CheckBox Controls */ nifty.subscribe(screen, getCameraEnabled().getId(), CheckBoxStateChangedEvent.class, new EventTopicSubscriber<CheckBoxStateChangedEvent>() { @Override public void onEvent(final String id, final CheckBoxStateChangedEvent event) { if(event.getCheckBox().isChecked()) { // Dettach free camera entityVO.setCamMode(true); app.dettachFreeCamera(); } else if(!event.getCheckBox().isChecked()) { entityVO.setCamMode(false); app.attachFreeCamera(); } } }); } @Override public void updatePanel() { agent = (VehicleAgentState) entityVO.getState(); updatePosition(); updateVelocity(); updateAcceleration(); updateHeading(); updateScale(); updatePlanningDetails(); } private void updateHeading() { heading.getRenderer(TextRenderer.class).setText(String.format("(%.2f, %.2f, %.2f)", agent.getHeading().x, agent.getHeading().y, agent.getHeading().z)); } private void updateAcceleration() { acceleration.getRenderer(TextRenderer.class).setText(String.format("(%.2f, %.2f, %.2f) m/s^2", agent.getAcceleration().x, agent.getAcceleration().y, agent.getAcceleration().z)); } private void updateVelocity() { velocity.getRenderer(TextRenderer.class).setText(String.format("(%.2f, %.2f, %.2f) m/s", agent.getVelocity().x, agent.getVelocity().y, agent.getVelocity().z)); } private void updatePosition() { position.getRenderer(TextRenderer.class).setText(String.format("(%.2f, %.2f, %.2f)", agent.getPosition().x, agent.getPosition().y, agent.getPosition().z)); } private void updateScale() { scale.getRenderer(TextRenderer.class).setText(String.format("(%.2f, %.2f, %.2f)", agent.getScale().x, agent.getScale().y, agent.getScale().z)); } private void updatePlanningDetails() { } /** * Gets the camera check box control of the nifty gui window. * * @return the camera check box control. */ public CheckBox getCameraEnabled() { return cameraEnabled; } private DropDown<AgentControlType> getAgentControlType() { return agentControlType; } @Override public void setEntity(VehicleAgentVO entity) { super.entityVO = entity; } }
3. Implementing the “VehicleModificationDialog” class
The “VehicleModificationDialog” class describes the vehicle modification dialogue properties (e.g., position, width, height, alignment, etc.). To implement this class:
- Inside the package “edu.utdallas.mavs.traffic.visualization.vis3D.dialog.vehicleModification”, create a class named “VehicleModificationDialog” that extends the “AbstractPropertyDialog” class defined in the package “edu.utdallas.mavs.divas.visualization.vis3D.dialog.customControls.voModification”.
- This class defines the vehicle modification dialogue properties (e.g., position, width, height, alignment, etc.). The following code provides a full implementation of this class:
package edu.utdallas.mavs.traffic.visualization.vis3D.dialog.vehicleModification; import java.util.HashMap; import java.util.Map; import de.lessvoid.nifty.Nifty; import de.lessvoid.nifty.elements.Element; import edu.utdallas.mavs.divas.visualization.vis3D.dialog.customControls.voModification.AbstractPropertyDialog; import edu.utdallas.mavs.traffic.visualization.vis3D.vo.VehicleAgentVO; /** * This class describes a property dialog for a vehicle agent. */ public class VehicleModificationDialog extends AbstractPropertyDialog<VehicleAgentVO, VehicleModificationDialogController> { /** * The {@link VehicleModificationDialog} constructor. * * @param parentElement * The parent element for the dialog. */ public VehicleModificationDialog(Element parentElement) { super(parentElement); } @Override public boolean isContextSelected(Object object) { if(object instanceof VehicleAgentVO) { return ((VehicleAgentVO) object).isContextSelected(); } else { return false; } } @Override public String getWidth() { return "275px"; } @Override public String getHeight() { return "310px"; } @Override public String getAlignment() { return "center"; } @Override public Map<String, String> getParameters() { return new HashMap<String, String>(); } @Override public Class<VehicleModificationDialogDefinition> getDefinitionClass() { return VehicleModificationDialogDefinition.class; } @Override public Class<VehicleModificationDialogController> getControllerClass() { return VehicleModificationDialogController.class; } @Override public void registerNiftyDefinition(Nifty nifty) { VehicleModificationDialogDefinition.register(nifty); } @Override public void updateDialog() { if(content != null) { try { content.getControl(getControllerClass()).updatePanel(); } catch(Exception e) { entity.setContextSelected(false); super.removeDialog(); } } } @Override public String getControllerName() { return (new VehicleModificationDialogController()).getClass().getName(); } @Override public String getPositionX() { return "40"; } @Override public String getPositionY() { return "40"; } @Override public String getContentHeight() { return "290px"; } @Override public String getContentWidth() { return "100%"; } @Override public String createDialogId(String id) { return String.format("#VehiclePropertyWindow%s", id); } @Override public String createDialogTitle(String id) { return String.format("%s %s", "Agent", id); } @Override public String getEntityId(Object entity) { return String.valueOf(((VehicleAgentVO) entity).getState().getID()); } @Override public void hideDialog() { super.showDialog(); } }