Dagger 2 DI

This commit is contained in:
serso 2016-01-13 17:41:05 +01:00
parent 96788ccc1f
commit 1e8be31ab5
40 changed files with 486 additions and 315 deletions

View File

@ -23,6 +23,7 @@
apply plugin: 'com.android.application'
apply plugin: 'maven'
apply plugin: 'signing'
apply plugin: 'com.neenbedankt.android-apt'
android {
compileSdkVersion 23
@ -98,6 +99,11 @@ dependencies {
}
compile 'commons-cli:commons-cli:1.2'
compile 'com.squareup:otto:1.3.8'
compile 'com.google.dagger:dagger:2.0.2'
apt "com.google.dagger:dagger-compiler:2.0.2"
compile 'javax.annotation:jsr250-api:1.0'
testCompile 'junit:junit:4.12'
testCompile 'net.sf.opencsv:opencsv:2.0'
testCompile 'org.mockito:mockito-core:1.9.0'

View File

@ -25,14 +25,20 @@ package org.solovyev.android.calculator;
import android.app.Application;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import jscl.NumeralBase;
import jscl.math.Generic;
import com.squareup.otto.Bus;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.common.msg.Message;
import java.util.List;
import java.util.concurrent.Executor;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import jscl.NumeralBase;
import jscl.math.Generic;
/**
* User: serso
@ -42,13 +48,14 @@ import java.util.List;
public class AndroidCalculator implements Calculator, CalculatorEventListener, SharedPreferences.OnSharedPreferenceChangeListener {
@Nonnull
private final CalculatorImpl calculator = new CalculatorImpl();
private final CalculatorImpl calculator;
@Nonnull
private final Application context;
public AndroidCalculator(@Nonnull Application application) {
public AndroidCalculator(@Nonnull Application application, @Nonnull Bus bus, Executor eventExecutor) {
this.context = application;
this.calculator = new CalculatorImpl(bus, eventExecutor);
this.calculator.addCalculatorEventListener(this);
PreferenceManager.getDefaultSharedPreferences(application).registerOnSharedPreferenceChangeListener(this);

View File

@ -29,8 +29,6 @@ import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
@ -40,12 +38,10 @@ import android.support.v4.app.FragmentTransaction;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import com.squareup.otto.Bus;
import org.solovyev.android.Check;
import org.solovyev.android.UiThreadExecutor;
import org.solovyev.android.Views;
import org.solovyev.android.calculator.ga.Ga;
import org.solovyev.android.calculator.language.Languages;
@ -60,10 +56,6 @@ import org.solovyev.android.checkout.Products;
import org.solovyev.android.checkout.RobotmediaDatabase;
import org.solovyev.android.checkout.RobotmediaInventory;
import org.solovyev.android.wizard.Wizards;
import org.solovyev.common.listeners.JEvent;
import org.solovyev.common.listeners.JEventListener;
import org.solovyev.common.listeners.JEventListeners;
import org.solovyev.common.listeners.Listeners;
import org.solovyev.common.threads.DelayedExecutor;
import java.util.Arrays;
@ -75,12 +67,6 @@ import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: serso
* Date: 12/1/12
* Time: 3:58 PM
*/
/**
* This class aggregates several useful in any Android application interfaces and provides access to {@link android.app.Application} object from a static context.
* NOTE: use this class only if you don't use and dependency injection library (if you use any you can directly set interfaces through it). <br/>
@ -108,13 +94,9 @@ public final class App {
@Nonnull
private static volatile Application application;
@Nonnull
private static volatile DelayedExecutor uiThreadExecutor;
@Nonnull
private static Bus bus;
private static Executor uiThreadExecutor;
private static volatile boolean initialized;
@Nonnull
private static CalculatorBroadcaster broadcaster;
@Nonnull
private static SharedPreferences preferences;
@Nonnull
private static volatile Ga ga;
@ -127,16 +109,13 @@ public final class App {
@Nonnull
private static volatile ScreenMetrics screenMetrics;
@Nonnull
private static final Handler handler = new Handler(Looper.getMainLooper());
@Nonnull
private static Wizards wizards;
@Nonnull
private static final Executor initThread = Executors.newSingleThreadExecutor(new ThreadFactory() {
@Override
public Thread newThread(@Nonnull Runnable r) {
return new Thread(r, "Init");
}
});
private static Editor editor;
@Nonnull
private static Bus bus;
@Nonnull
private static Display display;
@Nonnull
private static final Executor background = Executors.newFixedThreadPool(5, new ThreadFactory() {
@NonNull
@ -151,22 +130,15 @@ public final class App {
throw new AssertionError();
}
public static void init(@Nonnull Application application, @Nonnull Languages languages) {
init(application, new UiThreadExecutor(), Listeners.newEventBus(), languages);
}
public static void init(@Nonnull Application application,
@Nonnull UiThreadExecutor uiThreadExecutor,
@Nonnull JEventListeners<JEventListener<? extends JEvent>, JEvent> eventBus,
public static void init(@Nonnull CalculatorApplication application,
@Nonnull Languages languages) {
if (initialized) {
throw new IllegalStateException("Already initialized!");
}
App.application = application;
App.preferences = PreferenceManager.getDefaultSharedPreferences(application);
App.uiThreadExecutor = uiThreadExecutor;
App.bus = new MyBus();
App.ga = new Ga(application, preferences, eventBus);
App.uiThreadExecutor = application.uiThread;
App.ga = new Ga(application, preferences);
App.billing = new Billing(application, new Billing.DefaultConfiguration() {
@Nonnull
@Override
@ -184,11 +156,13 @@ public final class App {
}
}
});
App.broadcaster = new CalculatorBroadcaster(application, preferences, bus);
App.screenMetrics = new ScreenMetrics(application);
App.languages = languages;
App.languages.init();
App.wizards = new CalculatorWizards(application);
App.editor = application.editor;
App.display = application.display;
App.bus = application.bus;
App.initialized = true;
}
@ -215,33 +189,15 @@ public final class App {
* @return UI thread executor
*/
@Nonnull
public static DelayedExecutor getUiThreadExecutor() {
public static Executor getUiThreadExecutor() {
return uiThreadExecutor;
}
/**
* @return application's event bus
*/
@Nonnull
public static Bus getBus() {
return bus;
}
@Nonnull
public static CalculatorBroadcaster getBroadcaster() {
return broadcaster;
}
@Nonnull
public static Wizards getWizards() {
return wizards;
}
@Nonnull
public static Handler getHandler() {
return handler;
}
@Nonnull
public static Ga getGa() {
return ga;
@ -276,11 +232,6 @@ public final class App {
return Preferences.Widget.getTheme(getPreferences());
}
@Nonnull
public static Executor getInitThread() {
return initThread;
}
@Nonnull
public static Executor getBackground() {
return background;
@ -363,27 +314,16 @@ public final class App {
@Nonnull
public static Editor getEditor() {
return Locator.getInstance().getEditor();
return editor;
}
@Nonnull
public static Display getDisplay() {
return Locator.getInstance().getDisplay();
return display;
}
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);
}
});
}
@Nonnull
public static Bus getBus() {
return bus;
}
}

