Merge branch 'dev-app-structure' into dev
Conflicts: android-app-core/src/main/java/org/solovyev/android/calculator/CalculatorButtons.java android-app/AndroidManifest.xml android-app/src/main/java/org/solovyev/android/calculator/about/CalculatorFragmentType.java
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package org.solovyev.android;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 03.10.12
|
||||
* Time: 10:48
|
||||
*/
|
||||
public final class AndroidUtils2 {
|
||||
|
||||
private AndroidUtils2() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,251 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Vibrator;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.history.CalculatorHistoryState;
|
||||
import org.solovyev.android.calculator.view.AngleUnitsButton;
|
||||
import org.solovyev.android.calculator.view.NumeralBasesButton;
|
||||
import org.solovyev.android.calculator.view.OnDragListenerVibrator;
|
||||
import org.solovyev.android.history.HistoryDragProcessor;
|
||||
import org.solovyev.android.view.drag.*;
|
||||
import org.solovyev.common.Announcer;
|
||||
import org.solovyev.common.math.Point2d;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/28/12
|
||||
* Time: 12:12 AM
|
||||
*/
|
||||
public abstract class AbstractCalculatorHelper implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
@NotNull
|
||||
private CalculatorPreferences.Gui.Layout layout;
|
||||
|
||||
@NotNull
|
||||
private CalculatorPreferences.Gui.Theme theme;
|
||||
|
||||
@Nullable
|
||||
private Vibrator vibrator;
|
||||
|
||||
@NotNull
|
||||
private final Announcer<DragPreferencesChangeListener> dpclRegister = new Announcer<DragPreferencesChangeListener>(DragPreferencesChangeListener.class);
|
||||
|
||||
@NotNull
|
||||
private String logTag = "CalculatorActivity";
|
||||
|
||||
protected AbstractCalculatorHelper() {
|
||||
}
|
||||
|
||||
protected AbstractCalculatorHelper(@NotNull String logTag) {
|
||||
this.logTag = logTag;
|
||||
}
|
||||
|
||||
protected void onCreate(@NotNull Activity activity) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
|
||||
vibrator = (Vibrator) activity.getSystemService(Activity.VIBRATOR_SERVICE);
|
||||
layout = CalculatorPreferences.Gui.layout.getPreferenceNoError(preferences);
|
||||
theme = CalculatorPreferences.Gui.theme.getPreferenceNoError(preferences);
|
||||
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
// let's disable locking of screen for monkeyrunner
|
||||
if (CalculatorApplication.isMonkeyRunner(activity)) {
|
||||
final KeyguardManager km = (KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE);
|
||||
km.newKeyguardLock(activity.getClass().getName()).disableKeyguard();
|
||||
}
|
||||
}
|
||||
|
||||
public void logDebug(@NotNull String message) {
|
||||
Log.d(logTag, message);
|
||||
}
|
||||
|
||||
public void logError(@NotNull String message) {
|
||||
Log.e(logTag, message);
|
||||
}
|
||||
|
||||
public void processButtons(@NotNull final Activity activity, @NotNull View root) {
|
||||
dpclRegister.clear();
|
||||
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
final SimpleOnDragListener.Preferences dragPreferences = SimpleOnDragListener.getPreferences(preferences, activity);
|
||||
|
||||
setOnDragListeners(root, dragPreferences, preferences);
|
||||
|
||||
final OnDragListener historyOnDragListener = new OnDragListenerVibrator(newOnDragListener(new HistoryDragProcessor<CalculatorHistoryState>(getCalculator()), dragPreferences), vibrator, preferences);
|
||||
final DragButton historyButton = getButton(root, R.id.cpp_button_history);
|
||||
if (historyButton != null) {
|
||||
historyButton.setOnDragListener(historyOnDragListener);
|
||||
}
|
||||
|
||||
final DragButton subtractionButton = getButton(root, R.id.cpp_button_subtraction);
|
||||
if (subtractionButton != null) {
|
||||
subtractionButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new SimpleOnDragListener.DragProcessor() {
|
||||
@Override
|
||||
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
|
||||
if (dragDirection == DragDirection.down) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_operators, null);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, dragPreferences), vibrator, preferences));
|
||||
}
|
||||
|
||||
final OnDragListener toPositionOnDragListener = new OnDragListenerVibrator(new SimpleOnDragListener(new CursorDragProcessor(), dragPreferences), vibrator, preferences);
|
||||
|
||||
final DragButton rightButton = getButton(root, R.id.cpp_button_right);
|
||||
if (rightButton != null) {
|
||||
rightButton.setOnDragListener(toPositionOnDragListener);
|
||||
}
|
||||
|
||||
final DragButton leftButton = getButton(root, R.id.cpp_button_left);
|
||||
if (leftButton != null) {
|
||||
leftButton.setOnDragListener(toPositionOnDragListener);
|
||||
}
|
||||
|
||||
final DragButton equalsButton = getButton(root, R.id.cpp_button_equals);
|
||||
if (equalsButton != null) {
|
||||
equalsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new EvalDragProcessor(), dragPreferences), vibrator, preferences));
|
||||
}
|
||||
|
||||
final AngleUnitsButton angleUnitsButton = (AngleUnitsButton) getButton(root, R.id.cpp_button_6);
|
||||
if (angleUnitsButton != null) {
|
||||
angleUnitsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new CalculatorButtons.AngleUnitsChanger(activity), dragPreferences), vibrator, preferences));
|
||||
}
|
||||
|
||||
final NumeralBasesButton clearButton = (NumeralBasesButton) getButton(root, R.id.cpp_button_clear);
|
||||
if (clearButton != null) {
|
||||
clearButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new CalculatorButtons.NumeralBasesChanger(activity), dragPreferences), vibrator, preferences));
|
||||
}
|
||||
|
||||
final DragButton varsButton = getButton(root, R.id.cpp_button_vars);
|
||||
if (varsButton != null) {
|
||||
varsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new CalculatorButtons.VarsDragProcessor(activity), dragPreferences), vibrator, preferences));
|
||||
}
|
||||
|
||||
final DragButton functionsButton = getButton(root, R.id.cpp_button_functions);
|
||||
if (functionsButton != null) {
|
||||
functionsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new CalculatorButtons.FunctionsDragProcessor(activity), dragPreferences), vibrator, preferences));
|
||||
}
|
||||
|
||||
final DragButton roundBracketsButton = getButton(root, R.id.cpp_button_round_brackets);
|
||||
if (roundBracketsButton != null) {
|
||||
roundBracketsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new CalculatorButtons.RoundBracketsDragProcessor(), dragPreferences), vibrator, preferences));
|
||||
}
|
||||
|
||||
if (layout == CalculatorPreferences.Gui.Layout.simple) {
|
||||
toggleButtonDirectionText(root, R.id.cpp_button_1, false, DragDirection.up, DragDirection.down);
|
||||
toggleButtonDirectionText(root, R.id.cpp_button_2, false, DragDirection.up, DragDirection.down);
|
||||
toggleButtonDirectionText(root, R.id.cpp_button_3, false, DragDirection.up, DragDirection.down);
|
||||
|
||||
toggleButtonDirectionText(root, R.id.cpp_button_6, false, DragDirection.up, DragDirection.down);
|
||||
toggleButtonDirectionText(root, R.id.cpp_button_7, false, DragDirection.left, DragDirection.up, DragDirection.down);
|
||||
toggleButtonDirectionText(root, R.id.cpp_button_8, false, DragDirection.left, DragDirection.up, DragDirection.down);
|
||||
|
||||
toggleButtonDirectionText(root, R.id.cpp_button_clear, false, DragDirection.left, DragDirection.up, DragDirection.down);
|
||||
|
||||
toggleButtonDirectionText(root, R.id.cpp_button_4, false, DragDirection.down);
|
||||
toggleButtonDirectionText(root, R.id.cpp_button_5, false, DragDirection.down);
|
||||
|
||||
toggleButtonDirectionText(root, R.id.cpp_button_9, false, DragDirection.left);
|
||||
|
||||
toggleButtonDirectionText(root, R.id.cpp_button_multiplication, false, DragDirection.left);
|
||||
toggleButtonDirectionText(root, R.id.cpp_button_plus, false, DragDirection.down, DragDirection.up);
|
||||
}
|
||||
|
||||
CalculatorButtons.processButtons(theme, layout, root);
|
||||
CalculatorButtons.toggleEqualsButton(preferences, activity);
|
||||
CalculatorButtons.initMultiplicationButton(root);
|
||||
NumeralBaseButtons.toggleNumericDigits(activity, preferences);
|
||||
}
|
||||
|
||||
private void toggleButtonDirectionText(@NotNull View root, int id, boolean showDirectionText, @NotNull DragDirection... dragDirections) {
|
||||
final View v = getButton(root, id);
|
||||
if (v instanceof DirectionDragButton ) {
|
||||
final DirectionDragButton button = (DirectionDragButton)v;
|
||||
for (DragDirection dragDirection : dragDirections) {
|
||||
button.showDirectionText(showDirectionText, dragDirection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Calculator getCalculator() {
|
||||
return Locator.getInstance().getCalculator();
|
||||
}
|
||||
|
||||
|
||||
private void setOnDragListeners(@NotNull View root, @NotNull SimpleOnDragListener.Preferences dragPreferences, @NotNull SharedPreferences preferences) {
|
||||
final OnDragListener onDragListener = new OnDragListenerVibrator(newOnDragListener(new DigitButtonDragProcessor(getKeyboard()), dragPreferences), vibrator, preferences);
|
||||
|
||||
final List<Integer> dragButtonIds = new ArrayList<Integer>();
|
||||
|
||||
for (Field field : R.id.class.getDeclaredFields()) {
|
||||
int modifiers = field.getModifiers();
|
||||
if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) {
|
||||
try {
|
||||
int viewId = field.getInt(R.id.class);
|
||||
final View view = root.findViewById(viewId);
|
||||
if (view instanceof DragButton) {
|
||||
dragButtonIds.add(viewId);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
Log.e(R.id.class.getName(), e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Integer dragButtonId : dragButtonIds) {
|
||||
final DragButton button = getButton(root, dragButtonId);
|
||||
if (button != null) {
|
||||
button.setOnDragListener(onDragListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private CalculatorKeyboard getKeyboard() {
|
||||
return Locator.getInstance().getKeyboard();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <T extends DragButton> T getButton(@NotNull View root, int buttonId) {
|
||||
return (T) root.findViewById(buttonId);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private SimpleOnDragListener newOnDragListener(@NotNull SimpleOnDragListener.DragProcessor dragProcessor,
|
||||
@NotNull SimpleOnDragListener.Preferences dragPreferences) {
|
||||
final SimpleOnDragListener onDragListener = new SimpleOnDragListener(dragProcessor, dragPreferences);
|
||||
dpclRegister.addListener(onDragListener);
|
||||
return onDragListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||
if (key != null && key.startsWith("org.solovyev.android.calculator.DragButtonCalibrationActivity")) {
|
||||
dpclRegister.announce().onDragPreferencesChange(SimpleOnDragListener.getPreferences(preferences, CalculatorApplication.getInstance()));
|
||||
}
|
||||
}
|
||||
|
||||
public void onDestroy(@NotNull Activity activity) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
|
||||
preferences.unregisterOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
}
|
@@ -0,0 +1,230 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import jscl.NumeralBase;
|
||||
import jscl.math.Generic;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.history.CalculatorHistoryState;
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
import org.solovyev.common.history.HistoryAction;
|
||||
import org.solovyev.common.msg.Message;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/22/12
|
||||
* Time: 5:42 PM
|
||||
*/
|
||||
public class AndroidCalculator implements Calculator, CalculatorEventListener, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
@NotNull
|
||||
private final CalculatorImpl calculator = new CalculatorImpl();
|
||||
|
||||
@NotNull
|
||||
private final Application context;
|
||||
|
||||
public AndroidCalculator(@NotNull Application application) {
|
||||
this.context = application;
|
||||
this.calculator.addCalculatorEventListener(this);
|
||||
|
||||
PreferenceManager.getDefaultSharedPreferences(application).registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
public void init(@NotNull final Activity activity) {
|
||||
setEditor(activity);
|
||||
setDisplay(activity);
|
||||
}
|
||||
|
||||
public void setDisplay(@NotNull Activity activity) {
|
||||
final AndroidCalculatorDisplayView displayView = (AndroidCalculatorDisplayView) activity.findViewById(R.id.calculator_display);
|
||||
setDisplay(activity, displayView);
|
||||
}
|
||||
|
||||
public void setDisplay(@NotNull Context context, @NotNull AndroidCalculatorDisplayView displayView) {
|
||||
displayView.init(context);
|
||||
Locator.getInstance().getDisplay().setView(displayView);
|
||||
}
|
||||
|
||||
public void setEditor(@NotNull Activity activity) {
|
||||
final AndroidCalculatorEditorView editorView = (AndroidCalculatorEditorView) activity.findViewById(R.id.calculator_editor);
|
||||
setEditor(activity, editorView);
|
||||
}
|
||||
|
||||
public void setEditor(@NotNull Context context, @NotNull AndroidCalculatorEditorView editorView) {
|
||||
editorView.init(context);
|
||||
Locator.getInstance().getEditor().setView(editorView);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* DELEGATED TO CALCULATOR
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public CalculatorEventData evaluate(@NotNull JsclOperation operation, @NotNull String expression) {
|
||||
return calculator.evaluate(operation, expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public CalculatorEventData evaluate(@NotNull JsclOperation operation, @NotNull String expression, @NotNull Long sequenceId) {
|
||||
return calculator.evaluate(operation, expression, sequenceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConversionPossible(@NotNull Generic generic, @NotNull NumeralBase from, @NotNull NumeralBase to) {
|
||||
return calculator.isConversionPossible(generic, from, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public CalculatorEventData convert(@NotNull Generic generic, @NotNull NumeralBase to) {
|
||||
return calculator.convert(generic, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public CalculatorEventData fireCalculatorEvent(@NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
return calculator.fireCalculatorEvent(calculatorEventType, data);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CalculatorEventData fireCalculatorEvent(@NotNull CalculatorEventType calculatorEventType, @Nullable Object data, @NotNull Object source) {
|
||||
return calculator.fireCalculatorEvent(calculatorEventType, data, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public CalculatorEventData fireCalculatorEvent(@NotNull CalculatorEventType calculatorEventType, @Nullable Object data, @NotNull Long sequenceId) {
|
||||
return calculator.fireCalculatorEvent(calculatorEventType, data, sequenceId);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PreparedExpression prepareExpression(@NotNull String expression) throws CalculatorParseException {
|
||||
return calculator.prepareExpression(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
this.calculator.init();
|
||||
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
this.calculator.setCalculateOnFly(CalculatorPreferences.Calculations.calculateOnFly.getPreference(prefs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) {
|
||||
calculator.addCalculatorEventListener(calculatorEventListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCalculatorEventListener(@NotNull CalculatorEventListener calculatorEventListener) {
|
||||
calculator.removeCalculatorEventListener(calculatorEventListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
calculator.fireCalculatorEvent(calculatorEventData, calculatorEventType, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCalculatorEvents(@NotNull List<CalculatorEvent> calculatorEvents) {
|
||||
calculator.fireCalculatorEvents(calculatorEvents);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doHistoryAction(@NotNull HistoryAction historyAction) {
|
||||
calculator.doHistoryAction(historyAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentHistoryState(@NotNull CalculatorHistoryState editorHistoryState) {
|
||||
calculator.setCurrentHistoryState(editorHistoryState);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public CalculatorHistoryState getCurrentHistoryState() {
|
||||
return calculator.getCurrentHistoryState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate() {
|
||||
calculator.evaluate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluate(@NotNull Long sequenceId) {
|
||||
calculator.evaluate(sequenceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simplify() {
|
||||
calculator.simplify();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
switch (calculatorEventType) {
|
||||
case calculation_messages:
|
||||
CalculatorActivityLauncher.showCalculationMessagesDialog(CalculatorApplication.getInstance(), (List<Message>) data);
|
||||
break;
|
||||
case show_history:
|
||||
CalculatorActivityLauncher.showHistory(CalculatorApplication.getInstance());
|
||||
break;
|
||||
case show_history_detached:
|
||||
CalculatorActivityLauncher.showHistory(CalculatorApplication.getInstance(), true);
|
||||
break;
|
||||
case show_functions:
|
||||
CalculatorActivityLauncher.showFunctions(CalculatorApplication.getInstance());
|
||||
break;
|
||||
case show_functions_detached:
|
||||
CalculatorActivityLauncher.showFunctions(CalculatorApplication.getInstance(), true);
|
||||
break;
|
||||
case show_operators:
|
||||
CalculatorActivityLauncher.showOperators(CalculatorApplication.getInstance());
|
||||
break;
|
||||
case show_operators_detached:
|
||||
CalculatorActivityLauncher.showOperators(CalculatorApplication.getInstance(), true);
|
||||
break;
|
||||
case show_vars:
|
||||
CalculatorActivityLauncher.showVars(CalculatorApplication.getInstance());
|
||||
break;
|
||||
case show_vars_detached:
|
||||
CalculatorActivityLauncher.showVars(CalculatorApplication.getInstance(), true);
|
||||
break;
|
||||
case show_settings:
|
||||
CalculatorActivityLauncher.showSettings(CalculatorApplication.getInstance());
|
||||
break;
|
||||
case show_settings_detached:
|
||||
CalculatorActivityLauncher.showSettings(CalculatorApplication.getInstance(), true);
|
||||
break;
|
||||
case show_like_dialog:
|
||||
CalculatorActivityLauncher.likeButtonPressed(CalculatorApplication.getInstance());
|
||||
break;
|
||||
case open_app:
|
||||
CalculatorActivityLauncher.openApp(CalculatorApplication.getInstance());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(@NotNull SharedPreferences prefs, @NotNull String key) {
|
||||
if ( CalculatorPreferences.Calculations.calculateOnFly.getKey().equals(key) ) {
|
||||
this.calculator.setCalculateOnFly(CalculatorPreferences.Calculations.calculateOnFly.getPreference(prefs));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.text.ClipboardManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/22/12
|
||||
* Time: 1:35 PM
|
||||
*/
|
||||
public class AndroidCalculatorClipboard implements CalculatorClipboard {
|
||||
|
||||
@NotNull
|
||||
private final Context context;
|
||||
|
||||
public AndroidCalculatorClipboard(@NotNull Application application) {
|
||||
this.context = application;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
if ( clipboard.hasText() ) {
|
||||
return String.valueOf(clipboard.getText());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(@NotNull String text) {
|
||||
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
clipboard.setText(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(@NotNull CharSequence text) {
|
||||
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
clipboard.setText(text);
|
||||
}
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Vibrator;
|
||||
import android.preference.PreferenceManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.view.VibratorContainer;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/18/12
|
||||
* Time: 6:05 PM
|
||||
*/
|
||||
public class AndroidCalculatorKeyboard implements CalculatorKeyboard {
|
||||
|
||||
@NotNull
|
||||
private final CalculatorKeyboard calculatorKeyboard;
|
||||
|
||||
@NotNull
|
||||
private final Context context;
|
||||
|
||||
private VibratorContainer vibrator;
|
||||
|
||||
public AndroidCalculatorKeyboard(@NotNull Application application,
|
||||
@NotNull CalculatorKeyboard calculatorKeyboard) {
|
||||
this.context = application;
|
||||
this.calculatorKeyboard = calculatorKeyboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buttonPressed(@Nullable String text) {
|
||||
vibrate();
|
||||
calculatorKeyboard.buttonPressed(text);
|
||||
}
|
||||
|
||||
private void vibrate() {
|
||||
if (this.vibrator == null) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
final Vibrator vibrator = (Vibrator) context.getSystemService(Activity.VIBRATOR_SERVICE);
|
||||
|
||||
this.vibrator = new VibratorContainer(vibrator, preferences, 0.5f);
|
||||
}
|
||||
|
||||
this.vibrator.vibrate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void roundBracketsButtonPressed() {
|
||||
vibrate();
|
||||
calculatorKeyboard.roundBracketsButtonPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pasteButtonPressed() {
|
||||
vibrate();
|
||||
calculatorKeyboard.pasteButtonPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearButtonPressed() {
|
||||
vibrate();
|
||||
calculatorKeyboard.clearButtonPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyButtonPressed() {
|
||||
vibrate();
|
||||
calculatorKeyboard.copyButtonPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveCursorLeft() {
|
||||
vibrate();
|
||||
calculatorKeyboard.moveCursorLeft();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveCursorRight() {
|
||||
vibrate();
|
||||
calculatorKeyboard.moveCursorRight();
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.util.Log;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/11/12
|
||||
* Time: 12:15 AM
|
||||
*/
|
||||
public class AndroidCalculatorLogger implements CalculatorLogger {
|
||||
|
||||
@NotNull
|
||||
private static final String TAG = AndroidCalculatorLogger.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
public void debug(@Nullable String tag, @NotNull String message) {
|
||||
Log.d(getTag(tag), message);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getTag(@Nullable String tag) {
|
||||
return tag != null ? tag : TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(@Nullable String tag, @NotNull String message, @NotNull Throwable e) {
|
||||
Log.d(getTag(tag), message, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(@Nullable String tag, @NotNull String message, @NotNull Throwable e) {
|
||||
Log.e(getTag(tag), message, e);
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Application;
|
||||
import android.os.Handler;
|
||||
import android.widget.Toast;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.AndroidUtils;
|
||||
import org.solovyev.android.msg.AndroidMessage;
|
||||
import org.solovyev.common.msg.Message;
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/22/12
|
||||
* Time: 2:00 PM
|
||||
*/
|
||||
public class AndroidCalculatorNotifier implements CalculatorNotifier {
|
||||
|
||||
@NotNull
|
||||
private final Application application;
|
||||
|
||||
@NotNull
|
||||
private final Handler uiHandler = new Handler();
|
||||
|
||||
public AndroidCalculatorNotifier(@NotNull Application application) {
|
||||
assert AndroidUtils.isUiThread();
|
||||
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage(@NotNull Message message) {
|
||||
showMessageInUiThread(message.getLocalizedMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage(@NotNull Integer messageCode, @NotNull MessageType messageType, @NotNull List<Object> parameters) {
|
||||
showMessage(new AndroidMessage(messageCode, messageType, application, parameters));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMessage(@NotNull Integer messageCode, @NotNull MessageType messageType, @Nullable Object... parameters) {
|
||||
showMessage(new AndroidMessage(messageCode, messageType, application, parameters));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDebugMessage(@Nullable final String tag, @NotNull final String message) {
|
||||
/*if (AndroidUtils.isDebuggable(application)) {
|
||||
showMessageInUiThread(tag == null ? message : tag + ": " + message);
|
||||
}*/
|
||||
}
|
||||
|
||||
private void showMessageInUiThread(@NotNull final String message) {
|
||||
if (AndroidUtils.isUiThread()) {
|
||||
Toast.makeText(application, message, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
uiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(application,message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,94 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import jscl.AngleUnit;
|
||||
import jscl.NumeralBase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
|
||||
import org.solovyev.android.msg.AndroidMessage;
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/17/12
|
||||
* Time: 7:46 PM
|
||||
*/
|
||||
public class AndroidCalculatorPreferenceService implements CalculatorPreferenceService {
|
||||
|
||||
// one hour
|
||||
private static final Long PREFERRED_PREFS_INTERVAL_TIME = 1000L * 60L * 60L;
|
||||
|
||||
@NotNull
|
||||
private final Application application;
|
||||
|
||||
public AndroidCalculatorPreferenceService(@NotNull Application application) {
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkPreferredPreferences(boolean force) {
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(application);
|
||||
|
||||
final Long currentTime = System.currentTimeMillis();
|
||||
|
||||
if ( force || ( CalculatorPreferences.Calculations.showCalculationMessagesDialog.getPreference(prefs) && isTimeForCheck(currentTime, prefs))) {
|
||||
final NumeralBase preferredNumeralBase = CalculatorPreferences.Calculations.preferredNumeralBase.getPreference(prefs);
|
||||
final NumeralBase numeralBase = AndroidCalculatorEngine.Preferences.numeralBase.getPreference(prefs);
|
||||
|
||||
final AngleUnit preferredAngleUnits = CalculatorPreferences.Calculations.preferredAngleUnits.getPreference(prefs);
|
||||
final AngleUnit angleUnits = AndroidCalculatorEngine.Preferences.angleUnit.getPreference(prefs);
|
||||
|
||||
final List<CalculatorFixableMessage> messages = new ArrayList<CalculatorFixableMessage>(2);
|
||||
if ( numeralBase != preferredNumeralBase ) {
|
||||
messages.add(new CalculatorFixableMessage(application.getString(R.string.preferred_numeral_base_message, preferredNumeralBase.name(), numeralBase.name()), MessageType.warning, CalculatorFixableError.preferred_numeral_base));
|
||||
}
|
||||
|
||||
if ( angleUnits != preferredAngleUnits ) {
|
||||
messages.add(new CalculatorFixableMessage(application.getString(R.string.preferred_angle_units_message, preferredAngleUnits.name(), angleUnits.name()), MessageType.warning, CalculatorFixableError.preferred_angle_units));
|
||||
}
|
||||
|
||||
CalculatorMessagesDialog.showDialog(messages, application);
|
||||
|
||||
CalculatorPreferences.Calculations.lastPreferredPreferencesCheck.putPreference(prefs, currentTime);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isTimeForCheck(@NotNull Long currentTime, @NotNull SharedPreferences preferences) {
|
||||
final Long lastPreferredPreferencesCheckTime = CalculatorPreferences.Calculations.lastPreferredPreferencesCheck.getPreference(preferences);
|
||||
|
||||
return currentTime - lastPreferredPreferencesCheckTime > PREFERRED_PREFS_INTERVAL_TIME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPreferredAngleUnits() {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(application);
|
||||
setAngleUnits(CalculatorPreferences.Calculations.preferredAngleUnits.getPreference(preferences));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAngleUnits(@NotNull AngleUnit angleUnit) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(application);
|
||||
AndroidCalculatorEngine.Preferences.angleUnit.putPreference(preferences, angleUnit);
|
||||
|
||||
Locator.getInstance().getNotifier().showMessage(new AndroidMessage(R.string.c_angle_units_changed_to, MessageType.info, application, angleUnit.name()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPreferredNumeralBase() {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(application);
|
||||
setNumeralBase(CalculatorPreferences.Calculations.preferredNumeralBase.getPreference(preferences));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNumeralBase(@NotNull NumeralBase numeralBase) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(application);
|
||||
AndroidCalculatorEngine.Preferences.numeralBase.putPreference(preferences, numeralBase);
|
||||
|
||||
Locator.getInstance().getNotifier().showMessage(new AndroidMessage(R.string.c_numeral_base_changed_to, MessageType.info, application, numeralBase.name()));
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/7/12
|
||||
* Time: 7:17 PM
|
||||
*/
|
||||
public enum AndroidFunctionCategory {
|
||||
|
||||
trigonometric(R.string.c_fun_category_trig),
|
||||
hyperbolic_trigonometric(R.string.c_fun_category_hyper_trig),
|
||||
comparison(R.string.c_fun_category_comparison),
|
||||
my(R.string.c_fun_category_my),
|
||||
common(R.string.c_fun_category_common);
|
||||
|
||||
private final int captionId;
|
||||
|
||||
AndroidFunctionCategory(int captionId) {
|
||||
this.captionId = captionId;
|
||||
}
|
||||
|
||||
public int getCaptionId() {
|
||||
return captionId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AndroidFunctionCategory valueOf( @NotNull FunctionCategory functionCategory ) {
|
||||
for (AndroidFunctionCategory androidFunctionCategory : values()) {
|
||||
if ( androidFunctionCategory.name().equals(functionCategory.name()) ) {
|
||||
return androidFunctionCategory;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,109 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import jscl.NumeralBase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.units.CalculatorNumeralBase;
|
||||
import org.solovyev.android.view.drag.DirectionDragButton;
|
||||
import org.solovyev.android.view.drag.DragDirection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 4/21/12
|
||||
* Time: 8:00 PM
|
||||
*/
|
||||
public enum AndroidNumeralBase {
|
||||
|
||||
bin(CalculatorNumeralBase.bin) {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<Integer> getButtonIds() {
|
||||
return Arrays.asList(R.id.cpp_button_0, R.id.cpp_button_1);
|
||||
}
|
||||
},
|
||||
|
||||
oct(CalculatorNumeralBase.oct) {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<Integer> getButtonIds() {
|
||||
final List<Integer> result = new ArrayList<Integer>(bin.getButtonIds());
|
||||
result.addAll(Arrays.asList(R.id.cpp_button_2, R.id.cpp_button_3, R.id.cpp_button_4, R.id.cpp_button_5, R.id.cpp_button_6, R.id.cpp_button_7));
|
||||
return result;
|
||||
}
|
||||
},
|
||||
|
||||
dec(CalculatorNumeralBase.dec) {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<Integer> getButtonIds() {
|
||||
final List<Integer> result = new ArrayList<Integer>(oct.getButtonIds());
|
||||
result.addAll(Arrays.asList(R.id.cpp_button_8, R.id.cpp_button_9));
|
||||
return result;
|
||||
}
|
||||
},
|
||||
|
||||
hex(CalculatorNumeralBase.hex) {
|
||||
|
||||
@NotNull
|
||||
private List<Integer> specialHexButtonIds = Arrays.asList(R.id.cpp_button_1, R.id.cpp_button_2, R.id.cpp_button_3, R.id.cpp_button_4, R.id.cpp_button_5, R.id.cpp_button_6);
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<Integer> getButtonIds() {
|
||||
return dec.getButtonIds();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void toggleButton(boolean show, @NotNull DirectionDragButton button) {
|
||||
super.toggleButton(show, button);
|
||||
if (specialHexButtonIds.contains(button.getId())) {
|
||||
button.showDirectionText(show, DragDirection.left);
|
||||
button.invalidate();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
private final CalculatorNumeralBase calculatorNumeralBase;
|
||||
|
||||
private AndroidNumeralBase(@NotNull CalculatorNumeralBase calculatorNumeralBase) {
|
||||
this.calculatorNumeralBase = calculatorNumeralBase;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public abstract List<Integer> getButtonIds();
|
||||
|
||||
public void toggleButtons(boolean show, @NotNull Activity activity) {
|
||||
for (Integer buttonId : getButtonIds()) {
|
||||
final DirectionDragButton button = (DirectionDragButton) activity.findViewById(buttonId);
|
||||
if (button != null) {
|
||||
toggleButton(show, button);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void toggleButton(boolean show, @NotNull DirectionDragButton button) {
|
||||
button.setShowText(show);
|
||||
button.invalidate();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public NumeralBase getNumeralBase() {
|
||||
return calculatorNumeralBase.getNumeralBase();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static AndroidNumeralBase valueOf(@NotNull NumeralBase nb) {
|
||||
for (AndroidNumeralBase androidNumeralBase : values()) {
|
||||
if (androidNumeralBase.calculatorNumeralBase.getNumeralBase() == nb) {
|
||||
return androidNumeralBase;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(nb + " is not supported numeral base!");
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/7/12
|
||||
* Time: 7:41 PM
|
||||
*/
|
||||
public enum AndroidOperatorCategory {
|
||||
|
||||
derivatives(R.string.derivatives),
|
||||
other(R.string.other),
|
||||
my(R.string.c_fun_category_my),
|
||||
common(R.string.c_fun_category_common);
|
||||
|
||||
private final int captionId;
|
||||
|
||||
AndroidOperatorCategory(int captionId) {
|
||||
this.captionId = captionId;
|
||||
}
|
||||
|
||||
public int getCaptionId() {
|
||||
return captionId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AndroidOperatorCategory valueOf(@NotNull OperatorCategory operatorCategory) {
|
||||
for (AndroidOperatorCategory androidOperatorCategory : values()) {
|
||||
if ( androidOperatorCategory.name().equals(operatorCategory.name()) ) {
|
||||
return androidOperatorCategory;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/7/12
|
||||
* Time: 7:56 PM
|
||||
*/
|
||||
public enum AndroidVarCategory {
|
||||
|
||||
system(R.string.c_var_system),
|
||||
my(R.string.c_var_my);
|
||||
|
||||
private final int captionId;
|
||||
|
||||
AndroidVarCategory(int captionId) {
|
||||
this.captionId = captionId;
|
||||
}
|
||||
|
||||
public int getCaptionId() {
|
||||
return captionId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AndroidVarCategory valueOf(@NotNull VarCategory varCategory) {
|
||||
for (AndroidVarCategory androidVarCategory : values()) {
|
||||
if ( androidVarCategory.name().equals(varCategory.name()) ) {
|
||||
return androidVarCategory;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* 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.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.Html;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.AndroidUtils;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
import org.solovyev.android.calculator.about.CalculatorReleaseNotesFragment;
|
||||
import org.solovyev.android.fragments.FragmentUtils;
|
||||
import org.solovyev.android.prefs.Preference;
|
||||
import org.solovyev.common.equals.EqualsTool;
|
||||
import org.solovyev.common.history.HistoryAction;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
|
||||
public class CalculatorActivity extends SherlockFragmentActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
@NotNull
|
||||
public static final String TAG = CalculatorActivity.class.getSimpleName();
|
||||
|
||||
private boolean useBackAsPrev;
|
||||
|
||||
@NotNull
|
||||
private CalculatorActivityHelper activityHelper;
|
||||
|
||||
/**
|
||||
* Called when the activity is first created.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
final CalculatorPreferences.Gui.Layout layout = CalculatorPreferences.Gui.layout.getPreferenceNoError(preferences);
|
||||
|
||||
activityHelper = CalculatorApplication.getInstance().createActivityHelper(layout.getLayoutId(), TAG);
|
||||
activityHelper.logDebug("onCreate");
|
||||
activityHelper.onCreate(this, savedInstanceState);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
activityHelper.logDebug("super.onCreate");
|
||||
|
||||
if (findViewById(R.id.main_second_pane) != null) {
|
||||
activityHelper.addTab(this, CalculatorFragmentType.history, null, R.id.main_second_pane);
|
||||
activityHelper.addTab(this, CalculatorFragmentType.saved_history, null, R.id.main_second_pane);
|
||||
activityHelper.addTab(this, CalculatorFragmentType.variables, null, R.id.main_second_pane);
|
||||
activityHelper.addTab(this, CalculatorFragmentType.functions, null, R.id.main_second_pane);
|
||||
activityHelper.addTab(this, CalculatorFragmentType.operators, null, R.id.main_second_pane);
|
||||
activityHelper.addTab(this, CalculatorFragmentType.plotter, null, R.id.main_second_pane);
|
||||
activityHelper.addTab(this, CalculatorFragmentType.faq, null, R.id.main_second_pane);
|
||||
} else {
|
||||
getSupportActionBar().hide();
|
||||
}
|
||||
|
||||
FragmentUtils.createFragment(this, CalculatorEditorFragment.class, R.id.editorContainer, "editor");
|
||||
FragmentUtils.createFragment(this, CalculatorDisplayFragment.class, R.id.displayContainer, "display");
|
||||
FragmentUtils.createFragment(this, CalculatorKeyboardFragment.class, R.id.keyboardContainer, "keyboard");
|
||||
|
||||
this.useBackAsPrev = CalculatorPreferences.Gui.usePrevAsBack.getPreference(preferences);
|
||||
firstTimeInit(preferences, this);
|
||||
|
||||
toggleOrientationChange(preferences);
|
||||
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
Locator.getInstance().getPreferenceService().checkPreferredPreferences(false);
|
||||
|
||||
if ( CalculatorApplication.isMonkeyRunner(this) ) {
|
||||
Locator.getInstance().getKeyboard().buttonPressed("123");
|
||||
Locator.getInstance().getKeyboard().buttonPressed("+");
|
||||
Locator.getInstance().getKeyboard().buttonPressed("321");
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private AndroidCalculator getCalculator() {
|
||||
return ((AndroidCalculator) Locator.getInstance().getCalculator());
|
||||
}
|
||||
|
||||
private static void firstTimeInit(@NotNull SharedPreferences preferences, @NotNull Context context) {
|
||||
final Integer appOpenedCounter = CalculatorPreferences.appOpenedCounter.getPreference(preferences);
|
||||
if (appOpenedCounter != null) {
|
||||
CalculatorPreferences.appOpenedCounter.putPreference(preferences, appOpenedCounter + 1);
|
||||
}
|
||||
|
||||
final Integer savedVersion = CalculatorPreferences.appVersion.getPreference(preferences);
|
||||
|
||||
final int appVersion = AndroidUtils.getAppVersionCode(context, CalculatorActivity.class.getPackage().getName());
|
||||
|
||||
CalculatorPreferences.appVersion.putPreference(preferences, appVersion);
|
||||
|
||||
if (!CalculatorApplication.isMonkeyRunner(context)) {
|
||||
|
||||
boolean dialogShown = false;
|
||||
if (EqualsTool.areEqual(savedVersion, CalculatorPreferences.appVersion.getDefaultValue())) {
|
||||
// new start
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context).setMessage(R.string.c_first_start_text);
|
||||
builder.setPositiveButton(android.R.string.ok, null);
|
||||
builder.setTitle(R.string.c_first_start_text_title);
|
||||
builder.create().show();
|
||||
dialogShown = true;
|
||||
} else {
|
||||
if (savedVersion < appVersion) {
|
||||
final boolean showReleaseNotes = CalculatorPreferences.Gui.showReleaseNotes.getPreference(preferences);
|
||||
if (showReleaseNotes) {
|
||||
final String releaseNotes = CalculatorReleaseNotesFragment.getReleaseNotes(context, savedVersion + 1);
|
||||
if (!StringUtils.isEmpty(releaseNotes)) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context).setMessage(Html.fromHtml(releaseNotes));
|
||||
builder.setPositiveButton(android.R.string.ok, null);
|
||||
builder.setTitle(R.string.c_release_notes);
|
||||
builder.create().show();
|
||||
dialogShown = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Log.d(this.getClass().getName(), "Application was opened " + appOpenedCounter + " time!");
|
||||
if (!dialogShown) {
|
||||
if (appOpenedCounter != null && appOpenedCounter > 10) {
|
||||
dialogShown = showSpecialWindow(preferences, CalculatorPreferences.Gui.feedbackWindowShown, R.layout.feedback, R.id.feedbackText, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean showSpecialWindow(@NotNull SharedPreferences preferences, @NotNull Preference<Boolean> specialWindowShownPref, int layoutId, int textViewId, @NotNull Context context) {
|
||||
boolean result = false;
|
||||
|
||||
final Boolean specialWindowShown = specialWindowShownPref.getPreference(preferences);
|
||||
if ( specialWindowShown != null && !specialWindowShown ) {
|
||||
final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
|
||||
final View view = layoutInflater.inflate(layoutId, null);
|
||||
|
||||
final TextView feedbackTextView = (TextView) view.findViewById(textViewId);
|
||||
feedbackTextView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context).setView(view);
|
||||
builder.setPositiveButton(android.R.string.ok, null);
|
||||
builder.create().show();
|
||||
|
||||
result = true;
|
||||
specialWindowShownPref.putPreference(preferences, true);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
if (useBackAsPrev) {
|
||||
getCalculator().doHistoryAction(HistoryAction.undo);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public void equalsButtonClickHandler(@NotNull View v) {
|
||||
buttonPressed(CalculatorSpecialButton.equals);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
this.activityHelper.onPause(this);
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
final CalculatorPreferences.Gui.Layout newLayout = CalculatorPreferences.Gui.layout.getPreference(preferences);
|
||||
if ( newLayout != activityHelper.getLayout() ) {
|
||||
AndroidUtils.restartActivity(this);
|
||||
}
|
||||
|
||||
this.activityHelper.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
activityHelper.onDestroy(this);
|
||||
|
||||
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences preferences, @Nullable String key) {
|
||||
if ( CalculatorPreferences.Gui.usePrevAsBack.getKey().equals(key) ) {
|
||||
useBackAsPrev = CalculatorPreferences.Gui.usePrevAsBack.getPreference(preferences);
|
||||
}
|
||||
|
||||
if ( CalculatorPreferences.Gui.autoOrientation.getKey().equals(key) ) {
|
||||
toggleOrientationChange(preferences);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
activityHelper.onSaveInstanceState(this, outState);
|
||||
}
|
||||
|
||||
private void toggleOrientationChange(@Nullable SharedPreferences preferences) {
|
||||
preferences = preferences == null ? PreferenceManager.getDefaultSharedPreferences(this) : preferences;
|
||||
if (CalculatorPreferences.Gui.autoOrientation.getPreference(preferences)) {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
||||
} else {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* BUTTON HANDLERS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public void elementaryButtonClickHandler(@NotNull View v) {
|
||||
throw new UnsupportedOperationException("Not implemented yet!");
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public void historyButtonClickHandler(@NotNull View v) {
|
||||
buttonPressed(CalculatorSpecialButton.history);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public void eraseButtonClickHandler(@NotNull View v) {
|
||||
buttonPressed(CalculatorSpecialButton.erase);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public void simplifyButtonClickHandler(@NotNull View v) {
|
||||
throw new UnsupportedOperationException("Not implemented yet!");
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public void pasteButtonClickHandler(@NotNull View v) {
|
||||
buttonPressed(CalculatorSpecialButton.paste);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public void copyButtonClickHandler(@NotNull View v) {
|
||||
buttonPressed(CalculatorSpecialButton.copy);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static CalculatorKeyboard getKeyboard() {
|
||||
return Locator.getInstance().getKeyboard();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public void clearButtonClickHandler(@NotNull View v) {
|
||||
buttonPressed(CalculatorSpecialButton.clear);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public void digitButtonClickHandler(@NotNull View v) {
|
||||
Log.d(String.valueOf(v.getId()), "digitButtonClickHandler() for: " + v.getId() + ". Pressed: " + v.isPressed());
|
||||
|
||||
if (v instanceof Button) {
|
||||
buttonPressed(((Button)v).getText().toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void buttonPressed(@NotNull CalculatorSpecialButton button) {
|
||||
buttonPressed(button.getActionCode());
|
||||
}
|
||||
|
||||
private void buttonPressed(@NotNull String text) {
|
||||
getKeyboard().buttonPressed(text);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public void functionsButtonClickHandler(@NotNull View v) {
|
||||
buttonPressed(CalculatorSpecialButton.functions);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public void operatorsButtonClickHandler(@NotNull View v) {
|
||||
buttonPressed(CalculatorSpecialButton.operators);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public void varsButtonClickHandler(@NotNull View v) {
|
||||
buttonPressed(CalculatorSpecialButton.vars);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public void likeButtonClickHandler(@NotNull View v) {
|
||||
buttonPressed(CalculatorSpecialButton.like);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.View;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/25/12
|
||||
* Time: 10:31 PM
|
||||
*/
|
||||
public interface CalculatorActivityHelper {
|
||||
|
||||
void onCreate(@NotNull SherlockFragmentActivity activity, @Nullable Bundle savedInstanceState);
|
||||
void onCreate(@NotNull Activity activity, @Nullable Bundle savedInstanceState);
|
||||
|
||||
void onSaveInstanceState(@NotNull SherlockFragmentActivity activity, @NotNull Bundle outState);
|
||||
void onSaveInstanceState(@NotNull Activity activity, @NotNull Bundle outState);
|
||||
|
||||
int getLayoutId();
|
||||
|
||||
@NotNull
|
||||
CalculatorPreferences.Gui.Theme getTheme();
|
||||
|
||||
@NotNull
|
||||
CalculatorPreferences.Gui.Layout getLayout();
|
||||
|
||||
void onResume(@NotNull SherlockFragmentActivity activity);
|
||||
void onResume(@NotNull Activity activity);
|
||||
|
||||
void onPause(@NotNull Activity activity);
|
||||
void onPause(@NotNull SherlockFragmentActivity activity);
|
||||
|
||||
void onDestroy(@NotNull SherlockFragmentActivity activity);
|
||||
void onDestroy(@NotNull Activity activity);
|
||||
|
||||
void addTab(@NotNull SherlockFragmentActivity activity,
|
||||
@NotNull String tag,
|
||||
@NotNull Class<? extends Fragment> fragmentClass,
|
||||
@Nullable Bundle fragmentArgs,
|
||||
int captionResId,
|
||||
int parentViewId);
|
||||
|
||||
void addTab(@NotNull SherlockFragmentActivity activity,
|
||||
@NotNull CalculatorFragmentType fragmentType,
|
||||
@Nullable Bundle fragmentArgs,
|
||||
int parentViewId);
|
||||
|
||||
void setFragment(@NotNull SherlockFragmentActivity activity,
|
||||
@NotNull CalculatorFragmentType fragmentType,
|
||||
@Nullable Bundle fragmentArgs,
|
||||
int parentViewId);
|
||||
|
||||
|
||||
void logDebug(@NotNull String message);
|
||||
|
||||
void processButtons(@NotNull Activity activity, @NotNull View root);
|
||||
|
||||
void logError(@NotNull String message);
|
||||
}
|
@@ -0,0 +1,314 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import com.actionbarsherlock.app.ActionBar;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.AndroidUtils;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
import org.solovyev.android.sherlock.tabs.ActionBarFragmentTabListener;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/25/12
|
||||
* Time: 10:32 PM
|
||||
*/
|
||||
public class CalculatorActivityHelperImpl extends AbstractCalculatorHelper implements CalculatorActivityHelper {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTANTS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* FIELDS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private int layoutId;
|
||||
|
||||
private boolean homeIcon = false;
|
||||
|
||||
@NotNull
|
||||
private CalculatorPreferences.Gui.Theme theme;
|
||||
|
||||
@NotNull
|
||||
private CalculatorPreferences.Gui.Layout layout;
|
||||
|
||||
private int selectedNavigationIndex = 0;
|
||||
|
||||
public CalculatorActivityHelperImpl(int layoutId, @NotNull String logTag) {
|
||||
super(logTag);
|
||||
this.layoutId = layoutId;
|
||||
}
|
||||
|
||||
public CalculatorActivityHelperImpl(int layoutId, boolean homeIcon) {
|
||||
this.layoutId = layoutId;
|
||||
this.homeIcon = homeIcon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NotNull Activity activity, @Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(activity);
|
||||
|
||||
if (activity instanceof CalculatorEventListener) {
|
||||
Locator.getInstance().getCalculator().addCalculatorEventListener((CalculatorEventListener) activity);
|
||||
}
|
||||
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
|
||||
this.theme = CalculatorPreferences.Gui.getTheme(preferences);
|
||||
activity.setTheme(this.theme.getThemeId());
|
||||
|
||||
this.layout = CalculatorPreferences.Gui.getLayout(preferences);
|
||||
|
||||
activity.setContentView(layoutId);
|
||||
|
||||
final View root = activity.findViewById(R.id.main_layout);
|
||||
if (root != null) {
|
||||
processButtons(activity, root);
|
||||
addHelpInfo(activity, root);
|
||||
} else {
|
||||
Log.e(CalculatorActivityHelperImpl.class.getSimpleName(), "Root is null for " + activity.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NotNull final SherlockFragmentActivity activity, @Nullable Bundle savedInstanceState) {
|
||||
this.onCreate((Activity) activity, savedInstanceState);
|
||||
|
||||
final ActionBar actionBar = activity.getSupportActionBar();
|
||||
actionBar.setDisplayUseLogoEnabled(false);
|
||||
actionBar.setDisplayHomeAsUpEnabled(homeIcon);
|
||||
actionBar.setHomeButtonEnabled(false);
|
||||
actionBar.setDisplayShowHomeEnabled(true);
|
||||
|
||||
toggleTitle(activity, true);
|
||||
|
||||
actionBar.setIcon(R.drawable.ab_icon);
|
||||
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||
}
|
||||
|
||||
private void toggleTitle(@NotNull SherlockFragmentActivity activity, boolean showTitle) {
|
||||
final ActionBar actionBar = activity.getSupportActionBar();
|
||||
|
||||
if (activity instanceof CalculatorActivity) {
|
||||
if (AndroidUtils.getScreenOrientation(activity) == Configuration.ORIENTATION_PORTRAIT) {
|
||||
actionBar.setDisplayShowTitleEnabled(true);
|
||||
} else {
|
||||
actionBar.setDisplayShowTitleEnabled(false);
|
||||
}
|
||||
} else {
|
||||
actionBar.setDisplayShowTitleEnabled(showTitle);
|
||||
}
|
||||
}
|
||||
|
||||
public void restoreSavedTab(@NotNull SherlockFragmentActivity activity) {
|
||||
final ActionBar actionBar = activity.getSupportActionBar();
|
||||
if (selectedNavigationIndex >= 0 && selectedNavigationIndex < actionBar.getTabCount()) {
|
||||
actionBar.setSelectedNavigationItem(selectedNavigationIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NotNull SherlockFragmentActivity activity, @NotNull Bundle outState) {
|
||||
onSaveInstanceState((Activity) activity, outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NotNull Activity activity, @NotNull Bundle outState) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume(@NotNull Activity activity) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
|
||||
final CalculatorPreferences.Gui.Theme newTheme = CalculatorPreferences.Gui.theme.getPreference(preferences);
|
||||
if (!theme.equals(newTheme)) {
|
||||
AndroidUtils.restartActivity(activity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause(@NotNull Activity activity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause(@NotNull SherlockFragmentActivity activity) {
|
||||
onPause((Activity) activity);
|
||||
|
||||
final int selectedNavigationIndex = activity.getSupportActionBar().getSelectedNavigationIndex();
|
||||
if (selectedNavigationIndex >= 0) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
final SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putInt(getSavedTabPreferenceName(activity), selectedNavigationIndex);
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getSavedTabPreferenceName(@NotNull Activity activity) {
|
||||
return "tab_" + activity.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(@NotNull Activity activity) {
|
||||
super.onDestroy(activity);
|
||||
|
||||
if (activity instanceof CalculatorEventListener) {
|
||||
Locator.getInstance().getCalculator().removeCalculatorEventListener((CalculatorEventListener) activity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(@NotNull SherlockFragmentActivity activity) {
|
||||
this.onDestroy((Activity) activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTab(@NotNull SherlockFragmentActivity activity,
|
||||
@NotNull String tag,
|
||||
@NotNull Class<? extends Fragment> fragmentClass,
|
||||
@Nullable Bundle fragmentArgs,
|
||||
int captionResId,
|
||||
int parentViewId) {
|
||||
final ActionBar actionBar = activity.getSupportActionBar();
|
||||
|
||||
final ActionBar.Tab tab = actionBar.newTab();
|
||||
tab.setTag(tag);
|
||||
tab.setText(captionResId);
|
||||
|
||||
final ActionBarFragmentTabListener listener = new ActionBarFragmentTabListener(activity, tag, fragmentClass, fragmentArgs, parentViewId);
|
||||
tab.setTabListener(listener);
|
||||
actionBar.addTab(tab);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTab(@NotNull SherlockFragmentActivity activity, @NotNull CalculatorFragmentType fragmentType, @Nullable Bundle fragmentArgs, int parentViewId) {
|
||||
addTab(activity, fragmentType.getFragmentTag(), fragmentType.getFragmentClass(), fragmentArgs, fragmentType.getDefaultTitleResId(), parentViewId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFragment(@NotNull SherlockFragmentActivity activity, @NotNull CalculatorFragmentType fragmentType, @Nullable Bundle fragmentArgs, int parentViewId) {
|
||||
final FragmentManager fm = activity.getSupportFragmentManager();
|
||||
|
||||
Fragment fragment = fm.findFragmentByTag(fragmentType.getFragmentTag());
|
||||
if (fragment == null) {
|
||||
fragment = Fragment.instantiate(activity, fragmentType.getFragmentClass().getName(), fragmentArgs);
|
||||
final FragmentTransaction ft = fm.beginTransaction();
|
||||
ft.add(parentViewId, fragment, fragmentType.getFragmentTag());
|
||||
ft.commit();
|
||||
} else {
|
||||
if ( fragment.isDetached() ) {
|
||||
final FragmentTransaction ft = fm.beginTransaction();
|
||||
ft.attach(fragment);
|
||||
ft.commit();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLayoutId() {
|
||||
return layoutId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public CalculatorPreferences.Gui.Theme getTheme() {
|
||||
return theme;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public CalculatorPreferences.Gui.Layout getLayout() {
|
||||
return layout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume(@NotNull SherlockFragmentActivity activity) {
|
||||
onResume((Activity) activity);
|
||||
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
selectedNavigationIndex = preferences.getInt(getSavedTabPreferenceName(activity), -1);
|
||||
restoreSavedTab(activity);
|
||||
}
|
||||
|
||||
private void addHelpInfo(@NotNull Activity activity, @NotNull View root) {
|
||||
if ( CalculatorApplication.isMonkeyRunner(activity) ) {
|
||||
if ( root instanceof ViewGroup) {
|
||||
final TextView helperTextView = new TextView(activity);
|
||||
|
||||
final DisplayMetrics dm = new DisplayMetrics();
|
||||
activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
|
||||
|
||||
helperTextView.setTextSize(15);
|
||||
helperTextView.setTextColor(Color.WHITE);
|
||||
|
||||
final Configuration c = activity.getResources().getConfiguration();
|
||||
|
||||
final StringBuilder helpText = new StringBuilder();
|
||||
helpText.append("Size: ");
|
||||
if (AndroidUtils.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_XLARGE, c)) {
|
||||
helpText.append("xlarge");
|
||||
} else if (AndroidUtils.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE, c)) {
|
||||
helpText.append("large");
|
||||
} else if (AndroidUtils.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_NORMAL, c)) {
|
||||
helpText.append("normal");
|
||||
} else if (AndroidUtils.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_SMALL, c)) {
|
||||
helpText.append("small");
|
||||
} else {
|
||||
helpText.append("unknown");
|
||||
}
|
||||
|
||||
helpText.append(" (").append(dm.widthPixels).append("x").append(dm.heightPixels).append(")");
|
||||
|
||||
helpText.append(" Density: ");
|
||||
switch(dm.densityDpi){
|
||||
case DisplayMetrics.DENSITY_LOW:
|
||||
helpText.append("ldpi");
|
||||
break;
|
||||
case DisplayMetrics.DENSITY_MEDIUM:
|
||||
helpText.append("mdpi");
|
||||
break;
|
||||
case DisplayMetrics.DENSITY_HIGH:
|
||||
helpText.append("hdpi");
|
||||
break;
|
||||
case DisplayMetrics.DENSITY_XHIGH:
|
||||
helpText.append("xhdpi");
|
||||
break;
|
||||
case DisplayMetrics.DENSITY_TV:
|
||||
helpText.append("tv");
|
||||
break;
|
||||
}
|
||||
|
||||
helpText.append(" (").append(dm.densityDpi).append(")");
|
||||
|
||||
helperTextView.setText(helpText);
|
||||
|
||||
((ViewGroup) root).addView(helperTextView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,235 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
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;
|
||||
import org.solovyev.android.calculator.history.CalculatorHistoryActivity;
|
||||
import org.solovyev.android.calculator.math.edit.*;
|
||||
import org.solovyev.android.calculator.plot.CalculatorPlotActivity;
|
||||
import org.solovyev.android.calculator.plot.CalculatorPlotFragment;
|
||||
import org.solovyev.android.calculator.plot.PlotInput;
|
||||
import org.solovyev.common.msg.Message;
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/2/11
|
||||
* Time: 2:18 PM
|
||||
*/
|
||||
public final class CalculatorActivityLauncher implements CalculatorEventListener {
|
||||
|
||||
public CalculatorActivityLauncher() {
|
||||
}
|
||||
|
||||
public static void showHistory(@NotNull final Context context) {
|
||||
showHistory(context, false);
|
||||
}
|
||||
|
||||
public static void showHistory(@NotNull final Context context, boolean detached) {
|
||||
final Intent intent = new Intent(context, CalculatorHistoryActivity.class);
|
||||
addFlags(intent, detached);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
public static void showHelp(@NotNull final Context context) {
|
||||
context.startActivity(new Intent(context, CalculatorHelpActivity.class));
|
||||
}
|
||||
|
||||
public static void showSettings(@NotNull final Context context) {
|
||||
showSettings(context, false);
|
||||
}
|
||||
public static void showSettings(@NotNull final Context context, boolean detached) {
|
||||
final Intent intent = new Intent(context, CalculatorPreferencesActivity.class);
|
||||
addFlags(intent, detached);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
private static void addFlags(@NotNull Intent intent, boolean detached) {
|
||||
int flags = Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
|
||||
if (detached) {
|
||||
flags = flags | Intent.FLAG_ACTIVITY_NO_HISTORY;
|
||||
}
|
||||
|
||||
intent.setFlags(flags);
|
||||
|
||||
}
|
||||
|
||||
public static void showAbout(@NotNull final Context context) {
|
||||
context.startActivity(new Intent(context, CalculatorAboutActivity.class));
|
||||
}
|
||||
|
||||
public static void showFunctions(@NotNull final Context context) {
|
||||
showFunctions(context, false);
|
||||
}
|
||||
|
||||
public static void showFunctions(@NotNull final Context context, boolean detached) {
|
||||
final Intent intent = new Intent(context, CalculatorFunctionsActivity.class);
|
||||
addFlags(intent, detached);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
public static void showOperators(@NotNull final Context context) {
|
||||
showOperators(context, false);
|
||||
}
|
||||
|
||||
public static void showOperators(@NotNull final Context context, boolean detached) {
|
||||
final Intent intent = new Intent(context, CalculatorOperatorsActivity.class);
|
||||
addFlags(intent, detached);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
public static void showVars(@NotNull final Context context) {
|
||||
showVars(context, false);
|
||||
}
|
||||
|
||||
public static void showVars(@NotNull final Context context, boolean detached) {
|
||||
final Intent intent = new Intent(context, CalculatorVarsActivity.class);
|
||||
addFlags(intent, detached);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
public static void plotGraph(@NotNull final Context context, @NotNull Generic generic, @NotNull Constant constant){
|
||||
final Intent intent = new Intent();
|
||||
intent.putExtra(ChartFactory.TITLE, context.getString(R.string.c_graph));
|
||||
intent.putExtra(CalculatorPlotFragment.INPUT, new CalculatorPlotFragment.Input(generic.toString(), constant.getName()));
|
||||
intent.setClass(context, CalculatorPlotActivity.class);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
public static void createVar(@NotNull final Context context, @NotNull CalculatorDisplay calculatorDisplay) {
|
||||
final CalculatorDisplayViewState viewState = calculatorDisplay.getViewState();
|
||||
if (viewState.isValid() ) {
|
||||
final String varValue = viewState.getText();
|
||||
if (!StringUtils.isEmpty(varValue)) {
|
||||
if (CalculatorVarsFragment.isValidValue(varValue)) {
|
||||
if (context instanceof SherlockFragmentActivity) {
|
||||
VarEditDialogFragment.showDialog(VarEditDialogFragment.Input.newFromValue(varValue), ((SherlockFragmentActivity) context).getSupportFragmentManager());
|
||||
} else {
|
||||
final Intent intent = new Intent(context, CalculatorVarsActivity.class);
|
||||
intent.putExtra(CalculatorVarsFragment.CREATE_VAR_EXTRA_STRING, varValue);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
} else {
|
||||
Locator.getInstance().getNotifier().showMessage(R.string.c_value_is_not_a_number, MessageType.error);
|
||||
}
|
||||
} else {
|
||||
Locator.getInstance().getNotifier().showMessage(R.string.empty_var_error, MessageType.error);
|
||||
}
|
||||
} else {
|
||||
Locator.getInstance().getNotifier().showMessage(R.string.not_valid_result, MessageType.error);
|
||||
}
|
||||
}
|
||||
|
||||
public static void createFunction(@NotNull final Context context, @NotNull CalculatorDisplay calculatorDisplay) {
|
||||
final CalculatorDisplayViewState viewState = calculatorDisplay.getViewState();
|
||||
|
||||
if (viewState.isValid() ) {
|
||||
final String functionValue = viewState.getText();
|
||||
if (!StringUtils.isEmpty(functionValue)) {
|
||||
|
||||
FunctionEditDialogFragment.showDialog(FunctionEditDialogFragment.Input.newFromDisplay(viewState), context);
|
||||
|
||||
} else {
|
||||
Locator.getInstance().getNotifier().showMessage(R.string.empty_function_error, MessageType.error);
|
||||
}
|
||||
} else {
|
||||
Locator.getInstance().getNotifier().showMessage(R.string.not_valid_result, MessageType.error);
|
||||
}
|
||||
}
|
||||
|
||||
public static void openApp(@NotNull Context context) {
|
||||
final Intent intent = new Intent(context, CalculatorActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
public static void likeButtonPressed(@NotNull final Context context) {
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(CalculatorApplication.FACEBOOK_APP_URL));
|
||||
addFlags(intent, false);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
public static void showCalculationMessagesDialog(@NotNull Context context, @NotNull List<Message> messages) {
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
if ( CalculatorPreferences.Calculations.showCalculationMessagesDialog.getPreference(prefs) ) {
|
||||
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;
|
||||
case plot_graph:
|
||||
final PlotInput plotInput = (PlotInput) data;
|
||||
assert plotInput != null;
|
||||
App.getInstance().getUiThreadExecutor().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
plotGraph(App.getInstance().getApplication(), plotInput.getFunction(), plotInput.getConstant());
|
||||
}
|
||||
});
|
||||
break;
|
||||
case show_evaluation_error:
|
||||
final String errorMessage = (String) data;
|
||||
if (errorMessage != null) {
|
||||
App.getInstance().getUiThreadExecutor().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showEvaluationError(App.getInstance().getApplication(), errorMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void showEvaluationError(@NotNull Context context, @NotNull final String errorMessage) {
|
||||
final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
|
||||
|
||||
final View errorMessageView = layoutInflater.inflate(R.layout.display_error_message, null);
|
||||
((TextView) errorMessageView.findViewById(R.id.error_message_text_view)).setText(errorMessage);
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context)
|
||||
.setPositiveButton(R.string.c_cancel, null)
|
||||
.setView(errorMessageView);
|
||||
|
||||
builder.create().show();
|
||||
}
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/25/12
|
||||
* Time: 2:34 PM
|
||||
*/
|
||||
public class CalculatorActivityMobile extends CalculatorActivity {
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
CalculatorPreferences.Gui.layout.putPreference(prefs, CalculatorPreferences.Gui.Layout.main_calculator_mobile);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if ( !CalculatorApplication.isMonkeyRunner(this) ) {
|
||||
this.finish();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,181 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import net.robotmedia.billing.BillingController;
|
||||
import net.robotmedia.billing.helper.DefaultBillingObserver;
|
||||
import net.robotmedia.billing.model.BillingDB;
|
||||
import org.acra.ACRA;
|
||||
import org.acra.ReportingInteractionMode;
|
||||
import org.acra.annotation.ReportsCrashes;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.ads.AdsController;
|
||||
import org.solovyev.android.calculator.external.AndroidExternalListenersContainer;
|
||||
import org.solovyev.android.calculator.history.AndroidCalculatorHistory;
|
||||
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/1/11
|
||||
* Time: 1:21 PM
|
||||
*/
|
||||
/*@ReportsCrashes(formKey = "dEhDaW1nZU1qcFdsVUpiSnhON0c0ZHc6MQ",
|
||||
mode = ReportingInteractionMode.TOAST)*/
|
||||
@ReportsCrashes(formKey = "",
|
||||
mailTo = "se.solovyev+programming+calculatorpp+crashes+1.5@gmail.com",
|
||||
mode = ReportingInteractionMode.DIALOG,
|
||||
resToastText = R.string.crashed,
|
||||
resDialogTitle = R.string.crash_dialog_title,
|
||||
resDialogText = R.string.crash_dialog_text)
|
||||
public class CalculatorApplication extends android.app.Application {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTANTS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private static final String TAG = "Calculator++ Application";
|
||||
public static final String FACEBOOK_APP_URL = "http://www.facebook.com/calculatorpp";
|
||||
|
||||
public static final String AD_FREE_PRODUCT_ID = "ad_free";
|
||||
public static final String AD_FREE_P_KEY = "org.solovyev.android.calculator_ad_free";
|
||||
|
||||
public static final String ADMOB_USER_ID = "a14f02cf9c80cbc";
|
||||
|
||||
@NotNull
|
||||
private static CalculatorApplication instance;
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTRUCTORS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public CalculatorApplication() {
|
||||
instance = this;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* METHODS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
ACRA.init(this);
|
||||
|
||||
App.getInstance().init(this);
|
||||
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
CalculatorPreferences.setDefaultValues(preferences);
|
||||
|
||||
setTheme(preferences);
|
||||
|
||||
super.onCreate();
|
||||
|
||||
final AndroidCalculator calculator = new AndroidCalculator(this);
|
||||
|
||||
Locator.getInstance().init(calculator,
|
||||
new AndroidCalculatorEngine(this),
|
||||
new AndroidCalculatorClipboard(this),
|
||||
new AndroidCalculatorNotifier(this),
|
||||
new AndroidCalculatorHistory(this, calculator),
|
||||
new AndroidCalculatorLogger(),
|
||||
new AndroidCalculatorPreferenceService(this),
|
||||
new AndroidCalculatorKeyboard(this, new CalculatorKeyboardImpl(calculator)),
|
||||
new AndroidExternalListenersContainer(calculator));
|
||||
|
||||
Locator.getInstance().getCalculator().init();
|
||||
|
||||
BillingDB.init(CalculatorApplication.this);
|
||||
|
||||
AdsController.getInstance().init(ADMOB_USER_ID, AD_FREE_PRODUCT_ID, new BillingController.IConfiguration() {
|
||||
|
||||
@Override
|
||||
public byte[] getObfuscationSalt() {
|
||||
return new byte[]{81, -114, 32, -127, -32, -104, -40, -15, -47, 57, -13, -41, -33, 67, -114, 7, -11, 53, 126, 82};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPublicKey() {
|
||||
return CalculatorSecurity.getPK();
|
||||
}
|
||||
});
|
||||
|
||||
BillingController.registerObserver(new DefaultBillingObserver(this, null));
|
||||
|
||||
// init billing controller
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
BillingController.checkBillingSupported(CalculatorApplication.this);
|
||||
AdsController.getInstance().isAdFree(CalculatorApplication.this);
|
||||
|
||||
try {
|
||||
// prepare engine
|
||||
Locator.getInstance().getEngine().getMathEngine0().evaluate("1+1");
|
||||
Locator.getInstance().getEngine().getMathEngine0().evaluate("1*1");
|
||||
} catch (Throwable e) {
|
||||
Log.e(TAG, e.getMessage(), e);
|
||||
}
|
||||
|
||||
}
|
||||
}).start();
|
||||
|
||||
Locator.getInstance().getLogger().debug(TAG, "Application started!");
|
||||
Locator.getInstance().getNotifier().showDebugMessage(TAG, "Application started!");
|
||||
}
|
||||
|
||||
private void setTheme(@NotNull SharedPreferences preferences) {
|
||||
final CalculatorPreferences.Gui.Theme theme = CalculatorPreferences.Gui.getTheme(preferences);
|
||||
setTheme(theme.getThemeId());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CalculatorActivityHelper createActivityHelper(int layoutResId, @NotNull String logTag) {
|
||||
return new CalculatorActivityHelperImpl(layoutResId, logTag);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CalculatorFragmentHelper createFragmentHelper(int layoutId) {
|
||||
return new CalculatorFragmentHelperImpl(layoutId);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CalculatorFragmentHelper createFragmentHelper(int layoutId, int titleResId) {
|
||||
return new CalculatorFragmentHelperImpl(layoutId, titleResId);
|
||||
}
|
||||
@NotNull
|
||||
public CalculatorFragmentHelper createFragmentHelper(int layoutId, int titleResId, boolean listenersOnCreate) {
|
||||
return new CalculatorFragmentHelperImpl(layoutId, titleResId, listenersOnCreate);
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@NotNull
|
||||
public static CalculatorApplication getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static boolean isMonkeyRunner(@NotNull Context context) {
|
||||
// NOTE: this code is only for monkeyrunner
|
||||
return context.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD) == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import com.actionbarsherlock.app.SherlockFragment;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 25.09.12
|
||||
* Time: 12:03
|
||||
*/
|
||||
public class CalculatorDisplayFragment extends SherlockFragment {
|
||||
|
||||
@NotNull
|
||||
private CalculatorFragmentHelper fragmentHelper;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
|
||||
final CalculatorPreferences.Gui.Layout layout = CalculatorPreferences.Gui.getLayout(prefs);
|
||||
if (layout == CalculatorPreferences.Gui.Layout.main_calculator_mobile) {
|
||||
fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(R.layout.cpp_app_display_mobile, R.string.result);
|
||||
} else {
|
||||
fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(R.layout.cpp_app_display, R.string.result);
|
||||
}
|
||||
|
||||
fragmentHelper.onCreate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return fragmentHelper.onCreateView(this, inflater, container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View root, Bundle savedInstanceState) {
|
||||
super.onViewCreated(root, savedInstanceState);
|
||||
|
||||
((AndroidCalculator) Locator.getInstance().getCalculator()).setDisplay(getActivity());
|
||||
|
||||
fragmentHelper.onViewCreated(this, root);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
fragmentHelper.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
fragmentHelper.onPause(this);
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
fragmentHelper.onDestroy(this);
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
@@ -0,0 +1,122 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import com.actionbarsherlock.app.SherlockFragment;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.menu.ActivityMenu;
|
||||
import org.solovyev.android.menu.ListActivityMenu;
|
||||
import org.solovyev.android.sherlock.menu.SherlockMenuHelper;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 25.09.12
|
||||
* Time: 10:49
|
||||
*/
|
||||
public class CalculatorEditorFragment extends SherlockFragment {
|
||||
|
||||
@NotNull
|
||||
private CalculatorFragmentHelper fragmentHelper;
|
||||
|
||||
@NotNull
|
||||
private ActivityMenu<Menu, MenuItem> menu = ListActivityMenu.fromList(CalculatorMenu.class, SherlockMenuHelper.getInstance());
|
||||
|
||||
public CalculatorEditorFragment() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
fragmentHelper.onViewCreated(this, view);
|
||||
|
||||
((AndroidCalculator) Locator.getInstance().getCalculator()).setEditor(getActivity());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
|
||||
final CalculatorPreferences.Gui.Layout layout = CalculatorPreferences.Gui.getLayout(prefs);
|
||||
if (layout == CalculatorPreferences.Gui.Layout.main_calculator_mobile) {
|
||||
fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(R.layout.cpp_app_editor_mobile, R.string.editor);
|
||||
} else {
|
||||
fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(R.layout.cpp_app_editor, R.string.editor);
|
||||
}
|
||||
|
||||
fragmentHelper.onCreate(this);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return fragmentHelper.onCreateView(this, inflater, container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
this.fragmentHelper.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
this.fragmentHelper.onPause(this);
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
fragmentHelper.onDestroy(this);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* MENU
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
this.menu.onCreateOptionsMenu(this.getActivity(), menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
this.menu.onPrepareOptionsMenu(this.getActivity(), menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
return this.menu.onOptionsItemSelected(this.getActivity(), item);
|
||||
}
|
||||
}
|
@@ -0,0 +1,87 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.common.msg.Message;
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/17/12
|
||||
* Time: 6:54 PM
|
||||
*/
|
||||
public class CalculatorFixableMessage implements Parcelable {
|
||||
|
||||
public static final Creator<CalculatorFixableMessage> CREATOR = new Creator<CalculatorFixableMessage>() {
|
||||
@Override
|
||||
public CalculatorFixableMessage createFromParcel(@NotNull Parcel in) {
|
||||
return CalculatorFixableMessage.fromParcel(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalculatorFixableMessage[] newArray(int size) {
|
||||
return new CalculatorFixableMessage[size];
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
private static CalculatorFixableMessage fromParcel(@NotNull Parcel in) {
|
||||
final String message = in.readString();
|
||||
final MessageType messageType = (MessageType) in.readSerializable();
|
||||
final CalculatorFixableError fixableError = (CalculatorFixableError) in.readSerializable();
|
||||
|
||||
return new CalculatorFixableMessage(message, messageType, fixableError);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private final String message;
|
||||
|
||||
@NotNull
|
||||
private final MessageType messageType;
|
||||
|
||||
@Nullable
|
||||
private final CalculatorFixableError fixableError;
|
||||
|
||||
public CalculatorFixableMessage(@NotNull Message message) {
|
||||
this.message = message.getLocalizedMessage();
|
||||
this.messageType = message.getMessageType();
|
||||
this.fixableError = CalculatorFixableError.getErrorByMessageCode(message.getMessageCode());
|
||||
}
|
||||
|
||||
public CalculatorFixableMessage(@NotNull String message,
|
||||
@NotNull MessageType messageType,
|
||||
@Nullable CalculatorFixableError fixableError) {
|
||||
this.message = message;
|
||||
this.messageType = messageType;
|
||||
this.fixableError = fixableError;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NotNull Parcel out, int flags) {
|
||||
out.writeString(message);
|
||||
out.writeSerializable(messageType);
|
||||
out.writeSerializable(fixableError);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public MessageType getMessageType() {
|
||||
return messageType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CalculatorFixableError getFixableError() {
|
||||
return fixableError;
|
||||
}
|
||||
}
|
@@ -0,0 +1,87 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import com.actionbarsherlock.app.SherlockFragment;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 03.10.12
|
||||
* Time: 14:18
|
||||
*/
|
||||
public abstract class CalculatorFragment extends SherlockFragment {
|
||||
|
||||
@NotNull
|
||||
private final CalculatorFragmentHelper fragmentHelper;
|
||||
|
||||
protected CalculatorFragment(int layoutResId, int titleResId) {
|
||||
fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(layoutResId, titleResId);
|
||||
}
|
||||
|
||||
protected CalculatorFragment(@NotNull CalculatorFragmentType fragmentType) {
|
||||
fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(fragmentType.getDefaultLayoutId(), fragmentType.getDefaultTitleResId());
|
||||
}
|
||||
|
||||
protected CalculatorFragment(@NotNull CalculatorFragmentHelper fragmentHelper) {
|
||||
this.fragmentHelper = fragmentHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
fragmentHelper.onCreate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return fragmentHelper.onCreateView(this, inflater, container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
fragmentHelper.onViewCreated(this, view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
this.fragmentHelper.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
this.fragmentHelper.onPause(this);
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
fragmentHelper.onDestroy(this);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
}
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.os.Bundle;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 03.10.12
|
||||
* Time: 14:07
|
||||
*/
|
||||
public abstract class CalculatorFragmentActivity extends SherlockFragmentActivity {
|
||||
|
||||
@NotNull
|
||||
private final CalculatorActivityHelper activityHelper;
|
||||
|
||||
protected CalculatorFragmentActivity() {
|
||||
this(R.layout.main_empty);
|
||||
}
|
||||
|
||||
protected CalculatorFragmentActivity(int layoutResId) {
|
||||
this.activityHelper = CalculatorApplication.getInstance().createActivityHelper(layoutResId, getClass().getSimpleName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected CalculatorActivityHelper getActivityHelper() {
|
||||
return activityHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
activityHelper.onCreate(this, savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
activityHelper.onSaveInstanceState(this, outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
activityHelper.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
this.activityHelper.onPause(this);
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
activityHelper.onDestroy(this);
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/26/12
|
||||
* Time: 10:14 PM
|
||||
*/
|
||||
public interface CalculatorFragmentHelper {
|
||||
|
||||
boolean isPane(@NotNull Fragment fragment);
|
||||
|
||||
void setPaneTitle(@NotNull Fragment fragment, int titleResId);
|
||||
|
||||
void onCreate(@NotNull Fragment fragment);
|
||||
|
||||
@NotNull
|
||||
View onCreateView(@NotNull Fragment fragment, @NotNull LayoutInflater inflater, @Nullable ViewGroup container);
|
||||
|
||||
void onViewCreated(@NotNull Fragment fragment, @NotNull View root);
|
||||
|
||||
void onResume(@NotNull Fragment fragment);
|
||||
|
||||
void onPause(@NotNull Fragment fragment);
|
||||
|
||||
void onDestroy(@NotNull Fragment fragment);
|
||||
}
|
@@ -0,0 +1,131 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import com.google.ads.AdView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.ads.AdsController;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/26/12
|
||||
* Time: 10:14 PM
|
||||
*/
|
||||
public class CalculatorFragmentHelperImpl extends AbstractCalculatorHelper implements CalculatorFragmentHelper {
|
||||
|
||||
@Nullable
|
||||
private AdView adView;
|
||||
|
||||
private int layoutId;
|
||||
|
||||
private int titleResId = -1;
|
||||
|
||||
private boolean listenersOnCreate = true;
|
||||
|
||||
public CalculatorFragmentHelperImpl(int layoutId) {
|
||||
this.layoutId = layoutId;
|
||||
}
|
||||
|
||||
public CalculatorFragmentHelperImpl(int layoutId, int titleResId) {
|
||||
this.layoutId = layoutId;
|
||||
this.titleResId = titleResId;
|
||||
}
|
||||
|
||||
public CalculatorFragmentHelperImpl(int layoutId, int titleResId, boolean listenersOnCreate) {
|
||||
this.layoutId = layoutId;
|
||||
this.titleResId = titleResId;
|
||||
this.listenersOnCreate = listenersOnCreate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPane(@NotNull Fragment fragment) {
|
||||
return fragment.getActivity() instanceof CalculatorActivity;
|
||||
}
|
||||
|
||||
public void setPaneTitle(@NotNull Fragment fragment, int titleResId) {
|
||||
final TextView fragmentTitle = (TextView) fragment.getView().findViewById(R.id.fragment_title);
|
||||
if (fragmentTitle != null) {
|
||||
if (!isPane(fragment)) {
|
||||
fragmentTitle.setVisibility(View.GONE);
|
||||
} else {
|
||||
fragmentTitle.setText(fragment.getString(titleResId).toUpperCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NotNull Fragment fragment) {
|
||||
super.onCreate(fragment.getActivity());
|
||||
|
||||
if (listenersOnCreate) {
|
||||
if ( fragment instanceof CalculatorEventListener ) {
|
||||
Locator.getInstance().getCalculator().addCalculatorEventListener((CalculatorEventListener) fragment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume(@NotNull Fragment fragment) {
|
||||
if (!listenersOnCreate) {
|
||||
if ( fragment instanceof CalculatorEventListener ) {
|
||||
Locator.getInstance().getCalculator().addCalculatorEventListener((CalculatorEventListener) fragment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause(@NotNull Fragment fragment) {
|
||||
if (!listenersOnCreate) {
|
||||
if ( fragment instanceof CalculatorEventListener ) {
|
||||
Locator.getInstance().getCalculator().removeCalculatorEventListener((CalculatorEventListener) fragment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NotNull Fragment fragment, @NotNull View root) {
|
||||
final ViewGroup adParentView = (ViewGroup) root.findViewById(R.id.ad_parent_view);
|
||||
final ViewGroup mainFragmentLayout = (ViewGroup) root.findViewById(R.id.main_fragment_layout);
|
||||
|
||||
if (fragment instanceof CalculatorDisplayFragment || fragment instanceof CalculatorEditorFragment || fragment instanceof CalculatorKeyboardFragment) {
|
||||
// no ads in those fragments
|
||||
} else {
|
||||
if (adParentView != null) {
|
||||
adView = AdsController.getInstance().inflateAd(fragment.getActivity(), adParentView, R.id.ad_parent_view);
|
||||
} else if ( mainFragmentLayout != null ) {
|
||||
adView = AdsController.getInstance().inflateAd(fragment.getActivity(), mainFragmentLayout, R.id.main_fragment_layout);
|
||||
}
|
||||
}
|
||||
|
||||
processButtons(fragment.getActivity(), root);
|
||||
|
||||
if (titleResId >= 0) {
|
||||
this.setPaneTitle(fragment, titleResId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(@NotNull Fragment fragment) {
|
||||
super.onDestroy(fragment.getActivity());
|
||||
|
||||
if (listenersOnCreate) {
|
||||
if ( fragment instanceof CalculatorEventListener ) {
|
||||
Locator.getInstance().getCalculator().removeCalculatorEventListener((CalculatorEventListener) fragment);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.adView != null) {
|
||||
this.adView.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public View onCreateView(@NotNull Fragment fragment, @NotNull LayoutInflater inflater, @Nullable ViewGroup container) {
|
||||
return inflater.inflate(layoutId, container, false);
|
||||
}
|
||||
}
|
@@ -0,0 +1,147 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import com.actionbarsherlock.app.SherlockFragment;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 25.09.12
|
||||
* Time: 12:25
|
||||
*/
|
||||
public class CalculatorKeyboardFragment extends SherlockFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
@NotNull
|
||||
private CalculatorPreferences.Gui.Theme theme;
|
||||
|
||||
@NotNull
|
||||
private CalculatorFragmentHelper fragmentHelper;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
|
||||
|
||||
final CalculatorPreferences.Gui.Layout layout = CalculatorPreferences.Gui.getLayout(preferences);
|
||||
if (layout == CalculatorPreferences.Gui.Layout.main_calculator_mobile) {
|
||||
fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(R.layout.cpp_app_keyboard_mobile);
|
||||
} else {
|
||||
fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(R.layout.cpp_app_keyboard);
|
||||
}
|
||||
|
||||
fragmentHelper.onCreate(this);
|
||||
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
theme = CalculatorPreferences.Gui.theme.getPreferenceNoError(preferences);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return fragmentHelper.onCreateView(this, inflater, container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View root, Bundle savedInstanceState) {
|
||||
super.onViewCreated(root, savedInstanceState);
|
||||
|
||||
fragmentHelper.onViewCreated(this, root);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
this.fragmentHelper.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
this.fragmentHelper.onPause(this);
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
fragmentHelper.onDestroy(this);
|
||||
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
|
||||
preferences.unregisterOnSharedPreferenceChangeListener(this);
|
||||
|
||||
}
|
||||
|
||||
/* private static void setMarginsForView(@Nullable View view, int marginLeft, int marginBottom, @NotNull Context context) {
|
||||
// IMPORTANT: this is workaround for probably android bug
|
||||
// currently margin values set in styles are not applied for some reasons to the views (using include tag) => set them manually
|
||||
|
||||
if (view != null) {
|
||||
final DisplayMetrics dm = context.getResources().getDisplayMetrics();
|
||||
if (view.getLayoutParams() instanceof LinearLayout.LayoutParams) {
|
||||
final LinearLayout.LayoutParams oldParams = (LinearLayout.LayoutParams) view.getLayoutParams();
|
||||
final LinearLayout.LayoutParams newParams = new LinearLayout.LayoutParams(oldParams.width, oldParams.height, oldParams.weight);
|
||||
newParams.setMargins(AndroidUtils.toPixels(dm, marginLeft), 0, 0, AndroidUtils.toPixels(dm, marginBottom));
|
||||
view.setLayoutParams(newParams);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||
if (AndroidCalculatorEngine.Preferences.numeralBase.getKey().equals(key) ||
|
||||
CalculatorPreferences.Gui.hideNumeralBaseDigits.getKey().equals(key) ) {
|
||||
NumeralBaseButtons.toggleNumericDigits(this.getActivity(), preferences);
|
||||
}
|
||||
|
||||
if ( AndroidCalculatorEngine.Preferences.angleUnit.getKey().equals(key) ||
|
||||
AndroidCalculatorEngine.Preferences.numeralBase.getKey().equals(key) ) {
|
||||
View view = getView();
|
||||
if ( view != null) {
|
||||
// we should update state of angle units/numeral base button => we can achieve it by invalidating the whole view
|
||||
view.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
if ( CalculatorPreferences.Gui.showEqualsButton.getKey().equals(key) ) {
|
||||
CalculatorButtons.toggleEqualsButton(preferences, this.getActivity());
|
||||
}
|
||||
|
||||
if ( AndroidCalculatorEngine.Preferences.multiplicationSign.getKey().equals(key) ) {
|
||||
CalculatorButtons.initMultiplicationButton(getView());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private static AndroidCalculatorDisplayView getCalculatorDisplayView() {
|
||||
return (AndroidCalculatorDisplayView) Locator.getInstance().getDisplay().getView();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Calculator getCalculator() {
|
||||
return Locator.getInstance().getCalculator();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static CalculatorKeyboard getKeyboard() {
|
||||
return Locator.getInstance().getKeyboard();
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,75 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
|
||||
import org.solovyev.android.menu.LabeledMenuItem;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 4/23/12
|
||||
* Time: 2:25 PM
|
||||
*/
|
||||
enum CalculatorMenu implements LabeledMenuItem<MenuItem> {
|
||||
|
||||
settings(R.string.c_settings) {
|
||||
@Override
|
||||
public void onClick(@NotNull MenuItem data, @NotNull Context context) {
|
||||
CalculatorActivityLauncher.showSettings(context);
|
||||
}
|
||||
},
|
||||
|
||||
history(R.string.c_history) {
|
||||
@Override
|
||||
public void onClick(@NotNull MenuItem data, @NotNull Context context) {
|
||||
CalculatorActivityLauncher.showHistory(context);
|
||||
}
|
||||
},
|
||||
|
||||
about(R.string.c_about) {
|
||||
@Override
|
||||
public void onClick(@NotNull MenuItem data, @NotNull Context context) {
|
||||
CalculatorActivityLauncher.showAbout(context);
|
||||
}
|
||||
},
|
||||
|
||||
help(R.string.c_help) {
|
||||
@Override
|
||||
public void onClick(@NotNull MenuItem data, @NotNull Context context) {
|
||||
CalculatorActivityLauncher.showHelp(context);
|
||||
}
|
||||
},
|
||||
|
||||
conversion_tool(R.string.c_conversion_tool) {
|
||||
@Override
|
||||
public void onClick(@NotNull MenuItem data, @NotNull Context context) {
|
||||
new NumeralBaseConverterDialog(null).show(context);
|
||||
}
|
||||
},
|
||||
|
||||
exit(R.string.c_exit) {
|
||||
@Override
|
||||
public void onClick(@NotNull MenuItem data, @NotNull Context context) {
|
||||
if (context instanceof Activity) {
|
||||
((Activity) context).finish();
|
||||
} else {
|
||||
Log.e(CalculatorActivity.TAG, "Activity menu used with context");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final int captionResId;
|
||||
|
||||
private CalculatorMenu(int captionResId) {
|
||||
this.captionResId = captionResId;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getCaption(@NotNull Context context) {
|
||||
return context.getString(captionResId);
|
||||
}
|
||||
}
|
@@ -0,0 +1,229 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.TextView;
|
||||
import com.actionbarsherlock.app.SherlockActivity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.common.msg.Message;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/17/12
|
||||
* Time: 3:37 PM
|
||||
*/
|
||||
public class CalculatorMessagesDialog extends SherlockActivity {
|
||||
|
||||
private static final String INPUT = "input";
|
||||
|
||||
@NotNull
|
||||
private Input input = new Input(Collections.<CalculatorFixableMessage>emptyList());
|
||||
|
||||
public CalculatorMessagesDialog() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.calculator_messages_dialog);
|
||||
|
||||
final Intent intent = getIntent();
|
||||
if (intent != null) {
|
||||
parseIntent(intent);
|
||||
}
|
||||
|
||||
final CheckBox doNotShowCalculationMessagesCheckbox = (CheckBox) findViewById(R.id.do_not_show_calculation_messages_checkbox);
|
||||
|
||||
final Button closeButton = (Button) findViewById(R.id.close_button);
|
||||
closeButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (doNotShowCalculationMessagesCheckbox.isChecked()) {
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(CalculatorMessagesDialog.this);
|
||||
CalculatorPreferences.Calculations.showCalculationMessagesDialog.putPreference(prefs, false);
|
||||
}
|
||||
|
||||
CalculatorMessagesDialog.this.finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void parseIntent(@NotNull Intent intent) {
|
||||
final Input input = intent.getParcelableExtra(INPUT);
|
||||
if (input != null) {
|
||||
this.input = input;
|
||||
onInputChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void onInputChanged() {
|
||||
final ViewGroup viewGroup = (ViewGroup) findViewById(R.id.calculation_messages_container);
|
||||
viewGroup.removeAllViews();
|
||||
|
||||
final LayoutInflater layoutInflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
|
||||
final List<CalculatorFixableMessage> messages = input.getMessages();
|
||||
for (final CalculatorFixableMessage message : messages) {
|
||||
final View view = layoutInflater.inflate(R.layout.calculator_messages_dialog_message, null);
|
||||
|
||||
final TextView calculationMessagesTextView = (TextView) view.findViewById(R.id.calculation_messages_text_view);
|
||||
calculationMessagesTextView.setText(message.getMessage());
|
||||
|
||||
final Button fixButton = (Button) view.findViewById(R.id.fix_button);
|
||||
final CalculatorFixableError fixableError = message.getFixableError();
|
||||
if (fixableError == null) {
|
||||
fixButton.setVisibility(View.GONE);
|
||||
fixButton.setOnClickListener(null);
|
||||
} else {
|
||||
fixButton.setVisibility(View.VISIBLE);
|
||||
fixButton.setOnClickListener(new FixErrorOnClickListener(messages, message));
|
||||
}
|
||||
|
||||
viewGroup.addView(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(@NotNull Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
parseIntent(intent);
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public static void showDialogForMessages(@NotNull List<Message> messages, @NotNull Context context) {
|
||||
if (!messages.isEmpty()) {
|
||||
final Intent intent = new Intent(context, CalculatorMessagesDialog.class);
|
||||
|
||||
intent.putExtra(INPUT, Input.fromMessages(messages));
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
public static void showDialog(@NotNull List<CalculatorFixableMessage> messages, @NotNull Context context) {
|
||||
if (!messages.isEmpty()) {
|
||||
final Intent intent = new Intent(context, CalculatorMessagesDialog.class);
|
||||
|
||||
intent.putExtra(INPUT, new Input(messages));
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Input implements Parcelable {
|
||||
|
||||
public static final Creator<Input> CREATOR = new Creator<Input>() {
|
||||
@Override
|
||||
public Input createFromParcel(@NotNull Parcel in) {
|
||||
return Input.fromParcel(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Input[] newArray(int size) {
|
||||
return new Input[size];
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
private static Input fromParcel(@NotNull Parcel in) {
|
||||
final List<CalculatorFixableMessage> messages = new ArrayList<CalculatorFixableMessage>();
|
||||
in.readTypedList(messages, CalculatorFixableMessage.CREATOR);
|
||||
return new Input(messages);
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
private List<CalculatorFixableMessage> messages = new ArrayList<CalculatorFixableMessage>();
|
||||
|
||||
private Input(@NotNull List<CalculatorFixableMessage> messages) {
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<CalculatorFixableMessage> getMessages() {
|
||||
return messages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NotNull Parcel out, int flags) {
|
||||
out.writeTypedList(messages);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Input fromMessages(@NotNull List<Message> messages) {
|
||||
final List<CalculatorFixableMessage> stringMessages = new ArrayList<CalculatorFixableMessage>(messages.size());
|
||||
for (Message message : messages) {
|
||||
stringMessages.add(new CalculatorFixableMessage(message));
|
||||
}
|
||||
|
||||
return new Input(stringMessages);
|
||||
}
|
||||
}
|
||||
|
||||
private class FixErrorOnClickListener implements View.OnClickListener {
|
||||
|
||||
@NotNull
|
||||
private final List<CalculatorFixableMessage> messages;
|
||||
|
||||
@NotNull
|
||||
private final CalculatorFixableMessage currentMessage;
|
||||
|
||||
public FixErrorOnClickListener(@NotNull List<CalculatorFixableMessage> messages,
|
||||
@NotNull CalculatorFixableMessage message) {
|
||||
this.messages = messages;
|
||||
this.currentMessage = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final List<CalculatorFixableMessage> filteredMessages = new ArrayList<CalculatorFixableMessage>(messages.size() - 1);
|
||||
for (CalculatorFixableMessage message : messages) {
|
||||
if ( message.getFixableError() == null ) {
|
||||
filteredMessages.add(message);
|
||||
} else if ( message.getFixableError() != currentMessage.getFixableError() ) {
|
||||
filteredMessages.add(message);
|
||||
}
|
||||
}
|
||||
|
||||
currentMessage.getFixableError().fix();
|
||||
|
||||
if (!filteredMessages.isEmpty()) {
|
||||
CalculatorMessagesDialog.this.input = new Input(filteredMessages);
|
||||
onInputChanged();
|
||||
} else {
|
||||
CalculatorMessagesDialog.this.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* 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.app.AlertDialog;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
import com.actionbarsherlock.app.SherlockPreferenceActivity;
|
||||
import net.robotmedia.billing.BillingController;
|
||||
import net.robotmedia.billing.IBillingObserver;
|
||||
import net.robotmedia.billing.ResponseCode;
|
||||
import net.robotmedia.billing.helper.AbstractBillingObserver;
|
||||
import net.robotmedia.billing.model.Transaction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.AndroidUtils;
|
||||
import org.solovyev.android.ads.AdsController;
|
||||
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
|
||||
import org.solovyev.android.view.VibratorContainer;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 7/16/11
|
||||
* Time: 6:37 PM
|
||||
*/
|
||||
public class CalculatorPreferencesActivity extends SherlockPreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener, IBillingObserver {
|
||||
|
||||
public static final String CLEAR_BILLING_INFO = "clear_billing_info";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
//noinspection deprecation
|
||||
addPreferencesFromResource(R.xml.preferences);
|
||||
//noinspection deprecation
|
||||
addPreferencesFromResource(R.xml.preferences_calculations);
|
||||
addPreferencesFromResource(R.xml.preferences_appearance);
|
||||
addPreferencesFromResource(R.xml.preferences_plot);
|
||||
addPreferencesFromResource(R.xml.preferences_other);
|
||||
addPreferencesFromResource(R.xml.preferences_onscreen);
|
||||
|
||||
final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY);
|
||||
adFreePreference.setEnabled(false);
|
||||
|
||||
// observer must be set before net.robotmedia.billing.BillingController.checkBillingSupported()
|
||||
BillingController.registerObserver(this);
|
||||
|
||||
BillingController.checkBillingSupported(CalculatorPreferencesActivity.this);
|
||||
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
onSharedPreferenceChanged(preferences, AndroidCalculatorEngine.Preferences.roundResult.getKey());
|
||||
onSharedPreferenceChanged(preferences, VibratorContainer.Preferences.hapticFeedbackEnabled.getKey());
|
||||
|
||||
final Preference clearBillingInfoPreference = findPreference(CLEAR_BILLING_INFO);
|
||||
if (clearBillingInfoPreference != null) {
|
||||
clearBillingInfoPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
|
||||
Toast.makeText(CalculatorPreferencesActivity.this, R.string.c_calc_clearing, Toast.LENGTH_SHORT).show();
|
||||
|
||||
removeBillingInformation(CalculatorPreferencesActivity.this, PreferenceManager.getDefaultSharedPreferences(CalculatorPreferencesActivity.this));
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeBillingInformation(@NotNull Context context, @NotNull SharedPreferences preferences) {
|
||||
final SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putBoolean(AbstractBillingObserver.KEY_TRANSACTIONS_RESTORED, false);
|
||||
editor.commit();
|
||||
|
||||
BillingController.dropBillingData(context);
|
||||
}
|
||||
|
||||
private void setAdFreeAction() {
|
||||
final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY);
|
||||
|
||||
if (!AdsController.getInstance().isAdFree(this)) {
|
||||
Log.d(CalculatorPreferencesActivity.class.getName(), "Ad free is not purchased - enable preference!");
|
||||
|
||||
adFreePreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
|
||||
// check billing availability
|
||||
if (BillingController.checkBillingSupported(CalculatorPreferencesActivity.this) != BillingController.BillingStatus.SUPPORTED) {
|
||||
Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is not supported - warn user!");
|
||||
// warn about not supported billing
|
||||
new AlertDialog.Builder(CalculatorPreferencesActivity.this).setTitle(R.string.c_error).setMessage(R.string.c_billing_error).create().show();
|
||||
} else {
|
||||
Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is supported - continue!");
|
||||
if (!AdsController.getInstance().isAdFree(CalculatorPreferencesActivity.this)) {
|
||||
Log.d(CalculatorPreferencesActivity.class.getName(), "Item not purchased - try to purchase!");
|
||||
|
||||
// not purchased => purchasing
|
||||
Toast.makeText(CalculatorPreferencesActivity.this, R.string.c_calc_purchasing, Toast.LENGTH_SHORT).show();
|
||||
|
||||
// show purchase window for user
|
||||
BillingController.requestPurchase(CalculatorPreferencesActivity.this, CalculatorApplication.AD_FREE_PRODUCT_ID, true);
|
||||
} else {
|
||||
// disable preference
|
||||
adFreePreference.setEnabled(false);
|
||||
// and show message to user
|
||||
Toast.makeText(CalculatorPreferencesActivity.this, R.string.c_calc_already_purchased, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
adFreePreference.setEnabled(true);
|
||||
} else {
|
||||
Log.d(CalculatorPreferencesActivity.class.getName(), "Ad free is not purchased - disable preference!");
|
||||
adFreePreference.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
BillingController.unregisterObserver(this);
|
||||
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||
if (AndroidCalculatorEngine.Preferences.roundResult.getKey().equals(key)) {
|
||||
findPreference(AndroidCalculatorEngine.Preferences.precision.getKey()).setEnabled(preferences.getBoolean(key, AndroidCalculatorEngine.Preferences.roundResult.getDefaultValue()));
|
||||
} else if (VibratorContainer.Preferences.hapticFeedbackEnabled.getKey().equals(key)) {
|
||||
findPreference(VibratorContainer.Preferences.hapticFeedbackDuration.getKey()).setEnabled(VibratorContainer.Preferences.hapticFeedbackEnabled.getPreference(preferences));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCheckBillingSupportedResponse(boolean supported) {
|
||||
if (supported) {
|
||||
setAdFreeAction();
|
||||
} else {
|
||||
final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY);
|
||||
adFreePreference.setEnabled(false);
|
||||
Log.d(CalculatorPreferencesActivity.class.getName(), "Billing is not supported!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPurchaseIntentOK(@NotNull String productId, @NotNull PendingIntent purchaseIntent) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPurchaseIntentFailure(@NotNull String productId, @NotNull ResponseCode responseCode) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPurchaseStateChanged(@NotNull String itemId, @NotNull Transaction.PurchaseState state) {
|
||||
if (CalculatorApplication.AD_FREE_PRODUCT_ID.equals(itemId)) {
|
||||
final Preference adFreePreference = findPreference(CalculatorApplication.AD_FREE_P_KEY);
|
||||
if (adFreePreference != null) {
|
||||
switch (state) {
|
||||
case PURCHASED:
|
||||
adFreePreference.setEnabled(false);
|
||||
// restart activity to disable ads
|
||||
AndroidUtils.restartActivity(this);
|
||||
break;
|
||||
case CANCELLED:
|
||||
adFreePreference.setEnabled(true);
|
||||
break;
|
||||
case REFUNDED:
|
||||
adFreePreference.setEnabled(true);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPurchaseResponse(@NotNull String itemId, @NotNull ResponseCode response) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransactionsRestored() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onErrorRestoreTransactions(@NotNull ResponseCode responseCode) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2012. 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;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 1/4/12
|
||||
* Time: 1:23 AM
|
||||
*/
|
||||
public final class CalculatorSecurity {
|
||||
|
||||
private CalculatorSecurity() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getPK() {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
|
||||
result.append("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A");
|
||||
result.append("MIIBCgKCAQEAquP2a7dEhTaJEQeXtSyreH5dCmTDOd");
|
||||
result.append("dElCfg0ijOeB8JTxBiJTXLWnLA0kMaT/sRXswUaYI61YCQOoik82");
|
||||
result.append("qrFH7W4+OFtiLb8WGX+YPEpQQ/IBZu9qm3xzS9Nolu79EBff0/CLa1FuT9RtjO");
|
||||
result.append("iTW8Q0VP9meQdJEkfqJEyVCgHain+MGoQaRXI45EzkYmkz8TBx6X6aJF5NBAXnAWeyD0wPX1");
|
||||
result.append("uedHH7+LgLcjnPVw82YjyJSzYnaaD2GX0Y7PGoFe6J5K4yJGGX5mih45pe2HWcG5lAkQhu1uX2hCcCBdF3");
|
||||
result.append("W7paRq9mJvCsbn+BNTh9gq8QKui0ltmiWpa5U+/9L+FQIDAQAB");
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.common.JPredicate;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/3/11
|
||||
* Time: 12:54 AM
|
||||
*/
|
||||
public class CharacterAtPositionFinder implements JPredicate<Character> {
|
||||
|
||||
private int i;
|
||||
|
||||
@NotNull
|
||||
private final String targetString;
|
||||
|
||||
public CharacterAtPositionFinder(@NotNull String targetString, int i) {
|
||||
this.targetString = targetString;
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(@Nullable Character s) {
|
||||
return s != null && s.equals(targetString.charAt(i));
|
||||
}
|
||||
|
||||
public void setI(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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:45 PM
|
||||
*/
|
||||
public class CursorDragProcessor implements SimpleOnDragListener.DragProcessor{
|
||||
|
||||
public CursorDragProcessor() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
|
||||
boolean result = false;
|
||||
|
||||
if (dragButton instanceof DirectionDragButton) {
|
||||
String text = ((DirectionDragButton) dragButton).getText(dragDirection);
|
||||
if ("◀◀".equals(text)) {
|
||||
Locator.getInstance().getEditor().setCursorOnStart();
|
||||
result = true;
|
||||
} else if ("▶▶".equals(text)) {
|
||||
Locator.getInstance().getEditor().setCursorOnEnd();
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.view.MotionEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.view.drag.DragDirection;
|
||||
import org.solovyev.android.view.drag.SimpleOnDragListener;
|
||||
import org.solovyev.android.view.drag.DirectionDragButton;
|
||||
import org.solovyev.android.view.drag.DragButton;
|
||||
import org.solovyev.common.math.Point2d;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/24/11
|
||||
* Time: 9:52 PM
|
||||
*/
|
||||
public class EvalDragProcessor implements SimpleOnDragListener.DragProcessor {
|
||||
|
||||
public EvalDragProcessor() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
|
||||
boolean result = false;
|
||||
|
||||
if (dragButton instanceof DirectionDragButton) {
|
||||
String text = ((DirectionDragButton) dragButton).getText(dragDirection);
|
||||
if ("≡".equals(text)) {
|
||||
Locator.getInstance().getCalculator().simplify();
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.SharedPreferences;
|
||||
import jscl.NumeralBase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 4/20/12
|
||||
* Time: 5:03 PM
|
||||
*/
|
||||
public class NumeralBaseButtons {
|
||||
|
||||
public static void toggleNumericDigits(@NotNull Activity activity, @NotNull NumeralBase currentNumeralBase) {
|
||||
for (NumeralBase numeralBase : NumeralBase.values()) {
|
||||
if ( currentNumeralBase != numeralBase ) {
|
||||
AndroidNumeralBase.valueOf(numeralBase).toggleButtons(false, activity);
|
||||
}
|
||||
}
|
||||
|
||||
AndroidNumeralBase.valueOf(currentNumeralBase).toggleButtons(true, activity);
|
||||
}
|
||||
|
||||
public static void toggleNumericDigits(@NotNull Activity activity, @NotNull SharedPreferences preferences) {
|
||||
if (CalculatorPreferences.Gui.hideNumeralBaseDigits.getPreference(preferences)) {
|
||||
final NumeralBase nb = AndroidCalculatorEngine.Preferences.numeralBase.getPreference(preferences);
|
||||
toggleNumericDigits(activity, nb);
|
||||
} else {
|
||||
// set HEX to show all digits
|
||||
AndroidNumeralBase.valueOf(NumeralBase.hex).toggleButtons(true, activity);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||
* For more information, please, contact se.solovyev@gmail.com
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator.about;
|
||||
|
||||
import android.os.Bundle;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.CalculatorFragmentActivity;
|
||||
import org.solovyev.android.calculator.R;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/16/11
|
||||
* Time: 11:52 PM
|
||||
*/
|
||||
public class CalculatorAboutActivity extends CalculatorFragmentActivity {
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
getActivityHelper().addTab(this, CalculatorFragmentType.about, null, R.id.main_layout);
|
||||
getActivityHelper().addTab(this, CalculatorFragmentType.release_notes, null, R.id.main_layout);
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.about;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import org.solovyev.android.calculator.CalculatorFragment;
|
||||
import org.solovyev.android.calculator.R;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/24/11
|
||||
* Time: 11:55 PM
|
||||
*/
|
||||
public class CalculatorAboutFragment extends CalculatorFragment {
|
||||
|
||||
public CalculatorAboutFragment() {
|
||||
super(CalculatorFragmentType.about);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View root, Bundle savedInstanceState) {
|
||||
super.onViewCreated(root, savedInstanceState);
|
||||
|
||||
final TextView about = (TextView) root.findViewById(R.id.aboutTextView);
|
||||
about.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
package org.solovyev.android.calculator.about;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.CalculatorEditorFragment;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.calculator.help.CalculatorHelpFaqFragment;
|
||||
import org.solovyev.android.calculator.help.CalculatorHelpHintsFragment;
|
||||
import org.solovyev.android.calculator.help.CalculatorHelpScreensFragment;
|
||||
import org.solovyev.android.calculator.history.CalculatorHistoryFragment;
|
||||
import org.solovyev.android.calculator.history.CalculatorSavedHistoryFragment;
|
||||
import org.solovyev.android.calculator.math.edit.CalculatorFunctionsFragment;
|
||||
import org.solovyev.android.calculator.math.edit.CalculatorOperatorsFragment;
|
||||
import org.solovyev.android.calculator.math.edit.CalculatorVarsFragment;
|
||||
import org.solovyev.android.calculator.matrix.CalculatorMatrixEditFragment;
|
||||
import org.solovyev.android.calculator.plot.CalculatorPlotFragment;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 03.10.12
|
||||
* Time: 11:30
|
||||
*/
|
||||
public enum CalculatorFragmentType {
|
||||
|
||||
editor(CalculatorEditorFragment.class, R.layout.cpp_app_editor, R.string.editor),
|
||||
//display(CalculatorHistoryFragment.class, "history", R.layout.history_fragment, R.string.c_history),
|
||||
//keyboard(CalculatorHistoryFragment.class, "history", R.layout.history_fragment, R.string.c_history),
|
||||
history(CalculatorHistoryFragment.class, R.layout.history_fragment, R.string.c_history),
|
||||
saved_history(CalculatorSavedHistoryFragment.class, R.layout.history_fragment, R.string.c_saved_history),
|
||||
variables(CalculatorVarsFragment.class, R.layout.vars_fragment, R.string.c_vars),
|
||||
functions(CalculatorFunctionsFragment.class, R.layout.math_entities_fragment, R.string.c_functions),
|
||||
operators(CalculatorOperatorsFragment.class, R.layout.math_entities_fragment, R.string.c_operators),
|
||||
plotter(CalculatorPlotFragment.class, R.layout.plot_fragment, R.string.c_graph),
|
||||
about(CalculatorAboutFragment.class, R.layout.about_fragment, R.string.c_about),
|
||||
faq(CalculatorHelpFaqFragment.class, R.layout.help_faq_fragment, R.string.c_faq),
|
||||
hints(CalculatorHelpHintsFragment.class, R.layout.help_hints_fragment, R.string.c_hints),
|
||||
screens(CalculatorHelpScreensFragment.class, R.layout.help_screens_fragment, R.string.c_screens),
|
||||
|
||||
// todo serso: strings
|
||||
matrix_edit(CalculatorMatrixEditFragment.class, R.layout.matrix_edit_fragment, R.string.c_screens),
|
||||
release_notes(CalculatorReleaseNotesFragment.class, R.layout.release_notes_fragment, R.string.c_release_notes);
|
||||
|
||||
@NotNull
|
||||
private Class<? extends Fragment> fragmentClass;
|
||||
|
||||
private final int defaultLayoutId;
|
||||
|
||||
private int defaultTitleResId;
|
||||
|
||||
private CalculatorFragmentType(@NotNull Class<? extends Fragment> fragmentClass,
|
||||
int defaultLayoutId,
|
||||
int defaultTitleResId) {
|
||||
this.fragmentClass = fragmentClass;
|
||||
this.defaultLayoutId = defaultLayoutId;
|
||||
this.defaultTitleResId = defaultTitleResId;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getFragmentTag() {
|
||||
return this.name();
|
||||
}
|
||||
|
||||
public int getDefaultTitleResId() {
|
||||
return defaultTitleResId;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Class<? extends Fragment> getFragmentClass() {
|
||||
return fragmentClass;
|
||||
}
|
||||
|
||||
public int getDefaultLayoutId() {
|
||||
return defaultLayoutId;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String createSubFragmentTag(@NotNull String subFragmentTag) {
|
||||
return this.getFragmentTag() + "_" + subFragmentTag;
|
||||
}
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.about;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.text.Html;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.AndroidUtils;
|
||||
import org.solovyev.android.calculator.CalculatorApplication;
|
||||
import org.solovyev.android.calculator.CalculatorFragment;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/25/11
|
||||
* Time: 12:00 AM
|
||||
*/
|
||||
public class CalculatorReleaseNotesFragment extends CalculatorFragment {
|
||||
|
||||
public CalculatorReleaseNotesFragment() {
|
||||
super(CalculatorFragmentType.release_notes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View root, Bundle savedInstanceState) {
|
||||
super.onViewCreated(root, savedInstanceState);
|
||||
|
||||
final TextView releaseNotes = (TextView) root.findViewById(R.id.releaseNotesTextView);
|
||||
releaseNotes.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
|
||||
releaseNotes.setText(Html.fromHtml(getReleaseNotes(this.getActivity())));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getReleaseNotes(@NotNull Context context) {
|
||||
return getReleaseNotes(context, 0);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getReleaseNotes(@NotNull Context context, int minVersion) {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
|
||||
final String releaseNotesForTitle = context.getString(R.string.c_release_notes_for_title);
|
||||
final int version = AndroidUtils.getAppVersionCode(context, CalculatorApplication.class.getPackage().getName());
|
||||
|
||||
final TextHelper textHelper = new TextHelper(context.getResources(), CalculatorApplication.class.getPackage().getName());
|
||||
|
||||
boolean first = true;
|
||||
for ( int i = version; i >= minVersion; i-- ) {
|
||||
String releaseNotesForVersion = textHelper.getText("c_release_notes_for_" + i);
|
||||
if (!StringUtils.isEmpty(releaseNotesForVersion)){
|
||||
assert releaseNotesForVersion != null;
|
||||
if ( !first ) {
|
||||
result.append("<br/><br/>");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
releaseNotesForVersion = releaseNotesForVersion.replace("\n", "<br/>");
|
||||
result.append("<b>").append(releaseNotesForTitle).append(i).append("</b><br/><br/>");
|
||||
result.append(releaseNotesForVersion);
|
||||
}
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package org.solovyev.android.calculator.about;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.util.Log;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 4/20/12
|
||||
* Time: 3:31 PM
|
||||
*/
|
||||
public class TextHelper {
|
||||
|
||||
@NotNull
|
||||
public String packageName;
|
||||
|
||||
@NotNull
|
||||
public Resources resources;
|
||||
|
||||
public TextHelper(@NotNull Resources resources, @NotNull String packageName) {
|
||||
this.packageName = packageName;
|
||||
this.resources = resources;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getText(@NotNull String stringName) {
|
||||
final int stringId = this.resources.getIdentifier(stringName, "string", this.packageName);
|
||||
try {
|
||||
return resources.getString(stringId);
|
||||
} catch (Resources.NotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,327 @@
|
||||
package org.solovyev.android.calculator.function;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import jscl.math.Generic;
|
||||
import jscl.math.function.Constant;
|
||||
import jscl.math.function.CustomFunction;
|
||||
import jscl.math.function.Function;
|
||||
import jscl.math.function.IFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.math.edit.CalculatorFunctionsActivity;
|
||||
import org.solovyev.android.calculator.math.edit.CalculatorFunctionsFragment;
|
||||
import org.solovyev.android.calculator.math.edit.MathEntityRemover;
|
||||
import org.solovyev.android.calculator.model.AFunction;
|
||||
import org.solovyev.android.sherlock.AndroidSherlockUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/13/12
|
||||
* Time: 11:34 PM
|
||||
*/
|
||||
public class FunctionEditDialogFragment extends DialogFragment implements CalculatorEventListener {
|
||||
|
||||
private static final String INPUT = "input";
|
||||
|
||||
@NotNull
|
||||
private Input input;
|
||||
|
||||
public FunctionEditDialogFragment() {
|
||||
this(Input.newInstance());
|
||||
}
|
||||
|
||||
public FunctionEditDialogFragment(@NotNull Input input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
final View result = inflater.inflate(R.layout.function_edit, container, false);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
final Parcelable input = savedInstanceState.getParcelable(INPUT);
|
||||
if ( input instanceof Input ) {
|
||||
this.input = (Input)input;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NotNull View root, Bundle savedInstanceState) {
|
||||
super.onViewCreated(root, savedInstanceState);
|
||||
|
||||
final FunctionParamsView paramsView = (FunctionParamsView) root.findViewById(R.id.function_params_layout);
|
||||
|
||||
final AFunction.Builder builder;
|
||||
final AFunction function = input.getFunction();
|
||||
if (function != null) {
|
||||
builder = new AFunction.Builder(function);
|
||||
} else {
|
||||
builder = new AFunction.Builder();
|
||||
}
|
||||
|
||||
final List<String> parameterNames = input.getParameterNames();
|
||||
if (parameterNames != null) {
|
||||
paramsView.init(parameterNames);
|
||||
} else {
|
||||
paramsView.init();
|
||||
}
|
||||
|
||||
final EditText editName = (EditText) root.findViewById(R.id.function_edit_name);
|
||||
// show soft keyboard automatically
|
||||
editName.requestFocus();
|
||||
editName.setText(input.getName());
|
||||
|
||||
final EditText editDescription = (EditText) root.findViewById(R.id.function_edit_description);
|
||||
editDescription.setText(input.getDescription());
|
||||
|
||||
final EditText editContent = (EditText) root.findViewById(R.id.function_edit_value);
|
||||
editContent.setText(input.getContent());
|
||||
|
||||
root.findViewById(R.id.cancel_button).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
root.findViewById(R.id.save_button).setOnClickListener(new FunctionEditorSaver(builder, function, root, Locator.getInstance().getEngine().getFunctionsRegistry(), this));
|
||||
|
||||
if ( function == null ) {
|
||||
// CREATE MODE
|
||||
getDialog().setTitle(R.string.function_create_function);
|
||||
|
||||
root.findViewById(R.id.remove_button).setVisibility(View.GONE);
|
||||
} else {
|
||||
// EDIT MODE
|
||||
getDialog().setTitle(R.string.function_edit_function);
|
||||
|
||||
final Function customFunction = new CustomFunction.Builder(function).create();
|
||||
root.findViewById(R.id.remove_button).setOnClickListener(MathEntityRemover.newFunctionRemover(customFunction, null, this.getActivity(), FunctionEditDialogFragment.this));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(@NotNull Bundle out) {
|
||||
super.onSaveInstanceState(out);
|
||||
|
||||
out.putParcelable(INPUT, FunctionEditorSaver.readInput(input.getFunction(), getView()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
Locator.getInstance().getCalculator().addCalculatorEventListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
Locator.getInstance().getCalculator().removeCalculatorEventListener(this);
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
switch (calculatorEventType) {
|
||||
case function_removed:
|
||||
case function_added:
|
||||
case function_changed:
|
||||
if ( calculatorEventData.getSource() == FunctionEditDialogFragment.this ) {
|
||||
dismiss();
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public static void showDialog(@NotNull Input input, @NotNull Context context) {
|
||||
if (context instanceof SherlockFragmentActivity) {
|
||||
FunctionEditDialogFragment.showDialog(input, ((SherlockFragmentActivity) context).getSupportFragmentManager());
|
||||
} else {
|
||||
final Intent intent = new Intent(context, CalculatorFunctionsActivity.class);
|
||||
intent.putExtra(CalculatorFunctionsFragment.CREATE_FUNCTION_EXTRA, input);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
public static void showDialog(@NotNull Input input, @NotNull FragmentManager fm) {
|
||||
AndroidSherlockUtils.showDialog(new FunctionEditDialogFragment(input), "function-editor", fm);
|
||||
}
|
||||
|
||||
public static class Input implements Parcelable {
|
||||
|
||||
public static final Parcelable.Creator<Input> CREATOR = new Creator<Input>() {
|
||||
@Override
|
||||
public Input createFromParcel(@NotNull Parcel in) {
|
||||
return Input.fromParcel(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Input[] newArray(int size) {
|
||||
return new Input[size];
|
||||
}
|
||||
};
|
||||
|
||||
private static final Parcelable.Creator<String> STRING_CREATOR = new Creator<String>() {
|
||||
@Override
|
||||
public String createFromParcel(@NotNull Parcel in) {
|
||||
return in.readString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] newArray(int size) {
|
||||
return new String[size];
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
private static Input fromParcel(@NotNull Parcel in) {
|
||||
final Input result = new Input();
|
||||
result.name = in.readString();
|
||||
result.content = in.readString();
|
||||
result.description = in.readString();
|
||||
|
||||
final List<String> parameterNames = new ArrayList<String>();
|
||||
in.readTypedList(parameterNames, STRING_CREATOR);
|
||||
result.parameterNames = parameterNames;
|
||||
|
||||
result.function = (AFunction) in.readSerializable();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private AFunction function;
|
||||
|
||||
@Nullable
|
||||
private String name;
|
||||
|
||||
@Nullable
|
||||
private String content;
|
||||
|
||||
@Nullable
|
||||
private String description;
|
||||
|
||||
@Nullable
|
||||
private List<String> parameterNames;
|
||||
|
||||
private Input() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Input newInstance() {
|
||||
return new Input();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Input newFromFunction(@NotNull IFunction function) {
|
||||
final Input result = new Input();
|
||||
result.function = AFunction.fromIFunction(function);
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Input newInstance(@Nullable IFunction function,
|
||||
@Nullable String name,
|
||||
@Nullable String value,
|
||||
@Nullable String description,
|
||||
@NotNull List<String> parameterNames) {
|
||||
|
||||
final Input result = new Input();
|
||||
if (function != null) {
|
||||
result.function = AFunction.fromIFunction(function);
|
||||
}
|
||||
result.name = name;
|
||||
result.content = value;
|
||||
result.description = description;
|
||||
result.parameterNames = new ArrayList<String>(parameterNames);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AFunction getFunction() {
|
||||
return function;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getName() {
|
||||
return name == null ? (function == null ? null : function.getName()) : name;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getContent() {
|
||||
return content == null ? (function == null ? null : function.getContent()) : content;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getDescription() {
|
||||
return description == null ? (function == null ? null : function.getDescription()) : description;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<String> getParameterNames() {
|
||||
return parameterNames == null ? (function == null ? null : function.getParameterNames()) : parameterNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NotNull Parcel out, int flags) {
|
||||
out.writeString(name);
|
||||
out.writeString(content);
|
||||
out.writeString(description);
|
||||
out.writeList(parameterNames);
|
||||
out.writeSerializable(function);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Input newFromDisplay(@NotNull CalculatorDisplayViewState viewState) {
|
||||
final Input result = new Input();
|
||||
|
||||
result.content = viewState.getText();
|
||||
final Generic generic = viewState.getResult();
|
||||
if ( generic != null ) {
|
||||
final Set<Constant> constants = CalculatorUtils.getNotSystemConstants(generic);
|
||||
final List<String> parameterNames = new ArrayList<String>(constants.size());
|
||||
for (Constant constant : constants) {
|
||||
parameterNames.add(constant.getName());
|
||||
}
|
||||
result.parameterNames = parameterNames;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,180 @@
|
||||
package org.solovyev.android.calculator.function;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import jscl.CustomFunctionCalculationException;
|
||||
import jscl.math.function.CustomFunction;
|
||||
import jscl.math.function.Function;
|
||||
import jscl.math.function.IFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.Locator;
|
||||
import org.solovyev.android.calculator.CalculatorFunctionsMathRegistry;
|
||||
import org.solovyev.android.calculator.CalculatorMathRegistry;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.calculator.math.edit.VarEditorSaver;
|
||||
import org.solovyev.android.calculator.model.AFunction;
|
||||
import org.solovyev.android.calculator.model.MathEntityBuilder;
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class FunctionEditorSaver implements View.OnClickListener {
|
||||
|
||||
@NotNull
|
||||
private final Object source;
|
||||
|
||||
@NotNull
|
||||
private final AFunction.Builder builder;
|
||||
|
||||
@Nullable
|
||||
private final IFunction editedInstance;
|
||||
|
||||
@NotNull
|
||||
private final View view;
|
||||
|
||||
@NotNull
|
||||
private final CalculatorMathRegistry<Function> mathRegistry;
|
||||
|
||||
|
||||
public FunctionEditorSaver(@NotNull AFunction.Builder builder,
|
||||
@Nullable IFunction editedInstance,
|
||||
@NotNull View view,
|
||||
@NotNull CalculatorMathRegistry<Function> registry,
|
||||
@NotNull Object source) {
|
||||
|
||||
this.builder = builder;
|
||||
this.editedInstance = editedInstance;
|
||||
this.view = view;
|
||||
this.mathRegistry = registry;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final Integer error;
|
||||
|
||||
final FunctionEditDialogFragment.Input input = readInput(null, view);
|
||||
|
||||
final String name = input.getName();
|
||||
final String content = input.getContent();
|
||||
final String description = input.getDescription();
|
||||
|
||||
List<String> parameterNames = input.getParameterNames();
|
||||
if ( parameterNames == null ) {
|
||||
parameterNames = Collections.emptyList();
|
||||
}
|
||||
|
||||
if (VarEditorSaver.isValidName(name)) {
|
||||
|
||||
boolean canBeSaved = false;
|
||||
|
||||
final Function entityFromRegistry = mathRegistry.get(name);
|
||||
if (entityFromRegistry == null) {
|
||||
canBeSaved = true;
|
||||
} else if (editedInstance != null && entityFromRegistry.getId().equals(editedInstance.getId())) {
|
||||
canBeSaved = true;
|
||||
}
|
||||
|
||||
if (canBeSaved) {
|
||||
if (validateParameters(parameterNames)) {
|
||||
|
||||
if (!StringUtils.isEmpty(content)) {
|
||||
builder.setParameterNames(parameterNames);
|
||||
builder.setName(name);
|
||||
builder.setDescription(description);
|
||||
builder.setValue(content);
|
||||
error = null;
|
||||
} else {
|
||||
error = R.string.function_is_empty;
|
||||
}
|
||||
} else {
|
||||
error = R.string.function_param_not_empty;
|
||||
}
|
||||
} else {
|
||||
error = R.string.function_already_exists;
|
||||
}
|
||||
} else {
|
||||
error = R.string.function_name_is_not_valid;
|
||||
}
|
||||
|
||||
if (error != null) {
|
||||
Locator.getInstance().getNotifier().showMessage(error, MessageType.error);
|
||||
} else {
|
||||
try {
|
||||
CalculatorFunctionsMathRegistry.saveFunction(mathRegistry, new BuilderAdapter(builder), editedInstance, source, true);
|
||||
} catch (CustomFunctionCalculationException e) {
|
||||
Locator.getInstance().getNotifier().showMessage(e);
|
||||
} catch (AFunction.Builder.CreationException e) {
|
||||
Locator.getInstance().getNotifier().showMessage(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static FunctionEditDialogFragment.Input readInput(@Nullable IFunction function, @NotNull View root) {
|
||||
final EditText editName = (EditText) root.findViewById(R.id.function_edit_name);
|
||||
String name = editName.getText().toString();
|
||||
|
||||
final EditText editValue = (EditText) root.findViewById(R.id.function_edit_value);
|
||||
String content = editValue.getText().toString();
|
||||
|
||||
final EditText editDescription = (EditText) root.findViewById(R.id.function_edit_description);
|
||||
String description = editDescription.getText().toString();
|
||||
|
||||
final FunctionParamsView editParams = (FunctionParamsView) root.findViewById(R.id.function_params_layout);
|
||||
List<String> parameterNames = editParams.getParameterNames();
|
||||
|
||||
return FunctionEditDialogFragment.Input.newInstance(function, name, content, description, parameterNames);
|
||||
}
|
||||
|
||||
private boolean validateParameters(@NotNull List<String> parameterNames) {
|
||||
for (String parameterName : parameterNames) {
|
||||
if ( !VarEditorSaver.isValidName(parameterName) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final class BuilderAdapter implements MathEntityBuilder<Function> {
|
||||
|
||||
@NotNull
|
||||
private final AFunction.Builder nestedBuilder;
|
||||
|
||||
public BuilderAdapter(@NotNull AFunction.Builder nestedBuilder) {
|
||||
this.nestedBuilder = nestedBuilder;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public MathEntityBuilder<Function> setName(@NotNull String name) {
|
||||
nestedBuilder.setName(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public MathEntityBuilder<Function> setDescription(@Nullable String description) {
|
||||
nestedBuilder.setDescription(description);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public MathEntityBuilder<Function> setValue(@Nullable String value) {
|
||||
nestedBuilder.setValue(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Function create() {
|
||||
final AFunction function = nestedBuilder.create();
|
||||
return new CustomFunction.Builder(function).create();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
package org.solovyev.android.calculator.function;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcelable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.AbsSavedState;
|
||||
import android.widget.EditText;
|
||||
|
||||
public class FunctionParamEditText extends EditText {
|
||||
|
||||
public FunctionParamEditText(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public FunctionParamEditText(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public FunctionParamEditText(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
// we restore state manually outside
|
||||
@Override
|
||||
public Parcelable onSaveInstanceState() {
|
||||
super.onSaveInstanceState();
|
||||
return AbsSavedState.EMPTY_STATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestoreInstanceState(Parcelable state) {
|
||||
super.onRestoreInstanceState(null);
|
||||
}
|
||||
}
|
@@ -0,0 +1,189 @@
|
||||
package org.solovyev.android.calculator.function;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import jscl.text.MutableInt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class FunctionParamsView extends LinearLayout {
|
||||
|
||||
@NotNull
|
||||
private final MutableInt paramsCount = new MutableInt(0);
|
||||
|
||||
@NotNull
|
||||
private final List<Integer> paramIds = new ArrayList<Integer>(10);
|
||||
|
||||
private static final String PARAM_TAG_PREFIX = "function_param_";
|
||||
|
||||
public FunctionParamsView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public FunctionParamsView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public FunctionParamsView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public void init() {
|
||||
init(Collections.<String>emptyList());
|
||||
}
|
||||
|
||||
public void init(@NotNull List<String> parameters) {
|
||||
this.setOrientation(VERTICAL);
|
||||
|
||||
final LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
|
||||
final View addParamView = inflater.inflate(R.layout.function_add_param, null);
|
||||
|
||||
final View addParamButton = addParamView.findViewById(R.id.function_add_param_button);
|
||||
|
||||
addParamButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
addParam(null);
|
||||
}
|
||||
});
|
||||
|
||||
this.addView(addParamView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
for (String parameter : parameters) {
|
||||
addParam(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
public void addParam(@Nullable String name) {
|
||||
synchronized (paramsCount) {
|
||||
final LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
|
||||
final Integer id = paramsCount.intValue();
|
||||
|
||||
final View editParamView = inflater.inflate(R.layout.function_edit_param, null);
|
||||
|
||||
editParamView.setTag(getParamTag(id));
|
||||
|
||||
final EditText paramNameEditText = (EditText) editParamView.findViewById(R.id.function_param_edit_text);
|
||||
paramNameEditText.setText(name);
|
||||
|
||||
final View removeParamButton = editParamView.findViewById(R.id.function_remove_param_button);
|
||||
removeParamButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
removeParam(id);
|
||||
}
|
||||
});
|
||||
|
||||
final View upParamButton = editParamView.findViewById(R.id.function_up_param_button);
|
||||
upParamButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
upParam(id);
|
||||
}
|
||||
});
|
||||
|
||||
final View downParamButton = editParamView.findViewById(R.id.function_down_param_button);
|
||||
downParamButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
downParam(id);
|
||||
}
|
||||
});
|
||||
|
||||
this.addView(editParamView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
paramIds.add(id);
|
||||
paramsCount.increment();
|
||||
}
|
||||
}
|
||||
|
||||
private void downParam(@NotNull Integer id) {
|
||||
synchronized (paramsCount) {
|
||||
int index = paramIds.indexOf(id);
|
||||
if (index < paramIds.size() - 1) {
|
||||
swap(index, index + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void upParam(@NotNull Integer id) {
|
||||
synchronized (paramsCount) {
|
||||
int index = paramIds.indexOf(id);
|
||||
if (index > 0) {
|
||||
swap(index, index - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void swap(int index1, int index2) {
|
||||
final View editParamView1 = getParamView(paramIds.get(index1));
|
||||
final View editParamView2 = getParamView(paramIds.get(index2));
|
||||
|
||||
if (editParamView1 != null && editParamView2 != null) {
|
||||
final EditText paramNameEditText1 = (EditText) editParamView1.findViewById(R.id.function_param_edit_text);
|
||||
final EditText paramNameEditText2 = (EditText) editParamView2.findViewById(R.id.function_param_edit_text);
|
||||
swap(paramNameEditText1, paramNameEditText2);
|
||||
}
|
||||
}
|
||||
|
||||
private void swap(@NotNull TextView first,
|
||||
@NotNull TextView second) {
|
||||
final CharSequence tmp = first.getText();
|
||||
first.setText(second.getText());
|
||||
second.setText(tmp);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private View getParamView(@NotNull Integer id) {
|
||||
final String tag = getParamTag(id);
|
||||
return this.findViewWithTag(tag);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getParamTag(@NotNull Integer index) {
|
||||
return PARAM_TAG_PREFIX + index;
|
||||
}
|
||||
|
||||
public void removeParam(@NotNull Integer id) {
|
||||
synchronized (paramsCount) {
|
||||
if (paramIds.contains(id)) {
|
||||
final View editParamView = getParamView(id);
|
||||
if (editParamView != null) {
|
||||
this.removeView(editParamView);
|
||||
paramIds.remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<String> getParameterNames() {
|
||||
synchronized (paramsCount) {
|
||||
final List<String> result = new ArrayList<String>(paramsCount.intValue());
|
||||
|
||||
for (Integer id : paramIds) {
|
||||
final View paramView = getParamView(id);
|
||||
if ( paramView != null ) {
|
||||
final EditText paramNameEditText = (EditText) paramView.findViewById(R.id.function_param_edit_text);
|
||||
result.add(paramNameEditText.getText().toString());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.help;
|
||||
|
||||
import android.os.Bundle;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.CalculatorFragmentActivity;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/19/11
|
||||
* Time: 11:35 AM
|
||||
*/
|
||||
public class CalculatorHelpActivity extends CalculatorFragmentActivity {
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
getActivityHelper().addTab(this, CalculatorFragmentType.faq, null, R.id.main_layout);
|
||||
getActivityHelper().addTab(this, CalculatorFragmentType.hints, null, R.id.main_layout);
|
||||
getActivityHelper().addTab(this, CalculatorFragmentType.screens, null, R.id.main_layout);
|
||||
}
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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.help;
|
||||
|
||||
import org.solovyev.android.calculator.CalculatorFragment;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/19/11
|
||||
* Time: 11:37 AM
|
||||
*/
|
||||
public class CalculatorHelpFaqFragment extends CalculatorFragment {
|
||||
|
||||
public CalculatorHelpFaqFragment() {
|
||||
super(CalculatorFragmentType.faq);
|
||||
}
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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.help;
|
||||
|
||||
import org.solovyev.android.calculator.CalculatorFragment;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/19/11
|
||||
* Time: 11:37 AM
|
||||
*/
|
||||
public class CalculatorHelpHintsFragment extends CalculatorFragment {
|
||||
|
||||
public CalculatorHelpHintsFragment() {
|
||||
super(CalculatorFragmentType.hints);
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.help;
|
||||
|
||||
import org.solovyev.android.calculator.CalculatorFragment;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/19/11
|
||||
* Time: 11:38 AM
|
||||
*/
|
||||
public class CalculatorHelpScreensFragment extends CalculatorFragment {
|
||||
|
||||
public CalculatorHelpScreensFragment() {
|
||||
super(CalculatorFragmentType.screens);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* 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.history;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ListView;
|
||||
import com.actionbarsherlock.app.SherlockListFragment;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
import org.solovyev.android.menu.*;
|
||||
import org.solovyev.android.sherlock.menu.SherlockMenuHelper;
|
||||
import org.solovyev.common.collections.CollectionsUtils;
|
||||
import org.solovyev.common.equals.Equalizer;
|
||||
import org.solovyev.common.filter.Filter;
|
||||
import org.solovyev.common.filter.FilterRule;
|
||||
import org.solovyev.common.filter.FilterRulesChain;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/15/11
|
||||
* Time: 1:13 PM
|
||||
*/
|
||||
public abstract class AbstractCalculatorHistoryFragment extends SherlockListFragment implements CalculatorEventListener {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTANTS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@NotNull
|
||||
private static final String TAG = "CalculatorHistoryFragment";
|
||||
|
||||
public static final Comparator<CalculatorHistoryState> COMPARATOR = new Comparator<CalculatorHistoryState>() {
|
||||
@Override
|
||||
public int compare(CalculatorHistoryState state1, CalculatorHistoryState state2) {
|
||||
if (state1.isSaved() == state2.isSaved()) {
|
||||
long l = state2.getTime() - state1.getTime();
|
||||
return l > 0l ? 1 : (l < 0l ? -1 : 0);
|
||||
} else if (state1.isSaved()) {
|
||||
return -1;
|
||||
} else if (state2.isSaved()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* FIELDS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
|
||||
@NotNull
|
||||
private ArrayAdapter<CalculatorHistoryState> adapter;
|
||||
|
||||
@NotNull
|
||||
private CalculatorFragmentHelper fragmentHelper;
|
||||
|
||||
private ActivityMenu<Menu, MenuItem> menu = ListActivityMenu.fromResource(org.solovyev.android.calculator.R.menu.history_menu, HistoryMenu.class, SherlockMenuHelper.getInstance());
|
||||
|
||||
protected AbstractCalculatorHistoryFragment(@NotNull CalculatorFragmentType fragmentType) {
|
||||
fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(fragmentType.getDefaultLayoutId(), fragmentType.getDefaultTitleResId(), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
fragmentHelper.onCreate(this);
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
logDebug("onCreate");
|
||||
}
|
||||
|
||||
private int logDebug(@NotNull String msg) {
|
||||
return Log.d(TAG + ": " + getTag(), msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return fragmentHelper.onCreateView(this, inflater, container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View root, Bundle savedInstanceState) {
|
||||
super.onViewCreated(root, savedInstanceState);
|
||||
|
||||
logDebug("onViewCreated");
|
||||
|
||||
fragmentHelper.onViewCreated(this, root);
|
||||
|
||||
adapter = new HistoryArrayAdapter(this.getActivity(), getItemLayoutId(), org.solovyev.android.calculator.R.id.history_item, new ArrayList<CalculatorHistoryState>());
|
||||
setListAdapter(adapter);
|
||||
|
||||
final ListView lv = getListView();
|
||||
lv.setTextFilterEnabled(true);
|
||||
|
||||
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
public void onItemClick(final AdapterView<?> parent,
|
||||
final View view,
|
||||
final int position,
|
||||
final long id) {
|
||||
|
||||
useHistoryItem((CalculatorHistoryState) parent.getItemAtPosition(position));
|
||||
}
|
||||
});
|
||||
|
||||
lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
|
||||
@Override
|
||||
public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
|
||||
final CalculatorHistoryState historyState = (CalculatorHistoryState) parent.getItemAtPosition(position);
|
||||
|
||||
final Context context = getActivity();
|
||||
|
||||
final HistoryItemMenuData data = new HistoryItemMenuData(historyState, adapter);
|
||||
|
||||
final List<HistoryItemMenuItem> menuItems = CollectionsUtils.asList(HistoryItemMenuItem.values());
|
||||
|
||||
if (historyState.isSaved()) {
|
||||
menuItems.remove(HistoryItemMenuItem.save);
|
||||
} else {
|
||||
if (isAlreadySaved(historyState)) {
|
||||
menuItems.remove(HistoryItemMenuItem.save);
|
||||
}
|
||||
menuItems.remove(HistoryItemMenuItem.remove);
|
||||
menuItems.remove(HistoryItemMenuItem.edit);
|
||||
}
|
||||
|
||||
if (historyState.getDisplayState().isValid() && StringUtils.isEmpty(historyState.getDisplayState().getEditorState().getText())) {
|
||||
menuItems.remove(HistoryItemMenuItem.copy_result);
|
||||
}
|
||||
|
||||
final AMenuBuilder<HistoryItemMenuItem, HistoryItemMenuData> menuBuilder = AMenuBuilder.newInstance(context, MenuImpl.newInstance(menuItems));
|
||||
menuBuilder.create(data).show();
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
this.fragmentHelper.onResume(this);
|
||||
|
||||
updateAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
this.fragmentHelper.onPause(this);
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
logDebug("onDestroy");
|
||||
|
||||
fragmentHelper.onDestroy(this);
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
protected abstract int getItemLayoutId();
|
||||
|
||||
private void updateAdapter() {
|
||||
final List<CalculatorHistoryState> historyList = getHistoryList();
|
||||
|
||||
final ArrayAdapter<CalculatorHistoryState> adapter = getAdapter();
|
||||
try {
|
||||
adapter.setNotifyOnChange(false);
|
||||
adapter.clear();
|
||||
for (CalculatorHistoryState historyState : historyList) {
|
||||
adapter.add(historyState);
|
||||
}
|
||||
} finally {
|
||||
adapter.setNotifyOnChange(true);
|
||||
}
|
||||
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public static boolean isAlreadySaved(@NotNull CalculatorHistoryState historyState) {
|
||||
assert !historyState.isSaved();
|
||||
|
||||
boolean result = false;
|
||||
try {
|
||||
historyState.setSaved(true);
|
||||
if ( CollectionsUtils.contains(historyState, Locator.getInstance().getHistory().getSavedHistory(), new Equalizer<CalculatorHistoryState>() {
|
||||
@Override
|
||||
public boolean equals(@Nullable CalculatorHistoryState first, @Nullable CalculatorHistoryState second) {
|
||||
return first != null && second != null &&
|
||||
first.getTime() == second.getTime() &&
|
||||
first.getDisplayState().equals(second.getDisplayState()) &&
|
||||
first.getEditorState().equals(second.getEditorState());
|
||||
}
|
||||
}) ) {
|
||||
result = true;
|
||||
}
|
||||
} finally {
|
||||
historyState.setSaved(false);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void useHistoryItem(@NotNull final CalculatorHistoryState historyState) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.use_history_state, historyState);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<CalculatorHistoryState> getHistoryList() {
|
||||
final List<CalculatorHistoryState> calculatorHistoryStates = getHistoryItems();
|
||||
|
||||
Collections.sort(calculatorHistoryStates, COMPARATOR);
|
||||
|
||||
final FilterRulesChain<CalculatorHistoryState> filterRulesChain = new FilterRulesChain<CalculatorHistoryState>();
|
||||
filterRulesChain.addFilterRule(new FilterRule<CalculatorHistoryState>() {
|
||||
@Override
|
||||
public boolean isFiltered(CalculatorHistoryState object) {
|
||||
return object == null || StringUtils.isEmpty(object.getEditorState().getText());
|
||||
}
|
||||
});
|
||||
|
||||
new Filter<CalculatorHistoryState>(filterRulesChain).filter(calculatorHistoryStates.iterator());
|
||||
|
||||
return calculatorHistoryStates;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract List<CalculatorHistoryState> getHistoryItems();
|
||||
|
||||
@NotNull
|
||||
public static String getHistoryText(@NotNull CalculatorHistoryState state) {
|
||||
final StringBuilder result = new StringBuilder();
|
||||
result.append(state.getEditorState().getText());
|
||||
result.append(getIdentitySign(state.getDisplayState().getJsclOperation()));
|
||||
final String expressionResult = state.getDisplayState().getEditorState().getText();
|
||||
if (expressionResult != null) {
|
||||
result.append(expressionResult);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getIdentitySign(@NotNull JsclOperation jsclOperation) {
|
||||
return jsclOperation == JsclOperation.simplify ? "≡" : "=";
|
||||
}
|
||||
|
||||
protected abstract void clearHistory();
|
||||
|
||||
@NotNull
|
||||
protected ArrayAdapter<CalculatorHistoryState> getAdapter() {
|
||||
return adapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
switch (calculatorEventType) {
|
||||
case history_state_added:
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
logDebug("onCalculatorEvent");
|
||||
updateAdapter();
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case clear_history_requested:
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
clearHistory();
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* MENU
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
this.menu.onCreateOptionsMenu(this.getActivity(), menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
this.menu.onPrepareOptionsMenu(this.getActivity(), menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
return this.menu.onOptionsItemSelected(this.getActivity(), item);
|
||||
}
|
||||
|
||||
private static enum HistoryMenu implements IdentifiableMenuItem<MenuItem> {
|
||||
|
||||
clear_history(org.solovyev.android.calculator.R.id.history_menu_clear_history) {
|
||||
@Override
|
||||
public void onClick(@NotNull MenuItem data, @NotNull Context context) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.clear_history_requested, null);
|
||||
}
|
||||
};
|
||||
|
||||
private final int itemId;
|
||||
|
||||
HistoryMenu(int itemId) {
|
||||
this.itemId = itemId;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Integer getItemId() {
|
||||
return this.itemId;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* 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.history;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.Calculator;
|
||||
import org.solovyev.android.calculator.CalculatorEventData;
|
||||
import org.solovyev.android.calculator.CalculatorEventType;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.common.history.HistoryAction;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/9/11
|
||||
* Time: 6:35 PM
|
||||
*/
|
||||
public class AndroidCalculatorHistory implements CalculatorHistory {
|
||||
|
||||
@NotNull
|
||||
private final CalculatorHistoryImpl calculatorHistory;
|
||||
|
||||
@NotNull
|
||||
private final Context context;
|
||||
|
||||
public AndroidCalculatorHistory(@NotNull Application application, @NotNull Calculator calculator) {
|
||||
this.context = application;
|
||||
calculatorHistory = new CalculatorHistoryImpl(calculator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (preferences != null) {
|
||||
final String value = preferences.getString(context.getString(R.string.p_calc_history), null);
|
||||
if (value != null) {
|
||||
calculatorHistory.fromXml(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void save() {
|
||||
final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
final SharedPreferences.Editor editor = settings.edit();
|
||||
|
||||
editor.putString(context.getString(R.string.p_calc_history), calculatorHistory.toXml());
|
||||
|
||||
editor.commit();
|
||||
}
|
||||
|
||||
public void clearSavedHistory() {
|
||||
calculatorHistory.clearSavedHistory();
|
||||
save();
|
||||
}
|
||||
|
||||
public void removeSavedHistory(@NotNull CalculatorHistoryState historyState) {
|
||||
historyState.setSaved(false);
|
||||
calculatorHistory.removeSavedHistory(historyState);
|
||||
save();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return calculatorHistory.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalculatorHistoryState getLastHistoryState() {
|
||||
return calculatorHistory.getLastHistoryState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUndoAvailable() {
|
||||
return calculatorHistory.isUndoAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalculatorHistoryState undo(@Nullable CalculatorHistoryState currentState) {
|
||||
return calculatorHistory.undo(currentState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRedoAvailable() {
|
||||
return calculatorHistory.isRedoAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalculatorHistoryState redo(@Nullable CalculatorHistoryState currentState) {
|
||||
return calculatorHistory.redo(currentState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActionAvailable(@NotNull HistoryAction historyAction) {
|
||||
return calculatorHistory.isActionAvailable(historyAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CalculatorHistoryState doAction(@NotNull HistoryAction historyAction, @Nullable CalculatorHistoryState currentState) {
|
||||
return calculatorHistory.doAction(historyAction, currentState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addState(@Nullable CalculatorHistoryState currentState) {
|
||||
calculatorHistory.addState(currentState);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<CalculatorHistoryState> getStates() {
|
||||
return calculatorHistory.getStates();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<CalculatorHistoryState> getStates(boolean includeIntermediateStates) {
|
||||
return calculatorHistory.getStates(includeIntermediateStates);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
calculatorHistory.clear();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<CalculatorHistoryState> getSavedHistory() {
|
||||
return calculatorHistory.getSavedHistory();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CalculatorHistoryState addSavedState(@NotNull CalculatorHistoryState historyState) {
|
||||
return calculatorHistory.addSavedState(historyState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromXml(@NotNull String xml) {
|
||||
calculatorHistory.fromXml(xml);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toXml() {
|
||||
return calculatorHistory.toXml();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
calculatorHistory.onCalculatorEvent(calculatorEventData, calculatorEventType, data);
|
||||
}
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.history;
|
||||
|
||||
import android.os.Bundle;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/18/11
|
||||
* Time: 7:37 PM
|
||||
*/
|
||||
public class CalculatorHistoryActivity extends SherlockFragmentActivity implements CalculatorEventListener {
|
||||
|
||||
@NotNull
|
||||
private final CalculatorActivityHelper activityHelper = CalculatorApplication.getInstance().createActivityHelper(R.layout.main_empty, CalculatorHistoryActivity.class.getSimpleName());
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
activityHelper.onCreate(this, savedInstanceState);
|
||||
|
||||
activityHelper.addTab(this, CalculatorFragmentType.history, null, R.id.main_layout);
|
||||
activityHelper.addTab(this, CalculatorFragmentType.saved_history, null, R.id.main_layout);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
activityHelper.onSaveInstanceState(this, outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
activityHelper.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
this.activityHelper.onPause(this);
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
activityHelper.onDestroy(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
if ( calculatorEventType == CalculatorEventType.use_history_state ) {
|
||||
this.finish();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.history;
|
||||
|
||||
import android.preference.PreferenceManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.Locator;
|
||||
import org.solovyev.android.calculator.CalculatorPreferences;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/18/11
|
||||
* Time: 7:39 PM
|
||||
*/
|
||||
public class CalculatorHistoryFragment extends AbstractCalculatorHistoryFragment {
|
||||
|
||||
public CalculatorHistoryFragment() {
|
||||
super(CalculatorFragmentType.history);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getItemLayoutId() {
|
||||
return R.layout.history_item;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<CalculatorHistoryState> getHistoryItems() {
|
||||
final boolean showIntermediateCalculations = CalculatorPreferences.History.showIntermediateCalculations.getPreference(PreferenceManager.getDefaultSharedPreferences(getActivity()));
|
||||
return new ArrayList<CalculatorHistoryState>(Locator.getInstance().getHistory().getStates(showIntermediateCalculations));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearHistory() {
|
||||
Locator.getInstance().getHistory().clear();
|
||||
getAdapter().clear();
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.history;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.Locator;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/18/11
|
||||
* Time: 7:40 PM
|
||||
*/
|
||||
public class CalculatorSavedHistoryFragment extends AbstractCalculatorHistoryFragment {
|
||||
|
||||
public CalculatorSavedHistoryFragment() {
|
||||
super(CalculatorFragmentType.saved_history);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getItemLayoutId() {
|
||||
return R.layout.saved_history_item;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<CalculatorHistoryState> getHistoryItems() {
|
||||
return new ArrayList<CalculatorHistoryState>(Locator.getInstance().getHistory().getSavedHistory());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void clearHistory() {
|
||||
Locator.getInstance().getHistory().clearSavedHistory();
|
||||
getAdapter().clear();
|
||||
}
|
||||
}
|
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.history;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.TextView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/18/11
|
||||
* Time: 7:39 PM
|
||||
*/
|
||||
public class HistoryArrayAdapter extends ArrayAdapter<CalculatorHistoryState> {
|
||||
|
||||
HistoryArrayAdapter(Context context, int resource, int textViewResourceId, @NotNull List<CalculatorHistoryState> historyList) {
|
||||
super(context, resource, textViewResourceId, historyList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
final ViewGroup result = (ViewGroup) super.getView(position, convertView, parent);
|
||||
|
||||
final CalculatorHistoryState state = getItem(position);
|
||||
|
||||
final TextView time = (TextView) result.findViewById(R.id.history_time);
|
||||
time.setText(new SimpleDateFormat().format(new Date(state.getTime())));
|
||||
|
||||
final TextView editor = (TextView) result.findViewById(R.id.history_item);
|
||||
editor.setText(AbstractCalculatorHistoryFragment.getHistoryText(state));
|
||||
|
||||
final TextView commentView = (TextView) result.findViewById(R.id.history_item_comment);
|
||||
if (commentView != null) {
|
||||
final String comment = state.getComment();
|
||||
if (!StringUtils.isEmpty(comment)) {
|
||||
commentView.setText(comment);
|
||||
} else {
|
||||
commentView.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
final TextView status = (TextView) result.findViewById(R.id.history_item_status);
|
||||
if (status != null) {
|
||||
if (state.isSaved()) {
|
||||
status.setText(getContext().getString(R.string.c_history_item_saved));
|
||||
} else {
|
||||
if ( AbstractCalculatorHistoryFragment.isAlreadySaved(state) ) {
|
||||
status.setText(getContext().getString(R.string.c_history_item_already_saved));
|
||||
} else {
|
||||
status.setText(getContext().getString(R.string.c_history_item_not_saved));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyDataSetChanged() {
|
||||
this.setNotifyOnChange(false);
|
||||
this.sort(AbstractCalculatorHistoryFragment.COMPARATOR);
|
||||
this.setNotifyOnChange(true);
|
||||
super.notifyDataSetChanged();
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.history;
|
||||
|
||||
import android.widget.ArrayAdapter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/18/11
|
||||
* Time: 3:10 PM
|
||||
*/
|
||||
public class HistoryItemMenuData {
|
||||
|
||||
@NotNull
|
||||
private final ArrayAdapter<CalculatorHistoryState> adapter;
|
||||
|
||||
@NotNull
|
||||
private final CalculatorHistoryState historyState;
|
||||
|
||||
public HistoryItemMenuData(@NotNull CalculatorHistoryState historyState, ArrayAdapter<CalculatorHistoryState> adapter) {
|
||||
this.historyState = historyState;
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CalculatorHistoryState getHistoryState() {
|
||||
return historyState;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ArrayAdapter<CalculatorHistoryState> getAdapter() {
|
||||
return adapter;
|
||||
}
|
||||
}
|
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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.history;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.text.ClipboardManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.Locator;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.menu.LabeledMenuItem;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/18/11
|
||||
* Time: 3:09 PM
|
||||
*/
|
||||
public enum HistoryItemMenuItem implements LabeledMenuItem<HistoryItemMenuData> {
|
||||
|
||||
use(R.string.c_use) {
|
||||
@Override
|
||||
public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) {
|
||||
AbstractCalculatorHistoryFragment.useHistoryItem(data.getHistoryState());
|
||||
}
|
||||
},
|
||||
|
||||
copy_expression(R.string.c_copy_expression) {
|
||||
@Override
|
||||
public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) {
|
||||
final CalculatorHistoryState calculatorHistoryState = data.getHistoryState();
|
||||
final String text = calculatorHistoryState.getEditorState().getText();
|
||||
if (!StringUtils.isEmpty(text)) {
|
||||
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
|
||||
clipboard.setText(text);
|
||||
Toast.makeText(context, context.getText(R.string.c_expression_copied), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
copy_result(R.string.c_copy_result) {
|
||||
@Override
|
||||
public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) {
|
||||
final CalculatorHistoryState calculatorHistoryState = data.getHistoryState();
|
||||
final String text = calculatorHistoryState.getDisplayState().getEditorState().getText();
|
||||
if (!StringUtils.isEmpty(text)) {
|
||||
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
|
||||
clipboard.setText(text);
|
||||
Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
save(R.string.c_save) {
|
||||
@Override
|
||||
public void onClick(@NotNull final HistoryItemMenuData data, @NotNull final Context context) {
|
||||
final CalculatorHistoryState historyState = data.getHistoryState();
|
||||
if (!historyState.isSaved()) {
|
||||
createEditHistoryDialog(data, context, true);
|
||||
} else {
|
||||
Toast.makeText(context, context.getText(R.string.c_history_already_saved), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
edit(R.string.c_edit) {
|
||||
@Override
|
||||
public void onClick(@NotNull final HistoryItemMenuData data, @NotNull final Context context) {
|
||||
final CalculatorHistoryState historyState = data.getHistoryState();
|
||||
if (historyState.isSaved()) {
|
||||
createEditHistoryDialog(data, context, false);
|
||||
} else {
|
||||
Toast.makeText(context, context.getText(R.string.c_history_must_be_saved), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
remove(R.string.c_remove) {
|
||||
@Override
|
||||
public void onClick(@NotNull HistoryItemMenuData data, @NotNull Context context) {
|
||||
final CalculatorHistoryState historyState = data.getHistoryState();
|
||||
if (historyState.isSaved()) {
|
||||
data.getAdapter().remove(historyState);
|
||||
Locator.getInstance().getHistory().removeSavedHistory(historyState);
|
||||
Toast.makeText(context, context.getText(R.string.c_history_was_removed), Toast.LENGTH_LONG).show();
|
||||
data.getAdapter().notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static void createEditHistoryDialog(@NotNull final HistoryItemMenuData data, @NotNull final Context context, final boolean save) {
|
||||
final CalculatorHistoryState historyState = data.getHistoryState();
|
||||
|
||||
final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
final View editView = layoutInflater.inflate(R.layout.history_edit, null);
|
||||
final TextView historyExpression = (TextView)editView.findViewById(R.id.history_edit_expression);
|
||||
historyExpression.setText(AbstractCalculatorHistoryFragment.getHistoryText(historyState));
|
||||
|
||||
final EditText comment = (EditText)editView.findViewById(R.id.history_edit_comment);
|
||||
comment.setText(historyState.getComment());
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context)
|
||||
.setTitle(save ? R.string.c_save_history : R.string.c_edit_history)
|
||||
.setCancelable(true)
|
||||
.setNegativeButton(R.string.c_cancel, null)
|
||||
.setPositiveButton(R.string.c_save, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (save) {
|
||||
final CalculatorHistoryState savedHistoryItem = Locator.getInstance().getHistory().addSavedState(historyState);
|
||||
savedHistoryItem.setComment(comment.getText().toString());
|
||||
Locator.getInstance().getHistory().save();
|
||||
// we don't need to add element to the adapter as adapter of another activity must be updated and not this
|
||||
//data.getAdapter().add(savedHistoryItem);
|
||||
} else {
|
||||
historyState.setComment(comment.getText().toString());
|
||||
Locator.getInstance().getHistory().save();
|
||||
}
|
||||
data.getAdapter().notifyDataSetChanged();
|
||||
Toast.makeText(context, context.getText(R.string.c_history_saved), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
})
|
||||
.setView(editView);
|
||||
|
||||
builder.create().show();
|
||||
}
|
||||
|
||||
private final int captionId;
|
||||
|
||||
private HistoryItemMenuItem(int captionId) {
|
||||
this.captionId = captionId;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getCaption(@NotNull Context context) {
|
||||
return context.getString(captionId);
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.history;
|
||||
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.Editor;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/17/11
|
||||
* Time: 9:39 PM
|
||||
*/
|
||||
public class TextViewEditorAdapter implements Editor {
|
||||
|
||||
@NotNull
|
||||
private final TextView textView;
|
||||
|
||||
public TextViewEditorAdapter(@NotNull TextView textView) {
|
||||
this.textView = textView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getText() {
|
||||
return textView.getText().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(@Nullable CharSequence text) {
|
||||
textView.setText(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSelection() {
|
||||
return textView.getSelectionStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelection(int selection) {
|
||||
if ( textView instanceof EditText ) {
|
||||
((EditText) textView).setSelection(selection);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,354 @@
|
||||
/*
|
||||
* 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.math.edit;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.*;
|
||||
import com.actionbarsherlock.app.SherlockListFragment;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
import org.solovyev.android.menu.AMenuBuilder;
|
||||
import org.solovyev.android.menu.AMenuItem;
|
||||
import org.solovyev.android.menu.LabeledMenuItem;
|
||||
import org.solovyev.android.menu.MenuImpl;
|
||||
import org.solovyev.common.equals.EqualsTool;
|
||||
import org.solovyev.common.filter.Filter;
|
||||
import org.solovyev.common.filter.FilterRule;
|
||||
import org.solovyev.common.math.MathEntity;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/21/11
|
||||
* Time: 9:24 PM
|
||||
*/
|
||||
public abstract class AbstractMathEntityListFragment<T extends MathEntity> extends SherlockListFragment implements CalculatorEventListener {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTANTS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public static final String MATH_ENTITY_CATEGORY_EXTRA_STRING = "org.solovyev.android.calculator.CalculatorVarsActivity_math_entity_category";
|
||||
|
||||
protected final static List<Character> acceptableChars = Arrays.asList(StringUtils.toObject("1234567890abcdefghijklmnopqrstuvwxyzйцукенгшщзхъфывапролджэячсмитьбюё_".toCharArray()));
|
||||
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* FIELDS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Nullable
|
||||
private MathEntityArrayAdapter<T> adapter;
|
||||
|
||||
@Nullable
|
||||
private String category;
|
||||
|
||||
@NotNull
|
||||
private final CalculatorFragmentHelper fragmentHelper;
|
||||
|
||||
@NotNull
|
||||
private final Handler uiHandler = new Handler();
|
||||
|
||||
protected AbstractMathEntityListFragment(@NotNull CalculatorFragmentType fragmentType) {
|
||||
fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(fragmentType.getDefaultLayoutId(),fragmentType.getDefaultTitleResId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final Bundle bundle = getArguments();
|
||||
if (bundle != null) {
|
||||
category = bundle.getString(MATH_ENTITY_CATEGORY_EXTRA_STRING);
|
||||
}
|
||||
|
||||
fragmentHelper.onCreate(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return fragmentHelper.onCreateView(this, inflater, container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View root, Bundle savedInstanceState) {
|
||||
super.onViewCreated(root, savedInstanceState);
|
||||
|
||||
fragmentHelper.onViewCreated(this, root);
|
||||
|
||||
final ListView lv = getListView();
|
||||
lv.setTextFilterEnabled(true);
|
||||
|
||||
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||
public void onItemClick(final AdapterView<?> parent,
|
||||
final View view,
|
||||
final int position,
|
||||
final long id) {
|
||||
final AMenuItem<T> onClick = getOnClickAction();
|
||||
if (onClick != null) {
|
||||
onClick.onClick(((T) parent.getItemAtPosition(position)), getActivity());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
|
||||
@Override
|
||||
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
final T item = (T) parent.getItemAtPosition(position);
|
||||
|
||||
final List<LabeledMenuItem<T>> menuItems = getMenuItemsOnLongClick(item);
|
||||
|
||||
if (!menuItems.isEmpty()) {
|
||||
final AMenuBuilder<LabeledMenuItem<T>, T> menuBuilder = AMenuBuilder.newInstance(AbstractMathEntityListFragment.this.getActivity(), MenuImpl.newInstance(menuItems));
|
||||
menuBuilder.create(item).show();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract AMenuItem<T> getOnClickAction();
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
fragmentHelper.onDestroy(this);
|
||||
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract List<LabeledMenuItem<T>> getMenuItemsOnLongClick(@NotNull T item);
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
this.fragmentHelper.onPause(this);
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
this.fragmentHelper.onResume(this);
|
||||
|
||||
adapter = new MathEntityArrayAdapter<T>(getDescriptionGetter(), this.getActivity(), R.layout.math_entity, R.id.math_entity_text, getMathEntitiesByCategory());
|
||||
setListAdapter(adapter);
|
||||
|
||||
sort();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<T> getMathEntitiesByCategory() {
|
||||
final List<T> result = getMathEntities();
|
||||
|
||||
new Filter<T>(new FilterRule<T>() {
|
||||
@Override
|
||||
public boolean isFiltered(T t) {
|
||||
return !isInCategory(t);
|
||||
}
|
||||
}).filter(result.iterator());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean isInCategory(@Nullable T t) {
|
||||
return t != null && (category == null || EqualsTool.areEqual(getMathEntityCategory(t), category));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract MathEntityDescriptionGetter getDescriptionGetter();
|
||||
|
||||
@NotNull
|
||||
protected abstract List<T> getMathEntities();
|
||||
|
||||
@Nullable
|
||||
abstract String getMathEntityCategory(@NotNull T t);
|
||||
|
||||
protected void sort() {
|
||||
final MathEntityArrayAdapter<T> localAdapter = adapter;
|
||||
if (localAdapter != null) {
|
||||
localAdapter.sort(new Comparator<T>() {
|
||||
@Override
|
||||
public int compare(T function1, T function2) {
|
||||
return function1.getName().compareTo(function2.getName());
|
||||
}
|
||||
});
|
||||
|
||||
localAdapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
protected static class MathEntityArrayAdapter<T extends MathEntity> extends ArrayAdapter<T> {
|
||||
|
||||
@NotNull
|
||||
private final MathEntityDescriptionGetter descriptionGetter;
|
||||
|
||||
private MathEntityArrayAdapter(@NotNull MathEntityDescriptionGetter descriptionGetter,
|
||||
@NotNull Context context,
|
||||
int resource,
|
||||
int textViewResourceId,
|
||||
@NotNull List<T> objects) {
|
||||
|
||||
super(context, resource, textViewResourceId, objects);
|
||||
this.descriptionGetter = descriptionGetter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, @Nullable View convertView, ViewGroup parent) {
|
||||
final ViewGroup result;
|
||||
|
||||
if (convertView == null) {
|
||||
result = (ViewGroup) super.getView(position, convertView, parent);
|
||||
fillView(position, result);
|
||||
} else {
|
||||
result = (ViewGroup) convertView;
|
||||
fillView(position, result);
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void fillView(int position, @NotNull ViewGroup result) {
|
||||
final T mathEntity = getItem(position);
|
||||
|
||||
final TextView text = (TextView) result.findViewById(R.id.math_entity_text);
|
||||
text.setText(String.valueOf(mathEntity));
|
||||
|
||||
final String mathEntityDescription = descriptionGetter.getDescription(getContext(), mathEntity.getName());
|
||||
|
||||
final TextView description = (TextView) result.findViewById(R.id.math_entity_description);
|
||||
if (!StringUtils.isEmpty(mathEntityDescription)) {
|
||||
description.setVisibility(View.VISIBLE);
|
||||
description.setText(mathEntityDescription);
|
||||
} else {
|
||||
description.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static class MathEntityDescriptionGetterImpl implements MathEntityDescriptionGetter {
|
||||
|
||||
@NotNull
|
||||
private final CalculatorMathRegistry<?> mathRegistry;
|
||||
|
||||
public MathEntityDescriptionGetterImpl(@NotNull CalculatorMathRegistry<?> mathRegistry) {
|
||||
this.mathRegistry = mathRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(@NotNull Context context, @NotNull String mathEntityName) {
|
||||
return this.mathRegistry.getDescription(mathEntityName);
|
||||
}
|
||||
}
|
||||
|
||||
protected static interface MathEntityDescriptionGetter {
|
||||
|
||||
@Nullable
|
||||
String getDescription(@NotNull Context context, @NotNull String mathEntityName);
|
||||
}
|
||||
|
||||
public void addToAdapter(@NotNull T mathEntity) {
|
||||
if (this.adapter != null) {
|
||||
this.adapter.add(mathEntity);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeFromAdapter(@NotNull T mathEntity) {
|
||||
if (this.adapter != null) {
|
||||
this.adapter.remove(mathEntity);
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyAdapter() {
|
||||
if (this.adapter != null) {
|
||||
this.adapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected MathEntityArrayAdapter<T> getAdapter() {
|
||||
return adapter;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected Handler getUiHandler() {
|
||||
return uiHandler;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
static void createTab(@NotNull Context context,
|
||||
@NotNull TabHost tabHost,
|
||||
@NotNull String tabId,
|
||||
@NotNull String categoryId,
|
||||
int tabCaptionId,
|
||||
@NotNull Class<? extends Activity> activityClass,
|
||||
@Nullable Intent parentIntent) {
|
||||
|
||||
TabHost.TabSpec spec;
|
||||
|
||||
final Intent intent;
|
||||
if (parentIntent != null) {
|
||||
intent = new Intent(parentIntent);
|
||||
} else {
|
||||
intent = new Intent();
|
||||
}
|
||||
intent.setClass(context, activityClass);
|
||||
intent.putExtra(MATH_ENTITY_CATEGORY_EXTRA_STRING, categoryId);
|
||||
|
||||
// Initialize a TabSpec for each tab and add it to the TabHost
|
||||
spec = tabHost.newTabSpec(tabId).setIndicator(context.getString(tabCaptionId)).setContent(intent);
|
||||
|
||||
tabHost.addTab(spec);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Bundle createBundleFor(@NotNull String categoryId) {
|
||||
final Bundle result = new Bundle(1);
|
||||
putCategory(result, categoryId);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void putCategory(@NotNull Bundle bundle, @NotNull String categoryId) {
|
||||
bundle.putString(MATH_ENTITY_CATEGORY_EXTRA_STRING, categoryId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
}
|
||||
}
|
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.math.edit;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
import org.solovyev.android.calculator.history.CalculatorHistoryActivity;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/21/11
|
||||
* Time: 10:33 PM
|
||||
*/
|
||||
public class CalculatorFunctionsActivity extends SherlockFragmentActivity implements CalculatorEventListener {
|
||||
|
||||
@NotNull
|
||||
private final CalculatorActivityHelper activityHelper = CalculatorApplication.getInstance().createActivityHelper(R.layout.main_empty, CalculatorHistoryActivity.class.getSimpleName());
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
activityHelper.onCreate(this, savedInstanceState);
|
||||
|
||||
final Bundle bundle;
|
||||
|
||||
final Intent intent = getIntent();
|
||||
if (intent != null) {
|
||||
bundle = intent.getExtras();
|
||||
} else {
|
||||
bundle = null;
|
||||
}
|
||||
|
||||
final CalculatorFragmentType fragmentType = CalculatorFragmentType.functions;
|
||||
|
||||
for (FunctionCategory category : FunctionCategory.getCategoriesByTabOrder()) {
|
||||
final AndroidFunctionCategory androidCategory = AndroidFunctionCategory.valueOf(category);
|
||||
if (androidCategory != null) {
|
||||
|
||||
final Bundle fragmentParameters;
|
||||
|
||||
if (category == FunctionCategory.my && bundle != null) {
|
||||
AbstractMathEntityListFragment.putCategory(bundle, category.name());
|
||||
fragmentParameters = bundle;
|
||||
} else {
|
||||
fragmentParameters = AbstractMathEntityListFragment.createBundleFor(category.name());
|
||||
}
|
||||
|
||||
activityHelper.addTab(this, fragmentType.createSubFragmentTag(category.name()), fragmentType.getFragmentClass(), fragmentParameters, androidCategory.getCaptionId(), R.id.main_layout);
|
||||
} else {
|
||||
Log.e(CalculatorFunctionsActivity.class.getSimpleName(), "Unable to find android function category for " + category);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
activityHelper.onSaveInstanceState(this, outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
activityHelper.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
this.activityHelper.onPause(this);
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
this.activityHelper.onDestroy(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
switch (calculatorEventType) {
|
||||
case use_function:
|
||||
this.finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* 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.math.edit;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.text.ClipboardManager;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
import jscl.math.function.Function;
|
||||
import jscl.math.function.IFunction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
import org.solovyev.android.calculator.function.FunctionEditDialogFragment;
|
||||
import org.solovyev.android.menu.AMenuItem;
|
||||
import org.solovyev.android.menu.LabeledMenuItem;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/29/11
|
||||
* Time: 4:55 PM
|
||||
*/
|
||||
public class CalculatorFunctionsFragment extends AbstractMathEntityListFragment<Function> {
|
||||
|
||||
public static final String CREATE_FUNCTION_EXTRA = "create_function";
|
||||
|
||||
public CalculatorFunctionsFragment() {
|
||||
super(CalculatorFragmentType.functions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final Bundle bundle = getArguments();
|
||||
if (bundle != null) {
|
||||
final Parcelable parcelable = bundle.getParcelable(CREATE_FUNCTION_EXTRA);
|
||||
if (parcelable instanceof FunctionEditDialogFragment.Input) {
|
||||
FunctionEditDialogFragment.showDialog((FunctionEditDialogFragment.Input) parcelable, this.getActivity().getSupportFragmentManager());
|
||||
|
||||
// in order to stop intent for other tabs
|
||||
bundle.remove(CREATE_FUNCTION_EXTRA);
|
||||
}
|
||||
}
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AMenuItem<Function> getOnClickAction() {
|
||||
return LongClickMenuItem.use;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<LabeledMenuItem<Function>> getMenuItemsOnLongClick(@NotNull Function item) {
|
||||
List<LabeledMenuItem<Function>> result = new ArrayList<LabeledMenuItem<Function>>(Arrays.asList(LongClickMenuItem.values()));
|
||||
|
||||
final CalculatorMathRegistry<Function> functionsRegistry = Locator.getInstance().getEngine().getFunctionsRegistry();
|
||||
if ( StringUtils.isEmpty(functionsRegistry.getDescription(item.getName())) ) {
|
||||
result.remove(LongClickMenuItem.copy_description);
|
||||
}
|
||||
|
||||
final Function function = functionsRegistry.get(item.getName());
|
||||
if (function == null || function.isSystem()) {
|
||||
result.remove(LongClickMenuItem.edit);
|
||||
result.remove(LongClickMenuItem.remove);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@NotNull
|
||||
@Override
|
||||
protected MathEntityDescriptionGetter getDescriptionGetter() {
|
||||
return new MathEntityDescriptionGetterImpl(Locator.getInstance().getEngine().getFunctionsRegistry());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<Function> getMathEntities() {
|
||||
return new ArrayList<Function>(Locator.getInstance().getEngine().getFunctionsRegistry().getEntities());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getMathEntityCategory(@NotNull Function function) {
|
||||
return Locator.getInstance().getEngine().getFunctionsRegistry().getCategory(function);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
super.onCalculatorEvent(calculatorEventData, calculatorEventType, data);
|
||||
|
||||
switch (calculatorEventType) {
|
||||
case function_added:
|
||||
processFunctionAdded((Function) data);
|
||||
break;
|
||||
|
||||
case function_changed:
|
||||
processFunctionChanged((Change<IFunction>) data);
|
||||
break;
|
||||
|
||||
case function_removed:
|
||||
processFunctionRemoved((Function) data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void processFunctionRemoved(@NotNull final Function function) {
|
||||
if (this.isInCategory(function)) {
|
||||
getUiHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
removeFromAdapter(function);
|
||||
notifyAdapter();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void processFunctionChanged(@NotNull final Change<IFunction> change) {
|
||||
final IFunction newFunction = change.getNewValue();
|
||||
|
||||
if (newFunction instanceof Function) {
|
||||
|
||||
if (this.isInCategory((Function)newFunction)) {
|
||||
|
||||
getUiHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
IFunction oldValue = change.getOldValue();
|
||||
|
||||
if (oldValue.isIdDefined()) {
|
||||
final MathEntityArrayAdapter<Function> adapter = getAdapter();
|
||||
if ( adapter != null ) {
|
||||
for (int i = 0; i < adapter.getCount(); i++) {
|
||||
final Function functionFromAdapter = adapter.getItem(i);
|
||||
if ( functionFromAdapter.isIdDefined() && oldValue.getId().equals(functionFromAdapter.getId()) ) {
|
||||
adapter.remove(functionFromAdapter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addToAdapter((Function)newFunction);
|
||||
sort();
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException("Function must be instance of jscl.math.function.Function class!");
|
||||
}
|
||||
}
|
||||
|
||||
private void processFunctionAdded(@NotNull final Function function) {
|
||||
if (this.isInCategory(function)) {
|
||||
getUiHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
addToAdapter(function);
|
||||
sort();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* MENU
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.functions_menu, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
boolean result;
|
||||
|
||||
switch (item.getItemId()) {
|
||||
case R.id.functions_menu_add_function:
|
||||
FunctionEditDialogFragment.showDialog(FunctionEditDialogFragment.Input.newInstance(), this.getActivity().getSupportFragmentManager());
|
||||
result = true;
|
||||
break;
|
||||
default:
|
||||
result = super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private static enum LongClickMenuItem implements LabeledMenuItem<Function> {
|
||||
use(R.string.c_use) {
|
||||
@Override
|
||||
public void onClick(@NotNull Function function, @NotNull Context context) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.use_function, function);
|
||||
}
|
||||
},
|
||||
|
||||
edit(R.string.c_edit) {
|
||||
@Override
|
||||
public void onClick(@NotNull Function function, @NotNull Context context) {
|
||||
if (function instanceof IFunction) {
|
||||
FunctionEditDialogFragment.showDialog(FunctionEditDialogFragment.Input.newFromFunction((IFunction) function), ((SherlockFragmentActivity) context).getSupportFragmentManager());
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
remove(R.string.c_remove) {
|
||||
@Override
|
||||
public void onClick(@NotNull Function function, @NotNull Context context) {
|
||||
MathEntityRemover.newFunctionRemover(function, null, context, context).showConfirmationDialog();
|
||||
}
|
||||
},
|
||||
|
||||
copy_description(R.string.c_copy_description) {
|
||||
@Override
|
||||
public void onClick(@NotNull Function function, @NotNull Context context) {
|
||||
final String text = Locator.getInstance().getEngine().getFunctionsRegistry().getDescription(function.getName());
|
||||
if (!StringUtils.isEmpty(text)) {
|
||||
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
|
||||
clipboard.setText(text);
|
||||
}
|
||||
}
|
||||
};
|
||||
private final int captionId;
|
||||
|
||||
LongClickMenuItem(int captionId) {
|
||||
this.captionId = captionId;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getCaption(@NotNull Context context) {
|
||||
return context.getString(captionId);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.math.edit;
|
||||
|
||||
import android.os.Bundle;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
import org.solovyev.android.calculator.history.CalculatorHistoryActivity;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/21/11
|
||||
* Time: 10:33 PM
|
||||
*/
|
||||
public class CalculatorOperatorsActivity extends SherlockFragmentActivity implements CalculatorEventListener {
|
||||
|
||||
@NotNull
|
||||
private final CalculatorActivityHelper activityHelper = CalculatorApplication.getInstance().createActivityHelper(R.layout.main_empty, CalculatorHistoryActivity.class.getSimpleName());
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
activityHelper.onCreate(this, savedInstanceState);
|
||||
|
||||
final CalculatorFragmentType fragmentType = CalculatorFragmentType.operators;
|
||||
|
||||
for (OperatorCategory category : OperatorCategory.getCategoriesByTabOrder()) {
|
||||
final AndroidOperatorCategory androidCategory = AndroidOperatorCategory.valueOf(category);
|
||||
if (androidCategory != null) {
|
||||
activityHelper.addTab(this, fragmentType.createSubFragmentTag(category.name()), fragmentType.getFragmentClass(), AbstractMathEntityListFragment.createBundleFor(category.name()), androidCategory.getCaptionId(), R.id.main_layout);
|
||||
} else {
|
||||
activityHelper.logError("Unable to find android operator category for " + category);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
activityHelper.onSaveInstanceState(this, outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
activityHelper.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
this.activityHelper.onPause(this);
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
this.activityHelper.onDestroy(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
switch (calculatorEventType) {
|
||||
case use_operator:
|
||||
this.finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,133 @@
|
||||
package org.solovyev.android.calculator.math.edit;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.text.ClipboardManager;
|
||||
import jscl.math.operator.Operator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.Locator;
|
||||
import org.solovyev.android.calculator.CalculatorEventType;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
import org.solovyev.android.menu.AMenuItem;
|
||||
import org.solovyev.android.menu.LabeledMenuItem;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/17/11
|
||||
* Time: 1:53 PM
|
||||
*/
|
||||
|
||||
public class CalculatorOperatorsFragment extends AbstractMathEntityListFragment<Operator> {
|
||||
|
||||
public CalculatorOperatorsFragment() {
|
||||
super(CalculatorFragmentType.operators);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AMenuItem<Operator> getOnClickAction() {
|
||||
return LongClickMenuItem.use;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<LabeledMenuItem<Operator>> getMenuItemsOnLongClick(@NotNull Operator item) {
|
||||
final List<LabeledMenuItem<Operator>> result = new ArrayList<LabeledMenuItem<Operator>>(Arrays.asList(LongClickMenuItem.values()));
|
||||
|
||||
if ( StringUtils.isEmpty(OperatorDescriptionGetter.instance.getDescription(this.getActivity(), item.getName())) ) {
|
||||
result.remove(LongClickMenuItem.copy_description);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected MathEntityDescriptionGetter getDescriptionGetter() {
|
||||
return OperatorDescriptionGetter.instance;
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<Operator> getMathEntities() {
|
||||
final List<Operator> result = new ArrayList<Operator>();
|
||||
|
||||
result.addAll(Locator.getInstance().getEngine().getOperatorsRegistry().getEntities());
|
||||
result.addAll(Locator.getInstance().getEngine().getPostfixFunctionsRegistry().getEntities());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getMathEntityCategory(@NotNull Operator operator) {
|
||||
String result = Locator.getInstance().getEngine().getOperatorsRegistry().getCategory(operator);
|
||||
if (result == null) {
|
||||
result = Locator.getInstance().getEngine().getPostfixFunctionsRegistry().getCategory(operator);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static enum OperatorDescriptionGetter implements MathEntityDescriptionGetter {
|
||||
|
||||
instance;
|
||||
|
||||
@Override
|
||||
public String getDescription(@NotNull Context context, @NotNull String mathEntityName) {
|
||||
String result = Locator.getInstance().getEngine().getOperatorsRegistry().getDescription(mathEntityName);
|
||||
if (StringUtils.isEmpty(result)) {
|
||||
result = Locator.getInstance().getEngine().getPostfixFunctionsRegistry().getDescription(mathEntityName);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private static enum LongClickMenuItem implements LabeledMenuItem<Operator> {
|
||||
|
||||
use(R.string.c_use) {
|
||||
@Override
|
||||
public void onClick(@NotNull Operator data, @NotNull Context context) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.use_operator, data);
|
||||
}
|
||||
},
|
||||
|
||||
copy_description(R.string.c_copy_description) {
|
||||
@Override
|
||||
public void onClick(@NotNull Operator data, @NotNull Context context) {
|
||||
final String text = OperatorDescriptionGetter.instance.getDescription(context, data.getName());
|
||||
if (!StringUtils.isEmpty(text)) {
|
||||
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
|
||||
clipboard.setText(text);
|
||||
}
|
||||
}
|
||||
};
|
||||
private final int captionId;
|
||||
|
||||
LongClickMenuItem(int captionId) {
|
||||
this.captionId = captionId;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getCaption(@NotNull Context context) {
|
||||
return context.getString(captionId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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.math.edit;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
import org.solovyev.android.calculator.history.CalculatorHistoryActivity;
|
||||
import org.solovyev.android.calculator.AndroidVarCategory;
|
||||
import org.solovyev.android.calculator.VarCategory;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/21/11
|
||||
* Time: 11:05 PM
|
||||
*/
|
||||
public class CalculatorVarsActivity extends SherlockFragmentActivity implements CalculatorEventListener {
|
||||
|
||||
@NotNull
|
||||
private final CalculatorActivityHelper activityHelper = CalculatorApplication.getInstance().createActivityHelper(R.layout.main_empty, CalculatorHistoryActivity.class.getSimpleName());
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
activityHelper.onCreate(this, savedInstanceState);
|
||||
|
||||
final Bundle bundle;
|
||||
|
||||
final Intent intent = getIntent();
|
||||
if (intent != null) {
|
||||
bundle = intent.getExtras();
|
||||
} else {
|
||||
bundle = null;
|
||||
}
|
||||
|
||||
final CalculatorFragmentType fragmentType = CalculatorFragmentType.variables;
|
||||
|
||||
for (VarCategory category : VarCategory.getCategoriesByTabOrder()) {
|
||||
|
||||
final Bundle fragmentParameters;
|
||||
|
||||
if (category == VarCategory.my && bundle != null) {
|
||||
AbstractMathEntityListFragment.putCategory(bundle, category.name());
|
||||
fragmentParameters = bundle;
|
||||
} else {
|
||||
fragmentParameters = AbstractMathEntityListFragment.createBundleFor(category.name());
|
||||
}
|
||||
|
||||
|
||||
final AndroidVarCategory androidVarCategory = AndroidVarCategory.valueOf(category);
|
||||
|
||||
if (androidVarCategory != null) {
|
||||
activityHelper.addTab(this, fragmentType.createSubFragmentTag(category.name()), fragmentType.getFragmentClass(), fragmentParameters, androidVarCategory.getCaptionId(), R.id.main_layout);
|
||||
} else {
|
||||
activityHelper.logError("Unable to find android var category for " + category);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
activityHelper.onSaveInstanceState(this, outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
activityHelper.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
this.activityHelper.onPause(this);
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
this.activityHelper.onDestroy(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
switch (calculatorEventType) {
|
||||
case use_constant:
|
||||
this.finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* 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.math.edit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
import jscl.math.function.IConstant;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
import org.solovyev.android.calculator.math.MathType;
|
||||
import org.solovyev.android.menu.AMenuItem;
|
||||
import org.solovyev.android.menu.LabeledMenuItem;
|
||||
import org.solovyev.common.JPredicate;
|
||||
import org.solovyev.common.collections.CollectionsUtils;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/28/11
|
||||
* Time: 10:55 PM
|
||||
*/
|
||||
public class CalculatorVarsFragment extends AbstractMathEntityListFragment<IConstant> {
|
||||
|
||||
public static final String CREATE_VAR_EXTRA_STRING = "create_var";
|
||||
|
||||
public CalculatorVarsFragment() {
|
||||
super(CalculatorFragmentType.variables);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final Bundle bundle = getArguments();
|
||||
if (bundle != null) {
|
||||
final String varValue = bundle.getString(CREATE_VAR_EXTRA_STRING);
|
||||
if (!StringUtils.isEmpty(varValue)) {
|
||||
VarEditDialogFragment.showDialog(VarEditDialogFragment.Input.newFromValue(varValue), this.getActivity().getSupportFragmentManager());
|
||||
|
||||
// in order to stop intent for other tabs
|
||||
bundle.remove(CREATE_VAR_EXTRA_STRING);
|
||||
}
|
||||
}
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AMenuItem<IConstant> getOnClickAction() {
|
||||
return LongClickMenuItem.use;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<LabeledMenuItem<IConstant>> getMenuItemsOnLongClick(@NotNull IConstant item) {
|
||||
final List<LabeledMenuItem<IConstant>> result = new ArrayList<LabeledMenuItem<IConstant>>(Arrays.asList(LongClickMenuItem.values()));
|
||||
|
||||
if (item.isSystem()) {
|
||||
result.remove(LongClickMenuItem.edit);
|
||||
result.remove(LongClickMenuItem.remove);
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(Locator.getInstance().getEngine().getVarsRegistry().getDescription(item.getName()))) {
|
||||
result.remove(LongClickMenuItem.copy_description);
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(item.getValue())) {
|
||||
result.remove(LongClickMenuItem.copy_value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected MathEntityDescriptionGetter getDescriptionGetter() {
|
||||
return new MathEntityDescriptionGetterImpl(Locator.getInstance().getEngine().getVarsRegistry());
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public void addVarButtonClickHandler(@NotNull View v) {
|
||||
VarEditDialogFragment.showDialog(VarEditDialogFragment.Input.newInstance(), this.getActivity().getSupportFragmentManager());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<IConstant> getMathEntities() {
|
||||
final List<IConstant> result = new ArrayList<IConstant>(Locator.getInstance().getEngine().getVarsRegistry().getEntities());
|
||||
|
||||
CollectionsUtils.removeAll(result, new JPredicate<IConstant>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable IConstant var) {
|
||||
return var != null && CollectionsUtils.contains(var.getName(), MathType.INFINITY_JSCL, MathType.NAN);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getMathEntityCategory(@NotNull IConstant var) {
|
||||
return Locator.getInstance().getEngine().getVarsRegistry().getCategory(var);
|
||||
}
|
||||
|
||||
public static boolean isValidValue(@NotNull String value) {
|
||||
try {
|
||||
final PreparedExpression expression = ToJsclTextProcessor.getInstance().process(value);
|
||||
final List<IConstant> constants = expression.getUndefinedVars();
|
||||
return constants.isEmpty();
|
||||
} catch (RuntimeException e) {
|
||||
return true;
|
||||
} catch (CalculatorParseException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* MENU
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.vars_menu, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
boolean result;
|
||||
|
||||
switch (item.getItemId()) {
|
||||
case R.id.var_menu_add_var:
|
||||
VarEditDialogFragment.showDialog(VarEditDialogFragment.Input.newInstance(), this.getActivity().getSupportFragmentManager());
|
||||
result = true;
|
||||
break;
|
||||
default:
|
||||
result = super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
super.onCalculatorEvent(calculatorEventData, calculatorEventType, data);
|
||||
|
||||
switch (calculatorEventType) {
|
||||
case constant_added:
|
||||
processConstantAdded((IConstant) data);
|
||||
break;
|
||||
|
||||
case constant_changed:
|
||||
processConstantChanged((Change<IConstant>) data);
|
||||
break;
|
||||
|
||||
case constant_removed:
|
||||
processConstantRemoved((IConstant) data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void processConstantRemoved(@NotNull final IConstant constant) {
|
||||
if (this.isInCategory(constant)) {
|
||||
getUiHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
removeFromAdapter(constant);
|
||||
notifyAdapter();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void processConstantChanged(@NotNull final Change<IConstant> change) {
|
||||
final IConstant newConstant = change.getNewValue();
|
||||
if (this.isInCategory(newConstant)) {
|
||||
getUiHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
removeFromAdapter(change.getOldValue());
|
||||
addToAdapter(newConstant);
|
||||
sort();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void processConstantAdded(@NotNull final IConstant constant) {
|
||||
if (this.isInCategory(constant)) {
|
||||
getUiHandler().post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
addToAdapter(constant);
|
||||
sort();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private static enum LongClickMenuItem implements LabeledMenuItem<IConstant> {
|
||||
use(R.string.c_use) {
|
||||
@Override
|
||||
public void onClick(@NotNull IConstant data, @NotNull Context context) {
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.use_constant, data);
|
||||
}
|
||||
},
|
||||
|
||||
edit(R.string.c_edit) {
|
||||
@Override
|
||||
public void onClick(@NotNull IConstant constant, @NotNull Context context) {
|
||||
VarEditDialogFragment.showDialog(VarEditDialogFragment.Input.newFromConstant(constant), ((SherlockFragmentActivity) context).getSupportFragmentManager());
|
||||
}
|
||||
},
|
||||
|
||||
remove(R.string.c_remove) {
|
||||
@Override
|
||||
public void onClick(@NotNull IConstant constant, @NotNull Context context) {
|
||||
MathEntityRemover.newConstantRemover(constant, null, context, context).showConfirmationDialog();
|
||||
}
|
||||
},
|
||||
|
||||
copy_value(R.string.c_copy_value) {
|
||||
@Override
|
||||
public void onClick(@NotNull IConstant data, @NotNull Context context) {
|
||||
final String text = data.getValue();
|
||||
if (!StringUtils.isEmpty(text)) {
|
||||
assert text != null;
|
||||
Locator.getInstance().getClipboard().setText(text);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
copy_description(R.string.c_copy_description) {
|
||||
@Override
|
||||
public void onClick(@NotNull IConstant data, @NotNull Context context) {
|
||||
final String text = Locator.getInstance().getEngine().getVarsRegistry().getDescription(data.getName());
|
||||
if (!StringUtils.isEmpty(text)) {
|
||||
assert text != null;
|
||||
Locator.getInstance().getClipboard().setText(text);
|
||||
}
|
||||
}
|
||||
};
|
||||
private final int captionId;
|
||||
|
||||
LongClickMenuItem(int captionId) {
|
||||
this.captionId = captionId;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getCaption(@NotNull Context context) {
|
||||
return context.getString(captionId);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* 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.math.edit;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import jscl.math.function.Function;
|
||||
import jscl.math.function.IConstant;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.CalculatorEventType;
|
||||
import org.solovyev.android.calculator.Locator;
|
||||
import org.solovyev.android.calculator.CalculatorMathRegistry;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.common.math.MathEntity;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/22/11
|
||||
* Time: 9:36 PM
|
||||
*/
|
||||
public class MathEntityRemover<T extends MathEntity> implements View.OnClickListener, DialogInterface.OnClickListener {
|
||||
|
||||
@NotNull
|
||||
private final T mathEntity;
|
||||
|
||||
@Nullable
|
||||
private final DialogInterface.OnClickListener callbackOnCancel;
|
||||
|
||||
private final boolean confirmed;
|
||||
|
||||
@NotNull
|
||||
private final CalculatorMathRegistry<? super T> varsRegistry;
|
||||
|
||||
@NotNull
|
||||
private Context context;
|
||||
|
||||
@NotNull
|
||||
private final Object source;
|
||||
|
||||
@NotNull
|
||||
private final Params params;
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTRUCTORS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private MathEntityRemover(@NotNull T mathEntity,
|
||||
@Nullable DialogInterface.OnClickListener callbackOnCancel,
|
||||
boolean confirmed,
|
||||
@NotNull CalculatorMathRegistry<? super T> varsRegistry,
|
||||
@NotNull Context context,
|
||||
@NotNull Object source,
|
||||
@NotNull Params params) {
|
||||
this.mathEntity = mathEntity;
|
||||
this.callbackOnCancel = callbackOnCancel;
|
||||
this.confirmed = confirmed;
|
||||
this.varsRegistry = varsRegistry;
|
||||
this.context = context;
|
||||
this.source = source;
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public static MathEntityRemover<IConstant> newConstantRemover(@NotNull IConstant constant,
|
||||
@Nullable DialogInterface.OnClickListener callbackOnCancel,
|
||||
@NotNull Context context,
|
||||
@NotNull Object source) {
|
||||
return new MathEntityRemover<IConstant>(constant, callbackOnCancel, false, Locator.getInstance().getEngine().getVarsRegistry(), context, source, Params.newConstantInstance());
|
||||
}
|
||||
|
||||
public static MathEntityRemover<Function> newFunctionRemover(@NotNull Function function,
|
||||
@Nullable DialogInterface.OnClickListener callbackOnCancel,
|
||||
@NotNull Context context,
|
||||
@NotNull Object source) {
|
||||
return new MathEntityRemover<Function>(function, callbackOnCancel, false, Locator.getInstance().getEngine().getFunctionsRegistry(), context, source, Params.newFunctionInstance());
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* METHODS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
|
||||
public void showConfirmationDialog() {
|
||||
final TextView question = new TextView(context);
|
||||
question.setText(String.format(context.getString(params.getRemovalConfirmationQuestionResId()), mathEntity.getName()));
|
||||
question.setPadding(6, 6, 6, 6);
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context)
|
||||
.setCancelable(true)
|
||||
.setView(question)
|
||||
.setTitle(params.getRemovalConfirmationTitleResId())
|
||||
.setNegativeButton(R.string.c_no, callbackOnCancel)
|
||||
.setPositiveButton(R.string.c_yes, new MathEntityRemover<T>(mathEntity, callbackOnCancel, true, varsRegistry, context, source, params));
|
||||
|
||||
builder.create().show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(@Nullable View v) {
|
||||
if (!confirmed) {
|
||||
showConfirmationDialog();
|
||||
} else {
|
||||
varsRegistry.remove(mathEntity);
|
||||
varsRegistry.save();
|
||||
|
||||
Locator.getInstance().getCalculator().fireCalculatorEvent(params.getCalculatorEventType(), mathEntity, source);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
onClick(null);
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private static final class Params {
|
||||
|
||||
private int removalConfirmationTitleResId;
|
||||
|
||||
private int removalConfirmationQuestionResId;
|
||||
|
||||
private CalculatorEventType calculatorEventType;
|
||||
|
||||
private Params() {
|
||||
}
|
||||
|
||||
public int getRemovalConfirmationTitleResId() {
|
||||
return removalConfirmationTitleResId;
|
||||
}
|
||||
|
||||
public int getRemovalConfirmationQuestionResId() {
|
||||
return removalConfirmationQuestionResId;
|
||||
}
|
||||
|
||||
public CalculatorEventType getCalculatorEventType() {
|
||||
return calculatorEventType;
|
||||
}
|
||||
|
||||
private static <T extends MathEntity> Params newConstantInstance() {
|
||||
final Params result = new Params();
|
||||
result.removalConfirmationTitleResId = R.string.removal_confirmation;
|
||||
result.removalConfirmationQuestionResId = R.string.c_var_removal_confirmation_question;
|
||||
result.calculatorEventType = CalculatorEventType.constant_removed;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static <T extends MathEntity> Params newFunctionInstance() {
|
||||
final Params result = new Params();
|
||||
result.removalConfirmationTitleResId = R.string.removal_confirmation;
|
||||
result.removalConfirmationQuestionResId = R.string.function_removal_confirmation_question;
|
||||
result.calculatorEventType = CalculatorEventType.function_removed;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,220 @@
|
||||
package org.solovyev.android.calculator.math.edit;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
import jscl.math.function.IConstant;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.model.Var;
|
||||
import org.solovyev.android.sherlock.AndroidSherlockUtils;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 01.10.12
|
||||
* Time: 17:41
|
||||
*/
|
||||
public class VarEditDialogFragment extends DialogFragment implements CalculatorEventListener {
|
||||
|
||||
@NotNull
|
||||
private final Input input;
|
||||
|
||||
public VarEditDialogFragment() {
|
||||
this(Input.newInstance());
|
||||
}
|
||||
|
||||
public VarEditDialogFragment(@NotNull Input input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.var_edit, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
Locator.getInstance().getCalculator().addCalculatorEventListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
Locator.getInstance().getCalculator().removeCalculatorEventListener(this);
|
||||
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NotNull View root, Bundle savedInstanceState) {
|
||||
super.onViewCreated(root, savedInstanceState);
|
||||
|
||||
final String errorMsg = this.getString(R.string.c_char_is_not_accepted);
|
||||
|
||||
final EditText editName = (EditText) root.findViewById(R.id.var_edit_name);
|
||||
editName.setText(input.getName());
|
||||
editName.addTextChangedListener(new TextWatcher() {
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char c = s.charAt(i);
|
||||
if (!AbstractMathEntityListFragment.acceptableChars.contains(c)) {
|
||||
s.delete(i, i + 1);
|
||||
Toast.makeText(getActivity(), String.format(errorMsg, c), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// show soft keyboard automatically
|
||||
editName.requestFocus();
|
||||
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
|
||||
|
||||
final EditText editValue = (EditText) root.findViewById(R.id.var_edit_value);
|
||||
editValue.setText(input.getValue());
|
||||
|
||||
final EditText editDescription = (EditText) root.findViewById(R.id.var_edit_description);
|
||||
editDescription.setText(input.getDescription());
|
||||
|
||||
final Var.Builder varBuilder;
|
||||
final IConstant constant = input.getConstant();
|
||||
if (constant != null) {
|
||||
varBuilder = new Var.Builder(constant);
|
||||
} else {
|
||||
varBuilder = new Var.Builder();
|
||||
}
|
||||
|
||||
root.findViewById(R.id.cancel_button).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
root.findViewById(R.id.save_button).setOnClickListener(new VarEditorSaver<IConstant>(varBuilder, constant, root, Locator.getInstance().getEngine().getVarsRegistry(), this));
|
||||
|
||||
if ( constant == null ) {
|
||||
// CREATE MODE
|
||||
getDialog().setTitle(R.string.c_var_create_var);
|
||||
|
||||
root.findViewById(R.id.remove_button).setVisibility(View.GONE);
|
||||
} else {
|
||||
// EDIT MODE
|
||||
getDialog().setTitle(R.string.c_var_edit_var);
|
||||
|
||||
root.findViewById(R.id.remove_button).setOnClickListener(MathEntityRemover.newConstantRemover(constant, null, getActivity(), VarEditDialogFragment.this));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
|
||||
switch (calculatorEventType) {
|
||||
case constant_removed:
|
||||
case constant_added:
|
||||
case constant_changed:
|
||||
if ( calculatorEventData.getSource() == this ) {
|
||||
dismiss();
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public static void showDialog(@NotNull Input input, @NotNull FragmentManager fm) {
|
||||
AndroidSherlockUtils.showDialog(new VarEditDialogFragment(input), "constant-editor", fm);
|
||||
}
|
||||
|
||||
public static class Input {
|
||||
|
||||
@Nullable
|
||||
private IConstant constant;
|
||||
|
||||
@Nullable
|
||||
private String name;
|
||||
|
||||
@Nullable
|
||||
private String value;
|
||||
|
||||
@Nullable
|
||||
private String description;
|
||||
|
||||
private Input() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Input newInstance() {
|
||||
return new Input();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Input newFromConstant(@NotNull IConstant constant) {
|
||||
final Input result = new Input();
|
||||
result.constant = constant;
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Input newFromValue(@Nullable String value) {
|
||||
final Input result = new Input();
|
||||
result.value = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Input newInstance(@Nullable IConstant constant, @Nullable String name, @Nullable String value, @Nullable String description) {
|
||||
final Input result = new Input();
|
||||
result.constant = constant;
|
||||
result.name = name;
|
||||
result.value = value;
|
||||
result.description = description;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IConstant getConstant() {
|
||||
return constant;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getName() {
|
||||
return name == null ? (constant == null ? null : constant.getName()) : name;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getValue() {
|
||||
return value == null ? (constant == null ? null : constant.getValue()) : value;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getDescription() {
|
||||
return description == null ? (constant == null ? null : constant.getDescription()) : description;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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.math.edit;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import jscl.text.Identifier;
|
||||
import jscl.text.MutableInt;
|
||||
import jscl.text.ParseException;
|
||||
import jscl.text.Parser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.Locator;
|
||||
import org.solovyev.android.calculator.CalculatorMathRegistry;
|
||||
import org.solovyev.android.calculator.CalculatorVarsRegistry;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.calculator.math.MathType;
|
||||
import org.solovyev.android.calculator.model.MathEntityBuilder;
|
||||
import org.solovyev.common.math.MathEntity;
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/22/11
|
||||
* Time: 9:52 PM
|
||||
*/
|
||||
public class VarEditorSaver<T extends MathEntity> implements View.OnClickListener {
|
||||
|
||||
@NotNull
|
||||
private final MathEntityBuilder<? extends T> varBuilder;
|
||||
|
||||
@Nullable
|
||||
private final T editedInstance;
|
||||
|
||||
@NotNull
|
||||
private final CalculatorMathRegistry<T> mathRegistry;
|
||||
|
||||
@NotNull
|
||||
private final Object source;
|
||||
|
||||
@NotNull
|
||||
private View editView;
|
||||
|
||||
public VarEditorSaver(@NotNull MathEntityBuilder<? extends T> varBuilder,
|
||||
@Nullable T editedInstance,
|
||||
@NotNull View editView,
|
||||
@NotNull CalculatorMathRegistry<T> mathRegistry,
|
||||
@NotNull Object source) {
|
||||
this.varBuilder = varBuilder;
|
||||
this.editedInstance = editedInstance;
|
||||
this.editView = editView;
|
||||
this.mathRegistry = mathRegistry;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final Integer error;
|
||||
|
||||
final EditText editName = (EditText) editView.findViewById(R.id.var_edit_name);
|
||||
String name = editName.getText().toString();
|
||||
|
||||
final EditText editValue = (EditText) editView.findViewById(R.id.var_edit_value);
|
||||
String value = editValue.getText().toString();
|
||||
|
||||
final EditText editDescription = (EditText) editView.findViewById(R.id.var_edit_description);
|
||||
String description = editDescription.getText().toString();
|
||||
|
||||
if (isValidName(name)) {
|
||||
|
||||
boolean canBeSaved = false;
|
||||
|
||||
final T entityFromRegistry = mathRegistry.get(name);
|
||||
if (entityFromRegistry == null) {
|
||||
canBeSaved = true;
|
||||
} else if (editedInstance != null && entityFromRegistry.getId().equals(editedInstance.getId())) {
|
||||
canBeSaved = true;
|
||||
}
|
||||
|
||||
if (canBeSaved) {
|
||||
final MathType.Result mathType = MathType.getType(name, 0, false);
|
||||
|
||||
if (mathType.getMathType() == MathType.text || mathType.getMathType() == MathType.constant) {
|
||||
|
||||
if (StringUtils.isEmpty(value)) {
|
||||
// value is empty => undefined variable
|
||||
varBuilder.setName(name);
|
||||
varBuilder.setDescription(description);
|
||||
varBuilder.setValue(null);
|
||||
error = null;
|
||||
} else {
|
||||
// value is not empty => must be a number
|
||||
boolean valid = CalculatorVarsFragment.isValidValue(value);
|
||||
|
||||
if (valid) {
|
||||
varBuilder.setName(name);
|
||||
varBuilder.setDescription(description);
|
||||
varBuilder.setValue(value);
|
||||
error = null;
|
||||
} else {
|
||||
error = R.string.c_value_is_not_a_number;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
error = R.string.c_var_name_clashes;
|
||||
}
|
||||
} else {
|
||||
error = R.string.c_var_already_exists;
|
||||
}
|
||||
} else {
|
||||
error = R.string.c_name_is_not_valid;
|
||||
}
|
||||
|
||||
if (error != null) {
|
||||
Locator.getInstance().getNotifier().showMessage(error, MessageType.error);
|
||||
} else {
|
||||
CalculatorVarsRegistry.saveVariable(mathRegistry, varBuilder, editedInstance, source, true);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isValidName(@Nullable String name) {
|
||||
boolean result = false;
|
||||
|
||||
if (!StringUtils.isEmpty(name)) {
|
||||
try {
|
||||
assert name != null;
|
||||
Identifier.parser.parse(Parser.Parameters.newInstance(name, new MutableInt(0), Locator.getInstance().getEngine().getMathEngine0()), null);
|
||||
result = true;
|
||||
} catch (ParseException e) {
|
||||
// not valid name;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
package org.solovyev.android.calculator.model;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/25/11
|
||||
* Time: 1:40 PM
|
||||
*/
|
||||
public final class Messages {
|
||||
|
||||
|
||||
// not intended for instantiation
|
||||
private Messages() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
/** Arithmetic error occurred: {0} */
|
||||
public static final String msg_1 = "msg_1";
|
||||
|
||||
/** Too complex expression */
|
||||
public static final String msg_2 = "msg_2";
|
||||
|
||||
/** Too long execution time - check the expression */
|
||||
public static final String msg_3 = "msg_3";
|
||||
|
||||
/** Evaluation was cancelled */
|
||||
public static final String msg_4 = "msg_4";
|
||||
|
||||
/** No parameters are specified for function: {0} */
|
||||
public static final String msg_5 = "msg_5";
|
||||
|
||||
/** Infinite loop is detected in expression */
|
||||
public static final String msg_6 = "msg_6";
|
||||
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
package org.solovyev.android.calculator.plot;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.CalculatorFragmentActivity;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.calculator.about.CalculatorFragmentType;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/30/12
|
||||
* Time: 4:56 PM
|
||||
*/
|
||||
public class CalculatorPlotActivity extends CalculatorFragmentActivity {
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final Intent intent = getIntent();
|
||||
|
||||
final Bundle arguments;
|
||||
if (intent != null) {
|
||||
arguments = intent.getExtras();
|
||||
} else {
|
||||
arguments = null;
|
||||
}
|
||||
|
||||
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
|
||||
getActivityHelper().setFragment(this, CalculatorFragmentType.plotter, arguments, R.id.main_layout);
|
||||
}
|
||||
}
|
@@ -0,0 +1,582 @@
|
||||
/*
|
||||
* 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.plot;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import com.actionbarsherlock.view.Menu;
|
||||
import com.actionbarsherlock.view.MenuInflater;
|
||||
import com.actionbarsherlock.view.MenuItem;
|
||||
import jscl.math.Expression;
|
||||
import jscl.math.Generic;
|
||||
import jscl.math.function.Constant;
|
||||
import jscl.text.ParseException;
|
||||
import org.achartengine.GraphicalView;
|
||||
import org.achartengine.chart.XYChart;
|
||||
import org.achartengine.model.XYSeries;
|
||||
import org.achartengine.renderer.XYMultipleSeriesRenderer;
|
||||
import org.achartengine.tools.PanListener;
|
||||
import org.achartengine.tools.ZoomEvent;
|
||||
import org.achartengine.tools.ZoomListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.menu.ActivityMenu;
|
||||
import org.solovyev.android.menu.IdentifiableMenuItem;
|
||||
import org.solovyev.android.menu.ListActivityMenu;
|
||||
import org.solovyev.android.sherlock.menu.SherlockMenuHelper;
|
||||
import org.solovyev.common.MutableObject;
|
||||
import org.solovyev.common.collections.CollectionsUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/1/11
|
||||
* Time: 12:40 AM
|
||||
*/
|
||||
public class CalculatorPlotFragment extends CalculatorFragment implements CalculatorEventListener {
|
||||
|
||||
private static final String TAG = CalculatorPlotFragment.class.getSimpleName();
|
||||
|
||||
private static final int DEFAULT_MIN_NUMBER = -10;
|
||||
|
||||
private static final int DEFAULT_MAX_NUMBER = 10;
|
||||
|
||||
public static final String INPUT = "plotter_input";
|
||||
private static final String PLOT_BOUNDARIES = "plot_boundaries";
|
||||
|
||||
public static final long EVAL_DELAY_MILLIS = 200;
|
||||
|
||||
@Nullable
|
||||
private XYChart chart;
|
||||
|
||||
/**
|
||||
* The encapsulated graphical view.
|
||||
*/
|
||||
@Nullable
|
||||
private GraphicalView graphicalView;
|
||||
|
||||
// thread which calculated data for graph view
|
||||
@NotNull
|
||||
private final Executor plotExecutor = Executors.newSingleThreadExecutor();
|
||||
|
||||
// thread for applying UI changes
|
||||
@NotNull
|
||||
private final Handler uiHandler = new Handler();
|
||||
|
||||
@NotNull
|
||||
private PreparedInput preparedInput;
|
||||
|
||||
@Nullable
|
||||
private Input input;
|
||||
|
||||
@NotNull
|
||||
private final CalculatorEventHolder lastEventHolder = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId());
|
||||
|
||||
private int bgColor;
|
||||
|
||||
@NotNull
|
||||
private ActivityMenu<Menu, MenuItem> fragmentMenu = ListActivityMenu.fromResource(R.menu.plot_menu, PlotMenu.class, SherlockMenuHelper.getInstance());
|
||||
|
||||
public CalculatorPlotFragment() {
|
||||
super(CalculatorApplication.getInstance().createFragmentHelper(R.layout.plot_fragment, R.string.c_graph, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final Bundle arguments = getArguments();
|
||||
|
||||
if (arguments != null) {
|
||||
input = (Input) arguments.getSerializable(INPUT);
|
||||
}
|
||||
|
||||
if (input == null) {
|
||||
this.bgColor = getResources().getColor(R.color.cpp_pane_background);
|
||||
} else {
|
||||
this.bgColor = getResources().getColor(android.R.color.transparent);
|
||||
}
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PreparedInput prepareInputFromDisplay(@NotNull CalculatorDisplayViewState displayState, @Nullable Bundle savedInstanceState) {
|
||||
try {
|
||||
if (displayState.isValid() && displayState.getResult() != null) {
|
||||
final Generic expression = displayState.getResult();
|
||||
if (CalculatorUtils.isPlotPossible(expression, displayState.getOperation())) {
|
||||
final Constant constant = CollectionsUtils.getFirstCollectionElement(CalculatorUtils.getNotSystemConstants(expression));
|
||||
|
||||
final Input input = new Input(expression.toString(), constant.getName());
|
||||
return prepareInput(input, false, savedInstanceState);
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG, e.getLocalizedMessage(), e);
|
||||
}
|
||||
|
||||
return PreparedInput.newErrorInstance(false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PreparedInput prepareInput(@NotNull Input input, boolean fromInputArgs, @Nullable Bundle savedInstanceState) {
|
||||
PreparedInput result;
|
||||
|
||||
try {
|
||||
final PreparedExpression preparedExpression = ToJsclTextProcessor.getInstance().process(input.getExpression());
|
||||
final Generic expression = Expression.valueOf(preparedExpression.getExpression());
|
||||
final Constant variable = new Constant(input.getVariableName());
|
||||
|
||||
PlotBoundaries plotBoundaries = null;
|
||||
if ( savedInstanceState != null ) {
|
||||
plotBoundaries = (PlotBoundaries)savedInstanceState.getSerializable(PLOT_BOUNDARIES);
|
||||
}
|
||||
|
||||
result = PreparedInput.newInstance(input, expression, variable, fromInputArgs, plotBoundaries);
|
||||
} catch (ParseException e) {
|
||||
result = PreparedInput.newErrorInstance(fromInputArgs);
|
||||
Locator.getInstance().getNotifier().showMessage(e);
|
||||
} catch (CalculatorParseException e) {
|
||||
result = PreparedInput.newErrorInstance(fromInputArgs);
|
||||
Locator.getInstance().getNotifier().showMessage(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void createChart() {
|
||||
if (!preparedInput.isError()) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
|
||||
final Boolean interpolate = CalculatorPreferences.Graph.interpolate.getPreference(preferences);
|
||||
final GraphLineColor realLineColor = CalculatorPreferences.Graph.lineColorReal.getPreference(preferences);
|
||||
final GraphLineColor imagLineColor = CalculatorPreferences.Graph.lineColorImag.getPreference(preferences);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
try {
|
||||
this.chart = PlotUtils.prepareChart(getMinValue(null), getMaxValue(null), preparedInput.getExpression(), preparedInput.getVariable(), bgColor, interpolate, realLineColor.getColor(), imagLineColor.getColor());
|
||||
} catch (ArithmeticException e) {
|
||||
PlotUtils.handleArithmeticException(e, CalculatorPlotFragment.this);
|
||||
}
|
||||
} else {
|
||||
onError();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
if (input == null) {
|
||||
this.preparedInput = prepareInputFromDisplay(Locator.getInstance().getDisplay().getViewState(), savedInstanceState);
|
||||
} else {
|
||||
this.preparedInput = prepareInput(input, true, savedInstanceState);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle out) {
|
||||
super.onSaveInstanceState(out);
|
||||
|
||||
if (chart != null) {
|
||||
out.putSerializable(PLOT_BOUNDARIES, new PlotBoundaries(chart.getRenderer()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
createChart();
|
||||
createGraphicalView(getView(), this.preparedInput.getPlotBoundaries());
|
||||
}
|
||||
|
||||
private void createGraphicalView(@NotNull View root, @Nullable PlotBoundaries plotBoundaries) {
|
||||
final ViewGroup graphContainer = (ViewGroup) root.findViewById(R.id.main_fragment_layout);
|
||||
|
||||
if (graphicalView != null) {
|
||||
graphContainer.removeView(graphicalView);
|
||||
}
|
||||
|
||||
if (!preparedInput.isError()) {
|
||||
final XYChart chart = this.chart;
|
||||
assert chart != null;
|
||||
|
||||
double minValue = getMinValue(plotBoundaries);
|
||||
double maxValue = getMaxValue(plotBoundaries);
|
||||
|
||||
// reverting boundaries (as in prepareChart() we add some cached values )
|
||||
double minX = Double.MAX_VALUE;
|
||||
double minY = Double.MAX_VALUE;
|
||||
|
||||
double maxX = Double.MIN_VALUE;
|
||||
double maxY = Double.MIN_VALUE;
|
||||
|
||||
for (XYSeries series : chart.getDataset().getSeries()) {
|
||||
minX = Math.min(minX, series.getMinX());
|
||||
minY = Math.min(minY, series.getMinY());
|
||||
maxX = Math.max(maxX, series.getMaxX());
|
||||
maxY = Math.max(maxY, series.getMaxY());
|
||||
}
|
||||
|
||||
if (plotBoundaries == null) {
|
||||
chart.getRenderer().setXAxisMin(Math.max(minX, minValue));
|
||||
chart.getRenderer().setYAxisMin(Math.max(minY, minValue));
|
||||
chart.getRenderer().setXAxisMax(Math.min(maxX, maxValue));
|
||||
chart.getRenderer().setYAxisMax(Math.min(maxY, maxValue));
|
||||
} else {
|
||||
chart.getRenderer().setXAxisMin(plotBoundaries.xMin);
|
||||
chart.getRenderer().setYAxisMin(plotBoundaries.yMin);
|
||||
chart.getRenderer().setXAxisMax(plotBoundaries.xMax);
|
||||
chart.getRenderer().setYAxisMax(plotBoundaries.yMax);
|
||||
}
|
||||
|
||||
graphicalView = new GraphicalView(this.getActivity(), chart);
|
||||
graphicalView.setBackgroundColor(this.bgColor);
|
||||
|
||||
graphicalView.addZoomListener(new ZoomListener() {
|
||||
@Override
|
||||
public void zoomApplied(ZoomEvent e) {
|
||||
updateDataSets(chart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zoomReset() {
|
||||
updateDataSets(chart);
|
||||
}
|
||||
}, true, true);
|
||||
|
||||
graphicalView.addPanListener(new PanListener() {
|
||||
@Override
|
||||
public void panApplied() {
|
||||
updateDataSets(chart);
|
||||
}
|
||||
|
||||
});
|
||||
graphContainer.addView(graphicalView);
|
||||
|
||||
updateDataSets(chart, 50);
|
||||
} else {
|
||||
graphicalView = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private double getMaxValue(@Nullable PlotBoundaries plotBoundaries) {
|
||||
return plotBoundaries == null ? DEFAULT_MAX_NUMBER : plotBoundaries.xMax;
|
||||
}
|
||||
|
||||
private double getMinValue(@Nullable PlotBoundaries plotBoundaries) {
|
||||
return plotBoundaries == null ? DEFAULT_MIN_NUMBER : plotBoundaries.xMin;
|
||||
}
|
||||
|
||||
|
||||
private void updateDataSets(@NotNull final XYChart chart) {
|
||||
updateDataSets(chart, EVAL_DELAY_MILLIS);
|
||||
}
|
||||
|
||||
private void updateDataSets(@NotNull final XYChart chart, long millisToWait) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
|
||||
final GraphLineColor imagLineColor = CalculatorPreferences.Graph.lineColorImag.getPreference(preferences);
|
||||
|
||||
final Generic expression = preparedInput.getExpression();
|
||||
final Constant variable = preparedInput.getVariable();
|
||||
|
||||
if (expression != null && variable != null) {
|
||||
pendingOperation.setObject(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// allow only one runner at one time
|
||||
synchronized (pendingOperation) {
|
||||
//lock all operations with history
|
||||
if (pendingOperation.getObject() == this) {
|
||||
|
||||
plotExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final XYMultipleSeriesRenderer dr = chart.getRenderer();
|
||||
|
||||
final MyXYSeries realSeries = (MyXYSeries) chart.getDataset().getSeriesAt(0);
|
||||
|
||||
final MyXYSeries imagSeries;
|
||||
if (chart.getDataset().getSeriesCount() > 1) {
|
||||
imagSeries = (MyXYSeries) chart.getDataset().getSeriesAt(1);
|
||||
} else {
|
||||
imagSeries = new MyXYSeries(PlotUtils.getImagFunctionName(variable), PlotUtils.DEFAULT_NUMBER_OF_STEPS * 2);
|
||||
}
|
||||
|
||||
try {
|
||||
if (PlotUtils.addXY(dr.getXAxisMin(), dr.getXAxisMax(), expression, variable, realSeries, imagSeries, true, PlotUtils.DEFAULT_NUMBER_OF_STEPS)) {
|
||||
if (chart.getDataset().getSeriesCount() <= 1) {
|
||||
chart.getDataset().addSeries(imagSeries);
|
||||
chart.getRenderer().addSeriesRenderer(PlotUtils.createImagRenderer(imagLineColor.getColor()));
|
||||
}
|
||||
}
|
||||
} catch (ArithmeticException e) {
|
||||
PlotUtils.handleArithmeticException(e, CalculatorPlotFragment.this);
|
||||
}
|
||||
|
||||
uiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
graphicalView.repaint();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
uiHandler.postDelayed(pendingOperation.getObject(), millisToWait);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private final MutableObject<Runnable> pendingOperation = new MutableObject<Runnable>();
|
||||
|
||||
@Override
|
||||
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable final Object data) {
|
||||
if (calculatorEventType.isOfType(CalculatorEventType.display_state_changed)) {
|
||||
if (!preparedInput.isFromInputArgs()) {
|
||||
|
||||
final CalculatorEventHolder.Result result = this.lastEventHolder.apply(calculatorEventData);
|
||||
if (result.isNewAfter()) {
|
||||
this.preparedInput = prepareInputFromDisplay(((CalculatorDisplayChangeEventData) data).getNewValue(), null);
|
||||
createChart();
|
||||
|
||||
uiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final View view = getView();
|
||||
if (view != null) {
|
||||
createGraphicalView(view, preparedInput.getPlotBoundaries());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* public void zoomInClickHandler(@NotNull View v) {
|
||||
this.graphicalView.zoomIn();
|
||||
}
|
||||
|
||||
public void zoomOutClickHandler(@NotNull View v) {
|
||||
this.graphicalView.zoomOut();
|
||||
}*/
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* MENU
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
|
||||
final FragmentActivity activity = this.getActivity();
|
||||
if (activity != null) {
|
||||
fragmentMenu.onCreateOptionsMenu(activity, menu);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
|
||||
final FragmentActivity activity = this.getActivity();
|
||||
if (activity != null) {
|
||||
fragmentMenu.onPrepareOptionsMenu(activity, menu);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
return super.onOptionsItemSelected(item) || fragmentMenu.onOptionsItemSelected(this.getActivity(), item);
|
||||
}
|
||||
|
||||
public void onError() {
|
||||
this.chart = null;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private static enum PlotMenu implements IdentifiableMenuItem<MenuItem> {
|
||||
|
||||
preferences(R.id.menu_plot_settings) {
|
||||
@Override
|
||||
public void onClick(@NotNull MenuItem data, @NotNull Context context) {
|
||||
context.startActivity(new Intent(context, CalculatorPlotPreferenceActivity.class));
|
||||
}
|
||||
};
|
||||
|
||||
private final int itemId;
|
||||
|
||||
private PlotMenu(int itemId) {
|
||||
this.itemId = itemId;
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Integer getItemId() {
|
||||
return itemId;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class PlotBoundaries implements Serializable {
|
||||
|
||||
private double xMin;
|
||||
private double xMax;
|
||||
private double yMin;
|
||||
private double yMax;
|
||||
|
||||
public PlotBoundaries() {
|
||||
}
|
||||
|
||||
public PlotBoundaries(@NotNull XYMultipleSeriesRenderer renderer) {
|
||||
this.xMin = renderer.getXAxisMin();
|
||||
this.yMin = renderer.getYAxisMin();
|
||||
this.xMax = renderer.getXAxisMax();
|
||||
this.yMax = renderer.getYAxisMax();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PlotBoundaries{" +
|
||||
"yMax=" + yMax +
|
||||
", yMin=" + yMin +
|
||||
", xMax=" + xMax +
|
||||
", xMin=" + xMin +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
public static class PreparedInput {
|
||||
|
||||
@Nullable
|
||||
private Input input;
|
||||
|
||||
@Nullable
|
||||
private Generic expression;
|
||||
|
||||
@Nullable
|
||||
private Constant variable;
|
||||
|
||||
private boolean fromInputArgs;
|
||||
|
||||
@Nullable
|
||||
private PlotBoundaries plotBoundaries = null;
|
||||
|
||||
private PreparedInput() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PreparedInput newInstance(@NotNull Input input, @NotNull Generic expression, @NotNull Constant variable, boolean fromInputArgs, @Nullable PlotBoundaries plotBoundaries) {
|
||||
final PreparedInput result = new PreparedInput();
|
||||
|
||||
result.input = input;
|
||||
result.expression = expression;
|
||||
result.variable = variable;
|
||||
result.fromInputArgs = fromInputArgs;
|
||||
result.plotBoundaries = plotBoundaries;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PreparedInput newErrorInstance(boolean fromInputArgs) {
|
||||
final PreparedInput result = new PreparedInput();
|
||||
|
||||
result.input = null;
|
||||
result.expression = null;
|
||||
result.variable = null;
|
||||
result.fromInputArgs = fromInputArgs;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isFromInputArgs() {
|
||||
return fromInputArgs;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Input getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Generic getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PlotBoundaries getPlotBoundaries() {
|
||||
return plotBoundaries;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Constant getVariable() {
|
||||
return variable;
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return input == null || expression == null || variable == null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Input implements Serializable {
|
||||
|
||||
@NotNull
|
||||
private String expression;
|
||||
|
||||
@NotNull
|
||||
private String variableName;
|
||||
|
||||
public Input(@NotNull String expression, @NotNull String variableName) {
|
||||
this.expression = expression;
|
||||
this.variableName = variableName;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getVariableName() {
|
||||
return variableName;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package org.solovyev.android.calculator.plot;
|
||||
|
||||
import android.os.Bundle;
|
||||
import com.actionbarsherlock.app.SherlockPreferenceActivity;
|
||||
import org.solovyev.android.calculator.R;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/4/12
|
||||
* Time: 9:01 PM
|
||||
*/
|
||||
public class CalculatorPlotPreferenceActivity extends SherlockPreferenceActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
//noinspection deprecation
|
||||
addPreferencesFromResource(R.xml.preferences_plot);
|
||||
}
|
||||
}
|
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* 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.plot;
|
||||
|
||||
import org.achartengine.model.XYSeries;
|
||||
import org.achartengine.util.MathHelper;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/5/11
|
||||
* Time: 8:43 PM
|
||||
*/
|
||||
|
||||
/**
|
||||
* BEST SOLUTION IS TO MODIFY LIBRARY CLASS
|
||||
* NOTE: this class is a copy of XYSeries with some modifications:
|
||||
* 1. Possibility to insert point in th emiddle og the range
|
||||
*/
|
||||
|
||||
public class MyXYSeries extends XYSeries {
|
||||
/**
|
||||
* The series title.
|
||||
*/
|
||||
private String mTitle;
|
||||
/**
|
||||
* A list to contain the values for the X axis.
|
||||
*/
|
||||
private List<Double> mX = new ArrayList<Double>();
|
||||
/**
|
||||
* A list to contain the values for the Y axis.
|
||||
*/
|
||||
private List<Double> mY = new ArrayList<Double>();
|
||||
/**
|
||||
* The minimum value for the X axis.
|
||||
*/
|
||||
private double mMinX = MathHelper.NULL_VALUE;
|
||||
/**
|
||||
* The maximum value for the X axis.
|
||||
*/
|
||||
private double mMaxX = -MathHelper.NULL_VALUE;
|
||||
/**
|
||||
* The minimum value for the Y axis.
|
||||
*/
|
||||
private double mMinY = MathHelper.NULL_VALUE;
|
||||
/**
|
||||
* The maximum value for the Y axis.
|
||||
*/
|
||||
private double mMaxY = -MathHelper.NULL_VALUE;
|
||||
/**
|
||||
* The scale number for this series.
|
||||
*/
|
||||
private int mScaleNumber;
|
||||
|
||||
/**
|
||||
* Builds a new XY series.
|
||||
*
|
||||
* @param title the series title.
|
||||
*/
|
||||
public MyXYSeries(String title) {
|
||||
this(title, 10);
|
||||
}
|
||||
|
||||
public MyXYSeries(String title, int initialCapacity) {
|
||||
super(title, 0);
|
||||
|
||||
this.mX = new ArrayList<Double>(initialCapacity);
|
||||
this.mY = new ArrayList<Double>(initialCapacity);
|
||||
|
||||
mTitle = title;
|
||||
mScaleNumber = 0;
|
||||
|
||||
initRange();
|
||||
}
|
||||
|
||||
public int getScaleNumber() {
|
||||
return mScaleNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the range for both axes.
|
||||
*/
|
||||
private void initRange() {
|
||||
mMinX = MathHelper.NULL_VALUE;
|
||||
mMaxX = -MathHelper.NULL_VALUE;
|
||||
mMinY = MathHelper.NULL_VALUE;
|
||||
mMaxY = -MathHelper.NULL_VALUE;
|
||||
int length = getItemCount();
|
||||
for (int k = 0; k < length; k++) {
|
||||
double x = getX(k);
|
||||
double y = getY(k);
|
||||
updateRange(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the range on both axes.
|
||||
*
|
||||
* @param x the new x value
|
||||
* @param y the new y value
|
||||
*/
|
||||
private void updateRange(double x, double y) {
|
||||
mMinX = Math.min(mMinX, x);
|
||||
mMaxX = Math.max(mMaxX, x);
|
||||
mMinY = Math.min(mMinY, y);
|
||||
mMaxY = Math.max(mMaxY, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the series title.
|
||||
*
|
||||
* @return the series title
|
||||
*/
|
||||
public String getTitle() {
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the series title.
|
||||
*
|
||||
* @param title the series title
|
||||
*/
|
||||
public void setTitle(String title) {
|
||||
mTitle = title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new value to the series.
|
||||
*
|
||||
* @param x the value for the X axis
|
||||
* @param y the value for the Y axis
|
||||
*/
|
||||
public void add(double x, double y) {
|
||||
boolean added = false;
|
||||
for (int i = 0; i < mX.size(); i++ ) {
|
||||
if ( mX.get(i) > x ) {
|
||||
mX.add(i, x);
|
||||
mY.add(i, y);
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !added ) {
|
||||
mX.add(x);
|
||||
mY.add(y);
|
||||
}
|
||||
|
||||
updateRange(x, y);
|
||||
}
|
||||
|
||||
|
||||
public boolean needToAdd(double density, double x) {
|
||||
boolean result = true;
|
||||
|
||||
for (Double x1 : mX) {
|
||||
if (Math.abs(x - x1) < density) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an existing value from the series.
|
||||
*
|
||||
* @param index the index in the series of the value to remove
|
||||
*/
|
||||
public void remove(int index) {
|
||||
double removedX = mX.remove(index);
|
||||
double removedY = mY.remove(index);
|
||||
if (removedX == mMinX || removedX == mMaxX || removedY == mMinY || removedY == mMaxY) {
|
||||
initRange();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all the existing values from the series.
|
||||
*/
|
||||
public void clear() {
|
||||
mX.clear();
|
||||
mY.clear();
|
||||
initRange();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the X axis value at the specified index.
|
||||
*
|
||||
* @param index the index
|
||||
* @return the X value
|
||||
*/
|
||||
public double getX(int index) {
|
||||
return mX.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Y axis value at the specified index.
|
||||
*
|
||||
* @param index the index
|
||||
* @return the Y value
|
||||
*/
|
||||
public double getY(int index) {
|
||||
return mY.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the series item count.
|
||||
*
|
||||
* @return the series item count
|
||||
*/
|
||||
public int getItemCount() {
|
||||
return mX == null ? 0 : mX.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum value on the X axis.
|
||||
*
|
||||
* @return the X axis minimum value
|
||||
*/
|
||||
public double getMinX() {
|
||||
return mMinX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum value on the Y axis.
|
||||
*
|
||||
* @return the Y axis minimum value
|
||||
*/
|
||||
public double getMinY() {
|
||||
return mMinY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum value on the X axis.
|
||||
*
|
||||
* @return the X axis maximum value
|
||||
*/
|
||||
public double getMaxX() {
|
||||
return mMaxX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum value on the Y axis.
|
||||
*
|
||||
* @return the Y axis maximum value
|
||||
*/
|
||||
public double getMaxY() {
|
||||
return mMaxY;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,440 @@
|
||||
/*
|
||||
* 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.plot;
|
||||
|
||||
import jscl.math.Expression;
|
||||
import jscl.math.Generic;
|
||||
import jscl.math.JsclInteger;
|
||||
import jscl.math.NumericWrapper;
|
||||
import jscl.math.function.Constant;
|
||||
import jscl.math.numeric.Complex;
|
||||
import jscl.math.numeric.Numeric;
|
||||
import jscl.math.numeric.Real;
|
||||
import org.achartengine.chart.CubicLineChart;
|
||||
import org.achartengine.chart.PointStyle;
|
||||
import org.achartengine.chart.ScatterChart;
|
||||
import org.achartengine.chart.XYChart;
|
||||
import org.achartengine.model.XYMultipleSeriesDataset;
|
||||
import org.achartengine.renderer.BasicStroke;
|
||||
import org.achartengine.renderer.XYMultipleSeriesRenderer;
|
||||
import org.achartengine.renderer.XYSeriesRenderer;
|
||||
import org.achartengine.util.MathHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.Locator;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/5/11
|
||||
* Time: 8:58 PM
|
||||
*/
|
||||
public final class PlotUtils {
|
||||
|
||||
private static final double MAX_Y_DIFF = 1;
|
||||
private static final double MAX_X_DIFF = 1;
|
||||
static final int DEFAULT_NUMBER_OF_STEPS = 100;
|
||||
|
||||
// not intended for instantiation
|
||||
private PlotUtils() {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
public static boolean addXY(double minValue,
|
||||
double maxValue,
|
||||
@NotNull Generic expression,
|
||||
@NotNull Constant variable,
|
||||
@NotNull MyXYSeries realSeries,
|
||||
@Nullable MyXYSeries imagSeries,
|
||||
boolean addExtra,
|
||||
int numberOfSteps) {
|
||||
|
||||
boolean imagExists = false;
|
||||
|
||||
double min = Math.min(minValue, maxValue);
|
||||
double max = Math.max(minValue, maxValue);
|
||||
double dist = max - min;
|
||||
if (addExtra) {
|
||||
min = min - dist;
|
||||
max = max + dist;
|
||||
}
|
||||
|
||||
final double eps = 0.000000001;
|
||||
|
||||
final double defaultStep = Math.max(dist / numberOfSteps, eps);
|
||||
double step = defaultStep;
|
||||
|
||||
final Point real = new Point();
|
||||
final Point imag = new Point();
|
||||
|
||||
double x = min;
|
||||
|
||||
while (x <= max) {
|
||||
|
||||
boolean needToCalculateRealY = realSeries.needToAdd(step, x);
|
||||
|
||||
if (needToCalculateRealY) {
|
||||
final Complex c = calculatorExpression(expression, variable, x);
|
||||
Double y = prepareY(c.realPart());
|
||||
|
||||
if (y != null) {
|
||||
real.moveToNextPoint(x, y);
|
||||
addSingularityPoint(realSeries, real);
|
||||
realSeries.add(x, y);
|
||||
}
|
||||
|
||||
boolean needToCalculateImagY = imagSeries != null && imagSeries.needToAdd(step, x);
|
||||
if (needToCalculateImagY) {
|
||||
y = prepareY(c.imaginaryPart());
|
||||
if (y != null) {
|
||||
imag.moveToNextPoint(x, y);
|
||||
addSingularityPoint(imagSeries, imag);
|
||||
imagSeries.add(x, y);
|
||||
}
|
||||
if (c.imaginaryPart() != 0d) {
|
||||
imagExists = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
boolean needToCalculateImagY = imagSeries != null && imagSeries.needToAdd(step, x);
|
||||
if (needToCalculateImagY) {
|
||||
final Complex c = calculatorExpression(expression, variable, x);
|
||||
Double y = prepareY(c.imaginaryPart());
|
||||
if (y != null) {
|
||||
imag.moveToNextPoint(x, y);
|
||||
addSingularityPoint(imagSeries, imag);
|
||||
imagSeries.add(x, y);
|
||||
}
|
||||
if (c.imaginaryPart() != 0d) {
|
||||
imagExists = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
step = updateStep(real, step, defaultStep / 2);
|
||||
|
||||
x += step;
|
||||
}
|
||||
|
||||
return imagExists;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static String getImagFunctionName(@NotNull Constant variable) {
|
||||
return "g(" + variable.getName() + ")" + " = " + "Im(ƒ(" + variable.getName() + "))";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getRealFunctionName(@NotNull Generic expression, @NotNull Constant variable) {
|
||||
return "ƒ(" + variable.getName() + ")" + " = " + expression.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static XYChart prepareChart(final double minValue,
|
||||
final double maxValue,
|
||||
@NotNull final Generic expression,
|
||||
@NotNull final Constant variable,
|
||||
int bgColor,
|
||||
boolean interpolate,
|
||||
int realLineColor,
|
||||
int imagLineColor) {
|
||||
final MyXYSeries realSeries = new MyXYSeries(getRealFunctionName(expression, variable), DEFAULT_NUMBER_OF_STEPS * 2);
|
||||
final MyXYSeries imagSeries = new MyXYSeries(getImagFunctionName(variable), DEFAULT_NUMBER_OF_STEPS * 2);
|
||||
|
||||
boolean imagExists = addXY(minValue, maxValue, expression, variable, realSeries, imagSeries, false, DEFAULT_NUMBER_OF_STEPS);
|
||||
|
||||
final XYMultipleSeriesDataset data = new XYMultipleSeriesDataset();
|
||||
data.addSeries(realSeries);
|
||||
if (imagExists) {
|
||||
data.addSeries(imagSeries);
|
||||
}
|
||||
|
||||
final XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
|
||||
renderer.setShowGrid(true);
|
||||
renderer.setXTitle(variable.getName());
|
||||
renderer.setYTitle("f(" + variable.getName() + ")");
|
||||
renderer.setChartTitleTextSize(25);
|
||||
renderer.setAxisTitleTextSize(25);
|
||||
renderer.setLabelsTextSize(25);
|
||||
renderer.setLegendTextSize(25);
|
||||
renderer.setMargins(new int[]{25, 25, 25, 25});
|
||||
renderer.setApplyBackgroundColor(true);
|
||||
renderer.setBackgroundColor(bgColor);
|
||||
renderer.setMarginsColor(bgColor);
|
||||
|
||||
renderer.setZoomEnabled(true);
|
||||
renderer.setZoomButtonsVisible(true);
|
||||
|
||||
renderer.addSeriesRenderer(createCommonRenderer(realLineColor));
|
||||
if (imagExists) {
|
||||
renderer.addSeriesRenderer(createImagRenderer(imagLineColor));
|
||||
}
|
||||
|
||||
if (interpolate) {
|
||||
return new CubicLineChart(data, renderer, 0.1f);
|
||||
} else {
|
||||
return new ScatterChart(data, renderer);
|
||||
}
|
||||
}
|
||||
|
||||
static XYSeriesRenderer createImagRenderer(int color) {
|
||||
final XYSeriesRenderer imagRenderer = createCommonRenderer(color);
|
||||
imagRenderer.setStroke(BasicStroke.DASHED);
|
||||
return imagRenderer;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static XYSeriesRenderer createCommonRenderer(int color) {
|
||||
final XYSeriesRenderer renderer = new XYSeriesRenderer();
|
||||
renderer.setFillPoints(true);
|
||||
renderer.setPointStyle(PointStyle.CIRCLE);
|
||||
renderer.setLineWidth(3);
|
||||
renderer.setColor(color);
|
||||
renderer.setStroke(BasicStroke.SOLID);
|
||||
return renderer;
|
||||
}
|
||||
|
||||
static void handleArithmeticException(@NotNull ArithmeticException e, @NotNull CalculatorPlotFragment calculatorPlotFragment) {
|
||||
String message = e.getLocalizedMessage();
|
||||
if (StringUtils.isEmpty(message)) {
|
||||
message = e.getMessage();
|
||||
}
|
||||
Locator.getInstance().getNotifier().showMessage(R.string.arithmetic_error_while_plot, MessageType.error, Arrays.asList(message));
|
||||
calculatorPlotFragment.onError();
|
||||
}
|
||||
|
||||
private static class Point {
|
||||
private static final double DEFAULT = Double.MIN_VALUE;
|
||||
|
||||
private double x0 = DEFAULT;
|
||||
private double x1 = DEFAULT;
|
||||
private double x2 = DEFAULT;
|
||||
|
||||
private double y0 = DEFAULT;
|
||||
private double y1 = DEFAULT;
|
||||
private double y2 = DEFAULT;
|
||||
|
||||
private Point() {
|
||||
}
|
||||
|
||||
public void moveToNextPoint(double x, double y) {
|
||||
if ( this.x2 == x ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.x0 = this.x1;
|
||||
this.x1 = this.x2;
|
||||
this.x2 = x;
|
||||
|
||||
this.y0 = this.y1;
|
||||
this.y1 = this.y2;
|
||||
this.y2 = y;
|
||||
}
|
||||
|
||||
public boolean isFullyDefined() {
|
||||
return x0 != DEFAULT && x1 != DEFAULT && x2 != DEFAULT && y0 != DEFAULT && y1 != DEFAULT && y2 != DEFAULT;
|
||||
}
|
||||
|
||||
public double getDx2() {
|
||||
return x2 - x1;
|
||||
}
|
||||
|
||||
public double getAbsDx2() {
|
||||
if ( x2 > x1 ) {
|
||||
return Math.abs(x2 - x1);
|
||||
} else {
|
||||
return Math.abs(x1 - x2);
|
||||
}
|
||||
}
|
||||
|
||||
public double getAbsDx1() {
|
||||
if ( x1 > x0 ) {
|
||||
return Math.abs(x1 - x0);
|
||||
} else {
|
||||
return Math.abs(x0 - x1);
|
||||
}
|
||||
}
|
||||
|
||||
public double getAbsDy1() {
|
||||
if ( y1 > y0 ) {
|
||||
return Math.abs(y1 - y0);
|
||||
} else {
|
||||
return Math.abs(y0 - y1);
|
||||
}
|
||||
}
|
||||
|
||||
public double getAbsDy2() {
|
||||
if ( y2 > y1 ) {
|
||||
return Math.abs(y2 - y1);
|
||||
} else {
|
||||
return Math.abs(y1 - y2);
|
||||
}
|
||||
}
|
||||
|
||||
public double getX0() {
|
||||
return x0;
|
||||
}
|
||||
|
||||
public double getX1() {
|
||||
return x1;
|
||||
}
|
||||
|
||||
public double getX2() {
|
||||
return x2;
|
||||
}
|
||||
|
||||
public boolean isX2Defined() {
|
||||
return x2 != DEFAULT;
|
||||
}
|
||||
|
||||
public double getY0() {
|
||||
return y0;
|
||||
}
|
||||
|
||||
public double getY1() {
|
||||
return y1;
|
||||
}
|
||||
|
||||
public double getY2() {
|
||||
return y2;
|
||||
}
|
||||
|
||||
public void clearHistory () {
|
||||
this.x0 = DEFAULT;
|
||||
this.x1 = DEFAULT;
|
||||
this.y0 = DEFAULT;
|
||||
this.y1 = DEFAULT;
|
||||
}
|
||||
|
||||
public double getAbsDyDx2() {
|
||||
double dx2 = this.getAbsDx2();
|
||||
double dy2 = this.getAbsDy2();
|
||||
return dy2 / dx2;
|
||||
}
|
||||
|
||||
public double getAbsDyDx1() {
|
||||
double dx1 = this.getAbsDx1();
|
||||
double dy1 = this.getAbsDy1();
|
||||
return dy1 / dx1;
|
||||
}
|
||||
|
||||
public double getDyDx1() {
|
||||
double result = getAbsDyDx1();
|
||||
return y1 > y0 ? result : -result;
|
||||
}
|
||||
|
||||
public double getDyDx2() {
|
||||
double result = getAbsDyDx2();
|
||||
return y2 > y1 ? result : -result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Point{" +
|
||||
"x0=" + x0 +
|
||||
", x1=" + x1 +
|
||||
", x2=" + x2 +
|
||||
", y0=" + y0 +
|
||||
", y1=" + y1 +
|
||||
", y2=" + y2 +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
private static double updateStep(@NotNull Point real,
|
||||
double step,
|
||||
double eps) {
|
||||
if ( !real.isFullyDefined() ) {
|
||||
return step;
|
||||
} else {
|
||||
double dydx2 = real.getAbsDyDx2();
|
||||
double dydx1 = real.getAbsDyDx1();
|
||||
|
||||
double k = dydx2 / dydx1;
|
||||
|
||||
if ( k > 1 ) {
|
||||
step = step / k;
|
||||
} else if ( k > 0 ) {
|
||||
step = step * k;
|
||||
}
|
||||
|
||||
return Math.max(step, eps);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Complex calculatorExpression(@NotNull Generic expression, @NotNull Constant variable, double x) {
|
||||
try {
|
||||
return unwrap(expression.substitute(variable, Expression.valueOf(x)).numeric());
|
||||
} catch (RuntimeException e) {
|
||||
return NaN;
|
||||
}
|
||||
}
|
||||
|
||||
public static void addSingularityPoint(@NotNull MyXYSeries series,
|
||||
@NotNull Point point) {
|
||||
if (point.isFullyDefined()) {
|
||||
// y or prevY should be more than 1d because if they are too small false singularity may occur (e.g., 1/0.000000000000000001)
|
||||
// double dy0 = y1 - y0;
|
||||
// double dx0 = x1 - x0;
|
||||
// double dydx0 = dy0 / dx0;
|
||||
|
||||
double dy2 = point.getAbsDy2();
|
||||
double dx2 = point.getAbsDx2();
|
||||
//double dx1 = x2 - x1;
|
||||
// double dydx1 = dy2 / dx1;
|
||||
|
||||
if ( dy2 > MAX_Y_DIFF && dx2 < MAX_X_DIFF && isDifferentSign(point.getY2(), point.getY1()) && isDifferentSign(point.getDyDx1(), point.getDyDx2())) {
|
||||
//Log.d(CalculatorPlotActivity.class.getName(), "Singularity: " + point);
|
||||
//Log.d(CalculatorPlotActivity.class.getName(), String.valueOf(prevX + Math.abs(x - prevX) / 2) + ", null");
|
||||
series.add(point.getX1() + point.getAbsDx2() / 2, MathHelper.NULL_VALUE);
|
||||
point.clearHistory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDifferentSign(@NotNull Double y0, @NotNull Double y1) {
|
||||
return (y0 >= 0 && y1 < 0) || (y1 >= 0 && y0 < 0);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Double prepareY(double y) {
|
||||
if (Double.isNaN(y)) {
|
||||
return null;
|
||||
} else {
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Complex NaN = Complex.valueOf(Double.NaN, 0d);
|
||||
|
||||
@NotNull
|
||||
public static Complex unwrap(@Nullable Generic numeric) {
|
||||
if (numeric instanceof JsclInteger) {
|
||||
return Complex.valueOf(((JsclInteger) numeric).intValue(), 0d);
|
||||
} else if (numeric instanceof NumericWrapper) {
|
||||
return unwrap(((NumericWrapper) numeric).content());
|
||||
} else {
|
||||
return NaN;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Complex unwrap(@Nullable Numeric content) {
|
||||
if (content instanceof Real) {
|
||||
return Complex.valueOf(((Real) content).doubleValue(), 0d);
|
||||
} else if (content instanceof Complex) {
|
||||
return ((Complex) content);
|
||||
} else {
|
||||
throw new ArithmeticException();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.SharedPreferences;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.Locator;
|
||||
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 12/10/11
|
||||
* Time: 10:34 PM
|
||||
*/
|
||||
public class CalculatorAdditionalTitle extends TextView implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
public CalculatorAdditionalTitle(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public CalculatorAdditionalTitle(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public CalculatorAdditionalTitle(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
public void init(@NotNull SharedPreferences preferences) {
|
||||
onSharedPreferenceChanged(preferences, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences preferences, @Nullable String key) {
|
||||
setText(((AndroidCalculatorEngine) Locator.getInstance().getEngine()).getNumeralBaseFromPrefs(preferences)
|
||||
+ " / " +
|
||||
((AndroidCalculatorEngine) Locator.getInstance().getEngine()).getAngleUnitsFromPrefs(preferences));
|
||||
}
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
package org.solovyev.android.calculator.view;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Vibrator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.view.VibratorContainer;
|
||||
import org.solovyev.android.view.drag.DragButton;
|
||||
import org.solovyev.android.view.drag.OnDragListener;
|
||||
import org.solovyev.android.view.drag.OnDragListenerWrapper;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 4/20/12
|
||||
* Time: 3:27 PM
|
||||
*/
|
||||
public class OnDragListenerVibrator extends OnDragListenerWrapper {
|
||||
|
||||
private static final float VIBRATION_TIME_SCALE = 0.5f;
|
||||
|
||||
@NotNull
|
||||
private final VibratorContainer vibrator;
|
||||
|
||||
public OnDragListenerVibrator(@NotNull OnDragListener onDragListener,
|
||||
@Nullable Vibrator vibrator,
|
||||
@NotNull SharedPreferences preferences) {
|
||||
super(onDragListener);
|
||||
this.vibrator = new VibratorContainer(vibrator, preferences, VIBRATION_TIME_SCALE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDrag(@NotNull DragButton dragButton, @NotNull org.solovyev.android.view.drag.DragEvent event) {
|
||||
boolean result = super.onDrag(dragButton, event);
|
||||
|
||||
if (result) {
|
||||
vibrator.vibrate();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
package org.solovyev.android.fragments;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.common.collections.CollectionsUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/25/12
|
||||
* Time: 9:29 PM
|
||||
*/
|
||||
public class FragmentUtils {
|
||||
|
||||
public static void createFragment(@NotNull FragmentActivity activity,
|
||||
@NotNull Class<? extends Fragment> fragmentClass,
|
||||
int parentViewId,
|
||||
@NotNull String tag) {
|
||||
final FragmentManager fm = activity.getSupportFragmentManager();
|
||||
|
||||
Fragment messagesFragment = fm.findFragmentByTag(tag);
|
||||
|
||||
final FragmentTransaction ft = fm.beginTransaction();
|
||||
try {
|
||||
if (messagesFragment == null) {
|
||||
messagesFragment = Fragment.instantiate(activity, fragmentClass.getName(), null);
|
||||
ft.add(parentViewId, messagesFragment, tag);
|
||||
} else {
|
||||
if (messagesFragment.isDetached()) {
|
||||
ft.attach(messagesFragment);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
ft.commit();
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeFragments(@NotNull SherlockFragmentActivity activity, @NotNull String... fragmentTags) {
|
||||
removeFragments(activity, CollectionsUtils.asList(fragmentTags));
|
||||
}
|
||||
|
||||
public static void removeFragments(@NotNull SherlockFragmentActivity activity, @NotNull List<String> fragmentTags) {
|
||||
for (String fragmentTag : fragmentTags) {
|
||||
removeFragment(activity, fragmentTag);
|
||||
}
|
||||
}
|
||||
|
||||
public static void detachFragments(@NotNull SherlockFragmentActivity activity, @NotNull String... fragmentTags) {
|
||||
detachFragments(activity, CollectionsUtils.asList(fragmentTags));
|
||||
}
|
||||
|
||||
public static void detachFragments(@NotNull SherlockFragmentActivity activity, @NotNull List<String> fragmentTags) {
|
||||
for (String fragmentTag : fragmentTags) {
|
||||
detachFragment(activity, fragmentTag);
|
||||
}
|
||||
}
|
||||
|
||||
public static void detachFragment(@NotNull SherlockFragmentActivity activity, @NotNull String fragmentTag) {
|
||||
final Fragment fragment = activity.getSupportFragmentManager().findFragmentByTag(fragmentTag);
|
||||
if ( fragment != null ) {
|
||||
if ( !fragment.isDetached() ) {
|
||||
FragmentTransaction ft = activity.getSupportFragmentManager().beginTransaction();
|
||||
ft.detach(fragment);
|
||||
ft.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeFragment(@NotNull SherlockFragmentActivity activity, @NotNull String fragmentTag) {
|
||||
final Fragment fragment = activity.getSupportFragmentManager().findFragmentByTag(fragmentTag);
|
||||
if ( fragment != null ) {
|
||||
if ( fragment.isAdded()) {
|
||||
FragmentTransaction ft = activity.getSupportFragmentManager().beginTransaction();
|
||||
ft.remove(fragment);
|
||||
ft.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user