Calculator editor

This commit is contained in:
serso 2012-09-21 12:14:55 +04:00
parent 9f4b0ba4f9
commit 30fbc24f81
24 changed files with 1608 additions and 1337 deletions

View File

@ -0,0 +1,19 @@
package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* User: Solovyev_S
* Date: 21.09.12
* Time: 11:47
*/
public interface CalculatorEditor extends CalculatorEventListener/*, CursorControl*/ {
void setView(@Nullable CalculatorEditorView view);
@NotNull
CalculatorEditorViewState getViewState();
void setViewState(@NotNull CalculatorEditorViewState viewState);
}

View File

@ -0,0 +1,87 @@
package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* User: Solovyev_S
* Date: 21.09.12
* Time: 11:53
*/
public class CalculatorEditorImpl implements CalculatorEditor {
@Nullable
private CalculatorEditorView view;
@NotNull
private final Object viewLock = new Object();
@NotNull
private CalculatorEditorViewState lastViewState = CalculatorEditorViewStateImpl.newDefaultInstance();
@Override
public void setView(@Nullable CalculatorEditorView view) {
synchronized (viewLock) {
this.view = view;
if ( view != null ) {
view.setState(lastViewState);
}
}
}
@NotNull
@Override
public CalculatorEditorViewState getViewState() {
return lastViewState;
}
@Override
public void setViewState(@NotNull CalculatorEditorViewState viewState) {
synchronized (viewLock) {
this.lastViewState = viewState;
if (this.view != null) {
this.view.setState(viewState);
}
}
}
@Override
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData,
@NotNull CalculatorEventType calculatorEventType,
@Nullable Object data) {
//To change body of implemented methods use File | Settings | File Templates.
}
public void setCursorOnStart() {
synchronized (viewLock) {
newSelectionViewState(0);
}
}
private void newSelectionViewState(int newSelection) {
setViewState(CalculatorEditorViewStateImpl.newSelection(this.lastViewState, newSelection));
}
public void setCursorOnEnd() {
synchronized (viewLock) {
newSelectionViewState(this.lastViewState.getText().length());
}
}
public void moveCursorLeft() {
synchronized (viewLock) {
if (this.lastViewState.getSelection() > 0) {
newSelectionViewState(this.lastViewState.getSelection() - 1);
}
}
}
public void moveCursorRight() {
synchronized (viewLock) {
if (this.lastViewState.getSelection() < this.lastViewState.getText().length()) {
newSelectionViewState(this.lastViewState.getSelection() + 1);
}
}
}
}

View File

@ -0,0 +1,13 @@
package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull;
/**
* User: Solovyev_S
* Date: 21.09.12
* Time: 11:48
*/
public interface CalculatorEditorView {
void setState(@NotNull CalculatorEditorViewState viewState);
}

View File

@ -0,0 +1,16 @@
package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull;
/**
* User: Solovyev_S
* Date: 21.09.12
* Time: 11:48
*/
public interface CalculatorEditorViewState {
@NotNull
String getText();
int getSelection();
}

View File

@ -0,0 +1,49 @@
package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull;
/**
* User: Solovyev_S
* Date: 21.09.12
* Time: 12:02
*/
public class CalculatorEditorViewStateImpl implements CalculatorEditorViewState {
@NotNull
private String text = "";
private int selection = 0;
private CalculatorEditorViewStateImpl() {
}
public CalculatorEditorViewStateImpl(@NotNull CalculatorEditorViewState viewState) {
this.text = viewState.getText();
this.selection = viewState.getSelection();
}
@NotNull
@Override
public String getText() {
return this.text;
}
@Override
public int getSelection() {
return this.selection;
}
@NotNull
public static CalculatorEditorViewState newDefaultInstance() {
return new CalculatorEditorViewStateImpl();
}
@NotNull
public static CalculatorEditorViewState newSelection(@NotNull CalculatorEditorViewState viewState, int newSelection) {
final CalculatorEditorViewStateImpl result = new CalculatorEditorViewStateImpl(viewState);
result.selection = newSelection;
return result;
}
}

View File

@ -52,7 +52,12 @@ public class CalculatorEvaluationEventDataImpl implements CalculatorEvaluationEv
} }
@Override @Override
public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) { public boolean isAfter(@NotNull CalculatorEventDataId that) {
return calculatorEventData.isAfter(calculatorEventDataId); return calculatorEventData.isAfter(that);
}
@Override
public boolean isSameSequence(@NotNull CalculatorEventDataId that) {
return this.calculatorEventData.isSameSequence(that);
} }
} }

