This commit is contained in:
Sergey Solovyev
2012-12-01 17:46:16 +04:00
parent 5d1ddf976d
commit c2662e7537
243 changed files with 303 additions and 95 deletions

View File

@@ -10,6 +10,7 @@ import jscl.math.Generic;
import jscl.math.function.Constant;
import org.achartengine.ChartFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.about.CalculatorAboutActivity;
import org.solovyev.android.calculator.function.FunctionEditDialogFragment;
import org.solovyev.android.calculator.help.CalculatorHelpActivity;
@@ -28,9 +29,12 @@ import java.util.List;
* Date: 11/2/11
* Time: 2:18 PM
*/
public class CalculatorActivityLauncher {
public final class CalculatorActivityLauncher implements CalculatorEventListener {
public static void showHistory(@NotNull final Context context) {
public CalculatorActivityLauncher() {
}
public static void showHistory(@NotNull final Context context) {
showHistory(context, false);
}
@@ -166,4 +170,26 @@ public class CalculatorActivityLauncher {
CalculatorMessagesDialog.showDialogForMessages(messages, context);
}
}
@Override
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
switch (calculatorEventType){
case show_create_var_dialog:
App.getInstance().getUiThreadExecutor().execute(new Runnable() {
@Override
public void run() {
CalculatorActivityLauncher.createVar(App.getInstance().getApplication(), Locator.getInstance().getDisplay());
}
});
break;
case show_create_function_dialog:
App.getInstance().getUiThreadExecutor().execute(new Runnable() {
@Override
public void run() {
CalculatorActivityLauncher.createFunction(App.getInstance().getApplication(), Locator.getInstance().getDisplay());
}
});
break;
}
}
}

View File

@@ -75,6 +75,8 @@ public class CalculatorApplication extends android.app.Application {
public void onCreate() {
ACRA.init(this);
App.getInstance().init(this);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
CalculatorPreferences.setDefaultValues(preferences);

View File

@@ -1,257 +0,0 @@
package org.solovyev.android.calculator;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.preference.PreferenceManager;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.RemoteViews;
import jscl.AngleUnit;
import jscl.NumeralBase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.AndroidUtils;
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
import org.solovyev.android.calculator.view.AngleUnitsButton;
import org.solovyev.android.calculator.view.NumeralBasesButton;
import org.solovyev.android.view.drag.DragButton;
import org.solovyev.android.view.drag.DragDirection;
import org.solovyev.android.view.drag.SimpleOnDragListener;
import org.solovyev.common.math.Point2d;
/**
* User: serso
* Date: 9/28/12
* Time: 12:06 AM
*/
public final class CalculatorButtons {
private CalculatorButtons () {
}
public static void processButtons(@NotNull CalculatorPreferences.Gui.Theme theme,
@NotNull CalculatorPreferences.Gui.Layout layout,
@NotNull View root) {
if ( layout == CalculatorPreferences.Gui.Layout.main_calculator_mobile ) {
final float textSize = root.getContext().getResources().getDimension(R.dimen.cpp_keyboard_button_text_size_mobile);
AndroidUtils.processViewsOfType(root, DragButton.class, new AndroidUtils.ViewProcessor<DragButton>() {
@Override
public void process(@NotNull DragButton button) {
button.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize);
}
});
}
}
static void initMultiplicationButton(@NotNull View root) {
final View multiplicationButton = root.findViewById(R.id.multiplicationButton);
if ( multiplicationButton instanceof Button) {
((Button) multiplicationButton).setText(Locator.getInstance().getEngine().getMultiplicationSign());
}
}
public static void initMultiplicationButton(@NotNull RemoteViews views) {
views.setTextViewText(R.id.multiplicationButton, Locator.getInstance().getEngine().getMultiplicationSign());
}
public static void toggleEqualsButton(@Nullable SharedPreferences preferences,
@NotNull Activity activity) {
preferences = preferences == null ? PreferenceManager.getDefaultSharedPreferences(activity) : preferences;
final boolean large = AndroidUtils.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE, activity.getResources().getConfiguration()) &&
CalculatorPreferences.Gui.getLayout(preferences) != CalculatorPreferences.Gui.Layout.main_calculator_mobile;
if (!large) {
if (AndroidUtils.getScreenOrientation(activity) == Configuration.ORIENTATION_PORTRAIT
|| !CalculatorPreferences.Gui.autoOrientation.getPreference(preferences)) {
final DragButton equalsButton = (DragButton)activity.findViewById(R.id.equalsButton);
if (equalsButton != null) {
if (CalculatorPreferences.Gui.showEqualsButton.getPreference(preferences)) {
equalsButton.setVisibility(View.VISIBLE);
} else {
equalsButton.setVisibility(View.GONE);
}
}
}
}
}
/*
**********************************************************************
*
* STATIC CLASSES
*
**********************************************************************
*/
static class RoundBracketsDragProcessor implements SimpleOnDragListener.DragProcessor {
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
final boolean result;
if (dragDirection == DragDirection.left) {
getKeyboard().roundBracketsButtonPressed();
result = true;
} else {
result = new DigitButtonDragProcessor(getKeyboard()).processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent);
}
return result;
}
}
@NotNull
private static CalculatorKeyboard getKeyboard() {
return Locator.getInstance().getKeyboard();
}
static class VarsDragProcessor implements SimpleOnDragListener.DragProcessor {
@NotNull
private Context context;
VarsDragProcessor(@NotNull Context context) {
this.context = context;
}
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection,
@NotNull DragButton dragButton,
@NotNull Point2d startPoint2d,
@NotNull MotionEvent motionEvent) {
boolean result = false;
if (dragDirection == DragDirection.up) {
CalculatorActivityLauncher.createVar(context, Locator.getInstance().getDisplay());
result = true;
}
return result;
}
}
static class AngleUnitsChanger implements SimpleOnDragListener.DragProcessor {
@NotNull
private final DigitButtonDragProcessor processor;
@NotNull
private final Context context;
AngleUnitsChanger(@NotNull Context context) {
this.context = context;
this.processor = new DigitButtonDragProcessor(Locator.getInstance().getKeyboard());
}
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection,
@NotNull DragButton dragButton,
@NotNull Point2d startPoint2d,
@NotNull MotionEvent motionEvent) {
boolean result = false;
if (dragButton instanceof AngleUnitsButton) {
if (dragDirection != DragDirection.left) {
final String directionText = ((AngleUnitsButton) dragButton).getText(dragDirection);
if (directionText != null) {
try {
final AngleUnit angleUnits = AngleUnit.valueOf(directionText);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
final AngleUnit oldAngleUnits = AndroidCalculatorEngine.Preferences.angleUnit.getPreference(preferences);
if (oldAngleUnits != angleUnits) {
Locator.getInstance().getPreferenceService().setAngleUnits(angleUnits);
}
result = true;
} catch (IllegalArgumentException e) {
Log.d(this.getClass().getName(), "Unsupported angle units: " + directionText);
}
}
} else if (dragDirection == DragDirection.left) {
result = processor.processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent);
}
}
return result;
}
}
static class NumeralBasesChanger implements SimpleOnDragListener.DragProcessor {
@NotNull
private final Context context;
NumeralBasesChanger(@NotNull Context context) {
this.context = context;
}
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection,
@NotNull DragButton dragButton,
@NotNull Point2d startPoint2d,
@NotNull MotionEvent motionEvent) {
boolean result = false;
if (dragButton instanceof NumeralBasesButton) {
final String directionText = ((NumeralBasesButton) dragButton).getText(dragDirection);
if (directionText != null) {
try {
final NumeralBase numeralBase = NumeralBase.valueOf(directionText);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
final NumeralBase oldNumeralBase = AndroidCalculatorEngine.Preferences.numeralBase.getPreference(preferences);
if (oldNumeralBase != numeralBase) {
Locator.getInstance().getPreferenceService().setNumeralBase(numeralBase);
}
result = true;
} catch (IllegalArgumentException e) {
Log.d(this.getClass().getName(), "Unsupported numeral base: " + directionText);
}
}
}
return result;
}
}
static class FunctionsDragProcessor implements SimpleOnDragListener.DragProcessor {
@NotNull
private Context context;
FunctionsDragProcessor(@NotNull Context context) {
this.context = context;
}
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection,
@NotNull DragButton dragButton,
@NotNull Point2d startPoint2d,
@NotNull MotionEvent motionEvent) {
boolean result = false;
if (dragDirection == DragDirection.up) {
CalculatorActivityLauncher.createFunction(context, Locator.getInstance().getDisplay());
result = true;
}
return result;
}
}
}

