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')
}
compile 'commons-cli:commons-cli:1.2'
compile 'com.squareup:otto:1.3.8'
testCompile 'junit:junit:4.12'
testCompile 'net.sf.opencsv:opencsv:2.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.SpannableString;
import android.text.style.ForegroundColorSpan;
import com.squareup.otto.Bus;
import org.solovyev.android.Check;
import org.solovyev.android.UiThreadExecutor;
import org.solovyev.android.Views;
@ -97,7 +98,7 @@ public final class App {
@Nonnull
private static volatile DelayedExecutor uiThreadExecutor;
@Nonnull
private static volatile JEventListeners<JEventListener<? extends JEvent>, JEvent> eventBus;
private static Bus bus;
private static volatile boolean initialized;
@Nonnull
private static CalculatorBroadcaster broadcaster;
@ -138,7 +139,7 @@ public final class App {
App.application = application;
App.preferences = PreferenceManager.getDefaultSharedPreferences(application);
App.uiThreadExecutor = uiThreadExecutor;
App.eventBus = eventBus;
App.bus = new MyBus();
App.ga = new Ga(application, preferences, eventBus);
App.billing = new Billing(application, new Billing.DefaultConfiguration() {
@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.languages = languages;
App.wizards = new CalculatorWizards(application);
@ -195,8 +196,8 @@ public final class App {
* @return application's event bus
*/
@Nonnull
public static JEventListeners<JEventListener<? extends JEvent>, JEvent> getEventBus() {
return eventBus;
public static Bus getBus() {
return bus;
}
@Nonnull
@ -322,4 +323,20 @@ public final class App {
// NOTE: this code is only for monkeyrunner
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.preference.PreferenceManager;
import android.util.Log;
import android.util.TimingLogger;
import com.squareup.leakcanary.LeakCanary;
import org.acra.ACRA;
import org.acra.ACRAConfiguration;
@ -89,8 +88,6 @@ public class CalculatorApplication extends android.app.Application implements Sh
calculator.addCalculatorEventListener(listener);
}
calculator.addCalculatorEventListener(App.getBroadcaster());
Locator.getInstance().getCalculator().init();
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) {
if (Preferences.Onscreen.showAppIcon.getKey().equals(key)) {
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);
}
}

View File

@ -3,13 +3,15 @@ package org.solovyev.android.calculator;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashMap;
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_EDITOR_STATE_CHANGED = "org.solovyev.android.calculator.EDITOR_STATE_CHANGED";
@ -22,18 +24,24 @@ public final class CalculatorBroadcaster implements CalculatorEventListener, Sha
@Nonnull
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;
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) {
switch (calculatorEventType) {
case editor_state_changed:
case editor_state_changed_light:
sendBroadcastIntent(ACTION_EDITOR_STATE_CHANGED);
break;
case display_state_changed:
sendBroadcastIntent(ACTION_DISPLAY_STATE_CHANGED);
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.Nullable;
/**
* User: Solovyev_S
* Date: 20.09.12
* Time: 18:18
*/
class CalculatorEventDataImpl implements CalculatorEventData {
private static final long NO_SEQUENCE = -1L;
private final long eventId;
private final Object source;
@Nonnull
private Long sequenceId = NO_SEQUENCE;
private final long sequenceId;
private CalculatorEventDataImpl(long id, @Nonnull Long sequenceId, @Nullable Object source) {
private CalculatorEventDataImpl(long id, long sequenceId, @Nullable Object source) {
this.eventId = id;
this.sequenceId = sequenceId;
this.source = source;
}
@Nonnull
static CalculatorEventData newInstance(long id, @Nonnull Long sequenceId) {
static CalculatorEventData newInstance(long id, long sequenceId) {
return new CalculatorEventDataImpl(id, sequenceId, null);
}
@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);
}
@ -78,12 +72,24 @@ class CalculatorEventDataImpl implements CalculatorEventData {
@Override
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
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
@ -94,8 +100,7 @@ class CalculatorEventDataImpl implements CalculatorEventData {
CalculatorEventDataImpl that = (CalculatorEventDataImpl) o;
if (eventId != that.eventId) return false;
if (!sequenceId.equals(that.sequenceId))
return false;
if (sequenceId != that.sequenceId) return false;
return true;
}
@ -103,7 +108,7 @@ class CalculatorEventDataImpl implements CalculatorEventData {
@Override
public int hashCode() {
int result = (int) (eventId ^ (eventId >>> 32));
result = 31 * result + (sequenceId.hashCode());
result = 31 * result + (int) (sequenceId ^ (sequenceId >>> 32));
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
display_state_changed,

View File

@ -22,6 +22,16 @@
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.HistoryState;
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.Conversions;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
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
* Date: 20.09.12
@ -102,25 +102,11 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
private volatile long lastPreferenceCheck = 0L;
/*
**********************************************************************
*
* CONSTRUCTORS
*
**********************************************************************
*/
public CalculatorImpl() {
App.getBus().register(this);
this.addCalculatorEventListener(this);
}
/*
**********************************************************************
*
* METHODS
*
**********************************************************************
*/
@Nonnull
private static String doConversion(@Nonnull Generic generic,
@ -159,14 +145,6 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
return CalculatorEventDataImpl.newInstance(eventId, eventId, source);
}
/*
**********************************************************************
*
* CALCULATION
*
**********************************************************************
*/
@Nonnull
private CalculatorEventData nextEventData(@Nonnull Long sequenceId) {
long eventId = counter.incrementAndGet();
@ -497,31 +475,21 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
return eventData;
}
/*
**********************************************************************
*
* EVENTS HANDLER
*
**********************************************************************
*/
@Subscribe
public void onEditorChanged(@Nonnull Editor.ChangedEvent e) {
if (!calculateOnFly) {
return;
}
if (TextUtils.equals(e.newState.text, e.oldState.text)) {
return;
}
evaluate(JsclOperation.numeric, e.newState.getTextString(), e.newState.id);
}
@Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) {
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:
onDisplayStateChanged((CalculatorDisplayChangeEventData) data);
break;

View File

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

View File

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

View File

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

View File

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

View File

@ -33,16 +33,10 @@ import android.support.v4.app.NotificationCompat;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import com.squareup.otto.Subscribe;
import org.solovyev.android.Check;
import org.solovyev.android.Views;
import org.solovyev.android.calculator.App;
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 org.solovyev.android.calculator.*;
import javax.annotation.Nonnull;
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_NOTIFICATION_ACTION = "org.solovyev.android.calculator.onscreen.SHOW_NOTIFICATION";
private static final int NOTIFICATION_ID = 9031988; // my birthday =)
@Nonnull
private CalculatorOnscreenView view;
private boolean compatibilityStart = true;
private boolean viewCreated = false;
@Nonnull
private static Class<?> getIntentListenerClass() {
return INTENT_LISTENER_CLASS;
@ -93,14 +83,10 @@ public class CalculatorOnscreenService extends Service implements OnscreenViewLi
return null;
}
@Override
public void onCreate() {
super.onCreate();
App.getPreferences().registerOnSharedPreferenceChangeListener(this);
}
private void createView() {
if (!viewCreated) {
if (view != null) {
return;
}
final WindowManager wm = ((WindowManager) this.getSystemService(Context.WINDOW_SERVICE));
final DisplayMetrics dm = getResources().getDisplayMetrics();
@ -120,64 +106,39 @@ public class CalculatorOnscreenService extends Service implements OnscreenViewLi
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;
}
App.getBus().register(this);
App.getPreferences().registerOnSharedPreferenceChangeListener(this);
}
private int getHeight(int width) {
return 4 * width / 3;
}
private void startCalculatorListening() {
Locator.getInstance().getCalculator().addCalculatorEventListener(this);
}
private void stopCalculatorListening() {
Locator.getInstance().getCalculator().removeCalculatorEventListener(this);
}
@Override
public void onDestroy() {
if (view != null) {
App.getPreferences().unregisterOnSharedPreferenceChangeListener(this);
stopCalculatorListening();
if (viewCreated) {
this.view.hide();
App.getBus().unregister(this);
view.hide();
view = null;
}
super.onDestroy();
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
if (this.compatibilityStart) {
handleStart(intent);
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
final int result;
try {
this.compatibilityStart = false;
result = super.onStartCommand(intent, flags, startId);
final int result = super.onStartCommand(intent, flags, startId);
handleStart(intent);
} finally {
this.compatibilityStart = true;
}
return result;
}
private void handleStart(@Nullable Intent intent) {
if (intent != null) {
if (intent == null) {
return;
}
if (isShowWindowIntent(intent)) {
hideNotification();
createView();
@ -186,7 +147,6 @@ public class CalculatorOnscreenService extends Service implements OnscreenViewLi
showNotification();
}
}
}
private boolean isShowNotificationIntent(@Nonnull Intent intent) {
return intent.getAction().equals(SHOW_NOTIFICATION_ACTION);
@ -229,10 +189,6 @@ public class CalculatorOnscreenService extends Service implements OnscreenViewLi
@Override
public void onCalculatorEvent(@Nonnull CalculatorEventData calculatorEventData, @Nonnull CalculatorEventType calculatorEventType, @Nullable Object data) {
switch (calculatorEventType) {
case editor_state_changed:
case editor_state_changed_light:
view.updateEditorState(((CalculatorEditorChangeEventData) data).getNewValue());
break;
case display_state_changed:
view.updateDisplayState(((CalculatorDisplayChangeEventData) data).getNewValue());
break;
@ -241,12 +197,23 @@ public class CalculatorOnscreenService extends Service implements OnscreenViewLi
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (viewCreated) {
Check.isNotNull(view);
if (Preferences.Gui.theme.isSameKey(key) || Preferences.Onscreen.theme.isSameKey(key)) {
stopSelf();
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.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.*;
import android.widget.ImageView;
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.calculator.*;
import org.solovyev.android.prefs.Preference;
import java.util.Locale;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Locale;
/**
* 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() {
}
@ -167,14 +142,6 @@ public class CalculatorOnscreenView {
return result;
}
/*
**********************************************************************
*
* METHODS
*
**********************************************************************
*/
public static void persistState(@Nonnull Context context, @Nonnull CalculatorOnscreenViewState state) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
viewStatePreference.putPreference(preferences, state);
@ -195,14 +162,6 @@ public class CalculatorOnscreenView {
displayView.setState(displayState);
}
/*
**********************************************************************
*
* LIFECYCLE
*
**********************************************************************
*/
public void updateEditorState(@Nonnull EditorState editorState) {
checkInit();
editorView.setState(editorState);
@ -212,18 +171,20 @@ public class CalculatorOnscreenView {
checkInit();
final WindowManager.LayoutParams params = (WindowManager.LayoutParams) root.getLayoutParams();
params.height = height;
getWindowManager().updateViewLayout(root, params);
}
private void init() {
if (initialized) {
return;
}
if (!initialized) {
for (final CalculatorButton widgetButton : CalculatorButton.values()) {
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) {
@ -245,7 +206,6 @@ public class CalculatorOnscreenView {
}
});
}
}
final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
@ -290,7 +250,6 @@ public class CalculatorOnscreenView {
headerTitle.setOnTouchListener(new WindowDragTouchListener(wm, root));
initialized = true;
}
}
@ -301,12 +260,13 @@ public class CalculatorOnscreenView {
}
public void show() {
if (hidden) {
if (shown) {
return;
}
init();
attach();
hidden = false;
}
shown = true;
}
public void attach() {
@ -376,8 +336,9 @@ public class CalculatorOnscreenView {
public void hide() {
checkInit();
if (!hidden) {
if (!shown) {
return;
}
persistState(context, getCurrentState(!folded));
@ -387,8 +348,7 @@ public class CalculatorOnscreenView {
viewListener.onViewHidden();
}
hidden = true;
}
shown = false;
}
@Nonnull

View File

@ -30,6 +30,7 @@ import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.solovyev.common.text.Strings;
@ -62,7 +63,7 @@ public class AndroidEditorViewTest {
@Test
public void testCreation() throws Exception {
new EditorView(CalculatorApplication.getInstance());
new EditorView(RuntimeEnvironment.application);
}
@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 {
EditorState viewState = this.editor.getState();
Assert.assertEquals("", viewState.getText());
Assert.assertEquals(0, viewState.getSelection());
Assert.assertEquals("", viewState.getTextString());
Assert.assertEquals(0, viewState.selection);
viewState = this.editor.insert("");
Assert.assertEquals("", viewState.getText());
Assert.assertEquals(0, viewState.getSelection());
Assert.assertEquals("", viewState.getTextString());
Assert.assertEquals(0, viewState.selection);
viewState = this.editor.insert("test");
Assert.assertEquals("test", viewState.getText());
Assert.assertEquals(4, viewState.getSelection());
Assert.assertEquals("test", viewState.getTextString());
Assert.assertEquals(4, viewState.selection);
viewState = this.editor.insert("test");
Assert.assertEquals("testtest", viewState.getText());
Assert.assertEquals(8, viewState.getSelection());
Assert.assertEquals("testtest", viewState.getTextString());
Assert.assertEquals(8, viewState.selection);
viewState = this.editor.insert("");
Assert.assertEquals("testtest", viewState.getText());
Assert.assertEquals(8, viewState.getSelection());
Assert.assertEquals("testtest", viewState.getTextString());
Assert.assertEquals(8, viewState.selection);
viewState = this.editor.insert("1234567890");
Assert.assertEquals("testtest1234567890", viewState.getText());
Assert.assertEquals(18, viewState.getSelection());
Assert.assertEquals("testtest1234567890", viewState.getTextString());
Assert.assertEquals(18, viewState.selection);
viewState = this.editor.moveCursorLeft();
viewState = this.editor.insert("9");
Assert.assertEquals("testtest12345678990", viewState.getText());
Assert.assertEquals(18, viewState.getSelection());
Assert.assertEquals("testtest12345678990", viewState.getTextString());
Assert.assertEquals(18, viewState.selection);
viewState = this.editor.setCursorOnStart();
viewState = this.editor.insert("9");
Assert.assertEquals("9testtest12345678990", viewState.getText());
Assert.assertEquals(1, viewState.getSelection());
Assert.assertEquals("9testtest12345678990", viewState.getTextString());
Assert.assertEquals(1, viewState.selection);
viewState = this.editor.erase();
viewState = this.editor.insert("9");
Assert.assertEquals("9testtest12345678990", viewState.getText());
Assert.assertEquals(1, viewState.getSelection());
Assert.assertEquals("9testtest12345678990", viewState.getTextString());
Assert.assertEquals(1, viewState.selection);
viewState = this.editor.insert("öäü");
Assert.assertEquals("9öäütesttest12345678990", viewState.getText());
Assert.assertEquals("9öäütesttest12345678990", viewState.getTextString());
this.editor.setCursorOnEnd();
viewState = this.editor.insert("öäü");
Assert.assertEquals("9öäütesttest12345678990öäü", viewState.getText());
Assert.assertEquals("9öäütesttest12345678990öäü", viewState.getTextString());
}
@Test
@ -101,39 +101,39 @@ public class EditorTest extends AbstractCalculatorTest {
this.editor.setText("");
this.editor.erase();
Assert.assertEquals("", this.editor.getState().getText());
Assert.assertEquals("", this.editor.getState().getTextString());
this.editor.setText("test");
this.editor.erase();
Assert.assertEquals("tes", this.editor.getState().getText());
Assert.assertEquals("tes", this.editor.getState().getTextString());
this.editor.erase();
Assert.assertEquals("te", this.editor.getState().getText());
Assert.assertEquals("te", this.editor.getState().getTextString());
this.editor.erase();
Assert.assertEquals("t", this.editor.getState().getText());
Assert.assertEquals("t", this.editor.getState().getTextString());
this.editor.erase();
Assert.assertEquals("", this.editor.getState().getText());
Assert.assertEquals("", this.editor.getState().getTextString());
this.editor.erase();
Assert.assertEquals("", this.editor.getState().getText());
Assert.assertEquals("", this.editor.getState().getTextString());
this.editor.setText("1234");
this.editor.moveCursorLeft();
this.editor.erase();
Assert.assertEquals("124", this.editor.getState().getText());
Assert.assertEquals("124", this.editor.getState().getTextString());
this.editor.erase();
Assert.assertEquals("14", this.editor.getState().getText());
Assert.assertEquals("14", this.editor.getState().getTextString());
this.editor.erase();
Assert.assertEquals("4", this.editor.getState().getText());
Assert.assertEquals("4", this.editor.getState().getTextString());
this.editor.setText("1");
this.editor.moveCursorLeft();
this.editor.erase();
Assert.assertEquals("1", this.editor.getState().getText());
Assert.assertEquals("1", this.editor.getState().getTextString());
}
@Test
@ -141,91 +141,91 @@ public class EditorTest extends AbstractCalculatorTest {
this.editor.setText("");
EditorState viewState = this.editor.moveSelection(0);
Assert.assertEquals(0, viewState.getSelection());
Assert.assertEquals(0, viewState.selection);
viewState = this.editor.moveSelection(2);
Assert.assertEquals(0, viewState.getSelection());
Assert.assertEquals(0, viewState.selection);
viewState = this.editor.moveSelection(100);
Assert.assertEquals(0, viewState.getSelection());
Assert.assertEquals(0, viewState.selection);
viewState = this.editor.moveSelection(-3);
Assert.assertEquals(0, viewState.getSelection());
Assert.assertEquals(0, viewState.selection);
viewState = this.editor.moveSelection(-100);
Assert.assertEquals(0, viewState.getSelection());
Assert.assertEquals(0, viewState.selection);
viewState = this.editor.setText("0123456789");
viewState = this.editor.moveSelection(0);
Assert.assertEquals(10, viewState.getSelection());
Assert.assertEquals(10, viewState.selection);
viewState = this.editor.moveSelection(1);
Assert.assertEquals(10, viewState.getSelection());
Assert.assertEquals(10, viewState.selection);
viewState = this.editor.moveSelection(-2);
Assert.assertEquals(8, viewState.getSelection());
Assert.assertEquals(8, viewState.selection);
viewState = this.editor.moveSelection(1);
Assert.assertEquals(9, viewState.getSelection());
Assert.assertEquals(9, viewState.selection);
viewState = this.editor.moveSelection(-9);
Assert.assertEquals(0, viewState.getSelection());
Assert.assertEquals(0, viewState.selection);
viewState = this.editor.moveSelection(-10);
Assert.assertEquals(0, viewState.getSelection());
Assert.assertEquals(0, viewState.selection);
viewState = this.editor.moveSelection(2);
Assert.assertEquals(2, viewState.getSelection());
Assert.assertEquals(2, viewState.selection);
viewState = this.editor.moveSelection(2);
Assert.assertEquals(4, viewState.getSelection());
Assert.assertEquals(4, viewState.selection);
viewState = this.editor.moveSelection(-6);
Assert.assertEquals(0, viewState.getSelection());
Assert.assertEquals(0, viewState.selection);
}
@Test
public void testSetText() throws Exception {
EditorState viewState = this.editor.setText("test");
Assert.assertEquals("test", viewState.getText());
Assert.assertEquals(4, viewState.getSelection());
Assert.assertEquals("test", viewState.getTextString());
Assert.assertEquals(4, viewState.selection);
viewState = this.editor.setText("testtest");
Assert.assertEquals("testtest", viewState.getText());
Assert.assertEquals(8, viewState.getSelection());
Assert.assertEquals("testtest", viewState.getTextString());
Assert.assertEquals(8, viewState.selection);
viewState = this.editor.setText("");
Assert.assertEquals("", viewState.getText());
Assert.assertEquals(0, viewState.getSelection());
Assert.assertEquals("", viewState.getTextString());
Assert.assertEquals(0, viewState.selection);
viewState = this.editor.setText("testtest", 0);
Assert.assertEquals("testtest", viewState.getText());
Assert.assertEquals(0, viewState.getSelection());
Assert.assertEquals("testtest", viewState.getTextString());
Assert.assertEquals(0, viewState.selection);
viewState = this.editor.setText("testtest", 2);
Assert.assertEquals("testtest", viewState.getText());
Assert.assertEquals(2, viewState.getSelection());
Assert.assertEquals("testtest", viewState.getTextString());
Assert.assertEquals(2, viewState.selection);
viewState = this.editor.setText("", 0);
Assert.assertEquals("", viewState.getText());
Assert.assertEquals(0, viewState.getSelection());
Assert.assertEquals("", viewState.getTextString());
Assert.assertEquals(0, viewState.selection);
viewState = this.editor.setText("", 3);
Assert.assertEquals("", viewState.getText());
Assert.assertEquals(0, viewState.getSelection());
Assert.assertEquals("", viewState.getTextString());
Assert.assertEquals(0, viewState.selection);
viewState = this.editor.setText("", -3);
Assert.assertEquals("", viewState.getText());
Assert.assertEquals(0, viewState.getSelection());
Assert.assertEquals("", viewState.getTextString());
Assert.assertEquals(0, viewState.selection);
viewState = this.editor.setText("test");
Assert.assertEquals("test", viewState.getText());
Assert.assertEquals(4, viewState.getSelection());
Assert.assertEquals("test", viewState.getTextString());
Assert.assertEquals(4, viewState.selection);
viewState = this.editor.setText("", 2);
Assert.assertEquals("", viewState.getText());
Assert.assertEquals(0, viewState.getSelection());
Assert.assertEquals("", viewState.getTextString());
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.SimpleHistoryHelper;
import java.util.ArrayList;
import javax.annotation.Nonnull;
import java.util.Date;
import java.util.List;
import static org.junit.Assert.assertEquals;
@ -146,12 +145,12 @@ public class HistoryUtilsTest {
state.setTime(date.getTime());
history.addState(state);
assertEquals(emptyHistory, History.toXml(history.getStates()));
assertEquals(emptyHistory, createHistory(history).toXml());
state.setSaved(true);
assertEquals(toXml1, History.toXml(history.getStates()));
assertEquals(toXml1, createHistory(history).toXml());
calculatorDisplay = DisplayState.createValid(JsclOperation.numeric, null, "5/6", 3);
@ -180,13 +179,12 @@ public class HistoryUtilsTest {
state.setTime(date.getTime());
history.addState(state);
String xml = History.toXml(history.getStates());
String xml = createHistory(history).toXml();
assertEquals(toXml2, xml);
final List<HistoryState> fromXml = new ArrayList<HistoryState>();
final HistoryHelper<HistoryState> historyFromXml = SimpleHistoryHelper.newInstance();
History.fromXml(xml, fromXml);
for (HistoryState historyState : fromXml) {
final History actual = History.fromXml(xml);
for (HistoryState historyState : actual.getItems()) {
historyFromXml.addState(historyState);
}
@ -202,4 +200,11 @@ public class HistoryUtilsTest {
}
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;
}
}