changes, changes, changes

This commit is contained in:
serso 2011-10-13 01:46:44 +04:00
parent 1e2edc2e79
commit c6c5350602
24 changed files with 375 additions and 192 deletions

View File

@ -55,7 +55,7 @@
<include layout="@layout/calc_eight_digit_button"/> <include layout="@layout/calc_eight_digit_button"/>
<include layout="@layout/calc_nine_digit_button"/> <include layout="@layout/calc_nine_digit_button"/>
<include layout="@layout/calc_plus_button"/> <include layout="@layout/calc_plus_button"/>
<include layout="@layout/calc_paste_button"/> <include layout="@layout/calc_copy_button"/>
</LinearLayout> </LinearLayout>
@ -65,7 +65,7 @@
<include layout="@layout/calc_zero_digit_button"/> <include layout="@layout/calc_zero_digit_button"/>
<include layout="@layout/calc_square_brackets_button"/> <include layout="@layout/calc_square_brackets_button"/>
<include layout="@layout/calc_subtraction_button"/> <include layout="@layout/calc_subtraction_button"/>
<include layout="@layout/calc_copy_button"/> <include layout="@layout/calc_paste_button"/>
</LinearLayout> </LinearLayout>

View File

@ -6,9 +6,9 @@
~ or visit http://se.solovyev.org ~ or visit http://se.solovyev.org
--> -->
<org.solovyev.android.view.widgets.DirectionDragButton xmlns:a="http://schemas.android.com/apk/res/android" <org.solovyev.android.view.widgets.ColorButton xmlns:a="http://schemas.android.com/apk/res/android"
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/clearButton" a:id="@+id/clearButton"
a:text="@string/c_clear" a:drawableTop="@drawable/ic_delete"
style="@style/control_button_style" style="@style/control_image_button_style"
a:onClick="clearButtonClickHandler"/> a:onClick="clearButtonClickHandler"/>

View File

@ -6,10 +6,9 @@
~ or visit http://se.solovyev.org ~ or visit http://se.solovyev.org
--> -->
<ImageButton xmlns:a="http://schemas.android.com/apk/res/android" <org.solovyev.android.view.widgets.ColorButton xmlns:a="http://schemas.android.com/apk/res/android"
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/pasteButton" a:id="@+id/pasteButton"
a:src="@drawable/copy" a:drawableTop="@drawable/copy"
style="@style/control_button_style" style="@style/control_image_button_style"
a:padding="6dp"
a:onClick="copyButtonClickHandler"/> a:onClick="copyButtonClickHandler"/>

View File

@ -10,6 +10,5 @@
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/pasteButton" a:id="@+id/pasteButton"
a:src="@drawable/heart" a:src="@drawable/heart"
style="@style/control_button_style" style="@style/control_image_button_style"
a:padding="6dp"
a:onClick="donateButtonClickHandler"/> a:onClick="donateButtonClickHandler"/>

View File

@ -6,9 +6,9 @@
~ or visit http://se.solovyev.org ~ or visit http://se.solovyev.org
--> -->
<org.solovyev.android.view.widgets.DirectionDragButton xmlns:a="http://schemas.android.com/apk/res/android" <org.solovyev.android.view.widgets.ColorButton xmlns:a="http://schemas.android.com/apk/res/android"
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/eraseButton" a:id="@+id/eraseButton"
a:text="@string/c_erase" a:drawableTop="@drawable/sym_keyboard_delete"
style="@style/control_button_style" style="@style/control_image_button_style"
a:onClick="eraseButtonClickHandler"/> a:onClick="eraseButtonClickHandler"/>

View File

@ -6,10 +6,9 @@
~ or visit http://se.solovyev.org ~ or visit http://se.solovyev.org
--> -->
<ImageButton xmlns:a="http://schemas.android.com/apk/res/android" <org.solovyev.android.view.widgets.ColorButton xmlns:a="http://schemas.android.com/apk/res/android"
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/pasteButton" a:id="@+id/pasteButton"
a:src="@drawable/paste" a:drawableTop="@drawable/paste"
style="@style/control_button_style" style="@style/control_image_button_style"
a:padding="6dp"
a:onClick="pasteButtonClickHandler"/> a:onClick="pasteButtonClickHandler"/>

View File

