separating application

This commit is contained in:
Sergey Solovyev 2012-01-03 01:52:15 +04:00
parent c816772d04
commit 6f2040eb78
20 changed files with 873 additions and 709 deletions

View File

@ -13,9 +13,9 @@
<application a:icon="@drawable/icon" <application a:icon="@drawable/icon"
a:label="@string/c_app_name" a:label="@string/c_app_name"
a:name=".ApplicationContext"> a:name="org.solovyev.android.calculator.ApplicationContext">
<activity a:name=".CalculatorActivity" <activity a:name="org.solovyev.android.calculator.CalculatorActivityFree"
a:label="@string/c_app_name"> a:label="@string/c_app_name">
<intent-filter> <intent-filter>
@ -25,71 +25,71 @@
</activity> </activity>
<activity a:name=".CalculatorPreferencesActivity" <activity a:name="org.solovyev.android.calculator.CalculatorPreferencesActivity"
a:label="@string/c_app_settings" a:label="@string/c_app_settings"
a:configChanges="orientation|keyboardHidden"/> a:configChanges="orientation|keyboardHidden"/>
<activity a:name=".history.CalculatorHistoryActivity" <activity a:name="org.solovyev.android.calculator.history.CalculatorHistoryActivity"
a:label="@string/c_app_history" a:label="@string/c_app_history"
a:configChanges="orientation|keyboardHidden"/> a:configChanges="orientation|keyboardHidden"/>
<activity a:name=".history.HistoryActivityTab" <activity a:name="org.solovyev.android.calculator.history.HistoryActivityTab"
a:label="@string/c_history" a:label="@string/c_history"
a:configChanges="orientation|keyboardHidden"/> a:configChanges="orientation|keyboardHidden"/>
<activity a:name=".history.SavedHistoryActivityTab" <activity a:name="org.solovyev.android.calculator.history.SavedHistoryActivityTab"
a:label="@string/c_saved_history" a:label="@string/c_saved_history"
a:configChanges="orientation|keyboardHidden"/> a:configChanges="orientation|keyboardHidden"/>
<activity a:name=".about.CalculatorAboutTabActivity" <activity a:name="org.solovyev.android.calculator.about.CalculatorAboutTabActivity"
a:label="@string/c_about" a:label="@string/c_about"
a:configChanges="orientation|keyboardHidden"/> a:configChanges="orientation|keyboardHidden"/>
<activity a:name=".about.CalculatorAboutActivity" <activity a:name="org.solovyev.android.calculator.about.CalculatorAboutActivity"
a:label="@string/c_about" a:label="@string/c_about"
a:configChanges="orientation|keyboardHidden"/> a:configChanges="orientation|keyboardHidden"/>
<activity a:name=".about.CalculatorReleaseNotesActivity" <activity a:name="org.solovyev.android.calculator.about.CalculatorReleaseNotesActivity"
a:label="@string/c_about" a:label="@string/c_about"
a:configChanges="orientation|keyboardHidden"/> a:configChanges="orientation|keyboardHidden"/>
<activity a:name=".help.CalculatorHelpTabActivity" <activity a:name="org.solovyev.android.calculator.help.CalculatorHelpTabActivity"
a:label="@string/c_help" a:label="@string/c_help"
a:configChanges="orientation|keyboardHidden"/> a:configChanges="orientation|keyboardHidden"/>
<activity a:name=".help.HelpFaqActivity" <activity a:name="org.solovyev.android.calculator.help.HelpFaqActivity"
a:label="@string/c_help" a:label="@string/c_help"
a:configChanges="orientation|keyboardHidden"/> a:configChanges="orientation|keyboardHidden"/>
<activity a:name=".help.HelpHintsActivity" <activity a:name="org.solovyev.android.calculator.help.HelpHintsActivity"
a:label="@string/c_help" a:label="@string/c_help"
a:configChanges="orientation|keyboardHidden"/> a:configChanges="orientation|keyboardHidden"/>
<activity a:name=".help.HelpScreensActivity" <activity a:name="org.solovyev.android.calculator.help.HelpScreensActivity"
a:label="@string/c_help" a:label="@string/c_help"
a:configChanges="orientation|keyboardHidden"/> a:configChanges="orientation|keyboardHidden"/>
<activity a:name=".math.edit.CalculatorFunctionsActivity" <activity a:name="org.solovyev.android.calculator.math.edit.CalculatorFunctionsActivity"
a:label="@string/c_functions" a:label="@string/c_functions"
a:configChanges="orientation|keyboardHidden"/> a:configChanges="orientation|keyboardHidden"/>
<activity a:name=".math.edit.CalculatorFunctionsTabActivity" <activity a:name="org.solovyev.android.calculator.math.edit.CalculatorFunctionsTabActivity"
a:label="@string/c_functions" a:label="@string/c_functions"
a:configChanges="orientation|keyboardHidden"/> a:configChanges="orientation|keyboardHidden"/>
<activity a:name=".math.edit.CalculatorOperatorsActivity" <activity a:name="org.solovyev.android.calculator.math.edit.CalculatorOperatorsActivity"
a:label="@string/c_operators" a:label="@string/c_operators"
a:configChanges="orientation|keyboardHidden"/> a:configChanges="orientation|keyboardHidden"/>
<activity a:name=".math.edit.CalculatorVarsActivity" <activity a:name="org.solovyev.android.calculator.math.edit.CalculatorVarsActivity"
a:label="@string/c_vars_and_constants" a:label="@string/c_vars_and_constants"
a:configChanges="orientation|keyboardHidden"/> a:configChanges="orientation|keyboardHidden"/>
<activity a:name=".math.edit.CalculatorVarsTabActivity" <activity a:name="org.solovyev.android.calculator.math.edit.CalculatorVarsTabActivity"
a:label="@string/c_vars_and_constants" a:label="@string/c_vars_and_constants"
a:configChanges="orientation|keyboardHidden"/> a:configChanges="orientation|keyboardHidden"/>
<activity a:name=".CalculatorPlotActivity" <activity a:name="org.solovyev.android.calculator.CalculatorPlotActivity"
a:label="@string/c_plot_graph"/> a:label="@string/c_plot_graph"/>
</application> </application>

View File

@ -1,11 +0,0 @@
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "build.properties", and override values to adapt the script to your
# project structure.
# Project target.
target=android-4

View File

@ -9,7 +9,7 @@
<artifactId>calculator</artifactId> <artifactId>calculator</artifactId>
<version>1.1.4</version> <version>1.1.4</version>
<packaging>pom</packaging> <packaging>jar</packaging>
<properties> <properties>
<additionalLibs>${basedir}/src/misc/lib</additionalLibs> <additionalLibs>${basedir}/src/misc/lib</additionalLibs>
@ -80,7 +80,6 @@
<systemPath>${additionalLibs}/achartengine-0.7.0.jar</systemPath> <systemPath>${additionalLibs}/achartengine-0.7.0.jar</systemPath>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.intellij</groupId> <groupId>com.intellij</groupId>
<artifactId>annotations</artifactId> <artifactId>annotations</artifactId>
@ -88,5 +87,4 @@
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -8,6 +8,7 @@
<resources> <resources>
<string name="c_app_name">Calculadora++</string> <string name="c_app_name">Calculadora++</string>
<string name="c_app_name_free">Calculadora++ Free</string>
<string name="c_app_icon_name">Calc++</string> <string name="c_app_icon_name">Calc++</string>
<string name="c_app_settings">Configuración</string> <string name="c_app_settings">Configuración</string>
<string name="c_syntax_error">Error</string> <string name="c_syntax_error">Error</string>

