diff --git a/src/net/apocalypselabs/symat/CodeRunner.java b/src/net/apocalypselabs/symat/CodeRunner.java index 3a1ed9c..2769fa0 100644 --- a/src/net/apocalypselabs/symat/CodeRunner.java +++ b/src/net/apocalypselabs/symat/CodeRunner.java @@ -83,6 +83,7 @@ public class CodeRunner { // Add custom functions. se.eval("importClass(net.apocalypselabs.symat.Functions);" + "SyMAT_Functions = new net.apocalypselabs.symat.Functions();" + + "SyMAT_Functions.setLang('js');\n" + getFunctions("js")); // Allow engine access from scripts. se.put("engine", se); @@ -91,12 +92,14 @@ public class CodeRunner { } break; case "python": + case "jython": case "py": se = new ScriptEngineManager().getEngineByName("python"); try { se.eval("from math import *\n" + "from net.apocalypselabs.symat import Functions\n" - + "_=Functions()\n\n" + + "_=Functions()\n" + + "_.setLang('py')\n\n" + getFunctions("py")); // Allow engine access from scripts. se.put("engine", se); diff --git a/src/net/apocalypselabs/symat/Functions.java b/src/net/apocalypselabs/symat/Functions.java index 72f2547..4ec00aa 100644 --- a/src/net/apocalypselabs/symat/Functions.java +++ b/src/net/apocalypselabs/symat/Functions.java @@ -50,13 +50,17 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import static java.lang.Math.*; -import java.net.MalformedURLException; +import java.lang.reflect.Array; import java.net.URL; +import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.HashMap; -import java.util.logging.Level; -import java.util.logging.Logger; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; import javax.swing.JOptionPane; import static net.apocalypselabs.symat.Main.API_URL; import org.matheclipse.core.eval.EvalUtilities; @@ -77,6 +81,8 @@ public class Functions { private final EvalUtilities util = new EvalUtilities(true, true); Graph graphwin = new Graph(true); + private String lang = "py"; + /* Useful interactions */ @@ -263,6 +269,54 @@ public class Functions { return ans; } + /** + * Get all prime factors of input number. + * + * @param n An integer number. + * @return Array of primes. + * + * Thanks to + * http://www.javacodegeeks.com/2014/05/how-to-find-prime-factors-of-integer-numbers-in-java-factorization.html + * and http://stackoverflow.com/a/2451219/2534036 + */ + public long[] factor(long n) { + long i; + Set primes = new HashSet<>(); + long copyOfInput = n; + + for (i = 2; i <= copyOfInput; i++) { + if (copyOfInput % i == 0) { + primes.add(i); // prime factor + copyOfInput /= i; + i--; + } + } + long[] a = new long[primes.size()]; + int j = 0; + for (Object val : primes) { + a[j++] = (long) val; + } + return a; + } + + /** + * Get all unique permutations of the given array. + * @param objs Array of items. + * @return Matrix + */ + public Object[] perms(Object... objs) { + Permutations perm = new Permutations<>(objs); + + Set perms = new HashSet<>(); + + while (perm.hasNext()) { + perms.add(perm.next()); + } + + Object[][] a = new Object[perms.size()][objs.length]; + return perms.toArray(a); + } + /** * Multiply two matrices. * @@ -272,13 +326,18 @@ public class Functions { * @throws net.apocalypselabs.symat.BadInputException When the matrices are * wrong. */ - public double[][] mtimes(double[][] a, double[][] b) throws BadInputException { + public Object mtimes(double[][] a, double[][] b) throws BadInputException { + return tonativearray(mTimes(a, b)); + } + + private double[][] mTimes(double[][] a, double[][] b) throws BadInputException { double[][] ans = new double[a.length][b[0].length]; double sum = 0; int c, d, k, m = a.length, q = b[0].length, p = b.length; if (a[0].length != b.length) { - throw new BadInputException("First matrix column count must match second matrix row count."); + throw new BadInputException("First matrix column count must match " + + "second matrix row count."); } for (c = 0; c < m; c++) { @@ -302,7 +361,7 @@ public class Functions { * @throws BadInputException if the matrix is not square or power is less * than 0 */ - public double[][] mpower(double[][] a, int b) throws BadInputException { + public Object mpower(double[][] a, int b) throws BadInputException { if (a.length != a[0].length) { throw new BadInputException("Matrix needs to be square."); } @@ -316,9 +375,13 @@ public class Functions { if (i == 0) { ans = a; } else { - ans = mtimes(a, ans); + ans = mTimes(a, ans); } } + return tonativearray(ans); + } + + private double[][] tonativearray(double[][] ans) { return ans; } @@ -372,6 +435,7 @@ public class Functions { * Substitute newvar for variable in function and attempt to calculate a * numerical answer. *
Example: subs('32*x','x',2) = 64.0 + * * @param function Function * @param variable Variable to substitute * @param newvar Value to replace with @@ -383,6 +447,7 @@ public class Functions { /** * Attempt to find numerical value of input. + * * @param f Function * @return answer or zero if it doesn't exist */ @@ -603,4 +668,103 @@ public class Functions { public Functions() { Main.loadFrame(graphwin, false); } + + public void setLang(String l) { + lang = l; + } + + /** + * This class finds permutations of an array. + * + * Credit to http://stackoverflow.com/a/14444037/2534036 + * + * License: CC-BY-SA 3.0 + * + * @param + */ + class Permutations implements Iterator { + + private E[] arr; + private int[] ind; + private boolean has_next; + + public E[] output;//next() returns this array, make it public + + Permutations(E[] arr) { + this.arr = arr.clone(); + ind = new int[arr.length]; + //convert an array of any elements into array of integers - first occurrence is used to enumerate + Map hm = new HashMap(); + for (int i = 0; i < arr.length; i++) { + Integer n = hm.get(arr[i]); + if (n == null) { + hm.put(arr[i], i); + n = i; + } + ind[i] = n.intValue(); + } + Arrays.sort(ind);//start with ascending sequence of integers + + //output = new E[arr.length]; <-- cannot do in Java with generics, so use reflection + output = (E[]) Array.newInstance(arr.getClass().getComponentType(), arr.length); + has_next = true; + } + + @Override + public boolean hasNext() { + return has_next; + } + + /** + * Computes next permutations. Same array instance is returned every + * time! + * + * @return + */ + @Override + public E[] next() { + if (!has_next) { + throw new NoSuchElementException(); + } + + for (int i = 0; i < ind.length; i++) { + output[i] = arr[ind[i]]; + } + + //get next permutation + has_next = false; + for (int tail = ind.length - 1; tail > 0; tail--) { + if (ind[tail - 1] < ind[tail]) {//still increasing + + //find last element which does not exceed ind[tail-1] + int s = ind.length - 1; + while (ind[tail - 1] >= ind[s]) { + s--; + } + + swap(ind, tail - 1, s); + + //reverse order of elements in the tail + for (int i = tail, j = ind.length - 1; i < j; i++, j--) { + swap(ind, i, j); + } + has_next = true; + break; + } + + } + return output; + } + + private void swap(int[] arr, int i, int j) { + int t = arr[i]; + arr[i] = arr[j]; + arr[j] = t; + } + + @Override + public void remove() { + + } + } } diff --git a/src/net/apocalypselabs/symat/Main.java b/src/net/apocalypselabs/symat/Main.java index 85c2d78..703485a 100644 --- a/src/net/apocalypselabs/symat/Main.java +++ b/src/net/apocalypselabs/symat/Main.java @@ -66,6 +66,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Date; +import java.util.GregorianCalendar; import java.util.List; import javafx.application.Platform; import javax.swing.ImageIcon; @@ -94,7 +95,7 @@ public class Main extends JRibbonFrame { /** * Version name, as it should be displayed. */ - public static final String VERSION_NAME = "1.5"; + public static final String VERSION_NAME = "1.6"; /** * The word "SyMAT". @@ -107,7 +108,7 @@ public class Main extends JRibbonFrame { /** * Version number, for updates and //needs in scripts */ - public static final double APP_CODE = 17; + public static final double APP_CODE = 18; /** * Base URL for building API calls */ @@ -243,6 +244,16 @@ public class Main extends JRibbonFrame { if (!PrefStorage.getSetting("showrecent", "").equals("")) { recentItemsPanel.setVisible(false); } + + // Pi Day easter egg + GregorianCalendar piday = new GregorianCalendar(); + if ((piday.get(Calendar.MONTH) == 2) + && (piday.get(Calendar.DAY_OF_MONTH) == 14)) { + JOptionPane.showInternalMessageDialog(mainPane, + "Happy Pi Day from the SyMAT team!", + "3/14", + JOptionPane.PLAIN_MESSAGE); + } } /** @@ -304,15 +315,29 @@ public class Main extends JRibbonFrame { loadFrame(new Pads()); } }); + tasksbtn.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + loadFrame(new Tasks()); + } + }); - shellbtn.setPopupKeyTip("Open a window " - + "for running interactive commands."); - editorbtn.setPopupKeyTip("Write and run multiple-line scripts."); - graphbtn.setPopupKeyTip("Plot mathematical functions."); - notepadbtn.setPopupKeyTip("Write quick notes on a virtual napkin."); - wikibtn.setPopupKeyTip("View online documentation and tutorials."); - forumbtn.setPopupKeyTip("Discuss and share with the SyMAT community."); - padsbtn.setPopupKeyTip("Collaborate over the Internet on projects."); + shellbtn.setActionRichTooltip(new RichTooltip("Command Shell", + "Open a window for running interactive commands.")); + editorbtn.setActionRichTooltip(new RichTooltip("Code Editor", + "Write and run JavaScript and Python scripts.")); + graphbtn.setActionRichTooltip(new RichTooltip("Graph", + "Plot mathematical functions on a 2D graph.")); + notepadbtn.setActionRichTooltip(new RichTooltip("Notepad", + "Write quick notes on a virtual napkin.")); + wikibtn.setActionRichTooltip(new RichTooltip("SyMAT Wiki", + "View and edit online documentation and tutorials.")); + forumbtn.setActionRichTooltip(new RichTooltip("Support Forum", + "Discuss and share with the SyMAT community.")); + padsbtn.setActionRichTooltip(new RichTooltip("Code Pads", + "Collaborate over the Internet on projects.")); + tasksbtn.setActionRichTooltip(new RichTooltip("Task List", + "Manage tasks and to-do lists for projects.")); coreband.addCommandButton(shellbtn, RibbonElementPriority.TOP); coreband.addCommandButton(editorbtn, RibbonElementPriority.TOP); @@ -324,6 +349,7 @@ public class Main extends JRibbonFrame { webband.addCommandButton(forumbtn, RibbonElementPriority.LOW); collabband.addCommandButton(padsbtn, RibbonElementPriority.MEDIUM); + collabband.addCommandButton(tasksbtn, RibbonElementPriority.MEDIUM); coreband.setResizePolicies((List) Arrays.asList( new CoreRibbonResizePolicies.None(coreband.getControlPanel()), @@ -460,9 +486,9 @@ public class Main extends JRibbonFrame { if (recent == null) { RibbonApplicationMenuEntrySecondary blanksubbtn - = new RibbonApplicationMenuEntrySecondary( - null, "No recent files", null, - JCommandButton.CommandButtonKind.ACTION_ONLY); + = new RibbonApplicationMenuEntrySecondary( + null, "No recent files", null, + JCommandButton.CommandButtonKind.ACTION_ONLY); blanksubbtn.setEnabled(false); openbtn.addSecondaryMenuGroup("Recent Files", blanksubbtn); } else { @@ -564,6 +590,7 @@ public class Main extends JRibbonFrame { /** * Add a file to the recent files lists. + * * @param file The file path. */ public static void addRecentFile(String file) { @@ -947,6 +974,8 @@ public class Main extends JRibbonFrame { = new JCommandButton("Forum", getRibbonIcon("forum")); public static JCommandButton padsbtn = new JCommandButton("Pads", getRibbonIcon("pads")); + public static JCommandButton tasksbtn + = new JCommandButton("Tasks", getRibbonIcon("tasks")); public static RibbonApplicationMenuEntryPrimary openbtn; // Variables declaration - do not modify//GEN-BEGIN:variables diff --git a/src/net/apocalypselabs/symat/Tasks.form b/src/net/apocalypselabs/symat/Tasks.form new file mode 100644 index 0000000..d44f13f --- /dev/null +++ b/src/net/apocalypselabs/symat/Tasks.form @@ -0,0 +1,74 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/net/apocalypselabs/symat/Tasks.java b/src/net/apocalypselabs/symat/Tasks.java new file mode 100644 index 0000000..c5a81b9 --- /dev/null +++ b/src/net/apocalypselabs/symat/Tasks.java @@ -0,0 +1,136 @@ +/* + * CODE LICENSE ===================== + * Copyright (c) 2015, Apocalypse Laboratories + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * 4. You adhere to the Media License detailed below. If you do not, this license + * is automatically revoked and you must purge all copies of the software you + * possess, in source or binary form. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * MEDIA LICENSE ==================== + * All images and other graphical files (the "graphics") included with this + * software are copyright (c) 2015 Apocalypse Laboratories. You may not distribute + * the graphics or any program, source code repository, or other digital storage + * media containing them without written permission from Apocalypse Laboratories. + * This ban on distribution only applies to publicly available systems. + * A password-protected network file share, USB drive, or other storage scheme that + * cannot be easily accessed by the public is generally allowed. If in doubt, + * contact Apocalypse Laboratories. If Apocalypse Laboratories allows or denies + * you permission, that decision is considered final and binding. + */ +package net.apocalypselabs.symat; + +import net.apocalypselabs.symat.components.Task; + +/** + * + * @author Skylar + */ +public class Tasks extends javax.swing.JInternalFrame { + + /** + * Creates new form Tasks + */ + public Tasks() { + initComponents(); + } + + /** + * 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() { + + taskList = new javax.swing.JScrollPane(); + listPanel = new javax.swing.JPanel(); + jMenuBar1 = new javax.swing.JMenuBar(); + jMenu1 = new javax.swing.JMenu(); + jMenuItem1 = new javax.swing.JMenuItem(); + + setClosable(true); + setIconifiable(true); + setMaximizable(true); + setResizable(true); + setTitle("Tasks"); + + listPanel.setLayout(new javax.swing.BoxLayout(listPanel, javax.swing.BoxLayout.Y_AXIS)); + taskList.setViewportView(listPanel); + + jMenu1.setText("File"); + + jMenuItem1.setText("Sample"); + jMenuItem1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jMenuItem1ActionPerformed(evt); + } + }); + jMenu1.add(jMenuItem1); + + jMenuBar1.add(jMenu1); + + setJMenuBar(jMenuBar1); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(taskList, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 394, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(taskList, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 257, Short.MAX_VALUE) + ); + + pack(); + }// //GEN-END:initComponents + + private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem1ActionPerformed + for (int i = 1; i <= 5; i++) { + Task t = new Task( + (i % 2 == 0), + "Name " + i, + "Description " + i); + listPanel.add(t); + t.setVisible(true); + } + setSize(getWidth() + 1, getHeight()); + setSize(getWidth() - 1, getHeight()); + }//GEN-LAST:event_jMenuItem1ActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JMenu jMenu1; + private javax.swing.JMenuBar jMenuBar1; + private javax.swing.JMenuItem jMenuItem1; + private javax.swing.JPanel listPanel; + private javax.swing.JScrollPane taskList; + // End of variables declaration//GEN-END:variables +} diff --git a/src/net/apocalypselabs/symat/components/Task.form b/src/net/apocalypselabs/symat/components/Task.form new file mode 100644 index 0000000..579a57e --- /dev/null +++ b/src/net/apocalypselabs/symat/components/Task.form @@ -0,0 +1,81 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/net/apocalypselabs/symat/components/Task.java b/src/net/apocalypselabs/symat/components/Task.java new file mode 100644 index 0000000..9592d5a --- /dev/null +++ b/src/net/apocalypselabs/symat/components/Task.java @@ -0,0 +1,159 @@ +/* + * CODE LICENSE ===================== + * Copyright (c) 2015, Apocalypse Laboratories + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * 4. You adhere to the Media License detailed below. If you do not, this license + * is automatically revoked and you must purge all copies of the software you + * possess, in source or binary form. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * MEDIA LICENSE ==================== + * All images and other graphical files (the "graphics") included with this + * software are copyright (c) 2015 Apocalypse Laboratories. You may not distribute + * the graphics or any program, source code repository, or other digital storage + * media containing them without written permission from Apocalypse Laboratories. + * This ban on distribution only applies to publicly available systems. + * A password-protected network file share, USB drive, or other storage scheme that + * cannot be easily accessed by the public is generally allowed. If in doubt, + * contact Apocalypse Laboratories. If Apocalypse Laboratories allows or denies + * you permission, that decision is considered final and binding. + */ +package net.apocalypselabs.symat.components; + +import javax.swing.ImageIcon; +import javax.swing.JOptionPane; + +/** + * + * @author Skylar + */ +public class Task extends javax.swing.JPanel { + + private boolean taskDone = false; + + public Task(boolean complete, String name, String desc) { + this(); + taskDone = complete; + setComplete(complete); + taskName.setText(name); + taskDesc.setText(desc); + } + + /** + * Creates new form Task + */ + public Task() { + initComponents(); + } + + private void setComplete(boolean b) { + statusLabel.setIcon(new ImageIcon( + getClass().getResource( + "/net/apocalypselabs/symat/icons/" + + (b ? "green" : "red") + "light.png" + ))); + statusLabel.setToolTipText(b ? "Complete" : "Incomplete"); + } + + /** + * 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() { + + taskName = new javax.swing.JLabel(); + taskDesc = new javax.swing.JLabel(); + menuBtn = new javax.swing.JButton(); + statusLabel = new javax.swing.JLabel(); + + taskName.setFont(net.apocalypselabs.symat.Main.ubuntuRegular.deriveFont(20.0F)); + taskName.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); + taskName.setText("Unnamed task"); + + taskDesc.setFont(net.apocalypselabs.symat.Main.ubuntuRegular.deriveFont(12.0F)); + taskDesc.setText("No description"); + taskDesc.setVerticalAlignment(javax.swing.SwingConstants.TOP); + + menuBtn.setText("Menu"); + menuBtn.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + menuBtnActionPerformed(evt); + } + }); + + statusLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/net/apocalypselabs/symat/icons/redlight.png"))); // NOI18N + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(statusLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(taskName, javax.swing.GroupLayout.DEFAULT_SIZE, 262, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(menuBtn)) + .addComponent(taskDesc, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(menuBtn) + .addGap(0, 7, Short.MAX_VALUE)) + .addComponent(taskName, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(statusLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(taskDesc, javax.swing.GroupLayout.DEFAULT_SIZE, 38, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + private void menuBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuBtnActionPerformed + TaskMenu tm = new TaskMenu(taskDone, + taskName.getText(), + taskDesc.getText()); + JOptionPane.showInternalMessageDialog(this, tm, + "Task Options", JOptionPane.PLAIN_MESSAGE); + taskDone = tm.isComplete(); + setComplete(taskDone); + taskName.setText(tm.toString()); + taskDesc.setText(tm.getDesc()); + }//GEN-LAST:event_menuBtnActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton menuBtn; + private javax.swing.JLabel statusLabel; + private javax.swing.JLabel taskDesc; + private javax.swing.JLabel taskName; + // End of variables declaration//GEN-END:variables +} diff --git a/src/net/apocalypselabs/symat/components/TaskMenu.form b/src/net/apocalypselabs/symat/components/TaskMenu.form new file mode 100644 index 0000000..4275bec --- /dev/null +++ b/src/net/apocalypselabs/symat/components/TaskMenu.form @@ -0,0 +1,81 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/net/apocalypselabs/symat/components/TaskMenu.java b/src/net/apocalypselabs/symat/components/TaskMenu.java new file mode 100644 index 0000000..02f70ec --- /dev/null +++ b/src/net/apocalypselabs/symat/components/TaskMenu.java @@ -0,0 +1,162 @@ +/* + * CODE LICENSE ===================== + * Copyright (c) 2015, Apocalypse Laboratories + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * 4. You adhere to the Media License detailed below. If you do not, this license + * is automatically revoked and you must purge all copies of the software you + * possess, in source or binary form. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * MEDIA LICENSE ==================== + * All images and other graphical files (the "graphics") included with this + * software are copyright (c) 2015 Apocalypse Laboratories. You may not distribute + * the graphics or any program, source code repository, or other digital storage + * media containing them without written permission from Apocalypse Laboratories. + * This ban on distribution only applies to publicly available systems. + * A password-protected network file share, USB drive, or other storage scheme that + * cannot be easily accessed by the public is generally allowed. If in doubt, + * contact Apocalypse Laboratories. If Apocalypse Laboratories allows or denies + * you permission, that decision is considered final and binding. + */ +package net.apocalypselabs.symat.components; + +/** + * + * @author Skylar + */ +public class TaskMenu extends javax.swing.JPanel { + + /** + * Creates new TaskMenu + * @param complete If the task is completed. + * @param name Task name + * @param desc Task description + */ + public TaskMenu(boolean complete, String name, String desc) { + this(); + completeBox.setSelected(complete); + nameBox.setText(name); + descBox.setText(desc); + } + + /** + * Creates new TaskMenu + */ + public TaskMenu() { + initComponents(); + } + + /** + * Check if the task is marked as done. + * @return true if it is. + */ + public boolean isComplete() { + return completeBox.isSelected(); + } + + /** + * Get the name of the task. + * @return Task name. + */ + @Override + public String toString() { + return nameBox.getText(); + } + + /** + * Get the task description. + * @return The description. + */ + public String getDesc() { + return descBox.getText(); + } + + /** + * 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() { + + completeBox = new javax.swing.JCheckBox(); + nameBox = new javax.swing.JTextField(); + jLabel1 = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + jScrollPane1 = new javax.swing.JScrollPane(); + descBox = new javax.swing.JTextArea(); + + completeBox.setText("Task complete"); + + jLabel1.setText("Task Name:"); + + jLabel2.setText("Task Description:"); + + descBox.setColumns(20); + descBox.setRows(5); + jScrollPane1.setViewportView(descBox); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(nameBox) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel1) + .addComponent(completeBox) + .addComponent(jLabel2)) + .addGap(0, 0, Short.MAX_VALUE)) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 200, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(completeBox) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(nameBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 107, Short.MAX_VALUE)) + ); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JCheckBox completeBox; + private javax.swing.JTextArea descBox; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTextField nameBox; + // End of variables declaration//GEN-END:variables +} diff --git a/src/net/apocalypselabs/symat/functions.js b/src/net/apocalypselabs/symat/functions.js index e69de29..1c986f3 100644 --- a/src/net/apocalypselabs/symat/functions.js +++ b/src/net/apocalypselabs/symat/functions.js @@ -0,0 +1,3 @@ +function mprint(m) { + return JSON.stringify(m); +} \ No newline at end of file diff --git a/src/net/apocalypselabs/symat/functions.py b/src/net/apocalypselabs/symat/functions.py index 3183acc..a4917be 100644 --- a/src/net/apocalypselabs/symat/functions.py +++ b/src/net/apocalypselabs/symat/functions.py @@ -33,4 +33,18 @@ def vpa(expr): def readfile(path): return _.readfile(path) def savefile(data,path): - _.savefile(data,path) \ No newline at end of file + _.savefile(data,path) +def mtimes(a,b): + return _.mtimes(a,b) +def mpower(a,b): + return _.mpower(a,b) +def add(*a): + return _.add(a) +def subtract(*a): + return _.subtract(a) +def times(*a): + return _.times(a) +def divide(*a): + return _.divide(a) +def mod(*a): + return _.mod(a) \ No newline at end of file diff --git a/src/net/apocalypselabs/symat/icons/greenlight.png b/src/net/apocalypselabs/symat/icons/greenlight.png new file mode 100644 index 0000000..0113c8f Binary files /dev/null and b/src/net/apocalypselabs/symat/icons/greenlight.png differ diff --git a/src/net/apocalypselabs/symat/icons/redlight.png b/src/net/apocalypselabs/symat/icons/redlight.png new file mode 100644 index 0000000..4842485 Binary files /dev/null and b/src/net/apocalypselabs/symat/icons/redlight.png differ diff --git a/src/net/apocalypselabs/symat/images/tasks.png b/src/net/apocalypselabs/symat/images/tasks.png new file mode 100644 index 0000000..e08938a Binary files /dev/null and b/src/net/apocalypselabs/symat/images/tasks.png differ