diff --git a/src/net/apocalypselabs/symat/CodeRunner.java b/src/net/apocalypselabs/symat/CodeRunner.java index 93f59e4..ab7e83d 100644 --- a/src/net/apocalypselabs/symat/CodeRunner.java +++ b/src/net/apocalypselabs/symat/CodeRunner.java @@ -85,6 +85,16 @@ public class CodeRunner { this(lang); isShell = shell; } + + /** + * Inits the Python engine. + * @param fakeInit Set it to true. + */ + public CodeRunner(boolean fakeInit) { + if (fakeInit) { + se = new ScriptEngineManager().getEngineByName("python"); + } + } private void initError(Exception ex) { JOptionPane.showMessageDialog(null, "Error: " diff --git a/src/net/apocalypselabs/symat/Graph.form b/src/net/apocalypselabs/symat/Graph.form index 974ede2..9355961 100644 --- a/src/net/apocalypselabs/symat/Graph.form +++ b/src/net/apocalypselabs/symat/Graph.form @@ -124,7 +124,7 @@ - + diff --git a/src/net/apocalypselabs/symat/Graph.java b/src/net/apocalypselabs/symat/Graph.java index 42cbf8d..5a69dae 100644 --- a/src/net/apocalypselabs/symat/Graph.java +++ b/src/net/apocalypselabs/symat/Graph.java @@ -226,7 +226,7 @@ public class Graph extends javax.swing.JInternalFrame { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jButton1)) .addComponent(gLbl, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) diff --git a/src/net/apocalypselabs/symat/Interpreter.form b/src/net/apocalypselabs/symat/Interpreter.form index 38718cb..3ea2caa 100644 --- a/src/net/apocalypselabs/symat/Interpreter.form +++ b/src/net/apocalypselabs/symat/Interpreter.form @@ -1,6 +1,59 @@
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -12,6 +65,7 @@ + @@ -42,7 +96,7 @@ - + diff --git a/src/net/apocalypselabs/symat/Interpreter.java b/src/net/apocalypselabs/symat/Interpreter.java index 79fc30e..ec25373 100644 --- a/src/net/apocalypselabs/symat/Interpreter.java +++ b/src/net/apocalypselabs/symat/Interpreter.java @@ -38,15 +38,34 @@ import javax.swing.text.DefaultCaret; */ public class Interpreter extends javax.swing.JInternalFrame { - private final CodeRunner cr = new CodeRunner("javascript", true); + private final CodeRunner cr; private String[] history = new String[10]; // Command history buffer private int historyIndex = 0; // For going back in time and keeping things straight + private String lang = "javascript"; /** * Creates new form Interpreter + * + * @param useLang The script language to use. "javascript", "python", or + * "default". */ - public Interpreter() { + public Interpreter(String useLang) { initComponents(); + + // Setup code runner + lang = useLang; + if (lang.equals("default")) { + lang = PrefStorage.getSetting("shellLang", "javascript"); + } + cr = new CodeRunner(lang, true); + + // Set selected lang menu + if (lang.equals("python")) { + javascriptMenu.setSelected(false); + pythonMenu.setSelected(true); + } + + // Set font int font_size = 12; try { font_size = Integer.valueOf(PrefStorage.getSetting("editfont")); @@ -54,6 +73,8 @@ public class Interpreter extends javax.swing.JInternalFrame { } mainBox.setFont(new Font(Font.MONOSPACED, Font.PLAIN, font_size)); inputBox.setFont(new Font(Font.MONOSPACED, Font.PLAIN, font_size)); + + // Set theme if (PrefStorage.getSetting("theme").equals("dark")) { mainBox.setBackground(Color.BLACK); mainBox.setForeground(Color.WHITE); @@ -67,12 +88,18 @@ public class Interpreter extends javax.swing.JInternalFrame { inputBox.setForeground(Color.BLACK); setBackground(Color.LIGHT_GRAY); } + + // Misc. setup mainBox.setLineWrap(true); mainBox.setWrapStyleWord(true); mainBox.setText(">>"); inputBox.requestFocus(); } + public Interpreter() { + this("default"); + } + /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -82,11 +109,18 @@ public class Interpreter extends javax.swing.JInternalFrame { // //GEN-BEGIN:initComponents private void initComponents() { + langGroup = new javax.swing.ButtonGroup(); jScrollPane1 = new javax.swing.JScrollPane(); mainBox = new javax.swing.JTextArea(); inputBox = new javax.swing.JTextField(); runBtn = new javax.swing.JButton(); jLabel1 = new javax.swing.JLabel(); + jMenuBar1 = new javax.swing.JMenuBar(); + langMenu = new javax.swing.JMenu(); + jMenu1 = new javax.swing.JMenu(); + javascriptMenu = new javax.swing.JRadioButtonMenuItem(); + pythonMenu = new javax.swing.JRadioButtonMenuItem(); + setDefaultLang = new javax.swing.JMenuItem(); setClosable(true); setIconifiable(true); @@ -123,6 +157,43 @@ public class Interpreter extends javax.swing.JInternalFrame { jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); jLabel1.setText(">>"); + langMenu.setText("Language"); + + jMenu1.setText("Switch"); + + langGroup.add(javascriptMenu); + javascriptMenu.setSelected(true); + javascriptMenu.setText("JavaScript"); + javascriptMenu.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + javascriptMenuActionPerformed(evt); + } + }); + jMenu1.add(javascriptMenu); + + langGroup.add(pythonMenu); + pythonMenu.setText("Python"); + pythonMenu.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + pythonMenuActionPerformed(evt); + } + }); + jMenu1.add(pythonMenu); + + langMenu.add(jMenu1); + + setDefaultLang.setText("Set as default"); + setDefaultLang.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + setDefaultLangActionPerformed(evt); + } + }); + langMenu.add(setDefaultLang); + + jMenuBar1.add(langMenu); + + setJMenuBar(jMenuBar1); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( @@ -138,7 +209,7 @@ public class Interpreter extends javax.swing.JInternalFrame { layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 239, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(runBtn, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) @@ -187,6 +258,29 @@ public class Interpreter extends javax.swing.JInternalFrame { } }//GEN-LAST:event_inputBoxKeyPressed + private void setDefaultLangActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_setDefaultLangActionPerformed + String pref = "javascript"; + if (pythonMenu.isSelected()) { + pref = "python"; + } + PrefStorage.saveSetting("shellLang", pref); + PrefStorage.save(); + }//GEN-LAST:event_setDefaultLangActionPerformed + + private void javascriptMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_javascriptMenuActionPerformed + if (!lang.equals("javascript")) { + MainGUI.loadFrame(new Interpreter("javascript")); + dispose(); + } + }//GEN-LAST:event_javascriptMenuActionPerformed + + private void pythonMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pythonMenuActionPerformed + if (!lang.equals("python")) { + MainGUI.loadFrame(new Interpreter("python")); + dispose(); + } + }//GEN-LAST:event_pythonMenuActionPerformed + private void doRunCode() { String code = inputBox.getText(); mainBox.append(" " + code + "\n"); @@ -207,8 +301,15 @@ public class Interpreter extends javax.swing.JInternalFrame { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JTextField inputBox; private javax.swing.JLabel jLabel1; + private javax.swing.JMenu jMenu1; + private javax.swing.JMenuBar jMenuBar1; private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JRadioButtonMenuItem javascriptMenu; + private javax.swing.ButtonGroup langGroup; + private javax.swing.JMenu langMenu; private javax.swing.JTextArea mainBox; + private javax.swing.JRadioButtonMenuItem pythonMenu; private javax.swing.JButton runBtn; + private javax.swing.JMenuItem setDefaultLang; // End of variables declaration//GEN-END:variables } diff --git a/src/net/apocalypselabs/symat/MainGUI.form b/src/net/apocalypselabs/symat/MainGUI.form index ca9612b..56da12f 100644 --- a/src/net/apocalypselabs/symat/MainGUI.form +++ b/src/net/apocalypselabs/symat/MainGUI.form @@ -9,9 +9,6 @@ - - - @@ -216,18 +213,19 @@ + + - + - - - - + + + @@ -281,6 +279,26 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/net/apocalypselabs/symat/MainGUI.java b/src/net/apocalypselabs/symat/MainGUI.java index c66e32f..4c11414 100644 --- a/src/net/apocalypselabs/symat/MainGUI.java +++ b/src/net/apocalypselabs/symat/MainGUI.java @@ -1,7 +1,7 @@ -/* +/* * Apocalypse Laboratories * Open Source License - * + * * Source code can be used for any purpose, as long as: * - Compiled binaries are rebranded and trademarks are not * visible by the end user at any time, except to give @@ -14,7 +14,7 @@ * - and you provide your modified source code for download, * under the terms of the GNU LGPL v3 or a comparable * license. - * + * * Compiled binaries cannot be redistributed or mirrored, * unless: * - You have written permission from Apocalypse Laboratories; @@ -22,15 +22,14 @@ * not even behind a paywall or other blocking mechanism; * - or you have received a multi-computer license, in which * case you should take measures to prevent unauthorized - * downloads, such as preventing download access from the + * downloads, such as preventing download access from the * Internet. */ package net.apocalypselabs.symat; import java.awt.Color; -import java.awt.Component; -import java.awt.Font; import java.awt.Graphics; +import java.beans.PropertyVetoException; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -45,9 +44,10 @@ import javax.swing.JInternalFrame; */ public class MainGUI extends javax.swing.JFrame { - public static final String APP_NAME = "SyMAT 0.6"; - public static final double APP_CODE = 0.6; + public static final String APP_NAME = "SyMAT 0.7"; + public static final double APP_CODE = 0.7; public static String argfile = ""; + public static boolean skipPython = false; // Skip python init on start? /** * Creates new form MainGUI @@ -122,7 +122,6 @@ public class MainGUI extends javax.swing.JFrame { @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents private void initComponents() { - java.awt.GridBagConstraints gridBagConstraints; tabs = new javax.swing.JTabbedPane(); jPanel4 = new javax.swing.JPanel(); @@ -135,6 +134,7 @@ public class MainGUI extends javax.swing.JFrame { helpBtn = new javax.swing.JButton(); jLabel3 = new javax.swing.JLabel(); arrangeWindowsBtn = new javax.swing.JButton(); + closeAllBtn = new javax.swing.JButton(); jPanel3 = new javax.swing.JPanel(); jLabel4 = new javax.swing.JLabel(); displaySettingsBtn = new javax.swing.JButton(); @@ -155,7 +155,6 @@ public class MainGUI extends javax.swing.JFrame { setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setTitle(APP_NAME); setMinimumSize(new java.awt.Dimension(300, 400)); - setPreferredSize(new java.awt.Dimension(700, 575)); addComponentListener(new java.awt.event.ComponentAdapter() { public void componentShown(java.awt.event.ComponentEvent evt) { formComponentShown(evt); @@ -273,6 +272,19 @@ public class MainGUI extends javax.swing.JFrame { } }); + closeAllBtn.setIcon(new javax.swing.ImageIcon(getClass().getResource("/net/apocalypselabs/symat/closeall.png"))); // NOI18N + closeAllBtn.setText("Close All"); + closeAllBtn.setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 5, 5, 5)); + closeAllBtn.setFocusable(false); + closeAllBtn.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + closeAllBtn.setOpaque(false); + closeAllBtn.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM); + closeAllBtn.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + closeAllBtnActionPerformed(evt); + } + }); + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); jPanel2.setLayout(jPanel2Layout); jPanel2Layout.setHorizontalGroup( @@ -282,15 +294,17 @@ public class MainGUI extends javax.swing.JFrame { .addComponent(helpBtn) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(arrangeWindowsBtn) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(closeAllBtn) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jLabel3, javax.swing.GroupLayout.DEFAULT_SIZE, 555, Short.MAX_VALUE)) + .addComponent(jLabel3, javax.swing.GroupLayout.DEFAULT_SIZE, 492, Short.MAX_VALUE)) ); jPanel2Layout.setVerticalGroup( jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(helpBtn) - .addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(helpBtn) + .addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(arrangeWindowsBtn) + .addComponent(closeAllBtn) ); tabs.addTab("Tools", jPanel2); @@ -403,6 +417,16 @@ public class MainGUI extends javax.swing.JFrame { loadFrame(d); }//GEN-LAST:event_displaySettingsBtnActionPerformed + private void closeAllBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeAllBtnActionPerformed + for (JInternalFrame ji : mainPane.getAllFrames()) { + try { + ji.setClosed(true); + } catch (PropertyVetoException ex) { + ji.dispose(); + } + } + }//GEN-LAST:event_closeAllBtnActionPerformed + /** * Adds the given JInternalFrame to the mainPane. Automatically does layout * and sets visible as well. @@ -471,22 +495,27 @@ public class MainGUI extends javax.swing.JFrame { // + // Command line args + for (String arg : args) { + if (arg.equals("skippython")) { + skipPython = true; + } else { + argfile = args[0]; + } + } + /* Create and display the form */ java.awt.EventQueue.invokeLater(new Runnable() { @Override public void run() { - new MainGUI().setVisible(true); + new SplashScreen().setVisible(true); } }); - - // Trigger open passed script file - if (args.length == 1) { - argfile = args[0]; - } } // Variables declaration - do not modify//GEN-BEGIN:variables public static javax.swing.JButton arrangeWindowsBtn; + public static javax.swing.JButton closeAllBtn; public static javax.swing.JButton displaySettingsBtn; public static javax.swing.JButton editorBtn; public static javax.swing.JButton graphBtn; diff --git a/src/net/apocalypselabs/symat/SplashScreen.form b/src/net/apocalypselabs/symat/SplashScreen.form new file mode 100644 index 0000000..db0eefb --- /dev/null +++ b/src/net/apocalypselabs/symat/SplashScreen.form @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/net/apocalypselabs/symat/SplashScreen.java b/src/net/apocalypselabs/symat/SplashScreen.java new file mode 100644 index 0000000..c44282f --- /dev/null +++ b/src/net/apocalypselabs/symat/SplashScreen.java @@ -0,0 +1,123 @@ +/* + * Apocalypse Laboratories + * Open Source License + * + * Source code can be used for any purpose, as long as: + * - Compiled binaries are rebranded and trademarks are not + * visible by the end user at any time, except to give + * credit to Apocalypse Laboratories, such as by showing + * "Based on by Apocalypse Laboratories" or a + * similar notice; + * - You do not use the code for evil; + * - Rebranded compiled applications have significant + * differences in functionality; + * - and you provide your modified source code for download, + * under the terms of the GNU LGPL v3 or a comparable + * license. + * + * Compiled binaries cannot be redistributed or mirrored, + * unless: + * - You have written permission from Apocalypse Laboratories; + * - Downloads are not available from Apocalypse Laboratories, + * not even behind a paywall or other blocking mechanism; + * - or you have received a multi-computer license, in which + * case you should take measures to prevent unauthorized + * downloads, such as preventing download access from the + * Internet. + */ +package net.apocalypselabs.symat; + +import javax.swing.ImageIcon; + +/** + * + * @author Skylar + */ +public class SplashScreen extends javax.swing.JFrame { + + /** + * Creates new form SplashScreen + */ + public SplashScreen() { + initComponents(); + setIconImage((new ImageIcon(getClass().getResource("icon.png"))).getImage()); + setLocationRelativeTo(null); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jProgressBar1 = new javax.swing.JProgressBar(); + jLabel5 = new javax.swing.JLabel(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + setTitle(MainGUI.APP_NAME); + setMaximumSize(new java.awt.Dimension(320, 260)); + setMinimumSize(new java.awt.Dimension(320, 260)); + setResizable(false); + addComponentListener(new java.awt.event.ComponentAdapter() { + public void componentShown(java.awt.event.ComponentEvent evt) { + formComponentShown(evt); + } + }); + + jProgressBar1.setIndeterminate(true); + jProgressBar1.setMaximumSize(new java.awt.Dimension(32767, 20)); + jProgressBar1.setMinimumSize(new java.awt.Dimension(10, 20)); + jProgressBar1.setPreferredSize(new java.awt.Dimension(146, 20)); + + jLabel5.setIcon(new javax.swing.ImageIcon(getClass().getResource("/net/apocalypselabs/symat/splash.png"))); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jProgressBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jLabel5) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jLabel5) + .addGap(0, 0, 0) + .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + + pack(); + }// //GEN-END:initComponents + + private void formComponentShown(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentShown + new Loader().start(); + }//GEN-LAST:event_formComponentShown + + /** + * Load things that take a while. + */ + private class Loader extends Thread { + + @Override + public void run() { + if (!MainGUI.skipPython) { + // Python laggggsss when used for first time, this fixes the wait later. + System.out.println("Warming up Python engine, to skip run with argument 'skippython'"); + try { + CodeRunner python = new CodeRunner(true); + } catch (Exception ex) { + // Ignore + } + } + new MainGUI().setVisible(true); + dispose(); + } + } + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel5; + private javax.swing.JProgressBar jProgressBar1; + // End of variables declaration//GEN-END:variables +} diff --git a/src/net/apocalypselabs/symat/closeall.png b/src/net/apocalypselabs/symat/closeall.png new file mode 100644 index 0000000..8dbe367 Binary files /dev/null and b/src/net/apocalypselabs/symat/closeall.png differ diff --git a/src/net/apocalypselabs/symat/splash.png b/src/net/apocalypselabs/symat/splash.png new file mode 100644 index 0000000..99b4989 Binary files /dev/null and b/src/net/apocalypselabs/symat/splash.png differ