Enchanced result appearance

This commit is contained in:
Andrea Cavalli 2017-06-05 22:50:33 +02:00
parent 845e4cdfe0
commit d46a9c5df4
23 changed files with 307 additions and 83 deletions

View File

@ -198,7 +198,6 @@ public class BlockContainer implements GraphicalElement {
}
public Block getBlock(Caret caret) {
boolean found = false;
Block block = null;
int pos = 0;
@ -208,10 +207,11 @@ public class BlockContainer implements GraphicalElement {
final int deltaCaret = caret.getRemaining();
block= b.getBlock(caret);
found = found | (block != null);
if (caret.getRemaining() == 0 || (found == false && deltaCaret >= 0 && caret.getRemaining() < 0)) {
if (block != null) {
return block;
}
if (caret.getRemaining() == 0 || (deltaCaret >= 0 && caret.getRemaining() < 0)) {
block = getBlockAt(pos - 1);
found = true;
return block;
}
}

View File

@ -6,7 +6,7 @@ import org.warp.picalculator.gui.graphicengine.GraphicEngine;
import org.warp.picalculator.gui.graphicengine.Renderer;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.parser.features.FeaturePower;
import org.warp.picalculator.math.parser.features.FeaturePowerChar;
import org.warp.picalculator.math.parser.features.interfaces.Feature;
public class BlockPower extends Block {
@ -78,6 +78,6 @@ public class BlockPower extends Block {
@Override
public Feature toFeature(MathContext context) throws Error {
final Function exp = getExponentContainer().toFunction(context);
return new FeaturePower(exp);
return new FeaturePowerChar(exp);
}
}

View File

@ -11,6 +11,7 @@ import org.warp.picalculator.gui.graphicengine.GraphicEngine;
import org.warp.picalculator.gui.graphicengine.Renderer;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.Variable.V_TYPE;
import org.warp.picalculator.math.parser.features.FeatureVariable;
import org.warp.picalculator.math.parser.features.interfaces.Feature;
public class BlockVariable extends Block {
@ -241,7 +242,6 @@ public class BlockVariable extends Block {
@Override
public Feature toFeature(MathContext context) throws Error {
// TODO Auto-generated method stub
return null;
return new FeatureVariable(ch, type);
}
}

View File

@ -93,7 +93,8 @@ public abstract class InputContainer implements GraphicalElement, InputLayout, S
public Block getSelectedBlock() {
caret.resetRemaining();
return root.getBlock(caret);
Block selectedBlock = root.getBlock(caret);
return selectedBlock;
}
public void moveLeft() {

View File

@ -14,47 +14,89 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
public abstract class OutputContainer implements GraphicalElement, OutputLayout, Serializable {
private static final long serialVersionUID = -5714825964892683571L;
public final BlockContainer root;
public final ObjectArrayList<BlockContainer> roots;
private final Caret caret = new Caret(CaretState.HIDDEN, 0);
public OutputContainer() {
root = new BlockContainer();
roots = new ObjectArrayList<>();
roots.add(new BlockContainer());
}
public OutputContainer(boolean small) {
root = new BlockContainer(small);
roots = new ObjectArrayList<>();
roots.add(new BlockContainer(small));
}
public OutputContainer(boolean small, int minWidth, int minHeight) {
root = new BlockContainer(small);
roots = new ObjectArrayList<>();
roots.add(new BlockContainer(small));
}
public void setContent(ObjectArrayList<Block> blocks) {
root.clear();
for (Block b : blocks) {
root.appendBlockUnsafe(b);
public void setContentAsSingleGroup(ObjectArrayList<Block> blocks) {
roots.clear();
BlockContainer bcnt = new BlockContainer();
for (Block block : blocks) {
bcnt.appendBlockUnsafe(block);
}
roots.add(bcnt);
recomputeDimensions();
}
public void setContentAsMultipleGroups(ObjectArrayList<ObjectArrayList<Block>> roots) {
this.roots.clear();
for (ObjectArrayList<Block> blocks : roots) {
BlockContainer bcnt = new BlockContainer();
for (Block block : blocks) {
bcnt.appendBlockUnsafe(block);
}
this.roots.add(bcnt);
}
recomputeDimensions();
}
public void setContentAsMultipleElements(ObjectArrayList<Block> elems) {
this.roots.clear();
for (Block block : elems) {
BlockContainer bcnt = new BlockContainer();
bcnt.appendBlockUnsafe(block);
this.roots.add(bcnt);
}
recomputeDimensions();
}
@Override
public void recomputeDimensions() {
root.recomputeDimensions();
for (BlockContainer root : roots) {
root.recomputeDimensions();
}
}
@Override
public int getWidth() {
return root.getWidth();
int maxw = 0;
for (BlockContainer root : roots) {
int w = root.getWidth();
if (w > maxw) maxw = w;
}
return maxw;
}
@Override
public int getHeight() {
return root.getHeight();
int h = 0;
for (BlockContainer root : roots) {
h+=root.getHeight()+2;
}
if (h > 0) {
return h-2;
} else {
return h;
}
}
@Override
public int getLine() {
return root.getLine();
return 0;
}
/**
@ -78,11 +120,26 @@ public abstract class OutputContainer implements GraphicalElement, OutputLayout,
* Position relative to the window.
*/
public void draw(GraphicEngine ge, Renderer r, int x, int y) {
root.draw(ge, r, x, y, caret);
int offset = 0;
for (BlockContainer root : roots) {
root.draw(ge, r, x, y+offset, caret);
offset+=root.getHeight()+2;
}
}
public void clear() {
root.clear();
roots.clear();
roots.add(new BlockContainer());
recomputeDimensions();
}
public boolean isContentEmpty() {
for(BlockContainer root : roots) {
ObjectArrayList<Block> cnt = root.getContent();
if (cnt != null && !cnt.isEmpty()) {
return false;
}
}
return true;
}
}

View File

@ -1,5 +1,4 @@
package org.warp.picalculator.gui.expression.containers;
public interface OutputLayout {
}

View File

@ -115,7 +115,7 @@ public class MathInputScreen extends Screen {
userInput.draw(DisplayManager.engine, DisplayManager.renderer, padding, padding + 20);
if (!result.root.getContent().isEmpty()) {
if (!result.isContentEmpty()) {
result.draw(DisplayManager.engine, DisplayManager.renderer, DisplayManager.engine.getWidth() - result.getWidth() - 2, DisplayManager.engine.getHeight() - result.getHeight() - 2);
}
}
@ -203,9 +203,42 @@ public class MathInputScreen extends Screen {
calc.f2.clear();
}
calc.f.add(expr);
ObjectArrayList<Function> resultExpression = expr.solve();
ObjectArrayList<Block> resultBlocks = MathParser.parseOutput(calc, resultExpression);
result.setContent(resultBlocks);
int stop = 0;
boolean done = false;
ObjectArrayList<ObjectArrayList<Function>> resultExpressions = new ObjectArrayList<>();
resultExpressions.add(new ObjectArrayList<Function>(expr.getParameters()));
while (!done && stop < 3000) {
ObjectArrayList<ObjectArrayList<Function>> newResultExpressions = new ObjectArrayList<>();
done = true;
for (ObjectArrayList<Function> resultExpr : resultExpressions) {
ObjectArrayList<Function> newResults = new ObjectArrayList<>();
for (Function f : resultExpr) {
if (f.isSimplified() == false) {
done = false;
if (f instanceof Expression) {
ObjectArrayList<Function> fncResult = ((Expression)f).solve();
for (Function resultItem : fncResult) {
newResultExpressions.add(new ObjectArrayList<Function>(new Function[] {resultItem}));
}
} else {
List<Function> fncResult = f.simplify();
for (Function resultItem : fncResult) {
newResultExpressions.add(new ObjectArrayList<Function>(new Function[] {resultItem}));
}
}
} else {
newResults.add(f);
}
}
if (newResults.isEmpty() == false) {
newResultExpressions.add(newResults);
}
}
resultExpressions = newResultExpressions;
stop++;
}
ObjectArrayList<ObjectArrayList<Block>> resultBlocks = MathParser.parseOutput(calc, resultExpressions);
result.setContentAsMultipleGroups(resultBlocks);
// showVariablesDialog(() -> {
// currentExpression = newExpression;
// simplify();

View File

@ -0,0 +1,22 @@
package org.warp.picalculator.math.parser;
import org.warp.picalculator.Error;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.Subtraction;
import org.warp.picalculator.math.parser.features.FeatureDoubleImpl;
import org.warp.picalculator.math.parser.features.interfaces.Feature;
import org.warp.picalculator.math.parser.features.interfaces.FeatureDouble;
public class FeatureSubtraction extends FeatureDoubleImpl {
public FeatureSubtraction(Object child1, Object child2) {
super(child1, child2);
}
@Override
public Function toFunction(MathContext context) throws Error {
return new Subtraction(context, getFunction1(), getFunction2());
}
}

View File

@ -0,0 +1,21 @@
package org.warp.picalculator.math.parser;
import org.warp.picalculator.Error;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.SumSubtraction;
import org.warp.picalculator.math.parser.features.FeatureDoubleImpl;
import org.warp.picalculator.math.parser.features.interfaces.Feature;
public class FeatureSumSubtraction extends FeatureDoubleImpl {
public FeatureSumSubtraction(Object child1, Object child2) {
super(child1, child2);
}
@Override
public SumSubtraction toFunction(MathContext context) throws Error {
return new SumSubtraction(context, getFunction1(), getFunction2());
}
}

View File

@ -32,7 +32,7 @@ import org.warp.picalculator.math.parser.features.FeatureDivision;
import org.warp.picalculator.math.parser.features.FeatureMultiplication;
import org.warp.picalculator.math.parser.features.FeatureNumber;
import org.warp.picalculator.math.parser.features.FeatureParenthesis;
import org.warp.picalculator.math.parser.features.FeaturePower;
import org.warp.picalculator.math.parser.features.FeaturePowerChar;
import org.warp.picalculator.math.parser.features.FeatureSquareRoot;
import org.warp.picalculator.math.parser.features.FeatureSum;
import org.warp.picalculator.math.parser.features.FeatureVariable;
@ -55,24 +55,32 @@ public class MathParser {
return result;
}
public static ObjectArrayList<Block> parseOutput(MathContext context, ObjectArrayList<Function> expr) throws Error {
final ObjectArrayList<Block> resultBlocks = new ObjectArrayList<>();
for (Function f : expr) {
ObjectArrayList<Block> resultPart = f.toBlock(context);
if (resultPart == null) throw new Error(Errors.NOT_IMPLEMENTED, "Unknown function " + f.getClass().getSimpleName());
resultBlocks.addAll(resultPart);
public static ObjectArrayList<ObjectArrayList<Block>> parseOutput(MathContext context, ObjectArrayList<ObjectArrayList<Function>> resultExpressions) throws Error {
final ObjectArrayList<ObjectArrayList<Block>> result = new ObjectArrayList<>();
for (ObjectArrayList<Function> resultExpression : resultExpressions) {
final ObjectArrayList<Block> resultBlocks = new ObjectArrayList<>();
for (Function f : resultExpression) {
ObjectArrayList<Block> resultPart = f.toBlock(context);
if (resultPart == null) throw new Error(Errors.NOT_IMPLEMENTED, "Unknown function " + f.getClass().getSimpleName());
resultBlocks.addAll(resultPart);
}
result.add(resultBlocks);
}
return resultBlocks;
return result;
}
public static Function joinFeatures(final MathContext context, ObjectArrayList<Feature> features) throws Error {
features = fixFeatures(context, features);
final ObjectArrayList<Function> process = makeFunctions(context, features);
final ObjectArrayList<Function> process = new ObjectArrayList<>();
for (final Feature f : features) {
Function fnc = f.toFunction(context);
if (fnc == null) throw new Error(Errors.SYNTAX_ERROR, "\"" + f.getClass().getSimpleName() + "\" can't be converted into a Function!");
process.add(fnc);
}
fixStack(context, process);
if (process.size() > 1) {
@ -197,46 +205,6 @@ public class MathParser {
} while (lastLoopDidSomething);
}
private static ObjectArrayList<Function> makeFunctions(MathContext context, ObjectArrayList<Feature> features)
throws Error {
final ObjectArrayList<Function> process = new ObjectArrayList<>();
for (final Feature f : features) {
if (f instanceof FeatureDivision) {
process.add(new Division(context, (Function) ((FeatureDouble) f).getChild1(), (Function) ((FeatureDouble) f).getChild2()));
} else if (f instanceof FeatureMultiplication) {
process.add(new Multiplication(context, (Function) ((FeatureDouble) f).getChild1(), (Function) ((FeatureDouble) f).getChild2()));
} else if (f instanceof FeatureVariable) {
process.add(new Variable(context, ((FeatureVariable) f).ch, ((FeatureVariable) f).varType));
} else if (f instanceof FeatureSum) {
process.add(new Sum(context, (Function) ((FeatureDouble) f).getChild1(), (Function) ((FeatureDouble) f).getChild2()));
} else if (f instanceof FeaturePower) {
if (process.isEmpty()) {
throw new Error(Errors.SYNTAX_ERROR, "There is a power at the beginning of the expression!");
} else {
Function prec = process.remove(process.size()-1);
process.add(new Power(context, prec, (Function) ((FeatureSingle) f).getChild()));
}
} else if (f instanceof FeatureSquareRoot) {
process.add(new RootSquare(context, (Function) ((FeatureSingle) f).getChild()));
} else if (f instanceof FeatureParenthesis) {
process.add(new Expression(context, (Function) ((FeatureSingle) f).getChild()));
// } else if (f instanceof FeatureSubtraction) {
// process.add(new Subtraction(context, (Function) ((FeatureDouble) f).getChild1(), (Function) ((FeatureDouble) f).getChild2()));
// } else if (f instanceof FeatureSumSubtraction) {
// process.add(new SumSubtraction(context, (Function) ((FeatureDouble) f).getChild1(), (Function) ((FeatureDouble) f).getChild2()));
} else if (f instanceof FeatureNumber) {
process.add(new Number(context, ((FeatureNumber) f).getNumberString()));
} else if (f instanceof FeatureChar) {
//All the char features must have been changed already before
throw new Error(Errors.SYNTAX_ERROR, "\"" + f.getClass().getSimpleName() + "\" can't be converted into a Function!");
} else {
throw new Error(Errors.SYNTAX_ERROR, "\"" + f.getClass().getSimpleName() + "\" can't be converted into a Function!");
}
}
return process;
}
private static ObjectArrayList<Feature> fixFeatures(final MathContext context, ObjectArrayList<Feature> features)
throws Error {
@ -268,6 +236,12 @@ public class MathParser {
case MathematicalSymbols.SUM:
result = new FeatureSum(null, null);
break;
case MathematicalSymbols.SUM_SUBTRACTION:
result = new FeatureSumSubtraction(null, null);
break;
case MathematicalSymbols.SUBTRACTION:
result = new FeatureSubtraction(null, null);
break;
case MathematicalSymbols.MULTIPLICATION:
result = new FeatureMultiplication(null, null);
break;

View File

@ -1,5 +1,7 @@
package org.warp.picalculator.math.parser.features;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.parser.features.interfaces.Feature;
public class FeatureChar implements Feature {
@ -10,4 +12,9 @@ public class FeatureChar implements Feature {
this.ch = ch;
}
@Override
public Function toFunction(MathContext context) {
return null;
}
}

View File

@ -1,9 +1,18 @@
package org.warp.picalculator.math.parser.features;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.Division;
public class FeatureDivision extends FeatureDoubleImpl {
public FeatureDivision(Object child1, Object child2) {
super(child1, child2);
}
@Override
public Division toFunction(MathContext context) {
return new Division(context, getFunction1(), getFunction2());
}
}

View File

@ -1,6 +1,7 @@
package org.warp.picalculator.math.parser.features;
import org.warp.picalculator.math.parser.features.interfaces.FeatureDouble;
import org.warp.picalculator.math.Function;
public abstract class FeatureDoubleImpl implements FeatureDouble {
private Object child_1;
@ -30,4 +31,12 @@ public abstract class FeatureDoubleImpl implements FeatureDouble {
public void setChild2(Object obj) {
child_2 = obj;
}
protected Function getFunction1() {
return (Function) child_1;
}
protected Function getFunction2() {
return (Function) child_2;
}
}

View File

@ -1,9 +1,18 @@
package org.warp.picalculator.math.parser.features;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.Multiplication;
public class FeatureMultiplication extends FeatureDoubleImpl {
public FeatureMultiplication(Object child1, Object child2) {
super(child1, child2);
}
@Override
public Multiplication toFunction(MathContext context) {
return new Multiplication(context, getFunction1(), getFunction2());
}
}

View File

@ -1,5 +1,9 @@
package org.warp.picalculator.math.parser.features;
import org.warp.picalculator.Error;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.Number;
import org.warp.picalculator.math.parser.features.interfaces.FeatureBasic;
public class FeatureNumber implements FeatureBasic {
@ -24,4 +28,9 @@ public class FeatureNumber implements FeatureBasic {
public void append(char ch) {
numberString += ch;
}
@Override
public Number toFunction(MathContext context) throws Error {
return new Number(context, getNumberString());
}
}

View File

@ -1,9 +1,19 @@
package org.warp.picalculator.math.parser.features;
import org.warp.picalculator.Error;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.Expression;
public class FeatureParenthesis extends FeatureSingleImpl {
public FeatureParenthesis(Object child) {
super(child);
}
@Override
public Function toFunction(MathContext context) throws Error {
return new Expression(context, this.getFunction1());
}
}

View File

@ -1,9 +1,18 @@
package org.warp.picalculator.math.parser.features;
public class FeaturePower extends FeatureSingleImpl {
import org.warp.picalculator.Error;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.Power;
public FeaturePower(Object child) {
super(child);
public class FeaturePower extends FeatureDoubleImpl {
public FeaturePower(Object child1, Object child2) {
super(child1, child2);
}
@Override
public Power toFunction(MathContext context) throws Error {
return new Power(context, getFunction1(), getFunction2());
}
}

View File

@ -0,0 +1,19 @@
package org.warp.picalculator.math.parser.features;
import org.warp.picalculator.Error;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.Power;
public class FeaturePowerChar extends FeatureSingleImpl {
public FeaturePowerChar(Object child) {
super(child);
}
@Override
public Function toFunction(MathContext context) throws Error {
return null;
}
}

View File

@ -1,5 +1,6 @@
package org.warp.picalculator.math.parser.features;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.parser.features.interfaces.FeatureSingle;
public abstract class FeatureSingleImpl implements FeatureSingle {
@ -13,6 +14,10 @@ public abstract class FeatureSingleImpl implements FeatureSingle {
public Object getChild() {
return child;
}
protected Function getFunction1() {
return (Function) child;
}
@Override
public void setChild(Object obj) {

View File

@ -1,9 +1,18 @@
package org.warp.picalculator.math.parser.features;
import org.warp.picalculator.Error;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.RootSquare;
public class FeatureSquareRoot extends FeatureSingleImpl {
public FeatureSquareRoot(Object child) {
super(child);
}
@Override
public RootSquare toFunction(MathContext context) throws Error {
return new RootSquare(context, getFunction1());
}
}

View File

@ -1,9 +1,18 @@
package org.warp.picalculator.math.parser.features;
import org.warp.picalculator.Error;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.Sum;
public class FeatureSum extends FeatureDoubleImpl {
public FeatureSum(Object child1, Object child2) {
super(child1, child2);
}
@Override
public Sum toFunction(MathContext context) throws Error {
return new Sum(context, getFunction1(), getFunction2());
}
}

View File

@ -1,5 +1,8 @@
package org.warp.picalculator.math.parser.features;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
import org.warp.picalculator.math.functions.Variable;
import org.warp.picalculator.math.functions.Variable.V_TYPE;
public class FeatureVariable extends FeatureChar {
@ -11,4 +14,8 @@ public class FeatureVariable extends FeatureChar {
this.varType = varType;
}
@Override
public Function toFunction(MathContext context) {
return new Variable(context, ch, varType);
}
}

View File

@ -1,5 +1,11 @@
package org.warp.picalculator.math.parser.features.interfaces;
import org.warp.picalculator.Error;
import org.warp.picalculator.math.Function;
import org.warp.picalculator.math.MathContext;
public abstract interface Feature {
public Function toFunction(MathContext context) throws Error;
}