number formatting is working now

This commit is contained in:
Sergey Solovyev 2013-06-28 00:02:30 +04:00
parent c91d57a92c
commit 8d15db4c3f
25 changed files with 301 additions and 273 deletions

View File

@ -62,7 +62,7 @@
</style>
<style name="cpp_onscreen_editor_style" parent="cpp_editor_style">
<item name="android:ellipsize">end</item>
<item name="android:ellipsize">none</item>
<item name="android:singleLine">true</item>
<item name="android:maxLines">1</item>
<item name="android:minLines">1</item>

View File

@ -35,6 +35,7 @@ import android.util.TypedValue;
import org.solovyev.android.calculator.core.R;
import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.calculator.view.TextHighlighter;
import org.solovyev.android.calculator.text.TextProcessorEditorResult;
import org.solovyev.android.view.AutoResizeTextView;
import javax.annotation.Nonnull;
@ -59,7 +60,7 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements
*/
@Nonnull
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false);
private final static TextProcessor<TextProcessorEditorResult, String> textHighlighter = new TextHighlighter(Color.WHITE, false);
/*
**********************************************************************
@ -169,7 +170,7 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements
//Log.d(this.getClass().getName(), text);
try {
final TextHighlighter.Result processedText = textHighlighter.process(text);
final TextProcessorEditorResult processedText = textHighlighter.process(text);
text = processedText.toString();
result = Html.fromHtml(text);
} catch (CalculatorParseException e) {

View File

@ -23,44 +23,26 @@
package org.solovyev.android.calculator;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.os.Build;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextMenu;
import android.widget.EditText;
import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.calculator.view.TextHighlighter;
import org.solovyev.android.prefs.BooleanPreference;
import org.solovyev.common.collections.Collections;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 9/17/11
* Time: 12:25 AM
*/
public class AndroidCalculatorEditorView extends EditText implements SharedPreferences.OnSharedPreferenceChangeListener, CalculatorEditorView {
@Nonnull
private static final BooleanPreference colorDisplay = BooleanPreference.of("org.solovyev.android.calculator.CalculatorModel_color_display", true);
public class AndroidCalculatorEditorView extends EditText implements CalculatorEditorView {
private volatile boolean initialized = false;
private boolean highlightText = true;
@Nonnull
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false);
@SuppressWarnings("UnusedDeclaration")
@Nonnull
private volatile CalculatorEditorViewState viewState = CalculatorEditorViewStateImpl.newDefaultInstance();
@ -113,57 +95,15 @@ public class AndroidCalculatorEditorView extends EditText implements SharedPrefe
menu.removeItem(android.R.id.selectAll);
}
@Nullable
private CharSequence prepareText(@Nonnull String text, boolean highlightText) {
CharSequence result;
if (highlightText) {
try {
final TextHighlighter.Result processesText = textHighlighter.process(text);
assert processesText.getOffset() == 0;
result = Html.fromHtml(processesText.toString());
} catch (CalculatorParseException e) {
// set raw text
result = text;
Log.e(this.getClass().getName(), e.getMessage(), e);
}
} else {
result = text;
}
return result;
}
public boolean isHighlightText() {
return highlightText;
}
public void setHighlightText(boolean highlightText) {
this.highlightText = highlightText;
//this.highlightText = highlightText;
Locator.getInstance().getEditor().updateViewState();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
if (colorDisplay.getKey().equals(key)) {
this.setHighlightText(colorDisplay.getPreference(preferences));
}
}
public synchronized void init(@Nonnull Context context) {
public synchronized void init() {
if (!initialized) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
preferences.registerOnSharedPreferenceChangeListener(this);
this.addTextChangedListener(new TextWatcherImpl());
onSharedPreferenceChanged(preferences, colorDisplay.getKey());
initialized = true;
}
}
@ -172,8 +112,6 @@ public class AndroidCalculatorEditorView extends EditText implements SharedPrefe
public void setState(@Nonnull final CalculatorEditorViewState viewState) {
synchronized (this) {
final CharSequence text = prepareText(viewState.getText(), highlightText);
uiHandler.post(new Runnable() {
@Override
public void run() {
@ -182,7 +120,7 @@ public class AndroidCalculatorEditorView extends EditText implements SharedPrefe
try {
editorView.viewStateChange = true;
editorView.viewState = viewState;
editorView.setText(text, BufferType.EDITABLE);
editorView.setText(viewState.getTextAsCharSequence(), BufferType.EDITABLE);
final int selection = CalculatorEditorImpl.correctSelection(viewState.getSelection(), editorView.getText());
editorView.setSelection(selection);
} finally {

View File

@ -84,6 +84,7 @@ public final class CalculatorPreferences {
public static final Preference<Boolean> autoOrientation = BooleanPreference.of("autoOrientation", true);
public static final Preference<Boolean> hideNumeralBaseDigits = BooleanPreference.of("hideNumeralBaseDigits", true);
public static final Preference<Boolean> preventScreenFromFading = BooleanPreference.of("preventScreenFromFading", true);
public static final Preference<Boolean> colorDisplay = BooleanPreference.of("org.solovyev.android.calculator.CalculatorModel_color_display", true);
@Nonnull
public static Theme getTheme(@Nonnull SharedPreferences preferences) {

View File

@ -66,6 +66,12 @@ public final class ParcelableCalculatorEditorViewState implements CalculatorEdit
return viewState.getText();
}
@Nonnull
@Override
public CharSequence getTextAsCharSequence() {
return getText();
}
@Override
public int getSelection() {
return viewState.getSelection();

View File

@ -0,0 +1,75 @@
package org.solovyev.android.calculator.view;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.text.Html;
import android.util.Log;
import org.solovyev.android.calculator.CalculatorParseException;
import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.calculator.text.TextProcessorEditorResult;
import javax.annotation.Nonnull;
import static org.solovyev.android.calculator.CalculatorPreferences.Gui.colorDisplay;
import static org.solovyev.android.calculator.view.TextHighlighter.WHITE;
/**
* User: serso
* Date: 6/27/13
* Time: 6:11 PM
*/
public final class EditorTextProcessor implements TextProcessor<TextProcessorEditorResult, String>, SharedPreferences.OnSharedPreferenceChangeListener {
private boolean highlightText = true;
private final TextProcessor<TextProcessorEditorResult, String> textHighlighter = new TextHighlighter(WHITE, true);
public EditorTextProcessor() {
}
public void init(@Nonnull Context context) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
preferences.registerOnSharedPreferenceChangeListener(this);
onSharedPreferenceChanged(preferences, colorDisplay.getKey());
}
@Nonnull
@Override
public TextProcessorEditorResult process(@Nonnull String text) throws CalculatorParseException {
TextProcessorEditorResult result;
if (highlightText) {
try {
final TextProcessorEditorResult processesText = textHighlighter.process(text);
result = new TextProcessorEditorResult(Html.fromHtml(processesText.toString()), processesText.getOffset());
} catch (CalculatorParseException e) {
// set raw text
result = new TextProcessorEditorResult(text, 0);
Log.e(this.getClass().getName(), e.getMessage(), e);
}
} else {
result = new TextProcessorEditorResult(text, 0);
}
return result;
}
public boolean isHighlightText() {
return highlightText;
}
public void setHighlightText(boolean highlightText) {
this.highlightText = highlightText;
}
@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
if (colorDisplay.getKey().equals(key)) {
this.setHighlightText(colorDisplay.getPreference(preferences));
}
}
}

View File

@ -22,14 +22,14 @@
package org.solovyev.android.calculator.view;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.calculator.text.TextProcessorEditorResult;
import org.solovyev.common.MutableObject;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
@ -38,7 +38,9 @@ import java.util.Map;
* Date: 10/12/11
* Time: 9:47 PM
*/
public class TextHighlighter implements TextProcessor<TextHighlighter.Result, String> {
public class TextHighlighter implements TextProcessor<TextProcessorEditorResult, String> {
public static final int WHITE = -1;
private static final Map<String, String> nbFontAttributes = new HashMap<String, String>();
@ -46,54 +48,6 @@ public class TextHighlighter implements TextProcessor<TextHighlighter.Result, St
nbFontAttributes.put("color", "#008000");
}
public static class Result implements CharSequence {
@Nonnull
private final CharSequence charSequence;
@Nullable
private String string;
private final int offset;
public Result(@Nonnull CharSequence charSequence, int offset) {
this.charSequence = charSequence;
this.offset = offset;
}
@Override
public int length() {
return charSequence.length();
}
@Override
public char charAt(int i) {
return charSequence.charAt(i);
}
@Override
public CharSequence subSequence(int i, int i1) {
return charSequence.subSequence(i, i1);
}
@Override
public String toString() {
if (string == null) {
string = charSequence.toString();
}
return string;
}
@Nonnull
public CharSequence getCharSequence() {
return charSequence;
}
public int getOffset() {
return offset;
}
}
private final int color;
private final int colorRed;
private final int colorGreen;
@ -113,7 +67,7 @@ public class TextHighlighter implements TextProcessor<TextHighlighter.Result, St
@Nonnull
@Override
public Result process(@Nonnull String text) throws CalculatorParseException {
public TextProcessorEditorResult process(@Nonnull String text) throws CalculatorParseException {
final CharSequence result;
int maxNumberOfOpenGroupSymbols = 0;
@ -186,20 +140,17 @@ public class TextHighlighter implements TextProcessor<TextHighlighter.Result, St
final StringBuilder text2 = new StringBuilder(text1.length());
final CharSequence s = text1;
int i = processBracketGroup(text2, s, 0, 0, maxNumberOfOpenGroupSymbols);
for (; i < s.length(); i++) {
text2.append(s.charAt(i));
int i = processBracketGroup(text2, text1, 0, 0, maxNumberOfOpenGroupSymbols);
for (; i < text1.length(); i++) {
text2.append(text1.charAt(i));
}
//Log.d(AndroidCalculatorEditorView.class.getName(), text2.toString());
result = text2.toString();
} else {
result = text1.toString();
}
return new Result(result, resultOffset);
return new TextProcessorEditorResult(result, resultOffset);
}
private int processHighlightedText(@Nonnull StringBuilder result, int i, @Nonnull String match, @Nonnull String tag, @Nullable Map<String, String> tagAttributes) {

View File

@ -31,35 +31,26 @@ import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import org.solovyev.android.Views;
import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.external.AndroidExternalListenersContainer;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.Views;
import org.solovyev.android.calculator.CalculatorDisplayViewState;
import org.solovyev.android.calculator.CalculatorEditorViewState;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.external.AndroidExternalListenersContainer;
import org.solovyev.android.calculator.external.DefaultExternalCalculatorIntentHandler;
import org.solovyev.android.calculator.external.ExternalCalculatorIntentHandler;
import org.solovyev.android.calculator.external.ExternalCalculatorStateUpdater;
import static org.solovyev.android.calculator.external.AndroidExternalListenersContainer.INIT_ACTION;
/**
* User: serso
* Date: 11/20/12
* Time: 9:42 PM
*/
public class CalculatorOnscreenService extends Service implements ExternalCalculatorStateUpdater, OnscreenViewListener {
public class CalculatorOnscreenService extends Service implements OnscreenViewListener, CalculatorEventListener {
private static final int NOTIFICATION_ID = 9031988; // my birthday =)
@Nonnull
private final ExternalCalculatorIntentHandler intentHandler = new DefaultExternalCalculatorIntentHandler(this);
public static final Class<CalculatorOnscreenBroadcastReceiver> INTENT_LISTENER_CLASS = CalculatorOnscreenBroadcastReceiver.class;
@Nullable
private static String cursorColor;
@Nonnull
private CalculatorOnscreenView view;
@ -96,7 +87,7 @@ public class CalculatorOnscreenService extends Service implements ExternalCalcul
final int width = Math.min(width0, height0);
final int height = Math.max(width0, height0);
view = CalculatorOnscreenView.newInstance(this, CalculatorOnscreenViewState.newInstance(width, height, -1, -1), getCursorColor(this), this);
view = CalculatorOnscreenView.newInstance(this, CalculatorOnscreenViewState.newInstance(width, height, -1, -1), this);
view.show();
startCalculatorListening();
@ -110,7 +101,7 @@ public class CalculatorOnscreenService extends Service implements ExternalCalcul
}
private void startCalculatorListening() {
Locator.getInstance().getExternalListenersContainer().addExternalListener(getIntentListenerClass());
Locator.getInstance().getCalculator().addCalculatorEventListener(this);
}
@Nonnull
@ -119,7 +110,7 @@ public class CalculatorOnscreenService extends Service implements ExternalCalcul
}
private void stopCalculatorListening() {
Locator.getInstance().getExternalListenersContainer().removeExternalListener(getIntentListenerClass());
Locator.getInstance().getCalculator().removeCalculatorEventListener(this);
}
@Override
@ -131,20 +122,6 @@ public class CalculatorOnscreenService extends Service implements ExternalCalcul
super.onDestroy();
}
@Override
public void updateState(@Nonnull Context context, @Nonnull CalculatorEditorViewState editorState, @Nonnull CalculatorDisplayViewState displayState) {
view.updateDisplayState(displayState);
view.updateEditorState(editorState);
}
@Nonnull
private static String getCursorColor(@Nonnull Context context) {
if (cursorColor == null) {
cursorColor = Integer.toHexString(context.getResources().getColor(R.color.cpp_onscreen_cursor_color)).substring(2);
}
return cursorColor;
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
@ -182,16 +159,11 @@ public class CalculatorOnscreenService extends Service implements ExternalCalcul
showNotification();
}
}
if (viewCreated) {
intentHandler.onIntent(this, intent);
}
}
}
private boolean isInitIntent(@Nonnull Intent intent) {
return intent.getAction().equals(AndroidExternalListenersContainer.INIT_ACTION);
return intent.getAction().equals(INIT_ACTION);
}
private void hideNotification() {
@ -225,7 +197,7 @@ public class CalculatorOnscreenService extends Service implements ExternalCalcul
}
public static void showNotification(@Nonnull Context context) {
final Intent intent = new Intent(AndroidExternalListenersContainer.INIT_ACTION);
final Intent intent = new Intent(INIT_ACTION);
intent.setClass(context, getIntentListenerClass());
context.sendBroadcast(intent);
}
@ -237,10 +209,23 @@ public class CalculatorOnscreenService extends Service implements ExternalCalcul
@Nonnull
private static Intent createShowOnscreenViewIntent(@Nonnull Context context) {
final Intent intent = new Intent(AndroidExternalListenersContainer.INIT_ACTION);
final Intent intent = new Intent(INIT_ACTION);
intent.setClass(context, getIntentListenerClass());
intent.putExtra(AndroidExternalListenersContainer.INIT_ACTION_CREATE_VIEW_EXTRA, true);
return intent;
}
@Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) {
switch (calculatorEventType) {
case editor_state_changed:
case editor_state_changed_light:
view.updateEditorState(((CalculatorEditorChangeEventData) data).getNewValue());
break;
case display_state_changed:
view.updateDisplayState(((CalculatorDisplayChangeEventData) data).getNewValue());
break;
}
}
}

View File

@ -33,13 +33,12 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import org.solovyev.android.calculator.*;
import org.solovyev.android.prefs.Preference;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.*;
import org.solovyev.android.prefs.Preference;
/**
* User: serso
* Date: 11/21/12
@ -95,9 +94,6 @@ public class CalculatorOnscreenView {
@Nonnull
private CalculatorOnscreenViewState state = CalculatorOnscreenViewState.newDefaultState();
@Nonnull
private String cursorColor;
@Nullable
private OnscreenViewListener viewListener;
@ -133,13 +129,11 @@ public class CalculatorOnscreenView {
public static CalculatorOnscreenView newInstance(@Nonnull Context context,
@Nonnull CalculatorOnscreenViewState state,
@Nonnull String cursorColor,
@Nullable OnscreenViewListener viewListener) {
final CalculatorOnscreenView result = new CalculatorOnscreenView();
result.root = View.inflate(context, R.layout.onscreen_layout, null);
result.context = context;
result.cursorColor = cursorColor;
result.viewListener = viewListener;
final CalculatorOnscreenViewState persistedState = readState(context);
@ -222,7 +216,7 @@ public class CalculatorOnscreenView {
displayView.init(this.context, false);
editorView = (AndroidCalculatorEditorView) root.findViewById(R.id.calculator_editor);
editorView.init(this.context);
editorView.init();
final View onscreenFoldButton = root.findViewById(R.id.onscreen_fold_button);
onscreenFoldButton.setOnClickListener(new View.OnClickListener() {

View File

@ -173,13 +173,13 @@ abstract class AbstractCalculatorWidgetProvider extends AppWidgetProvider implem
}
private void updateEditorState(@Nonnull Context context, @Nonnull RemoteViews views, @Nonnull CalculatorEditorViewState editorState) {
String text = editorState.getText();
final CharSequence text = editorState.getTextAsCharSequence();
CharSequence newText = text;
int selection = editorState.getSelection();
if (selection >= 0 && selection <= text.length()) {
// inject cursor
newText = Html.fromHtml(text.substring(0, selection) + "<font color=\"#" + getCursorColor(context) + "\">|</font>" + text.substring(selection));
newText = Html.fromHtml(text.subSequence(0, selection) + "<font color=\"#" + getCursorColor(context) + "\">|</font>" + text.subSequence(selection, text.length()));
}
Locator.getInstance().getNotifier().showDebugMessage(TAG, "New editor state: " + text);
views.setTextViewText(R.id.calculator_editor, newText);

View File

@ -29,15 +29,13 @@ import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import jscl.NumeralBase;
import jscl.math.Generic;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.history.CalculatorHistoryState;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.common.history.HistoryAction;
import org.solovyev.common.msg.Message;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
/**
@ -81,7 +79,7 @@ public class AndroidCalculator implements Calculator, CalculatorEventListener, S
}
public void setEditor(@Nonnull Context context, @Nonnull AndroidCalculatorEditorView editorView) {
editorView.init(context);
editorView.init();
Locator.getInstance().getEditor().setView(editorView);
}

View File

@ -31,13 +31,9 @@ import android.util.Log;
import net.robotmedia.billing.BillingController;
import net.robotmedia.billing.helper.DefaultBillingObserver;
import net.robotmedia.billing.model.BillingDB;
import org.acra.ACRA;
import org.acra.ReportingInteractionMode;
import org.acra.annotation.ReportsCrashes;
import javax.annotation.Nonnull;
import org.solovyev.android.Android;
import org.solovyev.android.App;
import org.solovyev.android.ServiceLocator;
@ -48,8 +44,10 @@ import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
import org.solovyev.android.calculator.onscreen.CalculatorOnscreenStartActivity;
import org.solovyev.android.calculator.plot.AndroidCalculatorPlotter;
import org.solovyev.android.calculator.plot.CalculatorPlotterImpl;
import org.solovyev.android.calculator.view.EditorTextProcessor;
import org.solovyev.common.msg.MessageType;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;
@ -137,6 +135,8 @@ public class CalculatorApplication extends android.app.Application implements Sh
final AndroidCalculator calculator = new AndroidCalculator(this);
final EditorTextProcessor editorTextProcessor = new EditorTextProcessor();
Locator.getInstance().init(calculator,
new AndroidCalculatorEngine(this),
new AndroidCalculatorClipboard(this),
@ -146,7 +146,10 @@ public class CalculatorApplication extends android.app.Application implements Sh
new AndroidCalculatorPreferenceService(this),
new AndroidCalculatorKeyboard(this, new CalculatorKeyboardImpl(calculator)),
new AndroidExternalListenersContainer(calculator),
new AndroidCalculatorPlotter(this, new CalculatorPlotterImpl(calculator)));
new AndroidCalculatorPlotter(this, new CalculatorPlotterImpl(calculator)),
editorTextProcessor);
editorTextProcessor.init(this);
listeners.add(new CalculatorActivityLauncher());
for (CalculatorEventListener listener : listeners) {

View File

@ -41,7 +41,7 @@ import javax.annotation.Nullable;
public class CalculatorTestUtils {
public static void staticSetUp(@Nullable Context context) throws Exception {
Locator.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(CalculatorKeyboard.class), Mockito.mock(CalculatorExternalListenersContainer.class), Mockito.mock(CalculatorPlotter.class));
Locator.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(CalculatorKeyboard.class), Mockito.mock(CalculatorExternalListenersContainer.class), Mockito.mock(CalculatorPlotter.class), null);
Locator.getInstance().getEngine().init();
if (context != null) {
@ -51,7 +51,7 @@ public class CalculatorTestUtils {
public static void initViews(@Nonnull Context context) {
final AndroidCalculatorEditorView editor = new AndroidCalculatorEditorView(context);
editor.init(context);
editor.init();
Locator.getInstance().getEditor().setView(editor);
final AndroidCalculatorDisplayView display = new AndroidCalculatorDisplayView(context);

View File

@ -22,11 +22,11 @@
package org.solovyev.android.calculator;
import org.solovyev.common.gui.CursorControl;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.common.gui.CursorControl;
/**
* User: Solovyev_S
* Date: 21.09.12
@ -34,6 +34,9 @@ import org.solovyev.common.gui.CursorControl;
*/
public interface CalculatorEditor extends CalculatorEventListener {
@Nonnull
String TAG = CalculatorEditor.class.getSimpleName();
void setView(@Nullable CalculatorEditorView view);
@Nonnull

View File

@ -22,10 +22,41 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
/**
* User: Solovyev_S
* Date: 21.09.12
* Time: 13:46
*/
public interface CalculatorEditorChangeEventData extends Change<CalculatorEditorViewState> {
public final class CalculatorEditorChangeEventData implements Change<CalculatorEditorViewState> {
@Nonnull
private CalculatorEditorViewState oldState;
@Nonnull
private CalculatorEditorViewState newState;
private CalculatorEditorChangeEventData(@Nonnull CalculatorEditorViewState oldState,
@Nonnull CalculatorEditorViewState newState) {
this.oldState = oldState;
this.newState = newState;
}
public static CalculatorEditorChangeEventData newChangeEventData(@Nonnull CalculatorEditorViewState oldState,
@Nonnull CalculatorEditorViewState newState) {
return new CalculatorEditorChangeEventData(oldState, newState);
}
@Nonnull
@Override
public CalculatorEditorViewState getOldValue() {
return this.oldState;
}
@Nonnull
@Override
public CalculatorEditorViewState getNewValue() {
return this.newState;
}
}

View File

@ -1,57 +0,0 @@
/*
* Copyright 2013 serso aka se.solovyev
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Contact details
*
* Email: se.solovyev@gmail.com
* Site: http://se.solovyev.org
*/
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
/**
* User: Solovyev_S
* Date: 21.09.12
* Time: 13:46
*/
public class CalculatorEditorChangeEventDataImpl implements CalculatorEditorChangeEventData {
@Nonnull
private CalculatorEditorViewState oldState;
@Nonnull
private CalculatorEditorViewState newState;
public CalculatorEditorChangeEventDataImpl(@Nonnull CalculatorEditorViewState oldState,
@Nonnull CalculatorEditorViewState newState) {
this.oldState = oldState;
this.newState = newState;
}
@Nonnull
@Override
public CalculatorEditorViewState getOldValue() {
return this.oldState;
}
@Nonnull
@Override
public CalculatorEditorViewState getNewValue() {
return this.newState;
}
}

View File

@ -22,13 +22,19 @@
package org.solovyev.android.calculator;
import org.solovyev.android.calculator.history.CalculatorHistoryState;
import org.solovyev.android.calculator.history.EditorHistoryState;
import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.calculator.text.TextProcessorEditorResult;
import org.solovyev.common.gui.CursorControl;
import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.solovyev.android.calculator.history.CalculatorHistoryState;
import org.solovyev.android.calculator.history.EditorHistoryState;
import org.solovyev.common.gui.CursorControl;
import org.solovyev.common.text.Strings;
import static org.solovyev.android.calculator.CalculatorEditorChangeEventData.newChangeEventData;
import static org.solovyev.android.calculator.CalculatorEventType.editor_state_changed;
import static org.solovyev.android.calculator.CalculatorEventType.editor_state_changed_light;
/**
* User: Solovyev_S
@ -55,8 +61,12 @@ public class CalculatorEditorImpl implements CalculatorEditor {
@Nonnull
private final CursorControlAdapter cursorControlAdapter = new CursorControlAdapter(this);
public CalculatorEditorImpl(@Nonnull Calculator calculator) {
@Nullable
private final TextProcessor<TextProcessorEditorResult, String> textProcessor;
public CalculatorEditorImpl(@Nonnull Calculator calculator, @Nullable TextProcessor<TextProcessorEditorResult, String> textProcessor) {
this.calculator = calculator;
this.textProcessor = textProcessor;
this.calculator.addCalculatorEventListener(this);
this.lastEventHolder = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
}
@ -89,6 +99,14 @@ public class CalculatorEditorImpl implements CalculatorEditor {
}
private void setViewState(@Nonnull CalculatorEditorViewState newViewState, boolean majorChanges) {
if (textProcessor != null) {
try {
final TextProcessorEditorResult result = textProcessor.process(newViewState.getText());
newViewState = CalculatorEditorViewStateImpl.newInstance(result.getCharSequence(), newViewState.getSelection() + result.getOffset());
} catch (CalculatorParseException e) {
Locator.getInstance().getLogger().error(TAG, e.getMessage(), e);
}
}
synchronized (viewLock) {
final CalculatorEditorViewState oldViewState = this.lastViewState;
@ -97,11 +115,17 @@ public class CalculatorEditorImpl implements CalculatorEditor {
this.view.setState(newViewState);
}
if (majorChanges) {
calculator.fireCalculatorEvent(CalculatorEventType.editor_state_changed, new CalculatorEditorChangeEventDataImpl(oldViewState, newViewState));
} else {
calculator.fireCalculatorEvent(CalculatorEventType.editor_state_changed_light, new CalculatorEditorChangeEventDataImpl(oldViewState, newViewState));
}
fireStateChangedEvent(majorChanges, oldViewState, newViewState);
}
}
private void fireStateChangedEvent(boolean majorChanges, @Nonnull CalculatorEditorViewState oldViewState, @Nonnull CalculatorEditorViewState newViewState) {
assert Thread.holdsLock(viewLock);
if (majorChanges) {
calculator.fireCalculatorEvent(editor_state_changed, newChangeEventData(oldViewState, newViewState));
} else {
calculator.fireCalculatorEvent(editor_state_changed_light, newChangeEventData(oldViewState, newViewState));
}
}

View File

@ -36,5 +36,8 @@ public interface CalculatorEditorViewState extends Serializable {
@Nonnull
String getText();
@Nonnull
CharSequence getTextAsCharSequence();
int getSelection();
}

View File

@ -32,7 +32,7 @@ import javax.annotation.Nonnull;
public class CalculatorEditorViewStateImpl implements CalculatorEditorViewState {
@Nonnull
private String text = "";
private CharSequence text = "";
private int selection = 0;
@ -47,6 +47,12 @@ public class CalculatorEditorViewStateImpl implements CalculatorEditorViewState
@Nonnull
@Override
public String getText() {
return this.text.toString();
}
@Nonnull
@Override
public CharSequence getTextAsCharSequence() {
return this.text;
}
@ -70,7 +76,7 @@ public class CalculatorEditorViewStateImpl implements CalculatorEditorViewState
}
@Nonnull
public static CalculatorEditorViewState newInstance(@Nonnull String text, int selection) {
public static CalculatorEditorViewState newInstance(@Nonnull CharSequence text, int selection) {
final CalculatorEditorViewStateImpl result = new CalculatorEditorViewStateImpl();
result.text = text;
result.selection = selection;

View File

@ -22,11 +22,14 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import org.solovyev.android.calculator.external.CalculatorExternalListenersContainer;
import org.solovyev.android.calculator.history.CalculatorHistory;
import org.solovyev.android.calculator.plot.CalculatorPlotter;
import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.calculator.text.TextProcessorEditorResult;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: Solovyev_S
@ -44,7 +47,8 @@ public interface CalculatorLocator {
@Nonnull CalculatorPreferenceService preferenceService,
@Nonnull CalculatorKeyboard keyboard,
@Nonnull CalculatorExternalListenersContainer externalListenersContainer,
@Nonnull CalculatorPlotter plotter);
@Nonnull CalculatorPlotter plotter,
@Nullable TextProcessor<TextProcessorEditorResult, String> editorTextProcessor);
@Nonnull
Calculator getCalculator();

View File

@ -25,8 +25,11 @@ package org.solovyev.android.calculator;
import org.solovyev.android.calculator.external.CalculatorExternalListenersContainer;
import org.solovyev.android.calculator.history.CalculatorHistory;
import org.solovyev.android.calculator.plot.CalculatorPlotter;
import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.calculator.text.TextProcessorEditorResult;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: Solovyev_S
@ -87,7 +90,8 @@ public class Locator implements CalculatorLocator {
@Nonnull CalculatorPreferenceService preferenceService,
@Nonnull CalculatorKeyboard keyboard,
@Nonnull CalculatorExternalListenersContainer externalListenersContainer,
@Nonnull CalculatorPlotter plotter) {
@Nonnull CalculatorPlotter plotter,
@Nullable TextProcessor<TextProcessorEditorResult, String> editorTextProcessor) {
this.calculator = calculator;
this.calculatorEngine = engine;
@ -99,7 +103,7 @@ public class Locator implements CalculatorLocator {
this.calculatorExternalListenersContainer = externalListenersContainer;
this.calculatorPlotter = plotter;
calculatorEditor = new CalculatorEditorImpl(this.calculator);
calculatorEditor = new CalculatorEditorImpl(this.calculator, editorTextProcessor);
calculatorDisplay = new CalculatorDisplayImpl(this.calculator);
calculatorKeyboard = keyboard;
}

View File

@ -0,0 +1,58 @@
package org.solovyev.android.calculator.text;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 6/27/13
* Time: 8:07 PM
*/
public final class TextProcessorEditorResult implements CharSequence {
@Nonnull
private final CharSequence charSequence;
@Nullable
private String string;
private final int offset;
public TextProcessorEditorResult(@Nonnull CharSequence charSequence, int offset) {
this.charSequence = charSequence;
this.offset = offset;
}
@Override
public int length() {
return charSequence.length();
}
@Override
public char charAt(int i) {
return charSequence.charAt(i);
}
@Override
public CharSequence subSequence(int i, int i1) {
return charSequence.subSequence(i, i1);
}
@Nonnull
@Override
public String toString() {
if (string == null) {
string = charSequence.toString();
}
return string;
}
@Nonnull
public CharSequence getCharSequence() {
return charSequence;
}
public int getOffset() {
return offset;
}
}

View File

@ -35,7 +35,7 @@ import org.solovyev.android.calculator.plot.CalculatorPlotter;
public class AbstractCalculatorTest {
protected void setUp() throws Exception {
Locator.getInstance().init(new CalculatorImpl(), CalculatorTestUtils.newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(CalculatorKeyboard.class), Mockito.mock(CalculatorExternalListenersContainer.class), Mockito.mock(CalculatorPlotter.class));
Locator.getInstance().init(new CalculatorImpl(), CalculatorTestUtils.newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(CalculatorKeyboard.class), Mockito.mock(CalculatorExternalListenersContainer.class), Mockito.mock(CalculatorPlotter.class), null);
Locator.getInstance().getEngine().init();
}

View File

@ -22,12 +22,12 @@
package org.solovyev.android.calculator;
import javax.annotation.Nonnull;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import javax.annotation.Nonnull;
/**
* User: Solovyev_S
* Date: 21.09.12
@ -41,7 +41,7 @@ public class CalculatorEditorImplTest extends AbstractCalculatorTest {
@Before
public void setUp() throws Exception {
super.setUp();
this.calculatorEditor = new CalculatorEditorImpl(Locator.getInstance().getCalculator());
this.calculatorEditor = new CalculatorEditorImpl(Locator.getInstance().getCalculator(), null);
}
@Test

View File

@ -49,7 +49,7 @@ public class CalculatorTestUtils {
public static final int TIMEOUT = 15;
public static void staticSetUp() throws Exception {
Locator.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(CalculatorKeyboard.class), Mockito.mock(CalculatorExternalListenersContainer.class), Mockito.mock(CalculatorPlotter.class));
Locator.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(CalculatorKeyboard.class), Mockito.mock(CalculatorExternalListenersContainer.class), Mockito.mock(CalculatorPlotter.class), null);
Locator.getInstance().getEngine().init();
}