View File

@@ -1,212 +0,0 @@
package org.solovyev.android.calculator;
import android.content.SharedPreferences;
import jscl.AngleUnit;
import jscl.NumeralBase;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.AndroidUtils;
import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
import org.solovyev.android.calculator.plot.GraphLineColor;
import org.solovyev.android.prefs.*;
import org.solovyev.android.view.VibratorContainer;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
/**
* User: serso
* Date: 4/20/12
* Time: 12:42 PM
*/
public final class CalculatorPreferences {
private CalculatorPreferences() {
throw new AssertionError();
}
public static final Preference<Integer> appVersion = new IntegerPreference("application.version", -1);
public static final Preference<Integer> appOpenedCounter = new IntegerPreference("app_opened_counter", 0);
public static class OnscreenCalculator {
public static final Preference<Boolean> startOnBoot = new BooleanPreference("onscreen_start_on_boot", false);
}
public static class Calculations {
public static final Preference<Boolean> calculateOnFly = new BooleanPreference("calculations_calculate_on_fly", true);
public static final Preference<Boolean> showCalculationMessagesDialog = new BooleanPreference("show_calculation_messages_dialog", true);
public static final Preference<NumeralBase> preferredNumeralBase = StringPreference.newInstance("preferred_numeral_base", AndroidCalculatorEngine.Preferences.numeralBase.getDefaultValue(), NumeralBase.class);
public static final Preference<AngleUnit> preferredAngleUnits = StringPreference.newInstance("preferred_angle_units", AndroidCalculatorEngine.Preferences.angleUnit.getDefaultValue(), AngleUnit.class);
public static final Preference<Long> lastPreferredPreferencesCheck = new LongPreference("preferred_preferences_check_time", 0L);
}
public static class Gui {
public static final Preference<Theme> theme = StringPreference.newInstance("org.solovyev.android.calculator.CalculatorActivity_calc_theme", Theme.metro_blue_theme, Theme.class);
public static final Preference<Layout> layout = StringPreference.newInstance("org.solovyev.android.calculator.CalculatorActivity_calc_layout", Layout.main_calculator, Layout.class);
public static final Preference<Boolean> feedbackWindowShown = new BooleanPreference("feedback_window_shown", false);
public static final Preference<Boolean> notesppAnnounceShown = new BooleanPreference("notespp_announce_shown", false);
public static final Preference<Boolean> showReleaseNotes = new BooleanPreference("org.solovyev.android.calculator.CalculatorActivity_show_release_notes", true);
public static final Preference<Boolean> usePrevAsBack = new BooleanPreference("org.solovyev.android.calculator.CalculatorActivity_use_back_button_as_prev", false);
public static final Preference<Boolean> showEqualsButton = new BooleanPreference("showEqualsButton", true);
public static final Preference<Boolean> autoOrientation = new BooleanPreference("autoOrientation", true);
public static final Preference<Boolean> hideNumeralBaseDigits = new BooleanPreference("hideNumeralBaseDigits", true);
@NotNull
public static Theme getTheme(@NotNull SharedPreferences preferences) {
return theme.getPreferenceNoError(preferences);
}
@NotNull
public static Layout getLayout(@NotNull SharedPreferences preferences) {
return layout.getPreferenceNoError(preferences);
}
public static enum Theme {
default_theme(ThemeType.other, R.style.cpp_gray_theme),
violet_theme(ThemeType.other, R.style.cpp_violet_theme),
light_blue_theme(ThemeType.other, R.style.cpp_light_blue_theme),
metro_blue_theme(ThemeType.metro, R.style.cpp_metro_blue_theme),
metro_purple_theme(ThemeType.metro, R.style.cpp_metro_purple_theme),
metro_green_theme(ThemeType.metro, R.style.cpp_metro_green_theme);
@NotNull
private final ThemeType themeType;
@NotNull
private final Integer themeId;
Theme(@NotNull ThemeType themeType, @NotNull Integer themeId) {
this.themeType = themeType;
this.themeId = themeId;
}
@NotNull
public ThemeType getThemeType() {
return themeType;
}
@NotNull
public Integer getThemeId() {
return themeId;
}
}
public static enum ThemeType {
metro,
other
}
public static enum Layout {
main_calculator(R.layout.main_calculator),
main_calculator_mobile(R.layout.main_calculator_mobile),
// not used anymore
@Deprecated
main_cellphone(R.layout.main_calculator),
simple(R.layout.main_calculator);
private final int layoutId;
Layout(int layoutId) {
this.layoutId = layoutId;
}
public int getLayoutId() {
return layoutId;
}
}
}
public static class Graph {
public static final Preference<Boolean> interpolate = new BooleanPreference("graph_interpolate", true);
public static final Preference<GraphLineColor> lineColorReal = StringPreference.newInstance("graph_line_color_real", GraphLineColor.white, GraphLineColor.class);
public static final Preference<GraphLineColor> lineColorImag = StringPreference.newInstance("graph_line_color_imag", GraphLineColor.blue, GraphLineColor.class);
}
public static class History {
public static final Preference<Boolean> showIntermediateCalculations = new BooleanPreference("history_show_intermediate_calculations", false);
}
static void setDefaultValues(@NotNull SharedPreferences preferences) {
if (!AndroidCalculatorEngine.Preferences.groupingSeparator.isSet(preferences)) {
final Locale locale = Locale.getDefault();
if (locale != null) {
final DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(locale);
int index = MathType.grouping_separator.getTokens().indexOf(String.valueOf(decimalFormatSymbols.getGroupingSeparator()));
final String groupingSeparator;
if (index >= 0) {
groupingSeparator = MathType.grouping_separator.getTokens().get(index);
} else {
groupingSeparator = " ";
}
AndroidCalculatorEngine.Preferences.groupingSeparator.putPreference(preferences, groupingSeparator);
}
}
if (!AndroidCalculatorEngine.Preferences.angleUnit.isSet(preferences)) {
AndroidCalculatorEngine.Preferences.angleUnit.putDefault(preferences);
}
if (!AndroidCalculatorEngine.Preferences.numeralBase.isSet(preferences)) {
AndroidCalculatorEngine.Preferences.numeralBase.putDefault(preferences);
}
if (!AndroidCalculatorEngine.Preferences.multiplicationSign.isSet(preferences)) {
if (AndroidUtils.isPhoneModel(AndroidUtils.PhoneModel.samsung_galaxy_s) || AndroidUtils.isPhoneModel(AndroidUtils.PhoneModel.samsung_galaxy_s_2)) {
// workaround ofr samsung galaxy s phones
AndroidCalculatorEngine.Preferences.multiplicationSign.putPreference(preferences, "*");
}
}
applyDefaultPreference(preferences, Gui.theme);
applyDefaultPreference(preferences, Gui.layout);
if (Gui.layout.getPreference(preferences) == Gui.Layout.main_cellphone) {
Gui.layout.putDefault(preferences);
}
applyDefaultPreference(preferences, Gui.feedbackWindowShown);
applyDefaultPreference(preferences, Gui.notesppAnnounceShown);
applyDefaultPreference(preferences, Gui.showReleaseNotes);
applyDefaultPreference(preferences, Gui.usePrevAsBack);
applyDefaultPreference(preferences, Gui.showEqualsButton);
applyDefaultPreference(preferences, Gui.autoOrientation);
applyDefaultPreference(preferences, Gui.hideNumeralBaseDigits);
applyDefaultPreference(preferences, Graph.interpolate);
applyDefaultPreference(preferences, Graph.lineColorImag);
applyDefaultPreference(preferences, Graph.lineColorReal);
applyDefaultPreference(preferences, History.showIntermediateCalculations);
applyDefaultPreference(preferences, Calculations.calculateOnFly);
applyDefaultPreference(preferences, Calculations.preferredAngleUnits);
applyDefaultPreference(preferences, Calculations.preferredNumeralBase);
// renew value after each application start
Calculations.showCalculationMessagesDialog.putDefault(preferences);
Calculations.lastPreferredPreferencesCheck.putDefault(preferences);
if (!VibratorContainer.Preferences.hapticFeedbackEnabled.isSet(preferences)) {
VibratorContainer.Preferences.hapticFeedbackEnabled.putPreference(preferences, true);
}
if (!VibratorContainer.Preferences.hapticFeedbackDuration.isSet(preferences)) {
VibratorContainer.Preferences.hapticFeedbackDuration.putPreference(preferences, 60L);
}
}
private static void applyDefaultPreference(@NotNull SharedPreferences preferences, @NotNull Preference<?> preference) {
if (!preference.isSet(preferences)) {
preference.putDefault(preferences);
}
}
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.calculator;
import android.view.MotionEvent;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.view.drag.DirectionDragButton;
import org.solovyev.android.view.drag.DragButton;
import org.solovyev.android.view.drag.DragDirection;
import org.solovyev.android.view.drag.SimpleOnDragListener;
import org.solovyev.common.math.Point2d;
/**
* User: serso
* Date: 9/16/11
* Time: 11:48 PM
*/
public class DigitButtonDragProcessor implements SimpleOnDragListener.DragProcessor {
@NotNull
private CalculatorKeyboard calculatorKeyboard;
public DigitButtonDragProcessor(@NotNull CalculatorKeyboard calculatorKeyboard) {
this.calculatorKeyboard = calculatorKeyboard;
}
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
assert dragButton instanceof DirectionDragButton;
calculatorKeyboard.buttonPressed(((DirectionDragButton) dragButton).getText(dragDirection));
return true;
}
}