View File

@ -8,6 +8,7 @@
<resources> <resources>
<string name="c_app_name">Calculator++</string> <string name="c_app_name">Calculator++</string>
<string name="c_app_name_free">Calculator++ Free</string>
<string name="c_app_icon_name">Calc++</string> <string name="c_app_icon_name">Calc++</string>
<string name="c_app_settings">Impostazioni</string> <string name="c_app_settings">Impostazioni</string>
<string name="c_syntax_error">Errore</string> <string name="c_syntax_error">Errore</string>

View File

@ -8,6 +8,7 @@
<resources> <resources>
<string name="c_app_name">Калькулятор++</string> <string name="c_app_name">Калькулятор++</string>
<string name="c_app_name_free">Калькулятор++ Free</string>
<string name="c_app_icon_name">Кальк++</string> <string name="c_app_icon_name">Кальк++</string>
<string name="c_app_settings">Настройки</string> <string name="c_app_settings">Настройки</string>
<string name="c_syntax_error">Ошибка</string> <string name="c_syntax_error">Ошибка</string>
@ -162,4 +163,7 @@
<string name="c_calc_use_back_button_as_prev_summary">Устанавливает поведение по нажатию на кнопку Назад</string> <string name="c_calc_use_back_button_as_prev_summary">Устанавливает поведение по нажатию на кнопку Назад</string>
<string name="c_calc_use_back_button_as_prev_title">Использовать кнопку назад как назад по истории</string> <string name="c_calc_use_back_button_as_prev_title">Использовать кнопку назад как назад по истории</string>
<string name="c_warning">Внимание</string>
<string name="c_remove_prev_app_warning">Вы установили другую версию Калькулятора++.\nДля корректной работы приложения, пожалуйста, удалите предыдущую версию, все пользовательские данные будут автоматически перенесены в новое приложение.</string>
</resources> </resources>

View File

@ -8,6 +8,7 @@
<resources> <resources>
<string name="c_app_name">Calculator++</string> <string name="c_app_name">Calculator++</string>
<string name="c_app_name_free">Calculator++ Free</string>
<string name="c_app_icon_name">Calc++</string> <string name="c_app_icon_name">Calc++</string>
<string name="c_app_settings">Settings</string> <string name="c_app_settings">Settings</string>
<string name="c_syntax_error">Error</string> <string name="c_syntax_error">Error</string>
@ -162,4 +163,7 @@
<string name="c_calc_use_back_button_as_prev_summary">Defines the behaviour of the Back button</string> <string name="c_calc_use_back_button_as_prev_summary">Defines the behaviour of the Back button</string>
<string name="c_calc_use_back_button_as_prev_title">Use Back button as history prev</string> <string name="c_calc_use_back_button_as_prev_title">Use Back button as history prev</string>
<string name="c_warning">Warning</string>
<string name="c_remove_prev_app_warning">It seems that you\'ve installed another version of Calculator++.\nFor correct work of the application please remove previous version, all user data will be automatically transferred to the new version.</string>
</resources> </resources>

View File

@ -15,7 +15,6 @@ import android.view.View;
import android.widget.Button; import android.widget.Button;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.CalculatorActivity;
import org.solovyev.android.view.widgets.DragButton; import org.solovyev.android.view.widgets.DragButton;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@ -219,7 +218,7 @@ public enum ResourceCache {
try { try {
result.put(field.getName(), field.getInt(clazz)); result.put(field.getName(), field.getInt(clazz));
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
Log.e(CalculatorActivity.class.getName(), e.getMessage()); Log.e(ResourceCache.class.getName(), e.getMessage());
} }
} }
} }

View File

