/** * Copyright 2014 SMEdit * https://github.com/StarMade/SMEdit SMTools * https://github.com/StarMade/SMTools * * 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 jo.sm.ui; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.List; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.Action; import javax.swing.Box; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBoxMenuItem; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JTabbedPane; import javax.swing.JToolBar; import javax.swing.border.EmptyBorder; import jo.log.TextAreaLogHandler; import jo.sm.logic.RunnableLogic; import jo.sm.logic.StarMadeLogic; import jo.sm.mods.IBlocksPlugin; import jo.sm.mods.IPluginCallback; import jo.sm.mods.IRunnableWithProgress; import jo.sm.ui.act.Shot; import jo.sm.ui.act.edit.RedoAction; import jo.sm.ui.act.edit.RedoActionButton; import jo.sm.ui.act.edit.UndoAction; import jo.sm.ui.act.edit.UndoActionButton; import jo.sm.ui.act.file.OpenExistingAction; import jo.sm.ui.act.file.OpenExistingAction1; import jo.sm.ui.act.file.OpenFileAction; import jo.sm.ui.act.file.OpenFileAction1; import jo.sm.ui.act.file.QuitAction; import jo.sm.ui.act.file.SaveAction; import jo.sm.ui.act.file.SaveAsBlueprintAction; import jo.sm.ui.act.file.SaveAsBlueprintAction1; import jo.sm.ui.act.file.SaveAsFileAction; import jo.sm.ui.act.file.SaveAsFileAction1; import jo.sm.ui.act.memRefresh; import jo.sm.ui.act.plugin.BlocksPluginAction; import jo.sm.ui.act.view.AxisAction; import jo.sm.ui.act.view.DontDrawAction; import jo.sm.ui.act.view.PlainAction; import jo.sm.ui.logic.MenuLogic; import jo.sm.ui.logic.ShipSpec; import jo.sm.ui.logic.ShipTreeLogic; import jo.sm.ui.lwjgl.LWJGLRenderPanel; import jo.util.GlobalConfiguration; import jo.util.Paths; import jo.util.Resources; import jo.util.SplashScreen; @SuppressWarnings("serial") public class RenderFrame extends JFrame { private static final Logger log = Logger.getLogger(RenderFrame.class.getName()); private static final String os = System.getProperty("os.name").toLowerCase(); private static String[] mArgs; private static boolean debugLogging = true; public static void preLoad() { Properties props = StarMadeLogic.getProps(); String home = props.getProperty("starmade.home", ""); if (!StarMadeLogic.isStarMadeDirectory(home)) { home = System.getProperty("user.dir"); if (!StarMadeLogic.isStarMadeDirectory(home)) { home = JOptionPane.showInputDialog(null, "Enter in the home directory for StarMade", home); if (home == null) { System.exit(0); } } props.put("starmade.home", home); StarMadeLogic.saveProps(); } StarMadeLogic.setBaseDir(home); } public static void main(String[] args) { preLoad(); if (os.contains("windows")) { SplashScreen splash = new SplashScreen(args); if (!splash.error) { startup(args); } splash.close(); } else if (os.contains("mac")) { startup(args); } else if (os.contains("linux")) { startup(args); } } /** * Returns the startup run objects for app startup * only (not useful for script writers). * * @param args * the first loaded ship for the client */ public static void startup(String[] args) { final RenderFrame f = new RenderFrame(args); f.setVisible(true); try { /*Chenage the commented line to change the default loaded blueprint*/ /*method updated as of SMEdit v1.06*/ final ShipSpec spec = ShipTreeLogic.getBlueprintSpec("Omen-Navy-Class", true); //final ShipSpec spec = ShipTreeLogic.getBlueprintSpec("Isanth-VI", true); if (spec != null) { IRunnableWithProgress t = new IRunnableWithProgress() { @Override public void run(IPluginCallback cb) { StarMadeLogic.getInstance().setCurrentModel(spec); StarMadeLogic.setModel(ShipTreeLogic.loadShip(spec, cb)); } }; log.log(Level.INFO, "Loading Ship!"); RunnableLogic.run(f, "Loading...", t); } else { log.log(Level.WARNING, "Could not find the ship your asking to load!"); } } catch (Exception e) { log.log(Level.WARNING, "Ship load failed!", e); } log.config("Main application started: " + GlobalConfiguration.NAME); } /** * @return the debugLogging */ public static boolean isDebugLogging() { return debugLogging; } /** * @param aDebugLogging the debugLogging to set */ public static void setDebugLogging(boolean aDebugLogging) { debugLogging = aDebugLogging; } public static void debug(String s) { if (isDebugLogging()) { log.info(s); } } private boolean compactToolbars = true; private boolean borderedButtons = true; private RenderPanel mClient; private JToolBar outerToolBar; private JToolBar innerToolBar; private final JTabbedPane ClientWindows; public final JScrollPane textScroll; private JButton mPlugins; public RenderFrame(String[] args) { setTitle(GlobalConfiguration.NAME + " version 1.0" + ((float) GlobalConfiguration.getVersion() / 100)); mArgs = args; setIconImage(GlobalConfiguration.getImage(Resources.ICON)); setSize(1024, 768); setLocationRelativeTo(getOwner()); /* outer-most containers actually reserved for docking the toolbars. * so "cp" is actually not the contentpane of the JPanel, but let's * ignore that. */ JPanel outerToolPane = (JPanel) super.getContentPane(); JPanel innerToolPane = new JPanel(new BorderLayout()); JPanel cp = new JPanel(new BorderLayout()); outerToolPane.setLayout(new BorderLayout()); outerToolPane.add(innerToolPane, BorderLayout.CENTER); innerToolPane.add(cp, BorderLayout.CENTER); if ((mArgs.length > 0) && (mArgs[0].equals("-opengl"))) { mClient = new LWJGLRenderPanel(); } else { mClient = new AWTRenderPanel(); } setupMenus(); setupToolbars(); cp.setLayout(new BorderLayout()); JPanel main = new JPanel(new BorderLayout()); main.add(new EditPanel(getClient(), this), BorderLayout.WEST); main.add(getClient(), BorderLayout.CENTER); textScroll = new JScrollPane(TextAreaLogHandler.TEXT_AREA, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); textScroll.setBorder(null); textScroll.setVisible(true); ClientWindows = new JTabbedPane(); ClientWindows.setFont(new Font("Futura Md BT", 0, 10)); ClientWindows.addTab("Edit Window", main); ClientWindows.setFont(new Font("Futura Md BT", 0, 10)); ClientWindows.addTab("Log Window", textScroll); /* Toolbar placement */ innerToolPane.add(innerToolBar, BorderLayout.NORTH); outerToolPane.add(outerToolBar, BorderLayout.NORTH); getContentPane().add(ClientWindows, BorderLayout.CENTER); getContentPane().add(new StatusPanel(), BorderLayout.SOUTH); addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent evt) { if (safeClose()) { dispose(); System.exit(0); } } }); addWindowFocusListener(new WindowAdapter() { @Override public void windowGainedFocus(WindowEvent e) { getClient().requestFocusInWindow(); } }); } private void setupToolbars() { setOuterToolBar(new JToolBar()); setInnerToolBar(new JToolBar()); JButton openPrintButton; final ImageIcon op = new ImageIcon(Paths.getIconDirectory() + "/open_print.png"); openPrintButton = getDefaultButton(new OpenExistingAction1(this), "open a blueprint", op); outerToolBar.add(openPrintButton); JButton openButton; final ImageIcon o = new ImageIcon(Paths.getIconDirectory() + "/open.png"); openButton = getDefaultButton(new OpenFileAction1(this), "open a file", o); outerToolBar.add(openButton); JButton savePrintButton; final ImageIcon sp = new ImageIcon(Paths.getIconDirectory() + "/save.png"); savePrintButton = getDefaultButton(new SaveAsBlueprintAction1(this, false), "Save blueprint", sp); outerToolBar.add(savePrintButton); JButton saveButton; final ImageIcon sa = new ImageIcon(Paths.getIconDirectory() + "/save_as.png"); saveButton = getDefaultButton(new SaveAsFileAction1(this), "Save file", sa); outerToolBar.add(saveButton); JButton screenButton; final ImageIcon s = new ImageIcon(Paths.getIconDirectory() + "/shot.png"); screenButton = getDefaultButton(new Shot(this), "Screenshots of work", s); outerToolBar.add(screenButton); outerToolBar.addSeparator(); outerToolBar.addSeparator(); JButton undoButton; final ImageIcon u = new ImageIcon(Paths.getIconDirectory() + "/undo.png"); undoButton = getDefaultButton(new UndoActionButton(this), "Undo last action", u); outerToolBar.add(undoButton); JButton redoButton; final ImageIcon r = new ImageIcon(Paths.getIconDirectory() + "/redo.png"); redoButton = getDefaultButton(new RedoActionButton(this), "Redo last action", r); outerToolBar.add(redoButton); outerToolBar.add(Box.createHorizontalGlue()); final ImageIcon p = new ImageIcon(Paths.getIconDirectory() + "/plugins.png"); mPlugins = getDefaultActionlessButton("Plugins", "List of avalable plugins", p); outerToolBar.add(mPlugins); mPlugins.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { doPlugin(); } }); /*add memory ProgressBar*/ JButton memButton; final ImageIcon c = new ImageIcon(Paths.getIconDirectory() + "/cpu.png"); memButton = getProgressButton(new memRefresh(), "Click to refresh Memory use", c); outerToolBar.add(memButton); } private void setupMenus() { JMenuBar menuBar = new JMenuBar(); JMenu menuFile = new JMenu("File"); menuFile.setMnemonic(KeyEvent.VK_F); JMenu menuEdit = new JMenu("Edit"); menuEdit.setMnemonic(KeyEvent.VK_E); JMenu menuView = new JMenu("View"); menuView.setMnemonic(KeyEvent.VK_V); JMenu menuModify = new JMenu("Modify"); menuModify.setMnemonic(KeyEvent.VK_M); JMenu menuHelp = new JMenu("Help"); menuHelp.setMnemonic(KeyEvent.VK_H); /*layout*/ setJMenuBar(menuBar); menuBar.add(menuFile); menuFile.add(new OpenExistingAction(this)); menuFile.add(new OpenFileAction(this)); menuFile.add(new JSeparator()); menuFile.add(new SaveAction(this)); JMenu saveAs = new JMenu("Save As"); menuFile.add(saveAs); saveAs.add(new SaveAsBlueprintAction(this, false)); saveAs.add(new SaveAsBlueprintAction(this, true)); saveAs.add(new SaveAsFileAction(this)); JSeparator menuFileStart = new JSeparator(); menuFileStart.setName("pluginsStartHere"); menuFile.add(menuFileStart); menuFile.add(new JSeparator()); menuFile.add(new QuitAction(this)); menuBar.add(menuEdit); menuEdit.add(new UndoAction(this)); menuEdit.add(new RedoAction(this)); menuEdit.add(new JSeparator()); menuBar.add(menuView); menuView.add(new JCheckBoxMenuItem(new PlainAction(this))); menuView.add(new JCheckBoxMenuItem(new AxisAction(this))); menuView.add(new JCheckBoxMenuItem(new DontDrawAction(this))); JSeparator viewFileStart = new JSeparator(); viewFileStart.setName("pluginsStartHere"); menuView.add(viewFileStart); menuBar.add(menuModify); menuBar.add(menuHelp); /*link*/ menuFile.addMenuListener(new PluginPopupListener(this, IBlocksPlugin.SUBTYPE_FILE)); menuEdit.addMenuListener(new PluginPopupListener(this, IBlocksPlugin.SUBTYPE_EDIT)); menuView.addMenuListener(new PluginPopupListener(this, IBlocksPlugin.SUBTYPE_VIEW)); menuModify.addMenuListener(new PluginPopupListener(this, IBlocksPlugin.SUBTYPE_MODIFY, IBlocksPlugin.SUBTYPE_GENERATE)); } /** * Makes a JButton with the given icon and tooltop. If the icon cannot be * loaded, then the text will be used instead. * * Adds this RenderFame as an actionListener. * * @return a shiny new JButton * */ private JButton getDefaultButton(final Action a, final String tip, final ImageIcon i) { final JButton button = new JButton(a); button.setToolTipText(tip); button.setIcon(i); button.setFocusable(false); button.setMargin(new Insets(6, 3, 6, 3)); button.setPreferredSize(new Dimension(32, 32)); button.setMaximumSize(new Dimension(32, 32)); button.setBorder(new EmptyBorder(3, 3, 3, 3)); return button; } /** * Makes a JButton with the given icon and tooltop. If the icon cannot be * loaded, then the text will be used instead. * * Adds this RenderFame as an actionListener. * * @return a shiny new JButton * */ private JButton getDefaultActionlessButton(final String text, final String tip, final ImageIcon i) { final JButton button = new JButton(); button.setText(text); button.setToolTipText(tip); button.setIcon(i); button.setFocusable(false); button.setMargin(new Insets(6, 3, 6, 3)); button.setPreferredSize(new Dimension(75, 32)); button.setMaximumSize(new Dimension(75, 32)); button.setBorder(new EmptyBorder(3, 3, 3, 3)); button.setFont(new Font("Tahoma", 0, 10)); return button; } /** * Makes a JButton with the given icon and tooltop. If the icon cannot be * loaded, then the text will be used instead. * * Adds this RenderFame as an actionListener. * * @return a shiny new JButton * */ private JButton getProgressButton(final Action a, final String tip, final ImageIcon i) { MemProgressBar mem = new MemProgressBar(); mem.setMaximumSize(new Dimension(250, 32)); final JButton button = new JButton(a); //button.add(Box.createHorizontalGlue()); button.add(mem); button.setToolTipText(tip); button.setIcon(i); button.setFocusable(false); button.setPreferredSize(new Dimension(250, 32)); button.setMaximumSize(new Dimension(250, 32)); button.setBorder(new EmptyBorder(3, 3, 3, 3)); return button; } /** * * @param menu * @param subTypes */ public void updatePopup(JMenu menu, int... subTypes) { MenuLogic.clearPluginMenus(menu); ShipSpec spec = StarMadeLogic.getInstance().getCurrentModel(); if (spec == null) { return; } int type = spec.getClassification(); int lastModIndex = menu.getItemCount(); int lastCount = 0; for (int subType : subTypes) { int thisCount = MenuLogic.addPlugins(getClient(), menu, type, subType); if ((thisCount > 0) && (lastCount > 0)) { JSeparator sep = new JSeparator(); sep.setName("plugin"); menu.add(sep, lastModIndex); lastCount = 0; } lastCount += thisCount; lastModIndex = menu.getItemCount(); } } public void doPlugin() { JPopupMenu popup = new JPopupMenu(); int classification = StarMadeLogic.getInstance().getCurrentModel().getClassification(); List<IBlocksPlugin> plugins = StarMadeLogic.getBlocksPlugins(classification, IBlocksPlugin.SUBTYPE_PAINT); if (plugins.isEmpty()) { popup.add("no plugins"); } for (IBlocksPlugin plugin : plugins) { BlocksPluginAction action = new BlocksPluginAction(getClient(), plugin); JMenuItem men = new JMenuItem(action); popup.add(men); } Dimension d = mPlugins.getSize(); popup.show(mPlugins, d.width, d.height); } private boolean safeClose() { boolean pass; final int result = JOptionPane.showConfirmDialog(this, "Are you sure you would like to quit?", "Close", JOptionPane.WARNING_MESSAGE, JOptionPane.YES_NO_OPTION); pass = result == JOptionPane.YES_OPTION; return pass; } /** * * @return */ public RenderPanel getClient() { return mClient; } /** * * @param client */ public void setClient(RenderPanel client) { mClient = client; } /** * * @return */ public JFrame getFrame() { for (Component c = this; c != null; c = c.getParent()) { if (c instanceof JFrame) { return (JFrame) c; } } return null; } /** * @return the compactToolbars */ public boolean isCompactToolbars() { return compactToolbars; } /** * @param compactToolbars the compactToolbars to set */ public void setCompactToolbars(boolean compactToolbars) { this.compactToolbars = compactToolbars; } /** * @return the borderedButtons */ public boolean isBorderedButtons() { return borderedButtons; } /** * @param borderedButtons the borderedButtons to set */ public void setBorderedButtons(boolean borderedButtons) { this.borderedButtons = borderedButtons; } /** * @return the outerToolBar */ public JToolBar getOuterToolBar() { return outerToolBar; } /** * @param outerToolBar the outerToolBar to set */ public void setOuterToolBar(JToolBar outerToolBar) { this.outerToolBar = outerToolBar; } /** * @return the innerToolBar */ public JToolBar getInnerToolBar() { return innerToolBar; } /** * @param innerToolBar the innerToolBar to set */ public void setInnerToolBar(JToolBar innerToolBar) { this.innerToolBar = innerToolBar; } }