diff --git a/res/font_ex.rft b/res/font_ex.rft index 1f79a6e9..18475d17 100644 Binary files a/res/font_ex.rft and b/res/font_ex.rft differ diff --git a/src/org/warp/picalculator/TestGPU.java b/src/org/warp/picalculator/TestGPU.java index 8ea9b711..c88deb0e 100644 --- a/src/org/warp/picalculator/TestGPU.java +++ b/src/org/warp/picalculator/TestGPU.java @@ -10,6 +10,7 @@ import org.warp.picalculator.gui.expression.BlockContainer; import org.warp.picalculator.gui.expression.BlockDivision; import org.warp.picalculator.gui.expression.Caret; import org.warp.picalculator.gui.expression.CaretState; +import org.warp.picalculator.gui.expression.containers.NormalInputContainer; import org.warp.picalculator.gui.graphicengine.BinaryFont; import org.warp.picalculator.gui.graphicengine.Skin; import org.warp.picalculator.gui.graphicengine.cpu.CPUEngine; @@ -20,7 +21,7 @@ import org.warp.picalculator.gui.screens.MarioScreen; import org.warp.picalculator.math.MathContext; import org.warp.picalculator.math.MathematicalSymbols; import org.warp.picalculator.math.functions.Expression; -import org.warp.picalculator.math.parser.InputParser; +import org.warp.picalculator.math.parser.MathParser; import java.lang.management.ManagementFactory; import java.lang.management.OperatingSystemMXBean; @@ -48,7 +49,7 @@ public class TestGPU { private final Renderer r; private final GraphicEngine d; - private final BlockContainer c; + private final NormalInputContainer c; public Scene(GraphicEngine d) throws IOException, Error { this.d = d; @@ -62,22 +63,21 @@ public class TestGPU { //New expression framework test - c = new BlockContainer(false, 0, 200); - BlockDivision bd = new BlockDivision(); - c.addBlock(bd); - bd.getUpperContainer().addBlock(new BlockChar('5')); - bd.getUpperContainer().addBlock(new BlockChar(MathematicalSymbols.MULTIPLICATION)); - bd.getUpperContainer().addBlock(new BlockChar('2')); - bd.getLowerContainer().addBlock(new BlockChar('2')); - bd.recomputeDimensions(); - c.addBlock(new BlockChar(MathematicalSymbols.MULTIPLICATION)); - c.addBlock(new BlockChar('2')); - c.addBlock(new BlockChar('2')); - c.addBlock(new BlockChar('b')); + c = new NormalInputContainer(false, 0, 200); + c.typeChar(MathematicalSymbols.DIVISION); + c.typeChar('5'); + c.typeChar(MathematicalSymbols.MULTIPLICATION); + c.typeChar('2'); + c.moveRight(); + c.typeChar('2'); + c.moveRight(); + c.typeChar(MathematicalSymbols.MULTIPLICATION); + c.typeChar('2'); + c.typeChar('2'); c.recomputeDimensions(); - Expression expr = InputParser.parseInput(new MathContext(), c); - System.out.println(expr.toString()); + Expression expr = MathParser.parseInput(new MathContext(), c.root); + System.out.println("Parsed input:"+expr.toString()); d.start(this); @@ -119,7 +119,7 @@ public class TestGPU { r.glFillRect(162, 2.5f, 160, 160, 0, 0, 16, 16); //New expression framework test - c.draw(d, r, 10, 220, new Caret(CaretState.VISIBLE_ON, 10)); + c.draw(d, r, 10, 220); } } diff --git a/src/org/warp/picalculator/device/PIDisplay.java b/src/org/warp/picalculator/device/PIDisplay.java index dd2068cb..1910e5b0 100644 --- a/src/org/warp/picalculator/device/PIDisplay.java +++ b/src/org/warp/picalculator/device/PIDisplay.java @@ -25,16 +25,6 @@ import org.warp.picalculator.device.graphicengine.RAWFont; import org.warp.picalculator.device.graphicengine.Screen; import com.pi4j.wiringpi.Gpio; -/** - * STB Truetype oversampling demo. - * - *

- * This is a Java port of https:/ - * /github - * .com/nothings/stb/blob/master/tests/oversample/main.c. - *

- */ public final class PIDisplay { public static PIDisplay INSTANCE; private static float brightness; diff --git a/src/org/warp/picalculator/gui/DisplayManager.java b/src/org/warp/picalculator/gui/DisplayManager.java index 8b91a077..cd1be4ef 100644 --- a/src/org/warp/picalculator/gui/DisplayManager.java +++ b/src/org/warp/picalculator/gui/DisplayManager.java @@ -356,7 +356,7 @@ public final class DisplayManager implements RenderingLoop { Main.screenSize[1] = engine.getHeight(); } }; - + public void loop() { try { load_skin(); diff --git a/src/org/warp/picalculator/gui/expression/Block.java b/src/org/warp/picalculator/gui/expression/Block.java index 85967e38..b1d2ffb8 100644 --- a/src/org/warp/picalculator/gui/expression/Block.java +++ b/src/org/warp/picalculator/gui/expression/Block.java @@ -5,7 +5,7 @@ import org.warp.picalculator.gui.graphicengine.Renderer; import org.warp.picalculator.math.parser.features.interfaces.Feature; public abstract class Block implements GraphicalElement { - + protected boolean small; protected int width; protected int height; @@ -20,6 +20,10 @@ public abstract class Block implements GraphicalElement { */ public abstract void draw(GraphicEngine ge, Renderer r, int x, int y, Caret caret); + public abstract boolean putBlock(Caret caret, Block newBlock); + + public abstract boolean delBlock(Caret caret); + @Override public abstract void recomputeDimensions(); @@ -44,4 +48,5 @@ public abstract class Block implements GraphicalElement { public abstract void setSmall(boolean small); + public abstract int getClassID(); } diff --git a/src/org/warp/picalculator/gui/expression/BlockChar.java b/src/org/warp/picalculator/gui/expression/BlockChar.java index 18c87c50..04f3e6a0 100644 --- a/src/org/warp/picalculator/gui/expression/BlockChar.java +++ b/src/org/warp/picalculator/gui/expression/BlockChar.java @@ -6,7 +6,9 @@ import org.warp.picalculator.math.parser.features.FeatureChar; import org.warp.picalculator.math.parser.features.interfaces.Feature; public class BlockChar extends Block { - + + public static final int CLASS_ID = 0x00000001; + private final char ch; public BlockChar(char ch) { @@ -21,6 +23,16 @@ public class BlockChar extends Block { r.glDrawCharLeft(x, y, ch); } + @Override + public boolean putBlock(Caret caret, Block newBlock) { + return false; + } + + @Override + public boolean delBlock(Caret caret) { + return false; + } + @Override public void recomputeDimensions() { width = BlockContainer.getDefaultCharWidth(small); @@ -38,4 +50,9 @@ public class BlockChar extends Block { return ch; } + @Override + public int getClassID() { + return CLASS_ID; + } + } diff --git a/src/org/warp/picalculator/gui/expression/BlockContainer.java b/src/org/warp/picalculator/gui/expression/BlockContainer.java index 51235657..332975c5 100644 --- a/src/org/warp/picalculator/gui/expression/BlockContainer.java +++ b/src/org/warp/picalculator/gui/expression/BlockContainer.java @@ -11,6 +11,8 @@ import org.warp.picalculator.gui.graphicengine.gpu.GPUFont; public class BlockContainer implements GraphicalElement { + private static boolean initialized = false; + private final int minWidth; private final int minHeight; private final ObjectArrayList content; @@ -18,32 +20,54 @@ public class BlockContainer implements GraphicalElement { private int width; private int height; private int line; + public final boolean withBorder; public BlockContainer() { - this(false, BlockContainer.getDefaultCharWidth(true), BlockContainer.getDefaultCharHeight(true)); + this(false, BlockContainer.getDefaultCharWidth(false), BlockContainer.getDefaultCharHeight(false), true); } public BlockContainer(boolean small) { - this(small, BlockContainer.getDefaultCharWidth(true), BlockContainer.getDefaultCharHeight(true)); + this(small, BlockContainer.getDefaultCharWidth(small), BlockContainer.getDefaultCharHeight(small), true); } - public BlockContainer(boolean small, int minWidth, int minHeight) { - this(small, minWidth, minHeight, new ObjectArrayList<>()); + public BlockContainer(boolean small, boolean withBorder) { + this(small, BlockContainer.getDefaultCharWidth(small), BlockContainer.getDefaultCharHeight(small), withBorder); } - public BlockContainer(boolean small, int minWidth, int minHeight, ObjectArrayList content) { + public BlockContainer(boolean small, int minWidth, int minHeight, boolean withBorder) { + this(small, minWidth, minHeight, new ObjectArrayList<>(), withBorder); + } + + public BlockContainer(boolean small, int minWidth, int minHeight, ObjectArrayList content, boolean withBorder) { this.small = small; this.minWidth = minWidth; this.minHeight = minHeight; + this.withBorder = withBorder; for (Block b: content) { - b.setSmall(small); + if (b.isSmall() != small) { + b.setSmall(small); + } } this.content = content; recomputeDimensions(); } + + public void addBlock(int position, Block b) { + if (b.isSmall() != small) { + b.setSmall(small); + } + if (position >= content.size()) { + content.add(b); + } else { + content.add(position, b); + } + recomputeDimensions(); + } - public void addBlock(Block b) { - b.setSmall(small); + public void appendBlock(Block b) { + if (b.isSmall() != small) { + b.setSmall(small); + } content.add(b); recomputeDimensions(); } @@ -76,25 +100,81 @@ public class BlockContainer implements GraphicalElement { * @param caret Position of the caret. */ public void draw(GraphicEngine ge, Renderer r, int x, int y, Caret caret) { - int paddingX = 0; + int paddingX = 1; if (caret.getRemaining() == 0) { if (content.size() > 0) { - BlockContainer.drawCaret(ge, r, caret, x, y, content.get(0).getHeight()); + BlockContainer.drawCaret(ge, r, caret, x, y+line-content.get(0).line, content.get(0).height); } else { BlockContainer.drawCaret(ge, r, caret, x, y, height); } } - for (Block b : content) { - caret.skip(1); - b.draw(ge, r, x+paddingX, y+line-b.getLine(), caret); - paddingX += b.getWidth(); - if (caret.getRemaining() == 0) BlockContainer.drawCaret(ge, r, caret, x + paddingX, y+line-b.getLine(), b.height); + if (withBorder && content.size() == 0) { + r.glDrawLine(x+paddingX, y, x+paddingX+width-1, y); + r.glDrawLine(x+paddingX, y, x+paddingX, y+height-1); + r.glDrawLine(x+paddingX+width-1, y, x+paddingX+width-1, y+height-1); + r.glDrawLine(x+paddingX, y+height-1, x+paddingX+width-1, y+height-1); + } else { + for (Block b : content) { + caret.skip(1); + b.draw(ge, r, x+paddingX, y+line-b.line, caret); + paddingX += b.getWidth(); + if (caret.getRemaining() == 0) BlockContainer.drawCaret(ge, r, caret, x + paddingX, y+line-b.line, b.height); + paddingX += 1; + } } caret.skip(1); } + public boolean putBlock(Caret caret, Block newBlock) { + boolean added = false; + + if (caret.getRemaining() == 0) { + this.addBlock(0, newBlock); + added = true; + } + + int pos = 0; + for (Block b : content) { + caret.skip(1); + pos++; + added = added|b.putBlock(caret, newBlock); + if (caret.getRemaining() == 0) { + this.addBlock(pos, newBlock); + added = true; + } + } + caret.skip(1); + if (added) { + recomputeDimensions(); + } + return added; + } + + public boolean delBlock(Caret caret) { + boolean removed = false; + + int pos = 0; + for (Block b : content) { + caret.skip(1); + pos++; + int deltaCaret = caret.getRemaining(); + removed = removed|b.delBlock(caret); + if (caret.getRemaining() == 0 || (removed == false && deltaCaret >= 0 && caret.getRemaining() < 0)) { + this.removeAt(pos-1); + caret.setPosition(caret.getPosition()-deltaCaret); + removed = true; + } + } + caret.skip(1); + if (removed) { + recomputeDimensions(); + } + return removed; + } + + @Override public void recomputeDimensions() { int l = 0; //Line @@ -103,7 +183,7 @@ public class BlockContainer implements GraphicalElement { int h = 0; //Height for (Block b : content) { - w += b.getWidth(); + w += b.getWidth() + 1; final int bl = b.getLine(); final int bh = b.getHeight(); final int bh2 = bh - bl; @@ -115,6 +195,10 @@ public class BlockContainer implements GraphicalElement { } } + if (content.size() > 0) { + w -= 1; + } + h = h2 + l; line = l; @@ -127,6 +211,7 @@ public class BlockContainer implements GraphicalElement { height = h; } else { height = minHeight; + line = height/2; } } @@ -156,29 +241,35 @@ public class BlockContainer implements GraphicalElement { defFontSizes[1] = big.getCharacterHeight(); defFontSizes[2] = small.getCharacterWidth(); defFontSizes[3] = small.getCharacterHeight(); + initialized = true; } public static BinaryFont getDefaultFont(boolean small) { + checkInitialized(); return defFonts[small?1:0]; } - public static int getDefaultColor() { return defColor; } public static int getDefaultCharWidth(boolean b) { + checkInitialized(); return defFontSizes[b?2:0]; } public static int getDefaultCharHeight(boolean b) { + checkInitialized(); return defFontSizes[b?3:1]; } public static void drawCaret(GraphicEngine ge, Renderer r, Caret caret, int x, int y, int height) { - r.glColor(getDefaultColor()); - r.glDrawLine(x, y, x, y-1+height); - r.glDrawLine(x+1, y, x+1, y-1+height); + if (caret.getState() == CaretState.VISIBLE_ON) { + r.glColor(getDefaultColor()); + r.glDrawLine(x, y, x, y-1+height); + r.glDrawLine(x+1, y, x+1, y-1+height); + r.glDrawLine(x+2, y, x+2, y-1+height); + } } public void setSmall(boolean small) { @@ -190,4 +281,8 @@ public class BlockContainer implements GraphicalElement { return content.clone(); } + private static void checkInitialized() { + if (!initialized) throw new ExceptionInInitializerError("Please initialize BlockContainer by running the method BlockContainer.initialize(...) first!"); + } + } \ No newline at end of file diff --git a/src/org/warp/picalculator/gui/expression/BlockDivision.java b/src/org/warp/picalculator/gui/expression/BlockDivision.java index c73805d5..a2c3870c 100644 --- a/src/org/warp/picalculator/gui/expression/BlockDivision.java +++ b/src/org/warp/picalculator/gui/expression/BlockDivision.java @@ -8,6 +8,8 @@ import org.warp.picalculator.math.parser.features.interfaces.Feature; import it.unimi.dsi.fastutil.objects.ObjectArrayList; public class BlockDivision extends Block { + + public static final int CLASS_ID = 0x00000002; private final BlockContainer containerUp; private final BlockContainer containerDown; @@ -27,17 +29,39 @@ public class BlockDivision extends Block { BlockContainer.getDefaultFont(small).use(ge); r.glColor(BlockContainer.getDefaultColor()); containerUp.draw(ge, r, x+1+paddingLeftUpper, y, caret); - r.glDrawLine(x, y+h1+1, x+width, y+h1+1); + r.glDrawLine(x, y+h1+1, x+width-1, y+h1+1); containerDown.draw(ge, r, x+1+paddingLeftLower, y + h1+3, caret); } + @Override + public boolean putBlock(Caret caret, Block newBlock) { + boolean added = false; + added = added|containerUp.putBlock(caret, newBlock); + added = added|containerDown.putBlock(caret, newBlock); + if (added) { + recomputeDimensions(); + } + return added; + } + + @Override + public boolean delBlock(Caret caret) { + boolean removed = false; + removed = removed|containerUp.delBlock(caret); + removed = removed|containerDown.delBlock(caret); + if (removed) { + recomputeDimensions(); + } + return removed; + } + @Override public void recomputeDimensions() { final int w1 = containerUp.getWidth(); final int w2 = containerDown.getWidth(); final int h1 = containerUp.getHeight(); final int h2 = containerDown.getHeight(); - width = (w1>w2?w1:w2) + 2; + width = (w1>w2?w1:w2) + 4; height = h1+3+h2; line = h1+1; this.h1 = h1; @@ -49,6 +73,9 @@ public class BlockDivision extends Block { paddingLeftUpper = (w2 - w1) / 2; paddingLeftLower = 0; } + } else { + paddingLeftUpper = 0; + paddingLeftLower = 0; } } @@ -67,4 +94,9 @@ public class BlockDivision extends Block { public BlockContainer getLowerContainer() { return containerDown; } + + @Override + public int getClassID() { + return CLASS_ID; + } } diff --git a/src/org/warp/picalculator/gui/expression/BlockSquareRoot.java b/src/org/warp/picalculator/gui/expression/BlockSquareRoot.java new file mode 100644 index 00000000..74dd0581 --- /dev/null +++ b/src/org/warp/picalculator/gui/expression/BlockSquareRoot.java @@ -0,0 +1,87 @@ +package org.warp.picalculator.gui.expression; + +import org.warp.picalculator.Main; +import org.warp.picalculator.gui.graphicengine.GraphicEngine; +import org.warp.picalculator.gui.graphicengine.Renderer; +import org.warp.picalculator.math.parser.features.interfaces.Feature; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +public class BlockSquareRoot extends Block { + + public static final int CLASS_ID = 0x00000002; + + private final BlockContainer containerNumber; + + private int h1; + + public BlockSquareRoot() { + this.containerNumber = new BlockContainer(false); + recomputeDimensions(); + } + + @Override + public void draw(GraphicEngine ge, Renderer r, int x, int y, Caret caret) { + BlockContainer.getDefaultFont(small).use(ge); + r.glColor(BlockContainer.getDefaultColor()); + r.glDrawLine(x, y+height-10+1, x, y+height-10+2); // / + r.glDrawLine(x+1, y+height-10, x+1, y+height-10+1); // / + r.glDrawLine(x+2, y+height-10+2, x+2, y+height-10+6); // \ + r.glDrawLine(x+3, y+height-10+7, x+3, y+height-10+9); // \ + r.glDrawLine(x+5, y+height-h1-1-2, x+width-1, y+height-h1-1-2); // ---- + r.glDrawLine(x+5, y+height-h1-1-2, x+5, y+height-(h1-2)/3f*2f-1); // | + r.glDrawLine(x+4, y+height-(h1-2)/3f*2f-1, x+4, y+height-(h1-2)/3f-1); // | + r.glDrawLine(x+3, y+height-(h1-2)/3f-1, x+3, y+height-1); // | + containerNumber.draw(ge, r, x+7, y+3, caret); + } + + @Override + public boolean putBlock(Caret caret, Block newBlock) { + boolean added = false; + added = added|containerNumber.putBlock(caret, newBlock); + if (added) { + recomputeDimensions(); + } + return added; + } + + @Override + public boolean delBlock(Caret caret) { + boolean removed = false; + removed = removed|containerNumber.delBlock(caret); + if (removed) { + recomputeDimensions(); + } + return removed; + } + + @Override + public void recomputeDimensions() { + final int w1 = containerNumber.getWidth(); + h1 = containerNumber.getHeight(); + final int l1 = containerNumber.getLine(); + width = 8+w1+2; + height = 3+h1; + line = 3+l1; + if (height < 9) { + height = 9; + line+=(9-(3+h1)); + } + } + + @Override + public void setSmall(boolean small) { + this.small = small; + this.containerNumber.setSmall(small); + recomputeDimensions(); + } + + public BlockContainer getNumberContainer() { + return containerNumber; + } + + @Override + public int getClassID() { + return CLASS_ID; + } +} diff --git a/src/org/warp/picalculator/gui/expression/Caret.java b/src/org/warp/picalculator/gui/expression/Caret.java index 5bbdca50..736e5c89 100644 --- a/src/org/warp/picalculator/gui/expression/Caret.java +++ b/src/org/warp/picalculator/gui/expression/Caret.java @@ -5,7 +5,7 @@ public class Caret { private int pos; private int remaining; private CaretState state; - + public Caret(CaretState state, int pos) { this.state = state; this.pos = pos; @@ -27,4 +27,26 @@ public class Caret { public CaretState getState() { return state; } + + public void flipState() { + if (this.state == CaretState.VISIBLE_ON) { + this.state = CaretState.VISIBLE_OFF; + } else if (this.state == CaretState.VISIBLE_OFF) { + this.state = CaretState.VISIBLE_ON; + } + } + + public void turnOn() { + if (this.state == CaretState.VISIBLE_OFF) { + this.state = CaretState.VISIBLE_ON; + } + } + + public void setPosition(int i) { + this.pos = i; + } + + public void resetRemaining() { + remaining = pos; + } } diff --git a/src/org/warp/picalculator/gui/expression/containers/InlineInputContainer.java b/src/org/warp/picalculator/gui/expression/containers/InlineInputContainer.java new file mode 100644 index 00000000..d55f3b10 --- /dev/null +++ b/src/org/warp/picalculator/gui/expression/containers/InlineInputContainer.java @@ -0,0 +1,12 @@ +package org.warp.picalculator.gui.expression.containers; + +import org.warp.picalculator.gui.expression.Block; +import org.warp.picalculator.gui.expression.BlockChar; +import org.warp.picalculator.math.MathematicalSymbols; + +public class InlineInputContainer extends InputContainer { + @Override + public Block parseChar(char c) { + return new BlockChar(MathematicalSymbols.DIVISION); + } +} diff --git a/src/org/warp/picalculator/gui/expression/containers/InputContainer.java b/src/org/warp/picalculator/gui/expression/containers/InputContainer.java new file mode 100644 index 00000000..8a23aeb0 --- /dev/null +++ b/src/org/warp/picalculator/gui/expression/containers/InputContainer.java @@ -0,0 +1,136 @@ +package org.warp.picalculator.gui.expression.containers; + +import org.warp.picalculator.gui.expression.Block; +import org.warp.picalculator.gui.expression.BlockContainer; +import org.warp.picalculator.gui.expression.Caret; +import org.warp.picalculator.gui.expression.CaretState; +import org.warp.picalculator.gui.expression.GraphicalElement; +import org.warp.picalculator.gui.expression.layouts.InputLayout; +import org.warp.picalculator.gui.graphicengine.GraphicEngine; +import org.warp.picalculator.gui.graphicengine.Renderer; + +public abstract class InputContainer implements GraphicalElement, InputLayout { + public final BlockContainer root; + private Caret caret; + private static final float CARET_DURATION = 0.5f; + private float caretTime; + + public InputContainer() { + caret = new Caret(CaretState.VISIBLE_ON, 0); + root = new BlockContainer(false, false); + } + + public InputContainer(boolean small) { + caret = new Caret(CaretState.VISIBLE_ON, 0); + root = new BlockContainer(small, false); + } + + public InputContainer(boolean small, int minWidth, int minHeight) { + caret = new Caret(CaretState.VISIBLE_ON, 0); + root = new BlockContainer(small, false); + } + + public void typeChar(char c) { + Block b = parseChar(c); + if (b != null) { + caret.resetRemaining(); + if (root.putBlock(caret, b)) { + caret.setPosition(caret.getPosition()+1); + root.recomputeDimensions(); + } + } + caretTime = 0; + caret.turnOn(); + } + + public void typeChar(String c) { + typeChar(c.charAt(0)); + } + + public void del() { + caret.resetRemaining(); + if (root.delBlock(caret)) { + root.recomputeDimensions(); + } + if (caret.getPosition() > 0) { + caret.setPosition(caret.getPosition()-1); + } + caret.turnOn(); + caretTime = 0; + } + + public void moveLeft() { + if (caret.getPosition() > 0) { + caret.setPosition(caret.getPosition()-1); + } + caret.turnOn(); + caretTime = 0; + } + + public void moveRight() { + caret.setPosition(caret.getPosition()+1); + caret.turnOn(); + caretTime = 0; + } + + @Override + public void recomputeDimensions() { + root.recomputeDimensions(); + } + + @Override + public int getWidth() { + return root.getWidth(); + } + + @Override + public int getHeight() { + return root.getHeight(); + } + + @Override + public int getLine() { + return root.getLine(); + } + + /** + * + * @param delta Time, in seconds + * @return true if something changed + */ + public boolean beforeRender(float delta) { + boolean somethingChanged = false; + caretTime += delta; + if (caretTime >= CARET_DURATION) { + while (caretTime >= CARET_DURATION) { + caretTime -= CARET_DURATION; + caret.flipState(); + somethingChanged = true; + } + } + return somethingChanged; + } + + /** + * + * @param ge Graphic Engine class. + * @param r Graphic Renderer class of ge. + * @param x Position relative to the window. + * @param y Position relative to the window. + */ + public void draw(GraphicEngine ge, Renderer r, int x, int y) { + caret.resetRemaining(); + root.draw(ge, r, x, y, caret); + + int remaining = caret.getRemaining(); + if (remaining >= 0) { + caret.setPosition(caret.getPosition()-remaining-1); + } + } + + public void clear() { + caret = new Caret(CaretState.VISIBLE_ON, 0); + root.clear(); + recomputeDimensions(); + } +} diff --git a/src/org/warp/picalculator/gui/expression/containers/NormalInputContainer.java b/src/org/warp/picalculator/gui/expression/containers/NormalInputContainer.java new file mode 100644 index 00000000..a2ae198a --- /dev/null +++ b/src/org/warp/picalculator/gui/expression/containers/NormalInputContainer.java @@ -0,0 +1,35 @@ +package org.warp.picalculator.gui.expression.containers; + +import org.warp.picalculator.gui.expression.Block; +import org.warp.picalculator.gui.expression.BlockChar; +import org.warp.picalculator.gui.expression.BlockDivision; +import org.warp.picalculator.gui.expression.BlockSquareRoot; +import org.warp.picalculator.math.MathematicalSymbols; + +public class NormalInputContainer extends InputContainer { + @Override + public Block parseChar(char c) { + switch(c) { + case MathematicalSymbols.DIVISION: + return new BlockDivision(); + case MathematicalSymbols.SQUARE_ROOT: + return new BlockSquareRoot(); + case MathematicalSymbols.MULTIPLICATION: + case MathematicalSymbols.SUM: + case MathematicalSymbols.SUBTRACTION: + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return new BlockChar(c); + default: + return new BlockChar(c); + } + } +} diff --git a/src/org/warp/picalculator/gui/expression/containers/NormalOutputContainer.java b/src/org/warp/picalculator/gui/expression/containers/NormalOutputContainer.java new file mode 100644 index 00000000..081f2f46 --- /dev/null +++ b/src/org/warp/picalculator/gui/expression/containers/NormalOutputContainer.java @@ -0,0 +1,5 @@ +package org.warp.picalculator.gui.expression.containers; + +public class NormalOutputContainer extends OutputContainer { + +} diff --git a/src/org/warp/picalculator/gui/expression/containers/OutputContainer.java b/src/org/warp/picalculator/gui/expression/containers/OutputContainer.java new file mode 100644 index 00000000..221ea519 --- /dev/null +++ b/src/org/warp/picalculator/gui/expression/containers/OutputContainer.java @@ -0,0 +1,71 @@ +package org.warp.picalculator.gui.expression.containers; + +import org.warp.picalculator.gui.expression.Block; +import org.warp.picalculator.gui.expression.BlockContainer; +import org.warp.picalculator.gui.expression.Caret; +import org.warp.picalculator.gui.expression.CaretState; +import org.warp.picalculator.gui.expression.GraphicalElement; +import org.warp.picalculator.gui.expression.layouts.InputLayout; +import org.warp.picalculator.gui.graphicengine.GraphicEngine; +import org.warp.picalculator.gui.graphicengine.Renderer; + +public abstract class OutputContainer implements GraphicalElement, OutputLayout { + public final BlockContainer root; + private final Caret caret = new Caret(CaretState.HIDDEN, 0); + + public OutputContainer() { + root = new BlockContainer(); + } + + public OutputContainer(boolean small) { + root = new BlockContainer(small); + } + + public OutputContainer(boolean small, int minWidth, int minHeight) { + root = new BlockContainer(small); + } + + @Override + public void recomputeDimensions() { + root.recomputeDimensions(); + } + + @Override + public int getWidth() { + return root.getWidth(); + } + + @Override + public int getHeight() { + return root.getHeight(); + } + + @Override + public int getLine() { + return root.getLine(); + } + + /** + * + * @param delta Time, in seconds + */ + public void beforeRender(double delta) { + + } + + /** + * + * @param ge Graphic Engine class. + * @param r Graphic Renderer class of ge. + * @param x Position relative to the window. + * @param y Position relative to the window. + */ + public void draw(GraphicEngine ge, Renderer r, int x, int y) { + root.draw(ge, r, x, y, caret); + } + + public void clear() { + root.clear(); + recomputeDimensions(); + } +} diff --git a/src/org/warp/picalculator/gui/expression/containers/OutputLayout.java b/src/org/warp/picalculator/gui/expression/containers/OutputLayout.java new file mode 100644 index 00000000..fbb9d375 --- /dev/null +++ b/src/org/warp/picalculator/gui/expression/containers/OutputLayout.java @@ -0,0 +1,5 @@ +package org.warp.picalculator.gui.expression.containers; + +public interface OutputLayout { + +} diff --git a/src/org/warp/picalculator/gui/expression/layouts/InputLayout.java b/src/org/warp/picalculator/gui/expression/layouts/InputLayout.java new file mode 100644 index 00000000..04550bbe --- /dev/null +++ b/src/org/warp/picalculator/gui/expression/layouts/InputLayout.java @@ -0,0 +1,7 @@ +package org.warp.picalculator.gui.expression.layouts; + +import org.warp.picalculator.gui.expression.Block; + +public interface InputLayout { + public Block parseChar(char c); +} diff --git a/src/org/warp/picalculator/gui/graphicengine/cpu/CPUEngine.java b/src/org/warp/picalculator/gui/graphicengine/cpu/CPUEngine.java index 293a1fc2..7f9f1f56 100644 --- a/src/org/warp/picalculator/gui/graphicengine/cpu/CPUEngine.java +++ b/src/org/warp/picalculator/gui/graphicengine/cpu/CPUEngine.java @@ -269,17 +269,23 @@ public class CPUEngine implements GraphicEngine { } if (iy0 == iy1) { for (int x = 0; x <= ix1 - ix0; x++) { - canvas2d[ix0 + x + iy0 * size[0]] = color; + if ((ix0+x < size[0]) & (iy0 < size[1])) { + canvas2d[ix0 + x + iy0 * size[0]] = color; + } } } else if (ix0 == ix1) { for (int y = 0; y <= iy1 - iy0; y++) { - canvas2d[ix0 + (iy0 + y) * size[0]] = color; + if ((ix0 < size[0]) & (iy0+y < size[1])) { + canvas2d[ix0 + (iy0 + y) * size[0]] = color; + } } } else { final int m = (iy1 - iy0) / (ix1 - ix0); for (int texx = 0; texx <= ix1 - ix0; texx++) { if (ix0 + texx < size[0] && iy0 + (m * texx) < size[1]) { - canvas2d[(ix0 + texx) + (iy0 + (m * texx)) * size[0]] = color; + if ((ix0 + texx < size[0]) & ((iy0 + (m * texx)) < size[1])) { + canvas2d[(ix0 + texx) + (iy0 + (m * texx)) * size[0]] = color; + } } } } diff --git a/src/org/warp/picalculator/gui/graphicengine/gpu/GPUEngine.java b/src/org/warp/picalculator/gui/graphicengine/gpu/GPUEngine.java index cb71e2a4..276687f6 100644 --- a/src/org/warp/picalculator/gui/graphicengine/gpu/GPUEngine.java +++ b/src/org/warp/picalculator/gui/graphicengine/gpu/GPUEngine.java @@ -49,7 +49,7 @@ public class GPUEngine implements org.warp.picalculator.gui.graphicengine.Graphi public void setDisplayMode(int ww, int wh) { this.size[0] = ww; this.size[1] = wh; - wnd.window.setSize(ww, wh); + wnd.window.setSize(Utils.debugOn?ww*2:ww, Utils.debugOn?wh*2:wh); } @Override diff --git a/src/org/warp/picalculator/gui/graphicengine/gpu/GPURenderer.java b/src/org/warp/picalculator/gui/graphicengine/gpu/GPURenderer.java index da347e7b..2f5e23dc 100644 --- a/src/org/warp/picalculator/gui/graphicengine/gpu/GPURenderer.java +++ b/src/org/warp/picalculator/gui/graphicengine/gpu/GPURenderer.java @@ -24,7 +24,7 @@ import com.jogamp.opengl.util.texture.TextureIO; public class GPURenderer implements Renderer { - public GL2ES1 gl; + public static GL2ES1 gl; private final DeallocationHelper deallocationHelper = new DeallocationHelper(); FloatBuffer fbVertices; @@ -192,10 +192,10 @@ public class GPURenderer implements Renderer { final FileInputStream f = new FileInputStream("test.png"); final TextureData tx_dat = TextureIO.newTextureData(gl.getGLProfile(), f, false, TextureIO.PNG); final Texture tex = new Texture(gl, tx_dat); - tex.setTexParameteri(gl, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); + tex.setTexParameteri(gl, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); tex.setTexParameteri(gl, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); - tex.setTexParameteri(gl, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); - tex.setTexParameteri(gl, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE); +// tex.setTexParameteri(gl, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP_TO_EDGE); +// tex.setTexParameteri(gl, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP_TO_EDGE); return tex; } @@ -208,7 +208,10 @@ public class GPURenderer implements Renderer { final ByteArrayOutputStream os = new ByteArrayOutputStream(); ImageIO.write(img, "png", os); final InputStream fis = new ByteArrayInputStream(os.toByteArray()); - return TextureIO.newTexture(fis, false, TextureIO.PNG); + Texture tex = TextureIO.newTexture(fis, false, TextureIO.PNG); + tex.setTexParameteri(gl, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); + tex.setTexParameteri(gl, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST); + return tex; } @Override diff --git a/src/org/warp/picalculator/gui/graphicengine/gpu/NEWTWindow.java b/src/org/warp/picalculator/gui/graphicengine/gpu/NEWTWindow.java index 56d22152..663a6efc 100644 --- a/src/org/warp/picalculator/gui/graphicengine/gpu/NEWTWindow.java +++ b/src/org/warp/picalculator/gui/graphicengine/gpu/NEWTWindow.java @@ -54,6 +54,7 @@ import java.awt.event.ComponentListener; import java.nio.ByteBuffer; import java.util.Collection; +import org.warp.picalculator.Utils; import org.warp.picalculator.device.Keyboard; import org.warp.picalculator.device.Keyboard.Key; import org.warp.picalculator.gui.DisplayManager; @@ -278,7 +279,7 @@ class NEWTWindow implements GLEventListener { //Transparency gl.glEnable(GL2ES1.GL_BLEND); gl.glBlendFunc(GL2ES1.GL_SRC_ALPHA, GL2ES1.GL_ONE_MINUS_SRC_ALPHA); - gl.glShadeModel(GL2ES1.GL_SMOOTH); + gl.glShadeModel(GL2ES1.GL_FLAT); try { renderer.currentTex = ((GPUSkin) disp.loadSkin("test.png")).t; @@ -295,8 +296,8 @@ class NEWTWindow implements GLEventListener { @Override public void reshape(GLAutoDrawable glad, int x, int y, int width, int height) { - disp.size[0] = width; - disp.size[1] = height; + disp.size[0] = Utils.debugOn?width/2:width; + disp.size[1] = Utils.debugOn?height/2:height; final GL2ES1 gl = glad.getGL().getGL2ES1(); float max_wh, min_wh; if (width == 0) { @@ -318,7 +319,7 @@ class NEWTWindow implements GLEventListener { gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION); gl.glLoadIdentity(); - gl.glOrtho(0.0, width, height, 0.0, -1, 1); + gl.glOrtho(0.0, Utils.debugOn?width/2:width, Utils.debugOn?height/2:height, 0.0, -1, 1); gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); gl.glLoadIdentity(); diff --git a/src/org/warp/picalculator/gui/screens/MathInputScreen.java b/src/org/warp/picalculator/gui/screens/MathInputScreen.java index ba0b652a..995950ea 100644 --- a/src/org/warp/picalculator/gui/screens/MathInputScreen.java +++ b/src/org/warp/picalculator/gui/screens/MathInputScreen.java @@ -1,5 +1,6 @@ package org.warp.picalculator.gui.screens; +import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import it.unimi.dsi.fastutil.objects.ObjectArrayList; @@ -16,6 +17,11 @@ import org.warp.picalculator.Utils; import org.warp.picalculator.device.Keyboard; import org.warp.picalculator.device.Keyboard.Key; import org.warp.picalculator.gui.DisplayManager; +import org.warp.picalculator.gui.expression.BlockContainer; +import org.warp.picalculator.gui.expression.containers.InputContainer; +import org.warp.picalculator.gui.expression.containers.NormalInputContainer; +import org.warp.picalculator.gui.expression.containers.NormalOutputContainer; +import org.warp.picalculator.gui.expression.containers.OutputContainer; import org.warp.picalculator.gui.graphicengine.BinaryFont; import org.warp.picalculator.gui.graphicengine.Renderer; import org.warp.picalculator.math.AngleMode; @@ -32,114 +38,50 @@ import org.warp.picalculator.math.functions.Number; public class MathInputScreen extends Screen { - public volatile String currentExpression = ""; - public volatile String newExpression = ""; - public volatile int caretPos = 0; - public volatile boolean showCaret = true; - public volatile float showCaretDelta = 0f; public MathContext calc; - public boolean autoscroll; - public int scrollX = 0; + public InputContainer userInput; + public OutputContainer result; public int errorLevel = 0; // 0 = nessuno, 1 = risultato, 2 = tutto boolean mustRefresh = true; - boolean firstStep = true; public MathInputScreen() { super(); canBeInHistory = true; - - calc = new MathContext(); } @Override public void created() throws InterruptedException { - + calc = new MathContext(); + + try { + BlockContainer.initializeFonts(DisplayManager.engine.loadFont("ex"), DisplayManager.engine.loadFont("big")); + } catch (IOException e) { + e.printStackTrace(); + System.exit(1); + } + + userInput = new NormalInputContainer(); + result = new NormalOutputContainer(); + + calc.init(); } @Override public void init() throws InterruptedException { /* Fine caricamento */ - - // Parentesi f = new - // Parentesi("(Ⓐ(2X)*3Y)/(5Z^2)+(Ⓐ(11A)*13B)/(7CZ)=19XZ"); - // PARENTESI CON CALCOLI - // Funzione f = new Sottrazione(new Somma(new Parentesi("Ⓐ9/2+Ⓐ7/2", - // "").calcola(), new Termine("3.5")), new - // Parentesi("3*2√14","").calcola()); - // PARENTESI CON DUE NUMERI FRAZIONALI COMPLETI CON INCOGNITE: - // Funzione f = new - // Parentesi("(Ⓐ(2X)*3Y)/(5Z^2)+(Ⓐ(11A)*13B)/(7CZ)", ""); - // PARENTESI CON DUE NUMERI FRAZIONALI DISALLINEATI GRAFICAMENTE: - // Funzione f = new Parentesi("((5^2-1)/2)/5-5/(5/2)=2", ""); - // TERMINE DI PROVA COMPLETO: - // Funzione f = new Termine(new NumeroAvanzato(new Rational(3, 2), - // new Rational(7, 1), new Incognite(new Incognita('X', - // Rational.ONE)), new Incognite(new Incognita('Y', Rational.ONE)), - // new Incognite(new Incognita('z', Rational.ONE)))); - // PARENTESI REALISTICA CON INCOGNITE: - // Funzione f = new Equazione(new - // Parentesi("X^2+(MX-M+4)^2-4X-4(MX-M+4)^2+7", ""), new - // Termine("0")); - // POTENZA: - // Funzione f = new Parentesi("(MX-M+4)^2", ""); - // NUMERO SEMPLICE LUNGO: - // Funzione f = new Parentesi("-1219999799999996934.42229", ""); - // : - // Funzione f = new Parentesi("5Y+XY=2", "") - -// calcola("((5^2+3√(100/0.1))+Ⓐ(7)+9/15*2√(26/2))/21"); - calc.init(); -// interpreta("{(5X*(15X/3X))+(25X/(5X*(15X/3X)))=15{X=5"); //TODO RIMUOVERE - - // long start = System.nanoTime(); - // Termine result = - // Calculator.calcolarisultato("((5Ⓑ2+3√(100/0.1))*Ⓐ7+9/15*2√(26/2))/21"); - // long end = System.nanoTime(); - // long timeElapsed = end-start; - // System.out.println("RESULT: " + result); - // System.out.println("DECIMAl RESULT: " + - // result.getTerm().toBigDecimal()); - // System.out.println("Time elapsed: " + (double) timeElapsed / - // 1000000 + " milliseconds\n"); - // - // - // start = System.nanoTime(); - // RisultatoEquazione eresult = - // Calculator.calcolaequazione("((5Ⓑ2+3√(100/0.1))*Ⓐ7+9/15*2√(26/2))/21=(175*(2√7)+3*(2√13))/105"); - // end = System.nanoTime(); - // timeElapsed = end-start; - // System.out.println("Is an equation: " + eresult.isAnEquation); - // System.out.println("L-R: " + eresult.LR); - // System.out.println("Time elapsed: " + (double) timeElapsed / - // 1000000 + " milliseconds\n"); } - - public void interpreta(boolean temporary) throws Error { - final String eqn = newExpression; - if (!temporary) { - currentExpression = eqn; - } - - calc.parseInputString(eqn); - } - + @Override public void beforeRender(float dt) { - showCaretDelta += dt; - if (showCaretDelta >= 0.5f) { - mustRefresh = true; - showCaret = !showCaret; - showCaretDelta = 0f; - } - if (caretPos > newExpression.length()) { - caretPos = newExpression.length(); - } if (DisplayManager.error == null) { DisplayManager.renderer.glClearColor(0xFFc5c2af); } else { DisplayManager.renderer.glClearColor(0xFFDC3C32); } + if (userInput.beforeRender(dt)) { + mustRefresh = true; + } } private static final BinaryFont fontBig = Utils.getFont(false); @@ -165,71 +107,11 @@ public class MathInputScreen extends Screen { final int textColor = 0xFF000000; final int padding = 4; DisplayManager.renderer.glColor(textColor); - final int caretRealPos = MathematicalSymbols.getGraphicRepresentation(newExpression.substring(0, caretPos)).length() * (fontBig.getCharacterWidth() + 1); - final String inputTextWithoutCaret = MathematicalSymbols.getGraphicRepresentation(newExpression); - final boolean tooLongI = padding + fontBig.getStringWidth(newExpression) + padding >= Main.screenSize[0]; - int scrollI = 0; - if (tooLongI) { - scrollI = -scrollX; - if (-scrollI >= Main.screenSize[0]) { - scrollI += Main.screenSize[0]; - } else { - scrollI = 0; - } - } - DisplayManager.renderer.glDrawStringLeft(padding + scrollI, padding + 20, inputTextWithoutCaret); - if (showCaret) { - DisplayManager.renderer.glDrawStringLeft(padding + scrollI + caretRealPos, padding + 20, "|"); - } - if (tooLongI) { - DisplayManager.renderer.glColor(DisplayManager.renderer.glGetClearColor()); - DisplayManager.renderer.glFillColor(Main.screenSize[0] - 16 - 2, padding + 20, fontBig.getCharacterHeight(), Main.screenSize[0]); - DisplayManager.renderer.glColor(textColor); - DisplayManager.drawSkinPart(Main.screenSize[0] - 16, padding + 20 + fontBig.getCharacterHeight() / 2 - 16 / 2, 304, 0, 304 + 16, 16); - } - if (calc.f != null) { - int topSpacing = 0; - final Iterator iter = calc.f.iterator(); - while (iter.hasNext()) { - final Function fnc = iter.next(); - try { - final boolean tooLong = padding + fnc.getWidth() + padding >= Main.screenSize[0]; - int scrollA = 0; - if (tooLong) { - scrollA = -scrollX; - if (-scrollA >= Main.screenSize[0]) { - scrollA += Main.screenSize[0]; - } else { - scrollA = 0; - } - } - final int y = padding + 20 + padding + fontBig.getCharacterHeight() + 1 + topSpacing; - fnc.draw(padding + scrollA, y, null, null); - if (tooLong) { - DisplayManager.renderer.glColor(DisplayManager.renderer.glGetClearColor()); - DisplayManager.renderer.glFillColor(Main.screenSize[0] - 16 - 2, y, fnc.getHeight(), Main.screenSize[0]); - DisplayManager.renderer.glColor(textColor); - DisplayManager.drawSkinPart(Main.screenSize[0] - 16, y + fnc.getHeight() / 2 - 16 / 2, 304, 0, 304 + 16, 16); - } - } catch (final NullPointerException e) { - iter.remove(); - } - topSpacing += fnc.getHeight() + 2; - } - } - if (calc.f2 != null) { - int bottomSpacing = 0; - for (final Function f : calc.f2) { - bottomSpacing += f.getHeight() + 2; - f.draw(DisplayManager.engine.getWidth() - 2 - f.getWidth(), DisplayManager.engine.getHeight() - bottomSpacing, null, null); - } - if (calc.resultsCount > 1 && calc.resultsCount != calc.f2.size()) { - final String resultsCountText = calc.resultsCount + " total results".toUpperCase(); - DisplayManager.renderer.glColor(0xFF9AAEA0); - Utils.getFont(true).use(DisplayManager.engine); - bottomSpacing += fontBig.getCharacterHeight() + 2; - DisplayManager.renderer.glDrawStringRight(DisplayManager.engine.getWidth() - 2, DisplayManager.engine.getHeight() - bottomSpacing, resultsCountText); - } + + userInput.draw(DisplayManager.engine, DisplayManager.renderer, padding, padding + 20); + + if (!result.root.getContent().isEmpty()) { + result.draw(DisplayManager.engine, DisplayManager.renderer, DisplayManager.engine.getWidth() - 2, DisplayManager.engine.getHeight() - 2); } } @@ -247,141 +129,142 @@ public class MathInputScreen extends Screen { public boolean keyPressed(Key k) { switch (k) { case STEP: - if (newExpression.length() > 0) { - if (firstStep) { - try { - try { - interpreta(true); - showVariablesDialog(() -> { - currentExpression = newExpression; - calc.f2 = calc.f; - firstStep = false; - step(); - }); - } catch (final Exception ex) { - if (Utils.debugOn) { - ex.printStackTrace(); - } - throw new Error(Errors.SYNTAX_ERROR); - } - } catch (final Error e) { - final StringWriter sw = new StringWriter(); - final PrintWriter pw = new PrintWriter(sw); - e.printStackTrace(pw); - d.errorStackTrace = sw.toString().toUpperCase().replace("\t", " ").replace("\r", "").split("\n"); - DisplayManager.error = e.id.toString(); - System.err.println(e.id); - } - } else { - step(); - } - } - return true; +// if (newExpression.length() > 0) { +// if (firstStep) { +// try { +// try { +// interpreta(true); +// showVariablesDialog(() -> { +// currentExpression = newExpression; +// calc.f2 = calc.f; +// firstStep = false; +// step(); +// }); +// } catch (final Exception ex) { +// if (Utils.debugOn) { +// ex.printStackTrace(); +// } +// throw new Error(Errors.SYNTAX_ERROR); +// } +// } catch (final Error e) { +// final StringWriter sw = new StringWriter(); +// final PrintWriter pw = new PrintWriter(sw); +// e.printStackTrace(pw); +// d.errorStackTrace = sw.toString().toUpperCase().replace("\t", " ").replace("\r", "").split("\n"); +// DisplayManager.error = e.id.toString(); +// System.err.println(e.id); +// } +// } else { +// step(); +// } +// } +// return true; case SIMPLIFY: - if (DisplayManager.error != null) { - Utils.debug.println("Resetting after error..."); - DisplayManager.error = null; - currentExpression = null; - calc.f = null; - calc.f2 = null; - calc.resultsCount = 0; - return true; - } else { - try { - try { - if (!firstStep) { - step(); - } else { - if (newExpression != currentExpression && newExpression.length() > 0) { - changeEquationScreen(); - interpreta(true); - showVariablesDialog(() -> { - currentExpression = newExpression; - simplify(); - }); - } - } - } catch (final Exception ex) { - if (Utils.debugOn) { - ex.printStackTrace(); - } - throw new Error(Errors.SYNTAX_ERROR); - } - } catch (final Error e) { - final StringWriter sw = new StringWriter(); - final PrintWriter pw = new PrintWriter(sw); - e.printStackTrace(pw); - d.errorStackTrace = sw.toString().toUpperCase().replace("\t", " ").replace("\r", "").split("\n"); - DisplayManager.error = e.id.toString(); - System.err.println(e.id); - } - return true; - } +// if (DisplayManager.error != null) { +// Utils.debug.println("Resetting after error..."); +// DisplayManager.error = null; +// currentExpression = null; +// calc.f = null; +// calc.f2 = null; +// calc.resultsCount = 0; +// return true; +// } else { +// try { +// try { +// if (!firstStep) { +// step(); +// } else { +// if (newExpression != currentExpression && newExpression.length() > 0) { +// changeEquationScreen(); +// interpreta(true); +// showVariablesDialog(() -> { +// currentExpression = newExpression; +// simplify(); +// }); +// } +// } +// } catch (final Exception ex) { +// if (Utils.debugOn) { +// ex.printStackTrace(); +// } +// throw new Error(Errors.SYNTAX_ERROR); +// } +// } catch (final Error e) { +// final StringWriter sw = new StringWriter(); +// final PrintWriter pw = new PrintWriter(sw); +// e.printStackTrace(pw); +// d.errorStackTrace = sw.toString().toUpperCase().replace("\t", " ").replace("\r", "").split("\n"); +// DisplayManager.error = e.id.toString(); +// System.err.println(e.id); +// } +// return true; +// } + return true; case NUM0: - typeChar("0"); + typeChar('0'); return true; case NUM1: - typeChar("1"); + typeChar('1'); return true; case NUM2: - typeChar("2"); + typeChar('2'); return true; case NUM3: - typeChar("3"); + typeChar('3'); return true; case NUM4: - typeChar("4"); + typeChar('4'); return true; case NUM5: - typeChar("5"); + typeChar('5'); return true; case NUM6: - typeChar("6"); + typeChar('6'); return true; case NUM7: - typeChar("7"); + typeChar('7'); return true; case NUM8: - typeChar("8"); + typeChar('8'); return true; case NUM9: - typeChar("9"); + typeChar('9'); return true; case PLUS: - typeChar("+"); + typeChar('+'); return true; case MINUS: - typeChar("-"); + typeChar('-'); return true; case PLUS_MINUS: - typeChar("±"); + typeChar('±'); return true; case MULTIPLY: - typeChar("*"); + typeChar('*'); return true; case DIVIDE: - typeChar("/"); + typeChar('/'); return true; case PARENTHESIS_OPEN: - typeChar("("); + typeChar('('); return true; case PARENTHESIS_CLOSE: - typeChar(")"); + typeChar(')'); return true; case DOT: - typeChar("."); + typeChar('.'); return true; case EQUAL: - typeChar("="); + typeChar('='); return true; case SQRT: - typeChar("Ⓐ"); + typeChar('Ⓐ'); return true; case ROOT: - typeChar("√"); + typeChar('√'); return true; case POWER_OF_2: - typeChar(MathematicalSymbols.POWER + "2"); + typeChar(MathematicalSymbols.POWER_OF_TWO); return true; case POWER_OF_x: typeChar(MathematicalSymbols.POWER); @@ -390,10 +273,10 @@ public class MathInputScreen extends Screen { typeChar(MathematicalSymbols.PI); return true; case LETTER_X: - typeChar(MathematicalSymbols.variables()[23]); + typeChar(MathematicalSymbols.variables[23]); return true; case LETTER_Y: - typeChar(MathematicalSymbols.variables()[24]); + typeChar(MathematicalSymbols.variables[24]); return true; case SINE: typeChar(MathematicalSymbols.SINE); @@ -414,84 +297,56 @@ public class MathInputScreen extends Screen { typeChar(MathematicalSymbols.ARC_TANGENT); return true; case DELETE: - if (newExpression.length() > 0) { - if (caretPos > 0) { - caretPos -= 1; - newExpression = newExpression.substring(0, caretPos) + newExpression.substring(caretPos + 1, newExpression.length()); - } else { - newExpression = newExpression.substring(1); - } - try { - interpreta(true); - } catch (final Error e) {} - } - firstStep = true; + userInput.del(); + mustRefresh = true; return true; case LEFT: - if (caretPos > 0) { - caretPos -= 1; - } else { - caretPos = newExpression.length(); - } - scrollX = fontBig.getStringWidth(newExpression.substring(0, caretPos) + "|||"); - showCaret = true; - showCaretDelta = 0L; + userInput.moveLeft(); + mustRefresh = true; return true; case RIGHT: - if (caretPos < newExpression.length()) { - caretPos += 1; - } else { - caretPos = 0; - } - scrollX = fontBig.getStringWidth(newExpression.substring(0, caretPos) + "|||"); - showCaret = true; - showCaretDelta = 0L; + userInput.moveRight(); + mustRefresh = true; return true; case RESET: + userInput.clear(); + result.clear(); if (DisplayManager.error != null) { Utils.debug.println("Resetting after error..."); DisplayManager.error = null; - return true; - } else { - caretPos = 0; - newExpression = ""; - firstStep = false; - if (calc.f != null) { - calc.f = new ObjectArrayList<>(); - } - return true; } + return true; case SURD_MODE: - calc.exactMode = !calc.exactMode; - if (calc.exactMode == false) { - calc.f2 = solveExpression(calc.f2); - } else { - currentExpression = ""; - Keyboard.keyPressed(Key.SIMPLIFY); - } +// calc.exactMode = !calc.exactMode; +// if (calc.exactMode == false) { +// calc.f2 = solveExpression(calc.f2); +// } else { +// currentExpression = ""; +// Keyboard.keyPressed(Key.SIMPLIFY); +// } return true; case debug1: DisplayManager.INSTANCE.setScreen(new EmptyScreen()); return true; case HISTORY_BACK: - if (DisplayManager.INSTANCE.canGoBack()) { - if (currentExpression != null && currentExpression.length() > 0 & DisplayManager.sessions[DisplayManager.currentSession + 1] instanceof MathInputScreen) { - newExpression = currentExpression; - try { - interpreta(true); - } catch (final Error e) {} - } - } +// if (DisplayManager.INSTANCE.canGoBack()) { +// if (currentExpression != null && currentExpression.length() > 0 & DisplayManager.sessions[DisplayManager.currentSession + 1] instanceof MathInputScreen) { +// newExpression = currentExpression; +// try { +// interpreta(true); +// } catch (final Error e) {} +// } +// } return false; case HISTORY_FORWARD: - if (DisplayManager.INSTANCE.canGoForward()) { - if (currentExpression != null && currentExpression.length() > 0 & DisplayManager.sessions[DisplayManager.currentSession - 1] instanceof MathInputScreen) { - newExpression = currentExpression; - try { - interpreta(true); - } catch (final Error e) {} - } - } +// if (DisplayManager.INSTANCE.canGoForward()) { +// if (currentExpression != null && currentExpression.length() > 0 & DisplayManager.sessions[DisplayManager.currentSession - 1] instanceof MathInputScreen) { +// newExpression = currentExpression; +// try { +// interpreta(true); +// } catch (final Error e) {} +// } +// } return false; case debug_DEG: if (calc.angleMode.equals(AngleMode.DEG) == false) { @@ -660,20 +515,11 @@ public class MathInputScreen extends Screen { } } - public void typeChar(String chr) { - final int len = chr.length(); - newExpression = newExpression.substring(0, caretPos) + chr + newExpression.substring(caretPos, newExpression.length()); - caretPos += len; - scrollX = fontBig.getStringWidth(newExpression.substring(0, caretPos) + "|||"); - showCaret = true; - showCaretDelta = 0L; - firstStep = true; - try { - interpreta(true); - } catch (final Error e) {} -// f.clear(); //TODO: I removed this line to prevent input blanking when pressing EQUALS button and cloning this screen, but I must see why I created this part of code. + public void typeChar(char chr) { + userInput.typeChar(chr); + mustRefresh = true; } - + @Override public boolean keyReleased(Key k) { return false; @@ -751,21 +597,11 @@ public class MathInputScreen extends Screen { public MathInputScreen clone() { final MathInputScreen es = this; final MathInputScreen es2 = new MathInputScreen(); - es2.scrollX = es.scrollX; - es2.newExpression = es.newExpression; - es2.currentExpression = es.currentExpression; - es2.showCaret = es.showCaret; - es2.showCaretDelta = es.showCaretDelta; - es2.caretPos = es.caretPos; -// es2.calc.f = Utils.cloner.deepClone(es.calc.f); -// es2.calc.f2 = Utils.cloner.deepClone(es.calc.f2); -// es2.calc.resultsCount = es.calc.resultsCount; - es2.autoscroll = es.autoscroll; es2.errorLevel = es.errorLevel; es2.mustRefresh = es.mustRefresh; - es2.firstStep = es.firstStep; -// es2.calc.variablesValues = Utils.cloner.deepClone(es.calc.variablesValues); es2.calc = Utils.cloner.deepClone(es.calc); + es2.userInput = Utils.cloner.deepClone(es.userInput); + es2.result = Utils.cloner.deepClone(es.result); return es2; } diff --git a/src/org/warp/picalculator/math/MathContext.java b/src/org/warp/picalculator/math/MathContext.java index b3644c7f..ac8da5e2 100644 --- a/src/org/warp/picalculator/math/MathContext.java +++ b/src/org/warp/picalculator/math/MathContext.java @@ -102,18 +102,6 @@ public class MathContext { } } - public void parseInputString(String eqn) throws Error { - final ObjectArrayList fncs = new ObjectArrayList<>(); - if (eqn.length() > 0) { - try { - fncs.add(parseString(eqn.replace("sqrt", MathematicalSymbols.SQUARE_ROOT).replace("^", MathematicalSymbols.POWER))); - } catch (final Exception ex) { - - } - } - f = fncs; - } - /*public void solve(EquationScreen equationScreen, char letter) throws Error { if (Calculator.currentSession == 0 && Calculator.sessions[0] instanceof EquationScreen) { EquationScreen es = (EquationScreen) Calculator.sessions[0]; diff --git a/src/org/warp/picalculator/math/MathematicalSymbols.java b/src/org/warp/picalculator/math/MathematicalSymbols.java index 61ead678..21c768fb 100644 --- a/src/org/warp/picalculator/math/MathematicalSymbols.java +++ b/src/org/warp/picalculator/math/MathematicalSymbols.java @@ -16,6 +16,7 @@ public class MathematicalSymbols { public static final char PARENTHESIS_OPEN = '('; public static final char PARENTHESIS_CLOSE = ')'; public static final char POWER = 'Ⓑ'; + public static final char POWER_OF_TWO = 'Ⓘ'; public static final char EQUATION = '='; public static final char SYSTEM = '{'; public static final char SINE = 'Ⓒ'; @@ -29,7 +30,7 @@ public class MathematicalSymbols { public static final char[] functionsNSN = new char[] { NTH_ROOT, POWER }; - public static final char[] functionsSN = new char[] { SQUARE_ROOT, MINUS, SINE, COSINE, TANGENT, ARC_SINE, ARC_COSINE, ARC_TANGENT }; + public static final char[] functionsSN = new char[] { SQUARE_ROOT, POWER_OF_TWO, MINUS, SINE, COSINE, TANGENT, ARC_SINE, ARC_COSINE, ARC_TANGENT }; public static final char[] functions = concat(functionsNSN, functionsSN); diff --git a/src/org/warp/picalculator/math/functions/Division.java b/src/org/warp/picalculator/math/functions/Division.java index f0b44106..2458c3d8 100644 --- a/src/org/warp/picalculator/math/functions/Division.java +++ b/src/org/warp/picalculator/math/functions/Division.java @@ -96,4 +96,9 @@ public class Division extends FunctionOperator { public FunctionOperator clone() { return new Division(this.getMathContext(), this.getParameter1(), this.getParameter2()); } + + @Override + public String toString() { + return "("+this.getParameter1()+")/("+this.getParameter2()+")"; + } } \ No newline at end of file diff --git a/src/org/warp/picalculator/math/functions/Multiplication.java b/src/org/warp/picalculator/math/functions/Multiplication.java index 283f89d6..fc572f2b 100644 --- a/src/org/warp/picalculator/math/functions/Multiplication.java +++ b/src/org/warp/picalculator/math/functions/Multiplication.java @@ -106,10 +106,6 @@ public class Multiplication extends FunctionOperator { @Override public String toString() { - if (parameter1 != null && parameter2 != null) { - return parameter1.toString()+"*"+parameter2.toString(); - } else { - return super.toString(); - } + return "("+parameter1.toString()+")*("+parameter2.toString()+")"; } } \ No newline at end of file diff --git a/src/org/warp/picalculator/math/parser/InputParser.java b/src/org/warp/picalculator/math/parser/MathParser.java similarity index 85% rename from src/org/warp/picalculator/math/parser/InputParser.java rename to src/org/warp/picalculator/math/parser/MathParser.java index b536e865..3a25e814 100644 --- a/src/org/warp/picalculator/math/parser/InputParser.java +++ b/src/org/warp/picalculator/math/parser/MathParser.java @@ -7,6 +7,7 @@ import org.warp.picalculator.gui.expression.BlockChar; import org.warp.picalculator.gui.expression.BlockContainer; import org.warp.picalculator.gui.expression.BlockDivision; import org.warp.picalculator.math.Function; +import org.warp.picalculator.math.FunctionOperator; import org.warp.picalculator.math.FunctionSingle; import org.warp.picalculator.math.MathContext; import org.warp.picalculator.math.MathematicalSymbols; @@ -30,7 +31,7 @@ import com.sun.org.apache.xpath.internal.functions.Function2Args; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectListIterator; -public class InputParser { +public class MathParser { public static Expression parseInput(MathContext context, BlockContainer root) throws Error { Expression result; @@ -57,15 +58,19 @@ public class InputParser { Feature result; - if (block instanceof BlockChar) { - result = new FeatureChar(((BlockChar) block).getChar()); - } else if (block instanceof BlockDivision) { - BlockDivision bd = (BlockDivision) block; - Function upper = parseContainer(context, bd.getUpperContainer()); - Function lower = parseContainer(context, bd.getLowerContainer()); - result = new FeatureDivision(upper, lower); - } else { - throw new Error(Errors.SYNTAX_ERROR); + int blockType = block.getClassID(); + switch (blockType) { + case BlockChar.CLASS_ID: + result = new FeatureChar(((BlockChar) block).getChar()); + break; + case BlockDivision.CLASS_ID: + BlockDivision bd = (BlockDivision) block; + Function upper = parseContainer(context, bd.getUpperContainer()); + Function lower = parseContainer(context, bd.getLowerContainer()); + result = new FeatureDivision(upper, lower); + break; + default: + throw new Error(Errors.SYNTAX_ERROR); } return result; @@ -108,17 +113,31 @@ public class InputParser { } //Phase 2 - stackIterator = process.iterator(); + stackIterator = process.listIterator(); while (stackIterator.hasNext()) { Function f = stackIterator.next(); + final int curIndex = stackIterator.previousIndex(); if (f instanceof Multiplication || f instanceof Division) { - + if (curIndex-1>=0 && stackIterator.hasNext()) { + Function next = process.get(curIndex+1); + Function prev = process.get(curIndex-1); + stackIterator.set( + f.setParameter(0, prev) + .setParameter(1, next) + ); + process.remove(curIndex+1); + process.remove(curIndex-1); + } else { + if (f.getParameter(0) == null || f.getParameter(1) == null) { + throw new Error(Errors.MISSING_ARGUMENTS, "There is a function at the end without any argument specified."); + } + } } } //Phase 3 - stackIterator = process.iterator(); + stackIterator = process.listIterator(); while (stackIterator.hasNext()) { Function f = stackIterator.next();