@ -10,5 +10,6 @@
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/roundBracketsButton" a:text="()" a:id="@+id/roundBracketsButton" a:text="()"
calc:textUp="(" calc:textUp="("
calc:textDown=")" style="@style/digit_button_style" calc:textDown=")"
style="@style/digit_button_style"
a:onClick="digitButtonClickHandler"/> a:onClick="digitButtonClickHandler"/>

View File

@ -10,5 +10,6 @@
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/squareBracketsButton" a:text="[]" a:id="@+id/squareBracketsButton" a:text="[]"
calc:textUp="[" calc:textUp="["
calc:textDown="]" style="@style/digit_button_style" calc:textDown="]"
style="@style/digit_button_style"
a:onClick="digitButtonClickHandler"/> a:onClick="digitButtonClickHandler"/>

View File

@ -8,7 +8,7 @@
<org.solovyev.android.view.widgets.DirectionDragButton xmlns:a="http://schemas.android.com/apk/res/android" <org.solovyev.android.view.widgets.DirectionDragButton xmlns:a="http://schemas.android.com/apk/res/android"
a:id="@+id/varsButton" a:id="@+id/varsButton"
a:text="π,e,…" a:text="π,…"
a:textStyle="italic" a:textStyle="italic"
a:onClick="varsButtonClickHandler" a:onClick="varsButtonClickHandler"
style="@style/control_button_style"/> style="@style/control_button_style"/>

29
res/layout/vars.xml Normal file
View File

@ -0,0 +1,29 @@
<?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="vertical"
a:layout_width="match_parent"
a:layout_height="match_parent">
<ListView
a:layout_width="match_parent"
a:layout_height="match_parent"
a:layout_weight="1"
a:id="@android:id/list"/>
<Button
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:layout_gravity="center_horizontal"
a:text="@string/c_add"
a:paddingLeft="40dp"
a:paddingRight="40dp"
a:onClick="addVarButtonClickHandler"/>
</LinearLayout>

View File

@ -20,7 +20,7 @@
<!--ABOUT ACTIVITY--> <!--ABOUT ACTIVITY-->
<string name="c_copyright">Copyright (c) 2009-2011\n\n<b>Программа создана\nserso aka se.solovyev</b>\n\n <string name="c_copyright">Copyright (c) 2009-2011\n\n<b>Программа создана\nserso aka se.solovyev</b>\n\n
Эта программа бесплатна и открыта.\nИсходный код может быть найден на \n<a href="https://github.com/serso/android_calculator">http://github.com</a>\n\n Эта программа с открытыми исходным кодом:\nон может быть найден на \n<a href="https://github.com/serso/android_calculator">http://github.com</a>\n\n
За подробной информацией, пожалуйста,\nобращайтесь на почту\n<a href="mailto:se.solovyev@gmail.com">se.solovyev@gmail.com</a>\n За подробной информацией, пожалуйста,\nобращайтесь на почту\n<a href="mailto:se.solovyev@gmail.com">se.solovyev@gmail.com</a>\n
или посетите сайт \n<a href="http://se.solovyev.org">http://se.solovyev.org</a>\n\n или посетите сайт \n<a href="http://se.solovyev.org">http://se.solovyev.org</a>\n\n
Если вы хотите поддержать проект материально\nвы можете сделать это через \n<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;business=se%2esolovyev%40gmail%2ecom&amp;lc=RU&amp;item_name=Android%20Calculator&amp;currency_code=USD&amp;bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted">http://paypal.com</a> Если вы хотите поддержать проект материально\nвы можете сделать это через \n<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;business=se%2esolovyev%40gmail%2ecom&amp;lc=RU&amp;item_name=Android%20Calculator&amp;currency_code=USD&amp;bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted">http://paypal.com</a>
@ -55,9 +55,10 @@
<string name="c_sys.var.cannot.be.changed">Системная переменная не может быть изменена!</string> <string name="c_sys.var.cannot.be.changed">Системная переменная не может быть изменена!</string>
<string name="c_pi_description">Отношение длины окружности к диаметру</string> <string name="c_pi_description">Отношение длины окружности к диаметру</string>
<string name="c_e_description">Вещесвтенное число, такое что производная функции f(x) = e^x в точке x = 0 равно 1 <string name="c_e_description">Вещесвтенное число, такое что производная функции f(x) = e^x в точке x = 0 равно 1</string>
</string>
<string name="c_i_description">Мнимая единица, определённая как i^2 = 1</string> <string name="c_i_description">Мнимая единица, определённая как i^2 = 1</string>
<string name="c_nan_description">Не число</string>
<string name="c_infinity_description">Бесконечность</string>
<string name="c_calc_editor_hint">Введите новое выражение</string> <string name="c_calc_editor_hint">Введите новое выражение</string>
<string name="c_continue">Продолжить</string> <string name="c_continue">Продолжить</string>
<string name="c_press_to_copy">Нажмите для копирования</string> <string name="c_press_to_copy">Нажмите для копирования</string>