@ -0,0 +1,702 @@
/*
* 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.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.text.ClipboardManager;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.util.TypedValue;
import android.view.*;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import jscl.AngleUnit;
import jscl.NumeralBase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.AndroidUtils;
import org.solovyev.android.ResourceCache;
import org.solovyev.android.calculator.about.CalculatorReleaseNotesActivity;
import org.solovyev.android.calculator.history.CalculatorHistory;
import org.solovyev.android.calculator.history.CalculatorHistoryState;
import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.view.FontSizeAdjuster;
import org.solovyev.android.view.prefs.IntegerPreference;
import org.solovyev.android.view.prefs.Preference;
import org.solovyev.android.view.prefs.StringPreference;
import org.solovyev.android.view.widgets.*;
import org.solovyev.common.utils.Announcer;
import org.solovyev.common.utils.Point2d;
import org.solovyev.common.utils.StringUtils;
import org.solovyev.common.utils.history.HistoryAction;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
import java.util.Map;
public abstract class AbstractCalculatorActivity extends Activity implements FontSizeAdjuster, SharedPreferences.OnSharedPreferenceChangeListener {
private static final int HVGA_WIDTH_PIXELS = 320;
public static class Preferences {
@NotNull
private static final String APP_TYPE_P_KEY = "application.type";
private static final ApplicationData.Type APP_TYPE_DEFAULT = null;
public static final Preference<ApplicationData.Type> appType = StringPreference.newInstance(APP_TYPE_P_KEY, APP_TYPE_DEFAULT, ApplicationData.Type.class);
@NotNull
private static final String APP_VERSION_P_KEY = "application.version";
private static final int APP_VERSION_DEFAULT = -1;
public static final Preference<Integer> appVersion = new IntegerPreference(APP_VERSION_P_KEY, APP_VERSION_DEFAULT);
}
@NotNull
public static final String SHOW_RELEASE_NOTES_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_show_release_notes";
public static final boolean SHOW_RELEASE_NOTES_P_DEFAULT = true;
@NotNull
public static final String USE_BACK_AS_PREV_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_use_back_button_as_prev";
public static final boolean USE_BACK_AS_PREV_DEFAULT = false;
@NotNull
private final Announcer<DragPreferencesChangeListener> dpclRegister = new Announcer<DragPreferencesChangeListener>(DragPreferencesChangeListener.class);
@NotNull
private CalculatorModel calculatorModel;
private volatile boolean initialized;
@NotNull
private String themeName;
@NotNull
private String layoutName;
@Nullable
private Vibrator vibrator;
private boolean useBackAsPrev = USE_BACK_AS_PREV_DEFAULT;
@NotNull
private final ApplicationData applicationData;
protected AbstractCalculatorActivity(@NotNull ApplicationData applicationData) {
this.applicationData = applicationData;
}
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
final boolean customTitleSupported = requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
this.setTitle(this.applicationData.getApplicationTitle());
setDefaultValues(preferences);
setTheme(preferences);
super.onCreate(savedInstanceState);
setLayout(preferences);
if (customTitleSupported) {
try {
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.calc_title);
final CalculatorAdditionalTitle additionalAdditionalTitleText = (CalculatorAdditionalTitle)findViewById(R.id.additional_title_text);
additionalAdditionalTitleText.init(preferences);
preferences.registerOnSharedPreferenceChangeListener(additionalAdditionalTitleText);
} catch (ClassCastException e) {
// super fix for issue with class cast in android.view.Window.setFeatureInt() (see app error reports)
Log.d(AbstractCalculatorActivity.class.getName(), e.getMessage(), e);
}
}
ResourceCache.instance.initCaptions(ApplicationContext.getInstance(), R.string.class);
firstTimeInit(preferences);
vibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE);
CalculatorHistory.instance.load(this, preferences);
calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance);
dpclRegister.clear();
final SimpleOnDragListener.Preferences dragPreferences = SimpleOnDragListener.getPreferences(preferences, this);
setOnDragListeners(dragPreferences, preferences);
final OnDragListener historyOnDragListener = new OnDragListenerVibrator(newOnDragListener(new HistoryDragProcessor<CalculatorHistoryState>(this.calculatorModel), dragPreferences), vibrator, preferences);
((DragButton) findViewById(R.id.historyButton)).setOnDragListener(historyOnDragListener);
((DragButton) findViewById(R.id.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) {
operatorsButtonClickHandler(dragButton);
return true;
}
return false;
}
}, dragPreferences), vibrator, preferences));
final OnDragListener toPositionOnDragListener = new OnDragListenerVibrator(new SimpleOnDragListener(new CursorDragProcessor(calculatorModel), dragPreferences), vibrator, preferences);
((DragButton) findViewById(R.id.rightButton)).setOnDragListener(toPositionOnDragListener);
((DragButton) findViewById(R.id.leftButton)).setOnDragListener(toPositionOnDragListener);
final DragButton equalsButton = (DragButton) findViewById(R.id.equalsButton);
if (equalsButton != null) {
equalsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new EvalDragProcessor(calculatorModel), dragPreferences), vibrator, preferences));
}
final AngleUnitsButton angleUnitsButton = (AngleUnitsButton) findViewById(R.id.sixDigitButton);
if (angleUnitsButton != null) {
angleUnitsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new AngleUnitsChanger(), dragPreferences), vibrator, preferences));
}
final NumeralBasesButton numeralBasesButton = (NumeralBasesButton) findViewById(R.id.clearButton);
if (numeralBasesButton != null) {
numeralBasesButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new NumeralBasesChanger(), dragPreferences), vibrator, preferences));
}
final DragButton varsButton = (DragButton) findViewById(R.id.varsButton);
if (varsButton != null) {
varsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new VarsDragProcessor(), dragPreferences), vibrator, preferences));
}
final DragButton roundBracketsButton = (DragButton) findViewById(R.id.roundBracketsButton);
if ( roundBracketsButton != null ) {
roundBracketsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new RoundBracketsDragProcessor(), dragPreferences), vibrator, preferences));
}
CalculatorEngine.instance.reset(this, preferences);
initMultiplicationButton();
preferences.registerOnSharedPreferenceChangeListener(this);
}
private class AngleUnitsChanger implements SimpleOnDragListener.DragProcessor {
private final DigitButtonDragProcessor processor = new DigitButtonDragProcessor(calculatorModel);
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection,
@NotNull DragButton dragButton,
@NotNull Point2d startPoint2d,
@NotNull MotionEvent motionEvent) {
boolean result = false;
if (dragButton instanceof AngleUnitsButton) {
if (dragDirection != DragDirection.left ) {
final String directionText = ((AngleUnitsButton) dragButton).getText(dragDirection);
if ( directionText != null ) {
try {
final AngleUnit angleUnits = AngleUnit.valueOf(directionText);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(AbstractCalculatorActivity.this);
CalculatorEngine.Preferences.angleUnit.putPreference(preferences, angleUnits);
result = true;
} catch (IllegalArgumentException e) {
Log.d(this.getClass().getName(), "Unsupported angle units: " + directionText);
}
}
} else if ( dragDirection == DragDirection.left ) {
result = processor.processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent);
}
}
return result;
}
}
private class NumeralBasesChanger implements SimpleOnDragListener.DragProcessor {
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection,
@NotNull DragButton dragButton,
@NotNull Point2d startPoint2d,
@NotNull MotionEvent motionEvent) {
boolean result = false;
if ( dragButton instanceof NumeralBasesButton ) {
final String directionText = ((NumeralBasesButton) dragButton).getText(dragDirection);
if ( directionText != null ) {
try {
final NumeralBase numeralBase = NumeralBase.valueOf(directionText);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(AbstractCalculatorActivity.this);
CalculatorEngine.Preferences.numeralBase.putPreference(preferences, numeralBase);
result = true;
} catch (IllegalArgumentException e) {
Log.d(this.getClass().getName(), "Unsupported numeral base: " + directionText);
}
}
}
return result;
}
}
private class VarsDragProcessor implements SimpleOnDragListener.DragProcessor {
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection,
@NotNull DragButton dragButton,
@NotNull Point2d startPoint2d,
@NotNull MotionEvent motionEvent) {
boolean result = false;
if (dragDirection == DragDirection.up) {
CalculatorActivityLauncher.createVar(AbstractCalculatorActivity.this, AbstractCalculatorActivity.this.calculatorModel);
result = true;
}
return result;
}
}
private void setDefaultValues(@NotNull SharedPreferences preferences) {
if (!preferences.contains(CalculatorEngine.Preferences.groupingSeparator.getKey())) {
final Locale locale = Locale.getDefault();
if (locale != null) {
final DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(locale);
int index = MathType.grouping_separator.getTokens().indexOf(String.valueOf(decimalFormatSymbols.getGroupingSeparator()));
final String groupingSeparator;
if (index >= 0) {
groupingSeparator = MathType.grouping_separator.getTokens().get(index);
} else {
groupingSeparator = " ";
}
CalculatorEngine.Preferences.groupingSeparator.putPreference(preferences, groupingSeparator);
}
}
if (!preferences.contains(CalculatorEngine.Preferences.angleUnit.getKey())) {
CalculatorEngine.Preferences.angleUnit.putDefault(preferences);
}
if (!preferences.contains(CalculatorEngine.Preferences.numeralBase.getKey())) {
CalculatorEngine.Preferences.numeralBase.putDefault(preferences);
}
}
private synchronized void setOnDragListeners(@NotNull SimpleOnDragListener.Preferences dragPreferences, @NotNull SharedPreferences preferences) {
final OnDragListener onDragListener = new OnDragListenerVibrator(newOnDragListener(new DigitButtonDragProcessor(calculatorModel), dragPreferences), vibrator, preferences);
for (Integer dragButtonId : ResourceCache.instance.getDragButtonIds()) {
((DragButton) findViewById(dragButtonId)).setOnDragListener(onDragListener);
}
}
@NotNull
private SimpleOnDragListener newOnDragListener(@NotNull SimpleOnDragListener.DragProcessor dragProcessor,
@NotNull SimpleOnDragListener.Preferences dragPreferences) {
final SimpleOnDragListener onDragListener = new SimpleOnDragListener(dragProcessor, dragPreferences);
dpclRegister.addListener(onDragListener);
return onDragListener;
}
private 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 DragEvent event) {
boolean result = super.onDrag(dragButton, event);
if (result) {
vibrator.vibrate();
}
return result;
}
}
private synchronized void setLayout(@NotNull SharedPreferences preferences) {
final Map<String, Integer> layouts = ResourceCache.instance.getNameToIdCache(R.layout.class);
layoutName = preferences.getString(getString(R.string.p_calc_layout_key), getString(R.string.p_calc_layout));
Integer layoutId = layouts.get(layoutName);
if (layoutId == null) {
Log.d(this.getClass().getName(), "No saved layout found => applying default layout: " + R.layout.main_calculator);
layoutId = R.layout.main_calculator;
} else {
Log.d(this.getClass().getName(), "Saved layout found: " + layoutId);
}
setContentView(layoutId);
}
private synchronized void setTheme(@NotNull SharedPreferences preferences) {
final Map<String, Integer> styles = ResourceCache.instance.getNameToIdCache(R.style.class);
themeName = preferences.getString(getString(R.string.p_calc_theme_key), getString(R.string.p_calc_theme));
Integer styleId = styles.get(themeName);
if (styleId == null) {
Log.d(this.getClass().getName(), "No saved theme found => applying default theme: " + R.style.default_theme);
styleId = R.style.default_theme;
} else {
Log.d(this.getClass().getName(), "Saved theme found: " + styleId);
}
setTheme(styleId);
}
private synchronized void firstTimeInit(@NotNull SharedPreferences preferences) {
if (!initialized) {
final int savedVersion = Preferences.appVersion.getPreference(preferences);
final ApplicationData.Type savedAppType = Preferences.appType.getPreference(preferences);
final int appVersion = AndroidUtils.getAppVersionCode(this, AbstractCalculatorActivity.class.getPackage().getName());
final ApplicationData.Type appType = applicationData.getType();
Preferences.appVersion.putPreference(preferences, appVersion);
Preferences.appType.putPreference(preferences, appType);
if (savedVersion == Preferences.APP_VERSION_DEFAULT) {
// new start
final AlertDialog.Builder builder = new AlertDialog.Builder(this).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();
} else {
if (savedVersion < appVersion) {
final boolean showReleaseNotes = preferences.getBoolean(SHOW_RELEASE_NOTES_P_KEY, SHOW_RELEASE_NOTES_P_DEFAULT);
if (showReleaseNotes) {
final String releaseNotes = CalculatorReleaseNotesActivity.getReleaseNotes(this, savedVersion + 1);
if (!StringUtils.isEmpty(releaseNotes)) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this).setMessage(Html.fromHtml(releaseNotes));
builder.setPositiveButton(android.R.string.ok, null);
builder.setTitle(R.string.c_release_notes);
builder.create().show();
}
}
}
}
if (savedAppType != appType && savedAppType != null) {
// new start
final AlertDialog.Builder builder = new AlertDialog.Builder(this).setMessage(R.string.c_remove_prev_app_warning);
builder.setPositiveButton(android.R.string.ok, null);
builder.setTitle(R.string.c_warning);
builder.create().show();
}
ResourceCache.instance.init(R.id.class, this);
CalculatorEngine.instance.init(this, preferences);
initialized = true;
}
}
@SuppressWarnings({"UnusedDeclaration"})
public void elementaryButtonClickHandler(@NotNull View v) {
throw new UnsupportedOperationException("Not implemented yet!");
}
@SuppressWarnings({"UnusedDeclaration"})
public void numericButtonClickHandler(@NotNull View v) {
this.calculatorModel.evaluate();
}
@SuppressWarnings({"UnusedDeclaration"})
public void historyButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showHistory(this);
}
@SuppressWarnings({"UnusedDeclaration"})
public void eraseButtonClickHandler(@NotNull View v) {
calculatorModel.doTextOperation(new CalculatorModel.TextOperation() {
@Override
public void doOperation(@NotNull EditText editor) {
if (editor.getSelectionStart() > 0) {
editor.getText().delete(editor.getSelectionStart() - 1, editor.getSelectionStart());
}
}
});
}
@SuppressWarnings({"UnusedDeclaration"})
public void simplifyButtonClickHandler(@NotNull View v) {
throw new UnsupportedOperationException("Not implemented yet!");
}
@SuppressWarnings({"UnusedDeclaration"})
public void moveLeftButtonClickHandler(@NotNull View v) {
calculatorModel.moveCursorLeft();
}
@SuppressWarnings({"UnusedDeclaration"})
public void moveRightButtonClickHandler(@NotNull View v) {
calculatorModel.moveCursorRight();
}
@SuppressWarnings({"UnusedDeclaration"})
public void pasteButtonClickHandler(@NotNull View v) {
calculatorModel.doTextOperation(new CalculatorModel.TextOperation() {
@Override
public void doOperation(@NotNull EditText editor) {
final ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
if (clipboard.hasText()) {
editor.getText().insert(editor.getSelectionStart(), clipboard.getText());
}
}
});
}
@SuppressWarnings({"UnusedDeclaration"})
public void copyButtonClickHandler(@NotNull View v) {
calculatorModel.copyResult(this);
}
@SuppressWarnings({"UnusedDeclaration"})
public void clearButtonClickHandler(@NotNull View v) {
calculatorModel.clear();
}
@SuppressWarnings({"UnusedDeclaration"})
public void digitButtonClickHandler(@NotNull View v) {
Log.d(String.valueOf(v.getId()), "digitButtonClickHandler() for: " + v.getId() + ". Pressed: " + v.isPressed());
calculatorModel.processDigitButtonAction(((DirectionDragButton) v).getText().toString());
}
@SuppressWarnings({"UnusedDeclaration"})
public void functionsButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showFunctions(this);
}
@SuppressWarnings({"UnusedDeclaration"})
public void operatorsButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showOperators(this);
}
@SuppressWarnings({"UnusedDeclaration"})
public void varsButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showVars(this);
}
private final static String paypalDonateUrl = "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=se%2esolovyev%40gmail%2ecom&lc=RU&item_name=Android%20Calculator&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted";
@SuppressWarnings({"UnusedDeclaration"})
public void donateButtonClickHandler(@NotNull View v) {
final LayoutInflater layoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
final View view = layoutInflater.inflate(R.layout.donate, null);
final TextView donate = (TextView) view.findViewById(R.id.donateText);
donate.setMovementMethod(LinkMovementMethod.getInstance());
final AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setCancelable(true)
.setNegativeButton(R.string.c_cancel, null)
.setPositiveButton(R.string.c_donate, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
final Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(paypalDonateUrl));
startActivity(i);
}
})
.setView(view);
builder.create().show();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (useBackAsPrev) {
calculatorModel.doHistoryAction(HistoryAction.undo);
return true;
}
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
final MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.main_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
boolean result;
switch (item.getItemId()) {
case R.id.main_menu_item_settings:
CalculatorActivityLauncher.showSettings(this);
result = true;
break;
case R.id.main_menu_item_history:
CalculatorActivityLauncher.showHistory(this);
result = true;
break;
case R.id.main_menu_item_about:
CalculatorActivityLauncher.showAbout(this);
result = true;
break;
case R.id.main_menu_item_help:
CalculatorActivityLauncher.showHelp(this);
result = true;
break;
case R.id.main_menu_item_exit:
this.finish();
result = true;
break;
default:
result = super.onOptionsItemSelected(item);
}
return result;
}
/**
* The font sizes in the layout files are specified for a HVGA display.
* Adjust the font sizes accordingly if we are running on a different
* display.
*/
@Override
public void adjustFontSize(@NotNull TextView view) {
float fontPixelSize = view.getTextSize();
Display display = getWindowManager().getDefaultDisplay();
int h = Math.min(display.getWidth(), display.getHeight());
float ratio = (float) h / HVGA_WIDTH_PIXELS;
view.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontPixelSize * ratio);
}
public void restart() {
final Intent intent = getIntent();
/*
for compatibility with android_1.6_compatibility
overridePendingTransition(0, 0);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);*/
Log.d(this.getClass().getName(), "Finishing current activity!");
finish();
/*
for compatibility with android_1.6_compatibility
overridePendingTransition(0, 0);*/
Log.d(this.getClass().getName(), "Starting new activity!");
startActivity(intent);
}
@Override
protected void onResume() {
super.onResume();
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
final String newLayoutName = preferences.getString(getString(R.string.p_calc_layout_key), getString(R.string.p_calc_layout));
final String newThemeName = preferences.getString(getString(R.string.p_calc_theme_key), getString(R.string.p_calc_theme));
if (!themeName.equals(newThemeName) || !layoutName.equals(newLayoutName)) {
restart();
}
calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance);
calculatorModel.evaluate(calculatorModel.getDisplay().getJsclOperation());
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, @Nullable String key) {
if (key != null && key.startsWith("org.solovyev.android.calculator.DragButtonCalibrationActivity")) {
dpclRegister.announce().onDragPreferencesChange(SimpleOnDragListener.getPreferences(preferences, this));
}
if (CalculatorEngine.Preferences.getPreferenceKeys().contains(key)) {
CalculatorEngine.instance.reset(this, preferences);
this.calculatorModel.evaluate();
}
if ( USE_BACK_AS_PREV_P_KEY.equals(key) ) {
useBackAsPrev = preferences.getBoolean(USE_BACK_AS_PREV_P_KEY, USE_BACK_AS_PREV_DEFAULT);
}
if ( CalculatorEngine.Preferences.multiplicationSign.getKey().equals(key) ) {
initMultiplicationButton();
}
}
private void initMultiplicationButton() {
final View multiplicationButton = findViewById(R.id.multiplicationButton);
if ( multiplicationButton instanceof Button) {
((Button) multiplicationButton).setText(CalculatorEngine.instance.getMultiplicationSign());
}
}
private static class RoundBracketsDragProcessor implements SimpleOnDragListener.DragProcessor {
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
boolean result = false;
if ( dragDirection == DragDirection.left ) {
CalculatorModel.instance.doTextOperation(new CalculatorModel.TextOperation() {
@Override
public void doOperation(@NotNull EditText editor) {
final int cursorPosition = editor.getSelectionStart();
final StringBuilder text = new StringBuilder("(");
final String oldText = editor.getText().toString();
text.append(oldText.substring(0, cursorPosition));
text.append(")");
text.append(oldText.substring(cursorPosition));
editor.setText(text);
editor.setSelection(cursorPosition + 2);
}
});
result = true;
} else {
result = new DigitButtonDragProcessor(CalculatorModel.instance).processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent);
}
return result;
}
}
}