View File

@@ -1,107 +0,0 @@
package org.solovyev.android.calculator;
import android.os.Parcel;
import android.os.Parcelable;
import jscl.math.Generic;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.jscl.JsclOperation;
/**
* User: serso
* Date: 11/18/12
* Time: 1:40 PM
*/
public final class ParcelableCalculatorDisplayViewState implements CalculatorDisplayViewState, Parcelable {
public static final Creator<ParcelableCalculatorDisplayViewState> CREATOR = new Creator<ParcelableCalculatorDisplayViewState>() {
@Override
public ParcelableCalculatorDisplayViewState createFromParcel(@NotNull Parcel in) {
return ParcelableCalculatorDisplayViewState.fromParcel(in);
}
@Override
public ParcelableCalculatorDisplayViewState[] newArray(int size) {
return new ParcelableCalculatorDisplayViewState[size];
}
};
@NotNull
private static ParcelableCalculatorDisplayViewState fromParcel(@NotNull Parcel in) {
final int selection = in.readInt();
final boolean valid = in.readInt() == 1;
final String stringResult = in.readString();
final String errorMessage = in.readString();
final JsclOperation operation = (JsclOperation) in.readSerializable();
CalculatorDisplayViewState calculatorDisplayViewState;
if (valid) {
calculatorDisplayViewState = CalculatorDisplayViewStateImpl.newValidState(operation, null, stringResult, selection);
} else {
calculatorDisplayViewState = CalculatorDisplayViewStateImpl.newErrorState(operation, errorMessage);
}
return new ParcelableCalculatorDisplayViewState(calculatorDisplayViewState);
}
@NotNull
private CalculatorDisplayViewState viewState;
public ParcelableCalculatorDisplayViewState(@NotNull CalculatorDisplayViewState viewState) {
this.viewState = viewState;
}
@Override
@NotNull
public String getText() {
return viewState.getText();
}
@Override
public int getSelection() {
return viewState.getSelection();
}
@Override
@Nullable
public Generic getResult() {
return viewState.getResult();
}
@Override
public boolean isValid() {
return viewState.isValid();
}
@Override
@Nullable
public String getErrorMessage() {
return viewState.getErrorMessage();
}
@Override
@NotNull
public JsclOperation getOperation() {
return viewState.getOperation();
}
@Override
@Nullable
public String getStringResult() {
return viewState.getStringResult();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NotNull Parcel out, int flags) {
out.writeInt(viewState.getSelection());
out.writeInt(viewState.isValid() ? 1 : 0);
out.writeString(viewState.getStringResult());
out.writeString(viewState.getErrorMessage());
out.writeSerializable(viewState.getOperation());
}
}

View File

@@ -1,61 +0,0 @@
package org.solovyev.android.calculator;
import android.os.Parcel;
import android.os.Parcelable;
import org.jetbrains.annotations.NotNull;
/**
* User: serso
* Date: 11/18/12
* Time: 1:40 PM
*/
public final class ParcelableCalculatorEditorViewState implements CalculatorEditorViewState, Parcelable {
public static final Creator<ParcelableCalculatorEditorViewState> CREATOR = new Creator<ParcelableCalculatorEditorViewState>() {
@Override
public ParcelableCalculatorEditorViewState createFromParcel(@NotNull Parcel in) {
return ParcelableCalculatorEditorViewState.fromParcel(in);
}
@Override
public ParcelableCalculatorEditorViewState[] newArray(int size) {
return new ParcelableCalculatorEditorViewState[size];
}
};
@NotNull
private CalculatorEditorViewState viewState;
public ParcelableCalculatorEditorViewState(@NotNull CalculatorEditorViewState viewState) {
this.viewState = viewState;
}
@NotNull
private static ParcelableCalculatorEditorViewState fromParcel(@NotNull Parcel in) {
final String text = in.readString();
final int selection = in.readInt();
return new ParcelableCalculatorEditorViewState(CalculatorEditorViewStateImpl.newInstance(text, selection));
}
@Override
@NotNull
public String getText() {
return viewState.getText();
}
@Override
public int getSelection() {
return viewState.getSelection();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NotNull Parcel out, int flags) {
out.writeString(viewState.getText());
out.writeInt(viewState.getSelection());
}
}