View File

@ -0,0 +1,16 @@
package org.solovyev.android.calculator;
import org.solovyev.android.calculator.onscreen.CalculatorOnscreenService;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
void inject(CalculatorApplication application);
void inject(CalculatorEditorFragment fragment);
void inject(BaseUi ui);
void inject(CalculatorOnscreenService service);
}

View File

@ -0,0 +1,106 @@
package org.solovyev.android.calculator;
import android.app.Application;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import com.squareup.otto.Bus;
import org.solovyev.android.UiThreadExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import javax.annotation.Nonnull;
import javax.inject.Named;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class AppModule {
@NonNull
public static final String THREAD_INIT = "thread-init";
@NonNull
public static final String THREAD_UI = "thread-ui";
@NonNull
private final Application application;
public AppModule(@NonNull Application application) {
this.application = application;
}
@Provides
@Singleton
Handler provideHandler() {
return new Handler(Looper.getMainLooper());
}
@Provides
@Singleton
Bus provideBus(Handler handler) {
return new AppBus(handler);
}
@Provides
@Singleton
SharedPreferences providePreferences() {
return PreferenceManager.getDefaultSharedPreferences(application);
}
@Provides
@Singleton
Calculator provideCalculator(Bus bus, @Named(THREAD_UI) Executor executor) {
return new AndroidCalculator(application, bus, executor);
}
@Provides
@Singleton
@Named(THREAD_INIT)
Executor provideInitThread() {
return Executors.newSingleThreadExecutor(new ThreadFactory() {
@Override
public Thread newThread(@Nonnull Runnable r) {
return new Thread(r, "Init");
}
});
}
@Provides
@Singleton
@Named(THREAD_UI)
Executor provideUiThread() {
return new UiThreadExecutor();
}
private static class AppBus extends Bus {
@NonNull
private final Handler handler;
public AppBus(@Nonnull Handler handler) {
this.handler = handler;
}
@Override
public void post(final Object event) {
if (Looper.myLooper() == Looper.getMainLooper()) {
super.post(event);
return;
}
handler.post(new Runnable() {
@Override
public void run() {
AppBus.super.post(event);
}
});
}
}
}

View File

@ -43,6 +43,8 @@ import org.solovyev.android.views.dragbutton.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
@ -110,8 +112,14 @@ public abstract class BaseUi implements SharedPreferences.OnSharedPreferenceChan
return viewIds;
}
@Inject
SharedPreferences preferences;
@Inject
Editor editor;
protected void onCreate(@Nonnull Activity activity) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
((CalculatorApplication) activity.getApplication()).getComponent().inject(this);
layout = Preferences.Gui.layout.getPreferenceNoError(preferences);
theme = Preferences.Gui.theme.getPreferenceNoError(preferences);
@ -170,7 +178,7 @@ public abstract class BaseUi implements SharedPreferences.OnSharedPreferenceChan
minusButton.setOnDragListener(newDragListener(new OperatorsDragProcessor(), activity));
}
final DragListener toPositionDragListener = new SimpleDragListener(new CursorDragProcessor(), activity);
final DragListener toPositionDragListener = new SimpleDragListener(new CursorDragProcessor(editor), activity);
final DragButton rightButton = getButton(views, R.id.cpp_button_right);
if (rightButton != null) {
@ -278,7 +286,7 @@ public abstract class BaseUi implements SharedPreferences.OnSharedPreferenceChan
}
@Nonnull
private CalculatorKeyboard getKeyboard() {
private Keyboard getKeyboard() {
return Locator.getInstance().getKeyboard();
}

View File

@ -32,11 +32,17 @@ import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v7.app.ActionBar;
import android.text.method.LinkMovementMethod;
import android.view.*;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.Window;
import android.widget.TextView;
import org.solovyev.android.Activities;
import org.solovyev.android.Android;
import org.solovyev.android.Threads;
import org.solovyev.android.calculator.history.History;
import org.solovyev.android.calculator.plot.CalculatorPlotActivity;
import org.solovyev.android.calculator.wizard.CalculatorWizards;
import org.solovyev.android.fragments.FragmentUtils;
@ -47,13 +53,16 @@ import org.solovyev.common.Objects;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static android.os.Build.VERSION_CODES.GINGERBREAD_MR1;
import static android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static org.solovyev.android.calculator.Preferences.Gui.preventScreenFromFading;
import static org.solovyev.android.calculator.release.ReleaseNotes.hasReleaseNotes;
import static org.solovyev.android.wizard.WizardUi.*;
import static org.solovyev.android.wizard.WizardUi.continueWizard;
import static org.solovyev.android.wizard.WizardUi.createLaunchIntent;
import static org.solovyev.android.wizard.WizardUi.startWizard;
public class CalculatorActivity extends BaseActivity implements SharedPreferences.OnSharedPreferenceChangeListener, CalculatorEventListener {
@ -135,6 +144,9 @@ public class CalculatorActivity extends BaseActivity implements SharedPreference
return result;
}
@Inject
History history;
/**
* Called when the activity is first created.
*/
@ -203,7 +215,7 @@ public class CalculatorActivity extends BaseActivity implements SharedPreference
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (useBackAsPrev) {
Locator.getInstance().getHistory().undo();
history.undo();
return true;
}
}

View File