View File

@ -21,7 +21,7 @@
<!--ABOUT ACTIVITY--> <!--ABOUT ACTIVITY-->
<string name="c_copyright">Copyright (c) 2009-2011\n\n<b>Created by serso aka se.solovyev</b>\n\n <string name="c_copyright">Copyright (c) 2009-2011\n\n<b>Created by serso aka se.solovyev</b>\n\n
This program is free and open source.\nSource code can be found on\n<a href="https://github.com/serso/android_calculator">http://github.com</a>\n\n This program is open source:\nall source code can be found on\n<a href="https://github.com/serso/android_calculator">http://github.com</a>\n\n
For more information please\ncontact the author by email\n<a href="mailto:se.solovyev@gmail.com">se.solovyev@gmail.com</a> For more information please\ncontact the author by email\n<a href="mailto:se.solovyev@gmail.com">se.solovyev@gmail.com</a>
\nor visit\n<a href="http://se.solovyev.org">http://se.solovyev.org</a>\n\n \nor visit\n<a href="http://se.solovyev.org">http://se.solovyev.org</a>\n\n
If you want to support the project\nyou can donate money via\n<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;business=se%2esolovyev%40gmail%2ecom&amp;lc=RU&amp;item_name=Android%20Calculator&amp;currency_code=USD&amp;bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted">http://paypal.com</a> If you want to support the project\nyou can donate money via\n<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;business=se%2esolovyev%40gmail%2ecom&amp;lc=RU&amp;item_name=Android%20Calculator&amp;currency_code=USD&amp;bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted">http://paypal.com</a>
@ -29,8 +29,8 @@
<string name="c_undo">undo</string> <string name="c_undo">undo</string>
<string name="c_redo">redo</string> <string name="c_redo">redo</string>
<string name="c_clear">CE</string> <string name="c_clear">clear all</string>
<string name="c_erase">C</string> <string name="c_erase">clear</string>
<string name="c_paste">paste</string> <string name="c_paste">paste</string>
<string name="c_vars">vars</string> <string name="c_vars">vars</string>
@ -60,6 +60,9 @@
<string name="c_pi_description">Ratio of any circle\'s circumference to its diameter</string> <string name="c_pi_description">Ratio of any circle\'s circumference to its diameter</string>
<string name="c_e_description">Unique real number such that the value of the derivative (slope of the tangent line) of the function f(x) = e^x at the point x = 0 is equal to 1</string> <string name="c_e_description">Unique real number such that the value of the derivative (slope of the tangent line) of the function f(x) = e^x at the point x = 0 is equal to 1</string>
<string name="c_i_description">Imaginary unit, defined such that i^2 = 1</string> <string name="c_i_description">Imaginary unit, defined such that i^2 = 1</string>
<string name="c_nan_description">Not a number</string>
<string name="c_infinity_description">Infinity</string>
<string name="c_calc_editor_hint">Enter new expression</string> <string name="c_calc_editor_hint">Enter new expression</string>
<string name="c_press_to_copy">Press to copy</string> <string name="c_press_to_copy">Press to copy</string>
<string name="c_continue">Continue</string> <string name="c_continue">Continue</string>

View File

@ -12,6 +12,7 @@
<item name="android:layout_height">match_parent</item> <item name="android:layout_height">match_parent</item>
<item name="android:layout_weight">1</item> <item name="android:layout_weight">1</item>
<item name="android:focusable">true</item> <item name="android:focusable">true</item>
<item name="android:textSize">20dp</item>
<item name="android:background">@drawable/button</item> <item name="android:background">@drawable/button</item>
<item name="android:layout_marginLeft">1dp</item> <item name="android:layout_marginLeft">1dp</item>
</style> </style>
@ -21,9 +22,8 @@
</style> </style>
<style name="control_button_style" parent="button_style"/> <style name="control_button_style" parent="button_style"/>
<style name="control_image_button_style" parent="control_button_style">
<style name="button_small_style" parent="button_style"> <item name="android:padding">6dp</item>
<item name="android:textSize">30dp</item>
</style> </style>
<style name="editor_style"> <style name="editor_style">