View File

@@ -1,126 +0,0 @@
package org.solovyev.android.calculator.external;
import android.content.Context;
import android.content.Intent;
import android.os.Parcelable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.Calculator;
import org.solovyev.android.calculator.CalculatorApplication;
import org.solovyev.android.calculator.CalculatorDisplayChangeEventData;
import org.solovyev.android.calculator.CalculatorDisplayViewState;
import org.solovyev.android.calculator.CalculatorEditorChangeEventData;
import org.solovyev.android.calculator.CalculatorEditorViewState;
import org.solovyev.android.calculator.CalculatorEventData;
import org.solovyev.android.calculator.CalculatorEventHolder;
import org.solovyev.android.calculator.CalculatorEventListener;
import org.solovyev.android.calculator.CalculatorEventType;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.CalculatorUtils;
import org.solovyev.android.calculator.ParcelableCalculatorDisplayViewState;
import org.solovyev.android.calculator.ParcelableCalculatorEditorViewState;
import java.util.HashSet;
import java.util.Set;
/**
* User: serso
* Date: 10/19/12
* Time: 11:11 PM
*/
public class AndroidExternalListenersContainer implements CalculatorExternalListenersContainer, CalculatorEventListener {
/*
**********************************************************************
*
* CONSTANTS
*
**********************************************************************
*/
public static final String EVENT_ID_EXTRA = "eventId";
public static final String INIT_ACTION = "org.solovyev.android.calculator.INIT";
public static final String INIT_ACTION_CREATE_VIEW_EXTRA = "createView";
public static final String EDITOR_STATE_CHANGED_ACTION = "org.solovyev.android.calculator.EDITOR_STATE_CHANGED";
public static final String EDITOR_STATE_EXTRA = "editorState";
public static final String DISPLAY_STATE_CHANGED_ACTION = "org.solovyev.android.calculator.DISPLAY_STATE_CHANGED";
public static final String DISPLAY_STATE_EXTRA = "displayState";
private static final String TAG = "Calculator++ External Listener Helper";
private final Set<Class<?>> externalListeners = new HashSet<Class<?>>();
@NotNull
private final CalculatorEventHolder lastEvent = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
public AndroidExternalListenersContainer(@NotNull Calculator calculator) {
calculator.addCalculatorEventListener(this);
}
public void onEditorStateChanged(@NotNull Context context,
@NotNull CalculatorEventData calculatorEventData,
@NotNull CalculatorEditorViewState editorViewState) {
for (Class<?> externalListener : externalListeners) {
final Intent intent = new Intent(EDITOR_STATE_CHANGED_ACTION);
intent.setClass(context, externalListener);
intent.putExtra(EVENT_ID_EXTRA, calculatorEventData.getEventId());
intent.putExtra(EDITOR_STATE_EXTRA, (Parcelable) new ParcelableCalculatorEditorViewState(editorViewState));
context.sendBroadcast(intent);
Locator.getInstance().getNotifier().showDebugMessage(TAG, "Editor state changed broadcast sent");
}
}
private void onDisplayStateChanged(@NotNull Context context,
@NotNull CalculatorEventData calculatorEventData,
@NotNull CalculatorDisplayViewState displayViewState) {
for (Class<?> externalListener : externalListeners) {
final Intent intent = new Intent(DISPLAY_STATE_CHANGED_ACTION);
intent.setClass(context, externalListener);
intent.putExtra(EVENT_ID_EXTRA, calculatorEventData.getEventId());
intent.putExtra(DISPLAY_STATE_EXTRA, (Parcelable) new ParcelableCalculatorDisplayViewState(displayViewState));
context.sendBroadcast(intent);
Locator.getInstance().getNotifier().showDebugMessage(TAG, "Display state changed broadcast sent");
}
}
@Override
public void addExternalListener(@NotNull Class<?> externalCalculatorClass) {
externalListeners.add(externalCalculatorClass);
}
@Override
public boolean removeExternalListener(@NotNull Class<?> externalCalculatorClass) {
return externalListeners.remove(externalCalculatorClass);
}
@Override
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
final CalculatorEventHolder.Result result = lastEvent.apply(calculatorEventData);
if (result.isNewAfter()) {
switch (calculatorEventType) {
case editor_state_changed_light:
case editor_state_changed:
final CalculatorEditorChangeEventData editorChangeData = (CalculatorEditorChangeEventData) data;
final CalculatorEditorViewState newEditorState = editorChangeData.getNewValue();
Locator.getInstance().getNotifier().showDebugMessage(TAG, "Editor state changed: " + newEditorState.getText());
onEditorStateChanged(CalculatorApplication.getInstance(), calculatorEventData, newEditorState);
break;
case display_state_changed:
final CalculatorDisplayChangeEventData displayChangeData = (CalculatorDisplayChangeEventData) data;
final CalculatorDisplayViewState newDisplayState = displayChangeData.getNewValue();
Locator.getInstance().getNotifier().showDebugMessage(TAG, "Display state changed: " + newDisplayState.getText());
onDisplayStateChanged(CalculatorApplication.getInstance(), calculatorEventData, newDisplayState);
break;
}
}
}
}

View File

@@ -1,92 +0,0 @@
package org.solovyev.android.calculator.external;
import android.content.Context;
import android.content.Intent;
import android.os.Parcelable;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.CalculatorDisplayViewState;
import org.solovyev.android.calculator.CalculatorEditorViewState;
import org.solovyev.android.calculator.Locator;
import org.solovyev.common.MutableObject;
/**
* User: serso
* Date: 11/20/12
* Time: 10:34 PM
*/
public class DefaultExternalCalculatorIntentHandler implements ExternalCalculatorIntentHandler {
private static final String TAG = ExternalCalculatorIntentHandler.class.getSimpleName();
@NotNull
private final MutableObject<Long> lastDisplayEventId = new MutableObject<Long>(0L);
@NotNull
private final MutableObject<Long> lastEditorEventId = new MutableObject<Long>(0L);
@NotNull
private final ExternalCalculatorStateUpdater stateUpdater;
public DefaultExternalCalculatorIntentHandler(@NotNull ExternalCalculatorStateUpdater stateUpdater) {
this.stateUpdater = stateUpdater;
}
@Override
public void onIntent(@NotNull Context context, @NotNull Intent intent) {
if (AndroidExternalListenersContainer.EDITOR_STATE_CHANGED_ACTION.equals(intent.getAction())) {
Locator.getInstance().getNotifier().showDebugMessage(TAG, "Editor state changed broadcast received!");
final Long eventId = intent.getLongExtra(AndroidExternalListenersContainer.EVENT_ID_EXTRA, 0L);
boolean updateEditor = false;
synchronized (lastEditorEventId) {
if (eventId > lastEditorEventId.getObject()) {
lastEditorEventId.setObject(eventId);
updateEditor = true;
}
}
if (updateEditor) {
final Parcelable object = intent.getParcelableExtra(AndroidExternalListenersContainer.EDITOR_STATE_EXTRA);
if (object instanceof CalculatorEditorViewState) {
onEditorStateChanged(context, (CalculatorEditorViewState) object);
}
}
} else if (AndroidExternalListenersContainer.DISPLAY_STATE_CHANGED_ACTION.equals(intent.getAction())) {
Locator.getInstance().getNotifier().showDebugMessage(TAG, "Display state changed broadcast received!");
final Long eventId = intent.getLongExtra(AndroidExternalListenersContainer.EVENT_ID_EXTRA, 0L);
boolean updateDisplay = false;
synchronized (lastDisplayEventId) {
if (eventId > lastDisplayEventId.getObject()) {
lastDisplayEventId.setObject(eventId);
updateDisplay = true;
}
}
if (updateDisplay) {
final Parcelable object = intent.getParcelableExtra(AndroidExternalListenersContainer.DISPLAY_STATE_EXTRA);
if (object instanceof CalculatorDisplayViewState) {
onDisplayStateChanged(context, (CalculatorDisplayViewState) object);
}
}
} else if ( AndroidExternalListenersContainer.INIT_ACTION.equals(intent.getAction()) ) {
updateState(context, Locator.getInstance().getEditor().getViewState(), Locator.getInstance().getDisplay().getViewState());
}
}
protected void updateState(@NotNull Context context,
@NotNull CalculatorEditorViewState editorViewState,
@NotNull CalculatorDisplayViewState displayViewState) {
stateUpdater.updateState(context, editorViewState, displayViewState);
}
protected void onDisplayStateChanged(@NotNull Context context, @NotNull CalculatorDisplayViewState displayViewState) {
updateState(context, Locator.getInstance().getEditor().getViewState(), displayViewState);
}
protected void onEditorStateChanged(@NotNull Context context, @NotNull CalculatorEditorViewState editorViewState) {
updateState(context, editorViewState, Locator.getInstance().getDisplay().getViewState());
}
}