View File

@ -17,5 +17,7 @@ public interface CalculatorEventDataId {
@Nullable @Nullable
Long getSequenceId(); Long getSequenceId();
boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId); boolean isAfter(@NotNull CalculatorEventDataId that);
boolean isSameSequence(@NotNull CalculatorEventDataId that);
} }

View File

@ -37,8 +37,13 @@ class CalculatorEventDataIdImpl implements CalculatorEventDataId {
} }
@Override @Override
public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) { public boolean isAfter(@NotNull CalculatorEventDataId that) {
return this.eventId > calculatorEventDataId.getEventId(); return this.eventId > that.getEventId();
}
@Override
public boolean isSameSequence(@NotNull CalculatorEventDataId that) {
return this.sequenceId != null && this.sequenceId.equals(that.getSequenceId());
} }
@Override @Override

View File

@ -34,8 +34,13 @@ class CalculatorEventDataImpl implements CalculatorEventData {
} }
@Override @Override
public boolean isAfter(@NotNull CalculatorEventDataId calculatorEventDataId) { public boolean isAfter(@NotNull CalculatorEventDataId that) {
return this.calculatorEventDataId.isAfter(calculatorEventDataId); return this.calculatorEventDataId.isAfter(that);
}
@Override
public boolean isSameSequence(@NotNull CalculatorEventDataId that) {
return this.calculatorEventDataId.isSameSequence(that);
} }
@Override @Override

View File

@ -18,5 +18,8 @@ public interface CalculatorLocator {
@NotNull @NotNull
CalculatorDisplay getCalculatorDisplay(); CalculatorDisplay getCalculatorDisplay();
@NotNull
CalculatorEditor getCalculatorEditor();
void setCalculatorEngine(@NotNull JCalculatorEngine calculatorEngine); void setCalculatorEngine(@NotNull JCalculatorEngine calculatorEngine);
} }

View File

@ -13,10 +13,13 @@ public class CalculatorLocatorImpl implements CalculatorLocator {
private JCalculatorEngine calculatorEngine; private JCalculatorEngine calculatorEngine;
@NotNull @NotNull
private CalculatorDisplay calculatorDisplay = new CalculatorDisplayImpl(); private final CalculatorDisplay calculatorDisplay = new CalculatorDisplayImpl();
@NotNull @NotNull
private Calculator calculator = new CalculatorImpl(); private final CalculatorEditor calculatorEditor = new CalculatorEditorImpl();
@NotNull
private final Calculator calculator = new CalculatorImpl();
@NotNull @NotNull
private static final CalculatorLocator instance = new CalculatorLocatorImpl(); private static final CalculatorLocator instance = new CalculatorLocatorImpl();
@ -51,4 +54,10 @@ public class CalculatorLocatorImpl implements CalculatorLocator {
public CalculatorDisplay getCalculatorDisplay() { public CalculatorDisplay getCalculatorDisplay() {
return calculatorDisplay; return calculatorDisplay;
} }
@NotNull
@Override
public CalculatorEditor getCalculatorEditor() {
return calculatorEditor;
}
} }

View File

@ -50,17 +50,15 @@ public class CalculatorDisplayHistoryState implements Cloneable {
} }
@NotNull @NotNull
public static CalculatorDisplayHistoryState newInstance(@NotNull CalculatorDisplay display) { public static CalculatorDisplayHistoryState newInstance(@NotNull CalculatorDisplayViewState viewState) {
final CalculatorDisplayHistoryState result = new CalculatorDisplayHistoryState(); final CalculatorDisplayHistoryState result = new CalculatorDisplayHistoryState();
result.editorState = EditorHistoryState.newInstance(display.getViewState()); result.editorState = EditorHistoryState.newInstance(viewState);
final CalculatorDisplayViewState displayViewState = display.getViewState(); result.valid = viewState.isValid();
result.jsclOperation = viewState.getOperation();
result.valid = displayViewState.isValid(); result.genericResult = viewState.getResult();
result.jsclOperation = displayViewState.getOperation(); result.errorMessage = viewState.getErrorMessage();
result.genericResult = displayViewState.getResult();
result.errorMessage = displayViewState.getErrorMessage();
return result; return result;
} }

View File