View File

@ -0,0 +1,32 @@
/*
* 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/2/12
* Time: 9:08 PM
*/
public interface ApplicationData {
public static enum Type {
free,
pro
}
boolean isFree();
boolean isShowAd();
int getApplicationTitle();
@NotNull
Type getType();
}

View File

@ -0,0 +1,51 @@
/*
* 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/2/12
* Time: 9:32 PM
*/
public class ApplicationDataImpl implements ApplicationData {
private final boolean free;
private final int applicationTitle;
@NotNull
private final Type type;
public ApplicationDataImpl(boolean free, int applicationTitle, @NotNull Type type) {
this.free = free;
this.applicationTitle = applicationTitle;
this.type = type;
}
@Override
public boolean isFree() {
return this.free;
}
@Override
public boolean isShowAd() {
return this.free;
}
@Override
public int getApplicationTitle() {
return this.applicationTitle;
}
@Override
@NotNull
public Type getType() {
return type;
}
}

View File

@ -1,672 +1,26 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2012. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/ */
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.text.ClipboardManager;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.util.TypedValue;
import android.view.*;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import jscl.AngleUnit;
import jscl.NumeralBase;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.AndroidUtils;
import org.solovyev.android.ResourceCache;
import org.solovyev.android.calculator.about.CalculatorReleaseNotesActivity;
import org.solovyev.android.calculator.history.CalculatorHistory;
import org.solovyev.android.calculator.history.CalculatorHistoryState;
import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.view.FontSizeAdjuster;
import org.solovyev.android.view.widgets.*;
import org.solovyev.android.view.widgets.DragEvent;
import org.solovyev.common.utils.Announcer;
import org.solovyev.common.utils.Point2d;
import org.solovyev.common.utils.StringUtils;
import org.solovyev.common.utils.history.HistoryAction;
import java.text.DecimalFormatSymbols; /**
import java.util.Locale; * User: serso
import java.util.Map; * Date: 1/2/12
* Time: 9:33 PM
*/
public class CalculatorActivity extends AbstractCalculatorActivity {
public class CalculatorActivity extends Activity implements FontSizeAdjuster, SharedPreferences.OnSharedPreferenceChangeListener { public CalculatorActivity() {
super(createApplicationData());
private static final int HVGA_WIDTH_PIXELS = 320;
@NotNull
public static final String APP_VERSION_P_KEY = "application.version";
@NotNull
public static final String SHOW_RELEASE_NOTES_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_show_release_notes";
public static final boolean SHOW_RELEASE_NOTES_P_DEFAULT = true;
@NotNull
public static final String USE_BACK_AS_PREV_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_use_back_button_as_prev";
public static final boolean USE_BACK_AS_PREV_DEFAULT = false;
@NotNull
private final Announcer<DragPreferencesChangeListener> dpclRegister = new Announcer<DragPreferencesChangeListener>(DragPreferencesChangeListener.class);
@NotNull
private CalculatorModel calculatorModel;
private volatile boolean initialized;
@NotNull
private String themeName;
@NotNull
private String layoutName;
@Nullable
private Vibrator vibrator;
private boolean useBackAsPrev = USE_BACK_AS_PREV_DEFAULT;
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
Log.d(this.getClass().getName(), "org.solovyev.android.calculator.CalculatorActivity.onCreate()");
final boolean customTitleSupported = requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
setDefaultValues(preferences);
setTheme(preferences);
super.onCreate(savedInstanceState);
setLayout(preferences);
if (customTitleSupported) {
try {
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.calc_title);
final CalculatorAdditionalTitle additionalAdditionalTitleText = (CalculatorAdditionalTitle)findViewById(R.id.additional_title_text);
additionalAdditionalTitleText.init(preferences);
preferences.registerOnSharedPreferenceChangeListener(additionalAdditionalTitleText);
} catch (ClassCastException e) {
// super fix for issue with class cast in android.view.Window.setFeatureInt() (see app error reports)
Log.d(CalculatorActivity.class.getName(), e.getMessage(), e);
}
}
ResourceCache.instance.initCaptions(ApplicationContext.getInstance(), R.string.class);
firstTimeInit(preferences);
vibrator = (Vibrator) this.getSystemService(VIBRATOR_SERVICE);
CalculatorHistory.instance.load(this, preferences);
calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance);
dpclRegister.clear();
final SimpleOnDragListener.Preferences dragPreferences = SimpleOnDragListener.getPreferences(preferences, this);
setOnDragListeners(dragPreferences, preferences);
final OnDragListener historyOnDragListener = new OnDragListenerVibrator(newOnDragListener(new HistoryDragProcessor<CalculatorHistoryState>(this.calculatorModel), dragPreferences), vibrator, preferences);
((DragButton) findViewById(R.id.historyButton)).setOnDragListener(historyOnDragListener);
((DragButton) findViewById(R.id.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) {
operatorsButtonClickHandler(dragButton);
return true;
}
return false;
}
}, dragPreferences), vibrator, preferences));
final OnDragListener toPositionOnDragListener = new OnDragListenerVibrator(new SimpleOnDragListener(new CursorDragProcessor(calculatorModel), dragPreferences), vibrator, preferences);
((DragButton) findViewById(R.id.rightButton)).setOnDragListener(toPositionOnDragListener);
((DragButton) findViewById(R.id.leftButton)).setOnDragListener(toPositionOnDragListener);
final DragButton equalsButton = (DragButton) findViewById(R.id.equalsButton);
if (equalsButton != null) {
equalsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new EvalDragProcessor(calculatorModel), dragPreferences), vibrator, preferences));
}
final AngleUnitsButton angleUnitsButton = (AngleUnitsButton) findViewById(R.id.sixDigitButton);
if (angleUnitsButton != null) {
angleUnitsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new AngleUnitsChanger(), dragPreferences), vibrator, preferences));
}
final NumeralBasesButton numeralBasesButton = (NumeralBasesButton) findViewById(R.id.clearButton);
if (numeralBasesButton != null) {
numeralBasesButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new NumeralBasesChanger(), dragPreferences), vibrator, preferences));
}
final DragButton varsButton = (DragButton) findViewById(R.id.varsButton);
if (varsButton != null) {
varsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new VarsDragProcessor(), dragPreferences), vibrator, preferences));
}
final DragButton roundBracketsButton = (DragButton) findViewById(R.id.roundBracketsButton);
if ( roundBracketsButton != null ) {
roundBracketsButton.setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new RoundBracketsDragProcessor(), dragPreferences), vibrator, preferences));
}
CalculatorEngine.instance.reset(this, preferences);
initMultiplicationButton();
preferences.registerOnSharedPreferenceChangeListener(this);
}
private class AngleUnitsChanger implements SimpleOnDragListener.DragProcessor {
private final DigitButtonDragProcessor processor = new DigitButtonDragProcessor(calculatorModel);
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection,
@NotNull DragButton dragButton,
@NotNull Point2d startPoint2d,
@NotNull MotionEvent motionEvent) {
boolean result = false;
if (dragButton instanceof AngleUnitsButton) {
if (dragDirection != DragDirection.left ) {
final String directionText = ((AngleUnitsButton) dragButton).getText(dragDirection);
if ( directionText != null ) {
try {
final AngleUnit angleUnits = AngleUnit.valueOf(directionText);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(CalculatorActivity.this);
CalculatorEngine.Preferences.angleUnit.putPreference(preferences, angleUnits);
result = true;
} catch (IllegalArgumentException e) {
Log.d(this.getClass().getName(), "Unsupported angle units: " + directionText);
}
}
} else if ( dragDirection == DragDirection.left ) {
result = processor.processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent);
}
}
return result;
}
}
private class NumeralBasesChanger implements SimpleOnDragListener.DragProcessor {
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection,
@NotNull DragButton dragButton,
@NotNull Point2d startPoint2d,
@NotNull MotionEvent motionEvent) {
boolean result = false;
if ( dragButton instanceof NumeralBasesButton ) {
final String directionText = ((NumeralBasesButton) dragButton).getText(dragDirection);
if ( directionText != null ) {
try {
final NumeralBase numeralBase = NumeralBase.valueOf(directionText);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(CalculatorActivity.this);
CalculatorEngine.Preferences.numeralBase.putPreference(preferences, numeralBase);
result = true;
} catch (IllegalArgumentException e) {
Log.d(this.getClass().getName(), "Unsupported numeral base: " + directionText);
}
}
}
return result;
}
}
private class VarsDragProcessor implements SimpleOnDragListener.DragProcessor {
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection,
@NotNull DragButton dragButton,
@NotNull Point2d startPoint2d,
@NotNull MotionEvent motionEvent) {
boolean result = false;
if (dragDirection == DragDirection.up) {
CalculatorActivityLauncher.createVar(CalculatorActivity.this, CalculatorActivity.this.calculatorModel);
result = true;
}
return result;
}
}
private void setDefaultValues(@NotNull SharedPreferences preferences) {
if (!preferences.contains(CalculatorEngine.Preferences.groupingSeparator.getKey())) {
final Locale locale = Locale.getDefault();
if (locale != null) {
final DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(locale);
int index = MathType.grouping_separator.getTokens().indexOf(String.valueOf(decimalFormatSymbols.getGroupingSeparator()));
final String groupingSeparator;
if (index >= 0) {
groupingSeparator = MathType.grouping_separator.getTokens().get(index);
} else {
groupingSeparator = " ";
}
CalculatorEngine.Preferences.groupingSeparator.putPreference(preferences, groupingSeparator);
}
}
if (!preferences.contains(CalculatorEngine.Preferences.angleUnit.getKey())) {
CalculatorEngine.Preferences.angleUnit.putDefault(preferences);
}
if (!preferences.contains(CalculatorEngine.Preferences.numeralBase.getKey())) {
CalculatorEngine.Preferences.numeralBase.putDefault(preferences);
}
}
private synchronized void setOnDragListeners(@NotNull SimpleOnDragListener.Preferences dragPreferences, @NotNull SharedPreferences preferences) {
final OnDragListener onDragListener = new OnDragListenerVibrator(newOnDragListener(new DigitButtonDragProcessor(calculatorModel), dragPreferences), vibrator, preferences);
for (Integer dragButtonId : ResourceCache.instance.getDragButtonIds()) {
((DragButton) findViewById(dragButtonId)).setOnDragListener(onDragListener);
}
} }
@NotNull @NotNull
private SimpleOnDragListener newOnDragListener(@NotNull SimpleOnDragListener.DragProcessor dragProcessor, private static ApplicationData createApplicationData() {
@NotNull SimpleOnDragListener.Preferences dragPreferences) { return new ApplicationDataImpl(false, R.string.c_app_name, ApplicationData.Type.pro);
final SimpleOnDragListener onDragListener = new SimpleOnDragListener(dragProcessor, dragPreferences);
dpclRegister.addListener(onDragListener);
return onDragListener;
}
private 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 DragEvent event) {
boolean result = super.onDrag(dragButton, event);
if (result) {
vibrator.vibrate();
}
return result;
}
}
private synchronized void setLayout(@NotNull SharedPreferences preferences) {
final Map<String, Integer> layouts = ResourceCache.instance.getNameToIdCache(R.layout.class);
layoutName = preferences.getString(getString(R.string.p_calc_layout_key), getString(R.string.p_calc_layout));
Integer layoutId = layouts.get(layoutName);
if (layoutId == null) {
Log.d(this.getClass().getName(), "No saved layout found => applying default layout: " + R.layout.main_calculator);
layoutId = R.layout.main_calculator;
} else {
Log.d(this.getClass().getName(), "Saved layout found: " + layoutId);
}
setContentView(layoutId);
}
private synchronized void setTheme(@NotNull SharedPreferences preferences) {
final Map<String, Integer> styles = ResourceCache.instance.getNameToIdCache(R.style.class);
themeName = preferences.getString(getString(R.string.p_calc_theme_key), getString(R.string.p_calc_theme));
Integer styleId = styles.get(themeName);
if (styleId == null) {
Log.d(this.getClass().getName(), "No saved theme found => applying default theme: " + R.style.default_theme);
styleId = R.style.default_theme;
} else {
Log.d(this.getClass().getName(), "Saved theme found: " + styleId);
}
setTheme(styleId);
}
private synchronized void firstTimeInit(@NotNull SharedPreferences preferences) {
if (!initialized) {
final int savedVersion = preferences.getInt(APP_VERSION_P_KEY, -1);
final int appVersion = AndroidUtils.getAppVersionCode(this, CalculatorActivity.class.getPackage().getName());
final SharedPreferences.Editor pEditor = preferences.edit();
pEditor.putInt(APP_VERSION_P_KEY, appVersion);
pEditor.commit();
if (savedVersion == -1) {
// new start
final AlertDialog.Builder builder = new AlertDialog.Builder(this).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();
} else {
if (savedVersion < appVersion) {
final boolean showReleaseNotes = preferences.getBoolean(SHOW_RELEASE_NOTES_P_KEY, SHOW_RELEASE_NOTES_P_DEFAULT);
if (showReleaseNotes) {
final String releaseNotes = CalculatorReleaseNotesActivity.getReleaseNotes(this, savedVersion + 1);
if (!StringUtils.isEmpty(releaseNotes)) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this).setMessage(Html.fromHtml(releaseNotes));
builder.setPositiveButton(android.R.string.ok, null);
builder.setTitle(R.string.c_release_notes);
builder.create().show();
}
}
}
}
ResourceCache.instance.init(R.id.class, this);
CalculatorEngine.instance.init(this, preferences);
initialized = true;
}
}
@SuppressWarnings({"UnusedDeclaration"})
public void elementaryButtonClickHandler(@NotNull View v) {
throw new UnsupportedOperationException("Not implemented yet!");
}
@SuppressWarnings({"UnusedDeclaration"})
public void numericButtonClickHandler(@NotNull View v) {
this.calculatorModel.evaluate();
}
@SuppressWarnings({"UnusedDeclaration"})
public void historyButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showHistory(this);
}
@SuppressWarnings({"UnusedDeclaration"})
public void eraseButtonClickHandler(@NotNull View v) {
calculatorModel.doTextOperation(new CalculatorModel.TextOperation() {
@Override
public void doOperation(@NotNull EditText editor) {
if (editor.getSelectionStart() > 0) {
editor.getText().delete(editor.getSelectionStart() - 1, editor.getSelectionStart());
}
}
});
}
@SuppressWarnings({"UnusedDeclaration"})
public void simplifyButtonClickHandler(@NotNull View v) {
throw new UnsupportedOperationException("Not implemented yet!");
}
@SuppressWarnings({"UnusedDeclaration"})
public void moveLeftButtonClickHandler(@NotNull View v) {
calculatorModel.moveCursorLeft();
}
@SuppressWarnings({"UnusedDeclaration"})
public void moveRightButtonClickHandler(@NotNull View v) {
calculatorModel.moveCursorRight();
}
@SuppressWarnings({"UnusedDeclaration"})
public void pasteButtonClickHandler(@NotNull View v) {
calculatorModel.doTextOperation(new CalculatorModel.TextOperation() {
@Override
public void doOperation(@NotNull EditText editor) {
final ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
if (clipboard.hasText()) {
editor.getText().insert(editor.getSelectionStart(), clipboard.getText());
}
}
});
}
@SuppressWarnings({"UnusedDeclaration"})
public void copyButtonClickHandler(@NotNull View v) {
calculatorModel.copyResult(this);
}
@SuppressWarnings({"UnusedDeclaration"})
public void clearButtonClickHandler(@NotNull View v) {
calculatorModel.clear();
}
@SuppressWarnings({"UnusedDeclaration"})
public void digitButtonClickHandler(@NotNull View v) {
Log.d(String.valueOf(v.getId()), "digitButtonClickHandler() for: " + v.getId() + ". Pressed: " + v.isPressed());
calculatorModel.processDigitButtonAction(((DirectionDragButton) v).getText().toString());
}
@SuppressWarnings({"UnusedDeclaration"})
public void functionsButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showFunctions(this);
}
@SuppressWarnings({"UnusedDeclaration"})
public void operatorsButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showOperators(this);
}
@SuppressWarnings({"UnusedDeclaration"})
public void varsButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showVars(this);
}
private final static String paypalDonateUrl = "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=se%2esolovyev%40gmail%2ecom&lc=RU&item_name=Android%20Calculator&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted";
@SuppressWarnings({"UnusedDeclaration"})
public void donateButtonClickHandler(@NotNull View v) {
final LayoutInflater layoutInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
final View view = layoutInflater.inflate(R.layout.donate, null);
final TextView donate = (TextView) view.findViewById(R.id.donateText);
donate.setMovementMethod(LinkMovementMethod.getInstance());
final AlertDialog.Builder builder = new AlertDialog.Builder(this)
.setCancelable(true)
.setNegativeButton(R.string.c_cancel, null)
.setPositiveButton(R.string.c_donate, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
final Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(paypalDonateUrl));
startActivity(i);
}
})
.setView(view);
builder.create().show();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (useBackAsPrev) {
calculatorModel.doHistoryAction(HistoryAction.undo);
return true;
}
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
final MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.menu.main_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
boolean result;
switch (item.getItemId()) {
case R.id.main_menu_item_settings:
CalculatorActivityLauncher.showSettings(this);
result = true;
break;
case R.id.main_menu_item_history:
CalculatorActivityLauncher.showHistory(this);
result = true;
break;
case R.id.main_menu_item_about:
CalculatorActivityLauncher.showAbout(this);
result = true;
break;
case R.id.main_menu_item_help:
CalculatorActivityLauncher.showHelp(this);
result = true;
break;
case R.id.main_menu_item_exit:
this.finish();
result = true;
break;
default:
result = super.onOptionsItemSelected(item);
}
return result;
}
/**
* The font sizes in the layout files are specified for a HVGA display.
* Adjust the font sizes accordingly if we are running on a different
* display.
*/
@Override
public void adjustFontSize(@NotNull TextView view) {
float fontPixelSize = view.getTextSize();
Display display = getWindowManager().getDefaultDisplay();
int h = Math.min(display.getWidth(), display.getHeight());
float ratio = (float) h / HVGA_WIDTH_PIXELS;
view.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontPixelSize * ratio);
}
public void restart() {
final Intent intent = getIntent();
/*
for compatibility with android_1.6_compatibility
overridePendingTransition(0, 0);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);*/
Log.d(this.getClass().getName(), "Finishing current activity!");
finish();
/*
for compatibility with android_1.6_compatibility
overridePendingTransition(0, 0);*/
Log.d(this.getClass().getName(), "Starting new activity!");
startActivity(intent);
}
@Override
protected void onResume() {
super.onResume();
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
final String newLayoutName = preferences.getString(getString(R.string.p_calc_layout_key), getString(R.string.p_calc_layout));
final String newThemeName = preferences.getString(getString(R.string.p_calc_theme_key), getString(R.string.p_calc_theme));
if (!themeName.equals(newThemeName) || !layoutName.equals(newLayoutName)) {
restart();
}
calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance);
calculatorModel.evaluate(calculatorModel.getDisplay().getJsclOperation());
}
@Override
protected void onDestroy() {
super.onDestroy();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, @Nullable String key) {
if (key != null && key.startsWith("org.solovyev.android.calculator.DragButtonCalibrationActivity")) {
dpclRegister.announce().onDragPreferencesChange(SimpleOnDragListener.getPreferences(preferences, this));
}
if (CalculatorEngine.Preferences.getPreferenceKeys().contains(key)) {
CalculatorEngine.instance.reset(this, preferences);
this.calculatorModel.evaluate();
}
if ( USE_BACK_AS_PREV_P_KEY.equals(key) ) {
useBackAsPrev = preferences.getBoolean(USE_BACK_AS_PREV_P_KEY, USE_BACK_AS_PREV_DEFAULT);
}
if ( CalculatorEngine.Preferences.multiplicationSign.getKey().equals(key) ) {
initMultiplicationButton();
}
}
private void initMultiplicationButton() {
final View multiplicationButton = findViewById(R.id.multiplicationButton);
if ( multiplicationButton instanceof Button) {
((Button) multiplicationButton).setText(CalculatorEngine.instance.getMultiplicationSign());
}
}
private static class RoundBracketsDragProcessor implements SimpleOnDragListener.DragProcessor {
@Override
public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
boolean result = false;
if ( dragDirection == DragDirection.left ) {
CalculatorModel.instance.doTextOperation(new CalculatorModel.TextOperation() {
@Override
public void doOperation(@NotNull EditText editor) {
final int cursorPosition = editor.getSelectionStart();
final StringBuilder text = new StringBuilder("(");
final String oldText = editor.getText().toString();
text.append(oldText.substring(0, cursorPosition));
text.append(")");
text.append(oldText.substring(cursorPosition));
editor.setText(text);
editor.setSelection(cursorPosition + 2);
}
});
result = true;
} else {
result = new DigitButtonDragProcessor(CalculatorModel.instance).processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent);
}
return result;
}
} }
} }

