Otto bus is added to the project

This commit is contained in:
serso 2016-01-09 22:48:36 +01:00
parent 21b56bbe59
commit 5e1c47963c
19 changed files with 375 additions and 604 deletions

View File

@ -97,6 +97,7 @@ dependencies {
exclude(module: 'xpp3') exclude(module: 'xpp3')
} }
compile 'commons-cli:commons-cli:1.2' compile 'commons-cli:commons-cli:1.2'
compile 'com.squareup:otto:1.3.8'
testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
testCompile 'net.sf.opencsv:opencsv:2.0' testCompile 'net.sf.opencsv:opencsv:2.0'
testCompile 'org.mockito:mockito-core:1.9.0' testCompile 'org.mockito:mockito-core:1.9.0'

View File

@ -40,6 +40,7 @@ import android.support.v4.app.FragmentTransaction;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import com.squareup.otto.Bus;
import org.solovyev.android.Check; import org.solovyev.android.Check;
import org.solovyev.android.UiThreadExecutor; import org.solovyev.android.UiThreadExecutor;
import org.solovyev.android.Views; import org.solovyev.android.Views;
@ -97,7 +98,7 @@ public final class App {
@Nonnull @Nonnull
private static volatile DelayedExecutor uiThreadExecutor; private static volatile DelayedExecutor uiThreadExecutor;
@Nonnull @Nonnull
private static volatile JEventListeners<JEventListener<? extends JEvent>, JEvent> eventBus; private static Bus bus;
private static volatile boolean initialized; private static volatile boolean initialized;
@Nonnull @Nonnull
private static CalculatorBroadcaster broadcaster; private static CalculatorBroadcaster broadcaster;
@ -138,7 +139,7 @@ public final class App {
App.application = application; App.application = application;
App.preferences = PreferenceManager.getDefaultSharedPreferences(application); App.preferences = PreferenceManager.getDefaultSharedPreferences(application);
App.uiThreadExecutor = uiThreadExecutor; App.uiThreadExecutor = uiThreadExecutor;
App.eventBus = eventBus; App.bus = new MyBus();
App.ga = new Ga(application, preferences, eventBus); App.ga = new Ga(application, preferences, eventBus);
App.billing = new Billing(application, new Billing.DefaultConfiguration() { App.billing = new Billing(application, new Billing.DefaultConfiguration() {
@Nonnull @Nonnull
@ -157,7 +158,7 @@ public final class App {
} }
} }
}); });
App.broadcaster = new CalculatorBroadcaster(application, preferences); App.broadcaster = new CalculatorBroadcaster(application, preferences, bus);
App.screenMetrics = new ScreenMetrics(application); App.screenMetrics = new ScreenMetrics(application);
App.languages = languages; App.languages = languages;
App.wizards = new CalculatorWizards(application); App.wizards = new CalculatorWizards(application);
@ -195,8 +196,8 @@ public final class App {
* @return application's event bus * @return application's event bus
*/ */
@Nonnull @Nonnull
public static JEventListeners<JEventListener<? extends JEvent>, JEvent> getEventBus() { public static Bus getBus() {
return eventBus; return bus;
} }
@Nonnull @Nonnull
@ -322,4 +323,20 @@ public final class App {
// NOTE: this code is only for monkeyrunner // NOTE: this code is only for monkeyrunner
return context.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) == PackageManager.PERMISSION_GRANTED; return context.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) == PackageManager.PERMISSION_GRANTED;
} }
private static class MyBus extends Bus {
@Override
public void post(final Object event) {
if (Looper.myLooper() == Looper.getMainLooper()) {
super.post(event);
return;
}
handler.post(new Runnable() {
@Override
public void run() {
MyBus.super.post(event);
}
});
}
}
} }

View File