@ -1,6 +1,7 @@
package org.solovyev.android.calculator.history; package org.solovyev.android.calculator.history;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.CalculatorEventListener;
import org.solovyev.common.history.HistoryHelper; import org.solovyev.common.history.HistoryHelper;
/** /**
@ -8,7 +9,7 @@ import org.solovyev.common.history.HistoryHelper;
* Date: 20.09.12 * Date: 20.09.12
* Time: 16:11 * Time: 16:11
*/ */
public interface CalculatorHistory extends HistoryHelper<CalculatorHistoryState> { public interface CalculatorHistory extends HistoryHelper<CalculatorHistoryState>, CalculatorEventListener {
void fromXml(@NotNull String xml); void fromXml(@NotNull String xml);

View File

@ -2,6 +2,7 @@ package org.solovyev.android.calculator.history;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.*;
import org.solovyev.common.history.HistoryAction; import org.solovyev.common.history.HistoryAction;
import org.solovyev.common.history.HistoryHelper; import org.solovyev.common.history.HistoryHelper;
import org.solovyev.common.history.SimpleHistoryHelper; import org.solovyev.common.history.SimpleHistoryHelper;
@ -26,6 +27,9 @@ public class CalculatorHistoryImpl implements CalculatorHistory {
@NotNull @NotNull
private final List<CalculatorHistoryState> savedHistory = new ArrayList<CalculatorHistoryState>(); private final List<CalculatorHistoryState> savedHistory = new ArrayList<CalculatorHistoryState>();
@NotNull
private CalculatorEventDataId lastEventDataId = CalculatorLocatorImpl.getInstance().getCalculator().createFirstEventDataId();
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
return this.history.isEmpty(); return this.history.isEmpty();
@ -128,4 +132,26 @@ public class CalculatorHistoryImpl implements CalculatorHistory {
public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) { public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) {
this.savedHistory.remove(historyState); this.savedHistory.remove(historyState);
} }
@Override
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData,
@NotNull CalculatorEventType calculatorEventType,
@Nullable Object data) {
if (calculatorEventType.isOfType(CalculatorEventType.calculation_started, CalculatorEventType.calculation_result, CalculatorEventType.calculation_failed)) {
if ( calculatorEventData.isAfter(this.lastEventDataId) ) {
switch (calculatorEventType) {
case calculation_started:
CalculatorHistoryState.newInstance()
break;
}
CalculatorLocatorImpl.getInstance().getCalculatorDisplay().get
CalculatorHistoryState.newInstance(new TextViewEditorAdapter(this.editor), display);
this.lastEventDataId = calculatorEventData;
}
}
}
} }

View File

