group separator in editor
This commit is contained in:
parent
57984f9f51
commit
0d9e99886b
@ -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();
|
||||||
|
@ -29,7 +29,7 @@ public enum MathType {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
dot(200, true, true, "."){
|
dot(200, true, true, ".") {
|
||||||
@Override
|
@Override
|
||||||
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
|
public boolean isNeedMultiplicationSignBefore(@NotNull MathType mathTypeBefore) {
|
||||||
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit;
|
return super.isNeedMultiplicationSignBefore(mathTypeBefore) && mathTypeBefore != digit;
|
||||||
@ -38,17 +38,17 @@ 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)) {
|
||||||
result = PI + "/180";
|
result = PI + "/180";
|
||||||
} else {
|
} else {
|
||||||
result = null;
|
result = null;
|
||||||
@ -60,8 +60,8 @@ 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 {
|
||||||
return null;
|
return null;
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +255,7 @@ public enum MathType {
|
|||||||
|
|
||||||
for (MathType mathType : getMathTypesByPriority()) {
|
for (MathType mathType : getMathTypesByPriority()) {
|
||||||
final String s = get(mathType.getTokens(), startsWithFinder);
|
final String s = get(mathType.getTokens(), startsWithFinder);
|
||||||
if ( s != null ) {
|
if (s != null) {
|
||||||
return new Result(mathType, s);
|
return new Result(mathType, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,7 +268,7 @@ public enum MathType {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static List<MathType> getMathTypesByPriority() {
|
private static List<MathType> getMathTypesByPriority() {
|
||||||
if ( mathTypesByPriority == null ) {
|
if (mathTypesByPriority == null) {
|
||||||
final List<MathType> result = CollectionsUtils.asList(MathType.values());
|
final List<MathType> result = CollectionsUtils.asList(MathType.values());
|
||||||
|
|
||||||
Collections.sort(result, new Comparator<MathType>() {
|
Collections.sort(result, new Comparator<MathType>() {
|
||||||
@ -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
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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());
|
||||||
|
@ -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"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user