@ -25,7 +25,6 @@ package org.solovyev.android.calculator;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.Log; import android.util.Log;
import android.util.TimingLogger;
import com.squareup.leakcanary.LeakCanary; import com.squareup.leakcanary.LeakCanary;
import org.acra.ACRA; import org.acra.ACRA;
import org.acra.ACRAConfiguration; import org.acra.ACRAConfiguration;
@ -89,8 +88,6 @@ public class CalculatorApplication extends android.app.Application implements Sh
calculator.addCalculatorEventListener(listener); calculator.addCalculatorEventListener(listener);
} }
calculator.addCalculatorEventListener(App.getBroadcaster());
Locator.getInstance().getCalculator().init(); Locator.getInstance().getCalculator().init();
App.getInitializer().execute(new Runnable() { App.getInitializer().execute(new Runnable() {
@ -146,7 +143,7 @@ public class CalculatorApplication extends android.app.Application implements Sh
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (Preferences.Onscreen.showAppIcon.getKey().equals(key)) { if (Preferences.Onscreen.showAppIcon.getKey().equals(key)) {
boolean showAppIcon = Preferences.Onscreen.showAppIcon.getPreference(prefs); boolean showAppIcon = Preferences.Onscreen.showAppIcon.getPreference(prefs);
Android.toggleComponent(this, CalculatorOnscreenStartActivity.class, showAppIcon); Android.enableComponent(this, CalculatorOnscreenStartActivity.class, showAppIcon);
Locator.getInstance().getNotifier().showMessage(R.string.cpp_this_change_may_require_reboot, MessageType.info); Locator.getInstance().getNotifier().showMessage(R.string.cpp_this_change_may_require_reboot, MessageType.info);
} }
} }

View File

@ -3,13 +3,15 @@ package org.solovyev.android.calculator;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
public final class CalculatorBroadcaster implements CalculatorEventListener, SharedPreferences.OnSharedPreferenceChangeListener { public final class CalculatorBroadcaster implements SharedPreferences.OnSharedPreferenceChangeListener {
public static final String ACTION_INIT = "org.solovyev.android.calculator.INIT"; public static final String ACTION_INIT = "org.solovyev.android.calculator.INIT";
public static final String ACTION_EDITOR_STATE_CHANGED = "org.solovyev.android.calculator.EDITOR_STATE_CHANGED"; public static final String ACTION_EDITOR_STATE_CHANGED = "org.solovyev.android.calculator.EDITOR_STATE_CHANGED";
@ -22,18 +24,24 @@ public final class CalculatorBroadcaster implements CalculatorEventListener, Sha
@Nonnull @Nonnull
private final Intents intents = new Intents(); private final Intents intents = new Intents();
public CalculatorBroadcaster(@Nonnull Context context, @Nonnull SharedPreferences preferences) { public CalculatorBroadcaster(@Nonnull Context context, @Nonnull SharedPreferences preferences, @Nonnull Bus bus) {
this.context = context; this.context = context;
preferences.registerOnSharedPreferenceChangeListener(this); preferences.registerOnSharedPreferenceChangeListener(this);
bus.register(this);
}
@Subscribe
public void onEditorChanged(@Nonnull Editor.ChangedEvent e) {
sendBroadcastIntent(ACTION_EDITOR_STATE_CHANGED);
}
@Subscribe
public void onCursorMoved(@Nonnull Editor.CursorMovedEvent e) {
sendBroadcastIntent(ACTION_EDITOR_STATE_CHANGED);
} }
@Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) { public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) {
switch (calculatorEventType) { switch (calculatorEventType) {
case editor_state_changed:
case editor_state_changed_light:
sendBroadcastIntent(ACTION_EDITOR_STATE_CHANGED);
break;
case display_state_changed: case display_state_changed:
sendBroadcastIntent(ACTION_DISPLAY_STATE_CHANGED); sendBroadcastIntent(ACTION_DISPLAY_STATE_CHANGED);
break; break;

View File

@ -1,62 +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 final class CalculatorEditorChangeEventData implements Change<EditorState> {
@Nonnull
private EditorState oldState;
@Nonnull
private EditorState newState;
private CalculatorEditorChangeEventData(@Nonnull EditorState oldState,
@Nonnull EditorState newState) {
this.oldState = oldState;
this.newState = newState;
}
public static CalculatorEditorChangeEventData newChangeEventData(@Nonnull EditorState oldState,
@Nonnull EditorState newState) {
return new CalculatorEditorChangeEventData(oldState, newState);
}
@Nonnull
@Override
public EditorState getOldValue() {
return this.oldState;
}
@Nonnull
@Override
public EditorState getNewValue() {
return this.newState;
}
}

View File

@ -25,33 +25,27 @@ package org.solovyev.android.calculator;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
/**
* User: Solovyev_S
* Date: 20.09.12
* Time: 18:18
*/
class CalculatorEventDataImpl implements CalculatorEventData { class CalculatorEventDataImpl implements CalculatorEventData {
private static final long NO_SEQUENCE = -1L; private static final long NO_SEQUENCE = -1L;
private final long eventId; private final long eventId;
private final Object source; private final Object source;
@Nonnull private final long sequenceId;
private Long sequenceId = NO_SEQUENCE;
private CalculatorEventDataImpl(long id, @Nonnull Long sequenceId, @Nullable Object source) { private CalculatorEventDataImpl(long id, long sequenceId, @Nullable Object source) {
this.eventId = id; this.eventId = id;
this.sequenceId = sequenceId; this.sequenceId = sequenceId;
this.source = source; this.source = source;
} }
@Nonnull @Nonnull
static CalculatorEventData newInstance(long id, @Nonnull Long sequenceId) { static CalculatorEventData newInstance(long id, long sequenceId) {
return new CalculatorEventDataImpl(id, sequenceId, null); return new CalculatorEventDataImpl(id, sequenceId, null);
} }
@Nonnull @Nonnull
static CalculatorEventData newInstance(long id, @Nonnull Long sequenceId, @Nonnull Object source) { static CalculatorEventData newInstance(long id, long sequenceId, @Nonnull Object source) {
return new CalculatorEventDataImpl(id, sequenceId, source); return new CalculatorEventDataImpl(id, sequenceId, source);
} }
@ -78,12 +72,24 @@ class CalculatorEventDataImpl implements CalculatorEventData {
@Override @Override
public boolean isSameSequence(@Nonnull CalculatorEventData that) { public boolean isSameSequence(@Nonnull CalculatorEventData that) {
return !this.sequenceId.equals(NO_SEQUENCE) && this.sequenceId.equals(that.getSequenceId()); if (this.sequenceId == NO_SEQUENCE) {
return false;
}
if (this.sequenceId == that.getSequenceId()) {
return true;
}
return false;
} }
@Override @Override
public boolean isAfterSequence(@Nonnull CalculatorEventData that) { public boolean isAfterSequence(@Nonnull CalculatorEventData that) {
return !this.sequenceId.equals(NO_SEQUENCE) && this.sequenceId > that.getSequenceId(); if (this.sequenceId == NO_SEQUENCE) {
return false;
}
if (this.sequenceId > that.getSequenceId()) {
return true;
}
return false;
} }
@Override @Override
@ -94,8 +100,7 @@ class CalculatorEventDataImpl implements CalculatorEventData {
CalculatorEventDataImpl that = (CalculatorEventDataImpl) o; CalculatorEventDataImpl that = (CalculatorEventDataImpl) o;
if (eventId != that.eventId) return false; if (eventId != that.eventId) return false;
if (!sequenceId.equals(that.sequenceId)) if (sequenceId != that.sequenceId) return false;
return false;
return true; return true;
} }
@ -103,7 +108,7 @@ class CalculatorEventDataImpl implements CalculatorEventData {
@Override @Override
public int hashCode() { public int hashCode() {
int result = (int) (eventId ^ (eventId >>> 32)); int result = (int) (eventId ^ (eventId >>> 32));
result = 31 * result + (sequenceId.hashCode()); result = 31 * result + (int) (sequenceId ^ (sequenceId >>> 32));
return result; return result;
} }
} }

View File

@ -78,10 +78,6 @@ public enum CalculatorEventType {
********************************************************************** **********************************************************************
*/ */
// @Nonnull org.solovyev.android.calculator.CalculatorEditorChangeEventData
editor_state_changed,
editor_state_changed_light,
// @Nonnull CalculatorDisplayChangeEventData // @Nonnull CalculatorDisplayChangeEventData
display_state_changed, display_state_changed,

View File

@ -22,6 +22,16 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.text.TextUtils;
import com.squareup.otto.Subscribe;
import jscl.AbstractJsclArithmeticException;
import jscl.NumeralBase;
import jscl.NumeralBaseException;
import jscl.math.Generic;
import jscl.math.function.Function;
import jscl.math.function.IConstant;
import jscl.math.operator.Operator;
import jscl.text.ParseInterruptedException;
import org.solovyev.android.calculator.history.CalculatorHistory; import org.solovyev.android.calculator.history.CalculatorHistory;
import org.solovyev.android.calculator.history.HistoryState; import org.solovyev.android.calculator.history.HistoryState;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.jscl.JsclOperation;
@ -37,24 +47,14 @@ import org.solovyev.common.text.Strings;
import org.solovyev.common.units.ConversionException; import org.solovyev.common.units.ConversionException;
import org.solovyev.common.units.Conversions; import org.solovyev.common.units.Conversions;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import jscl.AbstractJsclArithmeticException;
import jscl.NumeralBase;
import jscl.NumeralBaseException;
import jscl.math.Generic;
import jscl.math.function.Function;
import jscl.math.function.IConstant;
import jscl.math.operator.Operator;
import jscl.text.ParseInterruptedException;
/** /**
* User: Solovyev_S * User: Solovyev_S
* Date: 20.09.12 * Date: 20.09.12
@ -102,25 +102,11 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
private volatile long lastPreferenceCheck = 0L; private volatile long lastPreferenceCheck = 0L;
/*
**********************************************************************
*
* CONSTRUCTORS
*
**********************************************************************
*/
public CalculatorImpl() { public CalculatorImpl() {
App.getBus().register(this);
this.addCalculatorEventListener(this); this.addCalculatorEventListener(this);
} }
/*
**********************************************************************
*
* METHODS
*
**********************************************************************
*/
@Nonnull @Nonnull
private static String doConversion(@Nonnull Generic generic, private static String doConversion(@Nonnull Generic generic,
@ -159,15 +145,7 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
return CalculatorEventDataImpl.newInstance(eventId, eventId, source); return CalculatorEventDataImpl.newInstance(eventId, eventId, source);
} }
/* @Nonnull
**********************************************************************
*
* CALCULATION
*
**********************************************************************
*/
@Nonnull
private CalculatorEventData nextEventData(@Nonnull Long sequenceId) { private CalculatorEventData nextEventData(@Nonnull Long sequenceId) {
long eventId = counter.incrementAndGet(); long eventId = counter.incrementAndGet();
return CalculatorEventDataImpl.newInstance(eventId, sequenceId); return CalculatorEventDataImpl.newInstance(eventId, sequenceId);
@ -497,31 +475,21 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
return eventData; return eventData;
} }
/* @Subscribe
********************************************************************** public void onEditorChanged(@Nonnull Editor.ChangedEvent e) {
* if (!calculateOnFly) {
* EVENTS HANDLER return;
* }
********************************************************************** if (TextUtils.equals(e.newState.text, e.oldState.text)) {
*/ return;
}
evaluate(JsclOperation.numeric, e.newState.getTextString(), e.newState.id);
}
@Override @Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) { public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) {
switch (calculatorEventType) { switch (calculatorEventType) {
case editor_state_changed:
if (calculateOnFly) {
final CalculatorEditorChangeEventData editorChangeEventData = (CalculatorEditorChangeEventData) data;
final String newText = editorChangeEventData.getNewValue().getTextString();
final String oldText = editorChangeEventData.getOldValue().getTextString();
if (!newText.equals(oldText)) {
evaluate(JsclOperation.numeric, editorChangeEventData.getNewValue().getTextString(), calculatorEventData.getSequenceId());
}
}
break;
case display_state_changed: case display_state_changed:
onDisplayStateChanged((CalculatorDisplayChangeEventData) data); onDisplayStateChanged((CalculatorDisplayChangeEventData) data);
break; break;

View File

@ -23,8 +23,8 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import org.solovyev.android.Check; import org.solovyev.android.Check;
import org.solovyev.android.calculator.history.HistoryState;
import org.solovyev.android.calculator.history.EditorHistoryState; import org.solovyev.android.calculator.history.EditorHistoryState;
import org.solovyev.android.calculator.history.HistoryState;
import org.solovyev.android.calculator.text.TextProcessor; import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.calculator.text.TextProcessorEditorResult; import org.solovyev.android.calculator.text.TextProcessorEditorResult;
import org.solovyev.common.text.Strings; import org.solovyev.common.text.Strings;
@ -33,16 +33,32 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static java.lang.Math.min; import static java.lang.Math.min;
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;
public class Editor implements CalculatorEventListener { public class Editor implements CalculatorEventListener {
private static final String TAG = App.subTag("Editor"); private static final String TAG = App.subTag("Editor");
@Nonnull public static class ChangedEvent {
private final Calculator calculator; @Nonnull
public final EditorState oldState;
@Nonnull
public final EditorState newState;
private ChangedEvent(@Nonnull EditorState oldState, @Nonnull EditorState newState) {
this.oldState = oldState;
this.newState = newState;
}
}
public static class CursorMovedEvent {
@Nonnull
public final EditorState state;
public CursorMovedEvent(@Nonnull EditorState state) {
this.state = state;
}
}
@Nonnull @Nonnull
private final CalculatorEventHolder lastEventHolder; private final CalculatorEventHolder lastEventHolder;
@Nullable @Nullable
@ -53,9 +69,8 @@ public class Editor implements CalculatorEventListener {
private EditorState state = EditorState.empty(); private EditorState state = EditorState.empty();
public Editor(@Nonnull Calculator calculator, @Nullable TextProcessor<TextProcessorEditorResult, String> textProcessor) { public Editor(@Nonnull Calculator calculator, @Nullable TextProcessor<TextProcessorEditorResult, String> textProcessor) {
this.calculator = calculator;
this.textProcessor = textProcessor; this.textProcessor = textProcessor;
this.calculator.addCalculatorEventListener(this); calculator.addCalculatorEventListener(this);
this.lastEventHolder = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId()); this.lastEventHolder = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
} }
@ -85,11 +100,7 @@ public class Editor implements CalculatorEventListener {
return state; return state;
} }
public void setState(@Nonnull EditorState state) { public void onTextChanged(@Nonnull EditorState newState) {
setState(state, true);
}
private void setState(@Nonnull EditorState newState, boolean majorChanges) {
Check.isMainThread(); Check.isMainThread();
if (textProcessor != null) { if (textProcessor != null) {
try { try {
@ -104,17 +115,16 @@ public class Editor implements CalculatorEventListener {
if (view != null) { if (view != null) {
view.setState(newState); view.setState(newState);
} }
fireStateChangedEvent(majorChanges, oldState, newState); App.getBus().post(new ChangedEvent(oldState, newState));
} }
private void fireStateChangedEvent(boolean majorChanges, @Nonnull EditorState oldViewState, @Nonnull EditorState newViewState) { private void onSelectionChanged(@Nonnull EditorState newState) {
Check.isMainThread(); Check.isMainThread();
state = newState;
if (majorChanges) { if (view != null) {
calculator.fireCalculatorEvent(editor_state_changed, newChangeEventData(oldViewState, newViewState)); view.setState(newState);
} else {
calculator.fireCalculatorEvent(editor_state_changed_light, newChangeEventData(oldViewState, newViewState));
} }
App.getBus().post(new CursorMovedEvent(newState));
} }
@Override @Override
@ -139,9 +149,9 @@ public class Editor implements CalculatorEventListener {
private EditorState newSelectionViewState(int newSelection) { private EditorState newSelectionViewState(int newSelection) {
Check.isMainThread(); Check.isMainThread();
if (state.selection != newSelection) { if (state.selection != newSelection) {
final EditorState result = EditorState.newSelection(state, newSelection); final EditorState newState = EditorState.forNewSelection(state, newSelection);
setState(result, false); onSelectionChanged(newState);
return result; return newState;
} else { } else {
return state; return state;
} }
@ -186,7 +196,7 @@ public class Editor implements CalculatorEventListener {
final String text = state.getTextString(); final String text = state.getTextString();
if (selection > 0 && text.length() > 0 && selection <= text.length()) { if (selection > 0 && text.length() > 0 && selection <= text.length()) {
final EditorState newState = EditorState.create(text.substring(0, selection - 1) + text.substring(selection, text.length()), selection - 1); final EditorState newState = EditorState.create(text.substring(0, selection - 1) + text.substring(selection, text.length()), selection - 1);
setState(newState); onTextChanged(newState);
return newState; return newState;
} else { } else {
return state; return state;
@ -203,18 +213,16 @@ public class Editor implements CalculatorEventListener {
public EditorState setText(@Nonnull String text) { public EditorState setText(@Nonnull String text) {
Check.isMainThread(); Check.isMainThread();
final EditorState result = EditorState.create(text, text.length()); final EditorState result = EditorState.create(text, text.length());
setState(result); onTextChanged(result);
return result; return result;
} }
@Nonnull @Nonnull
public EditorState setText(@Nonnull String text, int selection) { public EditorState setText(@Nonnull String text, int selection) {
Check.isMainThread(); Check.isMainThread();
selection = clamp(selection, text); final EditorState state = EditorState.create(text, clamp(selection, text));
onTextChanged(state);
final EditorState result = EditorState.create(text, selection); return state;
setState(result);
return result;
} }
@Nonnull @Nonnull
@ -233,7 +241,7 @@ public class Editor implements CalculatorEventListener {
int newSelection = clamp(text.length() + selection + selectionOffset, newTextLength); int newSelection = clamp(text.length() + selection + selectionOffset, newTextLength);
final EditorState newState = EditorState.create(oldText.substring(0, selection) + text + oldText.substring(selection), newSelection); final EditorState newState = EditorState.create(oldText.substring(0, selection) + text + oldText.substring(selection), newSelection);
setState(newState); onTextChanged(newState);
return newState; return newState;
} }
@ -249,8 +257,8 @@ public class Editor implements CalculatorEventListener {
Check.isMainThread(); Check.isMainThread();
selection = clamp(selection, state.text); selection = clamp(selection, state.text);
final EditorState result = EditorState.newSelection(state, selection); final EditorState result = EditorState.forNewSelection(state, selection);
setState(result, false); onSelectionChanged(result);
return result; return result;
} }

View File

@ -22,13 +22,16 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import java.io.Serializable; import org.solovyev.android.Check;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class EditorState implements Serializable { public class EditorState {
private static long counter;
public final long id;
@Nonnull @Nonnull
public final CharSequence text; public final CharSequence text;
public final int selection; public final int selection;
@ -40,6 +43,8 @@ public class EditorState implements Serializable {
} }
private EditorState(@Nonnull CharSequence text, int selection) { private EditorState(@Nonnull CharSequence text, int selection) {
Check.isMainThread();
this.id = counter++;
this.text = text; this.text = text;
this.selection = selection; this.selection = selection;
} }
@ -50,7 +55,7 @@ public class EditorState implements Serializable {
} }
@Nonnull @Nonnull
public static EditorState newSelection(@Nonnull EditorState state, int selection) { public static EditorState forNewSelection(@Nonnull EditorState state, int selection) {
return new EditorState(state.text, selection); return new EditorState(state.text, selection);
} }

View File

@ -22,6 +22,7 @@
package org.solovyev.android.calculator.history; package org.solovyev.android.calculator.history;
import com.squareup.otto.Subscribe;
import org.solovyev.android.calculator.*; 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;
@ -54,6 +55,7 @@ public class CalculatorHistoryImpl implements CalculatorHistory {
public CalculatorHistoryImpl(@Nonnull Calculator calculator) { public CalculatorHistoryImpl(@Nonnull Calculator calculator) {
calculator.addCalculatorEventListener(this); calculator.addCalculatorEventListener(this);
App.getBus().register(this);
} }
@Override @Override
@ -242,11 +244,16 @@ public class CalculatorHistoryImpl implements CalculatorHistory {
this.savedHistory.remove(historyState); this.savedHistory.remove(historyState);
} }
@Subscribe
public void onEditorChanged(@Nonnull Editor.ChangedEvent e) {
lastEditorViewState = e.newState;
}
@Override @Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData,
@Nonnull CalculatorEventType calculatorEventType, @Nonnull CalculatorEventType calculatorEventType,
@Nullable Object data) { @Nullable Object data) {
if (calculatorEventType.isOfType(editor_state_changed, display_state_changed, manual_calculation_requested)) { if (calculatorEventType.isOfType(display_state_changed, manual_calculation_requested)) {
final CalculatorEventHolder.Result result = lastEventData.apply(calculatorEventData); final CalculatorEventHolder.Result result = lastEventData.apply(calculatorEventData);
@ -255,10 +262,6 @@ public class CalculatorHistoryImpl implements CalculatorHistory {
case manual_calculation_requested: case manual_calculation_requested:
lastEditorViewState = (EditorState) data; lastEditorViewState = (EditorState) data;
break; break;
case editor_state_changed:
final CalculatorEditorChangeEventData editorChangeData = (CalculatorEditorChangeEventData) data;
lastEditorViewState = editorChangeData.getNewValue();
break;
case display_state_changed: case display_state_changed:
if (result.isSameSequence()) { if (result.isSameSequence()) {
if (lastEditorViewState != null) { if (lastEditorViewState != null) {

View File

@ -31,6 +31,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
@Root @Root
@ -77,6 +78,10 @@ public class History {
items.add(state); items.add(state);
} }
public void addAll(@Nonnull Collection<HistoryState> states) {
items.addAll(states);
}
public void clear() { public void clear() {
items.clear(); items.clear();
} }

View File

@ -33,16 +33,10 @@ import android.support.v4.app.NotificationCompat;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.view.WindowManager; import android.view.WindowManager;
import com.squareup.otto.Subscribe;
import org.solovyev.android.Check;
import org.solovyev.android.Views; import org.solovyev.android.Views;
import org.solovyev.android.calculator.App; import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.CalculatorDisplayChangeEventData;
import org.solovyev.android.calculator.CalculatorEditorChangeEventData;
import org.solovyev.android.calculator.CalculatorEventData;
import org.solovyev.android.calculator.CalculatorEventListener;
import org.solovyev.android.calculator.CalculatorEventType;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.Preferences;
import org.solovyev.android.calculator.R;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -58,13 +52,9 @@ public class CalculatorOnscreenService extends Service implements OnscreenViewLi
private static final String SHOW_WINDOW_ACTION = "org.solovyev.android.calculator.onscreen.SHOW_WINDOW"; private static final String SHOW_WINDOW_ACTION = "org.solovyev.android.calculator.onscreen.SHOW_WINDOW";
private static final String SHOW_NOTIFICATION_ACTION = "org.solovyev.android.calculator.onscreen.SHOW_NOTIFICATION"; private static final String SHOW_NOTIFICATION_ACTION = "org.solovyev.android.calculator.onscreen.SHOW_NOTIFICATION";
private static final int NOTIFICATION_ID = 9031988; // my birthday =) private static final int NOTIFICATION_ID = 9031988; // my birthday =)
@Nonnull
private CalculatorOnscreenView view; private CalculatorOnscreenView view;
private boolean compatibilityStart = true;
private boolean viewCreated = false;
@Nonnull @Nonnull
private static Class<?> getIntentListenerClass() { private static Class<?> getIntentListenerClass() {
return INTENT_LISTENER_CLASS; return INTENT_LISTENER_CLASS;
@ -93,98 +83,68 @@ public class CalculatorOnscreenService extends Service implements OnscreenViewLi
return null; return null;
} }
@Override
public void onCreate() {
super.onCreate();
App.getPreferences().registerOnSharedPreferenceChangeListener(this);
}
private void createView() { private void createView() {
if (!viewCreated) { if (view != null) {
final WindowManager wm = ((WindowManager) this.getSystemService(Context.WINDOW_SERVICE)); return;
final DisplayMetrics dm = getResources().getDisplayMetrics();
int twoThirdWidth = 2 * wm.getDefaultDisplay().getWidth() / 3;
int twoThirdHeight = 2 * wm.getDefaultDisplay().getHeight() / 3;
twoThirdWidth = Math.min(twoThirdWidth, twoThirdHeight);
twoThirdHeight = Math.max(twoThirdWidth, getHeight(twoThirdWidth));
final int baseWidth = Views.toPixels(dm, 300);
final int width0 = Math.min(twoThirdWidth, baseWidth);
final int height0 = Math.min(twoThirdHeight, getHeight(baseWidth));
final int width = Math.min(width0, height0);
final int height = Math.max(width0, height0);
view = CalculatorOnscreenView.create(this, CalculatorOnscreenViewState.create(width, height, -1, -1), this);
view.show();
startCalculatorListening();
view.updateEditorState(Locator.getInstance().getEditor().getState());
view.updateDisplayState(Locator.getInstance().getDisplay().getViewState());
viewCreated = true;
} }
final WindowManager wm = ((WindowManager) this.getSystemService(Context.WINDOW_SERVICE));
final DisplayMetrics dm = getResources().getDisplayMetrics();
int twoThirdWidth = 2 * wm.getDefaultDisplay().getWidth() / 3;
int twoThirdHeight = 2 * wm.getDefaultDisplay().getHeight() / 3;
twoThirdWidth = Math.min(twoThirdWidth, twoThirdHeight);
twoThirdHeight = Math.max(twoThirdWidth, getHeight(twoThirdWidth));
final int baseWidth = Views.toPixels(dm, 300);
final int width0 = Math.min(twoThirdWidth, baseWidth);
final int height0 = Math.min(twoThirdHeight, getHeight(baseWidth));
final int width = Math.min(width0, height0);
final int height = Math.max(width0, height0);
view = CalculatorOnscreenView.create(this, CalculatorOnscreenViewState.create(width, height, -1, -1), this);
view.show();
view.updateEditorState(Locator.getInstance().getEditor().getState());
view.updateDisplayState(Locator.getInstance().getDisplay().getViewState());
App.getBus().register(this);
App.getPreferences().registerOnSharedPreferenceChangeListener(this);
} }
private int getHeight(int width) { private int getHeight(int width) {
return 4 * width / 3; return 4 * width / 3;
} }
private void startCalculatorListening() {
Locator.getInstance().getCalculator().addCalculatorEventListener(this);
}
private void stopCalculatorListening() {
Locator.getInstance().getCalculator().removeCalculatorEventListener(this);
}
@Override @Override
public void onDestroy() { public void onDestroy() {
App.getPreferences().unregisterOnSharedPreferenceChangeListener(this); if (view != null) {
stopCalculatorListening(); App.getPreferences().unregisterOnSharedPreferenceChangeListener(this);
if (viewCreated) { App.getBus().unregister(this);
this.view.hide(); view.hide();
view = null;
} }
super.onDestroy(); super.onDestroy();
} }
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
if (this.compatibilityStart) {
handleStart(intent);
}
}
@Override @Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
final int result = super.onStartCommand(intent, flags, startId);
final int result; handleStart(intent);
try {
this.compatibilityStart = false;
result = super.onStartCommand(intent, flags, startId);
handleStart(intent);
} finally {
this.compatibilityStart = true;
}
return result; return result;
} }
private void handleStart(@Nullable Intent intent) { private void handleStart(@Nullable Intent intent) {
if (intent != null) { if (intent == null) {
return;
if (isShowWindowIntent(intent)) { }
hideNotification(); if (isShowWindowIntent(intent)) {
createView(); hideNotification();
App.getGa().onFloatingCalculatorOpened(); createView();
} else if (isShowNotificationIntent(intent)) { App.getGa().onFloatingCalculatorOpened();
showNotification(); } else if (isShowNotificationIntent(intent)) {
} showNotification();
} }
} }
@ -229,10 +189,6 @@ public class CalculatorOnscreenService extends Service implements OnscreenViewLi
@Override @Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) { public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) {
switch (calculatorEventType) { switch (calculatorEventType) {
case editor_state_changed:
case editor_state_changed_light:
view.updateEditorState(((CalculatorEditorChangeEventData) data).getNewValue());
break;
case display_state_changed: case display_state_changed:
view.updateDisplayState(((CalculatorDisplayChangeEventData) data).getNewValue()); view.updateDisplayState(((CalculatorDisplayChangeEventData) data).getNewValue());
break; break;
@ -241,12 +197,23 @@ public class CalculatorOnscreenService extends Service implements OnscreenViewLi
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (viewCreated) { Check.isNotNull(view);
if (Preferences.Gui.theme.isSameKey(key) || Preferences.Onscreen.theme.isSameKey(key)) { if (Preferences.Gui.theme.isSameKey(key) || Preferences.Onscreen.theme.isSameKey(key)) {
stopSelf(); stopSelf();
CalculatorOnscreenService.showOnscreenView(this); CalculatorOnscreenService.showOnscreenView(this);
}
} }
} }
@Subscribe
public void onEditorChanged(@Nonnull Editor.ChangedEvent e) {
Check.isNotNull(view);
view.updateEditorState(e.newState);
}
@Subscribe
public void onCursorMoved(@Nonnull Editor.CursorMovedEvent e) {
Check.isNotNull(view);
view.updateEditorState(e.state);
}
} }

View File

@ -30,27 +30,14 @@ import android.graphics.drawable.Drawable;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import android.view.Gravity; import android.view.*;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView; import android.widget.ImageView;
import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.AndroidCalculatorDisplayView;
import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.CalculatorButton;
import org.solovyev.android.calculator.DisplayState;
import org.solovyev.android.calculator.EditorState;
import org.solovyev.android.calculator.EditorView;
import org.solovyev.android.calculator.Preferences;
import org.solovyev.android.calculator.R;
import org.solovyev.android.prefs.Preference; import org.solovyev.android.prefs.Preference;
import java.util.Locale;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Locale;
/** /**
* User: serso * User: serso
@ -123,24 +110,12 @@ public class CalculatorOnscreenView {
********************************************************************** **********************************************************************
*/ */
private boolean minimized = false; private boolean minimized;
private boolean attached;
private boolean folded;
private boolean initialized;
private boolean shown;
private boolean attached = false;
private boolean folded = false;
private boolean initialized = false;
private boolean hidden = true;
/*
**********************************************************************
*
* CONSTRUCTORS
*
**********************************************************************
*/
private CalculatorOnscreenView() { private CalculatorOnscreenView() {
} }
@ -167,14 +142,6 @@ public class CalculatorOnscreenView {
return result; return result;
} }
/*
**********************************************************************
*
* METHODS
*
**********************************************************************
*/
public static void persistState(@Nonnull Context context, @Nonnull CalculatorOnscreenViewState state) { public static void persistState(@Nonnull Context context, @Nonnull CalculatorOnscreenViewState state) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
viewStatePreference.putPreference(preferences, state); viewStatePreference.putPreference(preferences, state);
@ -195,14 +162,6 @@ public class CalculatorOnscreenView {
displayView.setState(displayState); displayView.setState(displayState);
} }
/*
**********************************************************************
*
* LIFECYCLE
*
**********************************************************************
*/
public void updateEditorState(@Nonnull EditorState editorState) { public void updateEditorState(@Nonnull EditorState editorState) {
checkInit(); checkInit();
editorView.setState(editorState); editorView.setState(editorState);
@ -212,86 +171,86 @@ public class CalculatorOnscreenView {
checkInit(); checkInit();
final WindowManager.LayoutParams params = (WindowManager.LayoutParams) root.getLayoutParams(); final WindowManager.LayoutParams params = (WindowManager.LayoutParams) root.getLayoutParams();
params.height = height; params.height = height;
getWindowManager().updateViewLayout(root, params); getWindowManager().updateViewLayout(root, params);
} }
private void init() { private void init() {
if (initialized) {
return;
}
if (!initialized) { for (final CalculatorButton widgetButton : CalculatorButton.values()) {
for (final CalculatorButton widgetButton : CalculatorButton.values()) { final View button = root.findViewById(widgetButton.getButtonId());
final View button = root.findViewById(widgetButton.getButtonId()); if (button == null) {
if (button != null) { continue;
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (widgetButton.onClick()) {
v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
}
if (widgetButton == CalculatorButton.app) {
minimize();
}
}
});
button.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (widgetButton.onLongClick()) {
v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
}
return true;
}
});
}
} }
button.setOnClickListener(new View.OnClickListener() {
final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
header = root.findViewById(R.id.onscreen_header);
headerTitle = (ImageView) header.findViewById(R.id.onscreen_title);
headerTitleDrawable = headerTitle.getDrawable();
headerTitle.setImageDrawable(null);
content = root.findViewById(R.id.onscreen_content);
displayView = (AndroidCalculatorDisplayView) root.findViewById(R.id.calculator_display);
displayView.init(this.context, false);
editorView = (EditorView) root.findViewById(R.id.calculator_editor);
final View onscreenFoldButton = root.findViewById(R.id.onscreen_fold_button);
onscreenFoldButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
if (folded) { if (widgetButton.onClick()) {
unfold(); v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
} else { }
fold(); if (widgetButton == CalculatorButton.app) {
minimize();
} }
} }
}); });
button.setOnLongClickListener(new View.OnLongClickListener() {
final View onscreenHideButton = root.findViewById(R.id.onscreen_minimize_button);
onscreenHideButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public boolean onLongClick(View v) {
minimize(); if (widgetButton.onLongClick()) {
v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
}
return true;
} }
}); });
root.findViewById(R.id.onscreen_close_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
hide();
}
});
headerTitle.setOnTouchListener(new WindowDragTouchListener(wm, root));
initialized = true;
} }
final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
header = root.findViewById(R.id.onscreen_header);
headerTitle = (ImageView) header.findViewById(R.id.onscreen_title);
headerTitleDrawable = headerTitle.getDrawable();
headerTitle.setImageDrawable(null);
content = root.findViewById(R.id.onscreen_content);
displayView = (AndroidCalculatorDisplayView) root.findViewById(R.id.calculator_display);
displayView.init(this.context, false);
editorView = (EditorView) root.findViewById(R.id.calculator_editor);
final View onscreenFoldButton = root.findViewById(R.id.onscreen_fold_button);
onscreenFoldButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (folded) {
unfold();
} else {
fold();
}
}
});
final View onscreenHideButton = root.findViewById(R.id.onscreen_minimize_button);
onscreenHideButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
minimize();
}
});
root.findViewById(R.id.onscreen_close_button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
hide();
}
});
headerTitle.setOnTouchListener(new WindowDragTouchListener(wm, root));
initialized = true;
} }
private void checkInit() { private void checkInit() {
@ -301,12 +260,13 @@ public class CalculatorOnscreenView {
} }
public void show() { public void show() {
if (hidden) { if (shown) {
init(); return;
attach();
hidden = false;
} }
init();
attach();
shown = true;
} }
public void attach() { public void attach() {
@ -376,19 +336,19 @@ public class CalculatorOnscreenView {
public void hide() { public void hide() {
checkInit(); checkInit();
if (!shown) {
if (!hidden) { return;
persistState(context, getCurrentState(!folded));
detach();
if (viewListener != null) {
viewListener.onViewHidden();
}
hidden = true;
} }
persistState(context, getCurrentState(!folded));
detach();
if (viewListener != null) {
viewListener.onViewHidden();
}
shown = false;
} }
@Nonnull @Nonnull

View File

@ -30,6 +30,7 @@ import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.RobolectricGradleTestRunner; import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.solovyev.common.text.Strings; import org.solovyev.common.text.Strings;
@ -62,7 +63,7 @@ public class AndroidEditorViewTest {
@Test @Test
public void testCreation() throws Exception { public void testCreation() throws Exception {
new EditorView(CalculatorApplication.getInstance()); new EditorView(RuntimeEnvironment.application);
} }
@Test @Test

View File

@ -1,70 +0,0 @@
package org.solovyev.android.calculator;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowPreferenceManager;
import javax.annotation.Nonnull;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.robolectric.RuntimeEnvironment.application;
import static org.solovyev.android.calculator.CalculatorBroadcaster.ACTION_DISPLAY_STATE_CHANGED;
import static org.solovyev.android.calculator.CalculatorBroadcaster.ACTION_EDITOR_STATE_CHANGED;
import static org.solovyev.android.calculator.CalculatorEventType.*;
@Config(constants = BuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP)
@RunWith(RobolectricGradleTestRunner.class)
public class CalculatorBroadcasterTest {
@Nonnull
private CalculatorBroadcaster broadcaster;
@Before
public void setUp() throws Exception {
broadcaster = new CalculatorBroadcaster(application, ShadowPreferenceManager.getDefaultSharedPreferences(application));
}
@Test
public void testShouldSendEditorStateChangedIntent() throws Exception {
assertIntentSent(editor_state_changed, ACTION_EDITOR_STATE_CHANGED);
}
@Test
public void testShouldSendEditorStateChangedLiteIntent() throws Exception {
assertIntentSent(editor_state_changed_light, ACTION_EDITOR_STATE_CHANGED);
}
@Test
public void testShouldSendDisplayStateChangedIntent() throws Exception {
assertIntentSent(display_state_changed, ACTION_DISPLAY_STATE_CHANGED);
}
private void assertIntentSent(@Nonnull CalculatorEventType eventType, final String expectedAction) {
final BroadcastReceiver receiver = Mockito.mock(BroadcastReceiver.class);
application.registerReceiver(receiver, new IntentFilter(expectedAction));
broadcaster.onCalculatorEvent(CalculatorEventDataImpl.newInstance(1L, 1L), eventType, null);
verify(receiver, times(1)).onReceive(Mockito.<Context>any(), argThat(new BaseMatcher<Intent>() {
@Override
public boolean matches(Object o) {
return ((Intent) o).getAction().equals(expectedAction);
}
@Override
public void describeTo(Description description) {
}
}));
}
}

View File

@ -1,43 +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 org.junit.Assert;
import org.junit.Test;
/**
* User: serso
* Date: 10/20/12
* Time: 12:31 PM
*/
public class EditorStateTest {
@Test
public void testSerialization() throws Exception {
CalculatorTestUtils.testSerialization(EditorState.empty());
EditorState out = CalculatorTestUtils.testSerialization(EditorState.create("treter", 2));
Assert.assertEquals(2, out.getSelection());
Assert.assertEquals("treter", out.getText());
}
}

View File

@ -48,52 +48,52 @@ public class EditorTest extends AbstractCalculatorTest {
public void testInsert() throws Exception { public void testInsert() throws Exception {
EditorState viewState = this.editor.getState(); EditorState viewState = this.editor.getState();
Assert.assertEquals("", viewState.getText()); Assert.assertEquals("", viewState.getTextString());
Assert.assertEquals(0, viewState.getSelection()); Assert.assertEquals(0, viewState.selection);
viewState = this.editor.insert(""); viewState = this.editor.insert("");
Assert.assertEquals("", viewState.getText()); Assert.assertEquals("", viewState.getTextString());
Assert.assertEquals(0, viewState.getSelection()); Assert.assertEquals(0, viewState.selection);
viewState = this.editor.insert("test"); viewState = this.editor.insert("test");
Assert.assertEquals("test", viewState.getText()); Assert.assertEquals("test", viewState.getTextString());
Assert.assertEquals(4, viewState.getSelection()); Assert.assertEquals(4, viewState.selection);
viewState = this.editor.insert("test"); viewState = this.editor.insert("test");
Assert.assertEquals("testtest", viewState.getText()); Assert.assertEquals("testtest", viewState.getTextString());
Assert.assertEquals(8, viewState.getSelection()); Assert.assertEquals(8, viewState.selection);
viewState = this.editor.insert(""); viewState = this.editor.insert("");
Assert.assertEquals("testtest", viewState.getText()); Assert.assertEquals("testtest", viewState.getTextString());
Assert.assertEquals(8, viewState.getSelection()); Assert.assertEquals(8, viewState.selection);
viewState = this.editor.insert("1234567890"); viewState = this.editor.insert("1234567890");
Assert.assertEquals("testtest1234567890", viewState.getText()); Assert.assertEquals("testtest1234567890", viewState.getTextString());
Assert.assertEquals(18, viewState.getSelection()); Assert.assertEquals(18, viewState.selection);
viewState = this.editor.moveCursorLeft(); viewState = this.editor.moveCursorLeft();
viewState = this.editor.insert("9"); viewState = this.editor.insert("9");
Assert.assertEquals("testtest12345678990", viewState.getText()); Assert.assertEquals("testtest12345678990", viewState.getTextString());
Assert.assertEquals(18, viewState.getSelection()); Assert.assertEquals(18, viewState.selection);
viewState = this.editor.setCursorOnStart(); viewState = this.editor.setCursorOnStart();
viewState = this.editor.insert("9"); viewState = this.editor.insert("9");
Assert.assertEquals("9testtest12345678990", viewState.getText()); Assert.assertEquals("9testtest12345678990", viewState.getTextString());
Assert.assertEquals(1, viewState.getSelection()); Assert.assertEquals(1, viewState.selection);
viewState = this.editor.erase(); viewState = this.editor.erase();
viewState = this.editor.insert("9"); viewState = this.editor.insert("9");
Assert.assertEquals("9testtest12345678990", viewState.getText()); Assert.assertEquals("9testtest12345678990", viewState.getTextString());
Assert.assertEquals(1, viewState.getSelection()); Assert.assertEquals(1, viewState.selection);
viewState = this.editor.insert("öäü"); viewState = this.editor.insert("öäü");
Assert.assertEquals("9öäütesttest12345678990", viewState.getText()); Assert.assertEquals("9öäütesttest12345678990", viewState.getTextString());
this.editor.setCursorOnEnd(); this.editor.setCursorOnEnd();
viewState = this.editor.insert("öäü"); viewState = this.editor.insert("öäü");
Assert.assertEquals("9öäütesttest12345678990öäü", viewState.getText()); Assert.assertEquals("9öäütesttest12345678990öäü", viewState.getTextString());
} }
@Test @Test
@ -101,39 +101,39 @@ public class EditorTest extends AbstractCalculatorTest {
this.editor.setText(""); this.editor.setText("");
this.editor.erase(); this.editor.erase();
Assert.assertEquals("", this.editor.getState().getText()); Assert.assertEquals("", this.editor.getState().getTextString());
this.editor.setText("test"); this.editor.setText("test");
this.editor.erase(); this.editor.erase();
Assert.assertEquals("tes", this.editor.getState().getText()); Assert.assertEquals("tes", this.editor.getState().getTextString());
this.editor.erase(); this.editor.erase();
Assert.assertEquals("te", this.editor.getState().getText()); Assert.assertEquals("te", this.editor.getState().getTextString());
this.editor.erase(); this.editor.erase();
Assert.assertEquals("t", this.editor.getState().getText()); Assert.assertEquals("t", this.editor.getState().getTextString());
this.editor.erase(); this.editor.erase();
Assert.assertEquals("", this.editor.getState().getText()); Assert.assertEquals("", this.editor.getState().getTextString());
this.editor.erase(); this.editor.erase();
Assert.assertEquals("", this.editor.getState().getText()); Assert.assertEquals("", this.editor.getState().getTextString());
this.editor.setText("1234"); this.editor.setText("1234");
this.editor.moveCursorLeft(); this.editor.moveCursorLeft();
this.editor.erase(); this.editor.erase();
Assert.assertEquals("124", this.editor.getState().getText()); Assert.assertEquals("124", this.editor.getState().getTextString());
this.editor.erase(); this.editor.erase();
Assert.assertEquals("14", this.editor.getState().getText()); Assert.assertEquals("14", this.editor.getState().getTextString());
this.editor.erase(); this.editor.erase();
Assert.assertEquals("4", this.editor.getState().getText()); Assert.assertEquals("4", this.editor.getState().getTextString());
this.editor.setText("1"); this.editor.setText("1");
this.editor.moveCursorLeft(); this.editor.moveCursorLeft();
this.editor.erase(); this.editor.erase();
Assert.assertEquals("1", this.editor.getState().getText()); Assert.assertEquals("1", this.editor.getState().getTextString());
} }
@Test @Test
@ -141,91 +141,91 @@ public class EditorTest extends AbstractCalculatorTest {
this.editor.setText(""); this.editor.setText("");
EditorState viewState = this.editor.moveSelection(0); EditorState viewState = this.editor.moveSelection(0);
Assert.assertEquals(0, viewState.getSelection()); Assert.assertEquals(0, viewState.selection);
viewState = this.editor.moveSelection(2); viewState = this.editor.moveSelection(2);
Assert.assertEquals(0, viewState.getSelection()); Assert.assertEquals(0, viewState.selection);
viewState = this.editor.moveSelection(100); viewState = this.editor.moveSelection(100);
Assert.assertEquals(0, viewState.getSelection()); Assert.assertEquals(0, viewState.selection);
viewState = this.editor.moveSelection(-3); viewState = this.editor.moveSelection(-3);
Assert.assertEquals(0, viewState.getSelection()); Assert.assertEquals(0, viewState.selection);
viewState = this.editor.moveSelection(-100); viewState = this.editor.moveSelection(-100);
Assert.assertEquals(0, viewState.getSelection()); Assert.assertEquals(0, viewState.selection);
viewState = this.editor.setText("0123456789"); viewState = this.editor.setText("0123456789");
viewState = this.editor.moveSelection(0); viewState = this.editor.moveSelection(0);
Assert.assertEquals(10, viewState.getSelection()); Assert.assertEquals(10, viewState.selection);
viewState = this.editor.moveSelection(1); viewState = this.editor.moveSelection(1);
Assert.assertEquals(10, viewState.getSelection()); Assert.assertEquals(10, viewState.selection);
viewState = this.editor.moveSelection(-2); viewState = this.editor.moveSelection(-2);
Assert.assertEquals(8, viewState.getSelection()); Assert.assertEquals(8, viewState.selection);
viewState = this.editor.moveSelection(1); viewState = this.editor.moveSelection(1);
Assert.assertEquals(9, viewState.getSelection()); Assert.assertEquals(9, viewState.selection);
viewState = this.editor.moveSelection(-9); viewState = this.editor.moveSelection(-9);
Assert.assertEquals(0, viewState.getSelection()); Assert.assertEquals(0, viewState.selection);
viewState = this.editor.moveSelection(-10); viewState = this.editor.moveSelection(-10);
Assert.assertEquals(0, viewState.getSelection()); Assert.assertEquals(0, viewState.selection);
viewState = this.editor.moveSelection(2); viewState = this.editor.moveSelection(2);
Assert.assertEquals(2, viewState.getSelection()); Assert.assertEquals(2, viewState.selection);
viewState = this.editor.moveSelection(2); viewState = this.editor.moveSelection(2);
Assert.assertEquals(4, viewState.getSelection()); Assert.assertEquals(4, viewState.selection);
viewState = this.editor.moveSelection(-6); viewState = this.editor.moveSelection(-6);
Assert.assertEquals(0, viewState.getSelection()); Assert.assertEquals(0, viewState.selection);
} }
@Test @Test
public void testSetText() throws Exception { public void testSetText() throws Exception {
EditorState viewState = this.editor.setText("test"); EditorState viewState = this.editor.setText("test");
Assert.assertEquals("test", viewState.getText()); Assert.assertEquals("test", viewState.getTextString());
Assert.assertEquals(4, viewState.getSelection()); Assert.assertEquals(4, viewState.selection);
viewState = this.editor.setText("testtest"); viewState = this.editor.setText("testtest");
Assert.assertEquals("testtest", viewState.getText()); Assert.assertEquals("testtest", viewState.getTextString());
Assert.assertEquals(8, viewState.getSelection()); Assert.assertEquals(8, viewState.selection);
viewState = this.editor.setText(""); viewState = this.editor.setText("");
Assert.assertEquals("", viewState.getText()); Assert.assertEquals("", viewState.getTextString());
Assert.assertEquals(0, viewState.getSelection()); Assert.assertEquals(0, viewState.selection);
viewState = this.editor.setText("testtest", 0); viewState = this.editor.setText("testtest", 0);
Assert.assertEquals("testtest", viewState.getText()); Assert.assertEquals("testtest", viewState.getTextString());
Assert.assertEquals(0, viewState.getSelection()); Assert.assertEquals(0, viewState.selection);
viewState = this.editor.setText("testtest", 2); viewState = this.editor.setText("testtest", 2);
Assert.assertEquals("testtest", viewState.getText()); Assert.assertEquals("testtest", viewState.getTextString());
Assert.assertEquals(2, viewState.getSelection()); Assert.assertEquals(2, viewState.selection);
viewState = this.editor.setText("", 0); viewState = this.editor.setText("", 0);
Assert.assertEquals("", viewState.getText()); Assert.assertEquals("", viewState.getTextString());
Assert.assertEquals(0, viewState.getSelection()); Assert.assertEquals(0, viewState.selection);
viewState = this.editor.setText("", 3); viewState = this.editor.setText("", 3);
Assert.assertEquals("", viewState.getText()); Assert.assertEquals("", viewState.getTextString());
Assert.assertEquals(0, viewState.getSelection()); Assert.assertEquals(0, viewState.selection);
viewState = this.editor.setText("", -3); viewState = this.editor.setText("", -3);
Assert.assertEquals("", viewState.getText()); Assert.assertEquals("", viewState.getTextString());
Assert.assertEquals(0, viewState.getSelection()); Assert.assertEquals(0, viewState.selection);
viewState = this.editor.setText("test"); viewState = this.editor.setText("test");
Assert.assertEquals("test", viewState.getText()); Assert.assertEquals("test", viewState.getTextString());
Assert.assertEquals(4, viewState.getSelection()); Assert.assertEquals(4, viewState.selection);
viewState = this.editor.setText("", 2); viewState = this.editor.setText("", 2);
Assert.assertEquals("", viewState.getText()); Assert.assertEquals("", viewState.getTextString());
Assert.assertEquals(0, viewState.getSelection()); Assert.assertEquals(0, viewState.selection);
} }
} }

View File

@ -32,9 +32,8 @@ import org.solovyev.common.equals.CollectionEqualizer;
import org.solovyev.common.history.HistoryHelper; import org.solovyev.common.history.HistoryHelper;
import org.solovyev.common.history.SimpleHistoryHelper; import org.solovyev.common.history.SimpleHistoryHelper;
import java.util.ArrayList; import javax.annotation.Nonnull;
import java.util.Date; import java.util.Date;
import java.util.List;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@ -146,12 +145,12 @@ public class HistoryUtilsTest {
state.setTime(date.getTime()); state.setTime(date.getTime());
history.addState(state); history.addState(state);
assertEquals(emptyHistory, History.toXml(history.getStates())); assertEquals(emptyHistory, createHistory(history).toXml());
state.setSaved(true); state.setSaved(true);
assertEquals(toXml1, History.toXml(history.getStates())); assertEquals(toXml1, createHistory(history).toXml());
calculatorDisplay = DisplayState.createValid(JsclOperation.numeric, null, "5/6", 3); calculatorDisplay = DisplayState.createValid(JsclOperation.numeric, null, "5/6", 3);
@ -180,13 +179,12 @@ public class HistoryUtilsTest {
state.setTime(date.getTime()); state.setTime(date.getTime());
history.addState(state); history.addState(state);
String xml = History.toXml(history.getStates()); String xml = createHistory(history).toXml();
assertEquals(toXml2, xml); assertEquals(toXml2, xml);
final List<HistoryState> fromXml = new ArrayList<HistoryState>();
final HistoryHelper<HistoryState> historyFromXml = SimpleHistoryHelper.newInstance(); final HistoryHelper<HistoryState> historyFromXml = SimpleHistoryHelper.newInstance();
History.fromXml(xml, fromXml); final History actual = History.fromXml(xml);
for (HistoryState historyState : fromXml) { for (HistoryState historyState : actual.getItems()) {
historyFromXml.addState(historyState); historyFromXml.addState(historyState);
} }
@ -202,4 +200,11 @@ public class HistoryUtilsTest {
} }
Assert.assertTrue(Objects.areEqual(history.getStates(), historyFromXml.getStates(), new CollectionEqualizer<HistoryState>(null))); Assert.assertTrue(Objects.areEqual(history.getStates(), historyFromXml.getStates(), new CollectionEqualizer<HistoryState>(null)));
} }
@Nonnull
private History createHistory(HistoryHelper<HistoryState> history) {
final History result = new History();
result.addAll(history.getStates());
return result;
}
} }