@ -136,7 +136,7 @@ public final class CalculatorActivityLauncher implements CalculatorEventListener
}
public static void tryCreateVar(@Nonnull final Context context) {
final Display display = Locator.getInstance().getDisplay();
final Display display = App.getDisplay();
final DisplayState viewState = display.getState();
if (viewState.valid) {
final String varValue = viewState.text;
@ -162,7 +162,7 @@ public final class CalculatorActivityLauncher implements CalculatorEventListener
}
public static void tryCreateFunction(@Nonnull final Context context) {
final Display display = Locator.getInstance().getDisplay();
final Display display = App.getDisplay();
final DisplayState viewState = display.getState();
if (viewState.valid) {
@ -184,7 +184,7 @@ public final class CalculatorActivityLauncher implements CalculatorEventListener
public static void tryPlot() {
final CalculatorPlotter plotter = Locator.getInstance().getPlotter();
final Display display = Locator.getInstance().getDisplay();
final Display display = App.getDisplay();
final DisplayState viewState = display.getState();
if (viewState.valid) {

View File

@ -23,41 +23,78 @@
package org.solovyev.android.calculator;
import android.content.SharedPreferences;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import com.squareup.leakcanary.LeakCanary;
import com.squareup.otto.Bus;
import org.acra.ACRA;
import org.acra.ACRAConfiguration;
import org.acra.sender.HttpSender;
import org.solovyev.android.Android;
import org.solovyev.android.calculator.history.History;
import org.solovyev.android.calculator.language.Language;
import org.solovyev.android.calculator.language.Languages;
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
import org.solovyev.android.calculator.onscreen.CalculatorOnscreenStartActivity;
import org.solovyev.android.calculator.plot.AndroidCalculatorPlotter;
import org.solovyev.android.calculator.plot.CalculatorPlotterImpl;
import org.solovyev.android.calculator.view.EditorTextProcessor;
import org.solovyev.common.msg.MessageType;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.Executor;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Named;
public class CalculatorApplication extends android.app.Application implements SharedPreferences.OnSharedPreferenceChangeListener {
@Inject
@Named(AppModule.THREAD_INIT)
Executor initThread;
@Inject
Handler handler;
@Nonnull
private final List<CalculatorEventListener> listeners = new ArrayList<>();
private AppComponent component;
@Inject
Editor editor;
@Inject
Display display;
@Inject
Bus bus;
@Inject
Calculator calculator;
@Inject
Keyboard keyboard;
@Inject
@Named(AppModule.THREAD_UI)
Executor uiThread;
@Override
public void onCreate() {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
final Languages languages = new Languages(preferences);
onPreCreate(preferences, languages);
component = DaggerAppComponent.builder()
.appModule(new AppModule(this))
.build();
component.inject(this);
super.onCreate();
onPostCreate(preferences, languages);
}
@ -69,22 +106,15 @@ public class CalculatorApplication extends android.app.Application implements Sh
languages.updateContextLocale(this, true);
App.getGa().reportInitially(preferences);
final AndroidCalculator calculator = new AndroidCalculator(this);
final EditorTextProcessor editorTextProcessor = new EditorTextProcessor();
Locator.getInstance().init(calculator,
new AndroidCalculatorEngine(this),
new AndroidCalculatorClipboard(this),
new AndroidCalculatorNotifier(this),
new History(),
new AndroidCalculatorLogger(),
new AndroidCalculatorPreferenceService(this),
new CalculatorKeyboard(),
new AndroidCalculatorPlotter(this, new CalculatorPlotterImpl(calculator)),
editorTextProcessor);
editorTextProcessor.init(this);
keyboard,
new AndroidCalculatorPlotter(this, new CalculatorPlotterImpl(calculator))
);
listeners.add(new CalculatorActivityLauncher());
for (CalculatorEventListener listener : listeners) {
@ -93,20 +123,12 @@ public class CalculatorApplication extends android.app.Application implements Sh
Locator.getInstance().getCalculator().init();
App.getInitThread().execute(new Runnable() {
initThread.execute(new Runnable() {
@Override
public void run() {
warmUpEngine();
}
});
App.getHandler().postDelayed(new Runnable() {
@Override
public void run() {
// we must update the widget when app starts
App.getBroadcaster().sendInitIntent();
}
}, 100);
}
private void warmUpEngine() {
@ -154,4 +176,9 @@ public class CalculatorApplication extends android.app.Application implements Sh
Locator.getInstance().getNotifier().showMessage(R.string.cpp_this_change_may_require_reboot, MessageType.info);
}
}
@Nonnull
public AppComponent getComponent() {
return component;
}
}

View File

@ -3,13 +3,17 @@ package org.solovyev.android.calculator;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Handler;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.inject.Inject;
public final class CalculatorBroadcaster implements SharedPreferences.OnSharedPreferenceChangeListener {
public static final String ACTION_INIT = "org.solovyev.android.calculator.INIT";
@ -21,10 +25,18 @@ public final class CalculatorBroadcaster implements SharedPreferences.OnSharedPr
@Nonnull
private final Intents intents = new Intents();
public CalculatorBroadcaster(@Nonnull Context context, @Nonnull SharedPreferences preferences, @Nonnull Bus bus) {
@Inject
public CalculatorBroadcaster(@Nonnull Context context, @Nonnull SharedPreferences preferences, @Nonnull Bus bus, @Nonnull Handler handler) {
this.context = context;
preferences.registerOnSharedPreferenceChangeListener(this);
bus.register(this);
handler.postDelayed(new Runnable() {
@Override
public void run() {
// we must update the widget when app starts
sendInitIntent();
}
}, 100);
}
@Subscribe

View File

@ -107,7 +107,7 @@ public final class CalculatorButtons {
}
@Nonnull
private static CalculatorKeyboard getKeyboard() {
private static Keyboard getKeyboard() {
return Locator.getInstance().getKeyboard();
}

View File

@ -69,7 +69,7 @@ public class CalculatorDisplayFragment extends Fragment {
super.onViewCreated(root, savedInstanceState);
displayView = (DisplayView) root.findViewById(R.id.calculator_display);
Locator.getInstance().getDisplay().setView(displayView);
App.getDisplay().setView(displayView);
fragmentUi.onViewCreated(this, root);
}
@ -95,7 +95,7 @@ public class CalculatorDisplayFragment extends Fragment {
@Override
public void onDestroyView() {
Locator.getInstance().getDisplay().clearView(displayView);
App.getDisplay().clearView(displayView);
fragmentUi.onDestroyView(this);
super.onDestroyView();
}

View File

@ -50,7 +50,7 @@ public class CalculatorDisplayOnClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
if (v instanceof DisplayView) {
final Display cd = Locator.getInstance().getDisplay();
final Display cd = App.getDisplay();
final DisplayState displayViewState = cd.getState();

View File

@ -25,7 +25,6 @@ package org.solovyev.android.calculator;
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.Menu;
@ -39,23 +38,23 @@ import org.solovyev.android.menu.AndroidMenuHelper;
import org.solovyev.android.menu.ListActivityMenu;
import javax.annotation.Nonnull;
import javax.inject.Inject;
/**
* User: Solovyev_S
* Date: 25.09.12
* Time: 10:49
*/
public class CalculatorEditorFragment extends Fragment {
@Nonnull
private FragmentUi fragmentUi;
@Nonnull
private ActivityMenu<Menu, MenuItem> menu = ListActivityMenu.fromEnum(CalculatorMenu.class, AndroidMenuHelper.getInstance());
@Nonnull
private EditorView editorView;
@Inject
Editor editor;
@Inject
SharedPreferences preferences;
public CalculatorEditorFragment() {
}
@ -66,7 +65,7 @@ public class CalculatorEditorFragment extends Fragment {
fragmentUi.onViewCreated(this, view);
editorView = (EditorView) view.findViewById(R.id.calculator_editor);
Locator.getInstance().getEditor().setView(editorView);
editor.setView(editorView);
}
@Override
@ -78,8 +77,9 @@ public class CalculatorEditorFragment extends Fragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
final Preferences.Gui.Layout layout = Preferences.Gui.getLayout(prefs);
((CalculatorApplication) getActivity().getApplication()).getComponent().inject(this);
final Preferences.Gui.Layout layout = Preferences.Gui.getLayout(preferences);
if (!layout.isOptimized()) {
fragmentUi = new FragmentUi(R.layout.cpp_app_editor_mobile, R.string.editor);
} else {
@ -109,7 +109,7 @@ public class CalculatorEditorFragment extends Fragment {
@Override
public void onDestroyView() {
Locator.getInstance().getEditor().clearView(editorView);
editor.clearView(editorView);
fragmentUi.onDestroyView(this);
super.onDestroyView();
}

View File

@ -24,6 +24,7 @@ package org.solovyev.android.calculator;
import android.text.TextUtils;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import org.solovyev.android.calculator.jscl.JsclOperation;
@ -94,17 +95,17 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
@Nonnull
private final Executor calculationsExecutor = Executors.newFixedThreadPool(10);
// NOTE: only one thread is responsible for events as all events must be done in order of their creating
@Nonnull
private final Executor eventExecutor = App.getUiThreadExecutor();
private final Executor eventExecutor;
private volatile boolean calculateOnFly = true;
private volatile long lastPreferenceCheck = 0L;
public CalculatorImpl() {
App.getBus().register(this);
public CalculatorImpl(@Nonnull Bus bus, @Nonnull Executor eventExecutor) {
this.eventExecutor = eventExecutor;
bus.register(this);
this.addCalculatorEventListener(this);
}
@ -373,7 +374,7 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
@Nonnull final NumeralBase to) {
final CalculatorEventData eventDataId = nextEventData();
final DisplayState displayViewState = Locator.getInstance().getDisplay().getState();
final DisplayState displayViewState = App.getDisplay().getState();
final NumeralBase from = Locator.getInstance().getEngine().getNumeralBase();
calculationsExecutor.execute(new Runnable() {
@ -550,11 +551,11 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
@Nonnull
private Editor getEditor() {
return Locator.getInstance().getEditor();
return App.getEditor();
}
@Nonnull
private Display getDisplay() {
return Locator.getInstance().getDisplay();
return App.getDisplay();
}
}

View File

@ -22,31 +22,20 @@
package org.solovyev.android.calculator;
import org.solovyev.android.calculator.history.History;
import org.solovyev.android.calculator.plot.CalculatorPlotter;
import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.calculator.text.TextProcessorEditorResult;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: Solovyev_S
* Date: 20.09.12
* Time: 12:45
*/
public interface CalculatorLocator {
void init(@Nonnull Calculator calculator,
@Nonnull CalculatorEngine engine,
@Nonnull CalculatorClipboard clipboard,
@Nonnull CalculatorNotifier notifier,
@Nonnull History history,
@Nonnull CalculatorLogger logger,
@Nonnull CalculatorPreferenceService preferenceService,
@Nonnull CalculatorKeyboard keyboard,
@Nonnull CalculatorPlotter plotter,
@Nullable TextProcessor<TextProcessorEditorResult, String> editorTextProcessor);
@Nonnull Keyboard keyboard,
@Nonnull CalculatorPlotter plotter);
@Nonnull
Calculator getCalculator();
@ -55,13 +44,7 @@ public interface CalculatorLocator {
CalculatorEngine getEngine();
@Nonnull
Display getDisplay();
@Nonnull
Editor getEditor();
@Nonnull
CalculatorKeyboard getKeyboard();
Keyboard getKeyboard();
@Nonnull
CalculatorClipboard getClipboard();
@ -69,9 +52,6 @@ public interface CalculatorLocator {
@Nonnull
CalculatorNotifier getNotifier();
@Nonnull
History getHistory();
@Nonnull
CalculatorLogger getLogger();

View File

@ -37,76 +37,76 @@ public enum CalculatorSpecialButton {
history("history") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_history, null);
}
},
history_detached("history_detached") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_history_detached, null);
}
},
cursor_right("") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
keyboard.moveCursorRight();
}
},
cursor_left("") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
keyboard.moveCursorLeft();
}
},
settings("settings") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_settings, null);
}
},
settings_detached("settings_detached") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_settings_detached, null);
}
},
settings_widget("settings_widget") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_settings_widget, null);
}
},
like("like") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_like_dialog, null);
}
},
erase("erase") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
Locator.getInstance().getEditor().erase();
public void onClick(@Nonnull Keyboard keyboard) {
App.getEditor().erase();
}
},
paste("paste") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
keyboard.pasteButtonPressed();
}
},
copy("copy") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
keyboard.copyButtonPressed();
}
},
equals("=") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
final Calculator calculator = Locator.getInstance().getCalculator();
if (!calculator.isCalculateOnFly()) {
// no automatic calculations are => equals button must be used to calculate
@ -114,59 +114,59 @@ public enum CalculatorSpecialButton {
return;
}
final DisplayState displayState = Locator.getInstance().getDisplay().getState();
final DisplayState displayState = App.getDisplay().getState();
if (!displayState.valid) {
return;
}
Locator.getInstance().getEditor().setText(displayState.text);
App.getEditor().setText(displayState.text);
}
},
clear("clear") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
keyboard.clearButtonPressed();
}
},
functions("functions") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_functions, null);
}
},
functions_detached("functions_detached") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_functions_detached, null);
}
},
open_app("open_app") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.open_app, null);
}
},
vars("vars") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_vars, null);
}
},
vars_detached("vars_detached") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_vars_detached, null);
}
},
operators("operators") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_operators, null);
}
},
operators_detached("operators_detached") {
@Override
public void onClick(@Nonnull CalculatorKeyboard keyboard) {
public void onClick(@Nonnull Keyboard keyboard) {
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_operators_detached, null);
}
};
@ -207,5 +207,5 @@ public enum CalculatorSpecialButton {
return actionCode;
}
public abstract void onClick(@Nonnull CalculatorKeyboard keyboard);
public abstract void onClick(@Nonnull Keyboard keyboard);
}

