diff --git a/AndroidManifest.xml b/AndroidManifest.xml index d80ff689..20529517 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -13,9 +13,9 @@ + a:name="org.solovyev.android.calculator.ApplicationContext"> - @@ -25,71 +25,71 @@ - - - - - - - - - - - - - - - - - diff --git a/default.properties b/default.properties deleted file mode 100644 index b74c4880..00000000 --- a/default.properties +++ /dev/null @@ -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 diff --git a/pom.xml b/pom.xml index aae643d2..893eaf46 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ calculator 1.1.4 - pom + jar ${basedir}/src/misc/lib @@ -80,7 +80,6 @@ ${additionalLibs}/achartengine-0.7.0.jar - com.intellij annotations @@ -88,5 +87,4 @@ - \ No newline at end of file diff --git a/res/values-es/text_strings.xml b/res/values-es/text_strings.xml index c33c5187..df9aad27 100644 --- a/res/values-es/text_strings.xml +++ b/res/values-es/text_strings.xml @@ -8,6 +8,7 @@ Calculadora++ + Calculadora++ Free Calc++ Configuración Error diff --git a/res/values-it/text_strings.xml b/res/values-it/text_strings.xml index 3dd4d734..17415dc8 100644 --- a/res/values-it/text_strings.xml +++ b/res/values-it/text_strings.xml @@ -8,6 +8,7 @@ Calculator++ + Calculator++ Free Calc++ Impostazioni Errore diff --git a/res/values-ru/text_strings.xml b/res/values-ru/text_strings.xml index 89db23c9..2df378bf 100644 --- a/res/values-ru/text_strings.xml +++ b/res/values-ru/text_strings.xml @@ -8,6 +8,7 @@ Калькулятор++ + Калькулятор++ Free Кальк++ Настройки Ошибка @@ -162,4 +163,7 @@ Устанавливает поведение по нажатию на кнопку Назад Использовать кнопку назад как назад по истории + Внимание + Вы установили другую версию Калькулятора++.\nДля корректной работы приложения, пожалуйста, удалите предыдущую версию, все пользовательские данные будут автоматически перенесены в новое приложение. + \ No newline at end of file diff --git a/res/values/text_strings.xml b/res/values/text_strings.xml index cf9339ba..01fd64df 100644 --- a/res/values/text_strings.xml +++ b/res/values/text_strings.xml @@ -8,6 +8,7 @@ Calculator++ + Calculator++ Free Calc++ Settings Error @@ -162,4 +163,7 @@ Defines the behaviour of the Back button Use Back button as history prev + 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. + \ No newline at end of file diff --git a/src/main/java/org/solovyev/android/ResourceCache.java b/src/main/java/org/solovyev/android/ResourceCache.java index dd3b82c6..09dc56b6 100644 --- a/src/main/java/org/solovyev/android/ResourceCache.java +++ b/src/main/java/org/solovyev/android/ResourceCache.java @@ -15,7 +15,6 @@ import android.view.View; import android.widget.Button; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.CalculatorActivity; import org.solovyev.android.view.widgets.DragButton; import java.lang.reflect.Field; @@ -219,7 +218,7 @@ public enum ResourceCache { try { result.put(field.getName(), field.getInt(clazz)); } catch (IllegalAccessException e) { - Log.e(CalculatorActivity.class.getName(), e.getMessage()); + Log.e(ResourceCache.class.getName(), e.getMessage()); } } } diff --git a/src/main/java/org/solovyev/android/calculator/AbstractCalculatorActivity.java b/src/main/java/org/solovyev/android/calculator/AbstractCalculatorActivity.java new file mode 100644 index 00000000..297fe725 --- /dev/null +++ b/src/main/java/org/solovyev/android/calculator/AbstractCalculatorActivity.java @@ -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 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 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 dpclRegister = new Announcer(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(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 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 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¤cy_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; + } + } +} \ No newline at end of file diff --git a/src/main/java/org/solovyev/android/calculator/ApplicationData.java b/src/main/java/org/solovyev/android/calculator/ApplicationData.java new file mode 100644 index 00000000..afe2de29 --- /dev/null +++ b/src/main/java/org/solovyev/android/calculator/ApplicationData.java @@ -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(); + +} diff --git a/src/main/java/org/solovyev/android/calculator/ApplicationDataImpl.java b/src/main/java/org/solovyev/android/calculator/ApplicationDataImpl.java new file mode 100644 index 00000000..a1f04fe2 --- /dev/null +++ b/src/main/java/org/solovyev/android/calculator/ApplicationDataImpl.java @@ -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; + } +} diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java b/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java index 454c167c..e38bb76c 100644 --- a/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java +++ b/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java @@ -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 + * or visit http://se.solovyev.org */ 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.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; -import java.util.Map; +/** + * User: serso + * Date: 1/2/12 + * Time: 9:33 PM + */ +public class CalculatorActivity extends AbstractCalculatorActivity { -public class CalculatorActivity extends Activity implements FontSizeAdjuster, SharedPreferences.OnSharedPreferenceChangeListener { - - 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 dpclRegister = new Announcer(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(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); - } + public CalculatorActivity() { + super(createApplicationData()); } @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 static ApplicationData createApplicationData() { + return new ApplicationDataImpl(false, R.string.c_app_name, ApplicationData.Type.pro); } - - 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 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 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¤cy_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; - } - } -} \ No newline at end of file +} diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorActivityFree.java b/src/main/java/org/solovyev/android/calculator/CalculatorActivityFree.java new file mode 100644 index 00000000..1c13ffc8 --- /dev/null +++ b/src/main/java/org/solovyev/android/calculator/CalculatorActivityFree.java @@ -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); + } +} diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorModel.java b/src/main/java/org/solovyev/android/calculator/CalculatorModel.java index 9ce3515b..e5c4f80b 100644 --- a/src/main/java/org/solovyev/android/calculator/CalculatorModel.java +++ b/src/main/java/org/solovyev/android/calculator/CalculatorModel.java @@ -280,7 +280,6 @@ public enum CalculatorModel implements CursorControl, HistoryControl= minVersion; i-- ) { diff --git a/src/main/java/org/solovyev/android/calculator/help/CalculatorHelpTabActivity.java b/src/main/java/org/solovyev/android/calculator/help/CalculatorHelpTabActivity.java index 566aa6d1..ac2ad236 100644 --- a/src/main/java/org/solovyev/android/calculator/help/CalculatorHelpTabActivity.java +++ b/src/main/java/org/solovyev/android/calculator/help/CalculatorHelpTabActivity.java @@ -15,7 +15,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.solovyev.android.AndroidUtils; import org.solovyev.android.calculator.R; -import org.solovyev.android.AndroidUtils; /** * User: serso diff --git a/src/main/java/org/solovyev/android/calculator/history/AbstractHistoryActivity.java b/src/main/java/org/solovyev/android/calculator/history/AbstractHistoryActivity.java index dafaac7c..76990d9a 100644 --- a/src/main/java/org/solovyev/android/calculator/history/AbstractHistoryActivity.java +++ b/src/main/java/org/solovyev/android/calculator/history/AbstractHistoryActivity.java @@ -6,26 +6,29 @@ package org.solovyev.android.calculator.history; -import android.app.AlertDialog; import android.app.ListActivity; import android.content.Context; -import android.content.DialogInterface; import android.os.Bundle; -import android.view.*; -import android.widget.*; +import android.view.MenuInflater; +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.Nullable; import org.solovyev.android.calculator.CalculatorModel; import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.android.view.AMenu; import org.solovyev.android.view.AMenuBuilder; -import org.solovyev.android.view.AMenuItem; import org.solovyev.android.view.MenuImpl; 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 diff --git a/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryActivity.java b/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryActivity.java index ca86b9a2..a0b6e05a 100644 --- a/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryActivity.java +++ b/src/main/java/org/solovyev/android/calculator/history/CalculatorHistoryActivity.java @@ -12,7 +12,6 @@ import android.widget.TabHost; import org.jetbrains.annotations.Nullable; import org.solovyev.android.AndroidUtils; import org.solovyev.android.calculator.R; -import org.solovyev.android.AndroidUtils; /** * User: serso diff --git a/src/main/java/org/solovyev/android/calculator/math/edit/CalculatorVarsActivity.java b/src/main/java/org/solovyev/android/calculator/math/edit/CalculatorVarsActivity.java index f6834862..ad674e1a 100644 --- a/src/main/java/org/solovyev/android/calculator/math/edit/CalculatorVarsActivity.java +++ b/src/main/java/org/solovyev/android/calculator/math/edit/CalculatorVarsActivity.java @@ -13,7 +13,6 @@ import org.jetbrains.annotations.Nullable; import org.solovyev.android.AndroidUtils; import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.model.VarCategory; -import org.solovyev.android.AndroidUtils; /** * User: serso diff --git a/src/main/java/org/solovyev/android/view/prefs/StringPreference.java b/src/main/java/org/solovyev/android/view/prefs/StringPreference.java index de37604b..56ce5aca 100644 --- a/src/main/java/org/solovyev/android/view/prefs/StringPreference.java +++ b/src/main/java/org/solovyev/android/view/prefs/StringPreference.java @@ -37,6 +37,11 @@ public class StringPreference extends AbstractPreference { return new StringPreference(id, parser.parseValue(defaultValue), parser); } + @NotNull + public static StringPreference newInstance(@NotNull String id, @Nullable T defaultValue, @NotNull Class enumType) { + return new StringPreference(id, defaultValue, new EnumMapper(enumType)); + } + @Override protected T getPersistedValue(@NotNull SharedPreferences preferences) { return mapper.parseValue(preferences.getString(getKey(), null));