This commit is contained in:
serso 2016-01-08 10:30:09 +01:00
parent e3c3abf828
commit 0c78ac3322
9 changed files with 69 additions and 101 deletions

View File

@ -171,7 +171,7 @@ public class CalculatorApplication extends android.app.Application implements Sh
new AndroidCalculatorHistory(this, calculator), new AndroidCalculatorHistory(this, calculator),
new AndroidCalculatorLogger(), new AndroidCalculatorLogger(),
new AndroidCalculatorPreferenceService(this), new AndroidCalculatorPreferenceService(this),
new AndroidCalculatorKeyboard(this, new CalculatorKeyboardImpl(calculator)), new AndroidCalculatorKeyboard(this, new CalculatorKeyboardImpl()),
new AndroidCalculatorPlotter(this, new CalculatorPlotterImpl(calculator)), new AndroidCalculatorPlotter(this, new CalculatorPlotterImpl(calculator)),
editorTextProcessor); editorTextProcessor);

View File

@ -22,14 +22,6 @@
package org.solovyev.android.calculator; 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.CalculatorHistory;
import org.solovyev.android.calculator.history.HistoryState; import org.solovyev.android.calculator.history.HistoryState;
import org.solovyev.android.calculator.jscl.JsclOperation; 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.ConversionException;
import org.solovyev.common.units.Conversions; import org.solovyev.common.units.Conversions;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong; 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 * User: Solovyev_S
* Date: 20.09.12 * Date: 20.09.12
@ -175,21 +177,21 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
public void evaluate() { public void evaluate() {
final EditorState viewState = getEditor().getState(); final EditorState viewState = getEditor().getState();
final CalculatorEventData eventData = fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState); 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 @Override
public void evaluate(@Nonnull Long sequenceId) { public void evaluate(@Nonnull Long sequenceId) {
final EditorState viewState = getEditor().getState(); final EditorState viewState = getEditor().getState();
fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState, sequenceId); fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState, sequenceId);
this.evaluate(JsclOperation.numeric, viewState.getText(), sequenceId); this.evaluate(JsclOperation.numeric, viewState.getTextString(), sequenceId);
} }
@Override @Override
public void simplify() { public void simplify() {
final EditorState viewState = getEditor().getState(); final EditorState viewState = getEditor().getState();
final CalculatorEventData eventData = fireCalculatorEvent(CalculatorEventType.manual_calculation_requested, viewState); 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 @Nonnull
@ -511,11 +513,11 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
if (calculateOnFly) { if (calculateOnFly) {
final CalculatorEditorChangeEventData editorChangeEventData = (CalculatorEditorChangeEventData) data; final CalculatorEditorChangeEventData editorChangeEventData = (CalculatorEditorChangeEventData) data;
final String newText = editorChangeEventData.getNewValue().getText(); final String newText = editorChangeEventData.getNewValue().getTextString();
final String oldText = editorChangeEventData.getOldValue().getText(); final String oldText = editorChangeEventData.getOldValue().getTextString();
if (!newText.equals(oldText)) { if (!newText.equals(oldText)) {
evaluate(JsclOperation.numeric, editorChangeEventData.getNewValue().getText(), calculatorEventData.getSequenceId()); evaluate(JsclOperation.numeric, editorChangeEventData.getNewValue().getTextString(), calculatorEventData.getSequenceId());
} }
} }
break; break;

View File

@ -28,25 +28,11 @@ import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
/**
* User: serso
* Date: 9/22/12
* Time: 1:08 PM
*/
public class CalculatorKeyboardImpl implements CalculatorKeyboard { public class CalculatorKeyboardImpl implements CalculatorKeyboard {
@Nonnull
private final Calculator calculator;
public CalculatorKeyboardImpl(@Nonnull Calculator calculator) {
this.calculator = calculator;
}
@Override @Override
public boolean buttonPressed(@Nullable final String text) { public boolean buttonPressed(@Nullable final String text) {
if (!Strings.isEmpty(text)) { if (!Strings.isEmpty(text)) {
if (text == null) throw new AssertionError();
// process special buttons // process special buttons
boolean processed = processSpecialButtons(text); boolean processed = processSpecialButtons(text);
@ -113,15 +99,10 @@ public class CalculatorKeyboardImpl implements CalculatorKeyboard {
final Editor editor = Locator.getInstance().getEditor(); final Editor editor = Locator.getInstance().getEditor();
EditorState viewState = editor.getState(); EditorState viewState = editor.getState();
final int cursorPosition = viewState.getSelection(); final int cursorPosition = viewState.selection;
final String oldText = viewState.getText(); final CharSequence oldText = viewState.text;
final StringBuilder newText = new StringBuilder(oldText.length() + 2); editor.setText("(" + oldText.subSequence(0, cursorPosition) + ")" + oldText.subSequence(cursorPosition, oldText.length()), cursorPosition + 2);
newText.append("(");
newText.append(oldText.substring(0, cursorPosition));
newText.append(")");
newText.append(oldText.substring(cursorPosition));
editor.setText(newText.toString(), cursorPosition + 2);
} }
@Override @Override

View File

@ -93,8 +93,8 @@ public class Editor implements CalculatorEventListener {
Check.isMainThread(); Check.isMainThread();
if (textProcessor != null) { if (textProcessor != null) {
try { try {
final TextProcessorEditorResult result = textProcessor.process(newState.getText()); final TextProcessorEditorResult result = textProcessor.process(newState.getTextString());
newState = EditorState.create(result.getCharSequence(), newState.getSelection() + result.getOffset()); newState = EditorState.create(result.getCharSequence(), newState.selection + result.getOffset());
} catch (CalculatorParseException e) { } catch (CalculatorParseException e) {
Locator.getInstance().getLogger().error(TAG, e.getMessage(), e); Locator.getInstance().getLogger().error(TAG, e.getMessage(), e);
} }
@ -138,7 +138,7 @@ public class Editor implements CalculatorEventListener {
@Nonnull @Nonnull
private EditorState newSelectionViewState(int newSelection) { private EditorState newSelectionViewState(int newSelection) {
Check.isMainThread(); Check.isMainThread();
if (state.getSelection() != newSelection) { if (state.selection != newSelection) {
final EditorState result = EditorState.newSelection(state, newSelection); final EditorState result = EditorState.newSelection(state, newSelection);
setState(result, false); setState(result, false);
return result; return result;
@ -156,14 +156,14 @@ public class Editor implements CalculatorEventListener {
@Nonnull @Nonnull
public EditorState setCursorOnEnd() { public EditorState setCursorOnEnd() {
Check.isMainThread(); Check.isMainThread();
return newSelectionViewState(state.getText().length()); return newSelectionViewState(state.text.length());
} }
@Nonnull @Nonnull
public EditorState moveCursorLeft() { public EditorState moveCursorLeft() {
Check.isMainThread(); Check.isMainThread();
if (state.getSelection() > 0) { if (state.selection > 0) {
return newSelectionViewState(state.getSelection() - 1); return newSelectionViewState(state.selection - 1);
} else { } else {
return state; return state;
} }
@ -172,8 +172,8 @@ public class Editor implements CalculatorEventListener {
@Nonnull @Nonnull
public EditorState moveCursorRight() { public EditorState moveCursorRight() {
Check.isMainThread(); Check.isMainThread();
if (state.getSelection() < state.getText().length()) { if (state.selection < state.text.length()) {
return newSelectionViewState(state.getSelection() + 1); return newSelectionViewState(state.selection + 1);
} else { } else {
return state; return state;
} }
@ -182,15 +182,12 @@ public class Editor implements CalculatorEventListener {
@Nonnull @Nonnull
public EditorState erase() { public EditorState erase() {
Check.isMainThread(); Check.isMainThread();
int selection = state.getSelection(); int selection = state.selection;
final String text = state.getText(); final String text = state.getTextString();
if (selection > 0 && text.length() > 0 && selection <= text.length()) { if (selection > 0 && text.length() > 0 && selection <= text.length()) {
final StringBuilder newText = new StringBuilder(text.length() - 1); final EditorState newState = EditorState.create(text.substring(0, selection - 1) + text.substring(selection, text.length()), selection - 1);
newText.append(text.substring(0, selection - 1)).append(text.substring(selection, text.length())); setState(newState);
return newState;
final EditorState result = EditorState.create(newText.toString(), selection - 1);
setState(result);
return result;
} else { } else {
return state; return state;
} }
@ -229,33 +226,28 @@ public class Editor implements CalculatorEventListener {
@Nonnull @Nonnull
public EditorState insert(@Nonnull String text, int selectionOffset) { public EditorState insert(@Nonnull String text, int selectionOffset) {
Check.isMainThread(); Check.isMainThread();
final String oldText = state.getText(); final String oldText = state.getTextString();
final int selection = clamp(state.getSelection(), oldText); final int selection = clamp(state.selection, oldText);
int newTextLength = text.length() + oldText.length(); 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); int newSelection = clamp(text.length() + selection + selectionOffset, newTextLength);
final EditorState result = EditorState.create(newText.toString(), newSelection); final EditorState newState = EditorState.create(oldText.substring(0, selection) + text + oldText.substring(selection), newSelection);
setState(result); setState(newState);
return result; return newState;
} }
@Nonnull @Nonnull
public EditorState moveSelection(int offset) { public EditorState moveSelection(int offset) {
Check.isMainThread(); Check.isMainThread();
int selection = state.getSelection() + offset; int selection = state.selection + offset;
return setSelection(selection); return setSelection(selection);
} }
@Nonnull @Nonnull
public EditorState setSelection(int selection) { public EditorState setSelection(int selection) {
Check.isMainThread(); Check.isMainThread();
selection = clamp(selection, state.getText()); selection = clamp(selection, state.text);
final EditorState result = EditorState.newSelection(state, selection); final EditorState result = EditorState.newSelection(state, selection);
setState(result, false); setState(result, false);

View File

@ -22,22 +22,26 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import java.io.Serializable; import java.io.Serializable;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class EditorState implements Serializable { public class EditorState implements Serializable {
@Nonnull @Nonnull
private CharSequence text = ""; public final CharSequence text;
public final int selection;
private int selection = 0; @Nullable
private String textString;
private EditorState() { private EditorState() {
this("", 0);
} }
public EditorState(@Nonnull EditorState state) { private EditorState(@Nonnull CharSequence text, int selection) {
this.text = state.getText(); this.text = text;
this.selection = state.getSelection(); this.selection = selection;
} }
@Nonnull @Nonnull
@ -47,30 +51,19 @@ public class EditorState implements Serializable {
@Nonnull @Nonnull
public static EditorState newSelection(@Nonnull EditorState state, int selection) { public static EditorState newSelection(@Nonnull EditorState state, int selection) {
final EditorState result = new EditorState(state); return new EditorState(state.text, selection);
result.selection = selection;
return result;
} }
@Nonnull @Nonnull
public static EditorState create(@Nonnull CharSequence text, int selection) { public static EditorState create(@Nonnull CharSequence text, int selection) {
final EditorState result = new EditorState(); return new EditorState(text, selection);
result.text = text;
result.selection = selection;
return result;
} }
@Nonnull @Nonnull
public String getText() { public String getTextString() {
return this.text.toString(); if (textString == null) {
textString = text.toString();
} }
return textString;
@Nonnull
public CharSequence getTextAsCharSequence() {
return this.text;
}
public int getSelection() {
return this.selection;
} }
} }

View File

@ -90,11 +90,11 @@ public class EditorView extends EditText {
reportChanges = false; reportChanges = false;
if (App.getTheme().light && getContext() instanceof CalculatorOnscreenService) { if (App.getTheme().light && getContext() instanceof CalculatorOnscreenService) {
// don't need formatting // don't need formatting
setText(state.getText()); setText(state.getTextString());
} else { } 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); setSelection(selection);
} finally { } finally {
reportChanges = true; reportChanges = true;

View File

@ -50,8 +50,8 @@ public class EditorHistoryState implements Cloneable {
public static EditorHistoryState create(@Nonnull EditorState state) { public static EditorHistoryState create(@Nonnull EditorState state) {
final EditorHistoryState result = new EditorHistoryState(); final EditorHistoryState result = new EditorHistoryState();
result.text = String.valueOf(state.getText()); result.text = state.getTextString();
result.cursorPosition = state.getSelection(); result.cursorPosition = state.selection;
return result; return result;
} }

View File

@ -70,7 +70,7 @@ public final class LongClickEraser implements View.OnTouchListener {
@Override @Override
public void run() { public void run() {
final EditorState state = editor.erase(); final EditorState state = editor.erase();
if (isEmpty(state.getText())) { if (isEmpty(state.text)) {
stop(); stop();
return; return;
} }

View File

@ -203,11 +203,11 @@ public class CalculatorWidget extends AppWidgetProvider {
views.setTextColor(R.id.calculator_display, ContextCompat.getColor(context, theme.getDisplayTextColor(error))); 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) { private void updateEditorState(@Nonnull Context context, @Nonnull RemoteViews views, @Nonnull EditorState state, @Nonnull SimpleTheme theme) {
final CharSequence text = editorState.getTextAsCharSequence();
final boolean unspan = App.getTheme().light != theme.light; 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()) { if (selection < 0 || selection > text.length()) {
views.setTextViewText(R.id.calculator_editor, unspan ? unspan(text) : text); views.setTextViewText(R.id.calculator_editor, unspan ? unspan(text) : text);
return; return;