@ -9,6 +9,7 @@ import org.jetbrains.annotations.NotNull;
import org.simpleframework.xml.Element; import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root; import org.simpleframework.xml.Root;
import org.solovyev.android.calculator.CalculatorDisplay; import org.solovyev.android.calculator.CalculatorDisplay;
import org.solovyev.android.calculator.CalculatorEditor;
import org.solovyev.android.calculator.Editor; import org.solovyev.android.calculator.Editor;
/** /**
@ -38,9 +39,12 @@ public class CalculatorHistoryState extends AbstractHistoryState {
this.displayState = displayState; this.displayState = displayState;
} }
public static CalculatorHistoryState newInstance(@NotNull Editor editor, @NotNull CalculatorDisplay display) { public static CalculatorHistoryState newInstance(@NotNull CalculatorEditor editor,
final EditorHistoryState editorHistoryState = EditorHistoryState.newInstance(editor); @NotNull CalculatorDisplay display) {
final CalculatorDisplayHistoryState displayHistoryState = CalculatorDisplayHistoryState.newInstance(display); final EditorHistoryState editorHistoryState = EditorHistoryState.newInstance(editor.getViewState());
final CalculatorDisplayHistoryState displayHistoryState = CalculatorDisplayHistoryState.newInstance(display.getViewState());
return new CalculatorHistoryState(editorHistoryState, displayHistoryState); return new CalculatorHistoryState(editorHistoryState, displayHistoryState);
} }

View File

@ -10,6 +10,7 @@ import org.jetbrains.annotations.Nullable;
import org.simpleframework.xml.Element; import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root; import org.simpleframework.xml.Root;
import org.solovyev.android.calculator.CalculatorDisplayViewState; import org.solovyev.android.calculator.CalculatorDisplayViewState;
import org.solovyev.android.calculator.CalculatorEditorViewState;
import org.solovyev.android.calculator.Editor; import org.solovyev.android.calculator.Editor;
@Root @Root
@ -27,11 +28,11 @@ public class EditorHistoryState implements Cloneable{
} }
@NotNull @NotNull
public static EditorHistoryState newInstance(@NotNull Editor editor) { public static EditorHistoryState newInstance(@NotNull CalculatorEditorViewState viewState) {
final EditorHistoryState result = new EditorHistoryState(); final EditorHistoryState result = new EditorHistoryState();
result.text = String.valueOf(editor.getText()); result.text = String.valueOf(viewState.getText());
result.cursorPosition = editor.getSelection(); result.cursorPosition = viewState.getSelection();
return result; return result;
} }

View File

@ -11,7 +11,7 @@
a:layout_width="fill_parent" a:layout_width="fill_parent"
a:layout_height="0dp"> a:layout_height="0dp">
<org.solovyev.android.calculator.CalculatorEditor <org.solovyev.android.calculator.AndroidCalculatorEditorView
a:id="@+id/calculatorEditor" a:id="@+id/calculatorEditor"
style="@style/editor_style" style="@style/editor_style"
a:textIsSelectable="true" a:textIsSelectable="true"

View File

@ -7,6 +7,7 @@ package org.solovyev.android.calculator;
import android.content.Context; import android.content.Context;
import android.graphics.Color; import android.graphics.Color;
import android.os.Handler;
import android.text.Html; import android.text.Html;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
@ -33,132 +34,41 @@ import java.util.Set;
*/ */
public class AndroidCalculatorDisplayView extends AutoResizeTextView implements CalculatorDisplayView { public class AndroidCalculatorDisplayView extends AutoResizeTextView implements CalculatorDisplayView {
public static enum MenuItem implements LabeledMenuItem<CalculatorDisplayViewState> { /*
**********************************************************************
copy(R.string.c_copy) { *
@Override * STATIC FIELDS
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) { *
CalculatorModel.copyResult(context, data); **********************************************************************
} */
},
convert_to_bin(R.string.convert_to_bin) {
@Override
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
ConversionMenuItem.convert_to_bin.onClick(data, context);
}
@Override
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
return ConversionMenuItem.convert_to_bin.isItemVisibleFor(generic, operation);
}
},
convert_to_dec(R.string.convert_to_dec) {
@Override
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
ConversionMenuItem.convert_to_dec.onClick(data, context);
}
@Override
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
return ConversionMenuItem.convert_to_dec.isItemVisibleFor(generic, operation);
}
},
convert_to_hex(R.string.convert_to_hex) {
@Override
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
ConversionMenuItem.convert_to_hex.onClick(data, context);
}
@Override
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
return ConversionMenuItem.convert_to_hex.isItemVisibleFor(generic, operation);
}
},
convert(R.string.c_convert) {
@Override
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
final Generic result = data.getResult();
if (result != null) {
new NumeralBaseConverterDialog(result.toString()).show(context);
}
}
@Override
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
return operation == JsclOperation.numeric && generic.getConstants().isEmpty();
}
},
plot(R.string.c_plot) {
@Override
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
final Generic generic = data.getResult();
assert generic != null;
final Constant constant = CollectionsUtils.getFirstCollectionElement(getNotSystemConstants(generic));
assert constant != null;
CalculatorActivityLauncher.plotGraph(context, generic, constant);
}
@Override
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
boolean result = false;
if (operation == JsclOperation.simplify) {
if (getNotSystemConstants(generic).size() == 1) {
result = true;
}
}
return result;
}
@NotNull @NotNull
private Set<Constant> getNotSystemConstants(@NotNull Generic generic) { private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine());
final Set<Constant> notSystemConstants = new HashSet<Constant>();
for (Constant constant : generic.getConstants()) { /*
IConstant var = CalculatorEngine.instance.getVarsRegistry().get(constant.getName()); **********************************************************************
if (var != null && !var.isSystem() && !var.isDefined()) { *
notSystemConstants.add(constant); * FIELDS
} *
} **********************************************************************
*/
return notSystemConstants;
}
};
private final int captionId;
MenuItem(int captionId) {
this.captionId = captionId;
}
public final boolean isItemVisible(@NotNull CalculatorDisplayViewState displayViewState) {
//noinspection ConstantConditions
return displayViewState.isValid() && displayViewState.getResult() != null && isItemVisibleFor(displayViewState.getResult(), displayViewState.getOperation());
}
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
return true;
}
@NotNull
@Override
public String getCaption(@NotNull Context context) {
return context.getString(captionId);
}
}
@NotNull @NotNull
private CalculatorDisplayViewState state = CalculatorDisplayViewStateImpl.newDefaultInstance(); private CalculatorDisplayViewState state = CalculatorDisplayViewStateImpl.newDefaultInstance();
@NotNull @NotNull
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorEngine.instance.getEngine()); private final Object lock = new Object();
@NotNull
private final Handler handler = new Handler();
/*
**********************************************************************
*
* CONSTRUCTORS
*
**********************************************************************
*/
public AndroidCalculatorDisplayView(Context context) { public AndroidCalculatorDisplayView(Context context) {
super(context); super(context);
@ -172,35 +82,50 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements
super(context, attrs, defStyle); super(context, attrs, defStyle);
} }
/*
**********************************************************************
*
* METHODS
*
**********************************************************************
*/
public boolean isValid() { public boolean isValid() {
synchronized (lock) {
return this.state.isValid(); return this.state.isValid();
} }
}
@Override @Override
public void setState(@NotNull CalculatorDisplayViewState state) { public void setState(@NotNull final CalculatorDisplayViewState state) {
this.state = state; handler.postDelayed(new Runnable() {
@Override
public void run() {
synchronized (lock) {
AndroidCalculatorDisplayView.this.state = state;
if ( state.isValid() ) { if ( state.isValid() ) {
setTextColor(getResources().getColor(R.color.default_text_color)); setTextColor(getResources().getColor(R.color.default_text_color));
setText(state.getStringResult()); setText(state.getStringResult());
redraw();
} else { } else {
setTextColor(getResources().getColor(R.color.display_error_text_color)); setTextColor(getResources().getColor(R.color.display_error_text_color));
setText(state.getErrorMessage()); setText(state.getErrorMessage());
redraw();
} }
} }
}
}, 1);
}
@NotNull @NotNull
@Override @Override
public CalculatorDisplayViewState getState() { public CalculatorDisplayViewState getState() {
synchronized (lock) {
return this.state; return this.state;
} }
@Override
public void setText(CharSequence text, BufferType type) {
super.setText(text, type);
} }
public synchronized void redraw() { private synchronized void redraw() {
if (isValid()) { if (isValid()) {
String text = getText().toString(); String text = getText().toString();
@ -222,14 +147,4 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements
setMinTextSize(10); setMinTextSize(10);
resizeText(); resizeText();
} }
@Override
public int getSelection() {
return this.getSelectionStart();
}
@Override
public void setSelection(int selection) {
// not supported by TextView
}
} }

