changes
This commit is contained in:
parent
780d278fda
commit
848012615e
@ -10,6 +10,7 @@
|
|||||||
xmlns:calc="http://schemas.android.com/apk/res/org.solovyev.android.calculator"
|
xmlns:calc="http://schemas.android.com/apk/res/org.solovyev.android.calculator"
|
||||||
a:id="@+id/eightDigitButton" a:text="8"
|
a:id="@+id/eightDigitButton" a:text="8"
|
||||||
calc:textUp="ln"
|
calc:textUp="ln"
|
||||||
|
calc:textLeft="0b:"
|
||||||
calc:textDown="lg"
|
calc:textDown="lg"
|
||||||
calc:directionTextScale="0.5"
|
calc:directionTextScale="0.5"
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
a:id="@+id/fiveDigitButton"
|
a:id="@+id/fiveDigitButton"
|
||||||
a:text="5"
|
a:text="5"
|
||||||
calc:textUp="t"
|
calc:textUp="t"
|
||||||
|
calc:textLeft="e"
|
||||||
calc:textDown="j"
|
calc:textDown="j"
|
||||||
style="?digitButtonStyle"
|
style="?digitButtonStyle"
|
||||||
a:onClick="digitButtonClickHandler"/>
|
a:onClick="digitButtonClickHandler"/>
|
@ -10,6 +10,7 @@
|
|||||||
a:id="@+id/fourDigitButton"
|
a:id="@+id/fourDigitButton"
|
||||||
a:text="4"
|
a:text="4"
|
||||||
calc:textUp="x"
|
calc:textUp="x"
|
||||||
|
calc:textLeft="d"
|
||||||
calc:textDown="y"
|
calc:textDown="y"
|
||||||
style="?digitButtonStyle"
|
style="?digitButtonStyle"
|
||||||
a:onClick="digitButtonClickHandler"/>
|
a:onClick="digitButtonClickHandler"/>
|
@ -10,6 +10,7 @@
|
|||||||
xmlns:calc="http://schemas.android.com/apk/res/org.solovyev.android.calculator"
|
xmlns:calc="http://schemas.android.com/apk/res/org.solovyev.android.calculator"
|
||||||
a:id="@+id/nineDigitButton" a:text="9"
|
a:id="@+id/nineDigitButton" a:text="9"
|
||||||
calc:textDown="e"
|
calc:textDown="e"
|
||||||
|
calc:textLeft="0o:"
|
||||||
calc:textUp="π"
|
calc:textUp="π"
|
||||||
calc:directionTextScale="0.5"
|
calc:directionTextScale="0.5"
|
||||||
style="?digitButtonStyle"
|
style="?digitButtonStyle"
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
a:id="@+id/oneDigitButton"
|
a:id="@+id/oneDigitButton"
|
||||||
a:text="1"
|
a:text="1"
|
||||||
calc:textUp="sin"
|
calc:textUp="sin"
|
||||||
|
calc:textLeft="a"
|
||||||
calc:textDown="asin"
|
calc:textDown="asin"
|
||||||
style="?digitButtonStyle"
|
style="?digitButtonStyle"
|
||||||
a:onClick="digitButtonClickHandler"/>
|
a:onClick="digitButtonClickHandler"/>
|
@ -10,6 +10,7 @@
|
|||||||
xmlns:calc="http://schemas.android.com/apk/res/org.solovyev.android.calculator"
|
xmlns:calc="http://schemas.android.com/apk/res/org.solovyev.android.calculator"
|
||||||
a:id="@+id/sevenDigitButton" a:text="7"
|
a:id="@+id/sevenDigitButton" a:text="7"
|
||||||
calc:textUp="i"
|
calc:textUp="i"
|
||||||
|
calc:textLeft="0x:"
|
||||||
calc:textDown="!"
|
calc:textDown="!"
|
||||||
calc:directionTextScale="0.5"
|
calc:directionTextScale="0.5"
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
calc:textUp="deg"
|
calc:textUp="deg"
|
||||||
a:id="@+id/sixDigitButton"
|
a:id="@+id/sixDigitButton"
|
||||||
a:text="6"
|
a:text="6"
|
||||||
|
calc:textLeft="f"
|
||||||
calc:textDown="rad"
|
calc:textDown="rad"
|
||||||
style="?digitButtonStyle"
|
style="?digitButtonStyle"
|
||||||
a:onClick="digitButtonClickHandler"/>
|
a:onClick="digitButtonClickHandler"/>
|
@ -11,6 +11,7 @@
|
|||||||
a:id="@+id/threeDigitButton"
|
a:id="@+id/threeDigitButton"
|
||||||
a:text="3"
|
a:text="3"
|
||||||
calc:textUp="tan"
|
calc:textUp="tan"
|
||||||
|
calc:textLeft="c"
|
||||||
calc:textDown="atan"
|
calc:textDown="atan"
|
||||||
style="?digitButtonStyle"
|
style="?digitButtonStyle"
|
||||||
a:onClick="digitButtonClickHandler"/>
|
a:onClick="digitButtonClickHandler"/>
|
30
res/layout/calc_title.xml
Normal file
30
res/layout/calc_title.xml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ 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
|
||||||
|
-->
|
||||||
|
|
||||||
|
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
|
a:orientation="horizontal"
|
||||||
|
a:gravity="center_vertical"
|
||||||
|
a:layout_width="fill_parent"
|
||||||
|
a:layout_height="fill_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
a:layout_width="wrap_content"
|
||||||
|
a:layout_height="wrap_content"
|
||||||
|
a:layout_gravity="left"
|
||||||
|
style="@style/WindowTitle"
|
||||||
|
a:text="@string/c_app_name"/>
|
||||||
|
|
||||||
|
<org.solovyev.android.calculator.CalculatorAdditionalTitle
|
||||||
|
a:id="@+id/additional_title_text"
|
||||||
|
a:layout_width="fill_parent"
|
||||||
|
a:layout_height="wrap_content"
|
||||||
|
style="@style/WindowTitle"
|
||||||
|
a:gravity="center_vertical|right"
|
||||||
|
a:layout_gravity="right"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -11,6 +11,7 @@
|
|||||||
a:id="@+id/twoDigitButton"
|
a:id="@+id/twoDigitButton"
|
||||||
a:text="2"
|
a:text="2"
|
||||||
calc:textUp="cos"
|
calc:textUp="cos"
|
||||||
|
calc:textLeft="b"
|
||||||
calc:textDown="acos"
|
calc:textDown="acos"
|
||||||
style="?digitButtonStyle"
|
style="?digitButtonStyle"
|
||||||
a:onClick="digitButtonClickHandler"/>
|
a:onClick="digitButtonClickHandler"/>
|
@ -8,8 +8,10 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="p_drag_distance_key">org.solovyev.android.calculator.DragButtonCalibrationActivity_distance</string>
|
<string name="p_drag_distance_key">org.solovyev.android.calculator.DragButtonCalibrationActivity_distance</string>
|
||||||
<string name="p_drag_distance">15;350</string>
|
<string name="p_drag_distance">15;350</string>
|
||||||
|
|
||||||
<string name="p_drag_angle_key">org.solovyev.android.calculator.DragButtonCalibrationActivity_angle</string>
|
<string name="p_drag_angle_key">org.solovyev.android.calculator.DragButtonCalibrationActivity_angle</string>
|
||||||
<string name="p_drag_angle">0;45</string>
|
<string name="p_drag_angle">0;45</string>
|
||||||
|
|
||||||
<string name="p_drag_duration_key">org.solovyev.android.calculator.DragButtonCalibrationActivity_duration</string>
|
<string name="p_drag_duration_key">org.solovyev.android.calculator.DragButtonCalibrationActivity_duration</string>
|
||||||
<string name="p_drag_duration">40;2500</string>
|
<string name="p_drag_duration">40;2500</string>
|
||||||
|
|
||||||
|
@ -6,6 +6,20 @@
|
|||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
|
<style name="WindowTitle">
|
||||||
|
<item name="android:singleLine">true</item>
|
||||||
|
<item name="android:textAppearance">@style/TextAppearance_WindowTitle</item>
|
||||||
|
<item name="android:shadowColor">#BB000000</item>
|
||||||
|
<item name="android:shadowRadius">2.75</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="TextAppearance_WindowTitle">
|
||||||
|
<item name="android:textColor">#fff</item>
|
||||||
|
<item name="android:textSize">14sp</item>
|
||||||
|
<item name="android:textStyle">bold</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
<style name="default_text_size">
|
<style name="default_text_size">
|
||||||
<item name="android:textSize">20dp</item>
|
<item name="android:textSize">20dp</item>
|
||||||
</style>
|
</style>
|
||||||
|
@ -66,6 +66,8 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
|||||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
Log.d(this.getClass().getName(), "org.solovyev.android.calculator.CalculatorActivity.onCreate()");
|
Log.d(this.getClass().getName(), "org.solovyev.android.calculator.CalculatorActivity.onCreate()");
|
||||||
|
|
||||||
|
final boolean customTitleSupported = requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
|
||||||
|
|
||||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
|
||||||
setDefaultValues(preferences);
|
setDefaultValues(preferences);
|
||||||
@ -74,6 +76,13 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setLayout(preferences);
|
setLayout(preferences);
|
||||||
|
|
||||||
|
if (customTitleSupported) {
|
||||||
|
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.calc_title);
|
||||||
|
final CalculatorAdditionalTitle additionalAdditionalTitleText = (CalculatorAdditionalTitle)findViewById(R.id.additional_title_text);
|
||||||
|
additionalAdditionalTitleText.init(preferences);
|
||||||
|
preferences.registerOnSharedPreferenceChangeListener(additionalAdditionalTitleText);
|
||||||
|
}
|
||||||
|
|
||||||
ResourceCache.instance.initCaptions(ApplicationContext.getInstance(), R.string.class);
|
ResourceCache.instance.initCaptions(ApplicationContext.getInstance(), R.string.class);
|
||||||
firstTimeInit(preferences);
|
firstTimeInit(preferences);
|
||||||
|
|
||||||
@ -137,6 +146,8 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
|||||||
|
|
||||||
private class AngleUnitsChanger implements SimpleOnDragListener.DragProcessor {
|
private class AngleUnitsChanger implements SimpleOnDragListener.DragProcessor {
|
||||||
|
|
||||||
|
private final DigitButtonDragProcessor processor = new DigitButtonDragProcessor(calculatorModel);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean processDragEvent(@NotNull DragDirection dragDirection,
|
public boolean processDragEvent(@NotNull DragDirection dragDirection,
|
||||||
@NotNull DragButton dragButton,
|
@NotNull DragButton dragButton,
|
||||||
@ -144,22 +155,26 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
|||||||
@NotNull MotionEvent motionEvent) {
|
@NotNull MotionEvent motionEvent) {
|
||||||
boolean result = false;
|
boolean result = false;
|
||||||
|
|
||||||
if ( dragButton instanceof AngleUnitsButton ) {
|
if (dragButton instanceof AngleUnitsButton) {
|
||||||
final String directionText = ((AngleUnitsButton) dragButton).getText(dragDirection);
|
if (dragDirection == DragDirection.up || dragDirection == DragDirection.down ) {
|
||||||
if ( directionText != null ) {
|
final String directionText = ((AngleUnitsButton) dragButton).getText(dragDirection);
|
||||||
try {
|
if ( directionText != null ) {
|
||||||
|
try {
|
||||||
|
|
||||||
final AngleUnit angleUnits = AngleUnit.valueOf(directionText);
|
final AngleUnit angleUnits = AngleUnit.valueOf(directionText);
|
||||||
|
|
||||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(CalculatorActivity.this);
|
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(CalculatorActivity.this);
|
||||||
final SharedPreferences.Editor editor = preferences.edit();
|
final SharedPreferences.Editor editor = preferences.edit();
|
||||||
editor.putString(CalculatorEngine.ANGLE_UNITS_P_KEY, angleUnits.name());
|
editor.putString(CalculatorEngine.ANGLE_UNITS_P_KEY, angleUnits.name());
|
||||||
editor.commit();
|
editor.commit();
|
||||||
|
|
||||||
result = true;
|
result = true;
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
Log.d(this.getClass().getName(), "Unsupported angle units: " + directionText);
|
Log.d(this.getClass().getName(), "Unsupported angle units: " + directionText);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else if ( dragDirection == DragDirection.left ) {
|
||||||
|
result = processor.processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,6 +548,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
|||||||
}
|
}
|
||||||
|
|
||||||
calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance);
|
calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance);
|
||||||
|
calculatorModel.evaluate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 12/10/11
|
||||||
|
* Time: 10:34 PM
|
||||||
|
*/
|
||||||
|
public class CalculatorAdditionalTitle extends TextView implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
|
public CalculatorAdditionalTitle(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CalculatorAdditionalTitle(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CalculatorAdditionalTitle(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(@NotNull SharedPreferences preferences) {
|
||||||
|
onSharedPreferenceChanged(preferences, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSharedPreferenceChanged(SharedPreferences preferences, @Nullable String key) {
|
||||||
|
setText(CalculatorEngine.instance.getNumeralBaseFromPrefs(preferences) + " / " + CalculatorEngine.instance.getAngleUnitsFromPrefs(preferences));
|
||||||
|
}
|
||||||
|
}
|
@ -35,7 +35,7 @@ public class CalculatorDisplay extends AutoResizeTextView {
|
|||||||
private JsclOperation jsclOperation = JsclOperation.numeric;
|
private JsclOperation jsclOperation = JsclOperation.numeric;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final static TextProcessor<TextHighlighter.Result> textHighlighter = new TextHighlighter(Color.WHITE, true, CalculatorEngine.instance.getEngine());
|
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, true, CalculatorEngine.instance.getEngine());
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Generic genericResult;
|
private Generic genericResult;
|
||||||
|
@ -31,7 +31,7 @@ public class CalculatorEditor extends EditText implements SharedPreferences.OnSh
|
|||||||
private boolean highlightText = true;
|
private boolean highlightText = true;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final static TextProcessor<TextHighlighter.Result> textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine());
|
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine());
|
||||||
|
|
||||||
public CalculatorEditor(Context context) {
|
public CalculatorEditor(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
@ -8,18 +8,27 @@ package org.solovyev.android.calculator;
|
|||||||
|
|
||||||
import jscl.MathContext;
|
import jscl.MathContext;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
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.NumberBuilder;
|
||||||
import org.solovyev.android.calculator.model.CalculatorParseException;
|
import org.solovyev.android.calculator.model.CalculatorParseException;
|
||||||
import org.solovyev.android.calculator.model.TextProcessor;
|
import org.solovyev.android.calculator.model.TextProcessor;
|
||||||
import org.solovyev.common.utils.MutableObject;
|
import org.solovyev.common.utils.MutableObject;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 10/12/11
|
* Date: 10/12/11
|
||||||
* Time: 9:47 PM
|
* Time: 9:47 PM
|
||||||
*/
|
*/
|
||||||
public class TextHighlighter implements TextProcessor<TextHighlighter.Result> {
|
public class TextHighlighter implements TextProcessor<TextHighlighter.Result, String> {
|
||||||
|
|
||||||
|
private static final Map<String, String> nbFontAttributes = new HashMap<String, String>();
|
||||||
|
static {
|
||||||
|
nbFontAttributes.put("color", "#008000");
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public final MathContext mathContext;
|
public final MathContext mathContext;
|
||||||
@ -99,6 +108,7 @@ public class TextHighlighter implements TextProcessor<TextHighlighter.Result> {
|
|||||||
numberBuilder.process(text1, mathType, localNumberOffset);
|
numberBuilder.process(text1, mathType, localNumberOffset);
|
||||||
numberOffset += localNumberOffset.getObject();
|
numberOffset += localNumberOffset.getObject();
|
||||||
|
|
||||||
|
final String match = mathType.getMatch();
|
||||||
switch (mathType.getMathType()) {
|
switch (mathType.getMathType()) {
|
||||||
case open_group_symbol:
|
case open_group_symbol:
|
||||||
numberOfOpenGroupSymbols++;
|
numberOfOpenGroupSymbols++;
|
||||||
@ -110,19 +120,26 @@ public class TextHighlighter implements TextProcessor<TextHighlighter.Result> {
|
|||||||
text1.append(text.charAt(i));
|
text1.append(text.charAt(i));
|
||||||
break;
|
break;
|
||||||
case operator:
|
case operator:
|
||||||
text1.append(mathType.getMatch());
|
text1.append(match);
|
||||||
if (mathType.getMatch().length() > 1) {
|
if (match.length() > 1) {
|
||||||
i += mathType.getMatch().length() - 1;
|
i += match.length() - 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case function:
|
case function:
|
||||||
i = processHighlightedText(text1, i, mathType.getMatch(), "i");
|
i = processHighlightedText(text1, i, match, "i", null);
|
||||||
break;
|
break;
|
||||||
case constant:
|
case constant:
|
||||||
i = processHighlightedText(text1, i, mathType.getMatch(), "b");
|
i = processHighlightedText(text1, i, match, "b", null);
|
||||||
|
break;
|
||||||
|
case numeral_base:
|
||||||
|
i = processHighlightedText(text1, i, match, "font", nbFontAttributes);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
text1.append(text.charAt(i));
|
if (mathType.getMathType() == MathType.text || match.length() <= 1) {
|
||||||
|
text1.append(text.charAt(i));
|
||||||
|
} else {
|
||||||
|
i += match.length() - 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,10 +167,19 @@ public class TextHighlighter implements TextProcessor<TextHighlighter.Result> {
|
|||||||
return new Result(result, numberOffset);
|
return new Result(result, numberOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int processHighlightedText(@NotNull StringBuilder result, int i, @NotNull String functionName, @NotNull String tag) {
|
private int processHighlightedText(@NotNull StringBuilder result, int i, @NotNull String match, @NotNull String tag, @Nullable Map<String, String> tagAttributes) {
|
||||||
result.append("<").append(tag).append(">").append(functionName).append("</").append(tag).append(">");
|
result.append("<").append(tag);
|
||||||
if (functionName.length() > 1) {
|
|
||||||
return i + functionName.length() - 1;
|
if ( tagAttributes != null ) {
|
||||||
|
for (Map.Entry<String, String> entry : tagAttributes.entrySet()) {
|
||||||
|
// attr1="attr1_value" attr2="attr2_value"
|
||||||
|
result.append(" ").append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(">").append(match).append("</").append(tag).append(">");
|
||||||
|
if (match.length() > 1) {
|
||||||
|
return i + match.length() - 1;
|
||||||
} else {
|
} else {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -6,121 +6,21 @@
|
|||||||
|
|
||||||
package org.solovyev.android.calculator.jscl;
|
package org.solovyev.android.calculator.jscl;
|
||||||
|
|
||||||
import jscl.text.msg.Messages;
|
import jscl.math.Generic;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.solovyev.android.calculator.math.MathType;
|
|
||||||
import org.solovyev.android.calculator.model.CalculatorEngine;
|
|
||||||
import org.solovyev.android.calculator.model.CalculatorParseException;
|
import org.solovyev.android.calculator.model.CalculatorParseException;
|
||||||
import org.solovyev.android.calculator.model.TextProcessor;
|
import org.solovyev.android.calculator.model.TextProcessor;
|
||||||
import org.solovyev.common.utils.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
* Date: 10/6/11
|
* Date: 10/6/11
|
||||||
* Time: 9:48 PM
|
* Time: 9:48 PM
|
||||||
*/
|
*/
|
||||||
class FromJsclNumericTextProcessor implements TextProcessor<String> {
|
class FromJsclNumericTextProcessor implements TextProcessor<String, Generic> {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public String process(@NotNull String result) throws CalculatorParseException {
|
public String process(@NotNull Generic numeric) throws CalculatorParseException {
|
||||||
try {
|
return numeric.toString().replace("*", "");
|
||||||
final Double doubleValue = Double.valueOf(result);
|
|
||||||
|
|
||||||
if (doubleValue.isInfinite()) {
|
|
||||||
result = MathType.INFINITY;
|
|
||||||
} else {
|
|
||||||
result = CalculatorEngine.instance.format(doubleValue);
|
|
||||||
}
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
result = result.replace(MathType.INFINITY_JSCL, MathType.INFINITY);
|
|
||||||
try {
|
|
||||||
result = createResultForComplexNumber(result.replace(MathType.IMAGINARY_NUMBER_JSCL, MathType.IMAGINARY_NUMBER));
|
|
||||||
} catch (NumberFormatException e1) {
|
|
||||||
// throw original one
|
|
||||||
throw new CalculatorParseException(new jscl.text.ParseException(Messages.msg_8, 0, result, result));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String format(@NotNull String value) throws java.lang.NumberFormatException {
|
|
||||||
return CalculatorEngine.instance.format(Double.valueOf(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String createResultForComplexNumber(@NotNull final String s) {
|
|
||||||
final Complex complex = new Complex();
|
|
||||||
|
|
||||||
final StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
// may be it's just complex number
|
|
||||||
int signIndex = tryRealPart(s, complex, result, "+");
|
|
||||||
if (signIndex < 0) {
|
|
||||||
signIndex = tryRealPart(s, complex, result, "-");
|
|
||||||
}
|
|
||||||
|
|
||||||
int multiplyIndex = s.indexOf("*");
|
|
||||||
if (multiplyIndex >= 0) {
|
|
||||||
complex.setImaginary(format(s.substring(signIndex >= 0 ? signIndex + 1 : 0, multiplyIndex)));
|
|
||||||
result.append(complex.getImaginary());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
result.append(MathType.IMAGINARY_NUMBER);
|
|
||||||
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int tryRealPart(@NotNull String s,
|
|
||||||
@NotNull Complex complex,
|
|
||||||
@NotNull StringBuilder result,
|
|
||||||
@NotNull String sign) {
|
|
||||||
int index = s.lastIndexOf(sign);
|
|
||||||
if (index >= 0) {
|
|
||||||
final String substring = s.substring(0, index);
|
|
||||||
|
|
||||||
if (!StringUtils.isEmpty(substring)) {
|
|
||||||
try {
|
|
||||||
complex.setReal(format(substring));
|
|
||||||
result.append(complex.getReal());
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
// do nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.append(sign);
|
|
||||||
}
|
|
||||||
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Complex {
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private String real;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private String imaginary;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getReal() {
|
|
||||||
return real;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setReal(@Nullable String real) {
|
|
||||||
this.real = real;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getImaginary() {
|
|
||||||
return imaginary;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setImaginary(@Nullable String imaginary) {
|
|
||||||
this.imaginary = imaginary;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -60,14 +60,14 @@ public enum JsclOperation {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final TextProcessor<String> fromProcessor;
|
private final TextProcessor<String, Generic> fromProcessor;
|
||||||
|
|
||||||
JsclOperation(@NotNull TextProcessor<String> fromProcessor) {
|
JsclOperation(@NotNull TextProcessor<String, Generic> fromProcessor) {
|
||||||
this.fromProcessor = fromProcessor;
|
this.fromProcessor = fromProcessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public TextProcessor<String> getFromProcessor() {
|
public TextProcessor<String, Generic> getFromProcessor() {
|
||||||
return fromProcessor;
|
return fromProcessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.solovyev.android.calculator.math;
|
package org.solovyev.android.calculator.math;
|
||||||
|
|
||||||
|
import jscl.JsclMathEngine;
|
||||||
import jscl.NumeralBase;
|
import jscl.NumeralBase;
|
||||||
import jscl.math.function.Constant;
|
import jscl.math.function.Constant;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@ -336,6 +337,14 @@ public enum MathType {
|
|||||||
for (MathType mathType : getMathTypesByPriority()) {
|
for (MathType mathType : getMathTypesByPriority()) {
|
||||||
final String s = CollectionsUtils.find(mathType.getTokens(), startsWithFinder);
|
final String s = CollectionsUtils.find(mathType.getTokens(), startsWithFinder);
|
||||||
if (s != null) {
|
if (s != null) {
|
||||||
|
if ( s.length() == 1 ) {
|
||||||
|
if (JsclMathEngine.instance.getNumeralBase() == NumeralBase.hex) {
|
||||||
|
final Character ch = s.charAt(0);
|
||||||
|
if ( NumeralBase.hex.getAcceptableCharacters().contains(ch) ) {
|
||||||
|
return new Result(MathType.digit, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return new Result(mathType, s);
|
return new Result(mathType, s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,7 @@ import org.solovyev.common.msg.MessageRegistry;
|
|||||||
import org.solovyev.common.utils.MutableObject;
|
import org.solovyev.common.utils.MutableObject;
|
||||||
import org.solovyev.common.utils.StringUtils;
|
import org.solovyev.common.utils.StringUtils;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
import java.text.DecimalFormatSymbols;
|
import java.text.DecimalFormatSymbols;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@ -38,7 +35,6 @@ public enum CalculatorEngine {
|
|||||||
instance;
|
instance;
|
||||||
|
|
||||||
public static final String GROUPING_SEPARATOR_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_calc_grouping_separator";
|
public static final String GROUPING_SEPARATOR_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_calc_grouping_separator";
|
||||||
private static final String GROUPING_SEPARATOR_DEFAULT = " ";
|
|
||||||
|
|
||||||
public static final String ROUND_RESULT_P_KEY = "org.solovyev.android.calculator.CalculatorModel_round_result";
|
public static final String ROUND_RESULT_P_KEY = "org.solovyev.android.calculator.CalculatorModel_round_result";
|
||||||
public static final boolean ROUND_RESULT_DEFAULT = true;
|
public static final boolean ROUND_RESULT_DEFAULT = true;
|
||||||
@ -57,15 +53,11 @@ public enum CalculatorEngine {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private final Object lock = new Object();
|
private final Object lock = new Object();
|
||||||
|
|
||||||
private boolean roundResult = true;
|
|
||||||
|
|
||||||
private int precision = 5;
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private MathEngine engine = JsclMathEngine.instance;
|
private MathEngine engine = JsclMathEngine.instance;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public final TextProcessor<PreparedExpression> preprocessor = new ToJsclTextProcessor();
|
public final TextProcessor<PreparedExpression, String> preprocessor = new ToJsclTextProcessor();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final AndroidVarsRegistry varsRegister = new AndroidVarsRegistryImpl(engine.getConstantsRegistry());
|
private final AndroidVarsRegistry varsRegister = new AndroidVarsRegistryImpl(engine.getConstantsRegistry());
|
||||||
@ -78,46 +70,20 @@ public enum CalculatorEngine {
|
|||||||
|
|
||||||
private final AndroidMathRegistry<Operator> postfixFunctionsRegistry = new AndroidPostfixFunctionsRegistry(engine.getPostfixFunctionsRegistry());
|
private final AndroidMathRegistry<Operator> postfixFunctionsRegistry = new AndroidPostfixFunctionsRegistry(engine.getPostfixFunctionsRegistry());
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols(Locale.getDefault());
|
|
||||||
|
|
||||||
{
|
|
||||||
decimalGroupSymbols.setDecimalSeparator('.');
|
|
||||||
decimalGroupSymbols.setGroupingSeparator(GROUPING_SEPARATOR_DEFAULT.charAt(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean useGroupingSeparator = true;
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private ThreadKiller threadKiller = new AndroidThreadKiller();
|
private ThreadKiller threadKiller = new AndroidThreadKiller();
|
||||||
|
|
||||||
// calculation thread timeout in milliseconds, after timeout thread would be interrupted
|
// calculation thread timeout in milliseconds, after timeout thread would be interrupted
|
||||||
private int timeout = DEFAULT_TIMEOUT;
|
private int timeout = DEFAULT_TIMEOUT;
|
||||||
|
|
||||||
@NotNull
|
CalculatorEngine() {
|
||||||
public String format(@NotNull Double value) {
|
this.engine.setRoundResult(true);
|
||||||
return format(value, true);
|
this.engine.setUseGroupingSeparator(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public String format(@NotNull Double value, boolean round) {
|
public String format(@NotNull Double value, boolean round) {
|
||||||
if (!value.isInfinite() && !value.isNaN()) {
|
return getEngine().format(value, round);
|
||||||
final DecimalFormat df = new DecimalFormat();
|
|
||||||
df.setDecimalFormatSymbols(decimalGroupSymbols);
|
|
||||||
df.setGroupingUsed(useGroupingSeparator);
|
|
||||||
if (round) {
|
|
||||||
if (isRoundResult()) {
|
|
||||||
df.setMaximumFractionDigits(instance.getPrecision());
|
|
||||||
return df.format(new BigDecimal(value).setScale(instance.getPrecision(), BigDecimal.ROUND_HALF_UP).doubleValue());
|
|
||||||
} else {
|
|
||||||
return String.valueOf(value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return df.format(value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return String.valueOf(value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Result {
|
public static class Result {
|
||||||
@ -267,24 +233,16 @@ public enum CalculatorEngine {
|
|||||||
|
|
||||||
final Generic genericResult = calculationResult.getObject();
|
final Generic genericResult = calculationResult.getObject();
|
||||||
|
|
||||||
return new Result(operation.getFromProcessor().process(genericResult.toString()), operation, genericResult);
|
return new Result(operation.getFromProcessor().process(genericResult), operation, genericResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getPrecision() {
|
|
||||||
return precision;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPrecision(int precision) {
|
public void setPrecision(int precision) {
|
||||||
this.precision = precision;
|
this.getEngine().setPrecision(precision);
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isRoundResult() {
|
|
||||||
return roundResult;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRoundResult(boolean roundResult) {
|
public void setRoundResult(boolean roundResult) {
|
||||||
this.roundResult = roundResult;
|
this.getEngine().setRoundResult(roundResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(@Nullable Context context, @Nullable SharedPreferences preferences) {
|
public void init(@Nullable Context context, @Nullable SharedPreferences preferences) {
|
||||||
@ -300,15 +258,15 @@ public enum CalculatorEngine {
|
|||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
this.setPrecision(integerNumberMapper.parseValue(preferences.getString(RESULT_PRECISION_P_KEY, RESULT_PRECISION_DEFAULT)));
|
this.setPrecision(integerNumberMapper.parseValue(preferences.getString(RESULT_PRECISION_P_KEY, RESULT_PRECISION_DEFAULT)));
|
||||||
this.setRoundResult(preferences.getBoolean(ROUND_RESULT_P_KEY, ROUND_RESULT_DEFAULT));
|
this.setRoundResult(preferences.getBoolean(ROUND_RESULT_P_KEY, ROUND_RESULT_DEFAULT));
|
||||||
this.setAngleUnits(AngleUnit.valueOf(preferences.getString(ANGLE_UNITS_P_KEY, ANGLE_UNITS_DEFAULT)));
|
this.setAngleUnits(getAngleUnitsFromPrefs(preferences));
|
||||||
this.setNumeralBase(NumeralBase.valueOf(preferences.getString(NUMERAL_BASES_P_KEY, NUMERAL_BASES_DEFAULT)));
|
this.setNumeralBase(getNumeralBaseFromPrefs(preferences));
|
||||||
|
|
||||||
final String groupingSeparator = preferences.getString(GROUPING_SEPARATOR_P_KEY, GROUPING_SEPARATOR_DEFAULT);
|
final String groupingSeparator = preferences.getString(GROUPING_SEPARATOR_P_KEY, JsclMathEngine.GROUPING_SEPARATOR_DEFAULT);
|
||||||
if (StringUtils.isEmpty(groupingSeparator)) {
|
if (StringUtils.isEmpty(groupingSeparator)) {
|
||||||
this.useGroupingSeparator = false;
|
this.getEngine().setUseGroupingSeparator(false);
|
||||||
} else {
|
} else {
|
||||||
this.useGroupingSeparator = true;
|
this.getEngine().setUseGroupingSeparator(true);
|
||||||
this.decimalGroupSymbols.setGroupingSeparator(groupingSeparator.charAt(0));
|
this.getEngine().setGroupingSeparator(groupingSeparator.charAt(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,10 +274,20 @@ public enum CalculatorEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public NumeralBase getNumeralBaseFromPrefs(@NotNull SharedPreferences preferences) {
|
||||||
|
return NumeralBase.valueOf(preferences.getString(NUMERAL_BASES_P_KEY, NUMERAL_BASES_DEFAULT));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public AngleUnit getAngleUnitsFromPrefs(@NotNull SharedPreferences preferences) {
|
||||||
|
return AngleUnit.valueOf(preferences.getString(ANGLE_UNITS_P_KEY, ANGLE_UNITS_DEFAULT));
|
||||||
|
}
|
||||||
|
|
||||||
//for tests only
|
//for tests only
|
||||||
void setDecimalGroupSymbols(@NotNull DecimalFormatSymbols decimalGroupSymbols) {
|
void setDecimalGroupSymbols(@NotNull DecimalFormatSymbols decimalGroupSymbols) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
this.decimalGroupSymbols = decimalGroupSymbols;
|
this.getEngine().setDecimalGroupSymbols(decimalGroupSymbols);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator.model;
|
||||||
|
|
||||||
|
import jscl.math.Generic;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -13,13 +14,13 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
* Date: 10/18/11
|
* Date: 10/18/11
|
||||||
* Time: 10:39 PM
|
* Time: 10:39 PM
|
||||||
*/
|
*/
|
||||||
public enum DummyTextProcessor implements TextProcessor<String> {
|
public enum DummyTextProcessor implements TextProcessor<String, Generic> {
|
||||||
|
|
||||||
instance;
|
instance;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public String process(@NotNull String s) throws CalculatorParseException {
|
public String process(@NotNull Generic s) throws CalculatorParseException {
|
||||||
return s;
|
return s.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator.model;
|
||||||
|
|
||||||
import jscl.MathContext;
|
import jscl.MathContext;
|
||||||
|
import jscl.math.Generic;
|
||||||
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.MathType;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
@ -13,7 +14,7 @@ import java.util.List;
|
|||||||
* Date: 10/20/11
|
* Date: 10/20/11
|
||||||
* Time: 2:59 PM
|
* Time: 2:59 PM
|
||||||
*/
|
*/
|
||||||
public class FromJsclSimplifyTextProcessor implements TextProcessor<String> {
|
public class FromJsclSimplifyTextProcessor implements TextProcessor<String, Generic> {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final MathContext mathContext;
|
private final MathContext mathContext;
|
||||||
@ -24,7 +25,12 @@ public class FromJsclSimplifyTextProcessor implements TextProcessor<String> {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public String process(@NotNull String s) throws CalculatorParseException {
|
public String process(@NotNull Generic from) throws CalculatorParseException {
|
||||||
|
final String s = from.toString();
|
||||||
|
return process(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String process(@NotNull String s) {
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
final NumberBuilder numberBuilder = new NumberBuilder(true, mathContext.getNumeralBase());
|
final NumberBuilder numberBuilder = new NumberBuilder(true, mathContext.getNumeralBase());
|
||||||
|
@ -49,7 +49,7 @@ public class NumberBuilder {
|
|||||||
|
|
||||||
final MathType.Result possibleResult;
|
final MathType.Result possibleResult;
|
||||||
if ((CollectionsUtils.contains(mathTypeResult.getMathType(), MathType.digit, MathType.numeral_base, MathType.dot, MathType.grouping_separator, MathType.power_10) ||
|
if ((CollectionsUtils.contains(mathTypeResult.getMathType(), MathType.digit, MathType.numeral_base, MathType.dot, MathType.grouping_separator, MathType.power_10) ||
|
||||||
isSignAfterE(mathTypeResult)) && numeralBaseCheck(mathTypeResult)) {
|
isSignAfterE(mathTypeResult)) && numeralBaseCheck(mathTypeResult) && numeralBaseInTheStart(mathTypeResult.getMathType())) {
|
||||||
if (numberBuilder == null) {
|
if (numberBuilder == null) {
|
||||||
numberBuilder = new StringBuilder();
|
numberBuilder = new StringBuilder();
|
||||||
}
|
}
|
||||||
@ -68,6 +68,10 @@ public class NumberBuilder {
|
|||||||
return possibleResult == null ? mathTypeResult : possibleResult;
|
return possibleResult == null ? mathTypeResult : possibleResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean numeralBaseInTheStart(@NotNull MathType mathType) {
|
||||||
|
return mathType != MathType.numeral_base || numberBuilder == null;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean numeralBaseCheck( @NotNull MathType.Result mathType ) {
|
private boolean numeralBaseCheck( @NotNull MathType.Result mathType ) {
|
||||||
if ( mathType.getMathType() == MathType.digit ) {
|
if ( mathType.getMathType() == MathType.digit ) {
|
||||||
final Character ch = mathType.getMatch().charAt(0);
|
final Character ch = mathType.getMatch().charAt(0);
|
||||||
|
@ -7,8 +7,8 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
* Date: 9/26/11
|
* Date: 9/26/11
|
||||||
* Time: 12:12 PM
|
* Time: 12:12 PM
|
||||||
*/
|
*/
|
||||||
public interface TextProcessor<T extends CharSequence> {
|
public interface TextProcessor<TO extends CharSequence, FROM> {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
T process(@NotNull String s) throws CalculatorParseException;
|
TO process(@NotNull FROM from) throws CalculatorParseException;
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import org.solovyev.common.utils.CollectionsUtils;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
class ToJsclTextProcessor implements TextProcessor<PreparedExpression> {
|
class ToJsclTextProcessor implements TextProcessor<PreparedExpression, String> {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static final Integer MAX_DEPTH = 20;
|
private static final Integer MAX_DEPTH = 20;
|
||||||
|
@ -120,7 +120,18 @@ public class DirectionDragButton extends DragButton {
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Point2d getTextPosition(@NotNull Paint paint, @NotNull Paint basePaint, @NotNull CharSequence text, CharSequence baseText, int w, int h) {
|
public Point2d getTextPosition(@NotNull Paint paint, @NotNull Paint basePaint, @NotNull CharSequence text, CharSequence baseText, int w, int h) {
|
||||||
throw new UnsupportedOperationException("Not implemented yet!");
|
final Point2d result = new Point2d();
|
||||||
|
|
||||||
|
float width = paint.measureText(" ");
|
||||||
|
result.setX(width);
|
||||||
|
|
||||||
|
float selfHeight = paint.ascent() + paint.descent();
|
||||||
|
|
||||||
|
basePaint.measureText(StringUtils.getNotEmpty(baseText, "|"));
|
||||||
|
|
||||||
|
result.setY(h / 2 - selfHeight / 2);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}/*,
|
}/*,
|
||||||
right(DragDirection.right) {
|
right(DragDirection.right) {
|
||||||
@ -163,9 +174,9 @@ public class DirectionDragButton extends DragButton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static GuiDragDirection valueOf ( @NotNull DragDirection dragDirection ) {
|
public static GuiDragDirection valueOf(@NotNull DragDirection dragDirection) {
|
||||||
for (GuiDragDirection guiDragDirection : values()) {
|
for (GuiDragDirection guiDragDirection : values()) {
|
||||||
if ( guiDragDirection.dragDirection == dragDirection ) {
|
if (guiDragDirection.dragDirection == dragDirection) {
|
||||||
return guiDragDirection;
|
return guiDragDirection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -204,7 +215,7 @@ public class DirectionDragButton extends DragButton {
|
|||||||
default:
|
default:
|
||||||
// try drag direction text
|
// try drag direction text
|
||||||
for (GuiDragDirection guiDragDirection : GuiDragDirection.values()) {
|
for (GuiDragDirection guiDragDirection : GuiDragDirection.values()) {
|
||||||
if ( guiDragDirection.getAttributeId() == attr ) {
|
if (guiDragDirection.getAttributeId() == attr) {
|
||||||
this.directionTextDataMap.put(guiDragDirection, new DirectionTextData(guiDragDirection, attrValue));
|
this.directionTextDataMap.put(guiDragDirection, new DirectionTextData(guiDragDirection, attrValue));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,7 @@ public class SimpleOnDragListener implements OnDragListener, DragPreferencesChan
|
|||||||
DragDirection direction = null;
|
DragDirection direction = null;
|
||||||
for (Map.Entry<DragDirection, DragPreference> directionEntry : distancePreferences.getDirectionPreferences().entrySet()) {
|
for (Map.Entry<DragDirection, DragPreference> directionEntry : distancePreferences.getDirectionPreferences().entrySet()) {
|
||||||
|
|
||||||
|
Log.d(String.valueOf(dragButton.getId()), "Drag direction: " + directionEntry.getKey());
|
||||||
Log.d(String.valueOf(dragButton.getId()), "Trying direction interval: " + directionEntry.getValue().getInterval());
|
Log.d(String.valueOf(dragButton.getId()), "Trying direction interval: " + directionEntry.getValue().getInterval());
|
||||||
|
|
||||||
if (isInInterval(directionEntry.getValue().getInterval(), distance)) {
|
if (isInInterval(directionEntry.getValue().getInterval(), distance)) {
|
||||||
@ -180,7 +181,7 @@ public class SimpleOnDragListener implements OnDragListener, DragPreferencesChan
|
|||||||
|
|
||||||
transformInterval(preferenceType, dragDirection, intervalPref);
|
transformInterval(preferenceType, dragDirection, intervalPref);
|
||||||
|
|
||||||
Log.d(SimpleOnDragListener.class.getName(), "Preference loaded. Id: " + preferenceId + ", value: " + intervalPref.toString());
|
Log.d(SimpleOnDragListener.class.getName(), "Preference loaded for " + dragDirection +". Id: " + preferenceId + ", value: " + intervalPref.toString());
|
||||||
|
|
||||||
final DragPreference directionPreference = new DragPreference(dragDirection, intervalPref);
|
final DragPreference directionPreference = new DragPreference(dragDirection, intervalPref);
|
||||||
|
|
||||||
@ -207,9 +208,12 @@ public class SimpleOnDragListener implements OnDragListener, DragPreferencesChan
|
|||||||
if (dragDirection == DragDirection.up) {
|
if (dragDirection == DragDirection.up) {
|
||||||
interval.setLeftBorder(180f - rightBorder);
|
interval.setLeftBorder(180f - rightBorder);
|
||||||
interval.setRightBorder(180f - leftBorder);
|
interval.setRightBorder(180f - leftBorder);
|
||||||
} else if (dragDirection == DragDirection.left || dragDirection == DragDirection.right) {
|
} else if (dragDirection == DragDirection.left ) {
|
||||||
interval.setLeftBorder(90f - rightBorder / 2);
|
interval.setLeftBorder(90f - rightBorder / 2);
|
||||||
interval.setRightBorder(90f + leftBorder / 2);
|
interval.setRightBorder(90f + rightBorder / 2);
|
||||||
|
} else if ( dragDirection == DragDirection.right ) {
|
||||||
|
interval.setLeftBorder(180f + 90f - rightBorder / 2);
|
||||||
|
interval.setRightBorder(180f + 90f + rightBorder / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +48,11 @@ public class TextHighlighterTest {
|
|||||||
textHighlighter = new TextHighlighter(0, false, JsclMathEngine.instance);
|
textHighlighter = new TextHighlighter(0, false, JsclMathEngine.instance);
|
||||||
Assert.assertEquals("0.1E3", textHighlighter.process("0.1E3").toString());
|
Assert.assertEquals("0.1E3", textHighlighter.process("0.1E3").toString());
|
||||||
Assert.assertEquals("1E3", textHighlighter.process("1E3").toString());
|
Assert.assertEquals("1E3", textHighlighter.process("1E3").toString());
|
||||||
|
Assert.assertEquals("2<font color=\"#008000\">0x:</font>", textHighlighter.process("20x:").toString());
|
||||||
|
Assert.assertEquals("20x", textHighlighter.process("20x").toString());
|
||||||
|
Assert.assertEquals("22x", textHighlighter.process("22x").toString());
|
||||||
|
Assert.assertEquals("20t", textHighlighter.process("20t").toString());
|
||||||
|
Assert.assertEquals("20k", textHighlighter.process("20k").toString());
|
||||||
Assert.assertEquals("1 000 000E3", textHighlighter.process("1000000E3").toString());
|
Assert.assertEquals("1 000 000E3", textHighlighter.process("1000000E3").toString());
|
||||||
Assert.assertEquals("-1 000 000E3", textHighlighter.process("-1000000E3").toString());
|
Assert.assertEquals("-1 000 000E3", textHighlighter.process("-1000000E3").toString());
|
||||||
Assert.assertEquals("-1 000 000E-3", textHighlighter.process("-1000000E-3").toString());
|
Assert.assertEquals("-1 000 000E-3", textHighlighter.process("-1000000E-3").toString());
|
||||||
|
@ -6,8 +6,12 @@
|
|||||||
|
|
||||||
package org.solovyev.android.calculator.jscl;
|
package org.solovyev.android.calculator.jscl;
|
||||||
|
|
||||||
|
import jscl.math.Expression;
|
||||||
|
import jscl.math.Generic;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.solovyev.android.calculator.model.CalculatorEngine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
@ -16,13 +20,20 @@ import org.junit.Test;
|
|||||||
*/
|
*/
|
||||||
public class FromJsclNumericTextProcessorTest {
|
public class FromJsclNumericTextProcessorTest {
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setUp() throws Exception {
|
||||||
|
CalculatorEngine.instance.init(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateResultForComplexNumber() throws Exception {
|
public void testCreateResultForComplexNumber() throws Exception {
|
||||||
final FromJsclNumericTextProcessor cm = new FromJsclNumericTextProcessor();
|
final FromJsclNumericTextProcessor cm = new FromJsclNumericTextProcessor();
|
||||||
|
|
||||||
Assert.assertEquals("1.22133+23 123i", cm.createResultForComplexNumber("1.22133232+23123*i"));
|
Assert.assertEquals("1.22133+23 123i", cm.process(Expression.valueOf("1.22133232+23123*i").numeric()));
|
||||||
Assert.assertEquals("1.22133+1.2i", cm.createResultForComplexNumber("1.22133232+1.2*i"));
|
Assert.assertEquals("1.22133+1.2i", cm.process(Expression.valueOf("1.22133232+1.2*i").numeric()));
|
||||||
Assert.assertEquals("1.22i", cm.createResultForComplexNumber("1.22*i"));
|
Assert.assertEquals("1.22i", cm.process(Expression.valueOf("1.22*i").numeric()));
|
||||||
Assert.assertEquals("i", cm.createResultForComplexNumber("i"));
|
Assert.assertEquals("i", cm.process(Expression.valueOf("i").numeric()));
|
||||||
|
Generic numeric = Expression.valueOf("e^(π*i)+1").numeric();
|
||||||
|
junit.framework.Assert.assertEquals("0i", cm.process(numeric));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,8 +132,8 @@ public class CalculatorEngineTest {
|
|||||||
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "(2.0+2.0)!").getResult());
|
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "(2.0+2.0)!").getResult());
|
||||||
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "4.0!").getResult());
|
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "4.0!").getResult());
|
||||||
junit.framework.Assert.assertEquals("720", cm.evaluate(JsclOperation.numeric, "3!!").getResult());
|
junit.framework.Assert.assertEquals("720", cm.evaluate(JsclOperation.numeric, "3!!").getResult());
|
||||||
junit.framework.Assert.assertEquals("36.0", Expression.valueOf("3!^2").numeric().toString());
|
junit.framework.Assert.assertEquals("36", Expression.valueOf("3!^2").numeric().toString());
|
||||||
junit.framework.Assert.assertEquals("3.0", Expression.valueOf("cubic(27)").numeric().toString());
|
junit.framework.Assert.assertEquals("3", Expression.valueOf("cubic(27)").numeric().toString());
|
||||||
try {
|
try {
|
||||||
junit.framework.Assert.assertEquals("√(-1)!", cm.evaluate(JsclOperation.numeric, "i!").getResult());
|
junit.framework.Assert.assertEquals("√(-1)!", cm.evaluate(JsclOperation.numeric, "i!").getResult());
|
||||||
fail();
|
fail();
|
||||||
@ -369,8 +369,12 @@ public class CalculatorEngineTest {
|
|||||||
} catch (CalculatorEvalException e) {
|
} catch (CalculatorEvalException e) {
|
||||||
// ok
|
// ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cm.getEngine().setNumeralBase(NumeralBase.hex);
|
||||||
|
Assert.assertEquals("637b", cm.evaluate(JsclOperation.numeric, "56ce+cad").getResult());
|
||||||
} finally {
|
} finally {
|
||||||
cm.setNumeralBase(defaultNumeralBase);
|
cm.setNumeralBase(defaultNumeralBase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,11 @@ public class FromJsclSimplifyTextProcessorTest {
|
|||||||
|
|
||||||
Assert.assertEquals("tlog(3)", tp.process("t*log(3)"));
|
Assert.assertEquals("tlog(3)", tp.process("t*log(3)"));
|
||||||
Assert.assertEquals("t√(3)", tp.process("t*√(3)"));
|
Assert.assertEquals("t√(3)", tp.process("t*√(3)"));
|
||||||
|
Assert.assertEquals("20x", tp.process("20*x"));
|
||||||
|
Assert.assertEquals("20x", tp.process("20x"));
|
||||||
|
Assert.assertEquals("2×0x3", tp.process("2*0x3"));
|
||||||
|
Assert.assertEquals("2×0x:3", tp.process("2*0x:3"));
|
||||||
|
Assert.assertEquals("0x:3 000 000", tp.process("0x:3 000 000.00000000000001"));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator.model;
|
||||||
|
|
||||||
|
import jscl.JsclMathEngine;
|
||||||
|
import jscl.NumeralBase;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -120,4 +122,20 @@ public class ToJsclTextProcessorTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testPostfixFunction() throws Exception {
|
public void testPostfixFunction() throws Exception {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNumeralBases() throws Exception {
|
||||||
|
final ToJsclTextProcessor processor = new ToJsclTextProcessor();
|
||||||
|
|
||||||
|
final NumeralBase defaultNumeralBase = JsclMathEngine.instance.getNumeralBase();
|
||||||
|
try{
|
||||||
|
JsclMathEngine.instance.setNumeralBase(NumeralBase.bin);
|
||||||
|
Assert.assertEquals("101", JsclMathEngine.instance.evaluate("10+11"));
|
||||||
|
|
||||||
|
JsclMathEngine.instance.setNumeralBase(NumeralBase.hex);
|
||||||
|
Assert.assertEquals("56ce+cad", processor.process("56ce+cad").getExpression());
|
||||||
|
} finally {
|
||||||
|
JsclMathEngine.instance.setNumeralBase(defaultNumeralBase);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user