├── .gitignore ├── LICENSE ├── README.md ├── libs ├── core.jar ├── gluegen-rt-natives-linux-amd64.jar ├── gluegen-rt-natives-linux-armv6hf.jar ├── gluegen-rt-natives-linux-i586.jar ├── gluegen-rt-natives-macosx-universal.jar ├── gluegen-rt-natives-windows-amd64.jar ├── gluegen-rt-natives-windows-i586.jar ├── gluegen-rt.jar ├── jogl-all-natives-linux-amd64.jar ├── jogl-all-natives-linux-armv6hf.jar ├── jogl-all-natives-linux-i586.jar ├── jogl-all-natives-macosx-universal.jar ├── jogl-all-natives-windows-amd64.jar ├── jogl-all-natives-windows-i586.jar └── jogl-all.jar ├── misc └── screenshots │ └── jas_simple_ui.png └── src ├── CAS.java ├── CasCmdline.java ├── CasController.java ├── JGrapher.java ├── cas.fxml ├── jas ├── Function.java ├── MathContext.java ├── core │ ├── Assets.java │ ├── BinLeafNode.java │ ├── Calculus.java │ ├── Compiler.java │ ├── Evaluable.java │ ├── JASException.java │ ├── LeafNode.java │ ├── Mode.java │ ├── Nameable.java │ ├── Node.java │ ├── components │ │ ├── Constants.java │ │ ├── Fraction.java │ │ ├── List.java │ │ ├── Literal.java │ │ ├── Matrix.java │ │ ├── RawValue.java │ │ ├── Variable.java │ │ └── Vector.java │ └── operations │ │ ├── Argument.java │ │ ├── Binary.java │ │ ├── Custom.java │ │ ├── Manipulable.java │ │ ├── Manipulation.java │ │ ├── Operation.java │ │ ├── Signature.java │ │ └── Unary.java ├── extras │ └── Element.java ├── graph │ ├── Graph.java │ ├── GraphFunction.java │ ├── Plot.java │ ├── Point.java │ ├── Range.java │ └── SuppliedVar.java └── utils │ ├── AnsiColor.java │ ├── ColorFormatter.java │ ├── Timer.java │ └── Utils.java ├── jui ├── Button.java ├── Canvas.java ├── Chart.java ├── Container.java ├── Contextual.java ├── Controllable.java ├── Displayable.java ├── Event.java ├── EventListener.java ├── HBox.java ├── HChart.java ├── HItemBar.java ├── HSlider.java ├── Image.java ├── ItemBar.java ├── JNode.java ├── KeyControl.java ├── Label.java ├── MenuBar.java ├── MenuDropdown.java ├── MenuItem.java ├── Mode.java ├── MouseControl.java ├── ProgressBar.java ├── Scalable.java ├── ScrollField.java ├── Slider.java ├── SpaceHolder.java ├── Switch.java ├── Table.java ├── TextField.java ├── TextInput.java ├── VBox.java ├── VChart.java ├── VItemBar.java ├── VSlider.java ├── bundles │ ├── ColorSelector.java │ ├── EnumSelector.java │ ├── ProgressIndicator.java │ ├── ValueCollector.java │ └── ValueSelector.java └── customization │ ├── default │ ├── random │ ├── tardis_blue │ └── theme_blue └── tests ├── AutoTest.java ├── SpeedTest.java ├── TestPrint.java ├── cas ├── Benchmark.java ├── CasComprehensiveTest.java ├── CasExpansionTest.java ├── CasSimplificationTest.java └── FirstDerivativeTest.java ├── files ├── additional │ ├── bin_ops.txt │ ├── irr_num.txt │ ├── u_der.txt │ └── u_ops.txt ├── beautify │ ├── bin_ops.txt │ ├── irr_num.txt │ ├── u_der.txt │ └── u_ops.txt ├── bin_ops.txt ├── complexity │ ├── bin_ops.txt │ ├── irr_num.txt │ ├── u_der.txt │ └── u_ops.txt ├── expansion │ ├── bin_ops.txt │ ├── irr_num.txt │ ├── u_der.txt │ └── u_ops.txt ├── exponential │ ├── bin_ops.txt │ ├── irr_num.txt │ ├── u_der.txt │ └── u_ops.txt ├── irr_num.txt ├── nodes │ ├── bin_ops.txt │ ├── irr_num.txt │ ├── u_der.txt │ └── u_ops.txt ├── simplest │ ├── bin_ops.txt │ ├── irr_num.txt │ ├── u_der.txt │ └── u_ops.txt ├── simplification │ ├── bin_ops.txt │ ├── irr_num.txt │ ├── u_der.txt │ └── u_ops.txt ├── u_der.txt └── u_ops.txt └── specific ├── BinaryOperationTest.java ├── CustomOperationTest.java ├── FractionTest.java ├── GraphTest.java ├── LiteralTest.java ├── MathContextTest.java ├── NodeTest.java ├── RawValueTest.java └── UnaryOperationTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .idea/* 3 | hs_err* 4 | out 5 | out/* 6 | .DS_Store 7 | */.DS_Store 8 | lib 9 | lib/* 10 | 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Jiachen Ren 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /libs/core.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachenRen/java-algebra-system/573924b802ca72eb29b20205756862cef4fa6de1/libs/core.jar -------------------------------------------------------------------------------- /libs/gluegen-rt-natives-linux-amd64.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachenRen/java-algebra-system/573924b802ca72eb29b20205756862cef4fa6de1/libs/gluegen-rt-natives-linux-amd64.jar -------------------------------------------------------------------------------- /libs/gluegen-rt-natives-linux-armv6hf.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachenRen/java-algebra-system/573924b802ca72eb29b20205756862cef4fa6de1/libs/gluegen-rt-natives-linux-armv6hf.jar -------------------------------------------------------------------------------- /libs/gluegen-rt-natives-linux-i586.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachenRen/java-algebra-system/573924b802ca72eb29b20205756862cef4fa6de1/libs/gluegen-rt-natives-linux-i586.jar -------------------------------------------------------------------------------- /libs/gluegen-rt-natives-macosx-universal.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachenRen/java-algebra-system/573924b802ca72eb29b20205756862cef4fa6de1/libs/gluegen-rt-natives-macosx-universal.jar -------------------------------------------------------------------------------- /libs/gluegen-rt-natives-windows-amd64.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachenRen/java-algebra-system/573924b802ca72eb29b20205756862cef4fa6de1/libs/gluegen-rt-natives-windows-amd64.jar -------------------------------------------------------------------------------- /libs/gluegen-rt-natives-windows-i586.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachenRen/java-algebra-system/573924b802ca72eb29b20205756862cef4fa6de1/libs/gluegen-rt-natives-windows-i586.jar -------------------------------------------------------------------------------- /libs/gluegen-rt.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachenRen/java-algebra-system/573924b802ca72eb29b20205756862cef4fa6de1/libs/gluegen-rt.jar -------------------------------------------------------------------------------- /libs/jogl-all-natives-linux-amd64.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachenRen/java-algebra-system/573924b802ca72eb29b20205756862cef4fa6de1/libs/jogl-all-natives-linux-amd64.jar -------------------------------------------------------------------------------- /libs/jogl-all-natives-linux-armv6hf.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachenRen/java-algebra-system/573924b802ca72eb29b20205756862cef4fa6de1/libs/jogl-all-natives-linux-armv6hf.jar -------------------------------------------------------------------------------- /libs/jogl-all-natives-linux-i586.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachenRen/java-algebra-system/573924b802ca72eb29b20205756862cef4fa6de1/libs/jogl-all-natives-linux-i586.jar -------------------------------------------------------------------------------- /libs/jogl-all-natives-macosx-universal.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachenRen/java-algebra-system/573924b802ca72eb29b20205756862cef4fa6de1/libs/jogl-all-natives-macosx-universal.jar -------------------------------------------------------------------------------- /libs/jogl-all-natives-windows-amd64.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachenRen/java-algebra-system/573924b802ca72eb29b20205756862cef4fa6de1/libs/jogl-all-natives-windows-amd64.jar -------------------------------------------------------------------------------- /libs/jogl-all-natives-windows-i586.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachenRen/java-algebra-system/573924b802ca72eb29b20205756862cef4fa6de1/libs/jogl-all-natives-windows-i586.jar -------------------------------------------------------------------------------- /libs/jogl-all.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachenRen/java-algebra-system/573924b802ca72eb29b20205756862cef4fa6de1/libs/jogl-all.jar -------------------------------------------------------------------------------- /misc/screenshots/jas_simple_ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiachenRen/java-algebra-system/573924b802ca72eb29b20205756862cef4fa6de1/misc/screenshots/jas_simple_ui.png -------------------------------------------------------------------------------- /src/CAS.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | import javafx.application.Application; 4 | import javafx.beans.property.SimpleStringProperty; 5 | import javafx.fxml.FXMLLoader; 6 | import javafx.scene.Parent; 7 | import javafx.scene.Scene; 8 | import javafx.stage.Stage; 9 | import jas.core.*; 10 | import jas.core.Compiler; 11 | import jas.core.Node; 12 | import jas.core.operations.Operation; 13 | 14 | import java.util.NoSuchElementException; 15 | 16 | /** 17 | * Created by Jiachen on 3/2/18. 18 | * JMC Computer Algebra System user interface model 19 | */ 20 | public class CAS extends Application { 21 | 22 | public static void main(String[] args) { 23 | launch(args); 24 | } 25 | 26 | @Override 27 | public void start(Stage primaryStage) throws Exception { 28 | FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("cas.fxml")); 29 | Parent root = fxmlLoader.load(); 30 | CasController controller = fxmlLoader.getController(); 31 | 32 | SimpleStringProperty expression = new SimpleStringProperty(""); 33 | expression.bind(controller.input.textProperty()); 34 | expression.addListener((observable, oldValue, newValue) -> { 35 | try { 36 | Node node = Compiler.compile(newValue); 37 | String addExp = ""; 38 | if (node instanceof Operation) { 39 | Operation operation = (Operation) node; 40 | addExp = operation.copy().toAdditionOnly().toExponentialForm().toString(); 41 | } 42 | controller.additionOnlyExp.setText(addExp); 43 | 44 | int nodes1 = node.numNodes(), complexity1 = node.complexity(); 45 | controller.nodesBefore.setText(String.valueOf(nodes1)); 46 | controller.complexityBefore.setText(String.valueOf(complexity1)); 47 | 48 | node = node.simplify(); 49 | controller.simplified.setText(node.toString()); //should conform to MVC, setText should be in controller. 50 | 51 | controller.expanded.setText(node.copy().expand().simplify().beautify().toString()); 52 | 53 | node = node.beautify(); 54 | controller.beautified.setText(node.toString()); 55 | 56 | try { 57 | controller.vars.setText(node.extractVariables() 58 | .stream().map(Nameable::getName) 59 | .reduce((a, b) -> a + ", " + b).get()); 60 | } catch (NoSuchElementException e) { 61 | controller.vars.setText("None"); 62 | } 63 | 64 | 65 | controller.val.setText(String.valueOf(node.val())); 66 | 67 | controller.complexityAfter.setText(String.valueOf(node.complexity())); 68 | controller.nodesAfter.setText(String.valueOf(node.numNodes())); 69 | controller.errMsg.setText("\"\""); 70 | } catch (JASException e) { 71 | controller.error(e.getMessage()); 72 | } 73 | }); 74 | primaryStage.setTitle("JMC Computer Algebra System"); 75 | primaryStage.setScene(new Scene(root, 400, 400)); 76 | primaryStage.setMinHeight(400); 77 | primaryStage.setMinWidth(400); 78 | primaryStage.show(); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/CasCmdline.java: -------------------------------------------------------------------------------- 1 | import jas.core.Compiler; 2 | import jas.core.JASException; 3 | 4 | import java.util.Scanner; 5 | 6 | import static jas.utils.ColorFormatter.*; 7 | import static tests.TestPrint.l; 8 | import static tests.TestPrint.p; 9 | 10 | /** 11 | * Created by Jiachen on 3/2/18. 12 | * JMC Computer Algebra System commandline application 13 | */ 14 | public class CasCmdline { 15 | public static void main(String args[]) { 16 | System.out.println("Welcome to Java Algebra System (JAS)\nDesigned by Jiachen Ren\nMIT licensed (c) 2018\n"); 17 | Scanner scanner = new Scanner(System.in); 18 | while (true) { 19 | p(boldBlack("\t: ")); 20 | String input = scanner.nextLine(); 21 | if (input.equals("exit")) return; 22 | try { 23 | l(boldBlack("\t= ") + Compiler.compile(input).simplify().coloredString() + "\n"); 24 | } catch (JASException e) { 25 | l(lightBlue("\t> ") + lightRed(e.getMessage()) + "\n"); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/CasController.java: -------------------------------------------------------------------------------- 1 | import javafx.application.Platform; 2 | import javafx.event.ActionEvent; 3 | import javafx.scene.control.Label; 4 | import javafx.scene.control.TextField; 5 | import javafx.scene.input.KeyEvent; 6 | 7 | /** 8 | * Created by Jiachen on 3/2/18. 9 | * CAS Controller 10 | */ 11 | public class CasController { 12 | 13 | 14 | public Label simplified; 15 | public TextField input; 16 | public Label beautified; 17 | public Label additionOnlyExp; 18 | public Label nodesBefore; 19 | public Label complexityBefore; 20 | public Label complexityAfter; 21 | public Label nodesAfter; 22 | public Label errMsg; 23 | public Label val; 24 | public Label vars; 25 | public Label expanded; 26 | 27 | @SuppressWarnings("unused") 28 | public void textFieldInput(KeyEvent keyEvent) { 29 | // System.out.println(keyEvent.getEventType()); 30 | simplified.setVisible(true); 31 | beautified.setVisible(true); 32 | additionOnlyExp.setVisible(true); 33 | nodesBefore.setVisible(true); 34 | complexityBefore.setVisible(true); 35 | complexityAfter.setVisible(true); 36 | nodesAfter.setVisible(true); 37 | errMsg.setVisible(true); 38 | val.setVisible(true); 39 | vars.setVisible(true); 40 | expanded.setVisible(true); 41 | // System.out.println(input.textProperty().get()); 42 | // System.out.println(input.textProperty().get()); 43 | } 44 | 45 | public void launchJGrapher(ActionEvent actionEvent) { 46 | System.out.println(actionEvent); 47 | Platform.runLater(() -> JGrapher.main(new String[]{"processing.awt.PGraphicsJava2D"})); 48 | } 49 | 50 | void error(String msg) { 51 | String str = "..."; 52 | // this.addition.setText(str); 53 | // this.exponential.setText(str); 54 | this.nodesBefore.setText(str); 55 | this.complexityBefore.setText(str); 56 | // this.simplified.setText(str); 57 | // this.beautified.setText(str); 58 | this.complexityAfter.setText(str); 59 | this.nodesAfter.setText(str); 60 | errMsg.setText(msg); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/jas/Function.java: -------------------------------------------------------------------------------- 1 | package jas; 2 | 3 | import jas.core.Evaluable; 4 | import jas.core.Nameable; 5 | 6 | import java.util.ArrayList; 7 | 8 | /** 9 | * Created by Jiachen on 3/2/18. 10 | * Function class 11 | */ 12 | public class Function implements Evaluable, Nameable { 13 | 14 | private String name; 15 | private Evaluable evaluable; 16 | 17 | public Function(Evaluable evaluable) { 18 | this("", evaluable); 19 | } 20 | 21 | public Function(String name, Evaluable evaluable) { 22 | setName(name); 23 | this.evaluable = evaluable; 24 | } 25 | 26 | /** 27 | * This is an abstract method to be defined by the anonymous subclass of GraphFunction; the definition 28 | * of the subclass fro this method should properly define how the function is going to be 29 | * evaluated. 30 | * 31 | * @param val the value that is going to be plugged into this GraphFunction for evaluation 32 | * @return the result gained from the evaluation with val and this GraphFunction instance's definition. 33 | */ 34 | public double eval(double val) { 35 | return evaluable.eval(val); 36 | } 37 | 38 | public boolean equals(Function other) { 39 | return this.getName().equals(other.getName()); 40 | } 41 | 42 | public String getName() { 43 | return name; 44 | } 45 | 46 | public Function setName(String name) { 47 | this.name = name; 48 | return this; 49 | } 50 | 51 | public ArrayList numericalSolve(double y, double lowerBound, double upperBound, double accuracy) { 52 | return numericalSolve(y, lowerBound, upperBound, accuracy, 1000); 53 | } 54 | 55 | protected ArrayList numericalSolve(double y, double lowerBound, double upperBound, double accuracy, int steps) { 56 | if (Math.abs(upperBound - lowerBound) <= accuracy) { 57 | ArrayList results = new ArrayList<>(); 58 | double solution = (lowerBound + upperBound) / 2; 59 | results.add(solution); 60 | return results; 61 | } 62 | ArrayList solutions = new ArrayList<>(); 63 | double stepVal = (upperBound - lowerBound) / steps; 64 | boolean isAbove = this.eval(lowerBound) > y; 65 | for (double i = lowerBound + stepVal; i <= upperBound; i += stepVal) { 66 | double cur = this.eval(i); 67 | if (cur > y ^ isAbove) { 68 | isAbove = cur > y; 69 | solutions.addAll(numericalSolve(y, i - stepVal, i, accuracy, steps)); 70 | } 71 | } 72 | return solutions; 73 | } 74 | 75 | public Evaluable getEvaluable() { 76 | return evaluable; 77 | } 78 | 79 | public Function setEvaluable(Evaluable evaluable) { 80 | this.evaluable = evaluable; 81 | return this; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/jas/core/Assets.java: -------------------------------------------------------------------------------- 1 | package jas.core; 2 | 3 | 4 | import jas.Function; 5 | import jas.core.operations.Binary; 6 | import jas.core.operations.Custom; 7 | import jas.core.operations.Manipulation; 8 | import jas.core.operations.Unary; 9 | 10 | import java.util.ArrayList; 11 | import java.util.stream.Collectors; 12 | 13 | /** 14 | * Created by Jiachen on 3/2/18. 15 | * Assets 16 | */ 17 | public interface Assets { 18 | String DIGITS = "0123456789."; 19 | String VARS = "abcdfghjklmnopqrstuvwxyz_"; 20 | String LETTERS = "abcdefghijklmnopqrstuvwxyz"; 21 | 22 | static String operators() { 23 | return Binary.operators(); 24 | } 25 | 26 | static String symbols() { 27 | return operators() + ",()<>'"; 28 | } 29 | 30 | static boolean isSymbol(char c) { 31 | return symbols().contains(Character.toString(c)); 32 | } 33 | 34 | static boolean isValidVarName(String s) { 35 | if (s.isEmpty()) { 36 | return false; 37 | } 38 | if (!Character.isJavaIdentifierStart(s.charAt(0))) { 39 | return false; 40 | } 41 | for (int i = 1; i < s.length(); i++) { 42 | if (!Character.isJavaIdentifierPart(s.charAt(i))) { 43 | return false; 44 | } 45 | } 46 | return true; 47 | } 48 | 49 | static ArrayList reservedNames() { 50 | ArrayList names = new ArrayList<>(); 51 | names.addAll(Unary.registeredOperations().stream() 52 | .map(Function::getName) 53 | .collect(Collectors.toCollection(ArrayList::new))); 54 | names.addAll(Custom.registeredManipulations().stream() 55 | .map(Manipulation::getName) 56 | .collect(Collectors.toCollection(ArrayList::new))); 57 | names.add("list"); 58 | return names; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/jas/core/BinLeafNode.java: -------------------------------------------------------------------------------- 1 | package jas.core; 2 | 3 | /** 4 | * Created by Jiachen on 3/4/18. 5 | * BinLeafNode: classes that are not BinaryOperations. Just a tag. 6 | */ 7 | public interface BinLeafNode { 8 | } 9 | -------------------------------------------------------------------------------- /src/jas/core/Calculus.java: -------------------------------------------------------------------------------- 1 | package jas.core; 2 | 3 | /** 4 | * Created by Jiachen on 3/17/18. 5 | * Calculus 6 | */ 7 | public class Calculus { 8 | public static final String DERIVATIVE = "derivative"; 9 | public static final String SUM = "sum"; 10 | } 11 | -------------------------------------------------------------------------------- /src/jas/core/Evaluable.java: -------------------------------------------------------------------------------- 1 | package jas.core; 2 | 3 | /** 4 | * Created by Jiachen on 20/05/2017. 5 | * Evaluable 6 | */ 7 | public interface Evaluable { 8 | double eval(double x); 9 | } 10 | -------------------------------------------------------------------------------- /src/jas/core/JASException.java: -------------------------------------------------------------------------------- 1 | package jas.core; 2 | 3 | /** 4 | * Created by Jiachen on 3/10/18. 5 | * JMC Exception 6 | */ 7 | public class JASException extends RuntimeException { 8 | public JASException(String msg) { 9 | super(msg); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/jas/core/LeafNode.java: -------------------------------------------------------------------------------- 1 | package jas.core; 2 | 3 | /** 4 | * Created by Jiachen on 3/10/18. 5 | * Leaf Node: super class of Variable and RawValue 6 | */ 7 | public abstract class LeafNode extends Node implements BinLeafNode { 8 | public abstract Node copy(); 9 | 10 | public int levelOf(Node o) { 11 | return this.equals(o) ? 0 : -1; 12 | } 13 | 14 | public abstract String toString(); 15 | 16 | public int numNodes() { 17 | return 1; 18 | } 19 | 20 | // public abstract Node firstDerivative(); 21 | 22 | public abstract int complexity(); 23 | 24 | public Node beautify() { 25 | return this; 26 | } 27 | 28 | public abstract Node explicitNegativeForm(); 29 | 30 | public Node toAdditionOnly() { 31 | return this; 32 | } 33 | 34 | public Node toExponentialForm() { 35 | return this; 36 | } 37 | 38 | public Node expand() { 39 | return this; 40 | } 41 | 42 | public Node replace(Node o, Node r) { 43 | return this.equals(o) ? r : this; 44 | } 45 | 46 | public abstract boolean isUndefined(); 47 | 48 | /** 49 | * LeafNode, nothing could be done for reordering. 50 | */ 51 | public void order() { 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/jas/core/Mode.java: -------------------------------------------------------------------------------- 1 | package jas.core; 2 | 3 | import static jas.utils.AnsiColor.*; 4 | 5 | /** 6 | * Created by Jiachen on 3/4/18. 7 | * Mode: radians vs. degrees, debug on/off, etc. 8 | */ 9 | public class Mode { 10 | public static boolean DEBUG = false; 11 | public static boolean FRACTION = true; 12 | public static boolean COMPACT = true; 13 | public static String U_OP_COLOR = LIGHT_BLUE.toString(); 14 | public static String BIN_OP_COLOR = "[0m"; 15 | public static String CUSTOM_OP_COLOR = LIGHT_PURPLE.toString(); 16 | public static String CONSTANT_COLOR = LIGHT_CYAN.toString(); 17 | public static String CURLY_BRACKET_COLOR = LIGHT_PURPLE.toString(); 18 | public static String COMMA_COLOR = LIGHT_PURPLE.toString(); 19 | public static String PARENTHESIS_COLOR = LIGHT_RED.toString(); 20 | public static String LITERAL_COLOR = LIGHT_GREEN.toString(); 21 | public static String NUMBER_COLOR = GREEN.toString(); 22 | public static String FRACTION_COLOR = GREEN.toString(); 23 | public static String VARIABLE_COLOR = BOLD_BLACK.toString(); 24 | public static String DECIMAL_FORMAT = "0.##################"; //needs improvement! 25 | } 26 | -------------------------------------------------------------------------------- /src/jas/core/Nameable.java: -------------------------------------------------------------------------------- 1 | package jas.core; 2 | 3 | /** 4 | * Created by Jiachen on 3/15/18. 5 | * Nameable 6 | */ 7 | public interface Nameable { 8 | String getName(); 9 | } 10 | -------------------------------------------------------------------------------- /src/jas/core/components/Constants.java: -------------------------------------------------------------------------------- 1 | package jas.core.components; 2 | 3 | import jas.core.JASException; 4 | import jas.core.Mode; 5 | import jas.core.Node; 6 | import jas.utils.ColorFormatter; 7 | 8 | import java.util.ArrayList; 9 | 10 | /** 11 | * Created by Jiachen on 16/05/2017. 12 | * Constants 13 | */ 14 | public class Constants { 15 | static { 16 | constants = new ArrayList<>(); 17 | define("e", () -> Math.E); 18 | define("pi", () -> Math.PI); 19 | define("∞", () -> Double.POSITIVE_INFINITY); 20 | define("random", Math::random); 21 | } 22 | 23 | private static ArrayList constants; 24 | public static final Constant E = get("e"); 25 | public static final Constant PI = get("pi"); 26 | 27 | public static boolean contains(String symbol) { 28 | for (Constant constant : constants) { 29 | if (constant.getName().equals(symbol)) 30 | return true; 31 | } 32 | return false; 33 | } 34 | 35 | /** 36 | * add or define a Constant object into the static ArrayList Constants. 37 | * 38 | * @param name the name of the constant 39 | * @param computedConst the new computed const instance 40 | */ 41 | public static void define(String name, ComputedConst computedConst) { 42 | boolean defined = false; 43 | for (Constant constant : constants) { 44 | if (constant.getName().equals(name)) { 45 | constant.computedConst = computedConst; 46 | defined = true; 47 | } 48 | } 49 | if (!defined) constants.add(new Constant(name, computedConst)); 50 | } 51 | 52 | public static double valueOf(String constant) { 53 | for (Constant c : constants) { 54 | if (c.getName().equals(constant)) 55 | return c.computedConst.compute(); 56 | } 57 | return 0.0; 58 | } 59 | 60 | public static ArrayList list() { 61 | return constants; 62 | } 63 | 64 | public static Constant get(String name) { 65 | for (Constant constant : constants) { 66 | if (constant.getName().equals(name)) 67 | return constant; 68 | } 69 | throw new JASException("constant + \"" + name + "\" does not exist"); 70 | } 71 | 72 | public interface ComputedConst { 73 | double compute(); 74 | } 75 | 76 | public static class Constant extends Variable { 77 | private ComputedConst computedConst; 78 | 79 | public Constant(String name, ComputedConst computedConst) { 80 | super(name); 81 | this.computedConst = computedConst; 82 | 83 | } 84 | 85 | Constant(Constant other) { 86 | super(other.getName()); 87 | this.computedConst = other.computedConst; 88 | } 89 | 90 | public double eval(double x) { 91 | return computedConst.compute(); 92 | } 93 | 94 | public boolean equals(Node other) { 95 | return other instanceof Constant && (((Constant) other).getName().equals(getName()) 96 | || other.val() == this.val()); 97 | } 98 | 99 | @Override 100 | public String coloredString() { 101 | return ColorFormatter.color(toString(), Mode.CONSTANT_COLOR); 102 | } 103 | 104 | @Override 105 | public double val() { 106 | return computedConst.compute(); 107 | } 108 | 109 | @Override 110 | public Constant copy() { 111 | return new Constant(this); 112 | } 113 | 114 | @Override 115 | public Node firstDerivative(Variable v) { 116 | return RawValue.ZERO; 117 | } 118 | 119 | public int complexity() { 120 | return 2; 121 | } 122 | 123 | public int numNodes() { 124 | return 1; 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/jas/core/components/Literal.java: -------------------------------------------------------------------------------- 1 | package jas.core.components; 2 | 3 | import jas.core.Mode; 4 | import jas.core.Node; 5 | import jas.utils.ColorFormatter; 6 | 7 | /** 8 | * Created by Jiachen on 3/23/18. 9 | * Literal: non-calculable nodes 10 | */ 11 | public class Literal extends Variable { 12 | private String content; 13 | 14 | public Literal(String content) { 15 | super(content); 16 | this.content = content; 17 | } 18 | 19 | @Override 20 | public boolean equals(Node other) { 21 | return other instanceof Literal && ((Literal) other).content.equals(content); 22 | } 23 | 24 | @Override 25 | public Literal copy() { 26 | return new Literal(content); 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return "'" + content + "'"; 32 | } 33 | 34 | /** 35 | * If this method is successfully implemented, it would be marked as a milestone. 36 | * 37 | * @param v the variable in which the first derivative is taken with respect to. 38 | * @return first derivative of the expression 39 | */ 40 | @Override 41 | public Node firstDerivative(Variable v) { 42 | return RawValue.ZERO; 43 | } 44 | 45 | @Override 46 | public boolean isUndefined() { 47 | return false; 48 | } 49 | 50 | @Override 51 | public double eval(double x) { 52 | return Double.NaN; 53 | } 54 | 55 | @Override 56 | public String coloredString() { 57 | return ColorFormatter.color(this.toString(), Mode.LITERAL_COLOR); 58 | } 59 | 60 | public String get() { 61 | return content; 62 | } 63 | 64 | @Override 65 | public double val() { 66 | return Double.NaN; 67 | } 68 | 69 | @Override 70 | public Literal simplify() { 71 | return this; 72 | } 73 | 74 | @Deprecated 75 | public String getName() { 76 | return content; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/jas/core/components/Matrix.java: -------------------------------------------------------------------------------- 1 | package jas.core.components; 2 | 3 | import jas.core.Node; 4 | 5 | /** 6 | * Created by Jiachen on 3/20/18. 7 | */ 8 | public class Matrix extends Node { 9 | @Override 10 | public boolean equals(Node other) { 11 | return false; 12 | } 13 | 14 | @Override 15 | public Node copy() { 16 | return null; 17 | } 18 | 19 | /** 20 | * orders the expression according to lexicographic order. This saves some computational resource when trying to decide 21 | * whether a node within the binary tree the the canonical form of another. 22 | * e.g. c*b*3*a would be reordered to something like 3*a*c*b 23 | */ 24 | @Override 25 | public void order() { 26 | //TODO: implement 27 | } 28 | 29 | /** 30 | * returns 0, if the current instance is what you are looking for, i.e. this.equals(o); 31 | * returns -1 if not found. 32 | * 33 | * @param o the Node instance that you are looking for. 34 | * @return the level at which node is found. 35 | */ 36 | @Override 37 | public int levelOf(Node o) { 38 | return 0; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return null; 44 | } 45 | 46 | /** 47 | * numNodes() of expression "(3 + 4.5) * 5.3 / 2.7" returns 7 48 | * numNodes() of expression "(3 + 4.5) * ln(5.3 + 4) / 2.7 / (x + 1) * x / 3" returns 18 49 | * numNodes() of expression "3 - 2x + 4x - 4 + 7pi" returns 15 50 | * 51 | * @return number of nodes (including both leaf nodes and non-leaf nodes) 52 | */ 53 | @Override 54 | public int numNodes() { 55 | return 0; 56 | } 57 | 58 | /** 59 | * traverses the composite tree and evaluates every single node that represents a raw value. 60 | * e.g. if the Node represents the expression "(5 + 7) / 2 ^ 2", val() returns 3. 61 | * however, if variables exists in the expression, NaN is returned. 62 | * e.g. if the Node represents the expression "(5 + 7x) / 2 ^ 2", val() returns NaN. 63 | * 64 | * @return arbitrary value of the node. 65 | */ 66 | @Override 67 | public double val() { 68 | return 0; 69 | } 70 | 71 | /** 72 | * @return level of complexity of the expression represented by an integer with 1 being 73 | * the most simplistic 74 | */ 75 | @Override 76 | public int complexity() { 77 | return 0; 78 | } 79 | 80 | /** 81 | * NOTE: useful for simple simplifications. 82 | * Node::simplify(Node o) is optimized for complex simplifications like when taking the 10th derivative of x*cos(x)*sin(x) 83 | * 84 | * @return simplified expression 85 | */ 86 | @Override 87 | public Node simplify() { 88 | return null; 89 | } 90 | 91 | /** 92 | * basically reversing the effects of toAdditionalOnly and toExponentialForm 93 | * a*b^(-1) -> a/b, 94 | * a*(1/3) -> a/3, 95 | * a+(-1)*b -> a-b 96 | *

97 | * before invoking this method, the Node should already by at a stage where it is simplified, 98 | * converted to additional only and in exponential form. 99 | * 100 | * @return beautified version of the original 101 | */ 102 | @Override 103 | public Node beautify() { 104 | return null; 105 | } 106 | 107 | /** 108 | * (-#)*x will be converted to (-1)*#*x, where # denotes a number 109 | * NOTE: does not modify self. 110 | * 111 | * @return explicit negative form of the original Node 112 | */ 113 | @Override 114 | public Node explicitNegativeForm() { 115 | return null; 116 | } 117 | 118 | @Override 119 | public Node toAdditionOnly() { 120 | return null; 121 | } 122 | 123 | @Override 124 | public Node toExponentialForm() { 125 | return null; 126 | } 127 | 128 | /** 129 | * If this method is successfully implemented, it would be marked as a milestone. 130 | * 131 | * @param v the variable in which the first derivative is taken with respect to. 132 | * @return first derivative of the expression 133 | */ 134 | @Override 135 | public Node firstDerivative(Variable v) { 136 | return null; 137 | } 138 | 139 | /** 140 | * Expand the expression; its behavior is exactly what you would expect. 141 | * e.g. (a+b+...)(c+d) = a*c + a*d + b*c + ... 142 | * 143 | * @return expanded expression of type Node 144 | */ 145 | @Override 146 | public Node expand() { 147 | return null; 148 | } 149 | 150 | /** 151 | * @return string representation of the node coded with Ansi color codes. 152 | */ 153 | @Override 154 | public String coloredString() { 155 | return null; 156 | } 157 | 158 | /** 159 | * @param o the node to be replaced 160 | * @param r the node to take o's place 161 | * @return the original node with o replaced by r. 162 | */ 163 | @Override 164 | public Node replace(Node o, Node r) { 165 | return null; 166 | } 167 | 168 | @Override 169 | public boolean isUndefined() { 170 | return false; 171 | } 172 | 173 | @Override 174 | public double eval(double x) { 175 | return 0; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/jas/core/components/RawValue.java: -------------------------------------------------------------------------------- 1 | package jas.core.components; 2 | 3 | import jas.core.LeafNode; 4 | import jas.core.Mode; 5 | import jas.core.Node; 6 | import jas.core.operations.Binary; 7 | import jas.utils.ColorFormatter; 8 | 9 | import java.math.BigDecimal; 10 | import java.math.BigInteger; 11 | import java.text.DecimalFormat; 12 | 13 | /** 14 | * Created by Jiachen on 03/05/2017. 15 | * Wrapper class for a number 16 | * This class should NEVER modify a instance after it is created. Be sure to make new ones for every single operation. 17 | */ 18 | public class RawValue extends LeafNode { 19 | public static final RawValue UNDEF = new RawValue(Double.NaN); 20 | public static final RawValue ONE = new RawValue(1); 21 | public static final RawValue ZERO = new RawValue(0); 22 | public static final RawValue TWO = new RawValue(2); 23 | public static final RawValue INFINITY = new RawValue(Double.POSITIVE_INFINITY); 24 | 25 | private Double n; 26 | 27 | public RawValue(RawValue rawValue) { 28 | this(rawValue.n); 29 | } 30 | 31 | public RawValue(double n) { 32 | this.n = n; 33 | } 34 | 35 | public static boolean isInteger(double n) { 36 | return new RawValue(n).isInteger(); 37 | } 38 | 39 | public static boolean isNumeric(String str) { 40 | try { 41 | //noinspection ResultOfMethodCallIgnored 42 | Double.parseDouble(str); 43 | } catch (NumberFormatException nfe) { 44 | return false; 45 | } 46 | return true; 47 | } 48 | 49 | public boolean isInteger() { 50 | return (n % 1) == 0; 51 | } 52 | 53 | public double doubleValue() { 54 | return n; 55 | } 56 | 57 | public double eval(double x) { 58 | return doubleValue(); 59 | } 60 | 61 | public RawValue inverse() { 62 | if (isInteger()) return new Fraction(BigInteger.ONE, toBigInteger()); 63 | else return Fraction.convertToFraction(doubleValue(), Fraction.TOLERANCE).inverse(); 64 | } 65 | 66 | public boolean isZero() { 67 | return doubleValue() == 0; 68 | } 69 | 70 | public boolean isInfinite() { 71 | return n.isInfinite(); 72 | } 73 | 74 | /** 75 | * Removes the extra ".0" at the end of the n 76 | * 77 | * @return the formatted String representation of the n. 78 | */ 79 | public String toString() { 80 | if (isUndefined()) { 81 | return "undef"; 82 | } else if (doubleValue() == 0) return "0"; // fix a bug where 0.negate().toString() returns "-0" 83 | return format(doubleValue()); 84 | } 85 | 86 | public BigInteger toBigInteger() { 87 | return BigDecimal.valueOf(doubleValue()).toBigIntegerExact(); 88 | } 89 | 90 | private String format(double d) { 91 | DecimalFormat decimalFormat = new DecimalFormat(Mode.DECIMAL_FORMAT); 92 | return decimalFormat.format(d); 93 | } 94 | 95 | @SuppressWarnings("BooleanMethodIsAlwaysInverted") 96 | public boolean isPositive() { 97 | return doubleValue() > 0; 98 | } 99 | 100 | 101 | public long longValue() { 102 | return n.longValue(); 103 | } 104 | 105 | 106 | public boolean isUndefined() { 107 | return n.isNaN(); 108 | } 109 | 110 | 111 | public RawValue copy() { 112 | return new RawValue(n); 113 | } 114 | 115 | public Node explicitNegativeForm() { 116 | if (this.equals(ONE.negate())) return this; 117 | return doubleValue() < 0 ? new Binary(ONE.negate(), "*", this.copy().negate()) : this.copy(); 118 | } 119 | 120 | @Override 121 | public Node firstDerivative(Variable v) { 122 | if (isUndefined()) return UNDEF; 123 | return ZERO; 124 | } 125 | 126 | /** 127 | * @return string representation of the node coded with Ansi color codes. 128 | */ 129 | @Override 130 | public String coloredString() { 131 | return ColorFormatter.color(this.toString(), Mode.NUMBER_COLOR); 132 | } 133 | 134 | public boolean equals(Node other) { 135 | return other instanceof RawValue 136 | && other.isUndefined() 137 | && this.isUndefined() 138 | || other instanceof RawValue 139 | && ((RawValue) other).doubleValue() 140 | == this.doubleValue(); 141 | } 142 | 143 | public Node simplify() { 144 | return this; 145 | } 146 | 147 | public double val() { 148 | return doubleValue(); 149 | } 150 | 151 | public int complexity() { 152 | return 1; 153 | } 154 | 155 | 156 | @Override 157 | public RawValue negate() { 158 | return new RawValue(this.doubleValue() * -1); 159 | } 160 | 161 | 162 | } 163 | -------------------------------------------------------------------------------- /src/jas/core/components/Variable.java: -------------------------------------------------------------------------------- 1 | package jas.core.components; 2 | 3 | import jas.core.*; 4 | import jas.utils.ColorFormatter; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import java.util.Optional; 9 | 10 | /** 11 | * Created by Jiachen on 16/05/2017. 12 | * Variable class 13 | */ 14 | public class Variable extends LeafNode implements Nameable { 15 | private String name; 16 | private static Map storedVars = new HashMap<>(); 17 | 18 | public Variable(String name) { 19 | if (name.equals("")) throw new JASException("variable name cannot be empty"); 20 | this.name = name; 21 | } 22 | 23 | public double eval(double x) { 24 | return x; 25 | } 26 | 27 | public boolean equals(Node other) { 28 | return other instanceof Variable && ((Variable) other).getName().equals(name); 29 | } 30 | 31 | public String getName() { 32 | return name; 33 | } 34 | 35 | public String toString() { 36 | return name; 37 | } 38 | 39 | public void setName(String name) { 40 | this.name = name; 41 | } 42 | 43 | /** 44 | * Since a variable is not an arbitrary number, val() should return NaN. 45 | * If a value is stored in the variable, return the value. 46 | * 47 | * @return NaN or value of the definition 48 | */ 49 | public double val() { 50 | return get().orElse(RawValue.UNDEF).val(); 51 | } 52 | 53 | private Optional get() { 54 | return get(this.name); 55 | } 56 | 57 | public boolean isUndefined() { 58 | return false; 59 | } 60 | 61 | public Node simplify() { 62 | return get().orElse(this); 63 | } 64 | 65 | /** 66 | * Assign the variable with an Node 67 | * 68 | * @param var the name of the variable 69 | * @param o the Node to be assigned to the variable name . 70 | */ 71 | public static void store(Node o, String var) { 72 | storedVars.put(var, o); 73 | } 74 | 75 | /** 76 | * @param var variable name 77 | * @return Optional type of var's definition 78 | */ 79 | public static Optional get(String var) { 80 | return Optional.ofNullable(storedVars.get(var)); 81 | } 82 | 83 | /** 84 | * deletes the variable from stored variables 85 | * 86 | * @param var the name of the variable 87 | * @return definition of var 88 | */ 89 | public static Node del(String var) { 90 | return storedVars.remove(var); 91 | } 92 | 93 | /** 94 | * @param v the variable in which the first derivative is taken with respect to. 95 | * @return if v == this, 1, otherwise 0; rule of derivative applies. 96 | */ 97 | public Node firstDerivative(Variable v) { 98 | if (v.equals(this)) return RawValue.ONE; 99 | return RawValue.ZERO; 100 | } 101 | 102 | /** 103 | * @return string representation of the node coded with Ansi color codes. 104 | */ 105 | @Override 106 | public String coloredString() { 107 | return ColorFormatter.color(this.toString(), Mode.VARIABLE_COLOR); 108 | } 109 | 110 | /** 111 | * Ensures that if "x" is defined as "x = 3", the value gets replicated as well. 112 | * 113 | * @return new Variable instance that is identical to self. 114 | */ 115 | public Variable copy() { 116 | return new Variable(name); 117 | } 118 | 119 | public Node explicitNegativeForm() { 120 | return this.copy(); 121 | } 122 | 123 | public int complexity() { 124 | return 3; 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /src/jas/core/components/Vector.java: -------------------------------------------------------------------------------- 1 | package jas.core.components; 2 | 3 | import jas.core.Node; 4 | 5 | /** 6 | * Created by Jiachen on 3/20/18. 7 | */ 8 | public class Vector extends Node { 9 | @Override 10 | public boolean equals(Node other) { 11 | return false; 12 | } 13 | 14 | @Override 15 | public Node copy() { 16 | return null; 17 | } 18 | 19 | /** 20 | * orders the expression according to lexicographic order. This saves some computational resource when trying to decide 21 | * whether a node within the binary tree the the canonical form of another. 22 | * e.g. c*b*3*a would be reordered to something like 3*a*c*b 23 | */ 24 | @Override 25 | public void order() { 26 | //TODO: implement 27 | } 28 | 29 | /** 30 | * returns 0, if the current instance is what you are looking for, i.e. this.equals(o); 31 | * returns -1 if not found. 32 | * 33 | * @param o the Node instance that you are looking for. 34 | * @return the level at which node is found. 35 | */ 36 | @Override 37 | public int levelOf(Node o) { 38 | return 0; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return null; 44 | } 45 | 46 | /** 47 | * numNodes() of expression "(3 + 4.5) * 5.3 / 2.7" returns 7 48 | * numNodes() of expression "(3 + 4.5) * ln(5.3 + 4) / 2.7 / (x + 1) * x / 3" returns 18 49 | * numNodes() of expression "3 - 2x + 4x - 4 + 7pi" returns 15 50 | * 51 | * @return number of nodes (including both leaf nodes and non-leaf nodes) 52 | */ 53 | @Override 54 | public int numNodes() { 55 | return 0; 56 | } 57 | 58 | /** 59 | * traverses the composite tree and evaluates every single node that represents a raw value. 60 | * e.g. if the Node represents the expression "(5 + 7) / 2 ^ 2", val() returns 3. 61 | * however, if variables exists in the expression, NaN is returned. 62 | * e.g. if the Node represents the expression "(5 + 7x) / 2 ^ 2", val() returns NaN. 63 | * 64 | * @return arbitrary value of the node. 65 | */ 66 | @Override 67 | public double val() { 68 | return 0; 69 | } 70 | 71 | /** 72 | * @return level of complexity of the expression represented by an integer with 1 being 73 | * the most simplistic 74 | */ 75 | @Override 76 | public int complexity() { 77 | return 0; 78 | } 79 | 80 | /** 81 | * NOTE: useful for simple simplifications. 82 | * Node::simplify(Node o) is optimized for complex simplifications like when taking the 10th derivative of x*cos(x)*sin(x) 83 | * 84 | * @return simplified expression 85 | */ 86 | @Override 87 | public Node simplify() { 88 | return null; 89 | } 90 | 91 | /** 92 | * basically reversing the effects of toAdditionalOnly and toExponentialForm 93 | * a*b^(-1) -> a/b, 94 | * a*(1/3) -> a/3, 95 | * a+(-1)*b -> a-b 96 | *

97 | * before invoking this method, the Node should already by at a stage where it is simplified, 98 | * converted to additional only and in exponential form. 99 | * 100 | * @return beautified version of the original 101 | */ 102 | @Override 103 | public Node beautify() { 104 | return null; 105 | } 106 | 107 | /** 108 | * (-#)*x will be converted to (-1)*#*x, where # denotes a number 109 | * NOTE: does not modify self. 110 | * 111 | * @return explicit negative form of the original Node 112 | */ 113 | @Override 114 | public Node explicitNegativeForm() { 115 | return null; 116 | } 117 | 118 | @Override 119 | public Node toAdditionOnly() { 120 | return null; 121 | } 122 | 123 | @Override 124 | public Node toExponentialForm() { 125 | return null; 126 | } 127 | 128 | /** 129 | * If this method is successfully implemented, it would be marked as a milestone. 130 | * 131 | * @param v the variable in which the first derivative is taken with respect to. 132 | * @return first derivative of the expression 133 | */ 134 | @Override 135 | public Node firstDerivative(Variable v) { 136 | return null; 137 | } 138 | 139 | /** 140 | * Expand the expression; its behavior is exactly what you would expect. 141 | * e.g. (a+b+...)(c+d) = a*c + a*d + b*c + ... 142 | * 143 | * @return expanded expression of type Node 144 | */ 145 | @Override 146 | public Node expand() { 147 | return null; 148 | } 149 | 150 | /** 151 | * @return string representation of the node coded with Ansi color codes. 152 | */ 153 | @Override 154 | public String coloredString() { 155 | return null; 156 | } 157 | 158 | /** 159 | * @param o the node to be replaced 160 | * @param r the node to take o's place 161 | * @return the original node with o replaced by r. 162 | */ 163 | @Override 164 | public Node replace(Node o, Node r) { 165 | return null; 166 | } 167 | 168 | @Override 169 | public boolean isUndefined() { 170 | return false; 171 | } 172 | 173 | @Override 174 | public double eval(double x) { 175 | return 0; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/jas/core/operations/Argument.java: -------------------------------------------------------------------------------- 1 | package jas.core.operations; 2 | 3 | import jas.core.JASException; 4 | import jas.core.Node; 5 | import jas.core.components.*; 6 | 7 | /** 8 | * Created by Jiachen on 3/17/18. 9 | * Argument type 10 | */ 11 | public enum Argument { 12 | NUMBER, 13 | VARIABLE, 14 | ANY, 15 | OPERATION, 16 | MATRIX, 17 | LIST, 18 | VECTOR, 19 | LITERAL; 20 | 21 | public static Argument resolve(Node o) { 22 | if (!o.isNaN() || o instanceof RawValue) { 23 | return NUMBER; 24 | } else if (o instanceof Literal) { // be careful, Literal is a subclass of Variable. 25 | return LITERAL; 26 | } else if (o instanceof Variable) { 27 | return VARIABLE; 28 | } else if (o instanceof Operation) { 29 | return OPERATION; 30 | } else if (o instanceof Matrix) { 31 | return MATRIX; 32 | } else if (o instanceof List) { 33 | return LIST; 34 | } else if (o instanceof Vector) { 35 | return VECTOR; 36 | } 37 | throw new JASException("cannot resolve argument type \"" + o + "\""); 38 | } 39 | 40 | public boolean equals(Argument other) { 41 | return super.equals(ANY) || other == ANY || super.equals(other); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/jas/core/operations/Manipulable.java: -------------------------------------------------------------------------------- 1 | package jas.core.operations; 2 | 3 | import jas.core.Node; 4 | 5 | import java.util.ArrayList; 6 | 7 | /** 8 | * Created by Jiachen on 3/17/18. 9 | * Manipulable 10 | */ 11 | public interface Manipulable { 12 | Node manipulate(ArrayList operands); 13 | } 14 | -------------------------------------------------------------------------------- /src/jas/core/operations/Manipulation.java: -------------------------------------------------------------------------------- 1 | package jas.core.operations; 2 | 3 | import jas.core.Nameable; 4 | import jas.core.Node; 5 | 6 | import java.util.ArrayList; 7 | 8 | /** 9 | * Created by Jiachen on 3/17/18. 10 | * Named Manipulation 11 | */ 12 | public class Manipulation implements Nameable, Manipulable { 13 | private String name; 14 | private Manipulable manipulable; 15 | private Signature signature; 16 | 17 | public Manipulation(String name, Signature signature, Manipulable manipulable) { 18 | this.manipulable = manipulable; 19 | this.signature = signature; 20 | this.name = name; 21 | } 22 | 23 | public Node manipulate(ArrayList operands) { 24 | return manipulable.manipulate(operands); 25 | } 26 | 27 | public Signature getSignature() { 28 | return signature; 29 | } 30 | 31 | public boolean equals(Manipulation other) { 32 | return other.getName().equals(getName()) && other.signature.equals(signature); 33 | } 34 | 35 | public boolean equals(String name, Signature signature) { 36 | return name.equals(getName()) && getSignature().equals(signature); 37 | } 38 | 39 | public String toString() { 40 | return getName() + "(" + signature.toString() + ")"; 41 | } 42 | 43 | public String getName() { 44 | return name; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/jas/core/operations/Signature.java: -------------------------------------------------------------------------------- 1 | package jas.core.operations; 2 | 3 | import jas.core.Node; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.Collections; 8 | import java.util.Optional; 9 | import java.util.stream.Collectors; 10 | 11 | /** 12 | * Created by Jiachen on 3/17/18. 13 | * Signature 14 | */ 15 | public class Signature { 16 | public static final Signature ANY = new Signature(); 17 | private Argument[] args; 18 | 19 | public Signature(Argument... args) { 20 | this.args = args; 21 | } 22 | 23 | public Signature(int numArgs) { 24 | args = new Argument[numArgs]; 25 | Arrays.fill(args, Argument.ANY); 26 | } 27 | 28 | private Signature(ArrayList args) { 29 | this(args.toArray(new Argument[args.size()])); 30 | } 31 | 32 | public boolean equals(Signature other) { 33 | if (args.length == 0 && other.args.length == 0) return true; // special case 34 | if (other.args.length != this.args.length) return false; 35 | for (int i = 0; i < args.length; i++) { 36 | if (!args[i].equals(other.args[i])) 37 | return false; 38 | } 39 | return true; 40 | } 41 | 42 | static Signature resolve(ArrayList args) { 43 | return new Signature(args.stream() 44 | .map(Argument::resolve) 45 | .collect(Collectors.toCollection(ArrayList::new))); 46 | } 47 | 48 | public String toString() { 49 | if (this.args == null || args.length == 0) return "ANY..."; 50 | ArrayList args = new ArrayList<>(); 51 | Collections.addAll(args, this.args); 52 | Optional str = args.stream().map(Enum::toString).reduce((a, b) -> a + ", " + b); 53 | return str.orElse(""); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/jas/extras/Element.java: -------------------------------------------------------------------------------- 1 | package jas.extras; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | /** 8 | * Created by Jiachen on 9/12/17. 9 | * Element class that holds info for elements 10 | */ 11 | public enum Element { 12 | H(1, "Hydrogen", 1.008), 13 | He(2, "Helium", 4.003), 14 | Li(3, "Lithium", 6.941), 15 | C(6, "Carbon", 12.01), 16 | O(8, "Oxygen", 16.00), 17 | 18 | // ... 90+ others 19 | ; 20 | 21 | private final int atomicNumber; 22 | private final String fullName; 23 | private final double atomicMass; 24 | Element(int atomicNumber, String fullName, double atomicMass) { 25 | this.atomicNumber = atomicNumber; 26 | this.fullName = fullName; 27 | this.atomicMass = atomicMass; 28 | Holder.map.put(atomicNumber, this); 29 | } 30 | 31 | public static ArrayList getList() { 32 | ArrayList elements = new ArrayList<>(); 33 | Holder.map.values().forEach(elements::add); 34 | return elements; 35 | } 36 | 37 | public static Element forAtomicNumber(int atomicNumber) { 38 | return Holder.map.get(atomicNumber); 39 | } 40 | 41 | public int getAtomicNumber() { 42 | return atomicNumber; 43 | } 44 | 45 | public String getFullName() { 46 | return fullName; 47 | } 48 | 49 | public double getAtomicMass() { 50 | return atomicMass; 51 | } 52 | 53 | private static class Holder { 54 | static Map map = new HashMap<>(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/jas/graph/Point.java: -------------------------------------------------------------------------------- 1 | package jas.graph; 2 | 3 | /** 4 | * Created by Jiachen on 05/05/2017. 5 | * Point on the graph (graphing capabilities only) 6 | */ 7 | public class Point { 8 | private double x; 9 | private double y; 10 | private boolean isValidPoint; 11 | private boolean isAsymptoteAnchor; 12 | private boolean isAsymptoteTail; 13 | private boolean isOutOfScope; 14 | 15 | { 16 | isValidPoint = true; 17 | } 18 | 19 | public Point(double x, double y) { 20 | setX(x); 21 | setY(y); 22 | } 23 | 24 | Point(Point clone) { 25 | this.x = clone.x; 26 | this.y = clone.y; 27 | this.isValidPoint = clone.isValidPoint; 28 | this.isAsymptoteAnchor = clone.isAsymptoteAnchor; 29 | this.isAsymptoteTail = clone.isAsymptoteTail; 30 | this.isOutOfScope = clone.isOutOfScope; 31 | } 32 | 33 | public static double dist(Point a, Point b) { 34 | return Point.dist(a.getX(), a.getY(), b.getX(), b.getY()); 35 | } 36 | 37 | private static double dist(double x1, double y1, double x2, double y2) { 38 | return Math.pow(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2), 0.5); 39 | } 40 | 41 | public double getX() { 42 | return x; 43 | } 44 | 45 | public void setX(double x) { 46 | this.x = x; 47 | if (Double.isNaN(x) || Double.isInfinite(x)) 48 | isValidPoint = false; 49 | } 50 | 51 | boolean isValid() { 52 | return isValidPoint; 53 | } 54 | 55 | public double dist(Point other) { 56 | return Math.abs(this.getY() - other.getY()); 57 | } 58 | 59 | public double getY() { 60 | return y; 61 | } 62 | 63 | public void setY(double y) { 64 | this.y = y; 65 | if (Double.isNaN(y) || Double.isInfinite(y) || y > 1E37) 66 | isValidPoint = false; 67 | } 68 | 69 | public String toString() { 70 | return "x: " + x + " y " + y; 71 | } 72 | 73 | Point setAsAnchor() { 74 | isAsymptoteAnchor = true; 75 | return this; 76 | } 77 | 78 | boolean isAsymptoteAnchor() { 79 | return isAsymptoteAnchor; 80 | } 81 | 82 | Point setAsTail() { 83 | isAsymptoteTail = true; 84 | return this; 85 | } 86 | 87 | boolean isAsymptoteTail() { 88 | return isAsymptoteTail; 89 | } 90 | 91 | public boolean isOutOfScope() { 92 | return isOutOfScope; 93 | } 94 | 95 | void setOutOfScope(boolean temp) { 96 | this.isOutOfScope = temp; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/jas/graph/Range.java: -------------------------------------------------------------------------------- 1 | package jas.graph; 2 | 3 | /** 4 | * Created by Jiachen on 05/05/2017. 5 | * Range class (for graphing capabilities only) 6 | */ 7 | public class Range { 8 | private double low; 9 | private double high; 10 | private double step; 11 | private boolean hasNextStep; 12 | private double current; 13 | 14 | Range(Range clone) { 15 | this(clone.getLow(), clone.getHigh(), clone.getStep()); 16 | this.hasNextStep = clone.hasNextStep; 17 | this.current = clone.current; 18 | } 19 | 20 | Range(double low, double high, double step) { 21 | this.low = low; 22 | this.high = high; 23 | this.step = step; 24 | current = low; 25 | hasNextStep = true; 26 | assertValidity(); 27 | } 28 | 29 | double getLow() { 30 | return this.low; 31 | } 32 | 33 | double getHigh() { 34 | return this.high; 35 | } 36 | 37 | double getStep() { 38 | return step; 39 | } 40 | 41 | void setStep(double step) { 42 | this.step = step; 43 | } 44 | 45 | private void assertValidity() { 46 | if (high < low) { 47 | double temp = low; 48 | low = high; 49 | high = temp; 50 | } 51 | 52 | while (numSteps() > 2000 && step != 0.0) { 53 | step *= 1.05; 54 | } 55 | 56 | } 57 | 58 | private int numSteps() { 59 | return (int) (getSpan() / getStep()); 60 | } 61 | 62 | double getSpan() { 63 | return high - low; 64 | } 65 | 66 | Range(double low, double high) { 67 | this(low, high, 0); 68 | } 69 | 70 | double getCurStep() { 71 | return current; 72 | } 73 | 74 | void next() { 75 | if (current < high) current += step; 76 | else hasNextStep = false; 77 | } 78 | 79 | boolean hasNextStep() { 80 | return hasNextStep; 81 | } 82 | 83 | boolean isInScope(double val) { 84 | return val <= high && val >= low; 85 | } 86 | 87 | public String toString() { 88 | return "low: " + low + " high: " + high + " step: " + step; 89 | } 90 | 91 | /** 92 | * rescale the range according to the scaling factor 93 | * 94 | * @param scale the scale to be applied on the range. 1.5 95 | * would make the span 1.5 times the original 96 | * while 0.5 would make the span 0.5 times 97 | * the original. 98 | */ 99 | void rescale(double scale) { 100 | double original_span = this.getSpan(); 101 | double mid = (getLow() + getHigh()) / 2; 102 | original_span *= scale; 103 | this.low = mid - original_span / 2; 104 | this.high = mid + original_span / 2; 105 | current = low; 106 | hasNextStep = true; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/jas/graph/SuppliedVar.java: -------------------------------------------------------------------------------- 1 | package jas.graph; 2 | 3 | import jas.core.Mode; 4 | import jas.core.Node; 5 | import jas.core.components.Variable; 6 | 7 | /** 8 | * Created by Jiachen on 3/4/18. 9 | * Supplied Variable 10 | */ 11 | public class SuppliedVar extends Variable { 12 | private double val; 13 | 14 | public SuppliedVar(String name) { 15 | super(name); 16 | } 17 | 18 | @Override 19 | public double eval(double x) { 20 | return val; 21 | } 22 | 23 | @Override 24 | public boolean equals(Node other) { 25 | return other instanceof SuppliedVar && ((SuppliedVar) other).getName().equals(getName()); 26 | } 27 | 28 | public String toString() { 29 | return Mode.DEBUG ? "&" + getName() + "&" : getName(); 30 | } 31 | 32 | @Override 33 | public SuppliedVar copy() { 34 | super.copy(); 35 | return new SuppliedVar(this.getName()).setVal(this.val); 36 | } 37 | 38 | public SuppliedVar setVal(double val) { 39 | this.val = val; 40 | return this; 41 | } 42 | 43 | @Override 44 | public double val() { 45 | return val; 46 | } 47 | 48 | @Override 49 | public Node replace(Node o, Node r) { 50 | return o.equals(this) ? r : this; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/jas/utils/AnsiColor.java: -------------------------------------------------------------------------------- 1 | package jas.utils; 2 | 3 | /** 4 | * Created by Jiachen on 3/2/18. 5 | * An enum encapsulating Ansi color codes. 6 | */ 7 | public enum AnsiColor { 8 | BLACK("[0;30m"), 9 | BLUE("[0;34m"), 10 | GREEN("[0;32m"), 11 | CYAN("[0;36m"), 12 | RED("[0;31m"), 13 | PURPLE("[0;35m"), 14 | BROWN("[0;33m"), 15 | GRAY("[0;37m"), 16 | DARK_GRAY("[1;30m"), 17 | LIGHT_BLUE("[1;34m"), 18 | LIGHT_GREEN("[1;32m"), 19 | LIGHT_CYAN("[1;36m"), 20 | LIGHT_RED("[1;31m"), 21 | LIGHT_PURPLE("[1;35m"), 22 | YELLOW("[1;33m"), 23 | BOLD_BLACK("[1m"), 24 | WHITE("[1;37m"); 25 | private String raw; 26 | 27 | AnsiColor(String raw) { 28 | this.raw = raw; 29 | } 30 | 31 | public String toString() { 32 | return this.raw; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/jas/utils/ColorFormatter.java: -------------------------------------------------------------------------------- 1 | package jas.utils; 2 | 3 | import jui.JNode; 4 | 5 | /** 6 | * Created by Jiachen on 3/1/18. 7 | * ColorFormatter class whose job is to color the String for the system outputs. 8 | */ 9 | public class ColorFormatter { 10 | public static String boldBlack(Object o) { 11 | return color(o.toString(), "[1m"); 12 | } 13 | 14 | public static String color(String s, String modifier) { 15 | if (JNode.OS.toLowerCase().contains("windows")) return s; 16 | return (char) 27 + modifier + s + (char) 27 + "[0m"; 17 | } 18 | 19 | public static String lightRed(Object o) { 20 | return color(o.toString(), AnsiColor.LIGHT_RED.toString()); 21 | } 22 | 23 | public static String lightCyan(Object o) { 24 | return color(o.toString(), AnsiColor.LIGHT_CYAN.toString()); 25 | } 26 | 27 | public static String lightGreen(Object o) { 28 | return color(o.toString(), AnsiColor.LIGHT_GREEN.toString()); 29 | } 30 | 31 | public static String lightBlue(Object o) { 32 | return color(o.toString(), AnsiColor.LIGHT_BLUE.toString()); 33 | } 34 | 35 | public static String yellow(Object o) { 36 | return color(o.toString(), AnsiColor.YELLOW.toString()); 37 | } 38 | 39 | public static String purple(Object o) { 40 | return color(o.toString(), AnsiColor.PURPLE.toString()); 41 | } 42 | 43 | public static String lightPurple(Object o) { 44 | return color(o.toString(), AnsiColor.LIGHT_PURPLE.toString()); 45 | } 46 | 47 | /** 48 | * returns a colored line! 49 | * 50 | * @param modifier a sequence of escape characters for modifying the color& font. 51 | * @param line the line to be colored 52 | * @param symbols the symbols to be replaced with color 53 | * @return a beautifully formatted&colorful line for printing! 54 | * @since May 16th 55 | */ 56 | public static String coloredLine(String modifier, String line, String... symbols) { 57 | if (JNode.OS.toLowerCase().contains("windows")) 58 | return line; 59 | for (String symbol : symbols) { 60 | line = line.replace(symbol, (char) 27 + modifier + symbol + (char) 27 + "[0m"); 61 | } 62 | return line; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/jas/utils/Timer.java: -------------------------------------------------------------------------------- 1 | package jas.utils; 2 | 3 | /** 4 | * Created by Jiachen on 3/24/18. 5 | * Timer 6 | */ 7 | public class Timer { 8 | private long time; 9 | 10 | public Timer() { 11 | reset(); 12 | } 13 | 14 | public void reset() { 15 | time = current(); 16 | } 17 | 18 | private long current() { 19 | return System.currentTimeMillis(); 20 | } 21 | 22 | public long millis() { 23 | return current() - time; 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return millis() + " ms"; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/jas/utils/Utils.java: -------------------------------------------------------------------------------- 1 | package jas.utils; 2 | 3 | import java.io.*; 4 | import java.net.URI; 5 | import java.net.URISyntaxException; 6 | 7 | /** 8 | * Created by Jiachen on 3/10/18. 9 | * Utils 10 | */ 11 | public class Utils { 12 | public static String read(String filePath) { 13 | final String[] acc = {""}; 14 | InputStream inputStream; 15 | inputStream = Utils.class.getResourceAsStream(filePath); 16 | InputStreamReader reader = new InputStreamReader(inputStream); 17 | BufferedReader bufferedReader = new BufferedReader(reader); 18 | bufferedReader.lines().forEach(line -> acc[0] += line + "\n"); 19 | return acc[0]; 20 | } 21 | 22 | public static void write(String filePath, String content) { 23 | try { 24 | URI uri = Class.class.getResource(filePath).toURI(); 25 | PrintWriter pw = new PrintWriter(new File(uri)); 26 | pw.write(content); 27 | pw.flush(); 28 | pw.close(); 29 | } catch (IOException | URISyntaxException e) { 30 | e.printStackTrace(); 31 | } 32 | } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/jui/Button.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | 4 | import static processing.core.PConstants.CENTER; 5 | 6 | //code refactored Jan 30th. 7 | public class Button extends Contextual implements MouseControl { 8 | private boolean mousePressedOnButton; 9 | private boolean mouseOverTriggered; 10 | 11 | /*TODO add event listeners with enum*/ 12 | private Runnable onClickMethod, mousePressedMethod, mouseHeldMethod, mouseOverMethod, mouseFloatMethod; 13 | 14 | public Button(float x, float y, float w, float h) { 15 | super(x, y, w, h); 16 | init(); 17 | } 18 | 19 | public Button(float relativeW, float relativeH) { 20 | super(relativeW, relativeH); 21 | init(); 22 | } 23 | 24 | public Button() { 25 | super(); 26 | init(); 27 | } 28 | 29 | public Button(String content) { 30 | this(); 31 | init(); 32 | this.setContent(content); 33 | } 34 | 35 | public void init() { 36 | setContent("button"); 37 | setAlign(CENTER); 38 | setTextMode(Mode.VOLATILE); 39 | setBackgroundMode(Mode.VOLATILE); 40 | } 41 | 42 | public void display() { 43 | //updating the user defined methods in the background 44 | update(); 45 | 46 | //drawing the background 47 | if (font != null) getParent().textFont(font); 48 | super.display(); 49 | 50 | //render text 51 | super.displayText(); 52 | } 53 | 54 | private void update() { 55 | if (isMouseOver()) { 56 | if (getParent().mousePressed) { 57 | if (mouseHeldMethod != null) 58 | mouseHeldMethod.run(); 59 | } else { 60 | if (mouseFloatMethod != null) 61 | mouseFloatMethod.run(); 62 | if (!mouseOverTriggered) { 63 | //the mouseOverMethod should run only one time 64 | if (mouseOverMethod != null) 65 | mouseOverMethod.run(); 66 | mouseOverTriggered = true; 67 | } 68 | } 69 | } else { 70 | mouseOverTriggered = false; 71 | } 72 | } 73 | 74 | public Button onClick(Runnable temp_method) { 75 | onClickMethod = temp_method; 76 | return this; 77 | } 78 | 79 | public Button onMousePressed(Runnable temp_method) { 80 | mousePressedMethod = temp_method; 81 | return this; 82 | } 83 | 84 | public Button onMouseHeld(Runnable temp_method) { 85 | mouseHeldMethod = temp_method; 86 | return this; 87 | } 88 | 89 | public Button onMouseOver(Runnable temp_method) { 90 | mouseOverMethod = temp_method; 91 | return this; 92 | } 93 | 94 | public Button onMouseFloat(Runnable temp_method) { 95 | mouseFloatMethod = temp_method; 96 | return this; 97 | } 98 | 99 | //action receivers 100 | public void mousePressed() { 101 | super.mousePressed(); 102 | if (isMouseOver() && isVisible()) { 103 | mousePressedOnButton = true; 104 | this.press(); 105 | } 106 | } 107 | 108 | public void mouseReleased() { 109 | super.mouseReleased(); 110 | if (isMouseOver() && mousePressedOnButton && isVisible()) 111 | if (onClickMethod != null) 112 | onClickMethod.run(); 113 | mousePressedOnButton = false; 114 | } 115 | 116 | public void press() { 117 | if (mousePressedMethod != null) 118 | mousePressedMethod.run(); 119 | } 120 | 121 | @Override 122 | public Button inheritOutlook(Displayable other) { 123 | super.inheritOutlook(other); 124 | return this; 125 | } 126 | 127 | @Override 128 | public Button inheritMode(Displayable other) { 129 | super.inheritMode(other); 130 | return this; 131 | } 132 | 133 | 134 | public void keyPressed() { 135 | super.keyPressed(); 136 | } 137 | 138 | public void keyReleased() { 139 | super.keyReleased(); 140 | } 141 | 142 | public Button setDefaultContent(String temp) { 143 | this.setContent(temp); 144 | this.defaultContent = temp; 145 | return this; 146 | } 147 | 148 | public Button setContent(String temp) { 149 | super.setContent(temp); 150 | return this; 151 | } 152 | 153 | @Override 154 | public Button setId(String id) { 155 | super.setId(id); 156 | return this; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/jui/Canvas.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | public class Canvas { 4 | } 5 | -------------------------------------------------------------------------------- /src/jui/Chart.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | public abstract class Chart { 4 | } 5 | -------------------------------------------------------------------------------- /src/jui/Controllable.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | public interface Controllable { 4 | 5 | } -------------------------------------------------------------------------------- /src/jui/Event.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | /** 4 | * Created by Jiachen on 30/04/2017. 5 | */ 6 | public enum Event { 7 | KEY_PRESSED, 8 | KEY_RELEASED, 9 | KEY_HELD, 10 | MOUSE_PRESSED, 11 | MOUSE_RELEASED, 12 | MOUSE_OVER, 13 | MOUSE_ENTERED, 14 | MOUSE_LEFT, 15 | MOUSE_WHEEL, 16 | MOUSE_DRAGGED, 17 | MOUSE_HELD,//TODO 18 | MOUSE_CLICKED, //TODO 19 | CONTENT_CHANGED, 20 | } 21 | -------------------------------------------------------------------------------- /src/jui/EventListener.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | /** 4 | * Created by Jiachen on 30/04/2017. 5 | */ 6 | public class EventListener { 7 | private Event event; 8 | private Runnable attachedMethod; 9 | private String id; 10 | private boolean disabled; 11 | 12 | public EventListener(String id, Event event) { 13 | this.event = event; 14 | this.id = id; 15 | disabled = false; 16 | } 17 | 18 | public Event getEvent() { 19 | return event; 20 | } 21 | 22 | public EventListener setEvent(Event event) { 23 | this.event = event; 24 | return this; 25 | } 26 | 27 | public void invoke() { 28 | if (attachedMethod != null && !disabled) 29 | attachedMethod.run(); 30 | } 31 | 32 | public EventListener attachMethod(Runnable runnable) { 33 | this.attachedMethod = runnable; 34 | return this; 35 | } 36 | 37 | public String getId() { 38 | return id; 39 | } 40 | 41 | public void setId(String temp) { 42 | this.id = temp; 43 | } 44 | 45 | public EventListener setDisabled(boolean disabled) { 46 | this.disabled = disabled; 47 | return this; 48 | } 49 | 50 | public boolean isDisabled() { 51 | return disabled; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/jui/HChart.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | /** 4 | * Created by Jiachen on 28/01/2017. 5 | */ 6 | public class HChart extends Chart { 7 | } 8 | -------------------------------------------------------------------------------- /src/jui/HItemBar.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | /** 4 | * Created by Jiachen on 28/01/2017. 5 | */ 6 | public class HItemBar extends ItemBar { 7 | } 8 | -------------------------------------------------------------------------------- /src/jui/HSlider.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | import processing.core.PConstants; 4 | 5 | public class HSlider extends Slider implements MouseControl { 6 | { 7 | setRollerScalingHeight(1.5f); 8 | setRollerScalingWidth(.5f); 9 | setRollerScalingRadius(.6f); 10 | syncSettings(); 11 | } 12 | 13 | public HSlider(float x, float y, float w, float h) { 14 | super(x, y, w, h); 15 | } 16 | 17 | public HSlider(float relativeW, float relativeH) { 18 | super(relativeW, relativeH); 19 | } 20 | 21 | public HSlider() { 22 | super(); 23 | } 24 | 25 | public void syncSettings() { 26 | barHeight = (int) (h * barScalingFactor); 27 | if (roller.shape == PConstants.RECT) roller.x = x + roller.w / 2; 28 | else roller.x = x + roller.r; 29 | roller.y = y + h / 2; 30 | roller.setEllipse(barHeight * getRollerScalingRadius()); 31 | roller.setRect(barHeight * getRollerScalingWidth(), barHeight * getRollerScalingHeight()); 32 | gridDotSize = (int) (barHeight / 3); 33 | barWidth = w; 34 | } 35 | 36 | //TODO, to be implemented 37 | public void updateRollerPos() { 38 | if (val > valueHigh || val < valueLow) { 39 | if (val != valueLow && val != valueHigh) 40 | System.err.println("ERROR: slider value cannot be set to " + val + "," + 41 | " out of range(" + valueLow + "->" + valueHigh + ")"); 42 | return; 43 | } 44 | float temp = roller.shape == PConstants.ELLIPSE ? roller.r * 2 : roller.w; 45 | float offset = (val - valueLow) / (valueHigh - valueLow) * (barWidth - temp); 46 | roller.setX(this.x + temp / 2.0f + offset); 47 | } 48 | 49 | public HSlider setScalingFactor(float temp) { 50 | barScalingFactor = temp; 51 | syncSettings(); 52 | return this; 53 | } 54 | 55 | 56 | public void mouseDragged() { 57 | if (isLockedOn) 58 | roller.x = JNode.getParent().mouseX; 59 | switch (roller.shape) { 60 | case PConstants.ELLIPSE: 61 | roller.x = roller.x < x + roller.r ? 62 | x + roller.r : roller.x; 63 | roller.x = roller.x > x + w - roller.r ? 64 | x + w - roller.r : roller.x; 65 | break; 66 | case PConstants.RECT: 67 | roller.x = roller.x < x + roller.w / 2 ? 68 | x + roller.w / 2 : roller.x; 69 | roller.x = roller.x > x + w - roller.w / 2 ? 70 | x + w - roller.w / 2 : roller.x; 71 | break; 72 | } 73 | } 74 | 75 | public void drawGrid() { 76 | //not yet implemented!!! draw a circle if ELLIPSE, rect otherwise. 77 | getParent().pushStyle(); 78 | getParent().strokeWeight(gridDotSize); 79 | getParent().stroke(gridDotColor); 80 | float d = 0; 81 | float curX = 0, curY = y + getHeight() / 2; 82 | switch (roller.shape) { 83 | case PConstants.ELLIPSE: 84 | curX = x + roller.r; 85 | d = gridInterval / (valueHigh - valueLow) * (w - roller.r * 2); 86 | break; 87 | case PConstants.RECT: 88 | curX = x + roller.w / 2; 89 | d = gridInterval / (valueHigh - valueLow) * (w - roller.w); 90 | break; 91 | } 92 | while (curX < (roller.shape == PConstants.ELLIPSE ? x + w - roller.r : x + w - roller.w / 2)) { 93 | getParent().point(curX, curY); 94 | curX += d; 95 | } 96 | getParent().popStyle(); 97 | } 98 | 99 | public float getFloatValue() { 100 | float val = 0.0f; 101 | switch (roller.shape) { 102 | case PConstants.ELLIPSE: 103 | val = (roller.x - x - roller.r) / ((w) - roller.r * 2) * (valueHigh - valueLow) + valueLow; 104 | break; 105 | case PConstants.RECT: 106 | val = ((float) ((roller.x - x - roller.w / 2.0) / (w - roller.w) * (valueHigh - valueLow))) + valueLow; 107 | break; 108 | } 109 | val = val < valueLow ? valueLow : val; 110 | return val > valueHigh ? valueHigh : val; //fixed Jan 25 111 | } 112 | 113 | @Override //moved from Slider to VSlider. April 22nd 114 | public void mousePressed() { 115 | super.mousePressed(); 116 | if (mouseOverBar()) { 117 | roller.x = JNode.getParent().mouseX; 118 | } 119 | if (mouseOverRoller() && onFocusMethod != null) 120 | onFocusMethod.run(); 121 | } 122 | } -------------------------------------------------------------------------------- /src/jui/Image.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | /*created Jan 26th.*/ 4 | /*this is now effectively the newest version of JUI, modified April 22th, 2017*/ 5 | public class Image /*extends Displayable*/ { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/jui/ItemBar.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | public class ItemBar{ 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/jui/KeyControl.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | /** 4 | * Created by Jiachen on 30/04/2017. 5 | */ 6 | public interface KeyControl extends Controllable{ 7 | public void keyPressed(); 8 | 9 | public void keyReleased(); 10 | } 11 | -------------------------------------------------------------------------------- /src/jui/Label.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | import processing.core.PConstants; 4 | 5 | //add public abstract void setValue(float val); 6 | //Jan 29th: deprecated all textHeight dividend variable in TextInput, Button, and Label. 7 | //TODO the adjustTextSize method should be replaced with a better one. April 22nd. 8 | public class Label extends Contextual { 9 | public Label(float x, float y, float w, float h) { 10 | super(x, y, w, h); 11 | init(); 12 | } 13 | 14 | public Label(float relativeW, float relativeH) { 15 | super(relativeW, relativeH); 16 | init(); 17 | } 18 | 19 | public Label() { 20 | super(); 21 | init(); 22 | } 23 | 24 | public Label(String content) { 25 | super(); 26 | init(); 27 | setContent(content); 28 | } 29 | 30 | public void init() { 31 | setTextMode(Mode.CONSTANT); 32 | setAlign(PConstants.LEFT); 33 | } 34 | 35 | 36 | public void display() { 37 | //drawing the background 38 | super.display(); /*modified April 22nd*/ 39 | displayText(); 40 | } 41 | 42 | @Override 43 | public Label setContent(String content) { 44 | super.setContent(content); 45 | return this; 46 | } 47 | 48 | @Override 49 | public Label setId(String id) { 50 | super.setId(id); 51 | return this; 52 | } 53 | 54 | @Override 55 | public Label clone() { 56 | return (Label) super.clone(); 57 | } 58 | } -------------------------------------------------------------------------------- /src/jui/MenuBar.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | /** 4 | * Created by Jiachen on 28/01/2017. 5 | */ 6 | public class MenuBar { 7 | } 8 | -------------------------------------------------------------------------------- /src/jui/MenuItem.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | import processing.core.PConstants; 4 | import processing.core.PFont; 5 | 6 | public class MenuItem extends Label implements MouseControl { 7 | private Runnable onClickMethod; 8 | private boolean mousePressedOnButton; 9 | private MenuDropdown menu; 10 | private boolean expandable; 11 | 12 | public MenuItem(String content) { 13 | super(); 14 | super.setContent(content); 15 | } 16 | 17 | public MenuItem onClick(Runnable r) { 18 | onClickMethod = r; 19 | return this; 20 | } 21 | 22 | public void mousePressed() { 23 | if (isMouseOver() && getParent().mouseButton == PConstants.LEFT) 24 | mousePressedOnButton = true; 25 | if (menu != null && expandable) { 26 | menu.mousePressed(); 27 | } 28 | } 29 | 30 | public void mouseReleased() { 31 | if (isVisible() && isMouseOver() && mousePressedOnButton) 32 | if (onClickMethod != null) onClickMethod.run(); 33 | mousePressedOnButton = false; 34 | if (menu != null && expandable) { 35 | menu.mouseReleased(); 36 | } 37 | } 38 | 39 | //implement keyboard shortcuts here 40 | public void keyPressed() { 41 | if (menu != null && expandable) 42 | menu.keyPressed(); 43 | } 44 | 45 | public void keyReleased() { 46 | if (menu != null && expandable) 47 | menu.keyReleased(); 48 | } 49 | 50 | public void mouseDragged() { 51 | //deprecated 52 | } 53 | 54 | public MenuItem bind(MenuDropdown menuDropdown) { 55 | expandable = true; 56 | menu = menuDropdown; 57 | menu.relocate(getX() + getWidth(), getY()); 58 | menu.setVisible(false); 59 | 60 | //modified Jan 25th 61 | /* 62 | menu.setDisplayCoutour(this.displayContour); 63 | menu.setBackgroundColor(this.backgroundColor); 64 | menu.setContourThickness(this.contourThickness); 65 | menu.setContourColor(this.contourColor); 66 | menu.setTextColor(this.textColor); 67 | menu.setMouseOverBackgroundColor(this.mouseOverBackgroundColor); 68 | menu.setAlign(this.alignment); 69 | menu.setTextFont(this.font); 70 | menu.setTextSize(this.textSize); 71 | */ 72 | return this; 73 | } 74 | 75 | public boolean isExpandable() { 76 | return expandable; 77 | } 78 | 79 | public boolean hasFocus() { 80 | return (this.isMouseOver() && isVisible()) || (menu != null && menu.hasFocus()); 81 | } 82 | 83 | //fixed!!!! three hours of work, only because I forgot to add setVisible!!! Jan 28th. 84 | private void update() { 85 | if (isMouseOver()) 86 | menu.triggered = true; 87 | else if (!isMouseOver() && !menu.hasFocus()) 88 | menu.triggered = false; 89 | if (hasFocus()) { 90 | menu.relocate(getX() + getWidth(), getY()); 91 | menu.setVisible(true); 92 | menu.run();//modified Jan 25th 93 | } else { 94 | menu.setVisible(false); 95 | } 96 | } 97 | 98 | public void display() { 99 | if (expandable && menu != null) update(); 100 | this.applyContourStyle(); 101 | this.applyBackgroundStyle(); 102 | super.drawRect(); 103 | super.displayText(); 104 | } 105 | 106 | @Override 107 | public void applyBackgroundStyle() { 108 | if (expandable) { 109 | if (menu == null) { 110 | getParent().fill(hasFocus() ? mouseOverBackgroundColor : backgroundColor); 111 | } else { 112 | getParent().fill(hasFocus() && menu.triggered ? mouseOverBackgroundColor : backgroundColor); 113 | } 114 | } else { 115 | getParent().fill(hasFocus() ? mouseOverBackgroundColor : backgroundColor); 116 | } 117 | } 118 | 119 | @Deprecated 120 | public void adjustTextSize() { 121 | } 122 | 123 | @Override 124 | public MenuItem setVisible(boolean temp) { 125 | if (menu != null) menu.setVisible(temp); 126 | this.isVisible = temp; 127 | return this; 128 | } 129 | 130 | @Override 131 | public MenuItem setRounded(boolean temp) { 132 | this.isRounded = temp; 133 | if (menu != null) menu.setRounded(temp); 134 | return this; 135 | } 136 | 137 | @Override 138 | public MenuItem setContourColor(int c) { 139 | contourColor = c; 140 | if (menu != null) menu.setContourColor(contourColor); 141 | return this; 142 | } 143 | 144 | 145 | @Override 146 | public MenuItem setContourThickness(float thickness) { 147 | contourThickness = thickness; 148 | if (menu != null) menu.setContourThickness(contourThickness); 149 | return this; 150 | } 151 | 152 | @Override 153 | public MenuItem setContourVisible(boolean temp) { 154 | displayContour = temp; 155 | if (menu != null) menu.setContourVisible(displayContour); 156 | return this; 157 | } 158 | 159 | 160 | @Override 161 | public MenuItem setBackgroundColor(int c) { 162 | backgroundColor = c; 163 | if (menu != null) menu.setBackgroundColor(backgroundColor); 164 | return this; 165 | } 166 | 167 | 168 | @Override 169 | public MenuItem setMouseOverBackgroundColor(int c) { 170 | mouseOverBackgroundColor = c; 171 | if (menu != null) 172 | menu.setMouseOverBackgroundColor(mouseOverBackgroundColor); 173 | return this; 174 | } 175 | 176 | 177 | @Override 178 | public MenuItem setMousePressedBackgroundColor(int c) { 179 | mousePressedBackgroundColor = c; 180 | if (menu != null) 181 | menu.setMousePressedBackgroundColor(mousePressedBackgroundColor); 182 | return this; 183 | } 184 | 185 | @Override 186 | public MenuItem setTextColor(int c) { 187 | super.setTextColor(c); 188 | if (menu != null) menu.setTextColor(getTextColor()); 189 | return this; 190 | } 191 | 192 | @Override 193 | public MenuItem setTextFont(PFont font) { 194 | this.font = font; 195 | if (menu != null) menu.setTextFont(this.font); 196 | return this; 197 | } 198 | 199 | public MenuItem setTextSize(int textSize) { 200 | super.setTextSize(textSize); 201 | if (menu != null) menu.setTextSize(textSize); 202 | return this; 203 | } 204 | 205 | @Override 206 | public MenuItem setAlign(int align) { 207 | this.alignment = align; 208 | if (menu != null) menu.setAlign(alignment); 209 | return this; 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/jui/Mode.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | /** 4 | * Style Control for background/contour/text color 5 | */ 6 | public enum Mode { 7 | CONSTANT(0), VOLATILE(1), DISABLED(2); 8 | private int val; 9 | 10 | Mode(int i) { 11 | val = i; 12 | } 13 | 14 | public int getValue() { 15 | return val; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/jui/MouseControl.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | /** 4 | * Created by Jiachen on 30/04/2017. 5 | */ 6 | public interface MouseControl extends Controllable { 7 | boolean isMouseOver(); 8 | 9 | void mouseReleased(); 10 | 11 | void mousePressed(); 12 | 13 | void mouseDragged(); 14 | 15 | void mouseWheel(); 16 | } 17 | -------------------------------------------------------------------------------- /src/jui/ProgressBar.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | import processing.core.PApplet; 4 | import processing.core.PConstants; 5 | 6 | import static processing.core.PConstants.CENTER; 7 | import static processing.core.PConstants.LEFT; 8 | import static processing.core.PConstants.RIGHT; 9 | 10 | /** 11 | * Class ProgressBar. Written by Jiachen on 29/04/2017. 12 | */ 13 | public class ProgressBar extends Contextual implements Scalable { 14 | private float scalingFactor; 15 | private float widthScalingFactor; 16 | private float barHeight; 17 | private float barWidth; 18 | private float barY; 19 | private int progressBackgroundColor; 20 | private PApplet parent; 21 | private float percentageCompleted; 22 | private boolean completed; 23 | private boolean percentageVisible; 24 | private Style percentageTextStyle = Style.END; 25 | private Label percentageLabel; 26 | private String formattedPercentage; 27 | 28 | public enum Style { 29 | END, MIDDLE, LEFT,RIGHT 30 | } 31 | 32 | public ProgressBar(float x, float y, float w, float h) { 33 | super(x, y, w, h); 34 | init(); 35 | resize(w, h); 36 | relocate(x, y); 37 | } 38 | 39 | public ProgressBar(float relativeW, float relativeH) { 40 | super(relativeW, relativeH); 41 | init(); 42 | } 43 | 44 | public ProgressBar() { 45 | super(); 46 | init(); 47 | } 48 | 49 | private void init() { 50 | percentageLabel = (Label) new Label().setVisible(false); 51 | setScalingFactor(0.6f); 52 | setPercentageVisible(true); 53 | setPercentageTextStyle(Style.END); 54 | percentageLabel.setAlign(CENTER); 55 | this.setAlign(CENTER); 56 | setProgressBackgroundColor(mouseOverBackgroundColor); 57 | parent = JNode.getParent(); 58 | setCompletedPercentage(0.0f); 59 | setWidthScalingFactor(0.85f); 60 | } 61 | 62 | public ProgressBar setScalingFactor(float scale) { 63 | this.scalingFactor = scale; 64 | return this; 65 | } 66 | 67 | @Override 68 | public void display() { 69 | parent.pushStyle(); 70 | applyContourStyle(); 71 | applyBackgroundStyle(); 72 | if (isRounded) parent.rect(x, barY, barWidth, barHeight, rounding); 73 | else parent.rect(x, barY, barWidth, barHeight); 74 | parent.popStyle(); 75 | 76 | parent.fill(progressBackgroundColor); 77 | parent.noStroke(); 78 | parent.rectMode(PConstants.CORNER); 79 | if (isRounded) parent.rect(x, barY, barWidth * percentageCompleted, barHeight, rounding); 80 | else parent.rect(x, barY, barWidth * percentageCompleted, barHeight); 81 | 82 | if (percentageVisible) { 83 | if (percentageTextStyle.equals(Style.END)) { 84 | 85 | } else if (percentageTextStyle.equals(Style.LEFT)) { 86 | 87 | } 88 | switch (percentageTextStyle){ 89 | case END: 90 | this.applyTextColor(); 91 | percentageLabel.displayRawText(getContent()); 92 | break; 93 | case MIDDLE: 94 | setAlign(CENTER); 95 | displayText(formattedPercentage); 96 | break; 97 | case LEFT: 98 | setAlign(LEFT); 99 | displayText(formattedPercentage); 100 | break; 101 | case RIGHT: 102 | setAlign(RIGHT); 103 | displayText(formattedPercentage); 104 | break; 105 | } 106 | } 107 | } 108 | 109 | private String formatPercentage(float input) { 110 | input *= 100; 111 | String temp = Float.toString(input); 112 | if (!temp.contains(".")) return "%"; 113 | else { 114 | int index = temp.indexOf(".") + 2; 115 | int t = temp.length(); 116 | return temp.substring(0, index > t ? t : index) + "%"; 117 | } 118 | } 119 | 120 | @Override 121 | public void resize(float w, float h) { 122 | super.resize(w, h); 123 | if (percentageTextStyle.equals(Style.END) && percentageVisible) { 124 | this.barWidth = w * widthScalingFactor; 125 | } else { 126 | this.barWidth = w; 127 | } 128 | this.barHeight = h * scalingFactor; 129 | /*TODO should the height of the label be h or barHeight?*/ 130 | percentageLabel.resize(w * (1.0f - widthScalingFactor), h); 131 | } 132 | 133 | @Override 134 | public void relocate(float x, float y) { 135 | super.relocate(x, y); 136 | barY = y + h / 2 - barHeight / 2; 137 | percentageLabel.relocate(x + barWidth, y); 138 | } 139 | 140 | public ProgressBar setProgressBackgroundColor(int c) { 141 | progressBackgroundColor = c; 142 | return this; 143 | } 144 | 145 | public ProgressBar setProgressBackgroundColor(int r, int g, int b) { 146 | progressBackgroundColor = parent.color(r, g, b); 147 | return this; 148 | } 149 | 150 | public ProgressBar setProgressBackgroundColor(int r, int g, int b, int a) { 151 | progressBackgroundColor = parent.color(r, g, b, a); 152 | return this; 153 | } 154 | 155 | public ProgressBar setCompletedPercentage(float temp) { 156 | if (temp >= 1.0f) { 157 | temp = 1.0f; 158 | completed = true; 159 | } 160 | percentageCompleted = temp; 161 | formattedPercentage = formatPercentage(percentageCompleted); 162 | percentageLabel.setContent(formattedPercentage); 163 | return this; 164 | } 165 | 166 | public boolean hasCompleted() { 167 | return completed; 168 | } 169 | 170 | /** 171 | * only applicable if Style is .END 172 | */ 173 | public ProgressBar setWidthScalingFactor(float scale) { 174 | scale = scale > 0.9f ? 0.9f : scale; 175 | widthScalingFactor = scale; 176 | resize(w, h); 177 | return this; 178 | } 179 | 180 | public ProgressBar setPercentageTextStyle(Style style) { 181 | this.percentageTextStyle = style; 182 | resize(w, h); 183 | return this; 184 | } 185 | 186 | public ProgressBar setPercentageVisible(boolean temp) { 187 | percentageVisible = temp; 188 | resize(w, h); 189 | return this; 190 | } 191 | 192 | @Override 193 | public ProgressBar setAlign(int align) { 194 | super.setAlign(align); 195 | return this; 196 | } 197 | 198 | public float getPercentageCompleted(){ 199 | return percentageCompleted; 200 | } 201 | 202 | public Label getPercentageLabel() { 203 | return percentageLabel; 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /src/jui/Scalable.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | /** 4 | * Created by Jiachen on 29/04/2017. 5 | */ 6 | public interface Scalable { 7 | Displayable setScalingFactor(float scale); 8 | } 9 | -------------------------------------------------------------------------------- /src/jui/SpaceHolder.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | /** 4 | * Created by Jiachen on 26/04/2017. 5 | */ 6 | public class SpaceHolder extends Displayable { 7 | public SpaceHolder(float relativeW, float relativeH) { 8 | super(relativeW, relativeH); 9 | init(); 10 | } 11 | 12 | public SpaceHolder() { 13 | super(); 14 | init(); 15 | } 16 | 17 | public SpaceHolder(float x, float y, float w, float h) { 18 | super(x, y, w, h); 19 | init(); 20 | } 21 | 22 | private void init() { 23 | setVisible(false); 24 | } 25 | 26 | @Override 27 | public void display() { 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/jui/Switch.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | public class Switch extends Button { 4 | private String contentOff; 5 | private boolean isOn; 6 | private int backgroundColorOff; 7 | private int contourColorOff; 8 | private int textColorOff; 9 | private boolean pressedOnTarget; 10 | private String contentOn; 11 | 12 | public Switch(float x, float y, float w, float h) { 13 | super(x, y, w, h); 14 | } 15 | 16 | public Switch(float relativeW, float relativeH) { 17 | super(relativeW, relativeH); 18 | } 19 | 20 | public Switch() { 21 | super(); 22 | } 23 | 24 | @Override 25 | public void init() { 26 | super.init(); 27 | backgroundColorOff = backgroundColor; 28 | contourColorOff = contourColor; 29 | textColorOff = getTextColor(); 30 | this.addEventListener("@RESERVED", Event.MOUSE_PRESSED, () -> pressedOnTarget = true); 31 | this.addEventListener("@RESERVED", Event.MOUSE_LEFT, () -> pressedOnTarget = false); 32 | this.addEventListener("@RESERVED", Event.MOUSE_RELEASED, () -> { 33 | if (pressedOnTarget) setState(!isOn); 34 | pressedOnTarget = false; 35 | }); 36 | } 37 | 38 | public Switch setContentOff(String contentOff) { 39 | this.contentOff = contentOff; 40 | super.setContent(contentOff); 41 | return this; 42 | } 43 | 44 | public boolean isOn() { 45 | return isOn; 46 | } 47 | 48 | public Switch setBackgroundColorOff(int color) { 49 | this.backgroundColorOff = color; 50 | return this; 51 | } 52 | 53 | public Switch setContourColorOff(int color) { 54 | this.contourColorOff = color; 55 | return this; 56 | } 57 | 58 | public Switch setTextColorOff(int color) { 59 | this.textColorOff = color; 60 | return this; 61 | } 62 | 63 | @SuppressWarnings("deprecation") 64 | private Switch updateState() { 65 | setContent(isOn ? contentOn : contentOff); 66 | setBackgroundColor(isOn ? backgroundColor : backgroundColorOff); 67 | setTextColor(isOn ? getTextColor() : textColorOff); 68 | setContourColor(isOn ? contourColor : contourColorOff); 69 | return this; 70 | } 71 | 72 | public Switch setState(boolean isOn) { 73 | this.isOn = isOn; 74 | updateState(); 75 | return this; 76 | } 77 | 78 | public Switch setContentOn(String s) { 79 | super.setContent(s); 80 | this.contentOn = s; 81 | return this; 82 | } 83 | 84 | @Override 85 | public Switch inheritOutlook(Displayable other) { 86 | super.inheritOutlook(other); 87 | return this; 88 | } 89 | 90 | @Override 91 | public Switch inheritMode(Displayable other) { 92 | super.inheritMode(other); 93 | return this; 94 | } 95 | 96 | @Deprecated 97 | public Switch setContent(String s) { 98 | super.setContent(s); 99 | return this; 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/jui/TextField.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | import processing.core.PConstants; 4 | import processing.core.PGraphics; 5 | 6 | import java.io.IOException; 7 | import java.nio.file.Files; 8 | import java.nio.file.Paths; 9 | 10 | //designing. Jan 27th. Remember to implement mouseWheel() 11 | //building class, Jan 30th. PGraphics class is applied. 12 | //not finished Jan 30th. 13 | /*April 22nd: text wrapped withing text box!!! text(str,x,y,w,h)*/ 14 | //TODO: complete designing the class. 15 | public class TextField extends Contextual { 16 | private int spacing; 17 | private float textHeight; 18 | private PGraphics textArea; 19 | private int tx, ty; 20 | 21 | public TextField(float x, float y, float w, float h) { 22 | super(x, y, w, h); 23 | init(); 24 | } 25 | 26 | public TextField(float relativeW, float relativeH) { 27 | super(relativeW, relativeH); 28 | init(); 29 | } 30 | 31 | public TextField() { 32 | super(); 33 | init(); 34 | } 35 | 36 | private void init() { 37 | //setTextSize(15); //setting the default text size to 15 38 | //textHeight = this.getTextDimension("a")[1]; 39 | setAlign(PConstants.LEFT); 40 | setSpacing(5); 41 | updateTextAreaDim(); 42 | } 43 | 44 | public void display() { 45 | //drawing the background 46 | //does not work with FX2D!!! 47 | if (font != null) textArea.textFont(font); 48 | super.display(); 49 | 50 | //displaying the texts on the PGraphics unit, creating a second layer. 51 | 52 | if (textArea == null) return; 53 | textArea.beginDraw(); 54 | textArea.background(this.backgroundColor); 55 | textArea.fill(getTextColor()); 56 | //if (textSize > 0.0) textArea.textSize(textSize); 57 | textArea.textAlign(alignment); 58 | //textArea.background(0,0,0); testing completed. Jan 30th. 9:59 PM. 59 | textArea.text("Hello, My name is Jiachen. I built JUI", textArea.width / 2, textArea.height / 2); 60 | textArea.endDraw(); 61 | getParent().image(textArea, tx, ty); 62 | 63 | 64 | } 65 | 66 | private void updateTextAreaDim() { 67 | /* 68 | fill the width method. 69 | textArea.width = w; 70 | textArea.height = this.getHeight()-(isRounded?rounding*2:0); 71 | tx = x; 72 | ty = y+(isRounded?rounding:0); 73 | */ 74 | 75 | /* 76 | fill the height (which I decided is more reasonable) 77 | textArea = getParent().createGraphics(getWidth() - (isRounded ? rounding * 2 : 0), this.getHeight(), getParent().sketchRenderer()); 78 | textArea.pixelDensity = getParent().pixelDensity; 79 | //System.err.println(textArea.width); 80 | tx = x + (isRounded ? rounding : 0); 81 | ty = y; 82 | */ 83 | 84 | } 85 | 86 | /** 87 | * TODO to be completed 88 | * @param path the path of the file to be loaded 89 | * @return this instance of text field 90 | */ 91 | public TextField load(String path) { 92 | try { 93 | new String(Files.readAllBytes(Paths.get(path))); 94 | } catch (IOException e) { 95 | e.printStackTrace(); 96 | } 97 | return this; 98 | } 99 | 100 | public TextField append() { 101 | return this; 102 | } 103 | 104 | 105 | public TextField setSpacing(int temp) { 106 | this.spacing = temp; 107 | return this; 108 | } 109 | 110 | @Override 111 | public void resize(float w, float h) { 112 | super.resize(w, h); 113 | updateTextAreaDim(); 114 | } 115 | 116 | @Override 117 | public TextField setRounded(boolean temp) { 118 | super.setRounded(temp); 119 | updateTextAreaDim(); 120 | return this; 121 | } 122 | 123 | @Override 124 | public void relocate(float x, float y) { 125 | super.relocate(x, y); 126 | updateTextAreaDim(); 127 | } 128 | } -------------------------------------------------------------------------------- /src/jui/VChart.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | /** 4 | * Created by Jiachen on 28/01/2017. 5 | */ 6 | public class VChart extends Chart { 7 | } 8 | -------------------------------------------------------------------------------- /src/jui/VItemBar.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | public class VItemBar extends ItemBar{ 4 | VItemBar(){ 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/jui/VSlider.java: -------------------------------------------------------------------------------- 1 | package jui; 2 | 3 | import processing.core.PConstants; 4 | 5 | public class VSlider extends Slider implements MouseControl { 6 | 7 | { 8 | setRollerScalingHeight(.5f); 9 | setRollerScalingWidth(1.5f); 10 | setRollerScalingRadius(.6f); 11 | syncSettings(); 12 | } 13 | 14 | public VSlider(float x, float y, float w, float h) { 15 | super(x, y, w, h); 16 | } 17 | 18 | public VSlider(float relativeW, float relativeH) { 19 | super(relativeW, relativeH); 20 | } 21 | 22 | public VSlider(String id) { 23 | super(); 24 | } 25 | 26 | /** 27 | * Jan 4th, Roller Shape Ellipse needs to be added 28 | * updates the position of the roller. 29 | * 30 | * @since April 24th roller ellipse shape is considered. 31 | */ 32 | public void updateRollerPos() { 33 | if (val > valueHigh || val < valueLow) { 34 | if (val != valueLow && val != valueHigh) 35 | System.err.println(id + " : slider value cannot be set to " + val + ", out of range(" + valueLow + "->" + valueHigh + ")"); 36 | return; 37 | } 38 | float temp = roller.shape == PConstants.ELLIPSE ? roller.r * 2 : roller.h; 39 | float offset = (val - valueLow) / (valueHigh - valueLow) * (barHeight - temp); 40 | roller.setY(this.y + barHeight - temp / 2.0f - offset); 41 | } 42 | 43 | 44 | /** 45 | * @since May 2nd bug fixes. A bunch of unnecessary int casts were taken out 46 | * Synchronizes the appearance and dimension of the rectangular slider bar and 47 | * the roller according to the new dimension of the displayable object. 48 | */ 49 | public void syncSettings() { 50 | barWidth = w * barScalingFactor; 51 | if (roller.shape == PConstants.RECT) roller.y = y + h - roller.h / 2; 52 | else roller.y = y + h - roller.r; 53 | roller.x = x + w / 2; 54 | roller.setEllipse(barWidth * getRollerScalingRadius()); 55 | roller.setRect(barWidth * getRollerScalingWidth(), barWidth * getRollerScalingHeight()); 56 | barHeight = h; 57 | } 58 | 59 | public VSlider setScalingFactor(float temp) { 60 | barScalingFactor = temp; 61 | syncSettings(); 62 | return this; 63 | } 64 | 65 | public void mouseDragged() { 66 | if (isLockedOn) { 67 | roller.y = getParent().mouseY; 68 | roller.x = x + w / 2; 69 | } 70 | switch (roller.shape) { 71 | case PConstants.ELLIPSE: 72 | roller.y = roller.y < y + roller.r ? y + roller.r : roller.y; 73 | roller.y = roller.y > y + h - roller.r ? y + h - roller.r : roller.y; 74 | break; 75 | case PConstants.RECT: 76 | roller.y = roller.y < y + roller.h / 2 ? y + roller.h / 2 : roller.y; 77 | roller.y = roller.y > y + h - roller.h / 2 ? y + h - roller.h / 2 : roller.y; 78 | break; 79 | } 80 | } 81 | 82 | @Override 83 | public void mousePressed() { 84 | super.mousePressed(); 85 | if (mouseOverBar()) 86 | roller.y = getParent().mouseY; 87 | if (mouseOverRoller() && onFocusMethod != null) 88 | onFocusMethod.run(); 89 | } 90 | 91 | public void drawGrid() { 92 | getParent().pushStyle(); 93 | getParent().strokeWeight(gridDotSize); 94 | getParent().stroke(gridDotColor); 95 | float d = 0; 96 | float curX = x + getWidth() / 2, curY = 0; 97 | switch (roller.shape) { 98 | case PConstants.ELLIPSE: 99 | curY = y + roller.r; 100 | d = gridInterval / (valueHigh - valueLow) * (h - roller.r * 2); 101 | break; 102 | case PConstants.RECT: 103 | curY = y + roller.h / 2; 104 | d = gridInterval / (valueHigh - valueLow) * (h - roller.h); 105 | break; 106 | } 107 | while (curY < (roller.shape == PConstants.ELLIPSE ? y + h - roller.r : y + h - roller.h / 2)) { 108 | getParent().point(curX, curY); 109 | curY += d; 110 | } 111 | getParent().popStyle(); 112 | } 113 | 114 | public float getFloatValue() { 115 | float val = 0.0f; 116 | switch (roller.shape) { 117 | case PConstants.ELLIPSE: 118 | val = ((y + h - roller.r) - roller.y) / (h - roller.r * 2) * (valueHigh - valueLow) + valueLow; 119 | break; 120 | case PConstants.RECT: 121 | val = ((y + h - roller.h / 2) - roller.y) / (h - 122 | roller.h) * (valueHigh - valueLow) + valueLow; 123 | break; 124 | } 125 | val = val < valueLow ? valueLow : val; 126 | return val > valueHigh ? valueHigh : val; 127 | } 128 | 129 | } -------------------------------------------------------------------------------- /src/jui/bundles/EnumSelector.java: -------------------------------------------------------------------------------- 1 | package jui.bundles; 2 | 3 | import jui.Button; 4 | import jui.HBox; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | 9 | /** 10 | * Created by Jiachen on 30/04/2017. 11 | */ 12 | public class EnumSelector extends HBox { 13 | private ArrayList