View File

@ -25,7 +25,7 @@ import org.solovyev.common.collections.CollectionsUtils;
* Date: 9/17/11 * Date: 9/17/11
* Time: 12:25 AM * Time: 12:25 AM
*/ */
public class CalculatorEditor extends EditText implements SharedPreferences.OnSharedPreferenceChangeListener { public class AndroidCalculatorEditorView extends EditText implements SharedPreferences.OnSharedPreferenceChangeListener, CalculatorEditorView {
private static final String CALC_COLOR_DISPLAY_KEY = "org.solovyev.android.calculator.CalculatorModel_color_display"; private static final String CALC_COLOR_DISPLAY_KEY = "org.solovyev.android.calculator.CalculatorModel_color_display";
private static final boolean CALC_COLOR_DISPLAY_DEFAULT = true; private static final boolean CALC_COLOR_DISPLAY_DEFAULT = true;
@ -35,39 +35,16 @@ public class CalculatorEditor extends EditText implements SharedPreferences.OnSh
@NotNull @NotNull
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, true, CalculatorEngine.instance.getEngine()); private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, true, CalculatorEngine.instance.getEngine());
public CalculatorEditor(Context context) { public AndroidCalculatorEditorView(Context context) {
super(context); super(context);
init();
} }
public CalculatorEditor(Context context, AttributeSet attrs) { public AndroidCalculatorEditorView(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
init();
} }
private void init() { public AndroidCalculatorEditorView(Context context, AttributeSet attrs, int defStyle) {
// NOTE: in this solution cursor is missing super(context, attrs, defStyle);
/*this.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
final TextView textView = (TextView)v;
// backup the input type
int inputType = textView.getInputType();
// disable soft input
textView.setInputType(InputType.TYPE_NULL);
// call native handler
textView.onTouchEvent(event);
// restore input type
textView.setInputType(inputType);
// consume touch even
return true;
}
});*/
} }
@ -95,11 +72,6 @@ public class CalculatorEditor extends EditText implements SharedPreferences.OnSh
} }
} }
public CalculatorEditor(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
@Override @Override
protected void onCreateContextMenu(ContextMenu menu) { protected void onCreateContextMenu(ContextMenu menu) {
super.onCreateContextMenu(menu); super.onCreateContextMenu(menu);
@ -107,11 +79,6 @@ public class CalculatorEditor extends EditText implements SharedPreferences.OnSh
menu.removeItem(android.R.id.selectAll); menu.removeItem(android.R.id.selectAll);
} }
@Override
public void setText(CharSequence text, BufferType type) {
super.setText(text, type);
}
public synchronized void redraw() { public synchronized void redraw() {
String text = getText().toString(); String text = getText().toString();

View File

@ -0,0 +1,141 @@
package org.solovyev.android.calculator;
import android.content.Context;
import jscl.math.Generic;
import jscl.math.function.Constant;
import jscl.math.function.IConstant;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
import org.solovyev.android.menu.LabeledMenuItem;
import org.solovyev.common.collections.CollectionsUtils;
import java.util.HashSet;
import java.util.Set;
/**
* User: Solovyev_S
* Date: 21.09.12
* Time: 10:55
*/
public enum CalculatorDisplayMenuItem implements LabeledMenuItem<CalculatorDisplayViewState> {
copy(R.string.c_copy) {
@Override
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
CalculatorModel.copyResult(context, data);
}
},
convert_to_bin(R.string.convert_to_bin) {
@Override
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
ConversionMenuItem.convert_to_bin.onClick(data, context);
}
@Override
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
return ConversionMenuItem.convert_to_bin.isItemVisibleFor(generic, operation);
}
},
convert_to_dec(R.string.convert_to_dec) {
@Override
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
ConversionMenuItem.convert_to_dec.onClick(data, context);
}
@Override
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
return ConversionMenuItem.convert_to_dec.isItemVisibleFor(generic, operation);
}
},
convert_to_hex(R.string.convert_to_hex) {
@Override
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
ConversionMenuItem.convert_to_hex.onClick(data, context);
}
@Override
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
return ConversionMenuItem.convert_to_hex.isItemVisibleFor(generic, operation);
}
},
convert(R.string.c_convert) {
@Override
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
final Generic result = data.getResult();
if (result != null) {
new NumeralBaseConverterDialog(result.toString()).show(context);
}
}
@Override
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
return operation == JsclOperation.numeric && generic.getConstants().isEmpty();
}
},
plot(R.string.c_plot) {
@Override
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
final Generic generic = data.getResult();
assert generic != null;
final Constant constant = CollectionsUtils.getFirstCollectionElement(getNotSystemConstants(generic));
assert constant != null;
CalculatorActivityLauncher.plotGraph(context, generic, constant);
}
@Override
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
boolean result = false;
if (operation == JsclOperation.simplify) {
if (getNotSystemConstants(generic).size() == 1) {
result = true;
}
}
return result;
}
@NotNull
private Set<Constant> getNotSystemConstants(@NotNull Generic generic) {
final Set<Constant> notSystemConstants = new HashSet<Constant>();
for (Constant constant : generic.getConstants()) {
IConstant var = CalculatorEngine.instance.getVarsRegistry().get(constant.getName());
if (var != null && !var.isSystem() && !var.isDefined()) {
notSystemConstants.add(constant);
}
}
return notSystemConstants;
}
};
private final int captionId;
CalculatorDisplayMenuItem(int captionId) {
this.captionId = captionId;
}
public final boolean isItemVisible(@NotNull CalculatorDisplayViewState displayViewState) {
//noinspection ConstantConditions
return displayViewState.isValid() && displayViewState.getResult() != null && isItemVisibleFor(displayViewState.getResult(), displayViewState.getOperation());
}
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
return true;
}
@NotNull
@Override
public String getCaption(@NotNull Context context) {
return context.getString(captionId);
}
}