View File

@@ -1,15 +0,0 @@
package org.solovyev.android.calculator.external;
import android.content.Context;
import android.content.Intent;
import org.jetbrains.annotations.NotNull;
/**
* User: serso
* Date: 11/20/12
* Time: 10:33 PM
*/
public interface ExternalCalculatorIntentHandler {
void onIntent(@NotNull Context context, @NotNull Intent intent);
}

View File

@@ -1,18 +0,0 @@
package org.solovyev.android.calculator.external;
import android.content.Context;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.CalculatorDisplayViewState;
import org.solovyev.android.calculator.CalculatorEditorViewState;
/**
* User: serso
* Date: 11/20/12
* Time: 10:42 PM
*/
public interface ExternalCalculatorStateUpdater {
void updateState(@NotNull Context context,
@NotNull CalculatorEditorViewState editorState,
@NotNull CalculatorDisplayViewState displayState);
}

View File

@@ -1,294 +0,0 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.calculator.model;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import jscl.AngleUnit;
import jscl.JsclMathEngine;
import jscl.MathEngine;
import jscl.NumeralBase;
import jscl.math.function.Function;
import jscl.math.function.IConstant;
import jscl.math.operator.Operator;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.CalculatorEngine;
import org.solovyev.android.calculator.CalculatorEngineImpl;
import org.solovyev.android.calculator.CalculatorFunctionsMathRegistry;
import org.solovyev.android.calculator.CalculatorMathEngine;
import org.solovyev.android.calculator.CalculatorMathRegistry;
import org.solovyev.android.calculator.CalculatorOperatorsMathRegistry;
import org.solovyev.android.calculator.CalculatorPostfixFunctionsRegistry;
import org.solovyev.android.calculator.CalculatorVarsRegistry;
import org.solovyev.android.calculator.MathPersistenceEntity;
import org.solovyev.android.calculator.R;
import org.solovyev.android.prefs.BooleanPreference;
import org.solovyev.android.prefs.Preference;
import org.solovyev.android.prefs.StringPreference;
import org.solovyev.common.text.EnumMapper;
import org.solovyev.common.text.NumberMapper;
import org.solovyev.common.text.StringUtils;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* User: serso
* Date: 9/12/11
* Time: 11:38 PM
*/
public class AndroidCalculatorEngine implements CalculatorEngine, SharedPreferences.OnSharedPreferenceChangeListener {
private static final String GROUPING_SEPARATOR_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_calc_grouping_separator";
private static final String MULTIPLICATION_SIGN_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_calc_multiplication_sign";
private static final String MULTIPLICATION_SIGN_DEFAULT = "×";
private static final String MAX_CALCULATION_TIME_P_KEY = "calculation.max_calculation_time";
private static final String MAX_CALCULATION_TIME_DEFAULT = "5";
private static final String SCIENCE_NOTATION_P_KEY = "calculation.output.science_notation";
private static final boolean SCIENCE_NOTATION_DEFAULT = false;
private static final String ROUND_RESULT_P_KEY = "org.solovyev.android.calculator.CalculatorModel_round_result";
private static final boolean ROUND_RESULT_DEFAULT = true;
private static final String RESULT_PRECISION_P_KEY = "org.solovyev.android.calculator.CalculatorModel_result_precision";
private static final String RESULT_PRECISION_DEFAULT = "5";
private static final String NUMERAL_BASES_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_numeral_bases";
private static final String NUMERAL_BASES_DEFAULT = "dec";
private static final String ANGLE_UNITS_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_angle_units";
private static final String ANGLE_UNITS_DEFAULT = "deg";
public static class Preferences {
public static final Preference<String> groupingSeparator = StringPreference.newInstance(GROUPING_SEPARATOR_P_KEY, JsclMathEngine.GROUPING_SEPARATOR_DEFAULT);
public static final Preference<String> multiplicationSign = StringPreference.newInstance(MULTIPLICATION_SIGN_P_KEY, MULTIPLICATION_SIGN_DEFAULT);
public static final Preference<Integer> precision = StringPreference.newInstance(RESULT_PRECISION_P_KEY, RESULT_PRECISION_DEFAULT, new NumberMapper<Integer>(Integer.class));
public static final Preference<Boolean> roundResult = new BooleanPreference(ROUND_RESULT_P_KEY, ROUND_RESULT_DEFAULT);
public static final Preference<NumeralBase> numeralBase = StringPreference.newInstance(NUMERAL_BASES_P_KEY, NUMERAL_BASES_DEFAULT, EnumMapper.newInstance(NumeralBase.class));
public static final Preference<AngleUnit> angleUnit = StringPreference.newInstance(ANGLE_UNITS_P_KEY, ANGLE_UNITS_DEFAULT, EnumMapper.newInstance(AngleUnit.class));
public static final Preference<Boolean> scienceNotation = new BooleanPreference(SCIENCE_NOTATION_P_KEY, SCIENCE_NOTATION_DEFAULT);
public static final Preference<Integer> maxCalculationTime = StringPreference.newInstance(MAX_CALCULATION_TIME_P_KEY, MAX_CALCULATION_TIME_DEFAULT, new NumberMapper<Integer>(Integer.class));
private static final List<String> preferenceKeys = new ArrayList<String>();
static {
preferenceKeys.add(groupingSeparator.getKey());
preferenceKeys.add(multiplicationSign.getKey());
preferenceKeys.add(precision.getKey());
preferenceKeys.add(roundResult.getKey());
preferenceKeys.add(numeralBase.getKey());
preferenceKeys.add(angleUnit.getKey());
preferenceKeys.add(scienceNotation.getKey());
preferenceKeys.add(maxCalculationTime.getKey());
}
@NotNull
public static List<String> getPreferenceKeys() {
return Collections.unmodifiableList(preferenceKeys);
}
}
@NotNull
private final Context context;
@NotNull
private final CalculatorEngine calculatorEngine;
@NotNull
private final Object lock;
public AndroidCalculatorEngine(@NotNull Application application) {
this.context = application;
PreferenceManager.getDefaultSharedPreferences(application).registerOnSharedPreferenceChangeListener(this);
this.lock = new Object();
final JsclMathEngine engine = JsclMathEngine.getInstance();
this.calculatorEngine = new CalculatorEngineImpl(engine,
new CalculatorVarsRegistry(engine.getConstantsRegistry(), new AndroidMathEntityDao<Var>(R.string.p_calc_vars, application, Vars.class)),
new CalculatorFunctionsMathRegistry(engine.getFunctionsRegistry(), new AndroidMathEntityDao<AFunction>(R.string.p_calc_functions, application, Functions.class)),
new CalculatorOperatorsMathRegistry(engine.getOperatorsRegistry(), new AndroidMathEntityDao<MathPersistenceEntity>(null, application, null)),
new CalculatorPostfixFunctionsRegistry(engine.getPostfixFunctionsRegistry(), new AndroidMathEntityDao<MathPersistenceEntity>(null, application, null)),
this.lock);
}
@Override
@NotNull
public CalculatorMathRegistry<IConstant> getVarsRegistry() {
return calculatorEngine.getVarsRegistry();
}
@Override
@NotNull
public CalculatorMathRegistry<Function> getFunctionsRegistry() {
return calculatorEngine.getFunctionsRegistry();
}
@Override
@NotNull
public CalculatorMathRegistry<Operator> getOperatorsRegistry() {
return calculatorEngine.getOperatorsRegistry();
}
@Override
@NotNull
public CalculatorMathRegistry<Operator> getPostfixFunctionsRegistry() {
return calculatorEngine.getPostfixFunctionsRegistry();
}
@Override
@NotNull
public CalculatorMathEngine getMathEngine() {
return calculatorEngine.getMathEngine();
}
@NotNull
@Override
public MathEngine getMathEngine0() {
return calculatorEngine.getMathEngine0();
}
@NotNull
@Override
public NumeralBase getNumeralBase() {
return calculatorEngine.getNumeralBase();
}
@Override
public void init() {
synchronized (lock) {
reset();
}
}
@Override
public void reset() {
synchronized (lock) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
softReset(preferences);
calculatorEngine.reset();
}
}
@Override
public void softReset() {
synchronized (lock) {
softReset(PreferenceManager.getDefaultSharedPreferences(context));
calculatorEngine.softReset();
}
}
@Override
public void setUseGroupingSeparator(boolean useGroupingSeparator) {
calculatorEngine.setUseGroupingSeparator(useGroupingSeparator);
}
@Override
public void setGroupingSeparator(char groupingSeparator) {
calculatorEngine.setGroupingSeparator(groupingSeparator);
}
@Override
public void setPrecision(@NotNull Integer precision) {
calculatorEngine.setPrecision(precision);
}
@Override
public void setRoundResult(@NotNull Boolean round) {
calculatorEngine.setRoundResult(round);
}
@NotNull
@Override
public AngleUnit getAngleUnits() {
return calculatorEngine.getAngleUnits();
}
@Override
public void setAngleUnits(@NotNull AngleUnit angleUnits) {
calculatorEngine.setAngleUnits(angleUnits);
}
@Override
public void setNumeralBase(@NotNull NumeralBase numeralBase) {
calculatorEngine.setNumeralBase(numeralBase);
}
@Override
public void setMultiplicationSign(@NotNull String multiplicationSign) {
calculatorEngine.setMultiplicationSign(multiplicationSign);
}
@Override
public void setScienceNotation(@NotNull Boolean scienceNotation) {
calculatorEngine.setScienceNotation(scienceNotation);
}
@Override
public void setTimeout(@NotNull Integer timeout) {
calculatorEngine.setTimeout(timeout);
}
private void softReset(@NotNull SharedPreferences preferences) {
this.setPrecision(Preferences.precision.getPreference(preferences));
this.setRoundResult(Preferences.roundResult.getPreference(preferences));
this.setAngleUnits(getAngleUnitsFromPrefs(preferences));
this.setNumeralBase(getNumeralBaseFromPrefs(preferences));
this.setMultiplicationSign(Preferences.multiplicationSign.getPreference(preferences));
this.setScienceNotation(Preferences.scienceNotation.getPreference(preferences));
this.setTimeout(Preferences.maxCalculationTime.getPreference(preferences));
final String groupingSeparator = Preferences.groupingSeparator.getPreference(preferences);
if (StringUtils.isEmpty(groupingSeparator)) {
this.setUseGroupingSeparator(false);
} else {
this.setUseGroupingSeparator(true);
setGroupingSeparator(groupingSeparator.charAt(0));
}
}
@NotNull
public NumeralBase getNumeralBaseFromPrefs(@NotNull SharedPreferences preferences) {
return Preferences.numeralBase.getPreference(preferences);
}
@NotNull
public AngleUnit getAngleUnitsFromPrefs(@NotNull SharedPreferences preferences) {
return Preferences.angleUnit.getPreference(preferences);
}
//for tests only
public void setDecimalGroupSymbols(@NotNull DecimalFormatSymbols decimalGroupSymbols) {
this.calculatorEngine.setDecimalGroupSymbols(decimalGroupSymbols);
}
@Override
@NotNull
public String getMultiplicationSign() {
return calculatorEngine.getMultiplicationSign();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if ( Preferences.getPreferenceKeys().contains(key) ) {
this.softReset();
}
}
}