View File

@ -13,7 +13,8 @@ import android.util.Log;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.widget.EditText; import android.widget.EditText;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.math.MathType; import org.solovyev.android.calculator.model.ParseException;
import org.solovyev.android.calculator.model.TextProcessor;
/** /**
* User: serso * User: serso
@ -24,10 +25,8 @@ public class CalculatorEditor extends EditText {
private boolean highlightText = true; private boolean highlightText = true;
private final static int BASE_COLOUR = Color.WHITE; @NotNull
private final static int BASE_COLOUR_RED_COMPONENT = Color.red(BASE_COLOUR); private final static TextProcessor textHighlighter = new TextHighlighter(Color.WHITE);
private final static int BASE_COLOUR_GREEN_COMPONENT = Color.green(BASE_COLOUR);
private final static int BASE_COLOUR_BLUE_COMPONENT = Color.blue(BASE_COLOUR);
public CalculatorEditor(Context context) { public CalculatorEditor(Context context) {
super(context); super(context);
@ -54,9 +53,7 @@ public class CalculatorEditor extends EditText {
menu.removeItem(android.R.id.startSelectingText); menu.removeItem(android.R.id.startSelectingText);
} }
public synchronized void redraw() {
public void redraw() {
String text = getText().toString(); String text = getText().toString();
int selectionStart = getSelectionStart(); int selectionStart = getSelectionStart();
@ -64,107 +61,24 @@ public class CalculatorEditor extends EditText {
if (highlightText) { if (highlightText) {
text = highlightText(text); Log.d(this.getClass().getName(), text);
try {
text = textHighlighter.process(text);
} catch (ParseException e) {
Log.e(this.getClass().getName(), e.getMessage(), e);
}
Log.d(this.getClass().getName(), text);
super.setText(Html.fromHtml(text), BufferType.EDITABLE); super.setText(Html.fromHtml(text), BufferType.EDITABLE);
} else { } else {
super.setText(text, BufferType.EDITABLE); super.setText(text, BufferType.EDITABLE);
} }
Log.d(this.getClass().getName(), getText().toString());
setSelection(selectionStart, selectionEnd); setSelection(selectionStart, selectionEnd);
} }
private String highlightText(@NotNull final String text) {
final String result;
int maxNumberOfOpenGroupSymbols = 0;
int numberOfOpenGroupSymbols = 0;
final StringBuilder text1 = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
final MathType.Result mathType = MathType.getType(text, i);
switch (mathType.getMathType()) {
case open_group_symbol:
numberOfOpenGroupSymbols++;
maxNumberOfOpenGroupSymbols = Math.max(maxNumberOfOpenGroupSymbols, numberOfOpenGroupSymbols);
text1.append(text.charAt(i));
break;
case close_group_symbol:
numberOfOpenGroupSymbols--;
text1.append(text.charAt(i));
break;
case function:
i = processHighlightedText(text1, i, mathType.getMatch(), "i");
break;
case constant:
i = processHighlightedText(text1, i, mathType.getMatch(), "b");
break;
default:
text1.append(text.charAt(i));
}
}
if (maxNumberOfOpenGroupSymbols > 0) {
final StringBuilder text2 = new StringBuilder();
processBracketGroup(text2, text1.toString(), 0, 0, maxNumberOfOpenGroupSymbols);
Log.d(CalculatorEditor.class.getName(), text2.toString());
result = text2.toString();
} else {
result = text1.toString();
}
return result;
}
private int processHighlightedText(@NotNull StringBuilder result, int i, @NotNull String functionName, @NotNull String tag) {
result.append("<").append(tag).append(">").append(functionName).append("</").append(tag).append(">");
return i + functionName.length() - 1;
}
private int processBracketGroup(@NotNull StringBuilder result, @NotNull String s, int i, int numberOfOpenings, int maxNumberOfGroups) {
result.append("<font color=\"").append(getColor(maxNumberOfGroups, numberOfOpenings)).append("\">");
for (; i < s.length(); i++) {
char ch = s.charAt(i);
if (MathType.openGroupSymbols.contains(ch)) {
result.append(ch);
result.append("</font>");
i = processBracketGroup(result, s, i + 1, numberOfOpenings + 1, maxNumberOfGroups);
result.append("<font color=\"").append(getColor(maxNumberOfGroups, numberOfOpenings)).append("\">");
if (i < s.length() && MathType.closeGroupSymbols.contains(s.charAt(i))) {
result.append(s.charAt(i));
}
} else if (MathType.closeGroupSymbols.contains(ch)) {
break;
} else {
result.append(ch);
}
}
result.append("</font>");
return i;
}
private String getColor(int numberOfOpenGroupSymbols, int numberOfOpenings) {
double c = 0.7;
int offset = ((int) (255 * c)) * numberOfOpenings / (numberOfOpenGroupSymbols + 1);
int result = Color.rgb(BASE_COLOUR_RED_COMPONENT - offset, BASE_COLOUR_GREEN_COMPONENT - offset, BASE_COLOUR_BLUE_COMPONENT - offset);
return "#" + Integer.toHexString(result).substring(2);
}
public boolean isHighlightText() { public boolean isHighlightText() {
return highlightText; return highlightText;
} }

View File

@ -39,6 +39,8 @@ public class CalculatorVarsActivity extends ListActivity {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.vars);
adapter = new VarsArrayAdapter(this, R.layout.var, R.id.var_text, new ArrayList<Var>(CalculatorModel.instance.getVarsRegister().getVars())); adapter = new VarsArrayAdapter(this, R.layout.var, R.id.var_text, new ArrayList<Var>(CalculatorModel.instance.getVarsRegister().getVars()));
setListAdapter(adapter); setListAdapter(adapter);
@ -68,6 +70,12 @@ public class CalculatorVarsActivity extends ListActivity {
} }
@SuppressWarnings({"UnusedDeclaration"})
public void addVarButtonClickHandler(@NotNull View v) {
createEditVariableDialog(null, null, null, null);
}
private void createEditVariableDialog(@Nullable final Var var, @Nullable final String name, @Nullable final String value, @Nullable final String description) { private void createEditVariableDialog(@Nullable final Var var, @Nullable final String name, @Nullable final String value, @Nullable final String description) {
if (var == null || !var.isSystem()) { if (var == null || !var.isSystem()) {

View File

@ -107,7 +107,7 @@ public class CalculatorView implements CursorControl, HistoryControl<CalculatorH
@NotNull @NotNull
private final MutableObject<Runnable> currentRunner = new MutableObject<Runnable>(); private final MutableObject<Runnable> currentRunner = new MutableObject<Runnable>();
public void doTextOperation(@NotNull TextOperation operation) { public synchronized void doTextOperation(@NotNull TextOperation operation) {
final String editorStateBefore = this.editor.getText().toString(); final String editorStateBefore = this.editor.getText().toString();
operation.doOperation(this.editor); operation.doOperation(this.editor);

View File

@ -0,0 +1,132 @@
/*
* 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.graphics.Color;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.model.ParseException;
import org.solovyev.android.calculator.model.TextProcessor;
/**
* User: serso
* Date: 10/12/11
* Time: 9:47 PM
*/
public class TextHighlighter implements TextProcessor {
private final int color;
private final int colorRed;
private final int colorGreen;
private final int colorBlue;
public TextHighlighter(int baseColor) {
this.color = baseColor;
this.colorRed = Color.red(baseColor);
this.colorGreen = Color.green(baseColor);
this.colorBlue = Color.blue(baseColor);
}
@NotNull
@Override
public String process(@NotNull String text) throws ParseException {
final String result;
int maxNumberOfOpenGroupSymbols = 0;
int numberOfOpenGroupSymbols = 0;
final StringBuilder text1 = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
final MathType.Result mathType = MathType.getType(text, i);
switch (mathType.getMathType()) {
case open_group_symbol:
numberOfOpenGroupSymbols++;
maxNumberOfOpenGroupSymbols = Math.max(maxNumberOfOpenGroupSymbols, numberOfOpenGroupSymbols);
text1.append(text.charAt(i));
break;
case close_group_symbol:
numberOfOpenGroupSymbols--;
text1.append(text.charAt(i));
break;
case function:
i = processHighlightedText(text1, i, mathType.getMatch(), "i");
break;
case constant:
i = processHighlightedText(text1, i, mathType.getMatch(), "b");
break;
default:
text1.append(text.charAt(i));
}
}
if (maxNumberOfOpenGroupSymbols > 0) {
final StringBuilder text2 = new StringBuilder();
String s = text1.toString();
int i = processBracketGroup(text2, s, 0, 0, maxNumberOfOpenGroupSymbols);
for (; i < s.length(); i++) {
text2.append(s.charAt(i));
}
//Log.d(CalculatorEditor.class.getName(), text2.toString());
result = text2.toString();
} else {
result = text1.toString();
}
return result;
}
private int processHighlightedText(@NotNull StringBuilder result, int i, @NotNull String functionName, @NotNull String tag) {
result.append("<").append(tag).append(">").append(functionName).append("</").append(tag).append(">");
return i + functionName.length() - 1;
}
private int processBracketGroup(@NotNull StringBuilder result, @NotNull String s, int i, int numberOfOpenings, int maxNumberOfGroups) {
result.append("<font color=\"").append(getColor(maxNumberOfGroups, numberOfOpenings)).append("\">");
for (; i < s.length(); i++) {
char ch = s.charAt(i);
if (MathType.openGroupSymbols.contains(ch)) {
result.append(ch);
result.append("</font>");
i = processBracketGroup(result, s, i + 1, numberOfOpenings + 1, maxNumberOfGroups);
result.append("<font color=\"").append(getColor(maxNumberOfGroups, numberOfOpenings)).append("\">");
if (i < s.length() && MathType.closeGroupSymbols.contains(s.charAt(i))) {
result.append(s.charAt(i));
}
} else if (MathType.closeGroupSymbols.contains(ch)) {
break;
} else {
result.append(ch);
}
}
result.append("</font>");
return i;
}
private String getColor(int totalNumberOfOpenings, int numberOfOpenings) {
double c = 0.8;
int offset = ((int) (255 * c)) * numberOfOpenings / (totalNumberOfOpenings + 1);
// for tests:
// innt result = Color.rgb(BASE_COLOUR_RED_COMPONENT - offset, BASE_COLOUR_GREEN_COMPONENT - offset, BASE_COLOUR_BLUE_COMPONENT - offset);
int result = (0xFF << 24) | ((colorRed - offset) << 16) | ((colorGreen - offset) << 8) | (colorBlue - offset);
return "#" + Integer.toHexString(result).substring(2);
}
}