View File

@ -0,0 +1,53 @@
package org.solovyev.android.calculator;
import android.app.Activity;
import android.view.View;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.menu.AMenuBuilder;
import org.solovyev.android.menu.MenuImpl;
import java.util.ArrayList;
import java.util.List;
/**
* User: Solovyev_S
* Date: 21.09.12
* Time: 10:58
*/
public class CalculatorDisplayOnClickListener implements View.OnClickListener {
@NotNull
private final Activity activity;
public CalculatorDisplayOnClickListener(@NotNull Activity activity) {
this.activity = activity;
}
@Override
public void onClick(View v) {
if (v instanceof CalculatorDisplayView) {
final CalculatorDisplay cd = CalculatorLocatorImpl.getInstance().getCalculatorDisplay();
final CalculatorDisplayViewState displayViewState = cd.getViewState();
if (displayViewState.isValid()) {
final List<CalculatorDisplayMenuItem> filteredMenuItems = new ArrayList<CalculatorDisplayMenuItem>(CalculatorDisplayMenuItem.values().length);
for (CalculatorDisplayMenuItem menuItem : CalculatorDisplayMenuItem.values()) {
if (menuItem.isItemVisible(displayViewState)) {
filteredMenuItems.add(menuItem);
}
}
if (!filteredMenuItems.isEmpty()) {
AMenuBuilder.newInstance(activity, MenuImpl.newInstance(filteredMenuItems)).create(displayViewState).show();
}
} else {
final String errorMessage = displayViewState.getErrorMessage();
if (errorMessage != null) {
CalculatorModel.showEvaluationError(activity, errorMessage);
}
}
}
}
}