View File

@@ -1,99 +0,0 @@
package org.solovyev.android.calculator.model;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.preference.PreferenceManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import org.solovyev.android.calculator.CalculatorApplication;
import org.solovyev.android.calculator.MathEntityDao;
import org.solovyev.android.calculator.MathEntityPersistenceContainer;
import org.solovyev.android.calculator.MathPersistenceEntity;
import java.io.StringWriter;
/**
* User: serso
* Date: 10/7/12
* Time: 6:46 PM
*/
public class AndroidMathEntityDao<T extends MathPersistenceEntity> implements MathEntityDao<T> {
@NotNull
private static final String TAG = AndroidMathEntityDao.class.getSimpleName();
@Nullable
private final Integer preferenceStringId;
@NotNull
private final Context context;
@Nullable
private final Class<? extends MathEntityPersistenceContainer<T>> persistenceContainerClass;
public AndroidMathEntityDao(@Nullable Integer preferenceStringId,
@NotNull Application application,
@Nullable Class<? extends MathEntityPersistenceContainer<T>> persistenceContainerClass) {
this.preferenceStringId = preferenceStringId;
this.context = application;
this.persistenceContainerClass = persistenceContainerClass;
}
@Override
public void save(@NotNull MathEntityPersistenceContainer<T> container) {
if (preferenceStringId != null) {
final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
final SharedPreferences.Editor editor = settings.edit();
final StringWriter sw = new StringWriter();
final Serializer serializer = new Persister();
try {
serializer.write(container, sw);
} catch (Exception e) {
throw new RuntimeException(e);
}
editor.putString(context.getString(preferenceStringId), sw.toString());
editor.commit();
}
}
@Nullable
@Override
public MathEntityPersistenceContainer<T> load() {
if (persistenceContainerClass != null && preferenceStringId != null) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
if (preferences != null) {
final String value = preferences.getString(context.getString(preferenceStringId), null);
if (value != null) {
final Serializer serializer = new Persister();
try {
return serializer.read(persistenceContainerClass, value);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
return null;
}
@Nullable
public String getDescription(@NotNull String descriptionId) {
final Resources resources = context.getResources();
final int stringId = resources.getIdentifier(descriptionId, "string", CalculatorApplication.class.getPackage().getName());
try {
return resources.getString(stringId);
} catch (Resources.NotFoundException e) {
return null;
}
}
}

View File

@@ -1,28 +0,0 @@
package org.solovyev.android.calculator.plot;
import android.graphics.Color;
/**
* User: serso
* Date: 10/4/12
* Time: 10:08 PM
*/
public enum GraphLineColor {
white(Color.WHITE),
grey(Color.GRAY),
red(Color.RED),
blue(Color.rgb(16, 100, 140)),
green(Color.GREEN);
private final int color;
private GraphLineColor(int color) {
this.color = color;
}
public int getColor() {
return this.color;
}
}

View File

@@ -1,44 +0,0 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.android.calculator.view;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Paint;
import android.text.TextPaint;
import android.util.AttributeSet;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.R;
import org.solovyev.android.view.drag.DirectionDragButton;
/**
* User: serso
* Date: 11/22/11
* Time: 2:42 PM
*/
public class AngleUnitsButton extends DirectionDragButton {
public AngleUnitsButton(Context context, @NotNull AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void initDirectionTextPaint(@NotNull Paint basePaint,
@NotNull DirectionTextData directionTextData,
@NotNull Resources resources) {
super.initDirectionTextPaint(basePaint, directionTextData, resources);
final TextPaint directionTextPaint = directionTextData.getPaint();
if (Locator.getInstance().getEngine().getAngleUnits().name().equals(directionTextData.getText())) {
directionTextPaint.setColor(resources.getColor(R.color.cpp_selected_angle_unit_text_color));
} else {
directionTextPaint.setColor(resources.getColor(R.color.cpp_default_text_color));
directionTextPaint.setAlpha(getDirectionTextAlpha());
}
}
}

View File

@@ -1,44 +0,0 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.android.calculator.view;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Paint;
import android.text.TextPaint;
import android.util.AttributeSet;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.R;
import org.solovyev.android.view.drag.DirectionDragButton;
/**
* User: serso
* Date: 12/8/11
* Time: 2:22 AM
*/
public class NumeralBasesButton extends DirectionDragButton {
public NumeralBasesButton(Context context, @NotNull AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void initDirectionTextPaint(@NotNull Paint basePaint,
@NotNull DirectionTextData directionTextData,
@NotNull Resources resources) {
super.initDirectionTextPaint(basePaint, directionTextData, resources);
final TextPaint directionTextPaint = directionTextData.getPaint();
if (Locator.getInstance().getEngine().getNumeralBase().name().equals(directionTextData.getText())) {
directionTextPaint.setColor(resources.getColor(R.color.cpp_selected_angle_unit_text_color));
} else {
directionTextPaint.setColor(resources.getColor(R.color.cpp_default_text_color));
directionTextPaint.setAlpha(getDirectionTextAlpha());
}
}
}

View File

@@ -1,164 +0,0 @@
package org.solovyev.android.calculator.widget;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.text.Html;
import android.widget.RemoteViews;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.CalculatorButtons;
import org.solovyev.android.calculator.CalculatorDisplayViewState;
import org.solovyev.android.calculator.CalculatorEditorViewState;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.external.ExternalCalculatorIntentHandler;
import org.solovyev.android.calculator.external.ExternalCalculatorStateUpdater;
/**
* User: Solovyev_S
* Date: 19.10.12
* Time: 16:18
*/
abstract class AbstractCalculatorWidgetProvider extends AppWidgetProvider implements ExternalCalculatorStateUpdater {
static final String BUTTON_ID_EXTRA = "buttonId";
static final String BUTTON_PRESSED_ACTION = "org.solovyev.android.calculator.widget.BUTTON_PRESSED";
private static final String TAG = "Calculator++ Widget";
/*
**********************************************************************
*
* FIELDS
*
**********************************************************************
*/
@Nullable
private String cursorColor;
@NotNull
private ExternalCalculatorIntentHandler intentHandler = new CalculatorWidgetIntentHandler(this);
/*
**********************************************************************
*
* CONSTRUCTORS
*
**********************************************************************
*/
protected AbstractCalculatorWidgetProvider() {
final Class<? extends AppWidgetProvider> componentClass = this.getComponentClass();
Locator.getInstance().getExternalListenersContainer().addExternalListener(componentClass);
}
/*
**********************************************************************
*
* METHODS
*
**********************************************************************
*/
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
getCursorColor(context);
}
@NotNull
private String getCursorColor(@NotNull Context context) {
if (cursorColor == null) {
cursorColor = Integer.toHexString(context.getResources().getColor(R.color.cpp_widget_cursor_color)).substring(2);
}
return cursorColor;
}
@Override
public void onUpdate(@NotNull Context context,
@NotNull AppWidgetManager appWidgetManager,
@NotNull int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
updateWidget(context, appWidgetManager, appWidgetIds, Locator.getInstance().getEditor().getViewState(), Locator.getInstance().getDisplay().getViewState());
}
@Override
public void updateState(@NotNull Context context,
@NotNull CalculatorEditorViewState editorState,
@NotNull CalculatorDisplayViewState displayState) {
final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
final int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, getComponentClass()));
updateWidget(context, appWidgetManager, appWidgetIds, editorState, displayState);
}
@NotNull
protected Class<? extends AbstractCalculatorWidgetProvider> getComponentClass(){
return this.getClass();
}
private void updateWidget(@NotNull Context context,
@NotNull AppWidgetManager appWidgetManager,
@NotNull int[] appWidgetIds,
@NotNull CalculatorEditorViewState editorState,
@NotNull CalculatorDisplayViewState displayState) {
for (int appWidgetId : appWidgetIds) {
final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
for (WidgetButton button : WidgetButton.values()) {
final Intent onButtonClickIntent = new Intent(context, getComponentClass());
onButtonClickIntent.setAction(BUTTON_PRESSED_ACTION);
onButtonClickIntent.putExtra(BUTTON_ID_EXTRA, button.getButtonId());
final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, button.getButtonId(), onButtonClickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
if (pendingIntent != null) {
views.setOnClickPendingIntent(button.getButtonId(), pendingIntent);
}
}
updateEditorState(context, views, editorState);
updateDisplayState(context, views, displayState);
CalculatorButtons.initMultiplicationButton(views);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
this.intentHandler.onIntent(context, intent);
}
private void updateDisplayState(@NotNull Context context, @NotNull RemoteViews views, @NotNull CalculatorDisplayViewState displayState) {
if (displayState.isValid()) {
views.setTextViewText(R.id.calculator_display, displayState.getText());
views.setTextColor(R.id.calculator_display, context.getResources().getColor(R.color.cpp_default_text_color));
} else {
views.setTextColor(R.id.calculator_display, context.getResources().getColor(R.color.cpp_display_error_text_color));
}
}
private void updateEditorState(@NotNull Context context, @NotNull RemoteViews views, @NotNull CalculatorEditorViewState editorState) {
String text = editorState.getText();
CharSequence newText = text;
int selection = editorState.getSelection();
if (selection >= 0 && selection <= text.length()) {
// inject cursor
newText = Html.fromHtml(text.substring(0, selection) + "<font color=\"#" + getCursorColor(context) + "\">|</font>" + text.substring(selection));
}
Locator.getInstance().getNotifier().showDebugMessage(TAG, "New editor state: " + text);
views.setTextViewText(R.id.calculator_editor, newText);
}
}

View File

@@ -1,11 +0,0 @@
package org.solovyev.android.calculator.widget;
import android.app.Activity;
/**
* User: Solovyev_S
* Date: 19.10.12
* Time: 16:20
*/
public class CalculatorWidgetConfigurationActivity extends Activity {
}

View File

@@ -1,37 +0,0 @@
package org.solovyev.android.calculator.widget;
import android.content.Context;
import android.content.Intent;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.external.DefaultExternalCalculatorIntentHandler;
import org.solovyev.android.calculator.external.ExternalCalculatorStateUpdater;
/**
* User: serso
* Date: 11/20/12
* Time: 10:39 PM
*/
public class CalculatorWidgetIntentHandler extends DefaultExternalCalculatorIntentHandler {
public CalculatorWidgetIntentHandler(@NotNull ExternalCalculatorStateUpdater stateUpdater) {
super(stateUpdater);
}
@Override
public void onIntent(@NotNull Context context, @NotNull Intent intent) {
super.onIntent(context, intent);
if (AbstractCalculatorWidgetProvider.BUTTON_PRESSED_ACTION.equals(intent.getAction())) {
final int buttonId = intent.getIntExtra(AbstractCalculatorWidgetProvider.BUTTON_ID_EXTRA, 0);
final WidgetButton button = WidgetButton.getById(buttonId);
if (button != null) {
button.onClick(context);
}
} else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(intent.getAction())) {
updateState(context, Locator.getInstance().getEditor().getViewState(), Locator.getInstance().getDisplay().getViewState());
}
}
}

View File

@@ -1,9 +0,0 @@
package org.solovyev.android.calculator.widget;
/**
* User: serso
* Date: 11/18/12
* Time: 1:00 PM
*/
public class CalculatorWidgetProvider extends AbstractCalculatorWidgetProvider {
}

View File

@@ -1,9 +0,0 @@
package org.solovyev.android.calculator.widget;
/**
* User: serso
* Date: 11/18/12
* Time: 1:01 PM
*/
public class CalculatorWidgetProvider3x4 extends AbstractCalculatorWidgetProvider {
}

View File

@@ -1,9 +0,0 @@
package org.solovyev.android.calculator.widget;
/**
* User: serso
* Date: 11/18/12
* Time: 1:01 PM
*/
public class CalculatorWidgetProvider4x4 extends AbstractCalculatorWidgetProvider {
}

View File

@@ -1,9 +0,0 @@
package org.solovyev.android.calculator.widget;
/**
* User: serso
* Date: 11/18/12
* Time: 7:43 PM
*/
public class CalculatorWidgetProvider4x5 extends AbstractCalculatorWidgetProvider {
}

View File

@@ -1,131 +0,0 @@
package org.solovyev.android.calculator.widget;
import android.content.Context;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.Locator;
import org.solovyev.android.calculator.CalculatorSpecialButton;
import org.solovyev.android.calculator.R;
import java.util.HashMap;
import java.util.Map;
/**
* User: serso
* Date: 10/20/12
* Time: 12:05 AM
*/
public enum WidgetButton {
/*digits*/
one(R.id.oneDigitButton, "1"),
two(R.id.twoDigitButton, "2"),
three(R.id.threeDigitButton, "3"),
four(R.id.fourDigitButton, "4"),
five(R.id.fiveDigitButton, "5"),
six(R.id.sixDigitButton, "6"),
seven(R.id.sevenDigitButton, "7"),
eight(R.id.eightDigitButton, "8"),
nine(R.id.nineDigitButton, "9"),
zero(R.id.zeroDigitButton, "0"),
period(R.id.periodButton, "."),
brackets(R.id.roundBracketsButton, "()"),
settings(R.id.settingsButton, CalculatorSpecialButton.settings_detached),
like(R.id.likeButton, CalculatorSpecialButton.like),
/*last row*/
left(R.id.leftButton, CalculatorSpecialButton.cursor_left),
right(R.id.rightButton, CalculatorSpecialButton.cursor_right),
vars(R.id.vars_button, CalculatorSpecialButton.vars_detached),
functions(R.id.functions_button, CalculatorSpecialButton.functions_detached),
app(R.id.appButton, CalculatorSpecialButton.open_app),
history(R.id.historyButton, CalculatorSpecialButton.history_detached),
/*operations*/
multiplication(R.id.multiplicationButton, "*"),
division(R.id.divisionButton, "/"),
plus(R.id.plusButton, "+"),
subtraction(R.id.subtractionButton, "-"),
percent(R.id.percentButton, "%"),
power(R.id.powerButton, "^"),
/*last column*/
clear(R.id.clearButton, CalculatorSpecialButton.clear),
erase(R.id.eraseButton, CalculatorSpecialButton.erase, CalculatorSpecialButton.clear),
copy(R.id.copyButton, CalculatorSpecialButton.copy),
paste(R.id.pasteButton, CalculatorSpecialButton.paste),
/*equals*/
equals(R.id.equalsButton, CalculatorSpecialButton.equals);
private final int buttonId;
@NotNull
private final String onClickText;
@Nullable
private final String onLongClickText;
@NotNull
private static Map<Integer, WidgetButton> buttonsByIds = new HashMap<Integer, WidgetButton>();
WidgetButton(int buttonId, @NotNull CalculatorSpecialButton onClickButton, @Nullable CalculatorSpecialButton onLongClickButton) {
this(buttonId, onClickButton.getActionCode(), onLongClickButton == null ? null : onLongClickButton.getActionCode());
}
WidgetButton(int buttonId, @NotNull CalculatorSpecialButton onClickButton) {
this(buttonId, onClickButton, null);
}
WidgetButton(int buttonId, @NotNull String onClickText, @Nullable String onLongClickText) {
this.buttonId = buttonId;
this.onClickText = onClickText;
this.onLongClickText = onLongClickText;
}
WidgetButton(int buttonId, @NotNull String onClickText) {
this(buttonId, onClickText, null);
}
public void onLongClick(@NotNull Context context) {
Locator.getInstance().getNotifier().showDebugMessage("Calculator++ Widget", "Button pressed: " + onLongClickText);
if (onLongClickText != null) {
Locator.getInstance().getKeyboard().buttonPressed(onLongClickText);
}
}
public void onClick(@NotNull Context context) {
Locator.getInstance().getNotifier().showDebugMessage("Calculator++ Widget", "Button pressed: " + onClickText);
Locator.getInstance().getKeyboard().buttonPressed(onClickText);
}
@Nullable
public static WidgetButton getById(int buttonId) {
initButtonsByIdsMap();
return buttonsByIds.get(buttonId);
}
private static void initButtonsByIdsMap() {
if ( buttonsByIds.isEmpty() ) {
// if not initialized
final WidgetButton[] widgetButtons = values();
final Map<Integer, WidgetButton> localButtonsByIds = new HashMap<Integer, WidgetButton>(widgetButtons.length);
for (WidgetButton widgetButton : widgetButtons) {
localButtonsByIds.put(widgetButton.getButtonId(), widgetButton);
}
buttonsByIds = localButtonsByIds;
}
}
public int getButtonId() {
return buttonId;
}
}