View File

@ -37,6 +37,7 @@ public class Functions {
public final static String EXP = "exp"; public final static String EXP = "exp";
public final static String SQRT_SIGN = ""; public final static String SQRT_SIGN = "";
public final static String SQRT = "sqrt"; public final static String SQRT = "sqrt";
public final static String E = "E"; public final static String E = "E";
public final static String E_POWER = "10^"; public final static String E_POWER = "10^";

View File

@ -34,8 +34,11 @@ public enum MathType {
public static final String IMAGINARY_NUMBER_DEF = "sqrt(-1)"; public static final String IMAGINARY_NUMBER_DEF = "sqrt(-1)";
public static final String PI = "π"; public static final String PI = "π";
public static final String E = "e"; public static final String E = "e";
public final static String NAN = "NaN";
public final static String INFINITY = "";
public final static String INFINITY_DEF = "Infinity";
public static final List<String> constants = Arrays.asList(E, PI, IMAGINARY_NUMBER); public static final List<String> constants = Arrays.asList(E, PI, IMAGINARY_NUMBER, NAN, INFINITY);
public static final List<String> digits = Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9"); public static final List<String> digits = Arrays.asList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9");

View File

@ -22,7 +22,12 @@ class FromJsclTextProcessor implements TextProcessor {
@Override @Override
public String process(@NotNull String result) throws ParseException { public String process(@NotNull String result) throws ParseException {
try { try {
result = String.valueOf(round(result)); final Double roundedValue = round(result);
if ( roundedValue.isInfinite() ) {
result = MathType.INFINITY;
} else {
result = String.valueOf(roundedValue);
}
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
if (result.contains(MathType.IMAGINARY_NUMBER_DEF)) { if (result.contains(MathType.IMAGINARY_NUMBER_DEF)) {
try { try {

View File

@ -153,6 +153,12 @@ class VarsRegisterImpl implements VarsRegister {
} else if (systemVarName.equals(MathType.IMAGINARY_NUMBER)) { } else if (systemVarName.equals(MathType.IMAGINARY_NUMBER)) {
builder = new Var.Builder(systemVarName, MathType.IMAGINARY_NUMBER_DEF); builder = new Var.Builder(systemVarName, MathType.IMAGINARY_NUMBER_DEF);
varDescription = R.string.c_i_description; varDescription = R.string.c_i_description;
} else if (systemVarName.equals(MathType.NAN)) {
builder = new Var.Builder(systemVarName, MathType.NAN);
varDescription = R.string.c_nan_description;
} else if (systemVarName.equals(MathType.INFINITY)) {
builder = new Var.Builder(systemVarName, MathType.INFINITY_DEF);
varDescription = R.string.c_infinity_description;
} else { } else {
throw new IllegalArgumentException(systemVarName + " is not supported yet!"); throw new IllegalArgumentException(systemVarName + " is not supported yet!");
} }

View File

@ -26,6 +26,7 @@ import android.content.res.Resources;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
import android.graphics.Paint.Style; import android.graphics.Paint.Style;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.widget.Button; import android.widget.Button;
@ -33,6 +34,7 @@ import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.view.FontSizeAdjuster; import org.solovyev.android.view.FontSizeAdjuster;
import org.solovyev.common.utils.Point2d; import org.solovyev.common.utils.Point2d;
import org.solovyev.common.utils.StringUtils;
/** /**
* NOTE: copied from com.android.calculator2.ColorButton * NOTE: copied from com.android.calculator2.ColorButton
@ -42,14 +44,15 @@ import org.solovyev.common.utils.Point2d;
* Button with click-animation effect. * Button with click-animation effect.
*/ */
public class ColorButton extends Button { public class ColorButton extends Button {
int CLICK_FEEDBACK_COLOR;
static final int CLICK_FEEDBACK_INTERVAL = 10; private int CLICK_FEEDBACK_COLOR;
static final int CLICK_FEEDBACK_DURATION = 350; private static final int CLICK_FEEDBACK_INTERVAL = 10;
private static final int CLICK_FEEDBACK_DURATION = 350;
@NotNull @NotNull
private Point2d textPosition; private Point2d textPosition;
private long mAnimStart; private long animationStart;
private Paint mFeedbackPaint; private Paint feedbackPaint;
public ColorButton(Context context, AttributeSet attrs) { public ColorButton(Context context, AttributeSet attrs) {
this(context, attrs, true); this(context, attrs, true);
@ -66,12 +69,12 @@ public class ColorButton extends Button {
Resources res = getResources(); Resources res = getResources();
CLICK_FEEDBACK_COLOR = res.getColor(org.solovyev.android.calculator.R.color.magic_flame); CLICK_FEEDBACK_COLOR = res.getColor(org.solovyev.android.calculator.R.color.magic_flame);
mFeedbackPaint = new Paint(); feedbackPaint = new Paint();
mFeedbackPaint.setStyle(Style.STROKE); feedbackPaint.setStyle(Style.STROKE);
mFeedbackPaint.setStrokeWidth(2); feedbackPaint.setStrokeWidth(2);
getPaint().setColor(res.getColor(R.color.button_text_color)); getPaint().setColor(res.getColor(R.color.button_text_color));
mAnimStart = -1; animationStart = -1;
if (context instanceof FontSizeAdjuster) { if (context instanceof FontSizeAdjuster) {
((FontSizeAdjuster) context).adjustFontSize(this); ((FontSizeAdjuster) context).adjustFontSize(this);
@ -113,17 +116,17 @@ public class ColorButton extends Button {
int alpha = 255 - 255 * duration / CLICK_FEEDBACK_DURATION; int alpha = 255 - 255 * duration / CLICK_FEEDBACK_DURATION;
int color = CLICK_FEEDBACK_COLOR | (alpha << 24); int color = CLICK_FEEDBACK_COLOR | (alpha << 24);
mFeedbackPaint.setColor(color); feedbackPaint.setColor(color);
canvas.drawRect(1, 1, getWidth() - 1, getHeight() - 1, mFeedbackPaint); canvas.drawRect(1, 1, getWidth() - 1, getHeight() - 1, feedbackPaint);
} }
@Override @Override
public void onDraw(Canvas canvas) { public void onDraw(Canvas canvas) {
if (mAnimStart != -1) { if (animationStart != -1) {
int animDuration = (int) (System.currentTimeMillis() - mAnimStart); int animDuration = (int) (System.currentTimeMillis() - animationStart);
if (animDuration >= CLICK_FEEDBACK_DURATION) { if (animDuration >= CLICK_FEEDBACK_DURATION) {
mAnimStart = -1; animationStart = -1;
} else { } else {
drawMagicFlame(animDuration, canvas); drawMagicFlame(animDuration, canvas);
postInvalidateDelayed(CLICK_FEEDBACK_INTERVAL); postInvalidateDelayed(CLICK_FEEDBACK_INTERVAL);
@ -131,13 +134,48 @@ public class ColorButton extends Button {
} }
CharSequence text = getText(); CharSequence text = getText();
if (text != null && textPosition != null) { if (!StringUtils.isEmpty(text) && textPosition != null) {
canvas.drawText(text, 0, text.length(), textPosition.getX(), textPosition.getY(), getPaint()); canvas.drawText(text, 0, text.length(), textPosition.getX(), textPosition.getY(), getPaint());
} else {
drawDrawables(canvas);
}
}
private void drawDrawables(Canvas canvas) {
final int compoundPaddingLeft = getCompoundPaddingLeft();
final int compoundPaddingTop = getCompoundPaddingTop();
final int compoundPaddingRight = getCompoundPaddingRight();
final int compoundPaddingBottom = getCompoundPaddingBottom();
final int scrollX = getScrollX();
final int scrollY = getScrollY();
final int right = getRight();
final int left = getLeft();
final int bottom = getBottom();
final int top = getTop();
final Drawable[] drawables = getCompoundDrawables();
if (drawables != null) {
int vspace = bottom - top - compoundPaddingBottom - compoundPaddingTop;
int hspace = right - left - compoundPaddingRight - compoundPaddingLeft;
Drawable topDr = drawables[1];
// IMPORTANT: The coordinates computed are also used in invalidateDrawable()
// Make sure to update invalidateDrawable() when changing this code.
if (topDr != null) {
canvas.save();
canvas.translate(scrollX + compoundPaddingLeft + (hspace - topDr.getBounds().width()) / 2,
scrollY + getPaddingTop() + vspace / 2);
topDr.draw(canvas);
canvas.restore();
}
} }
} }
public void animateClickFeedback() { public void animateClickFeedback() {
mAnimStart = System.currentTimeMillis(); animationStart = System.currentTimeMillis();
invalidate(); invalidate();
} }

View File

@ -126,11 +126,10 @@ public class DirectionDragButton extends DragButton {
basePaint.measureText(StringUtils.getNotEmpty(baseText, "|")); basePaint.measureText(StringUtils.getNotEmpty(baseText, "|"));
float height = h - basePaint.ascent() - basePaint.descent();
if (direction < 0) { if (direction < 0) {
result.setY(height / 2 + height / 3 + selfHeight); result.setY(h / 2 + h / 3 - selfHeight / 2);
} else { } else {
result.setY(height / 2 - height / 3); result.setY(h / 2 - h / 3 - selfHeight / 2);
} }
return result; return result;
@ -158,7 +157,7 @@ public class DirectionDragButton extends DragButton {
upDownTextPaint = new TextPaint(paint); upDownTextPaint = new TextPaint(paint);
upDownTextPaint.setAlpha(150); upDownTextPaint.setAlpha(150);
upDownTextPaint.setTextSize(paint.getTextSize() / 2); upDownTextPaint.setTextSize(paint.getTextSize() / 3);
} }
private String getStyledUpDownText(@Nullable String text) { private String getStyledUpDownText(@Nullable String text) {

View File

@ -0,0 +1,45 @@
/*
* 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 junit.framework.Assert;
import org.junit.Test;
import org.solovyev.android.calculator.model.TextProcessor;
import java.util.Date;
import java.util.Random;
/**
* User: serso
* Date: 10/12/11
* Time: 10:07 PM
*/
public class TextHighlighterTest {
@Test
public void testProcess() throws Exception {
final TextProcessor textHighlighter = new TextHighlighter(0);
final Random random = new Random(new Date().getTime());
for (int i = 0; i < 1000; i++) {
final StringBuilder sb = new StringBuilder();
for (int j = 0; j < 1000; j++) {
sb.append(random.nextBoolean() ? "(" : ")");
}
try {
textHighlighter.process(sb.toString());
} catch (Exception e) {
System.out.println(sb.toString());
throw e;
}
}
Assert.assertEquals("<font color=\"#000000\"></font>)(((())())", textHighlighter.process(")(((())())"));
Assert.assertEquals(")", textHighlighter.process(")"));
Assert.assertEquals(")()(", textHighlighter.process(")()("));
}
}