View File

@ -27,22 +27,17 @@ import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.math.MathType; import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.model.CalculatorEngine; import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.history.HistoryControl; import org.solovyev.android.history.HistoryControl;
import org.solovyev.android.menu.AMenuBuilder;
import org.solovyev.android.menu.MenuImpl;
import org.solovyev.common.MutableObject; import org.solovyev.common.MutableObject;
import org.solovyev.common.history.HistoryAction; import org.solovyev.common.history.HistoryAction;
import org.solovyev.common.msg.Message; import org.solovyev.common.msg.Message;
import org.solovyev.common.text.StringUtils; import org.solovyev.common.text.StringUtils;
import java.util.ArrayList;
import java.util.List;
/** /**
* User: serso * User: serso
* Date: 9/12/11 * Date: 9/12/11
* Time: 11:15 PM * Time: 11:15 PM
*/ */
public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorHistoryState>, CalculatorEngineControl { public enum CalculatorModel implements HistoryControl<CalculatorHistoryState>, CalculatorEngineControl {
instance; instance;
@ -50,24 +45,31 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
public static final int EVAL_DELAY_MILLIS = 0; public static final int EVAL_DELAY_MILLIS = 0;
@NotNull @NotNull
private CalculatorEditor editor; private final CalculatorEditor editor;
@NotNull @NotNull
private AndroidCalculatorDisplayView display; private final CalculatorDisplay display;
@NotNull @NotNull
private CalculatorEngine calculatorEngine; private CalculatorEngine calculatorEngine;
private CalculatorModel() {
display = CalculatorLocatorImpl.getInstance().getCalculatorDisplay();
editor = CalculatorLocatorImpl.getInstance().getCalculatorEditor();
}
public CalculatorModel init(@NotNull final Activity activity, @NotNull SharedPreferences preferences, @NotNull CalculatorEngine calculator) { public CalculatorModel init(@NotNull final Activity activity, @NotNull SharedPreferences preferences, @NotNull CalculatorEngine calculator) {
Log.d(this.getClass().getName(), "CalculatorModel initialization with activity: " + activity); Log.d(this.getClass().getName(), "CalculatorModel initialization with activity: " + activity);
this.calculatorEngine = calculator; this.calculatorEngine = calculator;
this.editor = (CalculatorEditor) activity.findViewById(R.id.calculatorEditor); final AndroidCalculatorEditorView editorView = (AndroidCalculatorEditorView) activity.findViewById(R.id.calculatorEditor);
this.editor.init(preferences); editorView.init(preferences);
preferences.registerOnSharedPreferenceChangeListener(editor); preferences.registerOnSharedPreferenceChangeListener(editorView);
editor.setView(editorView);
this.display = (AndroidCalculatorDisplayView) activity.findViewById(R.id.calculatorDisplay); final AndroidCalculatorDisplayView displayView = (AndroidCalculatorDisplayView) activity.findViewById(R.id.calculatorDisplay);
this.display.setOnClickListener(new CalculatorDisplayOnClickListener(activity)); displayView.setOnClickListener(new CalculatorDisplayOnClickListener(activity));
display.setView(displayView);
final CalculatorHistoryState lastState = AndroidCalculatorHistoryImpl.instance.getLastHistoryState(); final CalculatorHistoryState lastState = AndroidCalculatorHistoryImpl.instance.getLastHistoryState();
if (lastState == null) { if (lastState == null) {
@ -80,7 +82,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
return this; return this;
} }
private static void showEvaluationError(@NotNull Activity activity, @NotNull final String errorMessage) { public static void showEvaluationError(@NotNull Activity activity, @NotNull final String errorMessage) {
final LayoutInflater layoutInflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); final LayoutInflater layoutInflater = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
final View errorMessageView = layoutInflater.inflate(R.layout.display_error_message, null); final View errorMessageView = layoutInflater.inflate(R.layout.display_error_message, null);
@ -94,7 +96,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
} }
public void copyResult(@NotNull Context context) { public void copyResult(@NotNull Context context) {
copyResult(context, display); copyResult(context, display.getViewState());
} }
public static void copyResult(@NotNull Context context, @NotNull final CalculatorDisplayViewState viewState) { public static void copyResult(@NotNull Context context, @NotNull final CalculatorDisplayViewState viewState) {
@ -112,26 +114,6 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
AndroidCalculatorHistoryImpl.instance.addState(getCurrentHistoryState()); AndroidCalculatorHistoryImpl.instance.addState(getCurrentHistoryState());
} }
public void setCursorOnStart() {
editor.setSelection(0);
}
public void setCursorOnEnd() {
editor.setSelection(editor.getText().length());
}
public void moveCursorLeft() {
if (editor.getSelectionStart() > 0) {
editor.setSelection(editor.getSelectionStart() - 1);
}
}
public void moveCursorRight() {
if (editor.getSelectionStart() < editor.getText().length()) {
editor.setSelection(editor.getSelectionStart() + 1);
}
}
public void doTextOperation(@NotNull TextOperation operation) { public void doTextOperation(@NotNull TextOperation operation) {
doTextOperation(operation, true); doTextOperation(operation, true);
} }
@ -354,7 +336,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
} }
editor.redraw(); editor.redraw();
display.redraw(); //display.redraw();
} }
} }
@ -362,50 +344,13 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
@NotNull @NotNull
public CalculatorHistoryState getCurrentHistoryState() { public CalculatorHistoryState getCurrentHistoryState() {
synchronized (AndroidCalculatorHistoryImpl.instance) { synchronized (AndroidCalculatorHistoryImpl.instance) {
return CalculatorHistoryState.newInstance(new TextViewEditorAdapter(this.editor), this.display); return CalculatorHistoryState.newInstance(new TextViewEditorAdapter(this.editor), display);
} }
} }
@NotNull @NotNull
public AndroidCalculatorDisplayView getDisplay() { public CalculatorDisplay getDisplay() {
return display; return display;
} }
private static class CalculatorDisplayOnClickListener implements View.OnClickListener {
@NotNull
private final Activity activity;
public CalculatorDisplayOnClickListener(@NotNull Activity activity) {
this.activity = activity;
}
@Override
public void onClick(View v) {
if (v instanceof CalculatorDisplayView) {
final CalculatorDisplay cd = CalculatorLocatorImpl.getInstance().getCalculatorDisplay();
final CalculatorDisplayViewState displayViewState = cd.getViewState();
if (displayViewState.isValid()) {
final List<AndroidCalculatorDisplayView.MenuItem> filteredMenuItems = new ArrayList<AndroidCalculatorDisplayView.MenuItem>(AndroidCalculatorDisplayView.MenuItem.values().length);
for (AndroidCalculatorDisplayView.MenuItem menuItem : AndroidCalculatorDisplayView.MenuItem.values()) {
if (menuItem.isItemVisible(displayViewState)) {
filteredMenuItems.add(menuItem);
}
}
if (!filteredMenuItems.isEmpty()) {
AMenuBuilder.newInstance(activity, MenuImpl.newInstance(filteredMenuItems)).create(cd).show();
}
} else {
final String errorMessage = displayViewState.getErrorMessage();
if (errorMessage != null) {
showEvaluationError(activity, errorMessage);
}
}
}
}
}
} }

View File

@ -11,6 +11,8 @@ import android.content.SharedPreferences;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.CalculatorEventData;
import org.solovyev.android.calculator.CalculatorEventType;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.common.history.HistoryAction; import org.solovyev.common.history.HistoryAction;
@ -142,4 +144,9 @@ public enum AndroidCalculatorHistoryImpl implements AndroidCalculatorHistory {
public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) { public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) {
calculatorHistory.removeSavedHistory(historyState); calculatorHistory.removeSavedHistory(historyState);
} }
@Override
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
calculatorHistory.onCalculatorEvent(calculatorEventData, calculatorEventType, data);
}
} }

View File

@ -173,7 +173,7 @@ public class TextHighlighter implements TextProcessor<TextHighlighter.Result, St
text2.append(s.charAt(i)); text2.append(s.charAt(i));
} }
//Log.d(CalculatorEditor.class.getName(), text2.toString()); //Log.d(AndroidCalculatorEditorView.class.getName(), text2.toString());
result = text2.toString(); result = text2.toString();
} else { } else {