View File

@ -34,15 +34,22 @@ import javax.annotation.Nonnull;
public class CursorDragProcessor implements SimpleDragListener.DragProcessor {
@Nonnull
private final Editor editor;
public CursorDragProcessor(@Nonnull Editor editor) {
this.editor = editor;
}
@Override
public boolean processDragEvent(@Nonnull DragDirection dragDirection, @Nonnull DragButton dragButton, @Nonnull PointF startPoint, @Nonnull MotionEvent motionEvent) {
if (dragButton instanceof DirectionDragButton) {
final String text = ((DirectionDragButton) dragButton).getText(dragDirection);
if ("◁◁".equals(text)) {
Locator.getInstance().getEditor().setCursorOnStart();
editor.setCursorOnStart();
return true;
} else if ("▷▷".equals(text)) {
Locator.getInstance().getEditor().setCursorOnEnd();
editor.setCursorOnEnd();
return true;
}
}

View File

@ -34,15 +34,15 @@ import javax.annotation.Nonnull;
public class DigitButtonDragProcessor implements SimpleDragListener.DragProcessor {
@Nonnull
private CalculatorKeyboard calculatorKeyboard;
private Keyboard keyboard;
public DigitButtonDragProcessor(@Nonnull CalculatorKeyboard calculatorKeyboard) {
this.calculatorKeyboard = calculatorKeyboard;
public DigitButtonDragProcessor(@Nonnull Keyboard keyboard) {
this.keyboard = keyboard;
}
@Override
public boolean processDragEvent(@Nonnull DragDirection direction, @Nonnull DragButton button, @Nonnull PointF startPoint, @Nonnull MotionEvent motionEvent) {
final String text = ((DirectionDragButton) button).getText(direction);
return calculatorKeyboard.buttonPressed(text);
return keyboard.buttonPressed(text);
}
}

View File

@ -22,13 +22,22 @@
package org.solovyev.android.calculator;
import com.squareup.otto.Bus;
import org.solovyev.android.Check;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import static org.solovyev.android.calculator.CalculatorEventType.*;
import static org.solovyev.android.calculator.CalculatorEventType.calculation_cancelled;
import static org.solovyev.android.calculator.CalculatorEventType.calculation_failed;
import static org.solovyev.android.calculator.CalculatorEventType.calculation_result;
import static org.solovyev.android.calculator.CalculatorEventType.conversion_failed;
import static org.solovyev.android.calculator.CalculatorEventType.conversion_result;
@Singleton
public class Display implements CalculatorEventListener {
public static class ChangedEvent {
@ -52,6 +61,10 @@ public class Display implements CalculatorEventListener {
@Nonnull
private DisplayState state = DisplayState.empty();
@Inject
Bus bus;
@Inject
public Display(@Nonnull Calculator calculator) {
this.lastEvent = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
calculator.addCalculatorEventListener(this);
@ -85,7 +98,7 @@ public class Display implements CalculatorEventListener {
if (view != null) {
view.setState(newState);
}
App.getBus().post(new ChangedEvent(oldState, newState));
bus.post(new ChangedEvent(oldState, newState));
}
@Override

View File

@ -22,15 +22,23 @@
package org.solovyev.android.calculator;
import android.content.SharedPreferences;
import com.squareup.otto.Bus;
import org.solovyev.android.Check;
import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.calculator.text.TextProcessorEditorResult;
import org.solovyev.android.calculator.view.EditorTextProcessor;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import static java.lang.Math.min;
@Singleton
public class Editor {
private static final String TAG = App.subTag("Editor");
@ -40,6 +48,14 @@ public class Editor {
private EditorView view;
@Nonnull
private EditorState state = EditorState.empty();
@Inject
Bus bus;
@Inject
public Editor(@Nonnull SharedPreferences preferences) {
this(new EditorTextProcessor(preferences));
}
public Editor(@Nullable TextProcessor<TextProcessorEditorResult, String> textProcessor) {
this.textProcessor = textProcessor;
}
@ -56,11 +72,13 @@ public class Editor {
Check.isMainThread();
this.view = view;
this.view.setState(state);
this.view.setEditor(this);
}
public void clearView(@Nonnull EditorView view) {
Check.isMainThread();
if (this.view == view) {
this.view.setEditor(null);
this.view = null;
}
}
@ -86,7 +104,7 @@ public class Editor {
if (view != null) {
view.setState(newState);
}
App.getBus().post(new ChangedEvent(oldState, newState));
bus.post(new ChangedEvent(oldState, newState));
return state;
}
@ -97,7 +115,7 @@ public class Editor {
if (view != null) {
view.setState(newState);
}
App.getBus().post(new CursorMovedEvent(newState));
bus.post(new CursorMovedEvent(newState));
return state;
}

View File

@ -31,12 +31,14 @@ import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextMenu;
import android.widget.EditText;
import org.solovyev.android.Check;
import org.solovyev.android.calculator.onscreen.CalculatorOnscreenService;
import java.lang.reflect.Method;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.reflect.Method;
public class EditorView extends EditText {
@ -46,6 +48,8 @@ public class EditorView extends EditText {
private boolean reportChanges;
@Nullable
private Method setShowSoftInputOnFocusMethod;
@Nullable
private Editor editor;
public EditorView(Context context) {
super(context);
@ -75,6 +79,10 @@ public class EditorView extends EditText {
reportChanges = true;
}
public void setEditor(@Nullable Editor editor) {
this.editor = editor;
}
@Override
protected void onCreateContextMenu(ContextMenu menu) {
super.onCreateContextMenu(menu);
@ -104,10 +112,15 @@ public class EditorView extends EditText {
// external text change => need to notify editor
super.onSelectionChanged(start, end);
if (start == end) {
// only if cursor moving, if selection do nothing
Locator.getInstance().getEditor().setSelection(start);
// only if cursor moving, if selection do nothing
if (start != end) {
return;
}
if (editor == null) {
Check.shouldNotHappen();
return;
}
editor.setSelection(start);
}
public void setShowSoftInputOnFocusCompat(boolean show) {
@ -143,11 +156,15 @@ public class EditorView extends EditText {
@Override
public void afterTextChanged(Editable s) {
// external text change => need to notify editor
if (!reportChanges) {
return;
}
// external text change => need to notify editor
Locator.getInstance().getEditor().setText(String.valueOf(s));
if (editor == null) {
Check.shouldNotHappen();
return;
}
editor.setText(String.valueOf(s));
}
}
}

View File

@ -27,8 +27,21 @@ import org.solovyev.common.text.Strings;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
public class CalculatorKeyboard {
@Singleton
public class Keyboard {
@Inject
Editor editor;
@Inject
Display display;
@Inject
public Keyboard() {
}
public boolean buttonPressed(@Nullable final String text) {
App.getGa().onButtonPressed(text);
@ -69,7 +82,6 @@ public class CalculatorKeyboard {
}
}
final Editor editor = Locator.getInstance().getEditor();
editor.insert(textToBeInserted.toString(), cursorPositionOffset);
}
@ -95,7 +107,6 @@ public class CalculatorKeyboard {
}
public void roundBracketsButtonPressed() {
final Editor editor = Locator.getInstance().getEditor();
EditorState viewState = editor.getState();
final int cursorPosition = viewState.selection;
@ -107,16 +118,16 @@ public class CalculatorKeyboard {
public void pasteButtonPressed() {
final String text = Locator.getInstance().getClipboard().getText();
if (text != null) {
Locator.getInstance().getEditor().insert(text);
editor.insert(text);
}
}
public void clearButtonPressed() {
Locator.getInstance().getEditor().clear();
editor.clear();
}
public void copyButtonPressed() {
final DisplayState displayState = Locator.getInstance().getDisplay().getState();
final DisplayState displayState = display.getState();
if (!displayState.valid) {
return;
}
@ -125,10 +136,10 @@ public class CalculatorKeyboard {
}
public void moveCursorLeft() {
Locator.getInstance().getEditor().moveCursorLeft();
editor.moveCursorLeft();
}
public void moveCursorRight() {
Locator.getInstance().getEditor().moveCursorRight();
editor.moveCursorRight();
}
}

View File

@ -22,19 +22,10 @@
package org.solovyev.android.calculator;
import org.solovyev.android.calculator.history.History;
import org.solovyev.android.calculator.plot.CalculatorPlotter;
import org.solovyev.android.calculator.text.TextProcessor;
import org.solovyev.android.calculator.text.TextProcessorEditorResult;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* User: Solovyev_S
* Date: 20.09.12
* Time: 12:45
*/
public class Locator implements CalculatorLocator {
@Nonnull
@ -44,13 +35,7 @@ public class Locator implements CalculatorLocator {
@Nonnull
private Calculator calculator;
@Nonnull
private Editor editor;
@Nonnull
private Display display;
@Nonnull
private CalculatorKeyboard calculatorKeyboard;
@Nonnull
private History history;
private Keyboard keyboard;
@Nonnull
private CalculatorNotifier calculatorNotifier = new DummyCalculatorNotifier();
@Nonnull
@ -76,25 +61,20 @@ public class Locator implements CalculatorLocator {
@Nonnull CalculatorEngine engine,
@Nonnull CalculatorClipboard clipboard,
@Nonnull CalculatorNotifier notifier,
@Nonnull History history,
@Nonnull CalculatorLogger logger,
@Nonnull CalculatorPreferenceService preferenceService,
@Nonnull CalculatorKeyboard keyboard,
@Nonnull CalculatorPlotter plotter,
@Nullable TextProcessor<TextProcessorEditorResult, String> editorTextProcessor) {
@Nonnull Keyboard keyboard,
@Nonnull CalculatorPlotter plotter) {
this.calculator = calculator;
this.calculatorEngine = engine;
this.calculatorClipboard = clipboard;
this.calculatorNotifier = notifier;
this.history = history;
this.calculatorLogger = logger;
this.calculatorPreferenceService = preferenceService;
this.calculatorPlotter = plotter;
editor = new Editor(editorTextProcessor);
display = new Display(this.calculator);
calculatorKeyboard = keyboard;
this.keyboard = keyboard;
}
@Nonnull
@ -111,24 +91,12 @@ public class Locator implements CalculatorLocator {
@Override
@Nonnull
public Display getDisplay() {
return display;
public Keyboard getKeyboard() {
return keyboard;
}
@Nonnull
@Override
public Editor getEditor() {
return editor;
}
@Override
@Nonnull
public CalculatorKeyboard getKeyboard() {
return calculatorKeyboard;
}
public static void setKeyboard(@Nonnull CalculatorKeyboard keyboard) {
instance.calculatorKeyboard = keyboard;
public static void setKeyboard(@Nonnull Keyboard keyboard) {
instance.keyboard = keyboard;
}
@Override
@ -143,12 +111,6 @@ public class Locator implements CalculatorLocator {
return calculatorNotifier;
}
@Override
@Nonnull
public History getHistory() {
return history;
}
@Override
@Nonnull
public CalculatorLogger getLogger() {

View File

@ -11,9 +11,6 @@ import com.google.android.gms.analytics.Tracker;
import org.solovyev.android.calculator.Preferences;
import org.solovyev.android.calculator.R;
import org.solovyev.common.listeners.JEvent;
import org.solovyev.common.listeners.JEventListener;
import org.solovyev.common.listeners.JEventListeners;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
@ -32,7 +29,7 @@ public final class Ga implements SharedPreferences.OnSharedPreferenceChangeListe
@Nonnull
private final Tracker tracker;
public Ga(@Nonnull Context context, @Nonnull SharedPreferences preferences, @Nonnull JEventListeners<JEventListener<? extends JEvent>, JEvent> bus) {
public Ga(@Nonnull Context context, @Nonnull SharedPreferences preferences) {
analytics = GoogleAnalytics.getInstance(context);
tracker = analytics.newTracker(R.xml.ga);
preferences.registerOnSharedPreferenceChangeListener(this);

View File

@ -61,6 +61,7 @@ import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static android.view.Menu.NONE;
import static org.solovyev.android.calculator.CalculatorEventType.clear_history_requested;
@ -84,6 +85,8 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul
private FragmentUi ui;
@Nullable
private AlertDialog clearDialog;
@Inject
History history;
protected BaseHistoryFragment(@Nonnull CalculatorFragmentType fragmentType) {
ui = new FragmentUi(fragmentType.getDefaultLayoutId(), fragmentType.getDefaultTitleResId(), false);
@ -220,7 +223,7 @@ public abstract class BaseHistoryFragment extends ListFragment implements Calcul
return true;
case R.string.c_remove:
getAdapter().remove(state);
Locator.getInstance().getHistory().removeSaved(state);
history.removeSaved(state);
Toast.makeText(context, context.getText(R.string.c_history_was_removed), Toast.LENGTH_LONG).show();
getAdapter().notifyDataSetChanged();
return true;

View File

@ -28,12 +28,14 @@ import android.support.annotation.NonNull;
import android.text.TextUtils;
import com.google.common.base.Strings;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import org.json.JSONArray;
import org.json.JSONException;
import org.solovyev.android.Check;
import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.AppModule;
import org.solovyev.android.calculator.CalculatorEventType;
import org.solovyev.android.calculator.Display;
import org.solovyev.android.calculator.DisplayState;
@ -49,9 +51,12 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Executor;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Named;
import static java.lang.Character.isDigit;
@ -66,15 +71,18 @@ public class History {
private final RecentHistory recent = new RecentHistory();
@Nonnull
private final List<HistoryState> saved = new ArrayList<>();
@Nonnull
private final Handler handler = App.getHandler();
@Inject
Handler handler;
@Inject
SharedPreferences preferences;
@Nullable
private EditorState lastEditorState;
private boolean initialized;
public History() {
App.getBus().register(this);
App.getInitThread().execute(new Runnable() {
@Inject
public History(Bus bus, @Named(AppModule.THREAD_INIT) Executor initThread) {
bus.register(this);
initThread.execute(new Runnable() {
@Override
public void run() {
init();
@ -82,9 +90,8 @@ public class History {
});
}
private static void migrateOldHistory() {
private void migrateOldHistory() {
try {
final SharedPreferences preferences = App.getPreferences();
final String xml = preferences.getString("org.solovyev.android.calculator.CalculatorModel_history", null);
if (TextUtils.isEmpty(xml)) {
return;
@ -101,7 +108,7 @@ public class History {
}
@Nullable
private static List<HistoryState> convertOldHistory(String xml) {
static List<HistoryState> convertOldHistory(@NonNull String xml) {
final OldHistory history = OldHistory.fromXml(xml);
if (history == null) {
// strange, history seems to be broken. Avoid clearing the preference

View File

@ -25,23 +25,26 @@ package org.solovyev.android.calculator.history;
import android.graphics.PointF;
import android.view.MotionEvent;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.views.dragbutton.DragButton;
import org.solovyev.android.views.dragbutton.DragDirection;
import org.solovyev.android.views.dragbutton.SimpleDragListener;
import javax.annotation.Nonnull;
import javax.inject.Inject;
public class HistoryDragProcessor implements SimpleDragListener.DragProcessor {
@Inject
History history;
@Override
public boolean processDragEvent(@Nonnull DragDirection direction, @Nonnull DragButton button, @Nonnull PointF startPoint, @Nonnull MotionEvent motionEvent) {
switch (direction) {
case up:
Locator.getInstance().getHistory().undo();
history.undo();
return true;
case down:
Locator.getInstance().getHistory().redo();
history.redo();
return true;
}
return false;

View File

@ -23,7 +23,6 @@
package org.solovyev.android.calculator.history;
import org.solovyev.android.calculator.CalculatorFragmentType;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.R;
import java.util.List;
@ -44,12 +43,12 @@ public class RecentHistoryFragment extends BaseHistoryFragment {
@Nonnull
@Override
protected List<HistoryState> getHistoryItems() {
return Locator.getInstance().getHistory().getRecent();
return history.getRecent();
}
@Override
protected void clearHistory() {
Locator.getInstance().getHistory().clearRecent();
history.clearRecent();
getAdapter().clear();
}
}

View File

@ -23,7 +23,6 @@
package org.solovyev.android.calculator.history;
import org.solovyev.android.calculator.CalculatorFragmentType;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.R;
import java.util.List;
@ -44,12 +43,12 @@ public class SavedHistoryFragment extends BaseHistoryFragment {
@Nonnull
@Override
protected List<HistoryState> getHistoryItems() {
return Locator.getInstance().getHistory().getSaved();
return history.getSaved();
}
@Override
protected void clearHistory() {
Locator.getInstance().getHistory().clearSaved();
history.clearSaved();
getAdapter().clear();
}
}

View File

@ -33,13 +33,21 @@ import android.support.v4.app.NotificationCompat;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import org.solovyev.android.Check;
import org.solovyev.android.Views;
import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.CalculatorApplication;
import org.solovyev.android.calculator.Display;
import org.solovyev.android.calculator.Editor;
import org.solovyev.android.calculator.Preferences;
import org.solovyev.android.calculator.R;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
public class CalculatorOnscreenService extends Service implements OnscreenViewListener, SharedPreferences.OnSharedPreferenceChangeListener {
@ -50,6 +58,9 @@ public class CalculatorOnscreenService extends Service implements OnscreenViewLi
private CalculatorOnscreenView view;
@Inject
Bus bus;
@Nonnull
private static Class<?> getIntentListenerClass() {
return INTENT_LISTENER_CLASS;
@ -101,10 +112,10 @@ public class CalculatorOnscreenService extends Service implements OnscreenViewLi
view = CalculatorOnscreenView.create(this, CalculatorOnscreenViewState.create(width, height, -1, -1), this);
view.show();
view.updateEditorState(Locator.getInstance().getEditor().getState());
view.updateDisplayState(Locator.getInstance().getDisplay().getState());
view.updateEditorState(App.getEditor().getState());
view.updateDisplayState(App.getDisplay().getState());
App.getBus().register(this);
bus.register(this);
App.getPreferences().registerOnSharedPreferenceChangeListener(this);
}
@ -112,11 +123,17 @@ public class CalculatorOnscreenService extends Service implements OnscreenViewLi
return 4 * width / 3;
}
@Override
public void onCreate() {
super.onCreate();
((CalculatorApplication) getApplication()).getComponent().inject(this);
}
@Override
public void onDestroy() {
if (view != null) {
App.getPreferences().unregisterOnSharedPreferenceChangeListener(this);
App.getBus().unregister(this);
bus.unregister(this);
view.hide();
view = null;
}

View File

@ -1,9 +1,7 @@
package org.solovyev.android.calculator.view;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;
import org.solovyev.android.calculator.App;
@ -14,15 +12,11 @@ import org.solovyev.android.calculator.text.TextProcessorEditorResult;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static org.solovyev.android.calculator.Preferences.Gui.colorDisplay;
import static org.solovyev.android.calculator.Preferences.Gui.theme;
/**
* User: serso
* Date: 6/27/13
* Time: 6:11 PM
*/
public final class EditorTextProcessor implements TextProcessor<TextProcessorEditorResult, String>, SharedPreferences.OnSharedPreferenceChangeListener {
private boolean highlightText = true;
@ -30,11 +24,7 @@ public final class EditorTextProcessor implements TextProcessor<TextProcessorEdi
@Nullable
private TextProcessor<TextProcessorEditorResult, String> textHighlighter;
public EditorTextProcessor() {
}
public void init(@Nonnull Context context) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
public EditorTextProcessor(@Nonnull SharedPreferences preferences) {
preferences.registerOnSharedPreferenceChangeListener(this);
onSharedPreferenceChanged(preferences, colorDisplay.getKey());
}

View File

@ -5,6 +5,7 @@ import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.View;
import org.solovyev.android.calculator.App;
import org.solovyev.android.calculator.Calculator;
import org.solovyev.android.calculator.Editor;
import org.solovyev.android.calculator.EditorState;
@ -23,7 +24,7 @@ public final class LongClickEraser implements View.OnTouchListener {
private final GestureDetector gestureDetector;
@Nonnull
private final Editor editor = Locator.getInstance().getEditor();
private final Editor editor = App.getEditor();
@Nonnull
private final Calculator calculator = Locator.getInstance().getCalculator();

View File

@ -120,8 +120,8 @@ public class CalculatorWidget extends AppWidgetProvider {
@Nonnull AppWidgetManager manager,
@Nonnull int[] widgetIds,
boolean partially) {
final EditorState editorState = Locator.getInstance().getEditor().getState();
final DisplayState displayState = Locator.getInstance().getDisplay().getState();
final EditorState editorState = App.getEditor().getState();
final DisplayState displayState = App.getDisplay().getState();
final Resources resources = context.getResources();
final SimpleTheme theme = App.getWidgetTheme().resolveThemeFor(App.getTheme());

View File

@ -23,7 +23,6 @@
package org.solovyev.android.calculator;
import org.mockito.Mockito;
import org.solovyev.android.calculator.history.History;
import org.solovyev.android.calculator.plot.CalculatorPlotter;
/**
@ -34,7 +33,7 @@ import org.solovyev.android.calculator.plot.CalculatorPlotter;
public class AbstractCalculatorTest {
protected void setUp() throws Exception {
Locator.getInstance().init(new CalculatorImpl(), CalculatorTestUtils.newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(History.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(CalculatorKeyboard.class), Mockito.mock(CalculatorPlotter.class), null);
Locator.getInstance().init(new CalculatorImpl(null, eventExecutor), CalculatorTestUtils.newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(Keyboard.class), Mockito.mock(CalculatorPlotter.class));
Locator.getInstance().getEngine().init();
}

View File

@ -95,7 +95,7 @@ public class AndroidEditorViewTest {
for (int j = 0; j < count; j++) {
try {
int textLength = random.nextInt(maxTextLength);
Locator.getInstance().getEditor().insert(Strings.generateRandomString(textLength), textLength);
App.getEditor().insert(Strings.generateRandomString(textLength), textLength);
} catch (Throwable e) {
System.out.println(e);
error.set(true);

View File

@ -24,7 +24,7 @@ public class CalculatorReceiverTest {
@Test
public void testShouldPressButtonOnIntent() throws Exception {
Locator.setKeyboard(mock(CalculatorKeyboard.class));
Locator.setKeyboard(mock(Keyboard.class));
final Intent intent = newButtonClickedIntent(application, four);
new CalculatorReceiver().onReceive(application, intent);
@ -35,7 +35,7 @@ public class CalculatorReceiverTest {
@Test
public void testShouldDoNothingIfButtonInvalid() throws Exception {
Locator.setKeyboard(mock(CalculatorKeyboard.class));
Locator.setKeyboard(mock(Keyboard.class));
final Intent intent = new Intent(application, CalculatorReceiver.class);
intent.setAction(ACTION_BUTTON_PRESSED);

View File

@ -26,8 +26,10 @@ import android.content.Context;
import org.junit.Assert;
import org.mockito.Mockito;
import org.solovyev.android.calculator.history.History;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.fakes.RoboSharedPreferences;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.language.Languages;
import org.solovyev.android.calculator.plot.CalculatorPlotter;
import java.io.ByteArrayInputStream;
@ -37,6 +39,8 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.text.DecimalFormatSymbols;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@ -56,7 +60,8 @@ public class CalculatorTestUtils {
public static final int TIMEOUT = 3;
public static void staticSetUp() throws Exception {
Locator.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(History.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(CalculatorKeyboard.class), Mockito.mock(CalculatorPlotter.class), null);
App.init(RuntimeEnvironment.application, new Languages(new RoboSharedPreferences(new HashMap<String, Map<String, Object>>(), "test", 0)));
Locator.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(Keyboard.class), Mockito.mock(CalculatorPlotter.class));
Locator.getInstance().getEngine().init();
final DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols();
@ -66,7 +71,7 @@ public class CalculatorTestUtils {
}
public static void staticSetUp(@Nullable Context context) throws Exception {
Locator.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(History.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(CalculatorKeyboard.class), Mockito.mock(CalculatorPlotter.class), null);
Locator.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class), Mockito.mock(Keyboard.class), Mockito.mock(CalculatorPlotter.class));
Locator.getInstance().getEngine().init();
if (context != null) {
@ -75,8 +80,8 @@ public class CalculatorTestUtils {
}
public static void initViews(@Nonnull Context context) {
Locator.getInstance().getEditor().setView(new EditorView(context));
Locator.getInstance().getDisplay().setView(new DisplayView(context));
App.getEditor().setView(new EditorView(context));
App.getDisplay().setView(new DisplayView(context));
}
@Nonnull
@ -100,7 +105,7 @@ public class CalculatorTestUtils {
public static void assertEval(@Nonnull String expected, @Nonnull String expression, @Nonnull JsclOperation operation) {
final Calculator calculator = Locator.getInstance().getCalculator();
Locator.getInstance().getDisplay().setState(DisplayState.empty());
App.getDisplay().setState(DisplayState.empty());
final CountDownLatch latch = new CountDownLatch(1);
final TestCalculatorEventListener calculatorEventListener = new TestCalculatorEventListener(latch);
@ -156,7 +161,7 @@ public class CalculatorTestUtils {
public static void assertError(@Nonnull String expression, @Nonnull JsclOperation operation) {
final Calculator calculator = Locator.getInstance().getCalculator();
Locator.getInstance().getDisplay().setState(DisplayState.empty());
App.getDisplay().setState(DisplayState.empty());
final CountDownLatch latch = new CountDownLatch(1);
final TestCalculatorEventListener calculatorEventListener = new TestCalculatorEventListener(latch);

View File

@ -22,22 +22,24 @@
package org.solovyev.android.calculator.history;
import com.squareup.otto.Bus;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.solovyev.android.CalculatorTestRunner;
import org.solovyev.android.calculator.CalculatorTestUtils;
import org.solovyev.android.calculator.DisplayState;
import org.solovyev.android.calculator.EditorState;
import java.util.List;
import java.util.concurrent.Executor;
import javax.annotation.Nonnull;
/**
* User: Solovyev_S
* Date: 10.10.12
* Time: 15:07
*/
@RunWith(CalculatorTestRunner.class)
public class HistoryTest {
@BeforeClass
@ -47,7 +49,12 @@ public class HistoryTest {
@Test
public void testGetStates() throws Exception {
History history = new History();
History history = new History(Mockito.any(Bus.class), new Executor() {
@Override
public void execute(@Nonnull Runnable command) {
command.run();
}
});
addState(history, "1");
addState(history, "12");

View File

@ -4,6 +4,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
}