group separator in editor

This commit is contained in:
serso 2011-10-23 15:10:25 +04:00
parent 1222bed9bd
commit 3e3f822a3e
6 changed files with 161 additions and 114 deletions

View File

@ -8,6 +8,7 @@ package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.math.MathType; import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.model.NumberBuilder;
import org.solovyev.android.calculator.model.ParseException; import org.solovyev.android.calculator.model.ParseException;
import org.solovyev.android.calculator.model.TextProcessor; import org.solovyev.android.calculator.model.TextProcessor;
@ -43,9 +44,12 @@ public class TextHighlighter implements TextProcessor<String> {
final StringBuilder text1 = new StringBuilder(); final StringBuilder text1 = new StringBuilder();
final NumberBuilder numberBuilder = new NumberBuilder();
for (int i = 0; i < text.length(); i++) { for (int i = 0; i < text.length(); i++) {
final MathType.Result mathType = MathType.getType(text, i); final MathType.Result mathType = MathType.getType(text, i);
numberBuilder.process(text1, mathType);
switch (mathType.getMathType()) { switch (mathType.getMathType()) {
case open_group_symbol: case open_group_symbol:
numberOfOpenGroupSymbols++; numberOfOpenGroupSymbols++;
@ -67,6 +71,8 @@ public class TextHighlighter implements TextProcessor<String> {
} }
} }
numberBuilder.process(text1);
if (maxNumberOfOpenGroupSymbols > 0) { if (maxNumberOfOpenGroupSymbols > 0) {
final StringBuilder text2 = new StringBuilder(); final StringBuilder text2 = new StringBuilder();

View File

@ -38,14 +38,14 @@ public enum MathType {
power_10(300, true, false, "E") { power_10(300, true, false, "E") {
@Override @Override
protected String getSubstitute(@NotNull String match) { protected String getSubstituteToJscl(@NotNull String match) {
return POWER_10_JSCL; return POWER_10_JSCL;
} }
}, },
postfix_function(400, true, false, Functions.allPostfix) { postfix_function(400, true, false, Functions.allPostfix) {
@Override @Override
protected String getSubstitute(@NotNull String match) { protected String getSubstituteToJscl(@NotNull String match) {
final String result; final String result;
if (match.equals(Functions.DEGREE)) { if (match.equals(Functions.DEGREE)) {
@ -60,7 +60,7 @@ public enum MathType {
unary_operation(500, false, false, "-", "=", "!"), unary_operation(500, false, false, "-", "=", "!"),
binary_operation(600, false, false, "-", "+", "*", "×", "", "/", "^") { binary_operation(600, false, false, "-", "+", "*", "×", "", "/", "^") {
@Override @Override
protected String getSubstitute(@NotNull String match) { protected String getSubstituteToJscl(@NotNull String match) {
if (match.equals("×") || match.equals("")) { if (match.equals("×") || match.equals("")) {
return "*"; return "*";
} else { } else {
@ -76,7 +76,7 @@ public enum MathType {
} }
@Override @Override
protected String getSubstitute(@NotNull String match) { protected String getSubstituteToJscl(@NotNull String match) {
return "("; return "(";
} }
}, },
@ -88,14 +88,14 @@ public enum MathType {
} }
@Override @Override
protected String getSubstitute(@NotNull String match) { protected String getSubstituteToJscl(@NotNull String match) {
return ")"; return ")";
} }
}, },
function(1000, true, true, Functions.allPrefix) { function(1000, true, true, Functions.allPrefix) {
@Override @Override
protected String getSubstitute(@NotNull String match) { protected String getSubstituteToJscl(@NotNull String match) {
final String result; final String result;
if (match.equals(Functions.LN)) { if (match.equals(Functions.LN)) {
@ -103,7 +103,22 @@ public enum MathType {
} else if (match.equals(Functions.SQRT)) { } else if (match.equals(Functions.SQRT)) {
result = Functions.SQRT_JSCL; result = Functions.SQRT_JSCL;
} else { } else {
result = match; result = null;
}
return result;
}
@Override
protected String getSubstituteFromJscl(@NotNull String match) {
final String result;
if (match.equals(Functions.LN_JSCL)) {
result = Functions.LN;
} else if (match.equals(Functions.SQRT_JSCL)) {
result = Functions.SQRT;
} else {
result = null;
} }
return result; return result;
@ -118,7 +133,23 @@ public enum MathType {
} }
}, },
text(1200, false, false); text(1200, false, false) {
@Override
public int processToJscl(@NotNull StringBuilder result, int i, @NotNull String match) {
if (match.length() > 0) {
result.append(match.charAt(0));
}
return i;
}
@Override
public int processFromJscl(@NotNull StringBuilder result, int i, @NotNull String match) {
if (match.length() > 0) {
result.append(match.charAt(0));
}
return i;
}
};
@NotNull @NotNull
private final List<String> tokens; private final List<String> tokens;
@ -164,14 +195,25 @@ public enum MathType {
return needMultiplicationSignBefore && mathTypeBefore.isNeedMultiplicationSignAfter(); return needMultiplicationSignBefore && mathTypeBefore.isNeedMultiplicationSignAfter();
} }
public int process(@NotNull StringBuilder result, int i, @NotNull String match) { public int processToJscl(@NotNull StringBuilder result, int i, @NotNull String match) {
final String substitute = getSubstitute(match); final String substitute = getSubstituteToJscl(match);
result.append(substitute == null ? match : substitute);
return i + match.length() - 1;
}
public int processFromJscl(@NotNull StringBuilder result, int i, @NotNull String match) {
final String substitute = getSubstituteFromJscl(match);
result.append(substitute == null ? match : substitute); result.append(substitute == null ? match : substitute);
return i + match.length() - 1; return i + match.length() - 1;
} }
@Nullable @Nullable
protected String getSubstitute(@NotNull String match) { protected String getSubstituteFromJscl(@NotNull String match) {
return null;
}
@Nullable
protected String getSubstituteToJscl(@NotNull String match) {
return null; return null;
} }
@ -256,8 +298,12 @@ public enum MathType {
this.match = match; this.match = match;
} }
public int process(@NotNull StringBuilder result, int i) { public int processToJscl(@NotNull StringBuilder result, int i) {
return mathType.process(result, i, match); return mathType.processToJscl(result, i, match);
}
public int processFromJscl(@NotNull StringBuilder result, int i) {
return mathType.processFromJscl(result, i, match);
} }
@NotNull @NotNull

View File

@ -2,10 +2,7 @@ package org.solovyev.android.calculator.model;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.math.Functions;
import org.solovyev.android.calculator.math.MathType; import org.solovyev.android.calculator.math.MathType;
import org.solovyev.common.utils.CollectionsUtils;
import org.solovyev.common.utils.Finder;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -17,91 +14,31 @@ import java.util.List;
*/ */
public class FromJsclSimplifyTextProcessor implements TextProcessor<String> { public class FromJsclSimplifyTextProcessor implements TextProcessor<String> {
@NotNull @NotNull
@Override @Override
public String process(@NotNull String s) throws ParseException { public String process(@NotNull String s) throws ParseException {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
MathType.Result mathTypeResult = null; final NumberBuilder numberBuilder = new NumberBuilder();
StringBuilder numberBuilder = null;
String number = null;
for (int i = 0; i < s.length(); i++) { for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i); char ch = s.charAt(i);
if ( Character.isWhitespace(ch) ) { if ( Character.isWhitespace(ch) ) {
continue; continue;
} }
mathTypeResult = MathType.getType(s, i); final MathType.Result mathTypeResult = MathType.getType(s, i);
final MathType mathType = mathTypeResult.getMathType(); numberBuilder.process(sb, mathTypeResult);
number = null; i = mathTypeResult.processFromJscl(sb, i);
if (mathType == MathType.digit || mathType == MathType.dot || mathType == MathType.power_10) {
if (numberBuilder == null) {
numberBuilder = new StringBuilder();
}
numberBuilder.append(mathTypeResult.getMatch());
} else {
if (numberBuilder != null) {
try {
number = numberBuilder.toString();
Double.valueOf(number);
} catch (NumberFormatException e) {
number = null;
} }
numberBuilder = null; numberBuilder.process(sb);
} else {
number = null;
}
}
replaceSystemVars(sb, number);
if (mathType == MathType.constant){
sb.append(mathTypeResult.getMatch());
i += mathTypeResult.getMatch().length() - 1;
} else if ( mathType == MathType.function) {
sb.append(fromJsclFunction(mathTypeResult.getMatch()));
i += mathTypeResult.getMatch().length() - 1;
} else {
sb.append(ch);
}
}
if (numberBuilder != null) {
try {
number = numberBuilder.toString();
Double.valueOf(number);
} catch (NumberFormatException e) {
number = null;
}
numberBuilder = null;
} else {
number = null;
}
replaceSystemVars(sb, number);
return removeMultiplicationSigns(sb.toString()); return removeMultiplicationSigns(sb.toString());
} }
@NotNull
private static String fromJsclFunction(@NotNull String function) {
final String result;
if (function.equals(Functions.LN_JSCL)) {
result = Functions.LN;
} else if (function.equals(Functions.SQRT_JSCL)) {
result = Functions.SQRT;
} else {
result = function;
}
return result;
}
@NotNull @NotNull
private String removeMultiplicationSigns(String s) { private String removeMultiplicationSigns(String s) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
@ -161,30 +98,4 @@ public class FromJsclSimplifyTextProcessor implements TextProcessor<String> {
return true; return true;
} }
@Nullable
private MathType replaceSystemVars(StringBuilder sb, String number) {
MathType result = null;
if (number != null) {
final String finalNumber = number;
final Var var = CollectionsUtils.get(CalculatorEngine.instance.getVarsRegister().getSystemVars(), new Finder<Var>() {
@Override
public boolean isFound(@Nullable Var var) {
return var != null && finalNumber.equals(var.getValue());
}
});
if (var != null) {
sb.delete(sb.length() - number.length(), sb.length());
sb.append(var.getName());
result = MathType.constant;
} else {
sb.delete(sb.length() - number.length(), sb.length());
sb.append(CalculatorEngine.instance.format(Double.valueOf(number)));
}
}
return result;
}
} }

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.android.calculator.model;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.math.MathType;
import org.solovyev.common.utils.CollectionsUtils;
import org.solovyev.common.utils.Finder;
/**
* User: serso
* Date: 10/23/11
* Time: 2:57 PM
*/
public class NumberBuilder {
@Nullable
private StringBuilder numberBuilder = null;
@Nullable
private String number = null;
public void process(@NotNull StringBuilder sb, @NotNull MathType.Result mathTypeResult) {
number = null;
if (mathTypeResult.getMathType() == MathType.digit || mathTypeResult.getMathType() == MathType.dot || mathTypeResult.getMathType() == MathType.power_10) {
if (numberBuilder == null) {
numberBuilder = new StringBuilder();
}
numberBuilder.append(mathTypeResult.getMatch());
replaceSystemVars(sb, number);
} else {
process(sb);
}
}
public void process(@NotNull StringBuilder sb) {
if (numberBuilder != null) {
try {
number = numberBuilder.toString();
Double.valueOf(number);
} catch (NumberFormatException e) {
number = null;
}
numberBuilder = null;
} else {
number = null;
}
replaceSystemVars(sb, number);
}
@Nullable
private MathType replaceSystemVars(StringBuilder sb, String number) {
MathType result = null;
if (number != null) {
final String finalNumber = number;
final Var var = CollectionsUtils.get(CalculatorEngine.instance.getVarsRegister().getSystemVars(), new Finder<Var>() {
@Override
public boolean isFound(@Nullable Var var) {
return var != null && finalNumber.equals(var.getValue());
}
});
if (var != null) {
sb.delete(sb.length() - number.length(), sb.length());
sb.append(var.getName());
result = MathType.constant;
} else {
sb.delete(sb.length() - number.length(), sb.length());
sb.append(CalculatorEngine.instance.format(Double.valueOf(number)));
}
}
return result;
}
}

View File

@ -54,7 +54,7 @@ class ToJsclTextProcessor implements TextProcessor<PreparedExpression> {
throw new ParseException("Empty function: " + mathTypeResult.getMatch()); throw new ParseException("Empty function: " + mathTypeResult.getMatch());
} }
i = mathTypeResult.process(result, i); i = mathTypeResult.processToJscl(result, i);
} }
return replaceVariables(result.toString()); return replaceVariables(result.toString());

View File

@ -41,5 +41,6 @@ public class TextHighlighterTest {
Assert.assertEquals("<font color=\"#000000\"></font>)(((())())", textHighlighter.process(")(((())())")); Assert.assertEquals("<font color=\"#000000\"></font>)(((())())", textHighlighter.process(")(((())())"));
Assert.assertEquals(")", textHighlighter.process(")")); Assert.assertEquals(")", textHighlighter.process(")"));
Assert.assertEquals(")()(", textHighlighter.process(")()(")); Assert.assertEquals(")()(", textHighlighter.process(")()("));
Assert.assertEquals("1 000 000", textHighlighter.process("1000000"));
} }
} }