package com.momega.spacesimulator; import com.jogamp.newt.event.KeyEvent; import com.momega.spacesimulator.builder.ModelBuilder; import com.momega.spacesimulator.context.Application; import com.momega.spacesimulator.context.ModelHolder; import com.momega.spacesimulator.model.HistoryPoint; import com.momega.spacesimulator.model.HistoryPointOrigin; import com.momega.spacesimulator.model.Model; import com.momega.spacesimulator.model.PositionProvider; import com.momega.spacesimulator.opengl.DefaultWindow; import com.momega.spacesimulator.opengl.MainGLRenderer; import com.momega.spacesimulator.renderer.ModelChangeEvent; import com.momega.spacesimulator.renderer.ModelChangeListener; import com.momega.spacesimulator.renderer.RendererModel; import com.momega.spacesimulator.renderer.StatusBarEvent; import com.momega.spacesimulator.service.HistoryPointListener; import com.momega.spacesimulator.service.HistoryPointService; import com.momega.spacesimulator.service.ModelBuilderFactory; import com.momega.spacesimulator.utils.TimeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.env.PropertySource; import org.springframework.core.env.SimpleCommandLinePropertySource; import com.momega.spacesimulator.controller.*; import com.momega.spacesimulator.swing.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.File; /** * The main window of the application * @author martin */ public class MainWindow extends DefaultWindow { private static final Logger logger = LoggerFactory.getLogger(MainWindow.class); private static final String BUILDER_CLASS_NAME_OPTION = "builderClassName"; private static final String FILE_NAME_OPTION = "fileName"; public MainWindow(String title) { super(title); } public static void main(String[] args) { final MainWindow window = new MainWindow("Space Simulator"); EventBusController controller = new EventBusController(); MainGLRenderer mr = new MainGLRenderer(window); controller.addController(new QuitController(window)); controller.addController(new UserPointController()); controller.addController(new TargetController(window)); controller.addController(new TakeScreenshotController()); controller.addController(new CameraController()); controller.addController(new TimeController(window)); controller.addController(new PerspectiveController(mr)); controller.addController(new ToolbarController()); controller.addController(new PreferencesController()); controller.addController(new InterplanetaryFlightController()); controller.addController(new LoadController()); controller.addController(new SaveController()); controller.addController(new SpacecraftController()); controller.addController(new CloseController()); controller.addController(new CreateFromBuilderController()); window.openWindow(mr, controller); final RendererModel rendererModel = RendererModel.getInstance(); rendererModel.addPropertyChangeListener(RendererModel.MODEL_FILE, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { File file = (File) evt.getNewValue(); String title = window.getTitle(); if (file != null) { title += " (" + file.getAbsolutePath() + ")"; } window.getFrame().setTitle(title); } }); PropertySource<?> ps = new SimpleCommandLinePropertySource(args); String builderClassName = (String) ps.getProperty(BUILDER_CLASS_NAME_OPTION); if (builderClassName != null) { ModelBuilder modelBuilder = Application.getInstance().getService(ModelBuilderFactory.class).createBuilder(builderClassName); RendererModel.getInstance().setModelBuilderRequested(modelBuilder); return; } String fileName = (String) ps.getProperty(FILE_NAME_OPTION); if (fileName!=null) { RendererModel.getInstance().setLoadFileRequested(new File(fileName)); return; } if (!rendererModel.isModelReady()) { ActionEvent event = new ActionEvent(window, ActionEvent.ACTION_FIRST, CreateFromBuilderController.CREATE_FROM_BUILDER_COMMAND); controller.actionPerformed(event); } } @Override public void windowClosing(Controller controller) { controller.actionPerformed(new ActionEvent(this, 0, QuitController.COMMAND)); } @Override protected Image getIcon() { return Icons.FRAME_ICON.getImage(); } @Override protected JMenuBar createMenuBar(Controller controller) { JMenuBar menuBar = new JMenuBar(); JMenu fileMenu = new JMenu("File"); fileMenu.setMnemonic(KeyEvent.VK_F); JMenuItem createItem = new JMenuItem("Create..."); createItem.setMnemonic(KeyEvent.VK_C); createItem.setIcon(Icons.CREATE_FROM_BUILDER); createItem.setActionCommand(CreateFromBuilderController.CREATE_FROM_BUILDER_COMMAND); createItem.addActionListener(controller); JMenuItem openItem = new JMenuItem("Open..."); openItem.setMnemonic(KeyEvent.VK_O); openItem.setIcon(SwingUtils.createImageIcon("/images/page_go.png")); openItem.setActionCommand(LoadController.LOAD_COMMAND); openItem.setAccelerator(KeyStroke.getKeyStroke("F3")); openItem.addActionListener(controller); final JMenuItem saveItem = new JMenuItem("Save"); saveItem.setActionCommand(SaveController.SAVE_COMMAND); saveItem.setMnemonic(KeyEvent.VK_S); saveItem.addActionListener(controller); saveItem.setAccelerator(KeyStroke.getKeyStroke("F2")); saveItem.setIcon(SwingUtils.createImageIcon("/images/page_save.png")); final JMenuItem saveAsItem = new JMenuItem("Save As..."); saveAsItem.setActionCommand(SaveController.SAVE_AS_COMMAND); saveAsItem.addActionListener(controller); final JMenuItem closeItem = new JMenuItem("Close"); closeItem.setActionCommand(CloseController.CLOSE_COMMAND); closeItem.addActionListener(controller); final JMenuItem saveScreenshotItem = new JMenuItem("Save Screenshot"); saveScreenshotItem.setActionCommand(TakeScreenshotController.COMMAND); saveScreenshotItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.ALT_DOWN_MASK)); saveScreenshotItem.addActionListener(controller); JMenuItem preferencesItem = new JMenuItem("Preferences..."); preferencesItem.setActionCommand(PreferencesController.COMMAND); preferencesItem.addActionListener(controller); JMenuItem exitItem = new JMenuItem("Exit..."); exitItem.setActionCommand(QuitController.COMMAND); exitItem.setIcon(SwingUtils.createImageIcon("/images/door_out.png")); exitItem.setMnemonic(KeyEvent.VK_X); exitItem.addActionListener(controller); fileMenu.add(createItem); fileMenu.add(openItem); fileMenu.add(saveItem); fileMenu.add(saveAsItem); fileMenu.add(closeItem); fileMenu.addSeparator(); fileMenu.add(saveScreenshotItem); fileMenu.addSeparator(); fileMenu.add(preferencesItem); fileMenu.addSeparator(); fileMenu.add(exitItem); final JMenu projectMenu = new JMenu("Project"); JMenuItem timeItem = new JMenuItem("Time..."); timeItem.setIcon(Icons.TIME); timeItem.addActionListener(controller); timeItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.ALT_DOWN_MASK)); timeItem.setActionCommand(TimeController.TIME_DIALOG); JMenuItem findItem = new JMenuItem("Find..."); JMenuItem newSpacecraftItem = new JMenuItem("New Spacecraft..."); newSpacecraftItem.setIcon(Icons.ADD_SPACECRAFT); newSpacecraftItem.setActionCommand(SpacecraftController.NEW_SPACECRAFT); newSpacecraftItem.addActionListener(controller); JMenuItem deleteSpacecraftItem = new JMenuItem("Delete Spacecraft..."); deleteSpacecraftItem.setIcon(Icons.DELETE_SPACECRAFT); deleteSpacecraftItem.setActionCommand(SpacecraftController.DELETE_SPACECRAFT); deleteSpacecraftItem.addActionListener(controller); JMenuItem newPointItem = new JMenuItem("New Point..."); newPointItem.setActionCommand(UserPointController.NEW_USER_POINT); newPointItem.addActionListener(controller); JMenuItem interplanetaryFlightItem = new JMenuItem("Interplanetary Flight..."); interplanetaryFlightItem.setActionCommand(InterplanetaryFlightController.INTERPLANETARY_FLIGHT); interplanetaryFlightItem.addActionListener(controller); projectMenu.add(timeItem); projectMenu.add(findItem); projectMenu.addSeparator(); projectMenu.add(newSpacecraftItem); projectMenu.add(deleteSpacecraftItem); projectMenu.add(newPointItem); projectMenu.add(interplanetaryFlightItem); JMenu helpMenu = new JMenu("Help"); helpMenu.setMnemonic(KeyEvent.VK_H); JMenuItem documentationItem = new JMenuItem("Documentation..."); JMenuItem aboutItem = new JMenuItem("About..."); helpMenu.add(documentationItem); documentationItem.setAccelerator(KeyStroke.getKeyStroke("F1")); documentationItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { String url = "https://github.com/momega/com.momega.spacesimulator/wiki/User-Documentation"; SwingUtils.openUrl(url); } }); helpMenu.add(aboutItem); menuBar.add(fileMenu); menuBar.add(projectMenu); menuBar.add(helpMenu); logger.info("menubar created"); RendererModel.getInstance().addPropertyChangeListener(RendererModel.MODEL_READY, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { boolean modelReady = (boolean) evt.getNewValue(); saveAsItem.setEnabled(modelReady); saveItem.setEnabled(modelReady); projectMenu.setEnabled(modelReady); saveScreenshotItem.setEnabled(modelReady); closeItem.setEnabled(modelReady); } }); RendererModel.getInstance().initPropertyChange(RendererModel.MODEL_READY, RendererModel.getInstance().isModelReady()); return menuBar; } @Override protected void createStatusBar(final Controller controller, JFrame frame) { JStatusBar statusPanel = new JStatusBar(); final JLabel statusLabel = new JLabel("The application has started."); statusPanel.setLeftComponent(statusLabel); final JLabel timeLabel = new JLabel(); timeLabel.setHorizontalAlignment(JLabel.CENTER); statusPanel.addRightComponent(timeLabel); timeLabel.setIcon(Icons.TIME); final JLabel warpLabel = new JLabel(); warpLabel.setHorizontalAlignment(JLabel.CENTER); statusPanel.addRightComponent(warpLabel); final JLabel fpsLabel = new JLabel(); fpsLabel.setHorizontalAlignment(JLabel.CENTER); statusPanel.addRightComponent(fpsLabel); RendererModel.getInstance().addModelChangeListener(new ModelChangeListener() { @Override public void modelChanged(ModelChangeEvent event) { if (event instanceof StatusBarEvent) { StatusBarEvent e = (StatusBarEvent) event; statusLabel.setText(e.getMessage()); } else { Model m = event.getModel(); timeLabel.setText(TimeUtils.timeAsString(m.getTime())); } } }); HistoryPointService historyPointService = Application.getInstance().getService(HistoryPointService.class); final HistoryPointListRenderer historyPointListRenderer = new HistoryPointListRenderer(); historyPointService.addHistoryPointListener(new HistoryPointListener() { @Override public void historyPointCreated(HistoryPoint historyPoint) { String message = historyPointListRenderer.getText(historyPoint); statusLabel.setText(message); ImageIcon icon = historyPointListRenderer.getIcon(historyPoint); statusLabel.setIcon(icon); } @Override public boolean supports(HistoryPoint historyPoint) { return true; } }); historyPointService.addHistoryPointListener(new HistoryPointListener() { @Override public void historyPointCreated(HistoryPoint historyPoint) { if (HistoryPointOrigin.END.equals(historyPoint.getOrigin())) { RendererModel.getInstance().removeSpacecraft(historyPoint.getSpacecraft()); RendererModel.getInstance().setDeleteSpacecraft(historyPoint.getSpacecraft()); } } @Override public boolean supports(HistoryPoint historyPoint) { return true; } }); RendererModel.getInstance().addPropertyChangeListener(RendererModel.WARP_FACTOR, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { double warpFactor = (double) evt.getNewValue(); String w = String.format("%3.5f", warpFactor); warpLabel.setText(w); } }); RendererModel.getInstance().initPropertyChange(RendererModel.WARP_FACTOR, RendererModel.getInstance().getWarpFactor()); timeLabel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (e.getClickCount()>1) { ActionEvent event = new ActionEvent(timeLabel, e.getID(), TimeController.TIME_DIALOG); controller.actionPerformed(event); } } }); RendererModel.getInstance().addPropertyChangeListener(RendererModel.FPS, new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { String w = String.format("%4.2f FPS", (float)evt.getNewValue()); fpsLabel.setText(w); } }); frame.add(statusPanel, BorderLayout.SOUTH); } @Override protected JToolBar createToolBar(Controller controller) { JToolBar toolBar = new JToolBar(); toolBar.setRollover(true); JButton warpDownButton = new JButton(); warpDownButton.setIcon(SwingUtils.createImageIcon("/images/control_rewind.png")); warpDownButton.setActionCommand(TimeController.WARP_SLOWER); warpDownButton.addActionListener(controller); JToggleButton startStopButton = new JToggleButton(); startStopButton.setIcon(SwingUtils.createImageIcon("/images/control_pause.png")); startStopButton.setSelectedIcon(SwingUtils.createImageIcon("/images/control_play.png")); startStopButton.setActionCommand(TimeController.WARP_STOP_OR_START); startStopButton.addActionListener(controller); JButton warpUp = new JButton(); warpUp.setIcon(SwingUtils.createImageIcon("/images/control_fastforward.png")); warpUp.setActionCommand(TimeController.WARP_FASTER); warpUp.addActionListener(controller); JComboBox<PositionProvider> movingObjectsBox = new JComboBox<>(); movingObjectsBox.setModel(RendererModel.getInstance().getMovingObjectsModel()); movingObjectsBox.setRenderer(new MovingObjectListRenderer()); movingObjectsBox.setMaximumSize(new Dimension(300, 100)); movingObjectsBox.setActionCommand(TargetController.SELECT_POSITION_PROVIDER); movingObjectsBox.addActionListener(controller); JToggleButton spacecraftButton = new JToggleButton(); spacecraftButton.setSelected(true); spacecraftButton.setIcon(Icons.SPACECRAFT); spacecraftButton.setToolTipText("Activate the spacecrafts"); spacecraftButton.setActionCommand(ToolbarController.SPACECRAFT_TOGGLE_COMMAND); spacecraftButton.addActionListener(controller); JToggleButton celestialButton = new JToggleButton(); celestialButton.setSelected(true); celestialButton.setIcon(Icons.CELESTIAL); celestialButton.setToolTipText("Activate the celestial bodies"); celestialButton.setActionCommand(ToolbarController.CELESTIAL_TOGGLE_COMMAND); celestialButton.addActionListener(controller); JToggleButton pointButton = new JToggleButton(); pointButton.setSelected(true); pointButton.setIcon(Icons.APSIS_POINT); pointButton.setToolTipText("Activate the points"); pointButton.setActionCommand(ToolbarController.POINT_TOGGLE_COMMAND); pointButton.addActionListener(controller); toolBar.add(warpDownButton); toolBar.add(startStopButton); toolBar.add(warpUp); toolBar.addSeparator(); toolBar.add(spacecraftButton); toolBar.add(celestialButton); toolBar.add(pointButton); toolBar.add(movingObjectsBox); JButton detailButton = new JButton(); detailButton.setIcon(SwingUtils.createImageIcon("/images/magnifier.png")); detailButton.setActionCommand(TargetController.DETAIL_POSITION_PROVIDER); detailButton.addActionListener(controller); toolBar.add(detailButton); logger.info("toolbar created"); return toolBar; } }