diff --git a/app/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java b/app/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java index 93752874..0f632e84 100644 --- a/app/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java +++ b/app/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java @@ -171,7 +171,7 @@ public class CalculatorApplication extends android.app.Application implements Sh new AndroidCalculatorHistory(this, calculator), new AndroidCalculatorLogger(), new AndroidCalculatorPreferenceService(this), - new AndroidCalculatorKeyboard(this, new CalculatorKeyboardImpl(calculator)), + new AndroidCalculatorKeyboard(this, new CalculatorKeyboardImpl()), new AndroidCalculatorPlotter(this, new CalculatorPlotterImpl(calculator)), editorTextProcessor); diff --git a/app/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java b/app/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java index def5f43a..69fc2dbe 100644 --- a/app/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java +++ b/app/src/main/java/org/solovyev/android/calculator/CalculatorImpl.java @@ -22,14 +22,6 @@ package org.solovyev.android.calculator; -import jscl.AbstractJsclArithmeticException; -import jscl.NumeralBase; -import jscl.NumeralBaseException; -import jscl.math.Generic; -import jscl.math.function.Function; -import jscl.math.function.IConstant; -import jscl.math.operator.Operator; -import jscl.text.ParseInterruptedException; import org.solovyev.android.calculator.history.CalculatorHistory; import org.solovyev.android.calculator.history.HistoryState; import org.solovyev.android.calculator.jscl.JsclOperation; @@ -45,14 +37,24 @@ import org.solovyev.common.text.Strings; import org.solovyev.common.units.ConversionException; import org.solovyev.common.units.Conversions; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import jscl.AbstractJsclArithmeticException; +import jscl.NumeralBase; +import jscl.NumeralBaseException; +import jscl.math.Generic; +import jscl.math.function.Function; +import jscl.math.function.IConstant; +import jscl.math.operator.Operator; +import jscl.text.ParseInterruptedException; + /** * User: Solovyev_S * Date: 20.09.12 @@ -175,21 +177,21 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener { public void evaluate() { final EditorState viewState = getEditor().getState(); final CalculatorEventData eventData = fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState); - this.evaluate(JsclOperation.numeric, viewState.getText(), eventData.getSequenceId()); + this.evaluate(JsclOperation.numeric, viewState.getTextString(), eventData.getSequenceId()); } @Override public void evaluate(@Nonnull Long sequenceId) { final EditorState viewState = getEditor().getState(); fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState, sequenceId); - this.evaluate(JsclOperation.numeric, viewState.getText(), sequenceId); + this.evaluate(JsclOperation.numeric, viewState.getTextString(), sequenceId); } @Override public void simplify() { final EditorState viewState = getEditor().getState(); final CalculatorEventData eventData = fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState); - this.evaluate(JsclOperation.simplify, viewState.getText(), eventData.getSequenceId()); + this.evaluate(JsclOperation.simplify, viewState.getTextString(), eventData.getSequenceId()); } @Nonnull @@ -511,11 +513,11 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener { if (calculateOnFly) { final CalculatorEditorChangeEventData editorChangeEventData = (CalculatorEditorChangeEventData) data; - final String newText = editorChangeEventData.getNewValue().getText(); - final String oldText = editorChangeEventData.getOldValue().getText(); + final String newText = editorChangeEventData.getNewValue().getTextString(); + final String oldText = editorChangeEventData.getOldValue().getTextString(); if (!newText.equals(oldText)) { - evaluate(JsclOperation.numeric, editorChangeEventData.getNewValue().getText(), calculatorEventData.getSequenceId()); + evaluate(JsclOperation.numeric, editorChangeEventData.getNewValue().getTextString(), calculatorEventData.getSequenceId()); } } break; diff --git a/app/src/main/java/org/solovyev/android/calculator/CalculatorKeyboardImpl.java b/app/src/main/java/org/solovyev/android/calculator/CalculatorKeyboardImpl.java index 43b6ff59..4271660b 100644 --- a/app/src/main/java/org/solovyev/android/calculator/CalculatorKeyboardImpl.java +++ b/app/src/main/java/org/solovyev/android/calculator/CalculatorKeyboardImpl.java @@ -28,25 +28,11 @@ import org.solovyev.common.text.Strings; import javax.annotation.Nonnull; import javax.annotation.Nullable; -/** - * User: serso - * Date: 9/22/12 - * Time: 1:08 PM - */ public class CalculatorKeyboardImpl implements CalculatorKeyboard { - @Nonnull - private final Calculator calculator; - - public CalculatorKeyboardImpl(@Nonnull Calculator calculator) { - this.calculator = calculator; - } - @Override public boolean buttonPressed(@Nullable final String text) { if (!Strings.isEmpty(text)) { - if (text == null) throw new AssertionError(); - // process special buttons boolean processed = processSpecialButtons(text); @@ -113,15 +99,10 @@ public class CalculatorKeyboardImpl implements CalculatorKeyboard { final Editor editor = Locator.getInstance().getEditor(); EditorState viewState = editor.getState(); - final int cursorPosition = viewState.getSelection(); - final String oldText = viewState.getText(); + final int cursorPosition = viewState.selection; + final CharSequence oldText = viewState.text; - final StringBuilder newText = new StringBuilder(oldText.length() + 2); - newText.append("("); - newText.append(oldText.substring(0, cursorPosition)); - newText.append(")"); - newText.append(oldText.substring(cursorPosition)); - editor.setText(newText.toString(), cursorPosition + 2); + editor.setText("(" + oldText.subSequence(0, cursorPosition) + ")" + oldText.subSequence(cursorPosition, oldText.length()), cursorPosition + 2); } @Override diff --git a/app/src/main/java/org/solovyev/android/calculator/Editor.java b/app/src/main/java/org/solovyev/android/calculator/Editor.java index d1cb1cb5..75a84551 100644 --- a/app/src/main/java/org/solovyev/android/calculator/Editor.java +++ b/app/src/main/java/org/solovyev/android/calculator/Editor.java @@ -93,8 +93,8 @@ public class Editor implements CalculatorEventListener { Check.isMainThread(); if (textProcessor != null) { try { - final TextProcessorEditorResult result = textProcessor.process(newState.getText()); - newState = EditorState.create(result.getCharSequence(), newState.getSelection() + result.getOffset()); + final TextProcessorEditorResult result = textProcessor.process(newState.getTextString()); + newState = EditorState.create(result.getCharSequence(), newState.selection + result.getOffset()); } catch (CalculatorParseException e) { Locator.getInstance().getLogger().error(TAG, e.getMessage(), e); } @@ -138,7 +138,7 @@ public class Editor implements CalculatorEventListener { @Nonnull private EditorState newSelectionViewState(int newSelection) { Check.isMainThread(); - if (state.getSelection() != newSelection) { + if (state.selection != newSelection) { final EditorState result = EditorState.newSelection(state, newSelection); setState(result, false); return result; @@ -156,14 +156,14 @@ public class Editor implements CalculatorEventListener { @Nonnull public EditorState setCursorOnEnd() { Check.isMainThread(); - return newSelectionViewState(state.getText().length()); + return newSelectionViewState(state.text.length()); } @Nonnull public EditorState moveCursorLeft() { Check.isMainThread(); - if (state.getSelection() > 0) { - return newSelectionViewState(state.getSelection() - 1); + if (state.selection > 0) { + return newSelectionViewState(state.selection - 1); } else { return state; } @@ -172,8 +172,8 @@ public class Editor implements CalculatorEventListener { @Nonnull public EditorState moveCursorRight() { Check.isMainThread(); - if (state.getSelection() < state.getText().length()) { - return newSelectionViewState(state.getSelection() + 1); + if (state.selection < state.text.length()) { + return newSelectionViewState(state.selection + 1); } else { return state; } @@ -182,15 +182,12 @@ public class Editor implements CalculatorEventListener { @Nonnull public EditorState erase() { Check.isMainThread(); - int selection = state.getSelection(); - final String text = state.getText(); + int selection = state.selection; + final String text = state.getTextString(); if (selection > 0 && text.length() > 0 && selection <= text.length()) { - final StringBuilder newText = new StringBuilder(text.length() - 1); - newText.append(text.substring(0, selection - 1)).append(text.substring(selection, text.length())); - - final EditorState result = EditorState.create(newText.toString(), selection - 1); - setState(result); - return result; + final EditorState newState = EditorState.create(text.substring(0, selection - 1) + text.substring(selection, text.length()), selection - 1); + setState(newState); + return newState; } else { return state; } @@ -229,33 +226,28 @@ public class Editor implements CalculatorEventListener { @Nonnull public EditorState insert(@Nonnull String text, int selectionOffset) { Check.isMainThread(); - final String oldText = state.getText(); - final int selection = clamp(state.getSelection(), oldText); + final String oldText = state.getTextString(); + final int selection = clamp(state.selection, oldText); int newTextLength = text.length() + oldText.length(); - final StringBuilder newText = new StringBuilder(newTextLength); - - newText.append(oldText.substring(0, selection)); - newText.append(text); - newText.append(oldText.substring(selection)); int newSelection = clamp(text.length() + selection + selectionOffset, newTextLength); - final EditorState result = EditorState.create(newText.toString(), newSelection); - setState(result); - return result; + final EditorState newState = EditorState.create(oldText.substring(0, selection) + text + oldText.substring(selection), newSelection); + setState(newState); + return newState; } @Nonnull public EditorState moveSelection(int offset) { Check.isMainThread(); - int selection = state.getSelection() + offset; + int selection = state.selection + offset; return setSelection(selection); } @Nonnull public EditorState setSelection(int selection) { Check.isMainThread(); - selection = clamp(selection, state.getText()); + selection = clamp(selection, state.text); final EditorState result = EditorState.newSelection(state, selection); setState(result, false); diff --git a/app/src/main/java/org/solovyev/android/calculator/EditorState.java b/app/src/main/java/org/solovyev/android/calculator/EditorState.java index 0b1dfd54..d5d03738 100644 --- a/app/src/main/java/org/solovyev/android/calculator/EditorState.java +++ b/app/src/main/java/org/solovyev/android/calculator/EditorState.java @@ -22,22 +22,26 @@ package org.solovyev.android.calculator; -import javax.annotation.Nonnull; import java.io.Serializable; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + public class EditorState implements Serializable { @Nonnull - private CharSequence text = ""; - - private int selection = 0; + public final CharSequence text; + public final int selection; + @Nullable + private String textString; private EditorState() { + this("", 0); } - public EditorState(@Nonnull EditorState state) { - this.text = state.getText(); - this.selection = state.getSelection(); + private EditorState(@Nonnull CharSequence text, int selection) { + this.text = text; + this.selection = selection; } @Nonnull @@ -47,30 +51,19 @@ public class EditorState implements Serializable { @Nonnull public static EditorState newSelection(@Nonnull EditorState state, int selection) { - final EditorState result = new EditorState(state); - result.selection = selection; - return result; + return new EditorState(state.text, selection); } @Nonnull public static EditorState create(@Nonnull CharSequence text, int selection) { - final EditorState result = new EditorState(); - result.text = text; - result.selection = selection; - return result; + return new EditorState(text, selection); } @Nonnull - public String getText() { - return this.text.toString(); - } - - @Nonnull - public CharSequence getTextAsCharSequence() { - return this.text; - } - - public int getSelection() { - return this.selection; + public String getTextString() { + if (textString == null) { + textString = text.toString(); + } + return textString; } } diff --git a/app/src/main/java/org/solovyev/android/calculator/EditorView.java b/app/src/main/java/org/solovyev/android/calculator/EditorView.java index 6dba4dde..b95682fc 100644 --- a/app/src/main/java/org/solovyev/android/calculator/EditorView.java +++ b/app/src/main/java/org/solovyev/android/calculator/EditorView.java @@ -90,11 +90,11 @@ public class EditorView extends EditText { reportChanges = false; if (App.getTheme().light && getContext() instanceof CalculatorOnscreenService) { // don't need formatting - setText(state.getText()); + setText(state.getTextString()); } else { - setText(state.getTextAsCharSequence(), BufferType.EDITABLE); + setText(state.text, BufferType.EDITABLE); } - final int selection = Editor.clamp(state.getSelection(), length()); + final int selection = Editor.clamp(state.selection, length()); setSelection(selection); } finally { reportChanges = true; diff --git a/app/src/main/java/org/solovyev/android/calculator/history/EditorHistoryState.java b/app/src/main/java/org/solovyev/android/calculator/history/EditorHistoryState.java index 6c6a6c0c..8284d7ca 100644 --- a/app/src/main/java/org/solovyev/android/calculator/history/EditorHistoryState.java +++ b/app/src/main/java/org/solovyev/android/calculator/history/EditorHistoryState.java @@ -50,8 +50,8 @@ public class EditorHistoryState implements Cloneable { public static EditorHistoryState create(@Nonnull EditorState state) { final EditorHistoryState result = new EditorHistoryState(); - result.text = String.valueOf(state.getText()); - result.cursorPosition = state.getSelection(); + result.text = state.getTextString(); + result.cursorPosition = state.selection; return result; } diff --git a/app/src/main/java/org/solovyev/android/calculator/view/LongClickEraser.java b/app/src/main/java/org/solovyev/android/calculator/view/LongClickEraser.java index 184919e8..6a45b836 100644 --- a/app/src/main/java/org/solovyev/android/calculator/view/LongClickEraser.java +++ b/app/src/main/java/org/solovyev/android/calculator/view/LongClickEraser.java @@ -70,7 +70,7 @@ public final class LongClickEraser implements View.OnTouchListener { @Override public void run() { final EditorState state = editor.erase(); - if (isEmpty(state.getText())) { + if (isEmpty(state.text)) { stop(); return; } diff --git a/app/src/main/java/org/solovyev/android/calculator/widget/CalculatorWidget.java b/app/src/main/java/org/solovyev/android/calculator/widget/CalculatorWidget.java index fbceeccb..31b9996e 100644 --- a/app/src/main/java/org/solovyev/android/calculator/widget/CalculatorWidget.java +++ b/app/src/main/java/org/solovyev/android/calculator/widget/CalculatorWidget.java @@ -203,11 +203,11 @@ public class CalculatorWidget extends AppWidgetProvider { views.setTextColor(R.id.calculator_display, ContextCompat.getColor(context, theme.getDisplayTextColor(error))); } - private void updateEditorState(@Nonnull Context context, @Nonnull RemoteViews views, @Nonnull EditorState editorState, @Nonnull SimpleTheme theme) { - final CharSequence text = editorState.getTextAsCharSequence(); + private void updateEditorState(@Nonnull Context context, @Nonnull RemoteViews views, @Nonnull EditorState state, @Nonnull SimpleTheme theme) { final boolean unspan = App.getTheme().light != theme.light; - final int selection = editorState.getSelection(); + final CharSequence text = state.text; + final int selection = state.selection; if (selection < 0 || selection > text.length()) { views.setTextViewText(R.id.calculator_editor, unspan ? unspan(text) : text); return;