diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorFailureImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorFailureImpl.java index 866146b3..2603093c 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorFailureImpl.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorFailureImpl.java @@ -31,4 +31,11 @@ public class CalculatorFailureImpl implements CalculatorFailure { public CalculatorEvalException getCalculationEvalException() { return exception instanceof CalculatorEvalException ? (CalculatorEvalException)exception : null; } + + @Override + public String toString() { + return "CalculatorFailureImpl{" + + "exception=" + exception + + '}'; + } } diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocator.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocator.java index 8fcb7732..04a321a6 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocator.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocator.java @@ -14,7 +14,8 @@ public interface CalculatorLocator { @NotNull CalculatorEngine engine, @NotNull CalculatorClipboard clipboard, @NotNull CalculatorNotifier notifier, - @NotNull CalculatorHistory history); + @NotNull CalculatorHistory history, + @NotNull CalculatorLogger logger); @NotNull Calculator getCalculator(); @@ -39,4 +40,7 @@ public interface CalculatorLocator { @NotNull CalculatorHistory getHistory(); + + @NotNull + CalculatorLogger getLogger(); } diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocatorImpl.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocatorImpl.java index 6f65ac48..d1ab0604 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocatorImpl.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLocatorImpl.java @@ -1,113 +1,124 @@ -package org.solovyev.android.calculator; - -import org.jetbrains.annotations.NotNull; -import org.solovyev.android.calculator.history.CalculatorHistory; - -/** - * User: Solovyev_S - * Date: 20.09.12 - * Time: 12:45 - */ -public class CalculatorLocatorImpl implements CalculatorLocator { - - @NotNull - private CalculatorEngine calculatorEngine; - - @NotNull - private Calculator calculator; - - @NotNull - private CalculatorEditor calculatorEditor; - - @NotNull - private CalculatorDisplay calculatorDisplay; - - @NotNull - private CalculatorKeyboard calculatorKeyboard; - - @NotNull - private CalculatorHistory calculatorHistory; - - @NotNull - private CalculatorNotifier calculatorNotifier = new DummyCalculatorNotifier(); - - @NotNull - private CalculatorClipboard calculatorClipboard = new DummyCalculatorClipboard(); - - @NotNull - private static final CalculatorLocator instance = new CalculatorLocatorImpl(); - - public CalculatorLocatorImpl() { - } - - @Override - public void init(@NotNull Calculator calculator, - @NotNull CalculatorEngine engine, - @NotNull CalculatorClipboard clipboard, - @NotNull CalculatorNotifier notifier, - @NotNull CalculatorHistory history) { - - this.calculator = calculator; - this.calculatorEngine = engine; - this.calculatorClipboard = clipboard; - this.calculatorNotifier = notifier; - this.calculatorHistory = history; - - calculatorEditor = new CalculatorEditorImpl(this.calculator); - calculatorDisplay = new CalculatorDisplayImpl(this.calculator); - calculatorKeyboard = new CalculatorKeyboardImpl(this.calculator); - } - - @NotNull - public static CalculatorLocator getInstance() { - return instance; - } - - @NotNull - @Override - public CalculatorEngine getEngine() { - return calculatorEngine; - } - - @NotNull - @Override - public Calculator getCalculator() { - return this.calculator; - } - - @Override - @NotNull - public CalculatorDisplay getDisplay() { - return calculatorDisplay; - } - - @NotNull - @Override - public CalculatorEditor getEditor() { - return calculatorEditor; - } - - @Override - @NotNull - public CalculatorKeyboard getKeyboard() { - return calculatorKeyboard; - } - - @Override - @NotNull - public CalculatorClipboard getClipboard() { - return calculatorClipboard; - } - - @Override - @NotNull - public CalculatorNotifier getNotifier() { - return calculatorNotifier; - } - - @Override - @NotNull - public CalculatorHistory getHistory() { - return calculatorHistory; - } -} +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; +import org.solovyev.android.calculator.history.CalculatorHistory; + +/** + * User: Solovyev_S + * Date: 20.09.12 + * Time: 12:45 + */ +public class CalculatorLocatorImpl implements CalculatorLocator { + + @NotNull + private CalculatorEngine calculatorEngine; + + @NotNull + private Calculator calculator; + + @NotNull + private CalculatorEditor calculatorEditor; + + @NotNull + private CalculatorDisplay calculatorDisplay; + + @NotNull + private CalculatorKeyboard calculatorKeyboard; + + @NotNull + private CalculatorHistory calculatorHistory; + + @NotNull + private CalculatorNotifier calculatorNotifier = new DummyCalculatorNotifier(); + + @NotNull + private CalculatorLogger calculatorLogger = new SystemOutCalculatorLogger(); + + @NotNull + private CalculatorClipboard calculatorClipboard = new DummyCalculatorClipboard(); + + @NotNull + private static final CalculatorLocator instance = new CalculatorLocatorImpl(); + + public CalculatorLocatorImpl() { + } + + @Override + public void init(@NotNull Calculator calculator, + @NotNull CalculatorEngine engine, + @NotNull CalculatorClipboard clipboard, + @NotNull CalculatorNotifier notifier, + @NotNull CalculatorHistory history, + @NotNull CalculatorLogger logger) { + + this.calculator = calculator; + this.calculatorEngine = engine; + this.calculatorClipboard = clipboard; + this.calculatorNotifier = notifier; + this.calculatorHistory = history; + this.calculatorLogger = logger; + + calculatorEditor = new CalculatorEditorImpl(this.calculator); + calculatorDisplay = new CalculatorDisplayImpl(this.calculator); + calculatorKeyboard = new CalculatorKeyboardImpl(this.calculator); + } + + @NotNull + public static CalculatorLocator getInstance() { + return instance; + } + + @NotNull + @Override + public CalculatorEngine getEngine() { + return calculatorEngine; + } + + @NotNull + @Override + public Calculator getCalculator() { + return this.calculator; + } + + @Override + @NotNull + public CalculatorDisplay getDisplay() { + return calculatorDisplay; + } + + @NotNull + @Override + public CalculatorEditor getEditor() { + return calculatorEditor; + } + + @Override + @NotNull + public CalculatorKeyboard getKeyboard() { + return calculatorKeyboard; + } + + @Override + @NotNull + public CalculatorClipboard getClipboard() { + return calculatorClipboard; + } + + @Override + @NotNull + public CalculatorNotifier getNotifier() { + return calculatorNotifier; + } + + @Override + @NotNull + public CalculatorHistory getHistory() { + return calculatorHistory; + } + + @Override + @NotNull + public CalculatorLogger getLogger() { + return calculatorLogger; + } +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLogger.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLogger.java new file mode 100644 index 00000000..60057cf8 --- /dev/null +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/CalculatorLogger.java @@ -0,0 +1,16 @@ +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * User: serso + * Date: 10/11/12 + * Time: 12:11 AM + */ +public interface CalculatorLogger { + + void debug(@Nullable String tag, @NotNull String message); + + void debug(@Nullable String tag, @NotNull String message, @NotNull Throwable e); +} diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/ListCalculatorEventContainer.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/ListCalculatorEventContainer.java index 591e3836..4434e9a0 100644 --- a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/ListCalculatorEventContainer.java +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/ListCalculatorEventContainer.java @@ -39,10 +39,18 @@ public class ListCalculatorEventContainer implements CalculatorEventContainer { public void fireCalculatorEvents(@NotNull List calculatorEvents) { final List listeners = this.listeners.getListeners(); + final CalculatorLogger logger = CalculatorLocatorImpl.getInstance().getLogger(); + for (CalculatorEvent e : calculatorEvents) { - //Log.d(TAG, "Event: " + e.getCalculatorEventType() + " with data: " + e.getData()); for (CalculatorEventListener listener : listeners) { + long startTime = System.currentTimeMillis(); listener.onCalculatorEvent(e.getCalculatorEventData(), e.getCalculatorEventType(), e.getData()); + long endTime = System.currentTimeMillis(); + long totalTime = (endTime - startTime); + if ( totalTime > 300 ) { + logger.debug(TAG + "_" + e.getCalculatorEventData().getEventId(), "Started event: " + e.getCalculatorEventType() + " with data: " + e.getData() + " for: " + listener.getClass().getSimpleName()); + logger.debug(TAG + "_" + e.getCalculatorEventData().getEventId(), "Total time, ms: " + totalTime); + } } } } diff --git a/calculatorpp-core/src/main/java/org/solovyev/android/calculator/SystemOutCalculatorLogger.java b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/SystemOutCalculatorLogger.java new file mode 100644 index 00000000..09656a52 --- /dev/null +++ b/calculatorpp-core/src/main/java/org/solovyev/android/calculator/SystemOutCalculatorLogger.java @@ -0,0 +1,31 @@ +package org.solovyev.android.calculator; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * User: serso + * Date: 10/11/12 + * Time: 12:12 AM + */ +public class SystemOutCalculatorLogger implements CalculatorLogger { + + @NotNull + private static final String TAG = SystemOutCalculatorLogger.class.getSimpleName(); + + @Override + public void debug(@Nullable String tag, @NotNull String message) { + System.out.println(getTag(tag) + ": " + message); + } + + @NotNull + private String getTag(@Nullable String tag) { + return tag != null ? tag : TAG; + } + + @Override + public void debug(@Nullable String tag, @NotNull String message, @NotNull Throwable e) { + debug(tag, message); + e.printStackTrace(System.out); + } +} diff --git a/calculatorpp-core/src/test/java/org/solovyev/android/calculator/AbstractCalculatorTest.java b/calculatorpp-core/src/test/java/org/solovyev/android/calculator/AbstractCalculatorTest.java index 6fe7698e..0aaf1a93 100644 --- a/calculatorpp-core/src/test/java/org/solovyev/android/calculator/AbstractCalculatorTest.java +++ b/calculatorpp-core/src/test/java/org/solovyev/android/calculator/AbstractCalculatorTest.java @@ -11,7 +11,7 @@ import org.solovyev.android.calculator.history.CalculatorHistory; public class AbstractCalculatorTest { protected void setUp() throws Exception { - CalculatorLocatorImpl.getInstance().init(new CalculatorImpl(), CalculatorTestUtils.newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class)); + CalculatorLocatorImpl.getInstance().init(new CalculatorImpl(), CalculatorTestUtils.newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), null); CalculatorLocatorImpl.getInstance().getEngine().init(); } diff --git a/calculatorpp-core/src/test/java/org/solovyev/android/calculator/CalculatorTestUtils.java b/calculatorpp-core/src/test/java/org/solovyev/android/calculator/CalculatorTestUtils.java index 46230c8f..acde331d 100644 --- a/calculatorpp-core/src/test/java/org/solovyev/android/calculator/CalculatorTestUtils.java +++ b/calculatorpp-core/src/test/java/org/solovyev/android/calculator/CalculatorTestUtils.java @@ -22,7 +22,7 @@ public class CalculatorTestUtils { public static final int TIMEOUT = 1; public static void staticSetUp() throws Exception { - CalculatorLocatorImpl.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class)); + CalculatorLocatorImpl.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), null); CalculatorLocatorImpl.getInstance().getEngine().init(); } diff --git a/calculatorpp/project.properties b/calculatorpp/project.properties index 677898c5..78b254f4 100644 --- a/calculatorpp/project.properties +++ b/calculatorpp/project.properties @@ -11,14 +11,14 @@ target=android-15 android.library.reference.1=gen-external-apklibs/org.solovyev.android_android-common-core_1.0.0 android.library.reference.2=gen-external-apklibs/org.solovyev.android_android-common-ads_1.0.0 -android.library.reference.3=gen-external-apklibs/org.solovyev.android_android-common-view_1.0.0 -android.library.reference.4=gen-external-apklibs/org.solovyev.android_android-common-preferences_1.0.0 -android.library.reference.5=gen-external-apklibs/org.solovyev.android_android-common-other_1.0.0 -android.library.reference.6=gen-external-apklibs/org.solovyev.android_android-common-menu_1.0.0 -android.library.reference.7=gen-external-apklibs/org.solovyev.android_android-common-sherlock_1.0.0 -android.library.reference.8=gen-external-apklibs/com.actionbarsherlock_library_4.1.0 -android.library.reference.9=gen-external-apklibs/org.solovyev.android_android-common-list_1.0.0 -android.library.reference.10=gen-external-apklibs/org.solovyev.android_billing_0.2 -android.library.reference.11=gen-external-apklibs/org.solovyev.android_android-common-db_1.0.0 +android.library.reference.3=gen-external-apklibs/org.solovyev.android_billing_0.2 +android.library.reference.4=gen-external-apklibs/org.solovyev.android_android-common-db_1.0.0 +android.library.reference.5=gen-external-apklibs/org.solovyev.android_android-common-view_1.0.0 +android.library.reference.6=gen-external-apklibs/org.solovyev.android_android-common-preferences_1.0.0 +android.library.reference.7=gen-external-apklibs/org.solovyev.android_android-common-other_1.0.0 +android.library.reference.8=gen-external-apklibs/org.solovyev.android_android-common-menu_1.0.0 +android.library.reference.9=gen-external-apklibs/org.solovyev.android_android-common-sherlock_1.0.0 +android.library.reference.10=gen-external-apklibs/com.actionbarsherlock_library_4.1.0 +android.library.reference.11=gen-external-apklibs/org.solovyev.android_android-common-list_1.0.0 diff --git a/calculatorpp/res/drawable-hdpi/equals.png b/calculatorpp/res/drawable-hdpi/equals.png deleted file mode 100644 index a764106c..00000000 Binary files a/calculatorpp/res/drawable-hdpi/equals.png and /dev/null differ diff --git a/calculatorpp/res/drawable-hdpi/equals9.9.png b/calculatorpp/res/drawable-hdpi/equals9.9.png deleted file mode 100644 index ee2bc0e4..00000000 Binary files a/calculatorpp/res/drawable-hdpi/equals9.9.png and /dev/null differ diff --git a/calculatorpp/res/drawable-ldpi/equals.png b/calculatorpp/res/drawable-ldpi/equals.png deleted file mode 100644 index f80d4327..00000000 Binary files a/calculatorpp/res/drawable-ldpi/equals.png and /dev/null differ diff --git a/calculatorpp/res/drawable-ldpi/equals9.9.png b/calculatorpp/res/drawable-ldpi/equals9.9.png deleted file mode 100644 index b47362e7..00000000 Binary files a/calculatorpp/res/drawable-ldpi/equals9.9.png and /dev/null differ diff --git a/calculatorpp/res/drawable-mdpi/equals.png b/calculatorpp/res/drawable-mdpi/equals.png deleted file mode 100644 index 563125c2..00000000 Binary files a/calculatorpp/res/drawable-mdpi/equals.png and /dev/null differ diff --git a/calculatorpp/res/drawable-mdpi/equals9.9.png b/calculatorpp/res/drawable-mdpi/equals9.9.png deleted file mode 100644 index a71af84f..00000000 Binary files a/calculatorpp/res/drawable-mdpi/equals9.9.png and /dev/null differ diff --git a/calculatorpp/res/drawable-xhdpi/equals.png b/calculatorpp/res/drawable-xhdpi/equals.png deleted file mode 100644 index 9de8a696..00000000 Binary files a/calculatorpp/res/drawable-xhdpi/equals.png and /dev/null differ diff --git a/calculatorpp/res/drawable-xhdpi/equals9.9.png b/calculatorpp/res/drawable-xhdpi/equals9.9.png deleted file mode 100644 index 2c002b9a..00000000 Binary files a/calculatorpp/res/drawable-xhdpi/equals9.9.png and /dev/null differ diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorDisplayView.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorDisplayView.java index 23040283..25283a0b 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorDisplayView.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorDisplayView.java @@ -51,7 +51,7 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements private final Object lock = new Object(); @NotNull - private final Handler handler = new Handler(); + private final Handler uiHandler = new Handler(); private volatile boolean initialized = false; @@ -88,7 +88,7 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements @Override public void setState(@NotNull final CalculatorDisplayViewState state) { - handler.post(new Runnable() { + uiHandler.post(new Runnable() { @Override public void run() { @@ -96,7 +96,12 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements try { viewStateChange = true; + long startTime = System.currentTimeMillis(); final CharSequence text = prepareText(state.getStringResult(), state.isValid()); + long endTime = System.currentTimeMillis(); + long totalTime = (endTime - startTime); + CalculatorLocatorImpl.getInstance().getLogger().debug("CalculatorDisplayView", "Total time, ms: " + totalTime); + AndroidCalculatorDisplayView.this.state = state; if (state.isValid()) { diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorEditorView.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorEditorView.java index 9650cedf..b3d7ba2e 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorEditorView.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorEditorView.java @@ -1,213 +1,214 @@ -/* - * Copyright (c) 2009-2011. Created by serso aka se.solovyev. - * For more information, please, contact se.solovyev@gmail.com - */ - -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.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.text.TextProcessor; -import org.solovyev.android.calculator.view.TextHighlighter; -import org.solovyev.common.collections.CollectionsUtils; - -/** - * User: serso - * Date: 9/17/11 - * Time: 12:25 AM - */ -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 boolean CALC_COLOR_DISPLAY_DEFAULT = true; - - private volatile boolean initialized = false; - - private boolean highlightText = true; - - @NotNull - private final static TextProcessor textHighlighter = new TextHighlighter(Color.WHITE, false); - - @NotNull - private volatile CalculatorEditorViewState viewState = CalculatorEditorViewStateImpl.newDefaultInstance(); - - private volatile boolean viewStateChange = false; - - // NOTE: static because super constructor calls some overridden methods (like onSelectionChanged and current lock is not yet created) - @NotNull - private static final Object lock = new Object(); - - @NotNull - private final Handler handler = new Handler(); - - public AndroidCalculatorEditorView(Context context) { - super(context); - } - - public AndroidCalculatorEditorView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public AndroidCalculatorEditorView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - @Override - public boolean onCheckIsTextEditor() { - // NOTE: code below can be used carefully and should not be copied without special intention - // The main purpose of code is to disable soft input (virtual keyboard) but leave all the TextEdit functionality, like cursor, scrolling, copy/paste menu etc - - if (Build.VERSION.SDK_INT >= 11) { - // fix for missing cursor in android 3 and higher - try { - // IDEA: return false always except if method was called from TextView.isCursorVisible() method - for (StackTraceElement stackTraceElement : CollectionsUtils.asList(Thread.currentThread().getStackTrace())) { - if ("isCursorVisible".equals(stackTraceElement.getMethodName())) { - return true; - } - } - } catch (RuntimeException e) { - // just in case... - } - - return false; - } else { - return false; - } - } - - @Override - protected void onCreateContextMenu(ContextMenu menu) { - super.onCreateContextMenu(menu); - - menu.removeItem(android.R.id.selectAll); - } - - @Nullable - private CharSequence prepareText(@NotNull 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; - CalculatorLocatorImpl.getInstance().getEditor().updateViewState(); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { - if (CALC_COLOR_DISPLAY_KEY.equals(key)) { - this.setHighlightText(preferences.getBoolean(CALC_COLOR_DISPLAY_KEY, CALC_COLOR_DISPLAY_DEFAULT)); - } - } - - public synchronized void init(@NotNull Context context) { - if (!initialized) { - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); - - preferences.registerOnSharedPreferenceChangeListener(this); - - this.addTextChangedListener(new TextWatcherImpl()); - - onSharedPreferenceChanged(preferences, CALC_COLOR_DISPLAY_KEY); - - initialized = true; - } - } - - @Override - public void setState(@NotNull final CalculatorEditorViewState viewState) { - - final CharSequence text = prepareText(viewState.getText(), highlightText); - - handler.post(new Runnable() { - @Override - public void run() { - final AndroidCalculatorEditorView editorView = AndroidCalculatorEditorView.this; - synchronized (lock) { - try { - editorView.viewStateChange = true; - editorView.viewState = viewState; - editorView.setText(text, BufferType.EDITABLE); - editorView.setSelection(viewState.getSelection()); - } finally { - editorView.viewStateChange = false; - } - } - } - }); - } - - @Override - protected void onSelectionChanged(int selStart, int selEnd) { - synchronized (lock) { - if (!viewStateChange) { - // external text change => need to notify editor - super.onSelectionChanged(selStart, selEnd); - CalculatorLocatorImpl.getInstance().getEditor().setSelection(selStart); - } - } - } - - public void handleTextChange(Editable s) { - synchronized (lock) { - if (!viewStateChange) { - // external text change => need to notify editor - CalculatorLocatorImpl.getInstance().getEditor().setText(String.valueOf(s)); - } - } - } - - private final class TextWatcherImpl implements TextWatcher { - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } - - @Override - public void afterTextChanged(Editable s) { - handleTextChange(s); - } - } -} +/* + * Copyright (c) 2009-2011. Created by serso aka se.solovyev. + * For more information, please, contact se.solovyev@gmail.com + */ + +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.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +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.CollectionsUtils; + +/** + * User: serso + * Date: 9/17/11 + * Time: 12:25 AM + */ +public class AndroidCalculatorEditorView extends EditText implements SharedPreferences.OnSharedPreferenceChangeListener, CalculatorEditorView { + + @NotNull + private static final BooleanPreference colorDisplay = new BooleanPreference("org.solovyev.android.calculator.CalculatorModel_color_display", true); + + private volatile boolean initialized = false; + + private boolean highlightText = true; + + @NotNull + private final static TextProcessor textHighlighter = new TextHighlighter(Color.WHITE, false); + + @NotNull + private volatile CalculatorEditorViewState viewState = CalculatorEditorViewStateImpl.newDefaultInstance(); + + private volatile boolean viewStateChange = false; + + // NOTE: static because super constructor calls some overridden methods (like onSelectionChanged and current lock is not yet created) + @NotNull + private static final Object lock = new Object(); + + @NotNull + private final Handler uiHandler = new Handler(); + + public AndroidCalculatorEditorView(Context context) { + super(context); + } + + public AndroidCalculatorEditorView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public AndroidCalculatorEditorView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public boolean onCheckIsTextEditor() { + // NOTE: code below can be used carefully and should not be copied without special intention + // The main purpose of code is to disable soft input (virtual keyboard) but leave all the TextEdit functionality, like cursor, scrolling, copy/paste menu etc + + if (Build.VERSION.SDK_INT >= 11) { + // fix for missing cursor in android 3 and higher + try { + // IDEA: return false always except if method was called from TextView.isCursorVisible() method + for (StackTraceElement stackTraceElement : CollectionsUtils.asList(Thread.currentThread().getStackTrace())) { + if ("isCursorVisible".equals(stackTraceElement.getMethodName())) { + return true; + } + } + } catch (RuntimeException e) { + // just in case... + } + + return false; + } else { + return false; + } + } + + @Override + protected void onCreateContextMenu(ContextMenu menu) { + super.onCreateContextMenu(menu); + + menu.removeItem(android.R.id.selectAll); + } + + @Nullable + private CharSequence prepareText(@NotNull 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; + CalculatorLocatorImpl.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(@NotNull Context context) { + if (!initialized) { + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + + preferences.registerOnSharedPreferenceChangeListener(this); + + this.addTextChangedListener(new TextWatcherImpl()); + + onSharedPreferenceChanged(preferences, colorDisplay.getKey()); + + initialized = true; + } + } + + @Override + public void setState(@NotNull final CalculatorEditorViewState viewState) { + + final CharSequence text = prepareText(viewState.getText(), highlightText); + + uiHandler.post(new Runnable() { + @Override + public void run() { + final AndroidCalculatorEditorView editorView = AndroidCalculatorEditorView.this; + synchronized (lock) { + try { + editorView.viewStateChange = true; + editorView.viewState = viewState; + editorView.setText(text, BufferType.EDITABLE); + editorView.setSelection(viewState.getSelection()); + } finally { + editorView.viewStateChange = false; + } + } + } + }); + } + + @Override + protected void onSelectionChanged(int selStart, int selEnd) { + synchronized (lock) { + if (!viewStateChange) { + // external text change => need to notify editor + super.onSelectionChanged(selStart, selEnd); + CalculatorLocatorImpl.getInstance().getEditor().setSelection(selStart); + } + } + } + + public void handleTextChange(Editable s) { + synchronized (lock) { + if (!viewStateChange) { + // external text change => need to notify editor + CalculatorLocatorImpl.getInstance().getEditor().setText(String.valueOf(s)); + } + } + } + + private final class TextWatcherImpl implements TextWatcher { + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + handleTextChange(s); + } + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorLogger.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorLogger.java new file mode 100644 index 00000000..3eaa63c0 --- /dev/null +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/AndroidCalculatorLogger.java @@ -0,0 +1,31 @@ +package org.solovyev.android.calculator; + +import android.util.Log; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * User: serso + * Date: 10/11/12 + * Time: 12:15 AM + */ +public class AndroidCalculatorLogger implements CalculatorLogger { + + @NotNull + private static final String TAG = AndroidCalculatorLogger.class.getSimpleName(); + + @Override + public void debug(@Nullable String tag, @NotNull String message) { + Log.d(getTag(tag), message); + } + + @NotNull + private String getTag(@Nullable String tag) { + return tag != null ? tag : TAG; + } + + @Override + public void debug(@Nullable String tag, @NotNull String message, @NotNull Throwable e) { + Log.d(getTag(tag), message, e); + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java index ab76d96f..d4b7ef59 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorApplication.java @@ -86,7 +86,8 @@ public class CalculatorApplication extends android.app.Application { new AndroidCalculatorEngine(this), new AndroidCalculatorClipboard(this), new AndroidCalculatorNotifier(this), - new AndroidCalculatorHistory(this, calculator)); + new AndroidCalculatorHistory(this, calculator), + new AndroidCalculatorLogger()); CalculatorLocatorImpl.getInstance().getCalculator().init(); diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorButtons.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorButtons.java index db0eeaa7..27ae4778 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorButtons.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorButtons.java @@ -75,17 +75,8 @@ public final class CalculatorButtons { if (equalsButton != null) { if (CalculatorPreferences.Gui.showEqualsButton.getPreference(preferences)) { equalsButton.setVisibility(View.VISIBLE); - final AndroidCalculatorDisplayView calculatorDisplayView = getCalculatorDisplayView(); - if (calculatorDisplayView != null) { - calculatorDisplayView.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null); - } } else { equalsButton.setVisibility(View.GONE); - // mobile phones - final AndroidCalculatorDisplayView calculatorDisplayView = getCalculatorDisplayView(); - if (calculatorDisplayView != null) { - calculatorDisplayView.setCompoundDrawablesWithIntrinsicBounds(activity.getResources().getDrawable(R.drawable.equals9), null, null, null); - } } } } diff --git a/calculatorpp/src/test/java/org/solovyev/android/calculator/CalculatorTestUtils.java b/calculatorpp/src/test/java/org/solovyev/android/calculator/CalculatorTestUtils.java index 31fd2bd0..ecc184bf 100644 --- a/calculatorpp/src/test/java/org/solovyev/android/calculator/CalculatorTestUtils.java +++ b/calculatorpp/src/test/java/org/solovyev/android/calculator/CalculatorTestUtils.java @@ -13,7 +13,7 @@ import org.solovyev.android.calculator.history.CalculatorHistory; public class CalculatorTestUtils { public static void staticSetUp() throws Exception { - CalculatorLocatorImpl.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class)); + CalculatorLocatorImpl.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), null); CalculatorLocatorImpl.getInstance().getEngine().init(); }