View File

@ -0,0 +1,26 @@
/*
* 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/2/12
* Time: 9:32 PM
*/
public class CalculatorActivityFree extends AbstractCalculatorActivity {
public CalculatorActivityFree() {
super(createApplicationData());
}
@NotNull
private static ApplicationData createApplicationData() {
return new ApplicationDataImpl(true, R.string.c_app_name_free, ApplicationData.Type.free);
}
}

View File

@ -280,7 +280,6 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
} }
public void processDigitButtonAction(@Nullable final String text, boolean delayEvaluate) { public void processDigitButtonAction(@Nullable final String text, boolean delayEvaluate) {
//Toast.makeText(CalculatorActivity.this, text, Toast.LENGTH_SHORT).show();
if (!StringUtils.isEmpty(text)) { if (!StringUtils.isEmpty(text)) {
doTextOperation(new CalculatorModel.TextOperation() { doTextOperation(new CalculatorModel.TextOperation() {

View File

@ -15,9 +15,8 @@ import android.widget.TextView;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.AndroidUtils; import org.solovyev.android.AndroidUtils;
import org.solovyev.android.ResourceCache; import org.solovyev.android.ResourceCache;
import org.solovyev.android.calculator.CalculatorActivity; import org.solovyev.android.calculator.AbstractCalculatorActivity;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.AndroidUtils;
import org.solovyev.common.utils.StringUtils; import org.solovyev.common.utils.StringUtils;
/** /**
@ -51,7 +50,7 @@ public class CalculatorReleaseNotesActivity extends Activity {
final StringBuilder result = new StringBuilder(); final StringBuilder result = new StringBuilder();
final String releaseNotesForTitle = context.getString(R.string.c_release_notes_for_title); final String releaseNotesForTitle = context.getString(R.string.c_release_notes_for_title);
final int version = AndroidUtils.getAppVersionCode(context, CalculatorActivity.class.getPackage().getName()); final int version = AndroidUtils.getAppVersionCode(context, AbstractCalculatorActivity.class.getPackage().getName());
boolean first = true; boolean first = true;
for ( int i = version; i >= minVersion; i-- ) { for ( int i = version; i >= minVersion; i-- ) {

View File

@ -15,7 +15,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.AndroidUtils; import org.solovyev.android.AndroidUtils;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.AndroidUtils;
/** /**
* User: serso * User: serso

View File

@ -6,26 +6,29 @@
package org.solovyev.android.calculator.history; package org.solovyev.android.calculator.history;
import android.app.AlertDialog;
import android.app.ListActivity; import android.app.ListActivity;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle; import android.os.Bundle;
import android.view.*; import android.view.MenuInflater;
import android.widget.*; import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ListView;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.CalculatorModel; import org.solovyev.android.calculator.CalculatorModel;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.view.AMenu;
import org.solovyev.android.view.AMenuBuilder; import org.solovyev.android.view.AMenuBuilder;
import org.solovyev.android.view.AMenuItem;
import org.solovyev.android.view.MenuImpl; import org.solovyev.android.view.MenuImpl;
import org.solovyev.common.utils.*; import org.solovyev.common.utils.*;
import org.solovyev.common.utils.Filter;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/** /**
* User: serso * User: serso

View File

@ -12,7 +12,6 @@ import android.widget.TabHost;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.solovyev.android.AndroidUtils; import org.solovyev.android.AndroidUtils;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.AndroidUtils;
/** /**
* User: serso * User: serso

View File

@ -13,7 +13,6 @@ import org.jetbrains.annotations.Nullable;
import org.solovyev.android.AndroidUtils; import org.solovyev.android.AndroidUtils;
import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.model.VarCategory; import org.solovyev.android.calculator.model.VarCategory;
import org.solovyev.android.AndroidUtils;
/** /**
* User: serso * User: serso

View File

@ -37,6 +37,11 @@ public class StringPreference<T> extends AbstractPreference<T> {
return new StringPreference<T>(id, parser.parseValue(defaultValue), parser); return new StringPreference<T>(id, parser.parseValue(defaultValue), parser);
} }
@NotNull
public static <T extends Enum> StringPreference<T> newInstance(@NotNull String id, @Nullable T defaultValue, @NotNull Class<T> enumType) {
return new StringPreference<T>(id, defaultValue, new EnumMapper<T>(enumType));
}
@Override @Override
protected T getPersistedValue(@NotNull SharedPreferences preferences) { protected T getPersistedValue(@NotNull SharedPreferences preferences) {
return mapper.parseValue(preferences.getString(getKey(), null)); return mapper.parseValue(preferences.getString(getKey(), null));