This commit is contained in:
Sergey Solovyev 2012-09-30 20:35:44 +04:00
parent 043576f5e8
commit e946b1547c
31 changed files with 2865 additions and 2192 deletions

View File

@ -1,22 +1,55 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import org.jetbrains.annotations.NotNull; import jscl.math.Generic;
import jscl.math.function.Constant;
/** import jscl.math.function.IConstant;
* User: serso import org.jetbrains.annotations.NotNull;
* Date: 9/22/12 import org.solovyev.android.calculator.jscl.JsclOperation;
* Time: 7:13 PM
*/ import java.util.HashSet;
public final class CalculatorUtils { import java.util.Set;
static final long FIRST_ID = 0; /**
* User: serso
private CalculatorUtils() { * Date: 9/22/12
throw new AssertionError(); * Time: 7:13 PM
} */
public final class CalculatorUtils {
@NotNull
public static CalculatorEventData createFirstEventDataId() { static final long FIRST_ID = 0;
return CalculatorEventDataImpl.newInstance(FIRST_ID, FIRST_ID);
} private CalculatorUtils() {
} throw new AssertionError();
}
@NotNull
public static CalculatorEventData createFirstEventDataId() {
return CalculatorEventDataImpl.newInstance(FIRST_ID, FIRST_ID);
}
@NotNull
public static Set<Constant> getNotSystemConstants(@NotNull Generic expression) {
final Set<Constant> notSystemConstants = new HashSet<Constant>();
for (Constant constant : expression.getConstants()) {
IConstant var = CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().get(constant.getName());
if (var != null && !var.isSystem() && !var.isDefined()) {
notSystemConstants.add(constant);
}
}
return notSystemConstants;
}
public static boolean isPlotPossible(@NotNull Generic expression, @NotNull JsclOperation operation) {
boolean result = false;
if (operation == JsclOperation.simplify) {
if (getNotSystemConstants(expression).size() == 1) {
result = true;
}
}
return result;
}
}

View File

@ -1,66 +1,60 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto" android:versionCode="81" android:versionName="1.3.2" <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto" android:versionCode="81" android:versionName="1.3.2"
package="org.solovyev.android.calculator"> package="org.solovyev.android.calculator">
<uses-permission android:name="android.permission.VIBRATE"/> <uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="com.android.vending.BILLING"/> <uses-permission android:name="com.android.vending.BILLING"/>
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="8"/> <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="8"/>
<application android:debuggable="true" android:hardwareAccelerated="false" android:icon="@drawable/icon" android:label="@string/c_app_name" android:name=".CalculatorApplication" android:theme="@style/metro_blue_theme"> <application android:debuggable="true" android:hardwareAccelerated="false" android:icon="@drawable/icon" android:label="@string/c_app_name" android:name=".CalculatorApplication" android:theme="@style/metro_blue_theme">
<activity android:label="@string/c_app_name" android:name=".CalculatorActivity" android:windowSoftInputMode="adjustPan"> <activity android:label="@string/c_app_name" android:name=".CalculatorActivity" android:windowSoftInputMode="adjustPan">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter> </intent-filter>
</activity> </activity>
<!--NOTE: a:configChanges="orientation|keyboardHidden" is needed to correct work of dialog windows (not to close them on orientation change) --> <!--NOTE: a:configChanges="orientation|keyboardHidden" is needed to correct work of dialog windows (not to close them on orientation change) -->
<activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_app_settings" android:name=".CalculatorPreferencesActivity"/> <activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_app_settings" android:name=".CalculatorPreferencesActivity"/>
<activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_history" android:name=".history.CalculatorHistoryFragmentActivity"/> <activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_history" android:name=".history.CalculatorHistoryFragmentActivity"/>
<activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_about" android:name=".about.CalculatorAboutTabActivity"/> <activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_about" android:name=".about.CalculatorAboutTabActivity"/>
<activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_about" android:name=".about.CalculatorAboutActivity"/> <activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_about" android:name=".about.CalculatorAboutActivity"/>
<activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_about" android:name=".about.CalculatorReleaseNotesActivity"/> <activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_about" android:name=".about.CalculatorReleaseNotesActivity"/>
<activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_help" android:name=".help.CalculatorHelpTabActivity"/> <activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_help" android:name=".help.CalculatorHelpTabActivity"/>
<activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_help" android:name=".help.HelpFaqActivity"/> <activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_help" android:name=".help.HelpFaqActivity"/>
<activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_help" android:name=".help.HelpHintsActivity"/> <activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_help" android:name=".help.HelpHintsActivity"/>
<activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_help" android:name=".help.HelpScreensActivity"/> <activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_help" android:name=".help.HelpScreensActivity"/>
<activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_functions" android:name=".math.edit.CalculatorFunctionsFragmentActivity"/> <activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_functions" android:name=".math.edit.CalculatorFunctionsFragmentActivity"/>
<activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_functions" android:name=".math.edit.CalculatorFunctionsFragment"/> <activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_vars_and_constants" android:name=".math.edit.CalculatorVarsFragmentActivity"/>
<activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_operators" android:name=".math.edit.CalculatorOperatorsFragment"/> <activity android:label="@string/c_plot_graph" android:name=".plot.CalculatorPlotActivity"/>
<activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_vars_and_constants" android:name=".math.edit.CalculatorVarsFragmentActivity"/> <activity android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" android:name="com.google.ads.AdActivity"/>
<activity android:configChanges="orientation|keyboardHidden" android:label="@string/c_vars_and_constants" android:name=".math.edit.CalculatorVarsFragment"/> <service android:name="net.robotmedia.billing.BillingService"/>
<receiver android:name="net.robotmedia.billing.BillingReceiver">
<activity android:label="@string/c_plot_graph" android:name=".plot.CalculatorPlotActivity"/> <intent-filter>
<action android:name="com.android.vending.billing.IN_APP_NOTIFY"/>
<activity android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" android:name="com.google.ads.AdActivity"/> <action android:name="com.android.vending.billing.RESPONSE_CODE"/>
<action android:name="com.android.vending.billing.PURCHASE_STATE_CHANGED"/>
<service android:name="net.robotmedia.billing.BillingService"/> </intent-filter>
<receiver android:name="net.robotmedia.billing.BillingReceiver"> </receiver>
<intent-filter>
<action android:name="com.android.vending.billing.IN_APP_NOTIFY"/> </application>
<action android:name="com.android.vending.billing.RESPONSE_CODE"/>
<action android:name="com.android.vending.billing.PURCHASE_STATE_CHANGED"/>
</intent-filter>
</receiver>
</application>
</manifest> </manifest>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2009-2011. Created by serso aka se.solovyev.
~ For more information, please, contact se.solovyev@gmail.com
~ or visit http://se.solovyev.org
-->
<org.solovyev.android.calculator.AndroidCalculatorDisplayView
xmlns:a="http://schemas.android.com/apk/res/android"
a:id="@+id/calculatorDisplay"
style="@style/display_style"
a:inputType="textMultiLine"
a:maxLines="3"
a:scrollHorizontally="false"
a:scrollbars="none"/>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2009-2011. Created by serso aka se.solovyev.
~ For more information, please, contact se.solovyev@gmail.com
~ or visit http://se.solovyev.org
-->
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:id="@+id/main_fragment_layout"
style="?fragmentLayoutStyle"
a:layout_width="match_parent"
a:layout_height="match_parent">
<TextView a:id="@+id/fragmentTitle"
a:layout_height="wrap_content"
a:layout_width="match_parent"
style="?fragmentTitleStyle"/>
<org.solovyev.android.calculator.AndroidCalculatorEditorView
a:id="@+id/calculatorEditor"
style="@style/editor_style"
a:textIsSelectable="true"
a:singleLine="false"
a:scrollbars="vertical"
a:hint ="@string/c_calc_editor_hint"/>
</LinearLayout>

View File

@ -10,6 +10,7 @@
xmlns:a="http://schemas.android.com/apk/res/android" xmlns:a="http://schemas.android.com/apk/res/android"
a:id="@+id/calculatorDisplay" a:id="@+id/calculatorDisplay"
style="@style/display_style" style="@style/display_style"
a:padding="@dimen/editor_padding"
a:inputType="textMultiLine" a:inputType="textMultiLine"
a:maxLines="3" a:maxLines="3"
a:scrollHorizontally="false" a:scrollHorizontally="false"

View File

@ -1,21 +1,24 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
~ Copyright (c) 2009-2011. Created by serso aka se.solovyev. ~ Copyright (c) 2009-2011. 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 ~ or visit http://se.solovyev.org
--> -->
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:layout_width="match_parent" a:id="@+id/main_fragment_layout"
a:layout_height="wrap_content"> style="?fragmentLayoutStyle"
a:layout_width="match_parent"
<org.solovyev.android.calculator.AndroidCalculatorEditorView a:layout_height="match_parent"
a:id="@+id/calculatorEditor" a:padding="@dimen/editor_padding">
style="@style/editor_style"
a:textIsSelectable="true" <org.solovyev.android.calculator.AndroidCalculatorEditorView
a:singleLine="false" a:id="@+id/calculatorEditor"
a:scrollbars="vertical" style="@style/editor_style"
a:hint ="@string/c_calc_editor_hint"/> a:textIsSelectable="true"
a:singleLine="false"
a:scrollbars="vertical"
a:hint="@string/c_calc_editor_hint"/>
</LinearLayout> </LinearLayout>

View File

@ -1,17 +1,16 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:orientation="vertical" a:id="@+id/main_fragment_layout"
a:id="@+id/main_fragment_layout" style="?fragmentLayoutStyle"
style="?fragmentLayoutStyle" a:layout_width="match_parent"
a:layout_width="match_parent" a:layout_height="match_parent">
a:layout_height="match_parent">
<TextView a:id="@+id/fragmentTitle"
<TextView a:id="@+id/fragmentTitle" a:layout_height="wrap_content"
a:layout_height="wrap_content" a:layout_width="match_parent"
a:layout_width="match_parent" style="?fragmentTitleStyle"/>
style="?fragmentTitleStyle"/>
<ListView style="?fragmentListViewStyle"/>
<ListView style="?fragmentListViewStyle"/>
</LinearLayout> </LinearLayout>

View File

@ -1,17 +1,16 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:orientation="vertical" a:id="@+id/main_fragment_layout"
a:id="@+id/main_fragment_layout" style="?fragmentLayoutStyle"
style="?fragmentLayoutStyle" a:layout_width="match_parent"
a:layout_width="match_parent" a:layout_height="match_parent">
a:layout_height="match_parent">
<TextView a:id="@+id/fragmentTitle"
<TextView a:id="@+id/fragmentTitle" a:layout_height="wrap_content"
a:layout_height="wrap_content" a:layout_width="match_parent"
a:layout_width="match_parent" style="?fragmentTitleStyle"/>
style="?fragmentTitleStyle"/>
<ListView style="?fragmentListViewStyle"/>
<ListView style="?fragmentListViewStyle"/>
</LinearLayout> </LinearLayout>

View File

@ -1,17 +1,16 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:orientation="vertical" a:id="@+id/main_fragment_layout"
a:id="@+id/main_fragment_layout" style="?fragmentLayoutStyle"
style="?fragmentLayoutStyle" a:layout_width="match_parent"
a:layout_width="match_parent" a:layout_height="match_parent">
a:layout_height="match_parent">
<TextView a:id="@+id/fragmentTitle"
<TextView a:id="@+id/fragmentTitle" a:layout_height="wrap_content"
a:layout_height="wrap_content" a:layout_width="match_parent"
a:layout_width="match_parent" style="?fragmentTitleStyle"/>
style="?fragmentTitleStyle"/>
<ListView style="?fragmentListViewStyle"/>
<ListView style="?fragmentListViewStyle"/>
</LinearLayout> </LinearLayout>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:id="@+id/main_fragment_layout"
style="?fragmentLayoutStyle"
a:layout_width="match_parent"
a:layout_height="match_parent">
<TextView a:id="@+id/fragmentTitle"
a:layout_height="wrap_content"
a:layout_width="match_parent"
style="?fragmentTitleStyle"/>
</LinearLayout>

View File

@ -1,31 +1,30 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
~ Copyright (c) 2009-2011. Created by serso aka se.solovyev. ~ Copyright (c) 2009-2011. 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 ~ or visit http://se.solovyev.org
--> -->
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:orientation="vertical" a:id="@+id/main_fragment_layout"
a:id="@+id/main_fragment_layout" style="?fragmentLayoutStyle"
style="?fragmentLayoutStyle" a:layout_width="match_parent"
a:layout_width="match_parent" a:layout_height="match_parent">
a:layout_height="match_parent">
<TextView a:id="@+id/fragmentTitle"
<TextView a:id="@+id/fragmentTitle" a:layout_height="wrap_content"
a:layout_height="wrap_content" a:layout_width="match_parent"
a:layout_width="match_parent" style="?fragmentTitleStyle"/>
style="?fragmentTitleStyle"/>
<ListView style="?fragmentListViewStyle"/>
<ListView style="?fragmentListViewStyle"/>
<!--todo serso: uncomment-->
<!--todo serso: uncomment--> <!--<Button
<!--<Button a:id="@+id/add_var_button"
a:id="@+id/add_var_button" a:text="@string/c_add"
a:text="@string/c_add" style="?buttonStyle"
style="?buttonStyle" a:onClick="addVarButtonClickHandler"
a:onClick="addVarButtonClickHandler" a:layout_marginBottom="@dimen/pane_padding"/>-->
a:layout_marginBottom="@dimen/pane_padding"/>-->
</LinearLayout> </LinearLayout>

View File

@ -1,3 +1,5 @@
<resources> <resources>
<dimen name="keyboard_button_text_size">20dp</dimen> <dimen name="editor_text_size">15sp</dimen>
<dimen name="display_text_size">15sp</dimen>
<dimen name="keyboard_button_text_size">20dp</dimen>
</resources> </resources>

View File

@ -1,10 +1,14 @@
<resources> <resources>
<dimen name="button_margin">0.5dp</dimen> <dimen name="button_margin">0.5dp</dimen>
<dimen name="text_size">20sp</dimen> <dimen name="text_size">20sp</dimen>
<dimen name="keyboard_button_text_size">30dp</dimen> <dimen name="keyboard_button_text_size">30dp</dimen>
<dimen name="button_text_size">20dp</dimen> <dimen name="button_text_size">20dp</dimen>
<dimen name="display_text_size">25sp</dimen> <dimen name="display_text_size">25sp</dimen>
<dimen name="editor_text_size">25sp</dimen> <dimen name="editor_text_size">25sp</dimen>
<dimen name="pane_margin">5dp</dimen> <dimen name="pane_margin">5dp</dimen>
<dimen name="pane_padding">5dp</dimen> <dimen name="pane_padding">5dp</dimen>
<!--only for not multipane-->
<dimen name="editor_padding">5dp</dimen>
<dimen name="display_padding">3dp</dimen>
</resources> </resources>

View File

@ -1,96 +1,97 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
~ Copyright (c) 2009-2011. Created by serso aka se.solovyev. ~ Copyright (c) 2009-2011. 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 ~ or visit http://se.solovyev.org
--> -->
<resources> <resources>
<style name="default_digit_button_style" parent="keyboard_button_style"> <style name="default_digit_button_style" parent="keyboard_button_style">
<item name="android:background">@drawable/default_button</item> <item name="android:background">@drawable/default_button</item>
</style> </style>
<style name="default_control_button_style" parent="keyboard_button_style"/> <style name="default_control_button_style" parent="keyboard_button_style"/>
<style name="default_operation_button_style" parent="default_digit_button_style"> <style name="default_operation_button_style" parent="default_digit_button_style">
<item name="android:textColor">@color/button_operator_text_color</item> <item name="android:textColor">@color/button_operator_text_color</item>
</style> </style>
<style name="default_control_image_button_style" parent="default_control_button_style"> <style name="default_control_image_button_style" parent="default_control_button_style">
<item name="android:padding">6dp</item> <item name="android:padding">6dp</item>
</style> </style>
<style name="default_fragment_list_view_style"> <style name="default_fragment_list_view_style">
<item name="android:id">@android:id/list</item> <item name="android:id">@android:id/list</item>
<item name="android:divider">@null</item> <item name="android:divider">@null</item>
<item name="android:dividerHeight">0dp</item> <item name="android:dividerHeight">0dp</item>
<item name="android:cacheColorHint">@android:color/transparent</item> <item name="android:cacheColorHint">@android:color/transparent</item>
<item name="android:layout_height">match_parent</item> <item name="android:layout_height">match_parent</item>
<item name="android:layout_width">match_parent</item> <item name="android:layout_width">match_parent</item>
<item name="android:layout_weight">1</item> <item name="android:layout_weight">1</item>
<item name="android:fadingEdge">none</item> <item name="android:fadingEdge">none</item>
<item name="android:layout_marginBottom">@dimen/pane_padding</item> <item name="android:layout_marginBottom">@dimen/pane_padding</item>
</style> </style>
<style name="default_fragment_title_style"> <style name="default_fragment_title_style">
<item name="android:textColor">@android:color/white</item> <item name="android:textColor">@android:color/white</item>
<item name="android:textSize">25sp</item> <item name="android:textSize">20sp</item>
</style> </style>
<style name="default_button_style" parent="button_style"> <style name="default_button_style" parent="button_style">
<item name="android:paddingTop">5dp</item> <item name="android:paddingTop">5dp</item>
<item name="android:paddingBottom">5dp</item> <item name="android:paddingBottom">5dp</item>
<item name="android:paddingLeft">10dp</item> <item name="android:paddingLeft">10dp</item>
<item name="android:paddingRight">10dp</item> <item name="android:paddingRight">10dp</item>
</style> </style>
<style name="default_pane_style_transparent" parent="default_pane_style"> <style name="default_pane_style_transparent" parent="default_pane_style">
<item name="android:background">@android:color/transparent</item> <item name="android:background">@android:color/transparent</item>
<item name="android:padding">0dp</item> <item name="android:padding">0dp</item>
</style> </style>
<style name="default_pane_style"> <style name="default_pane_style">
<item name="android:layout_marginLeft">@dimen/pane_margin</item> <item name="android:layout_marginLeft">@dimen/pane_margin</item>
<item name="android:layout_marginTop">@dimen/pane_margin</item> <item name="android:layout_marginTop">@dimen/pane_margin</item>
<item name="android:padding">@dimen/pane_padding</item> <item name="android:padding">@dimen/pane_padding</item>
<item name="android:background">@drawable/pane_background</item> <item name="android:background">@drawable/pane_background</item>
</style> </style>
<style name="default_main_multi_pane_layout_style" parent="default_main_layout_style"> <style name="default_main_multi_pane_layout_style" parent="default_main_layout_style">
<item name="android:paddingRight">@dimen/pane_padding</item> <item name="android:paddingRight">@dimen/pane_padding</item>
<item name="android:paddingBottom">@dimen/pane_padding</item> <item name="android:paddingBottom">@dimen/pane_padding</item>
</style> </style>
<style name="default_fragment_multi_pane_layout_style" parent="default_fragment_layout_style"> <style name="default_fragment_multi_pane_layout_style" parent="default_fragment_layout_style">
</style> </style>
<style name="default_fragment_layout_style"> <style name="default_fragment_layout_style">
<item name="android:layout_margin">0dp</item> <item name="android:layout_margin">0dp</item>
<item name="android:padding">0dp</item> <item name="android:padding">0dp</item>
</style> <item name="android:orientation">vertical</item>
</style>
<style name="default_main_layout_style">
<item name="android:background">@color/default_background</item> <style name="default_main_layout_style">
<item name="android:baselineAligned">false</item> <item name="android:background">@color/default_background</item>
<item name="android:layout_height">match_parent</item> <item name="android:baselineAligned">false</item>
<item name="android:layout_width">match_parent</item> <item name="android:layout_height">match_parent</item>
</style> <item name="android:layout_width">match_parent</item>
</style>
<style name="default_theme" parent="Theme.Sherlock">
<item name="digitButtonStyle">@style/default_digit_button_style</item> <style name="default_theme" parent="Theme.Sherlock">
<item name="controlButtonStyle">@style/default_control_button_style</item> <item name="digitButtonStyle">@style/default_digit_button_style</item>
<item name="controlImageButtonStyle">@style/default_control_image_button_style</item> <item name="controlButtonStyle">@style/default_control_button_style</item>
<item name="operationButtonStyle">@style/default_operation_button_style</item> <item name="controlImageButtonStyle">@style/default_control_image_button_style</item>
<item name="fragmentTitleStyle">@style/default_fragment_title_style</item> <item name="operationButtonStyle">@style/default_operation_button_style</item>
<item name="fragmentListViewStyle">@style/default_fragment_list_view_style</item> <item name="fragmentTitleStyle">@style/default_fragment_title_style</item>
<item name="buttonStyle">@style/default_button_style</item> <item name="fragmentListViewStyle">@style/default_fragment_list_view_style</item>
<item name="buttonStyle">@style/default_button_style</item>
<item name="mainLayoutStyle">@style/default_main_layout_style</item>
<item name="mainMultiPaneLayoutStyle">@style/default_main_multi_pane_layout_style</item> <item name="mainLayoutStyle">@style/default_main_layout_style</item>
<item name="mainMultiPaneLayoutStyle">@style/default_main_multi_pane_layout_style</item>
<item name="fragmentLayoutStyle">@style/default_fragment_layout_style</item>
<item name="fragmentLayoutStyle">@style/default_fragment_layout_style</item>
<item name="paneStyle">@style/default_pane_style</item>
<item name="paneStyleTransparent">@style/default_pane_style_transparent</item> <item name="paneStyle">@style/default_pane_style</item>
</style> <item name="paneStyleTransparent">@style/default_pane_style_transparent</item>
</style>
</resources> </resources>

View File

@ -1,65 +1,63 @@
<!-- <!--
~ Copyright (c) 2009-2011. Created by serso aka se.solovyev. ~ Copyright (c) 2009-2011. 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 ~ or visit http://se.solovyev.org
--> -->
<resources> <resources>
<style name="WindowTitle"> <style name="WindowTitle">
<item name="android:singleLine">true</item> <item name="android:singleLine">true</item>
<item name="android:textAppearance">@style/TextAppearance_WindowTitle</item> <item name="android:textAppearance">@style/TextAppearance_WindowTitle</item>
<item name="android:shadowColor">#BB000000</item> <item name="android:shadowColor">#BB000000</item>
<item name="android:shadowRadius">2.75</item> <item name="android:shadowRadius">2.75</item>
</style> </style>
<style name="TextAppearance_WindowTitle"> <style name="TextAppearance_WindowTitle">
<item name="android:textColor">#fff</item> <item name="android:textColor">#fff</item>
<item name="android:textSize">14sp</item> <item name="android:textSize">14sp</item>
<item name="android:textStyle">bold</item> <item name="android:textStyle">bold</item>
</style> </style>
<style name="default_text_size"> <style name="default_text_size">
<item name="android:textSize">@dimen/text_size</item> <item name="android:textSize">@dimen/text_size</item>
</style> </style>
<style name="keyboard_button_style_parent"> <style name="keyboard_button_style_parent">
<item name="android:textSize">@dimen/keyboard_button_text_size</item> <item name="android:textSize">@dimen/keyboard_button_text_size</item>
<item name="android:textColor">@color/button_text_color</item> <item name="android:textColor">@color/button_text_color</item>
</style> </style>
<style name="button_style_parent"> <style name="button_style_parent">
<item name="android:textSize">@dimen/button_text_size</item> <item name="android:textSize">@dimen/button_text_size</item>
<item name="android:textColor">@color/button_text_color</item> <item name="android:textColor">@color/button_text_color</item>
</style> </style>
<style name="display_style_parent" parent="default_text"> <style name="display_style_parent" parent="default_text">
<item name="android:textSize">@dimen/display_text_size</item> <item name="android:textSize">@dimen/display_text_size</item>
<item name="android:padding">3dp</item> </style>
</style>
<style name="editor_style_parent" parent="default_text">
<style name="editor_style_parent" parent="default_text"> <item name="android:textSize">@dimen/editor_text_size</item>
<item name="android:textSize">@dimen/editor_text_size</item> </style>
<item name="android:padding">5dp</item>
</style> <style name="about_style_parent" parent="default_text">
<item name="android:textSize">15dp</item>
<style name="about_style_parent" parent="default_text"> <item name="android:padding">5dp</item>
<item name="android:textSize">15dp</item> </style>
<item name="android:padding">5dp</item>
</style> <style name="math_entity_text_parent">
<item name="android:textSize">20dp</item>
<style name="math_entity_text_parent"> </style>
<item name="android:textSize">20dp</item>
</style> <style name="math_entity_description_parent">
<item name="android:textSize">15dp</item>
<style name="math_entity_description_parent"> </style>
<item name="android:textSize">15dp</item>
</style> <style name="add_var_button_parent">
<item name="android:paddingLeft">40dp</item>
<style name="add_var_button_parent"> <item name="android:paddingRight">40dp</item>
<item name="android:paddingLeft">40dp</item> </style>
<item name="android:paddingRight">40dp</item>
</style>
</resources> </resources>

View File

@ -207,4 +207,6 @@
<string name="convert_to_bin">Convert to bin</string> <string name="convert_to_bin">Convert to bin</string>
<string name="convert_to_dec">Convert to dec</string> <string name="convert_to_dec">Convert to dec</string>
<string name="editor">Editor</string>
</resources> </resources>

View File

@ -1,352 +1,354 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com * For more information, please, contact se.solovyev@gmail.com
*/ */
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.Html; import android.text.Html;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.util.Log; import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.app.SherlockFragmentActivity;
import net.robotmedia.billing.BillingController; import net.robotmedia.billing.BillingController;
import net.robotmedia.billing.IBillingObserver; import net.robotmedia.billing.IBillingObserver;
import org.jetbrains.annotations.NotNull; 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.about.CalculatorReleaseNotesActivity; import org.solovyev.android.calculator.about.CalculatorReleaseNotesActivity;
import org.solovyev.android.calculator.history.CalculatorHistoryFragment; import org.solovyev.android.calculator.history.CalculatorHistoryFragment;
import org.solovyev.android.calculator.history.CalculatorSavedHistoryFragment; import org.solovyev.android.calculator.history.CalculatorSavedHistoryFragment;
import org.solovyev.android.calculator.math.edit.CalculatorFunctionsFragment; import org.solovyev.android.calculator.math.edit.CalculatorFunctionsFragment;
import org.solovyev.android.calculator.math.edit.CalculatorOperatorsFragment; import org.solovyev.android.calculator.math.edit.CalculatorOperatorsFragment;
import org.solovyev.android.calculator.math.edit.CalculatorVarsFragment; import org.solovyev.android.calculator.math.edit.CalculatorVarsFragment;
import org.solovyev.android.fragments.FragmentUtils; import org.solovyev.android.calculator.plot.CalculatorPlotFragment;
import org.solovyev.android.prefs.Preference; import org.solovyev.android.fragments.FragmentUtils;
import org.solovyev.android.view.ColorButton; import org.solovyev.android.prefs.Preference;
import org.solovyev.common.equals.EqualsTool; import org.solovyev.android.view.ColorButton;
import org.solovyev.common.history.HistoryAction; import org.solovyev.common.equals.EqualsTool;
import org.solovyev.common.text.StringUtils; import org.solovyev.common.history.HistoryAction;
import org.solovyev.common.text.StringUtils;
public class CalculatorActivity extends SherlockFragmentActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
public class CalculatorActivity extends SherlockFragmentActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
@NotNull
public static final String TAG = CalculatorActivity.class.getSimpleName(); @NotNull
public static final String TAG = CalculatorActivity.class.getSimpleName();
@Nullable
private IBillingObserver billingObserver; @Nullable
private IBillingObserver billingObserver;
private boolean useBackAsPrev;
private boolean useBackAsPrev;
@NotNull
private CalculatorActivityHelper activityHelper; @NotNull
private CalculatorActivityHelper activityHelper;
/**
* Called when the activity is first created. /**
*/ * Called when the activity is first created.
@Override */
public void onCreate(@Nullable Bundle savedInstanceState) { @Override
public void onCreate(@Nullable Bundle savedInstanceState) {
CalculatorApplication.registerOnRemoteStackTrace();
CalculatorApplication.registerOnRemoteStackTrace();
/*final boolean customTitleSupported = requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);*/
/*final boolean customTitleSupported = requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);*/
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
final CalculatorPreferences.Gui.Layout layout = CalculatorPreferences.Gui.layout.getPreferenceNoError(preferences);
final CalculatorPreferences.Gui.Layout layout = CalculatorPreferences.Gui.layout.getPreferenceNoError(preferences);
activityHelper = CalculatorApplication.getInstance().createActivityHelper(layout.getLayoutId(), TAG);
activityHelper.logDebug("onCreate"); activityHelper = CalculatorApplication.getInstance().createActivityHelper(layout.getLayoutId(), TAG);
activityHelper.onCreate(this, savedInstanceState); activityHelper.logDebug("onCreate");
activityHelper.onCreate(this, savedInstanceState);
super.onCreate(savedInstanceState);
activityHelper.logDebug("super.onCreate"); super.onCreate(savedInstanceState);
activityHelper.logDebug("super.onCreate");
if (findViewById(R.id.main_second_pane) != null) {
activityHelper.addTab(this, "history", CalculatorHistoryFragment.class, null, R.string.c_history, R.id.main_second_pane); if (findViewById(R.id.main_second_pane) != null) {
activityHelper.addTab(this, "saved_history", CalculatorSavedHistoryFragment.class, null, R.string.c_saved_history, R.id.main_second_pane); activityHelper.addTab(this, "history", CalculatorHistoryFragment.class, null, R.string.c_history, R.id.main_second_pane);
activityHelper.addTab(this, "vars", CalculatorVarsFragment.class, null, R.string.c_vars, R.id.main_second_pane); activityHelper.addTab(this, "saved_history", CalculatorSavedHistoryFragment.class, null, R.string.c_saved_history, R.id.main_second_pane);
activityHelper.addTab(this, "functions", CalculatorFunctionsFragment.class, null, R.string.c_functions, R.id.main_second_pane); activityHelper.addTab(this, "vars", CalculatorVarsFragment.class, null, R.string.c_vars, R.id.main_second_pane);
activityHelper.addTab(this, "operators", CalculatorOperatorsFragment.class, null, R.string.c_operators, R.id.main_second_pane); activityHelper.addTab(this, "functions", CalculatorFunctionsFragment.class, null, R.string.c_functions, R.id.main_second_pane);
activityHelper.addTab(this, "operators", CalculatorOperatorsFragment.class, null, R.string.c_operators, R.id.main_second_pane);
activityHelper.restoreSavedTab(this); activityHelper.addTab(this, "plot", CalculatorPlotFragment.class, null, R.string.c_plot, R.id.main_second_pane);
} else {
getSupportActionBar().hide(); activityHelper.restoreSavedTab(this);
} } else {
getSupportActionBar().hide();
FragmentUtils.createFragment(this, CalculatorEditorFragment.class, R.id.editorContainer, "editor"); }
FragmentUtils.createFragment(this, CalculatorDisplayFragment.class, R.id.displayContainer, "display");
FragmentUtils.createFragment(this, CalculatorKeyboardFragment.class, R.id.keyboardContainer, "keyboard"); FragmentUtils.createFragment(this, CalculatorEditorFragment.class, R.id.editorContainer, "editor");
FragmentUtils.createFragment(this, CalculatorDisplayFragment.class, R.id.displayContainer, "display");
/*if (customTitleSupported) { FragmentUtils.createFragment(this, CalculatorKeyboardFragment.class, R.id.keyboardContainer, "keyboard");
try {
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.calc_title); /*if (customTitleSupported) {
final CalculatorAdditionalTitle additionalAdditionalTitleText = (CalculatorAdditionalTitle)findViewById(R.id.additional_title_text); try {
additionalAdditionalTitleText.init(preferences); getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.calc_title);
preferences.registerOnSharedPreferenceChangeListener(additionalAdditionalTitleText); final CalculatorAdditionalTitle additionalAdditionalTitleText = (CalculatorAdditionalTitle)findViewById(R.id.additional_title_text);
} catch (ClassCastException e) { additionalAdditionalTitleText.init(preferences);
// super fix for issue with class cast in android.view.Window.setFeatureInt() (see app error reports) preferences.registerOnSharedPreferenceChangeListener(additionalAdditionalTitleText);
Log.e(CalculatorActivity.class.getName(), e.getMessage(), e); } catch (ClassCastException e) {
} // super fix for issue with class cast in android.view.Window.setFeatureInt() (see app error reports)
}*/ Log.e(CalculatorActivity.class.getName(), e.getMessage(), e);
}
billingObserver = new CalculatorBillingObserver(this); }*/
BillingController.registerObserver(billingObserver);
billingObserver = new CalculatorBillingObserver(this);
this.useBackAsPrev = CalculatorPreferences.Gui.usePrevAsBack.getPreference(preferences); BillingController.registerObserver(billingObserver);
firstTimeInit(preferences, this);
this.useBackAsPrev = CalculatorPreferences.Gui.usePrevAsBack.getPreference(preferences);
// init billing controller firstTimeInit(preferences, this);
BillingController.checkBillingSupported(this);
// init billing controller
toggleOrientationChange(preferences); BillingController.checkBillingSupported(this);
CalculatorButtons.toggleEqualsButton(preferences, this, activityHelper.getTheme(), findViewById(R.id.main_layout)); toggleOrientationChange(preferences);
preferences.registerOnSharedPreferenceChangeListener(this); CalculatorButtons.toggleEqualsButton(preferences, this, activityHelper.getTheme(), findViewById(R.id.main_layout));
}
preferences.registerOnSharedPreferenceChangeListener(this);
@NotNull }
private AndroidCalculator getCalculator() {
return ((AndroidCalculator) CalculatorLocatorImpl.getInstance().getCalculator()); @NotNull
} private AndroidCalculator getCalculator() {
return ((AndroidCalculator) CalculatorLocatorImpl.getInstance().getCalculator());
private static void firstTimeInit(@NotNull SharedPreferences preferences, @NotNull Context context) { }
final Integer appOpenedCounter = CalculatorPreferences.appOpenedCounter.getPreference(preferences);
if (appOpenedCounter != null) { private static void firstTimeInit(@NotNull SharedPreferences preferences, @NotNull Context context) {
CalculatorPreferences.appOpenedCounter.putPreference(preferences, appOpenedCounter + 1); final Integer appOpenedCounter = CalculatorPreferences.appOpenedCounter.getPreference(preferences);
} if (appOpenedCounter != null) {
CalculatorPreferences.appOpenedCounter.putPreference(preferences, appOpenedCounter + 1);
final Integer savedVersion = CalculatorPreferences.appVersion.getPreference(preferences); }
final int appVersion = AndroidUtils.getAppVersionCode(context, CalculatorActivity.class.getPackage().getName()); final Integer savedVersion = CalculatorPreferences.appVersion.getPreference(preferences);
CalculatorPreferences.appVersion.putPreference(preferences, appVersion); final int appVersion = AndroidUtils.getAppVersionCode(context, CalculatorActivity.class.getPackage().getName());
boolean dialogShown = false; CalculatorPreferences.appVersion.putPreference(preferences, appVersion);
if (EqualsTool.areEqual(savedVersion, CalculatorPreferences.appVersion.getDefaultValue())) {
// new start boolean dialogShown = false;
final AlertDialog.Builder builder = new AlertDialog.Builder(context).setMessage(R.string.c_first_start_text); if (EqualsTool.areEqual(savedVersion, CalculatorPreferences.appVersion.getDefaultValue())) {
builder.setPositiveButton(android.R.string.ok, null); // new start
builder.setTitle(R.string.c_first_start_text_title); final AlertDialog.Builder builder = new AlertDialog.Builder(context).setMessage(R.string.c_first_start_text);
builder.create().show(); builder.setPositiveButton(android.R.string.ok, null);
dialogShown = true; builder.setTitle(R.string.c_first_start_text_title);
} else { builder.create().show();
if (savedVersion < appVersion) { dialogShown = true;
final boolean showReleaseNotes = CalculatorPreferences.Gui.showReleaseNotes.getPreference(preferences); } else {
if (showReleaseNotes) { if (savedVersion < appVersion) {
final String releaseNotes = CalculatorReleaseNotesActivity.getReleaseNotes(context, savedVersion + 1); final boolean showReleaseNotes = CalculatorPreferences.Gui.showReleaseNotes.getPreference(preferences);
if (!StringUtils.isEmpty(releaseNotes)) { if (showReleaseNotes) {
final AlertDialog.Builder builder = new AlertDialog.Builder(context).setMessage(Html.fromHtml(releaseNotes)); final String releaseNotes = CalculatorReleaseNotesActivity.getReleaseNotes(context, savedVersion + 1);
builder.setPositiveButton(android.R.string.ok, null); if (!StringUtils.isEmpty(releaseNotes)) {
builder.setTitle(R.string.c_release_notes); final AlertDialog.Builder builder = new AlertDialog.Builder(context).setMessage(Html.fromHtml(releaseNotes));
builder.create().show(); builder.setPositiveButton(android.R.string.ok, null);
dialogShown = true; builder.setTitle(R.string.c_release_notes);
} builder.create().show();
} dialogShown = true;
} }
} }
}
}
//Log.d(this.getClass().getName(), "Application was opened " + appOpenedCounter + " time!");
if (!dialogShown) {
if (appOpenedCounter != null && appOpenedCounter > 10) { //Log.d(this.getClass().getName(), "Application was opened " + appOpenedCounter + " time!");
dialogShown = showSpecialWindow(preferences, CalculatorPreferences.Gui.feedbackWindowShown, R.layout.feedback, R.id.feedbackText, context); if (!dialogShown) {
} if (appOpenedCounter != null && appOpenedCounter > 10) {
} dialogShown = showSpecialWindow(preferences, CalculatorPreferences.Gui.feedbackWindowShown, R.layout.feedback, R.id.feedbackText, context);
}
if (!dialogShown) { }
dialogShown = showSpecialWindow(preferences, CalculatorPreferences.Gui.notesppAnnounceShown, R.layout.notespp_announce, R.id.notespp_announce, context);
} if (!dialogShown) {
} dialogShown = showSpecialWindow(preferences, CalculatorPreferences.Gui.notesppAnnounceShown, R.layout.notespp_announce, R.id.notespp_announce, context);
}
private static boolean showSpecialWindow(@NotNull SharedPreferences preferences, @NotNull Preference<Boolean> specialWindowShownPref, int layoutId, int textViewId, @NotNull Context context) { }
boolean result = false;
private static boolean showSpecialWindow(@NotNull SharedPreferences preferences, @NotNull Preference<Boolean> specialWindowShownPref, int layoutId, int textViewId, @NotNull Context context) {
final Boolean specialWindowShown = specialWindowShownPref.getPreference(preferences); boolean result = false;
if ( specialWindowShown != null && !specialWindowShown ) {
final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE); final Boolean specialWindowShown = specialWindowShownPref.getPreference(preferences);
final View view = layoutInflater.inflate(layoutId, null); if ( specialWindowShown != null && !specialWindowShown ) {
final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
final TextView feedbackTextView = (TextView) view.findViewById(textViewId); final View view = layoutInflater.inflate(layoutId, null);
feedbackTextView.setMovementMethod(LinkMovementMethod.getInstance());
final TextView feedbackTextView = (TextView) view.findViewById(textViewId);
final AlertDialog.Builder builder = new AlertDialog.Builder(context).setView(view); feedbackTextView.setMovementMethod(LinkMovementMethod.getInstance());
builder.setPositiveButton(android.R.string.ok, null);
builder.create().show(); final AlertDialog.Builder builder = new AlertDialog.Builder(context).setView(view);
builder.setPositiveButton(android.R.string.ok, null);
result = true; builder.create().show();
specialWindowShownPref.putPreference(preferences, true);
} result = true;
specialWindowShownPref.putPreference(preferences, true);
return result; }
}
return result;
@Override }
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) { @Override
if (useBackAsPrev) { public boolean onKeyDown(int keyCode, KeyEvent event) {
getCalculator().doHistoryAction(HistoryAction.undo); if (keyCode == KeyEvent.KEYCODE_BACK) {
return true; if (useBackAsPrev) {
} getCalculator().doHistoryAction(HistoryAction.undo);
} return true;
return super.onKeyDown(keyCode, event); }
} }
return super.onKeyDown(keyCode, event);
@SuppressWarnings({"UnusedDeclaration"}) }
public void equalsButtonClickHandler(@NotNull View v) {
getCalculator().evaluate(); @SuppressWarnings({"UnusedDeclaration"})
} public void equalsButtonClickHandler(@NotNull View v) {
getCalculator().evaluate();
@Override }
protected void onResume() {
super.onResume(); @Override
protected void onResume() {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); super.onResume();
final CalculatorPreferences.Gui.Layout newLayout = CalculatorPreferences.Gui.layout.getPreference(preferences);
if ( newLayout.getLayoutId() != activityHelper.getLayoutId() ) { final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
AndroidUtils.restartActivity(this); final CalculatorPreferences.Gui.Layout newLayout = CalculatorPreferences.Gui.layout.getPreference(preferences);
} if ( newLayout.getLayoutId() != activityHelper.getLayoutId() ) {
AndroidUtils.restartActivity(this);
this.activityHelper.onResume(this); }
}
this.activityHelper.onResume(this);
@Override }
protected void onDestroy() {
if (billingObserver != null) { @Override
BillingController.unregisterObserver(billingObserver); protected void onDestroy() {
} if (billingObserver != null) {
BillingController.unregisterObserver(billingObserver);
activityHelper.onDestroy(this); }
super.onDestroy(); activityHelper.onDestroy(this);
}
super.onDestroy();
@Override }
public void onSharedPreferenceChanged(SharedPreferences preferences, @Nullable String key) {
if ( CalculatorPreferences.Gui.usePrevAsBack.getKey().equals(key) ) { @Override
useBackAsPrev = CalculatorPreferences.Gui.usePrevAsBack.getPreference(preferences); public void onSharedPreferenceChanged(SharedPreferences preferences, @Nullable String key) {
} if ( CalculatorPreferences.Gui.usePrevAsBack.getKey().equals(key) ) {
useBackAsPrev = CalculatorPreferences.Gui.usePrevAsBack.getPreference(preferences);
if ( CalculatorPreferences.Gui.autoOrientation.getKey().equals(key) ) { }
toggleOrientationChange(preferences);
} if ( CalculatorPreferences.Gui.autoOrientation.getKey().equals(key) ) {
} toggleOrientationChange(preferences);
}
@Override }
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); @Override
protected void onSaveInstanceState(Bundle outState) {
activityHelper.onSaveInstanceState(this, outState); super.onSaveInstanceState(outState);
}
activityHelper.onSaveInstanceState(this, outState);
private void toggleOrientationChange(@Nullable SharedPreferences preferences) { }
preferences = preferences == null ? PreferenceManager.getDefaultSharedPreferences(this) : preferences;
if (CalculatorPreferences.Gui.autoOrientation.getPreference(preferences)) { private void toggleOrientationChange(@Nullable SharedPreferences preferences) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); preferences = preferences == null ? PreferenceManager.getDefaultSharedPreferences(this) : preferences;
} else { if (CalculatorPreferences.Gui.autoOrientation.getPreference(preferences)) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
} } else {
} setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
/* }
**********************************************************************
* /*
* BUTTON HANDLERS **********************************************************************
* *
********************************************************************** * BUTTON HANDLERS
*/ *
**********************************************************************
@SuppressWarnings({"UnusedDeclaration"}) */
public void elementaryButtonClickHandler(@NotNull View v) {
throw new UnsupportedOperationException("Not implemented yet!"); @SuppressWarnings({"UnusedDeclaration"})
} public void elementaryButtonClickHandler(@NotNull View v) {
throw new UnsupportedOperationException("Not implemented yet!");
@SuppressWarnings({"UnusedDeclaration"}) }
public void historyButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showHistory(this); @SuppressWarnings({"UnusedDeclaration"})
} public void historyButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showHistory(this);
@SuppressWarnings({"UnusedDeclaration"}) }
public void eraseButtonClickHandler(@NotNull View v) {
CalculatorLocatorImpl.getInstance().getEditor().erase(); @SuppressWarnings({"UnusedDeclaration"})
} public void eraseButtonClickHandler(@NotNull View v) {
CalculatorLocatorImpl.getInstance().getEditor().erase();
@SuppressWarnings({"UnusedDeclaration"}) }
public void simplifyButtonClickHandler(@NotNull View v) {
throw new UnsupportedOperationException("Not implemented yet!"); @SuppressWarnings({"UnusedDeclaration"})
} public void simplifyButtonClickHandler(@NotNull View v) {
throw new UnsupportedOperationException("Not implemented yet!");
@SuppressWarnings({"UnusedDeclaration"}) }
public void moveLeftButtonClickHandler(@NotNull View v) {
getKeyboard().moveCursorLeft(); @SuppressWarnings({"UnusedDeclaration"})
} public void moveLeftButtonClickHandler(@NotNull View v) {
getKeyboard().moveCursorLeft();
@SuppressWarnings({"UnusedDeclaration"}) }
public void moveRightButtonClickHandler(@NotNull View v) {
getKeyboard().moveCursorRight(); @SuppressWarnings({"UnusedDeclaration"})
} public void moveRightButtonClickHandler(@NotNull View v) {
getKeyboard().moveCursorRight();
@SuppressWarnings({"UnusedDeclaration"}) }
public void pasteButtonClickHandler(@NotNull View v) {
getKeyboard().pasteButtonPressed(); @SuppressWarnings({"UnusedDeclaration"})
} public void pasteButtonClickHandler(@NotNull View v) {
getKeyboard().pasteButtonPressed();
@SuppressWarnings({"UnusedDeclaration"}) }
public void copyButtonClickHandler(@NotNull View v) {
getKeyboard().copyButtonPressed(); @SuppressWarnings({"UnusedDeclaration"})
} public void copyButtonClickHandler(@NotNull View v) {
getKeyboard().copyButtonPressed();
@NotNull }
private static CalculatorKeyboard getKeyboard() {
return CalculatorLocatorImpl.getInstance().getKeyboard(); @NotNull
} private static CalculatorKeyboard getKeyboard() {
return CalculatorLocatorImpl.getInstance().getKeyboard();
@SuppressWarnings({"UnusedDeclaration"}) }
public void clearButtonClickHandler(@NotNull View v) {
getKeyboard().clearButtonPressed(); @SuppressWarnings({"UnusedDeclaration"})
} public void clearButtonClickHandler(@NotNull View v) {
getKeyboard().clearButtonPressed();
@SuppressWarnings({"UnusedDeclaration"}) }
public void digitButtonClickHandler(@NotNull View v) {
Log.d(String.valueOf(v.getId()), "digitButtonClickHandler() for: " + v.getId() + ". Pressed: " + v.isPressed()); @SuppressWarnings({"UnusedDeclaration"})
if (((ColorButton) v).isShowText()) { public void digitButtonClickHandler(@NotNull View v) {
getKeyboard().digitButtonPressed(((ColorButton) v).getText().toString()); Log.d(String.valueOf(v.getId()), "digitButtonClickHandler() for: " + v.getId() + ". Pressed: " + v.isPressed());
} if (((ColorButton) v).isShowText()) {
} getKeyboard().digitButtonPressed(((ColorButton) v).getText().toString());
}
@SuppressWarnings({"UnusedDeclaration"}) }
public void functionsButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showFunctions(this); @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 operatorsButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showOperators(this);
public static void operatorsButtonClickHandler(@NotNull Activity activity) { }
CalculatorActivityLauncher.showOperators(activity);
} public static void operatorsButtonClickHandler(@NotNull Activity activity) {
CalculatorActivityLauncher.showOperators(activity);
@SuppressWarnings({"UnusedDeclaration"}) }
public void varsButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showVars(this); @SuppressWarnings({"UnusedDeclaration"})
} public void varsButtonClickHandler(@NotNull View v) {
CalculatorActivityLauncher.showVars(this);
@SuppressWarnings({"UnusedDeclaration"}) }
public void donateButtonClickHandler(@NotNull View v) {
CalculatorApplication.showDonationDialog(this); @SuppressWarnings({"UnusedDeclaration"})
} public void donateButtonClickHandler(@NotNull View v) {
CalculatorApplication.showDonationDialog(this);
}
} }

View File

@ -1,160 +1,174 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.app.Activity; import android.app.Activity;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.app.SherlockFragmentActivity;
import org.jetbrains.annotations.NotNull; 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.sherlock.tabs.ActionBarFragmentTabListener; import org.solovyev.android.sherlock.tabs.ActionBarFragmentTabListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
* User: serso * User: serso
* Date: 9/25/12 * Date: 9/25/12
* Time: 10:32 PM * Time: 10:32 PM
*/ */
public class CalculatorActivityHelperImpl extends AbstractCalculatorHelper implements CalculatorActivityHelper { public class CalculatorActivityHelperImpl extends AbstractCalculatorHelper implements CalculatorActivityHelper {
/* /*
********************************************************************** **********************************************************************
* *
* CONSTANTS * CONSTANTS
* *
********************************************************************** **********************************************************************
*/ */
private static final String SELECTED_NAV = "selected_nav"; private static final String SELECTED_NAV = "selected_nav";
/* /*
********************************************************************** **********************************************************************
* *
* FIELDS * FIELDS
* *
********************************************************************** **********************************************************************
*/ */
private int layoutId; private int layoutId;
private boolean homeIcon = false; private boolean homeIcon = false;
@NotNull @NotNull
private final List<String> fragmentTags = new ArrayList<String>(); private final List<String> fragmentTags = new ArrayList<String>();
@NotNull @NotNull
private CalculatorPreferences.Gui.Theme theme; private CalculatorPreferences.Gui.Theme theme;
private int navPosition = 0; private int navPosition = 0;
public CalculatorActivityHelperImpl(int layoutId, @NotNull String logTag) { public CalculatorActivityHelperImpl(int layoutId, @NotNull String logTag) {
super(logTag); super(logTag);
this.layoutId = layoutId; this.layoutId = layoutId;
} }
public CalculatorActivityHelperImpl(int layoutId, boolean homeIcon) { public CalculatorActivityHelperImpl(int layoutId, boolean homeIcon) {
this.layoutId = layoutId; this.layoutId = layoutId;
this.homeIcon = homeIcon; this.homeIcon = homeIcon;
} }
@Override @Override
public void onCreate(@NotNull Activity activity, @Nullable Bundle savedInstanceState) { public void onCreate(@NotNull Activity activity, @Nullable Bundle savedInstanceState) {
super.onCreate(activity); super.onCreate(activity);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity); if ( activity instanceof CalculatorEventListener) {
CalculatorLocatorImpl.getInstance().getCalculator().addCalculatorEventListener((CalculatorEventListener)activity);
this.theme = CalculatorPreferences.Gui.getTheme(preferences); }
activity.setTheme(this.theme.getThemeId());
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
activity.setContentView(layoutId);
this.theme = CalculatorPreferences.Gui.getTheme(preferences);
CalculatorButtons.processButtons(true, theme, activity.getWindow().getDecorView()); activity.setTheme(this.theme.getThemeId());
}
activity.setContentView(layoutId);
@Override
public void onCreate(@NotNull final SherlockFragmentActivity activity, @Nullable Bundle savedInstanceState) { CalculatorButtons.processButtons(true, theme, activity.getWindow().getDecorView());
this.onCreate((Activity) activity, savedInstanceState); }
final ActionBar actionBar = activity.getSupportActionBar(); @Override
actionBar.setDisplayUseLogoEnabled(false); public void onCreate(@NotNull final SherlockFragmentActivity activity, @Nullable Bundle savedInstanceState) {
actionBar.setDisplayHomeAsUpEnabled(homeIcon); this.onCreate((Activity) activity, savedInstanceState);
actionBar.setDisplayShowHomeEnabled(true);
actionBar.setDisplayShowTitleEnabled(true); final ActionBar actionBar = activity.getSupportActionBar();
actionBar.setDisplayUseLogoEnabled(false);
if (savedInstanceState != null) { actionBar.setDisplayHomeAsUpEnabled(homeIcon);
navPosition = savedInstanceState.getInt(SELECTED_NAV, 0); actionBar.setHomeButtonEnabled(false);
} actionBar.setDisplayShowHomeEnabled(true);
} actionBar.setDisplayShowTitleEnabled(true);
@Override if (savedInstanceState != null) {
public void restoreSavedTab(@NotNull SherlockFragmentActivity activity) { navPosition = savedInstanceState.getInt(SELECTED_NAV, 0);
final ActionBar actionBar = activity.getSupportActionBar(); }
if (navPosition >= 0 && navPosition < actionBar.getTabCount()) { }
activity.getSupportActionBar().setSelectedNavigationItem(navPosition);
} @Override
} public void restoreSavedTab(@NotNull SherlockFragmentActivity activity) {
final ActionBar actionBar = activity.getSupportActionBar();
@Override if (navPosition >= 0 && navPosition < actionBar.getTabCount()) {
public void onSaveInstanceState(@NotNull SherlockFragmentActivity activity, @NotNull Bundle outState) { activity.getSupportActionBar().setSelectedNavigationItem(navPosition);
onSaveInstanceState((Activity) activity, outState); }
outState.putInt(SELECTED_NAV, activity.getSupportActionBar().getSelectedNavigationIndex()); }
}
@Override
@Override public void onSaveInstanceState(@NotNull SherlockFragmentActivity activity, @NotNull Bundle outState) {
public void onSaveInstanceState(@NotNull Activity activity, @NotNull Bundle outState) { onSaveInstanceState((Activity) activity, outState);
} outState.putInt(SELECTED_NAV, activity.getSupportActionBar().getSelectedNavigationIndex());
}
@Override
public void onResume(@NotNull Activity activity) { @Override
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity); public void onSaveInstanceState(@NotNull Activity activity, @NotNull Bundle outState) {
}
final CalculatorPreferences.Gui.Theme newTheme = CalculatorPreferences.Gui.theme.getPreference(preferences);
if (!theme.equals(newTheme)) { @Override
AndroidUtils.restartActivity(activity); public void onResume(@NotNull Activity activity) {
} final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
}
final CalculatorPreferences.Gui.Theme newTheme = CalculatorPreferences.Gui.theme.getPreference(preferences);
@Override if (!theme.equals(newTheme)) {
public void onDestroy(@NotNull SherlockFragmentActivity activity) { AndroidUtils.restartActivity(activity);
super.onDestroy(activity); }
} }
@Override @Override
public void addTab(@NotNull SherlockFragmentActivity activity, public void onDestroy(@NotNull Activity activity) {
@NotNull String tag, super.onDestroy(activity);
@NotNull Class<? extends Fragment> fragmentClass,
@Nullable Bundle fragmentArgs, if ( activity instanceof CalculatorEventListener) {
int captionResId, CalculatorLocatorImpl.getInstance().getCalculator().removeCalculatorEventListener((CalculatorEventListener)activity);
int parentViewId) { }
activity.getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); }
final ActionBar actionBar = activity.getSupportActionBar(); @Override
final ActionBar.Tab tab = actionBar.newTab(); public void onDestroy(@NotNull SherlockFragmentActivity activity) {
tab.setTag(tag); this.onDestroy((Activity)activity);
tab.setText(captionResId); }
tab.setTabListener(new ActionBarFragmentTabListener(activity, tag, fragmentClass, fragmentArgs, parentViewId));
actionBar.addTab(tab); @Override
public void addTab(@NotNull SherlockFragmentActivity activity,
fragmentTags.add(tag); @NotNull String tag,
} @NotNull Class<? extends Fragment> fragmentClass,
@Nullable Bundle fragmentArgs,
@Override int captionResId,
public int getLayoutId() { int parentViewId) {
return layoutId; activity.getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
}
final ActionBar actionBar = activity.getSupportActionBar();
@Override final ActionBar.Tab tab = actionBar.newTab();
@NotNull tab.setTag(tag);
public CalculatorPreferences.Gui.Theme getTheme() { tab.setText(captionResId);
return theme; tab.setTabListener(new ActionBarFragmentTabListener(activity, tag, fragmentClass, fragmentArgs, parentViewId));
} actionBar.addTab(tab);
@Override fragmentTags.add(tag);
public void onResume(@NotNull SherlockFragmentActivity activity) { }
onResume((Activity) activity);
} @Override
} public int getLayoutId() {
return layoutId;
}
@Override
@NotNull
public CalculatorPreferences.Gui.Theme getTheme() {
return theme;
}
@Override
public void onResume(@NotNull SherlockFragmentActivity activity) {
onResume((Activity) activity);
}
}

View File

@ -1,82 +1,83 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.widget.Toast; import android.widget.Toast;
import jscl.math.Generic; import jscl.math.Generic;
import jscl.math.function.Constant; import jscl.math.function.Constant;
import org.achartengine.ChartFactory; import org.achartengine.ChartFactory;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.about.CalculatorAboutTabActivity; import org.solovyev.android.calculator.about.CalculatorAboutTabActivity;
import org.solovyev.android.calculator.help.CalculatorHelpTabActivity; import org.solovyev.android.calculator.help.CalculatorHelpTabActivity;
import org.solovyev.android.calculator.history.CalculatorHistoryFragmentActivity; import org.solovyev.android.calculator.history.CalculatorHistoryFragmentActivity;
import org.solovyev.android.calculator.math.edit.CalculatorFunctionsFragmentActivity; import org.solovyev.android.calculator.math.edit.CalculatorFunctionsFragmentActivity;
import org.solovyev.android.calculator.math.edit.CalculatorOperatorsFragment; import org.solovyev.android.calculator.math.edit.CalculatorOperatorsFragment;
import org.solovyev.android.calculator.math.edit.CalculatorVarsFragment; import org.solovyev.android.calculator.math.edit.CalculatorVarsFragment;
import org.solovyev.android.calculator.math.edit.CalculatorVarsFragmentActivity; import org.solovyev.android.calculator.math.edit.CalculatorVarsFragmentActivity;
import org.solovyev.android.calculator.plot.CalculatorPlotActivity; import org.solovyev.android.calculator.plot.CalculatorPlotActivity;
import org.solovyev.common.text.StringUtils; import org.solovyev.android.calculator.plot.CalculatorPlotFragment;
import org.solovyev.common.text.StringUtils;
/**
* User: serso /**
* Date: 11/2/11 * User: serso
* Time: 2:18 PM * Date: 11/2/11
*/ * Time: 2:18 PM
public class CalculatorActivityLauncher { */
public class CalculatorActivityLauncher {
public static void showHistory(@NotNull final Context context) {
context.startActivity(new Intent(context, CalculatorHistoryFragmentActivity.class)); public static void showHistory(@NotNull final Context context) {
} context.startActivity(new Intent(context, CalculatorHistoryFragmentActivity.class));
}
public static void showHelp(@NotNull final Context context) {
context.startActivity(new Intent(context, CalculatorHelpTabActivity.class)); public static void showHelp(@NotNull final Context context) {
} context.startActivity(new Intent(context, CalculatorHelpTabActivity.class));
}
public static void showSettings(@NotNull final Context context) {
context.startActivity(new Intent(context, CalculatorPreferencesActivity.class)); public static void showSettings(@NotNull final Context context) {
} context.startActivity(new Intent(context, CalculatorPreferencesActivity.class));
}
public static void showAbout(@NotNull final Context context) {
context.startActivity(new Intent(context, CalculatorAboutTabActivity.class)); public static void showAbout(@NotNull final Context context) {
} context.startActivity(new Intent(context, CalculatorAboutTabActivity.class));
}
public static void showFunctions(@NotNull final Context context) {
context.startActivity(new Intent(context, CalculatorFunctionsFragmentActivity.class)); public static void showFunctions(@NotNull final Context context) {
} context.startActivity(new Intent(context, CalculatorFunctionsFragmentActivity.class));
}
public static void showOperators(@NotNull final Context context) {
context.startActivity(new Intent(context, CalculatorOperatorsFragment.class)); public static void showOperators(@NotNull final Context context) {
} context.startActivity(new Intent(context, CalculatorOperatorsFragment.class));
}
public static void showVars(@NotNull final Context context) {
context.startActivity(new Intent(context, CalculatorVarsFragmentActivity.class)); public static void showVars(@NotNull final Context context) {
} context.startActivity(new Intent(context, CalculatorVarsFragmentActivity.class));
}
public static void plotGraph(@NotNull final Context context, @NotNull Generic generic, @NotNull Constant constant){
final Intent intent = new Intent(); public static void plotGraph(@NotNull final Context context, @NotNull Generic generic, @NotNull Constant constant){
intent.putExtra(ChartFactory.TITLE, context.getString(R.string.c_graph)); final Intent intent = new Intent();
intent.putExtra(CalculatorPlotActivity.INPUT, new CalculatorPlotActivity.Input(generic.toString(), constant.getName())); intent.putExtra(ChartFactory.TITLE, context.getString(R.string.c_graph));
intent.setClass(context, CalculatorPlotActivity.class); intent.putExtra(CalculatorPlotFragment.INPUT, new CalculatorPlotFragment.Input(generic.toString(), constant.getName()));
context.startActivity(intent); intent.setClass(context, CalculatorPlotActivity.class);
} context.startActivity(intent);
}
public static void createVar(@NotNull final Context context, @NotNull CalculatorDisplay calculatorDisplay) {
final CalculatorDisplayViewState viewState = calculatorDisplay.getViewState(); public static void createVar(@NotNull final Context context, @NotNull CalculatorDisplay calculatorDisplay) {
if (viewState.isValid() ) { final CalculatorDisplayViewState viewState = calculatorDisplay.getViewState();
final String varValue = viewState.getText(); if (viewState.isValid() ) {
if (!StringUtils.isEmpty(varValue)) { final String varValue = viewState.getText();
if (CalculatorVarsFragment.isValidValue(varValue)) { if (!StringUtils.isEmpty(varValue)) {
final Intent intent = new Intent(context, CalculatorVarsFragmentActivity.class); if (CalculatorVarsFragment.isValidValue(varValue)) {
intent.putExtra(CalculatorVarsFragment.CREATE_VAR_EXTRA_STRING, varValue); final Intent intent = new Intent(context, CalculatorVarsFragmentActivity.class);
context.startActivity(intent); intent.putExtra(CalculatorVarsFragment.CREATE_VAR_EXTRA_STRING, varValue);
} else { context.startActivity(intent);
Toast.makeText(context, R.string.c_not_valid_result, Toast.LENGTH_SHORT).show(); } else {
} Toast.makeText(context, R.string.c_not_valid_result, Toast.LENGTH_SHORT).show();
} else { }
Toast.makeText(context, R.string.c_empty_var_error, Toast.LENGTH_SHORT).show(); } else {
} Toast.makeText(context, R.string.c_empty_var_error, Toast.LENGTH_SHORT).show();
} else { }
Toast.makeText(context, R.string.c_not_valid_result, Toast.LENGTH_SHORT).show(); } else {
} Toast.makeText(context, R.string.c_not_valid_result, Toast.LENGTH_SHORT).show();
} }
} }
}

View File

@ -1,122 +1,132 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.net.Uri; import android.net.Uri;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import net.robotmedia.billing.BillingController; import net.robotmedia.billing.BillingController;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.ads.AdsController; import org.solovyev.android.ads.AdsController;
import org.solovyev.android.calculator.history.AndroidCalculatorHistory; import org.solovyev.android.calculator.history.AndroidCalculatorHistory;
import org.solovyev.android.calculator.model.AndroidCalculatorEngine; import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
/** /**
* User: serso * User: serso
* Date: 12/1/11 * Date: 12/1/11
* Time: 1:21 PM * Time: 1:21 PM
*/ */
public class CalculatorApplication extends android.app.Application { public class CalculatorApplication extends android.app.Application {
private static final 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"; private static final 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";
public static final String AD_FREE_PRODUCT_ID = "ad_free"; public static final String AD_FREE_PRODUCT_ID = "ad_free";
public static final String AD_FREE_P_KEY = "org.solovyev.android.calculator_ad_free"; public static final String AD_FREE_P_KEY = "org.solovyev.android.calculator_ad_free";
public static final String ADMOB_USER_ID = "a14f02cf9c80cbc"; public static final String ADMOB_USER_ID = "a14f02cf9c80cbc";
public static final String REMOTE_STACK_TRACE_URL = "http://calculatorpp.com/crash_reports/upload.php"; public static final String REMOTE_STACK_TRACE_URL = "http://calculatorpp.com/crash_reports/upload.php";
@NotNull @NotNull
private static CalculatorApplication instance; private static CalculatorApplication instance;
public CalculatorApplication() { public CalculatorApplication() {
instance = this; instance = this;
} }
@NotNull @NotNull
public static CalculatorApplication getInstance() { public static CalculatorApplication getInstance() {
return instance; return instance;
} }
@Override @Override
public void onCreate() { public void onCreate() {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
setTheme(preferences); setTheme(preferences);
super.onCreate(); super.onCreate();
final AndroidCalculator calculator = new AndroidCalculator(); final AndroidCalculator calculator = new AndroidCalculator();
CalculatorLocatorImpl.getInstance().init(calculator, CalculatorLocatorImpl.getInstance().init(calculator,
new AndroidCalculatorEngine(this), new AndroidCalculatorEngine(this),
new AndroidCalculatorClipboard(this), new AndroidCalculatorClipboard(this),
new AndroidCalculatorNotifier(this), new AndroidCalculatorNotifier(this),
new AndroidCalculatorHistory(this, calculator)); new AndroidCalculatorHistory(this, calculator));
CalculatorLocatorImpl.getInstance().getCalculator().init(); CalculatorLocatorImpl.getInstance().getCalculator().init();
AdsController.getInstance().init(ADMOB_USER_ID, AD_FREE_PRODUCT_ID, new BillingController.IConfiguration() { AdsController.getInstance().init(ADMOB_USER_ID, AD_FREE_PRODUCT_ID, new BillingController.IConfiguration() {
@Override @Override
public byte[] getObfuscationSalt() { public byte[] getObfuscationSalt() {
return new byte[]{81, -114, 32, -127, -32, -104, -40, -15, -47, 57, -13, -41, -33, 67, -114, 7, -11, 53, 126, 82}; return new byte[]{81, -114, 32, -127, -32, -104, -40, -15, -47, 57, -13, -41, -33, 67, -114, 7, -11, 53, 126, 82};
} }
@Override @Override
public String getPublicKey() { public String getPublicKey() {
return CalculatorSecurity.getPK(); return CalculatorSecurity.getPK();
} }
}); });
CalculatorPreferences.setDefaultValues(preferences); CalculatorPreferences.setDefaultValues(preferences);
} }
private void setTheme(@NotNull SharedPreferences preferences) { private void setTheme(@NotNull SharedPreferences preferences) {
final CalculatorPreferences.Gui.Theme theme = CalculatorPreferences.Gui.getTheme(preferences); final CalculatorPreferences.Gui.Theme theme = CalculatorPreferences.Gui.getTheme(preferences);
setTheme(theme.getThemeId()); setTheme(theme.getThemeId());
} }
public static void showDonationDialog(@NotNull final Context context) { public static void showDonationDialog(@NotNull final Context context) {
final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE); final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(LAYOUT_INFLATER_SERVICE);
final View view = layoutInflater.inflate(R.layout.donate, null); final View view = layoutInflater.inflate(R.layout.donate, null);
final TextView donate = (TextView) view.findViewById(R.id.donateText); final TextView donate = (TextView) view.findViewById(R.id.donateText);
donate.setMovementMethod(LinkMovementMethod.getInstance()); donate.setMovementMethod(LinkMovementMethod.getInstance());
final AlertDialog.Builder builder = new AlertDialog.Builder(context) final AlertDialog.Builder builder = new AlertDialog.Builder(context)
.setCancelable(true) .setCancelable(true)
.setNegativeButton(R.string.c_cancel, null) .setNegativeButton(R.string.c_cancel, null)
.setPositiveButton(R.string.c_donate, new DialogInterface.OnClickListener() { .setPositiveButton(R.string.c_donate, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
final Intent i = new Intent(Intent.ACTION_VIEW); final Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(paypalDonateUrl)); i.setData(Uri.parse(paypalDonateUrl));
context.startActivity(i); context.startActivity(i);
} }
}) })
.setView(view); .setView(view);
builder.create().show(); builder.create().show();
} }
public static void registerOnRemoteStackTrace() { public static void registerOnRemoteStackTrace() {
//Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(null, REMOTE_STACK_TRACE_URL)); //Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler(null, REMOTE_STACK_TRACE_URL));
} }
@NotNull @NotNull
public CalculatorActivityHelper createActivityHelper(int layoutResId, @NotNull String logTag) { public CalculatorActivityHelper createActivityHelper(int layoutResId, @NotNull String logTag) {
return new CalculatorActivityHelperImpl(layoutResId, logTag); return new CalculatorActivityHelperImpl(layoutResId, logTag);
} }
@NotNull @NotNull
public CalculatorFragmentHelper createFragmentHelper(int layoutId) { public CalculatorFragmentHelper createFragmentHelper(int layoutId) {
return new CalculatorFragmentHelperImpl(layoutId); return new CalculatorFragmentHelperImpl(layoutId);
} }
}
@NotNull
public CalculatorFragmentHelper createFragmentHelper(int layoutId, int titleResId) {
return new CalculatorFragmentHelperImpl(layoutId, titleResId);
}
@NotNull
public CalculatorFragmentHelper createFragmentHelper(int layoutId, int titleResId, boolean listenersOnCreate) {
return new CalculatorFragmentHelperImpl(layoutId, titleResId, listenersOnCreate);
}
}

View File

@ -3,16 +3,12 @@ package org.solovyev.android.calculator;
import android.content.Context; import android.content.Context;
import jscl.math.Generic; import jscl.math.Generic;
import jscl.math.function.Constant; import jscl.math.function.Constant;
import jscl.math.function.IConstant;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog; import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
import org.solovyev.android.menu.LabeledMenuItem; import org.solovyev.android.menu.LabeledMenuItem;
import org.solovyev.common.collections.CollectionsUtils; import org.solovyev.common.collections.CollectionsUtils;
import java.util.HashSet;
import java.util.Set;
/** /**
* User: Solovyev_S * User: Solovyev_S
* Date: 21.09.12 * Date: 21.09.12
@ -84,37 +80,16 @@ public enum CalculatorDisplayMenuItem implements LabeledMenuItem<CalculatorDispl
final Generic generic = data.getResult(); final Generic generic = data.getResult();
assert generic != null; assert generic != null;
final Constant constant = CollectionsUtils.getFirstCollectionElement(getNotSystemConstants(generic)); final Constant constant = CollectionsUtils.getFirstCollectionElement(CalculatorUtils.getNotSystemConstants(generic));
assert constant != null; assert constant != null;
CalculatorActivityLauncher.plotGraph(context, generic, constant); CalculatorActivityLauncher.plotGraph(context, generic, constant);
} }
@Override @Override
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) { protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
boolean result = false; return CalculatorUtils.isPlotPossible(generic, operation);
if (operation == JsclOperation.simplify) {
if (getNotSystemConstants(generic).size() == 1) {
result = true;
}
}
return result;
} }
@NotNull
private Set<Constant> getNotSystemConstants(@NotNull Generic generic) {
final Set<Constant> notSystemConstants = new HashSet<Constant>();
for (Constant constant : generic.getConstants()) {
IConstant var = CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().get(constant.getName());
if (var != null && !var.isSystem() && !var.isDefined()) {
notSystemConstants.add(constant);
}
}
return notSystemConstants;
}
}; };
private final int captionId; private final int captionId;

View File

@ -1,64 +1,98 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.actionbarsherlock.app.SherlockFragment; import com.actionbarsherlock.app.SherlockFragment;
import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem; import com.actionbarsherlock.view.MenuItem;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.solovyev.android.menu.ActivityMenu; import org.solovyev.android.menu.ActivityMenu;
import org.solovyev.android.menu.ListActivityMenu; import org.solovyev.android.menu.ListActivityMenu;
import org.solovyev.android.sherlock.menu.SherlockMenuHelper; import org.solovyev.android.sherlock.menu.SherlockMenuHelper;
/** /**
* User: Solovyev_S * User: Solovyev_S
* Date: 25.09.12 * Date: 25.09.12
* Time: 10:49 * Time: 10:49
*/ */
public class CalculatorEditorFragment extends SherlockFragment { public class CalculatorEditorFragment extends SherlockFragment {
@NotNull @NotNull
private ActivityMenu<Menu, MenuItem> menu = ListActivityMenu.fromList(CalculatorMenu.class, SherlockMenuHelper.getInstance()); private ActivityMenu<Menu, MenuItem> menu = ListActivityMenu.fromList(CalculatorMenu.class, SherlockMenuHelper.getInstance());
@Override private CalculatorFragmentHelper fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(R.layout.calc_editor, R.string.editor);
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); @Override
public void onCreate(Bundle savedInstanceState) {
setHasOptionsMenu(true); super.onCreate(savedInstanceState);
}
fragmentHelper.onCreate(this);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { setHasOptionsMenu(true);
return inflater.inflate(R.layout.calc_editor, container, false); }
}
@Override
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
public void onViewCreated(View view, Bundle savedInstanceState) { return fragmentHelper.onCreateView(this, inflater, container);
super.onViewCreated(view, savedInstanceState); }
((AndroidCalculator) CalculatorLocatorImpl.getInstance().getCalculator()).setEditor(getActivity()); @Override
} public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
@Override
public void onActivityCreated(Bundle savedInstanceState) { fragmentHelper.onViewCreated(this, view);
super.onActivityCreated(savedInstanceState);
} ((AndroidCalculator) CalculatorLocatorImpl.getInstance().getCalculator()).setEditor(getActivity());
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { @Override
this.menu.onCreateOptionsMenu(this.getActivity(), menu); public void onActivityCreated(Bundle savedInstanceState) {
} super.onActivityCreated(savedInstanceState);
}
@Override
public void onPrepareOptionsMenu(Menu menu) { @Override
this.menu.onPrepareOptionsMenu(this.getActivity(), menu); public void onDestroy() {
} fragmentHelper.onDestroy(this);
super.onDestroy();
@Override }
public boolean onOptionsItemSelected(MenuItem item) {
return this.menu.onOptionsItemSelected(this.getActivity(), item); @Override
} public void onResume() {
} super.onResume();
this.fragmentHelper.onResume(this);
}
@Override
public void onPause() {
this.fragmentHelper.onPause(this);
super.onPause();
}
/*
**********************************************************************
*
* MENU
*
**********************************************************************
*/
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
this.menu.onCreateOptionsMenu(this.getActivity(), menu);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
this.menu.onPrepareOptionsMenu(this.getActivity(), menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
return this.menu.onOptionsItemSelected(this.getActivity(), item);
}
}

View File

@ -1,30 +1,33 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
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.math.edit.AbstractMathEntityListFragment;
/**
/** * User: serso
* User: serso * Date: 9/26/12
* Date: 9/26/12 * Time: 10:14 PM
* Time: 10:14 PM */
*/ public interface CalculatorFragmentHelper {
public interface CalculatorFragmentHelper {
boolean isPane(@NotNull Fragment fragment);
boolean isPane(@NotNull Fragment fragment);
void setPaneTitle(@NotNull Fragment fragment, int titleResId);
void setPaneTitle(@NotNull Fragment fragment, int titleResId);
void onCreate(@NotNull Fragment fragment);
void onCreate(@NotNull Fragment fragment);
void onResume(@NotNull Fragment fragment);
void onViewCreated(@NotNull Fragment fragment, @NotNull View root);
void onPause(@NotNull Fragment fragment);
void onDestroy(@NotNull Fragment fragment);
@NotNull
@NotNull View onCreateView(@NotNull Fragment fragment, @NotNull LayoutInflater inflater, @Nullable ViewGroup container);
View onCreateView(@NotNull Fragment fragment, @NotNull LayoutInflater inflater, @Nullable ViewGroup container);
} void onViewCreated(@NotNull Fragment fragment, @NotNull View root);
void onDestroy(@NotNull Fragment fragment);
}

View File

@ -1,76 +1,126 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.ViewParent; import android.widget.TextView;
import android.widget.LinearLayout; import com.google.ads.AdView;
import android.widget.TextView; import org.jetbrains.annotations.NotNull;
import com.google.ads.AdView; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull; import org.solovyev.android.ads.AdsController;
import org.jetbrains.annotations.Nullable; import org.solovyev.android.calculator.plot.CalculatorPlotFragment;
import org.solovyev.android.ads.AdsController;
/**
/** * User: serso
* User: serso * Date: 9/26/12
* Date: 9/26/12 * Time: 10:14 PM
* Time: 10:14 PM */
*/ public class CalculatorFragmentHelperImpl extends AbstractCalculatorHelper implements CalculatorFragmentHelper {
public class CalculatorFragmentHelperImpl extends AbstractCalculatorHelper implements CalculatorFragmentHelper {
@Nullable
@Nullable private AdView adView;
private AdView adView;
private int layoutId;
private int layoutId;
private int titleResId = -1;
public CalculatorFragmentHelperImpl(int layoutId) {
this.layoutId = layoutId; private boolean listenersOnCreate = true;
}
public CalculatorFragmentHelperImpl(int layoutId) {
@Override this.layoutId = layoutId;
public boolean isPane(@NotNull Fragment fragment) { }
return fragment.getActivity() instanceof CalculatorActivity;
} public CalculatorFragmentHelperImpl(int layoutId, int titleResId) {
this.layoutId = layoutId;
public void setPaneTitle(@NotNull Fragment fragment, int titleResId) { this.titleResId = titleResId;
final TextView fragmentTitle = (TextView) fragment.getView().findViewById(R.id.fragmentTitle); }
if (fragmentTitle != null) {
if (!isPane(fragment)) { public CalculatorFragmentHelperImpl(int layoutId, int titleResId, boolean listenersOnCreate) {
fragmentTitle.setVisibility(View.GONE); this.layoutId = layoutId;
} else { this.titleResId = titleResId;
fragmentTitle.setText(fragment.getString(titleResId).toUpperCase()); this.listenersOnCreate = listenersOnCreate;
} }
}
} @Override
public boolean isPane(@NotNull Fragment fragment) {
@Override return fragment.getActivity() instanceof CalculatorActivity;
public void onCreate(@NotNull Fragment fragment) { }
super.onCreate(fragment.getActivity());
} public void setPaneTitle(@NotNull Fragment fragment, int titleResId) {
final TextView fragmentTitle = (TextView) fragment.getView().findViewById(R.id.fragmentTitle);
@Override if (fragmentTitle != null) {
public void onViewCreated(@NotNull Fragment fragment, @NotNull View root) { if (!isPane(fragment)) {
final ViewGroup mainFragmentLayout = (ViewGroup) root.findViewById(R.id.main_fragment_layout); fragmentTitle.setVisibility(View.GONE);
if (mainFragmentLayout != null) { } else {
adView = AdsController.getInstance().inflateAd(fragment.getActivity(), mainFragmentLayout, R.id.main_fragment_layout); fragmentTitle.setText(fragment.getString(titleResId).toUpperCase());
} }
}
processButtons(fragment.getActivity(), root); }
}
@Override
@Override public void onCreate(@NotNull Fragment fragment) {
public void onDestroy(@NotNull Fragment fragment) { super.onCreate(fragment.getActivity());
super.onDestroy(fragment.getActivity());
if (listenersOnCreate) {
if (this.adView != null) { if ( fragment instanceof CalculatorEventListener ) {
this.adView.destroy(); CalculatorLocatorImpl.getInstance().getCalculator().addCalculatorEventListener((CalculatorEventListener) fragment);
} }
} }
}
@NotNull
@Override @Override
public View onCreateView(@NotNull Fragment fragment, @NotNull LayoutInflater inflater, @Nullable ViewGroup container) { public void onResume(@NotNull Fragment fragment) {
return inflater.inflate(layoutId, container, false); if (!listenersOnCreate) {
} if ( fragment instanceof CalculatorEventListener ) {
} CalculatorLocatorImpl.getInstance().getCalculator().addCalculatorEventListener((CalculatorEventListener) fragment);
}
}
}
@Override
public void onPause(@NotNull Fragment fragment) {
if (!listenersOnCreate) {
if ( fragment instanceof CalculatorEventListener ) {
CalculatorLocatorImpl.getInstance().getCalculator().removeCalculatorEventListener((CalculatorEventListener) fragment);
}
}
}
@Override
public void onViewCreated(@NotNull Fragment fragment, @NotNull View root) {
final ViewGroup mainFragmentLayout = (ViewGroup) root.findViewById(R.id.main_fragment_layout);
if (mainFragmentLayout != null) {
if (!(fragment instanceof CalculatorPlotFragment)) {
adView = AdsController.getInstance().inflateAd(fragment.getActivity(), mainFragmentLayout, R.id.main_fragment_layout);
}
}
processButtons(fragment.getActivity(), root);
if (titleResId >= 0) {
this.setPaneTitle(fragment, titleResId);
}
}
@Override
public void onDestroy(@NotNull Fragment fragment) {
super.onDestroy(fragment.getActivity());
if (listenersOnCreate) {
if ( fragment instanceof CalculatorEventListener ) {
CalculatorLocatorImpl.getInstance().getCalculator().removeCalculatorEventListener((CalculatorEventListener) fragment);
}
}
if (this.adView != null) {
this.adView.destroy();
}
}
@NotNull
@Override
public View onCreateView(@NotNull Fragment fragment, @NotNull LayoutInflater inflater, @Nullable ViewGroup container) {
return inflater.inflate(layoutId, container, false);
}
}

View File

@ -1,119 +1,134 @@
package org.solovyev.android.calculator; package org.solovyev.android.calculator;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import com.actionbarsherlock.app.SherlockFragment; import com.actionbarsherlock.app.SherlockFragment;
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.model.AndroidCalculatorEngine; import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
/** /**
* User: Solovyev_S * User: Solovyev_S
* Date: 25.09.12 * Date: 25.09.12
* Time: 12:25 * Time: 12:25
*/ */
public class CalculatorKeyboardFragment extends SherlockFragment implements SharedPreferences.OnSharedPreferenceChangeListener { public class CalculatorKeyboardFragment extends SherlockFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
@NotNull @NotNull
private NumeralBaseButtons numeralBaseButtons = new NumeralBaseButtons(); private NumeralBaseButtons numeralBaseButtons = new NumeralBaseButtons();
@NotNull @NotNull
private CalculatorPreferences.Gui.Theme theme; private CalculatorPreferences.Gui.Theme theme;
@NotNull @NotNull
private CalculatorFragmentHelper fragmentHelper; private CalculatorFragmentHelper fragmentHelper;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity()); final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(R.layout.calc_keyboard); fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(R.layout.calc_keyboard);
fragmentHelper.onCreate(this); fragmentHelper.onCreate(this);
preferences.registerOnSharedPreferenceChangeListener(this); preferences.registerOnSharedPreferenceChangeListener(this);
theme = CalculatorPreferences.Gui.theme.getPreferenceNoError(preferences); theme = CalculatorPreferences.Gui.theme.getPreferenceNoError(preferences);
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return fragmentHelper.onCreateView(this, inflater, container); return fragmentHelper.onCreateView(this, inflater, container);
} }
@Override @Override
public void onViewCreated(View root, Bundle savedInstanceState) { public void onViewCreated(View root, Bundle savedInstanceState) {
super.onViewCreated(root, savedInstanceState); super.onViewCreated(root, savedInstanceState);
fragmentHelper.onViewCreated(this, root); fragmentHelper.onViewCreated(this, root);
} }
@Override
public void onDestroy() { @Override
super.onDestroy(); public void onResume() {
super.onResume();
fragmentHelper.onDestroy(this);
this.fragmentHelper.onResume(this);
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity()); }
preferences.unregisterOnSharedPreferenceChangeListener(this);
@Override
} public void onPause() {
this.fragmentHelper.onPause(this);
/* private static void setMarginsForView(@Nullable View view, int marginLeft, int marginBottom, @NotNull Context context) {
// IMPORTANT: this is workaround for probably android bug super.onPause();
// currently margin values set in styles are not applied for some reasons to the views (using include tag) => set them manually }
if (view != null) { @Override
final DisplayMetrics dm = context.getResources().getDisplayMetrics(); public void onDestroy() {
if (view.getLayoutParams() instanceof LinearLayout.LayoutParams) { super.onDestroy();
final LinearLayout.LayoutParams oldParams = (LinearLayout.LayoutParams) view.getLayoutParams();
final LinearLayout.LayoutParams newParams = new LinearLayout.LayoutParams(oldParams.width, oldParams.height, oldParams.weight); fragmentHelper.onDestroy(this);
newParams.setMargins(AndroidUtils.toPixels(dm, marginLeft), 0, 0, AndroidUtils.toPixels(dm, marginBottom));
view.setLayoutParams(newParams); final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this.getActivity());
} preferences.unregisterOnSharedPreferenceChangeListener(this);
}
}*/ }
@Override /* private static void setMarginsForView(@Nullable View view, int marginLeft, int marginBottom, @NotNull Context context) {
public void onActivityCreated(Bundle savedInstanceState) { // IMPORTANT: this is workaround for probably android bug
super.onActivityCreated(savedInstanceState); // currently margin values set in styles are not applied for some reasons to the views (using include tag) => set them manually
}
if (view != null) {
@Override final DisplayMetrics dm = context.getResources().getDisplayMetrics();
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { if (view.getLayoutParams() instanceof LinearLayout.LayoutParams) {
if (AndroidCalculatorEngine.Preferences.numeralBase.getKey().equals(key)) { final LinearLayout.LayoutParams oldParams = (LinearLayout.LayoutParams) view.getLayoutParams();
numeralBaseButtons.toggleNumericDigits(this.getActivity(), preferences); final LinearLayout.LayoutParams newParams = new LinearLayout.LayoutParams(oldParams.width, oldParams.height, oldParams.weight);
} newParams.setMargins(AndroidUtils.toPixels(dm, marginLeft), 0, 0, AndroidUtils.toPixels(dm, marginBottom));
view.setLayoutParams(newParams);
if ( CalculatorPreferences.Gui.showEqualsButton.getKey().equals(key) ) { }
CalculatorButtons.toggleEqualsButton(preferences, this.getActivity(), theme, getView()); }
} }*/
if ( AndroidCalculatorEngine.Preferences.multiplicationSign.getKey().equals(key) ) { @Override
CalculatorButtons.initMultiplicationButton(getView()); public void onActivityCreated(Bundle savedInstanceState) {
} super.onActivityCreated(savedInstanceState);
} }
@Override
@Nullable public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
private static AndroidCalculatorDisplayView getCalculatorDisplayView() { if (AndroidCalculatorEngine.Preferences.numeralBase.getKey().equals(key)) {
return (AndroidCalculatorDisplayView) CalculatorLocatorImpl.getInstance().getDisplay().getView(); numeralBaseButtons.toggleNumericDigits(this.getActivity(), preferences);
} }
@NotNull if ( CalculatorPreferences.Gui.showEqualsButton.getKey().equals(key) ) {
private Calculator getCalculator() { CalculatorButtons.toggleEqualsButton(preferences, this.getActivity(), theme, getView());
return CalculatorLocatorImpl.getInstance().getCalculator(); }
}
if ( AndroidCalculatorEngine.Preferences.multiplicationSign.getKey().equals(key) ) {
@NotNull CalculatorButtons.initMultiplicationButton(getView());
private static CalculatorKeyboard getKeyboard() { }
return CalculatorLocatorImpl.getInstance().getKeyboard(); }
}
}
@Nullable
private static AndroidCalculatorDisplayView getCalculatorDisplayView() {
return (AndroidCalculatorDisplayView) CalculatorLocatorImpl.getInstance().getDisplay().getView();
}
@NotNull
private Calculator getCalculator() {
return CalculatorLocatorImpl.getInstance().getCalculator();
}
@NotNull
private static CalculatorKeyboard getKeyboard() {
return CalculatorLocatorImpl.getInstance().getKeyboard();
}
}

View File

@ -1,324 +1,318 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. 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 * or visit http://se.solovyev.org
*/ */
package org.solovyev.android.calculator.history; package org.solovyev.android.calculator.history;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.ListView; import android.widget.ListView;
import com.actionbarsherlock.app.SherlockListFragment; import com.actionbarsherlock.app.SherlockListFragment;
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.*; import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.jscl.JsclOperation; import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.menu.AMenuBuilder; import org.solovyev.android.menu.AMenuBuilder;
import org.solovyev.android.menu.MenuImpl; import org.solovyev.android.menu.MenuImpl;
import org.solovyev.common.collections.CollectionsUtils; import org.solovyev.common.collections.CollectionsUtils;
import org.solovyev.common.equals.Equalizer; import org.solovyev.common.equals.Equalizer;
import org.solovyev.common.filter.Filter; import org.solovyev.common.filter.Filter;
import org.solovyev.common.filter.FilterRule; import org.solovyev.common.filter.FilterRule;
import org.solovyev.common.filter.FilterRulesChain; import org.solovyev.common.filter.FilterRulesChain;
import org.solovyev.common.text.StringUtils; import org.solovyev.common.text.StringUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
/** /**
* User: serso * User: serso
* Date: 10/15/11 * Date: 10/15/11
* Time: 1:13 PM * Time: 1:13 PM
*/ */
public abstract class AbstractCalculatorHistoryFragment extends SherlockListFragment implements CalculatorEventListener { public abstract class AbstractCalculatorHistoryFragment extends SherlockListFragment implements CalculatorEventListener {
/* /*
********************************************************************** **********************************************************************
* *
* CONSTANTS * CONSTANTS
* *
********************************************************************** **********************************************************************
*/ */
@NotNull @NotNull
private static final String TAG = "CalculatorHistoryFragment"; private static final String TAG = "CalculatorHistoryFragment";
public static final Comparator<CalculatorHistoryState> COMPARATOR = new Comparator<CalculatorHistoryState>() { public static final Comparator<CalculatorHistoryState> COMPARATOR = new Comparator<CalculatorHistoryState>() {
@Override @Override
public int compare(CalculatorHistoryState state1, CalculatorHistoryState state2) { public int compare(CalculatorHistoryState state1, CalculatorHistoryState state2) {
if (state1.isSaved() == state2.isSaved()) { if (state1.isSaved() == state2.isSaved()) {
long l = state2.getTime() - state1.getTime(); long l = state2.getTime() - state1.getTime();
return l > 0l ? 1 : (l < 0l ? -1 : 0); return l > 0l ? 1 : (l < 0l ? -1 : 0);
} else if (state1.isSaved()) { } else if (state1.isSaved()) {
return -1; return -1;
} else if (state2.isSaved()) { } else if (state2.isSaved()) {
return 1; return 1;
} }
return 0; return 0;
} }
}; };
/* /*
********************************************************************** **********************************************************************
* *
* FIELDS * FIELDS
* *
********************************************************************** **********************************************************************
*/ */
@NotNull @NotNull
private ArrayAdapter<CalculatorHistoryState> adapter; private ArrayAdapter<CalculatorHistoryState> adapter;
@NotNull @NotNull
private CalculatorFragmentHelper fragmentHelper; private CalculatorFragmentHelper fragmentHelper;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(R.layout.history_fragment); fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(R.layout.history_fragment, getTitleResId(), false);
fragmentHelper.onCreate(this); fragmentHelper.onCreate(this);
logDebug("onCreate"); logDebug("onCreate");
} }
private int logDebug(@NotNull String msg) { private int logDebug(@NotNull String msg) {
return Log.d(TAG + ": " + getTag(), msg); return Log.d(TAG + ": " + getTag(), msg);
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return fragmentHelper.onCreateView(this, inflater, container); return fragmentHelper.onCreateView(this, inflater, container);
} }
@Override @Override
public void onViewCreated(View root, Bundle savedInstanceState) { public void onViewCreated(View root, Bundle savedInstanceState) {
super.onViewCreated(root, savedInstanceState); super.onViewCreated(root, savedInstanceState);
logDebug("onViewCreated"); logDebug("onViewCreated");
fragmentHelper.onViewCreated(this, root); fragmentHelper.onViewCreated(this, root);
fragmentHelper.setPaneTitle(this, getTitleResId());
adapter = new HistoryArrayAdapter(this.getActivity(), getItemLayoutId(), R.id.history_item, new ArrayList<CalculatorHistoryState>());
adapter = new HistoryArrayAdapter(this.getActivity(), getItemLayoutId(), R.id.history_item, new ArrayList<CalculatorHistoryState>()); setListAdapter(adapter);
setListAdapter(adapter);
final ListView lv = getListView();
final ListView lv = getListView(); lv.setTextFilterEnabled(true);
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(final AdapterView<?> parent,
public void onItemClick(final AdapterView<?> parent, final View view,
final View view, final int position,
final int position, final long id) {
final long id) {
useHistoryItem((CalculatorHistoryState) parent.getItemAtPosition(position));
useHistoryItem((CalculatorHistoryState) parent.getItemAtPosition(position)); }
} });
});
lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override
@Override public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) {
public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) { final CalculatorHistoryState historyState = (CalculatorHistoryState) parent.getItemAtPosition(position);
final CalculatorHistoryState historyState = (CalculatorHistoryState) parent.getItemAtPosition(position);
final Context context = getActivity();
final Context context = getActivity();
final HistoryItemMenuData data = new HistoryItemMenuData(historyState, adapter);
final HistoryItemMenuData data = new HistoryItemMenuData(historyState, adapter);
final List<HistoryItemMenuItem> menuItems = CollectionsUtils.asList(HistoryItemMenuItem.values());
final List<HistoryItemMenuItem> menuItems = CollectionsUtils.asList(HistoryItemMenuItem.values());
if (historyState.isSaved()) {
if (historyState.isSaved()) { menuItems.remove(HistoryItemMenuItem.save);
menuItems.remove(HistoryItemMenuItem.save); } else {
} else { if (isAlreadySaved(historyState)) {
if (isAlreadySaved(historyState)) { menuItems.remove(HistoryItemMenuItem.save);
menuItems.remove(HistoryItemMenuItem.save); }
} menuItems.remove(HistoryItemMenuItem.remove);
menuItems.remove(HistoryItemMenuItem.remove); menuItems.remove(HistoryItemMenuItem.edit);
menuItems.remove(HistoryItemMenuItem.edit); }
}
if (historyState.getDisplayState().isValid() && StringUtils.isEmpty(historyState.getDisplayState().getEditorState().getText())) {
if (historyState.getDisplayState().isValid() && StringUtils.isEmpty(historyState.getDisplayState().getEditorState().getText())) { menuItems.remove(HistoryItemMenuItem.copy_result);
menuItems.remove(HistoryItemMenuItem.copy_result); }
}
final AMenuBuilder<HistoryItemMenuItem, HistoryItemMenuData> menuBuilder = AMenuBuilder.newInstance(context, MenuImpl.newInstance(menuItems));
final AMenuBuilder<HistoryItemMenuItem, HistoryItemMenuData> menuBuilder = AMenuBuilder.newInstance(context, MenuImpl.newInstance(menuItems)); menuBuilder.create(data).show();
menuBuilder.create(data).show();
return true;
return true; }
} });
}); }
}
protected abstract int getTitleResId();
protected abstract int getTitleResId();
@Override @Override
public void onDestroy() { public void onResume() {
logDebug("onDestroy"); super.onResume();
fragmentHelper.onDestroy(this); this.fragmentHelper.onResume(this);
super.onDestroy(); updateAdapter();
} }
protected abstract int getItemLayoutId(); @Override
public void onPause() {
@Override this.fragmentHelper.onPause(this);
public void onResume() {
logDebug("onResume"); super.onPause();
}
super.onResume();
@Override
public void onDestroy() {
CalculatorLocatorImpl.getInstance().getCalculator().addCalculatorEventListener(this); logDebug("onDestroy");
updateAdapter(); fragmentHelper.onDestroy(this);
}
super.onDestroy();
@Override }
public void onPause() {
logDebug("onPause"); protected abstract int getItemLayoutId();
super.onPause(); private void updateAdapter() {
final List<CalculatorHistoryState> historyList = getHistoryList();
CalculatorLocatorImpl.getInstance().getCalculator().removeCalculatorEventListener(this);
final ArrayAdapter<CalculatorHistoryState> adapter = getAdapter();
} try {
adapter.setNotifyOnChange(false);
private void updateAdapter() { adapter.clear();
final List<CalculatorHistoryState> historyList = getHistoryList(); for (CalculatorHistoryState historyState : historyList) {
adapter.add(historyState);
final ArrayAdapter<CalculatorHistoryState> adapter = getAdapter(); }
try { } finally {
adapter.setNotifyOnChange(false); adapter.setNotifyOnChange(true);
adapter.clear(); }
for (CalculatorHistoryState historyState : historyList) {
adapter.add(historyState); adapter.notifyDataSetChanged();
} }
} finally {
adapter.setNotifyOnChange(true); public static boolean isAlreadySaved(@NotNull CalculatorHistoryState historyState) {
} assert !historyState.isSaved();
adapter.notifyDataSetChanged(); boolean result = false;
} try {
historyState.setSaved(true);
public static boolean isAlreadySaved(@NotNull CalculatorHistoryState historyState) { if ( CollectionsUtils.contains(historyState, CalculatorLocatorImpl.getInstance().getHistory().getSavedHistory(), new Equalizer<CalculatorHistoryState>() {
assert !historyState.isSaved(); @Override
public boolean equals(@Nullable CalculatorHistoryState first, @Nullable CalculatorHistoryState second) {
boolean result = false; return first != null && second != null &&
try { first.getTime() == second.getTime() &&
historyState.setSaved(true); first.getDisplayState().equals(second.getDisplayState()) &&
if ( CollectionsUtils.contains(historyState, CalculatorLocatorImpl.getInstance().getHistory().getSavedHistory(), new Equalizer<CalculatorHistoryState>() { first.getEditorState().equals(second.getEditorState());
@Override }
public boolean equals(@Nullable CalculatorHistoryState first, @Nullable CalculatorHistoryState second) { }) ) {
return first != null && second != null && result = true;
first.getTime() == second.getTime() && }
first.getDisplayState().equals(second.getDisplayState()) && } finally {
first.getEditorState().equals(second.getEditorState()); historyState.setSaved(false);
} }
}) ) { return result;
result = true; }
}
} finally { public static void useHistoryItem(@NotNull final CalculatorHistoryState historyState) {
historyState.setSaved(false); CalculatorLocatorImpl.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.use_history_state, historyState);
} }
return result;
} @NotNull
private List<CalculatorHistoryState> getHistoryList() {
public static void useHistoryItem(@NotNull final CalculatorHistoryState historyState) { final List<CalculatorHistoryState> calculatorHistoryStates = getHistoryItems();
CalculatorLocatorImpl.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.use_history_state, historyState);
} Collections.sort(calculatorHistoryStates, COMPARATOR);
@NotNull final FilterRulesChain<CalculatorHistoryState> filterRulesChain = new FilterRulesChain<CalculatorHistoryState>();
private List<CalculatorHistoryState> getHistoryList() { filterRulesChain.addFilterRule(new FilterRule<CalculatorHistoryState>() {
final List<CalculatorHistoryState> calculatorHistoryStates = getHistoryItems(); @Override
public boolean isFiltered(CalculatorHistoryState object) {
Collections.sort(calculatorHistoryStates, COMPARATOR); return object == null || StringUtils.isEmpty(object.getEditorState().getText());
}
final FilterRulesChain<CalculatorHistoryState> filterRulesChain = new FilterRulesChain<CalculatorHistoryState>(); });
filterRulesChain.addFilterRule(new FilterRule<CalculatorHistoryState>() {
@Override new Filter<CalculatorHistoryState>(filterRulesChain).filter(calculatorHistoryStates.iterator());
public boolean isFiltered(CalculatorHistoryState object) {
return object == null || StringUtils.isEmpty(object.getEditorState().getText()); return calculatorHistoryStates;
} }
});
@NotNull
new Filter<CalculatorHistoryState>(filterRulesChain).filter(calculatorHistoryStates.iterator()); protected abstract List<CalculatorHistoryState> getHistoryItems();
return calculatorHistoryStates; @NotNull
} public static String getHistoryText(@NotNull CalculatorHistoryState state) {
final StringBuilder result = new StringBuilder();
@NotNull result.append(state.getEditorState().getText());
protected abstract List<CalculatorHistoryState> getHistoryItems(); result.append(getIdentitySign(state.getDisplayState().getJsclOperation()));
final String expressionResult = state.getDisplayState().getEditorState().getText();
@NotNull if (expressionResult != null) {
public static String getHistoryText(@NotNull CalculatorHistoryState state) { result.append(expressionResult);
final StringBuilder result = new StringBuilder(); }
result.append(state.getEditorState().getText()); return result.toString();
result.append(getIdentitySign(state.getDisplayState().getJsclOperation())); }
final String expressionResult = state.getDisplayState().getEditorState().getText();
if (expressionResult != null) { @NotNull
result.append(expressionResult); private static String getIdentitySign(@NotNull JsclOperation jsclOperation) {
} return jsclOperation == JsclOperation.simplify ? "" : "=";
return result.toString(); }
}
// todo serso: menu
@NotNull /* @Override
private static String getIdentitySign(@NotNull JsclOperation jsclOperation) { public boolean onCreateOptionsMenu(android.view.Menu menu) {
return jsclOperation == JsclOperation.simplify ? "" : "="; final MenuInflater menuInflater = getMenuInflater();
} menuInflater.inflate(R.menu.history_menu, menu);
return true;
// todo serso: menu }
/* @Override
public boolean onCreateOptionsMenu(android.view.Menu menu) { @Override
final MenuInflater menuInflater = getMenuInflater(); public boolean onOptionsItemSelected(MenuItem item) {
menuInflater.inflate(R.menu.history_menu, menu); boolean result;
return true;
} switch (item.getItemId()) {
case R.id.history_menu_clear_history:
@Override clearHistory();
public boolean onOptionsItemSelected(MenuItem item) { result = true;
boolean result; break;
default:
switch (item.getItemId()) { result = super.onOptionsItemSelected(item);
case R.id.history_menu_clear_history: }
clearHistory();
result = true; return result;
break; }*/
default:
result = super.onOptionsItemSelected(item); protected abstract void clearHistory();
}
@NotNull
return result; protected ArrayAdapter<CalculatorHistoryState> getAdapter() {
}*/ return adapter;
}
protected abstract void clearHistory();
@Override
@NotNull public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
protected ArrayAdapter<CalculatorHistoryState> getAdapter() { if ( calculatorEventType == CalculatorEventType.history_state_added ) {
return adapter;
} getActivity().runOnUiThread(new Runnable() {
@Override
@Override public void run() {
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) { logDebug("onCalculatorEvent");
if ( calculatorEventType == CalculatorEventType.history_state_added ) { updateAdapter();
}
getActivity().runOnUiThread(new Runnable() { });
@Override }
public void run() { }
logDebug("onCalculatorEvent"); }
updateAdapter();
}
});
}
}
}

View File

@ -30,8 +30,6 @@ public class CalculatorHistoryFragmentActivity extends SherlockFragmentActivity
activityHelper.addTab(this, "history", CalculatorHistoryFragment.class, null, R.string.c_history, R.id.main_layout); activityHelper.addTab(this, "history", CalculatorHistoryFragment.class, null, R.string.c_history, R.id.main_layout);
activityHelper.addTab(this, "saved_history", CalculatorSavedHistoryFragment.class, null, R.string.c_saved_history, R.id.main_layout); activityHelper.addTab(this, "saved_history", CalculatorSavedHistoryFragment.class, null, R.string.c_saved_history, R.id.main_layout);
CalculatorLocatorImpl.getInstance().getCalculator().addCalculatorEventListener(this);
} }
@Override @Override
@ -53,8 +51,6 @@ public class CalculatorHistoryFragmentActivity extends SherlockFragmentActivity
super.onDestroy(); super.onDestroy();
activityHelper.onDestroy(this); activityHelper.onDestroy(this);
CalculatorLocatorImpl.getInstance().getCalculator().removeCalculatorEventListener(this);
} }
@Override @Override

View File

@ -1,321 +1,329 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. 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 * or visit http://se.solovyev.org
*/ */
package org.solovyev.android.calculator.math.edit; package org.solovyev.android.calculator.math.edit;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.*; import android.widget.*;
import com.actionbarsherlock.app.SherlockListFragment; import com.actionbarsherlock.app.SherlockListFragment;
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.*; import org.solovyev.android.calculator.*;
import org.solovyev.android.menu.AMenuBuilder; import org.solovyev.android.menu.AMenuBuilder;
import org.solovyev.android.menu.LabeledMenuItem; import org.solovyev.android.menu.LabeledMenuItem;
import org.solovyev.android.menu.MenuImpl; import org.solovyev.android.menu.MenuImpl;
import org.solovyev.common.equals.EqualsTool; import org.solovyev.common.equals.EqualsTool;
import org.solovyev.common.filter.Filter; import org.solovyev.common.filter.Filter;
import org.solovyev.common.filter.FilterRule; import org.solovyev.common.filter.FilterRule;
import org.solovyev.common.math.MathEntity; import org.solovyev.common.math.MathEntity;
import org.solovyev.common.text.StringUtils; import org.solovyev.common.text.StringUtils;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
/** /**
* User: serso * User: serso
* Date: 12/21/11 * Date: 12/21/11
* Time: 9:24 PM * Time: 9:24 PM
*/ */
public abstract class AbstractMathEntityListFragment<T extends MathEntity> extends SherlockListFragment { public abstract class AbstractMathEntityListFragment<T extends MathEntity> extends SherlockListFragment {
/* /*
********************************************************************** **********************************************************************
* *
* CONSTANTS * CONSTANTS
* *
********************************************************************** **********************************************************************
*/ */
public static final String MATH_ENTITY_CATEGORY_EXTRA_STRING = "org.solovyev.android.calculator.CalculatorVarsActivity_math_entity_category"; public static final String MATH_ENTITY_CATEGORY_EXTRA_STRING = "org.solovyev.android.calculator.CalculatorVarsActivity_math_entity_category";
protected final static List<Character> acceptableChars = Arrays.asList(StringUtils.toObject("1234567890abcdefghijklmnopqrstuvwxyzйцукенгшщзхъфывапролджэячсмитьбюё_".toCharArray())); protected final static List<Character> acceptableChars = Arrays.asList(StringUtils.toObject("1234567890abcdefghijklmnopqrstuvwxyzйцукенгшщзхъфывапролджэячсмитьбюё_".toCharArray()));
/* /*
********************************************************************** **********************************************************************
* *
* FIELDS * FIELDS
* *
********************************************************************** **********************************************************************
*/ */
@Nullable @Nullable
private MathEntityArrayAdapter<T> adapter; private MathEntityArrayAdapter<T> adapter;
@Nullable @Nullable
private String category; private String category;
@NotNull @NotNull
private CalculatorFragmentHelper fragmentHelper; private CalculatorFragmentHelper fragmentHelper;
protected int getLayoutId() { protected int getLayoutId() {
return R.layout.math_entities_fragment; return R.layout.math_entities_fragment;
} }
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
final Bundle bundle = getArguments(); final Bundle bundle = getArguments();
if ( bundle != null ) { if ( bundle != null ) {
category = bundle.getString(MATH_ENTITY_CATEGORY_EXTRA_STRING); category = bundle.getString(MATH_ENTITY_CATEGORY_EXTRA_STRING);
} }
fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(getLayoutId()); fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(getLayoutId(), getTitleResId());
fragmentHelper.onCreate(this); fragmentHelper.onCreate(this);
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return fragmentHelper.onCreateView(this, inflater, container); return fragmentHelper.onCreateView(this, inflater, container);
} }
@Override @Override
public void onViewCreated(View root, Bundle savedInstanceState) { public void onViewCreated(View root, Bundle savedInstanceState) {
super.onViewCreated(root, savedInstanceState); super.onViewCreated(root, savedInstanceState);
fragmentHelper.onViewCreated(this, root); fragmentHelper.onViewCreated(this, root);
this.fragmentHelper.setPaneTitle(this, getTitleResId());
final ListView lv = getListView();
final ListView lv = getListView(); lv.setTextFilterEnabled(true);
lv.setTextFilterEnabled(true);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { public void onItemClick(final AdapterView<?> parent,
public void onItemClick(final AdapterView<?> parent, final View view,
final View view, final int position,
final int position, final long id) {
final long id) {
CalculatorLocatorImpl.getInstance().getKeyboard().digitButtonPressed(((MathEntity) parent.getItemAtPosition(position)).getName());
CalculatorLocatorImpl.getInstance().getKeyboard().digitButtonPressed(((MathEntity) parent.getItemAtPosition(position)).getName()); getActivity().finish();
getActivity().finish(); }
} });
});
getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
getListView().setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { @Override
@Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { final T item = (T) parent.getItemAtPosition(position);
final T item = (T) parent.getItemAtPosition(position);
final List<LabeledMenuItem<T>> menuItems = getMenuItemsOnLongClick(item);
final List<LabeledMenuItem<T>> menuItems = getMenuItemsOnLongClick(item);
if (!menuItems.isEmpty()) {
if (!menuItems.isEmpty()) { final AMenuBuilder<LabeledMenuItem<T>, T> menuBuilder = AMenuBuilder.newInstance(AbstractMathEntityListFragment.this.getActivity(), MenuImpl.newInstance(menuItems));
final AMenuBuilder<LabeledMenuItem<T>, T> menuBuilder = AMenuBuilder.newInstance(AbstractMathEntityListFragment.this.getActivity(), MenuImpl.newInstance(menuItems)); menuBuilder.create(item).show();
menuBuilder.create(item).show(); }
}
return true;
return true; }
} });
}); }
}
protected abstract int getTitleResId();
protected abstract int getTitleResId();
@Override
@Override public void onDestroy() {
public void onDestroy() { fragmentHelper.onDestroy(this);
fragmentHelper.onDestroy(this);
super.onDestroy();
super.onDestroy(); }
}
@NotNull
@NotNull protected abstract List<LabeledMenuItem<T>> getMenuItemsOnLongClick(@NotNull T item);
protected abstract List<LabeledMenuItem<T>> getMenuItemsOnLongClick(@NotNull T item);
@Override
@Override public void onPause() {
public void onResume() { this.fragmentHelper.onPause(this);
super.onResume();
super.onPause();
adapter = new MathEntityArrayAdapter<T>(getDescriptionGetter(), this.getActivity(), R.layout.math_entity, R.id.math_entity_text, getMathEntitiesByCategory()); }
setListAdapter(adapter);
@Override
sort(); public void onResume() {
} super.onResume();
@NotNull this.fragmentHelper.onResume(this);
private List<T> getMathEntitiesByCategory() {
final List<T> result = getMathEntities(); adapter = new MathEntityArrayAdapter<T>(getDescriptionGetter(), this.getActivity(), R.layout.math_entity, R.id.math_entity_text, getMathEntitiesByCategory());
setListAdapter(adapter);
new Filter<T>(new FilterRule<T>() {
@Override sort();
public boolean isFiltered(T t) { }
return !isInCategory(t);
} @NotNull
}).filter(result.iterator()); private List<T> getMathEntitiesByCategory() {
final List<T> result = getMathEntities();
return result;
} new Filter<T>(new FilterRule<T>() {
@Override
protected boolean isInCategory(@Nullable T t) { public boolean isFiltered(T t) {
return t != null && (category == null || EqualsTool.areEqual(getMathEntityCategory(t), category)); return !isInCategory(t);
} }
}).filter(result.iterator());
@NotNull
protected abstract MathEntityDescriptionGetter getDescriptionGetter(); return result;
}
@NotNull
protected abstract List<T> getMathEntities(); protected boolean isInCategory(@Nullable T t) {
return t != null && (category == null || EqualsTool.areEqual(getMathEntityCategory(t), category));
@Nullable }
abstract String getMathEntityCategory(@NotNull T t);
@NotNull
protected void sort() { protected abstract MathEntityDescriptionGetter getDescriptionGetter();
final MathEntityArrayAdapter<T> localAdapter = adapter;
if (localAdapter != null) { @NotNull
localAdapter.sort(new Comparator<T>() { protected abstract List<T> getMathEntities();
@Override
public int compare(T function1, T function2) { @Nullable
return function1.getName().compareTo(function2.getName()); abstract String getMathEntityCategory(@NotNull T t);
}
}); protected void sort() {
final MathEntityArrayAdapter<T> localAdapter = adapter;
localAdapter.notifyDataSetChanged(); if (localAdapter != null) {
} localAdapter.sort(new Comparator<T>() {
} @Override
public int compare(T function1, T function2) {
protected static class MathEntityArrayAdapter<T extends MathEntity> extends ArrayAdapter<T> { return function1.getName().compareTo(function2.getName());
}
@NotNull });
private final MathEntityDescriptionGetter descriptionGetter;
localAdapter.notifyDataSetChanged();
private MathEntityArrayAdapter(@NotNull MathEntityDescriptionGetter descriptionGetter, }
@NotNull Context context, }
int resource,
int textViewResourceId, protected static class MathEntityArrayAdapter<T extends MathEntity> extends ArrayAdapter<T> {
@NotNull List<T> objects) {
@NotNull
super(context, resource, textViewResourceId, objects); private final MathEntityDescriptionGetter descriptionGetter;
this.descriptionGetter = descriptionGetter;
} private MathEntityArrayAdapter(@NotNull MathEntityDescriptionGetter descriptionGetter,
@NotNull Context context,
@Override int resource,
public View getView(int position, View convertView, ViewGroup parent) { int textViewResourceId,
final ViewGroup result = (ViewGroup) super.getView(position, convertView, parent); @NotNull List<T> objects) {
final T mathEntity = getItem(position); super(context, resource, textViewResourceId, objects);
this.descriptionGetter = descriptionGetter;
final String mathEntityDescription = descriptionGetter.getDescription(getContext(), mathEntity.getName()); }
if (!StringUtils.isEmpty(mathEntityDescription)) {
TextView description = (TextView) result.findViewById(R.id.math_entity_description); @Override
if (description == null) { public View getView(int position, View convertView, ViewGroup parent) {
final LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Activity.LAYOUT_INFLATER_SERVICE); final ViewGroup result = (ViewGroup) super.getView(position, convertView, parent);
final ViewGroup itemView = (ViewGroup) layoutInflater.inflate(R.layout.math_entity, null);
description = (TextView) itemView.findViewById(R.id.math_entity_description); final T mathEntity = getItem(position);
itemView.removeView(description);
result.addView(description); final String mathEntityDescription = descriptionGetter.getDescription(getContext(), mathEntity.getName());
} if (!StringUtils.isEmpty(mathEntityDescription)) {
description.setText(mathEntityDescription); TextView description = (TextView) result.findViewById(R.id.math_entity_description);
} else { if (description == null) {
TextView description = (TextView) result.findViewById(R.id.math_entity_description); final LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
if (description != null) { final ViewGroup itemView = (ViewGroup) layoutInflater.inflate(R.layout.math_entity, null);
result.removeView(description); description = (TextView) itemView.findViewById(R.id.math_entity_description);
} itemView.removeView(description);
} result.addView(description);
}
description.setText(mathEntityDescription);
return result; } else {
} TextView description = (TextView) result.findViewById(R.id.math_entity_description);
} if (description != null) {
result.removeView(description);
protected static class MathEntityDescriptionGetterImpl implements MathEntityDescriptionGetter { }
}
@NotNull
private final CalculatorMathRegistry<?> mathRegistry;
return result;
public MathEntityDescriptionGetterImpl(@NotNull CalculatorMathRegistry<?> mathRegistry) { }
this.mathRegistry = mathRegistry; }
}
protected static class MathEntityDescriptionGetterImpl implements MathEntityDescriptionGetter {
@Override
public String getDescription(@NotNull Context context, @NotNull String mathEntityName) { @NotNull
return this.mathRegistry.getDescription(mathEntityName); private final CalculatorMathRegistry<?> mathRegistry;
}
} public MathEntityDescriptionGetterImpl(@NotNull CalculatorMathRegistry<?> mathRegistry) {
this.mathRegistry = mathRegistry;
protected static interface MathEntityDescriptionGetter { }
@Nullable @Override
String getDescription(@NotNull Context context, @NotNull String mathEntityName); public String getDescription(@NotNull Context context, @NotNull String mathEntityName) {
} return this.mathRegistry.getDescription(mathEntityName);
}
public void addToAdapter(@NotNull T mathEntity) { }
if (this.adapter != null) {
this.adapter.add(mathEntity); protected static interface MathEntityDescriptionGetter {
}
} @Nullable
String getDescription(@NotNull Context context, @NotNull String mathEntityName);
public void removeFromAdapter(@NotNull T mathEntity) { }
if (this.adapter != null) {
this.adapter.remove(mathEntity); public void addToAdapter(@NotNull T mathEntity) {
} if (this.adapter != null) {
} this.adapter.add(mathEntity);
}
public void notifyAdapter() { }
if (this.adapter != null) {
this.adapter.notifyDataSetChanged(); public void removeFromAdapter(@NotNull T mathEntity) {
} if (this.adapter != null) {
} this.adapter.remove(mathEntity);
}
/* }
**********************************************************************
* public void notifyAdapter() {
* STATIC if (this.adapter != null) {
* this.adapter.notifyDataSetChanged();
********************************************************************** }
*/ }
static void createTab(@NotNull Context context, /*
@NotNull TabHost tabHost, **********************************************************************
@NotNull String tabId, *
@NotNull String categoryId, * STATIC
int tabCaptionId, *
@NotNull Class<? extends Activity> activityClass, **********************************************************************
@Nullable Intent parentIntent) { */
TabHost.TabSpec spec; static void createTab(@NotNull Context context,
@NotNull TabHost tabHost,
final Intent intent; @NotNull String tabId,
if (parentIntent != null) { @NotNull String categoryId,
intent = new Intent(parentIntent); int tabCaptionId,
} else { @NotNull Class<? extends Activity> activityClass,
intent = new Intent(); @Nullable Intent parentIntent) {
}
intent.setClass(context, activityClass); TabHost.TabSpec spec;
intent.putExtra(MATH_ENTITY_CATEGORY_EXTRA_STRING, categoryId);
final Intent intent;
// Initialize a TabSpec for each tab and add it to the TabHost if (parentIntent != null) {
spec = tabHost.newTabSpec(tabId).setIndicator(context.getString(tabCaptionId)).setContent(intent); intent = new Intent(parentIntent);
} else {
tabHost.addTab(spec); intent = new Intent();
} }
intent.setClass(context, activityClass);
@NotNull intent.putExtra(MATH_ENTITY_CATEGORY_EXTRA_STRING, categoryId);
public static Bundle createBundleFor(@NotNull String categoryId) {
final Bundle result = new Bundle(1); // Initialize a TabSpec for each tab and add it to the TabHost
putCategory(result, categoryId); spec = tabHost.newTabSpec(tabId).setIndicator(context.getString(tabCaptionId)).setContent(intent);
return result;
} tabHost.addTab(spec);
}
static void putCategory(@NotNull Bundle bundle, @NotNull String categoryId) {
bundle.putString(MATH_ENTITY_CATEGORY_EXTRA_STRING, categoryId); @NotNull
} public static Bundle createBundleFor(@NotNull String categoryId) {
} final Bundle result = new Bundle(1);
putCategory(result, categoryId);
return result;
}
static void putCategory(@NotNull Bundle bundle, @NotNull String categoryId) {
bundle.putString(MATH_ENTITY_CATEGORY_EXTRA_STRING, categoryId);
}
}

View File

@ -1,68 +1,63 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. 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 * or visit http://se.solovyev.org
*/ */
package org.solovyev.android.calculator.math.edit; package org.solovyev.android.calculator.math.edit;
import android.os.Bundle; import android.os.Bundle;
import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.app.SherlockFragmentActivity;
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.*; import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.history.CalculatorHistoryFragment; import org.solovyev.android.calculator.history.CalculatorHistoryFragmentActivity;
import org.solovyev.android.calculator.history.CalculatorHistoryFragmentActivity; import org.solovyev.android.calculator.model.AndroidFunctionsMathRegistry;
import org.solovyev.android.calculator.model.AndroidFunctionsMathRegistry;
/**
/** * User: serso
* User: serso * Date: 12/21/11
* Date: 12/21/11 * Time: 10:33 PM
* Time: 10:33 PM */
*/ public class CalculatorFunctionsFragmentActivity extends SherlockFragmentActivity implements CalculatorEventListener {
public class CalculatorFunctionsFragmentActivity extends SherlockFragmentActivity implements CalculatorEventListener {
@NotNull
@NotNull private final CalculatorActivityHelper activityHelper = CalculatorApplication.getInstance().createActivityHelper(R.layout.main_empty, CalculatorHistoryFragmentActivity.class.getSimpleName());
private final CalculatorActivityHelper activityHelper = CalculatorApplication.getInstance().createActivityHelper(R.layout.main_empty, CalculatorHistoryFragmentActivity.class.getSimpleName());
@Override
@Override public void onCreate(@Nullable Bundle savedInstanceState) {
public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState);
super.onCreate(savedInstanceState);
activityHelper.onCreate(this, savedInstanceState);
activityHelper.onCreate(this, savedInstanceState);
for (AndroidFunctionsMathRegistry.Category category : AndroidFunctionsMathRegistry.Category.getCategoriesByTabOrder()) {
for (AndroidFunctionsMathRegistry.Category category : AndroidFunctionsMathRegistry.Category.getCategoriesByTabOrder()) { activityHelper.addTab(this, category.name(), CalculatorFunctionsFragment.class, AbstractMathEntityListFragment.createBundleFor(category.name()), category.getCaptionId(), R.id.main_layout);
activityHelper.addTab(this, category.name(), CalculatorFunctionsFragment.class, AbstractMathEntityListFragment.createBundleFor(category.name()), category.getCaptionId(), R.id.main_layout); }
} }
CalculatorLocatorImpl.getInstance().getCalculator().addCalculatorEventListener(this); @Override
} protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
@Override
protected void onSaveInstanceState(Bundle outState) { activityHelper.onSaveInstanceState(this, outState);
super.onSaveInstanceState(outState); }
activityHelper.onSaveInstanceState(this, outState); @Override
} protected void onResume() {
super.onResume();
@Override
protected void onResume() { activityHelper.onResume(this);
super.onResume(); }
activityHelper.onResume(this); @Override
} protected void onDestroy() {
super.onDestroy();
@Override
protected void onDestroy() { this.activityHelper.onDestroy(this);
super.onDestroy(); }
this.activityHelper.onDestroy(this); @Override
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
CalculatorLocatorImpl.getInstance().getCalculator().removeCalculatorEventListener(this); //To change body of implemented methods use File | Settings | File Templates.
} }
}
@Override
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
//To change body of implemented methods use File | Settings | File Templates.
}
}

View File

@ -1,89 +1,85 @@
/* /*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev. * Copyright (c) 2009-2011. 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 * or visit http://se.solovyev.org
*/ */
package org.solovyev.android.calculator.math.edit; package org.solovyev.android.calculator.math.edit;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.app.SherlockFragmentActivity;
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.*; import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.history.CalculatorHistoryFragmentActivity; import org.solovyev.android.calculator.history.CalculatorHistoryFragmentActivity;
import org.solovyev.android.calculator.model.VarCategory; import org.solovyev.android.calculator.model.VarCategory;
/** /**
* User: serso * User: serso
* Date: 12/21/11 * Date: 12/21/11
* Time: 11:05 PM * Time: 11:05 PM
*/ */
public class CalculatorVarsFragmentActivity extends SherlockFragmentActivity implements CalculatorEventListener { public class CalculatorVarsFragmentActivity extends SherlockFragmentActivity implements CalculatorEventListener {
@NotNull @NotNull
private final CalculatorActivityHelper activityHelper = CalculatorApplication.getInstance().createActivityHelper(R.layout.main_empty, CalculatorHistoryFragmentActivity.class.getSimpleName()); private final CalculatorActivityHelper activityHelper = CalculatorApplication.getInstance().createActivityHelper(R.layout.main_empty, CalculatorHistoryFragmentActivity.class.getSimpleName());
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
activityHelper.onCreate(this, savedInstanceState); activityHelper.onCreate(this, savedInstanceState);
final Bundle bundle; final Bundle bundle;
final Intent intent = getIntent(); final Intent intent = getIntent();
if (intent != null) { if (intent != null) {
bundle = intent.getExtras(); bundle = intent.getExtras();
} else { } else {
bundle = null; bundle = null;
} }
for (VarCategory category : VarCategory.getCategoriesByTabOrder()) { for (VarCategory category : VarCategory.getCategoriesByTabOrder()) {
final Bundle fragmentParameters; final Bundle fragmentParameters;
if (category == VarCategory.my && bundle != null) { if (category == VarCategory.my && bundle != null) {
AbstractMathEntityListFragment.putCategory(bundle, category.name()); AbstractMathEntityListFragment.putCategory(bundle, category.name());
fragmentParameters = bundle; fragmentParameters = bundle;
} else { } else {
fragmentParameters = AbstractMathEntityListFragment.createBundleFor(category.name()); fragmentParameters = AbstractMathEntityListFragment.createBundleFor(category.name());
} }
activityHelper.addTab(this, category.name(), CalculatorVarsFragment.class, fragmentParameters, category.getCaptionId(), R.id.main_layout); activityHelper.addTab(this, category.name(), CalculatorVarsFragment.class, fragmentParameters, category.getCaptionId(), R.id.main_layout);
} }
}
CalculatorLocatorImpl.getInstance().getCalculator().addCalculatorEventListener(this);
} @Override
protected void onSaveInstanceState(Bundle outState) {
@Override super.onSaveInstanceState(outState);
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); activityHelper.onSaveInstanceState(this, outState);
}
activityHelper.onSaveInstanceState(this, outState);
} @Override
protected void onResume() {
@Override super.onResume();
protected void onResume() {
super.onResume(); activityHelper.onResume(this);
}
activityHelper.onResume(this);
} @Override
protected void onDestroy() {
@Override super.onDestroy();
protected void onDestroy() {
super.onDestroy(); this.activityHelper.onDestroy(this);
}
this.activityHelper.onDestroy(this);
@Override
CalculatorLocatorImpl.getInstance().getCalculator().removeCalculatorEventListener(this); public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
} //To change body of implemented methods use File | Settings | File Templates.
}
@Override }
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
//To change body of implemented methods use File | Settings | File Templates.
}
}

View File

@ -0,0 +1,488 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.android.calculator.plot;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragment;
import jscl.math.Expression;
import jscl.math.Generic;
import jscl.math.function.Constant;
import jscl.text.ParseException;
import org.achartengine.GraphicalView;
import org.achartengine.chart.CubicLineChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.chart.XYChart;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.BasicStroke;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import org.achartengine.tools.PanListener;
import org.achartengine.tools.ZoomEvent;
import org.achartengine.tools.ZoomListener;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.*;
import org.solovyev.common.MutableObject;
import org.solovyev.common.collections.CollectionsUtils;
import java.io.Serializable;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
* User: serso
* Date: 12/1/11
* Time: 12:40 AM
*/
public class CalculatorPlotFragment extends SherlockFragment implements CalculatorEventListener {
private static final String TAG = CalculatorPlotFragment.class.getSimpleName();
private static final int DEFAULT_NUMBER_OF_STEPS = 100;
private static final int DEFAULT_MIN_NUMBER = -10;
private static final int DEFAULT_MAX_NUMBER = 10;
public static final String INPUT = "org.solovyev.android.calculator.CalculatorPlotActivity_input";
public static final long EVAL_DELAY_MILLIS = 200;
private XYChart chart;
/**
* The encapsulated graphical view.
*/
private GraphicalView graphicalView;
@NotNull
private Generic expression;
@NotNull
private Constant variable;
@NotNull
private final CalculatorFragmentHelper fragmentHelper = CalculatorApplication.getInstance().createFragmentHelper(R.layout.plot_fragment, R.string.c_plot, false);
@NotNull
private final Executor plotExecutor = Executors.newSingleThreadExecutor();
@NotNull
private final Handler uiHandler = new Handler();
@Nullable
private Input input = null;
private boolean inputFromArgs = true;
@NotNull
private CalculatorEventData lastCalculatorEventData = CalculatorUtils.createFirstEventDataId();
private int bgColor;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.fragmentHelper.onCreate(this);
final Bundle arguments = getArguments();
if (arguments != null) {
input = (Input) arguments.getSerializable(INPUT);
}
if (input == null) {
inputFromArgs = false;
createInputFromDisplayState(CalculatorLocatorImpl.getInstance().getDisplay().getViewState());
this.bgColor = getResources().getColor(R.color.pane_background);
} else {
this.bgColor = getResources().getColor(android.R.color.transparent);
prepareData();
}
}
private void createInputFromDisplayState(@NotNull CalculatorDisplayViewState displayState) {
try {
if (displayState.isValid() && displayState.getResult() != null) {
final Generic expression = displayState.getResult();
if (CalculatorUtils.isPlotPossible(expression, displayState.getOperation())) {
final Constant constant = CollectionsUtils.getFirstCollectionElement(CalculatorUtils.getNotSystemConstants(expression));
input = new Input(expression.toString(), constant.getName());
prepareData();
}
}
} catch (RuntimeException e) {
this.input = null;
Log.e(TAG, e.getLocalizedMessage(), e);
}
}
private void prepareData(){
try {
if (input != null) {
final PreparedExpression preparedExpression = ToJsclTextProcessor.getInstance().process(input.getExpression());
this.expression = Expression.valueOf(preparedExpression.getExpression());
this.variable = new Constant(input.getVariableName());
this.chart = prepareChart(getMinValue(null), getMaxValue(null), this.expression, variable, bgColor);
}
} catch (ParseException e) {
this.input = null;
Toast.makeText(this.getActivity(), e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
} catch (CalculatorParseException e) {
this.input = null;
Toast.makeText(this.getActivity(), e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return this.fragmentHelper.onCreateView(this, inflater, container);
}
@Override
public void onViewCreated(View root, Bundle savedInstanceState) {
super.onViewCreated(root, savedInstanceState);
this.fragmentHelper.onViewCreated(this, root);
updateGraphicalView(root);
}
@Override
public void onResume() {
super.onResume();
this.fragmentHelper.onResume(this);
if ( !inputFromArgs ) {
createInputFromDisplayState(CalculatorLocatorImpl.getInstance().getDisplay().getViewState());
updateGraphicalView(getView());
}
}
@Override
public void onPause() {
this.fragmentHelper.onPause(this);
super.onPause();
}
private void updateGraphicalView(@NotNull View root) {
if (input != null) {
// todo serso
final Object lastNonConfigurationInstance = null;//getLastNonConfigurationInstance();
setGraphicalView(root, lastNonConfigurationInstance instanceof PlotBoundaries ? (PlotBoundaries) lastNonConfigurationInstance : null);
} else {
Toast.makeText(this.getActivity(), "Plot is not possible!", Toast.LENGTH_LONG).show();
}
}
@Override
public void onDestroy() {
this.fragmentHelper.onDestroy(this);
super.onDestroy();
}
private void setGraphicalView(@NotNull View root, @Nullable PlotBoundaries plotBoundaries) {
double minValue = getMinValue(plotBoundaries);
double maxValue = getMaxValue(plotBoundaries);
final ViewGroup graphContainer = (ViewGroup) root.findViewById(R.id.main_fragment_layout);
if (graphicalView != null) {
graphContainer.removeView(graphicalView);
}
// reverting boundaries (as in prepareChart() we add some cached values )
double minX = Double.MAX_VALUE;
double minY = Double.MAX_VALUE;
double maxX = Double.MIN_VALUE;
double maxY = Double.MIN_VALUE;
for (XYSeries series : chart.getDataset().getSeries()) {
minX = Math.min(minX, series.getMinX());
minY = Math.min(minY, series.getMinY());
maxX = Math.max(maxX, series.getMaxX());
maxY = Math.max(maxY, series.getMaxY());
}
Log.d(CalculatorPlotFragment.class.getName(), "min x: " + minX + ", min y: " + minY + ", max x: " + maxX + ", max y: " + maxY);
Log.d(CalculatorPlotFragment.class.getName(), "Plot boundaries are " + plotBoundaries);
if (plotBoundaries == null) {
chart.getRenderer().setXAxisMin(Math.max(minX, minValue));
chart.getRenderer().setYAxisMin(Math.max(minY, minValue));
chart.getRenderer().setXAxisMax(Math.min(maxX, maxValue));
chart.getRenderer().setYAxisMax(Math.min(maxY, maxValue));
} else {
chart.getRenderer().setXAxisMin(plotBoundaries.xMin);
chart.getRenderer().setYAxisMin(plotBoundaries.yMin);
chart.getRenderer().setXAxisMax(plotBoundaries.xMax);
chart.getRenderer().setYAxisMax(plotBoundaries.yMax);
}
graphicalView = new GraphicalView(this.getActivity(), chart);
graphicalView.setBackgroundColor(this.bgColor);
graphicalView.addZoomListener(new ZoomListener() {
@Override
public void zoomApplied(ZoomEvent e) {
updateDataSets(chart);
}
@Override
public void zoomReset() {
updateDataSets(chart);
}
}, true, true);
graphicalView.addPanListener(new PanListener() {
@Override
public void panApplied() {
Log.d(TAG, "org.achartengine.tools.PanListener.panApplied");
updateDataSets(chart);
}
});
graphContainer.addView(graphicalView);
updateDataSets(chart, 50);
}
private double getMaxValue(@Nullable PlotBoundaries plotBoundaries) {
return plotBoundaries == null ? DEFAULT_MAX_NUMBER : plotBoundaries.xMax;
}
private double getMinValue(@Nullable PlotBoundaries plotBoundaries) {
return plotBoundaries == null ? DEFAULT_MIN_NUMBER : plotBoundaries.xMin;
}
private void updateDataSets(@NotNull final XYChart chart) {
updateDataSets(chart, EVAL_DELAY_MILLIS);
}
private void updateDataSets(@NotNull final XYChart chart, long millisToWait) {
pendingOperation.setObject(new Runnable() {
@Override
public void run() {
// allow only one runner at one time
synchronized (pendingOperation) {
//lock all operations with history
if (pendingOperation.getObject() == this) {
plotExecutor.execute(new Runnable() {
@Override
public void run() {
Log.d(TAG, "org.solovyev.android.calculator.plot.CalculatorPlotActivity.updateDataSets");
final XYMultipleSeriesRenderer dr = chart.getRenderer();
//Log.d(CalculatorPlotActivity.class.getName(), "x = [" + dr.getXAxisMin() + ", " + dr.getXAxisMax() + "], y = [" + dr.getYAxisMin() + ", " + dr.getYAxisMax() + "]");
final MyXYSeries realSeries = (MyXYSeries) chart.getDataset().getSeriesAt(0);
final MyXYSeries imagSeries;
if (chart.getDataset().getSeriesCount() > 1) {
imagSeries = (MyXYSeries) chart.getDataset().getSeriesAt(1);
} else {
imagSeries = new MyXYSeries(getImagFunctionName(CalculatorPlotFragment.this.variable), DEFAULT_NUMBER_OF_STEPS * 2);
}
try {
if (PlotUtils.addXY(dr.getXAxisMin(), dr.getXAxisMax(), expression, variable, realSeries, imagSeries, true, DEFAULT_NUMBER_OF_STEPS)) {
if (chart.getDataset().getSeriesCount() <= 1) {
chart.getDataset().addSeries(imagSeries);
chart.getRenderer().addSeriesRenderer(createImagRenderer());
}
}
} catch (ArithmeticException e) {
// todo serso: translate
Toast.makeText(CalculatorPlotFragment.this.getActivity(), "Arithmetic error: " + e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
}
if (pendingOperation.getObject() == this) {
uiHandler.post(new Runnable() {
@Override
public void run() {
graphicalView.repaint();
}
});
}
}
});
}
}
}
});
uiHandler.postDelayed(pendingOperation.getObject(), millisToWait);
}
@NotNull
private static String getImagFunctionName(@NotNull Constant variable) {
return "g(" + variable.getName() + ")" + " = " + "Im(ƒ(" + variable.getName() + "))";
}
@NotNull
private static String getRealFunctionName(@NotNull Generic expression, @NotNull Constant variable) {
return "ƒ(" + variable.getName() + ")" + " = " + expression.toString();
}
@NotNull
private final MutableObject<Runnable> pendingOperation = new MutableObject<Runnable>();
private static XYChart prepareChart(final double minValue, final double maxValue, @NotNull final Generic expression, @NotNull final Constant variable, int bgColor) {
final MyXYSeries realSeries = new MyXYSeries(getRealFunctionName(expression, variable), DEFAULT_NUMBER_OF_STEPS * 2);
final MyXYSeries imagSeries = new MyXYSeries(getImagFunctionName(variable), DEFAULT_NUMBER_OF_STEPS * 2);
boolean imagExists = PlotUtils.addXY(minValue, maxValue, expression, variable, realSeries, imagSeries, false, DEFAULT_NUMBER_OF_STEPS);
final XYMultipleSeriesDataset data = new XYMultipleSeriesDataset();
data.addSeries(realSeries);
if (imagExists) {
data.addSeries(imagSeries);
}
final XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
renderer.setShowGrid(true);
renderer.setXTitle(variable.getName());
renderer.setYTitle("f(" + variable.getName() + ")");
renderer.setChartTitleTextSize(20);
renderer.setApplyBackgroundColor(true);
renderer.setBackgroundColor(bgColor);
renderer.setMarginsColor(bgColor);
renderer.setZoomEnabled(true);
renderer.setZoomButtonsVisible(true);
renderer.addSeriesRenderer(createCommonRenderer());
if (imagExists) {
renderer.addSeriesRenderer(createImagRenderer());
}
return new CubicLineChart(data, renderer, 0.1f);
}
private static XYSeriesRenderer createImagRenderer() {
final XYSeriesRenderer imagRenderer = createCommonRenderer();
imagRenderer.setStroke(BasicStroke.DASHED);
imagRenderer.setColor(Color.LTGRAY);
return imagRenderer;
}
@Override
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable final Object data) {
if ( calculatorEventType.isOfType(CalculatorEventType.display_state_changed) ) {
if ( !inputFromArgs ) {
if ( calculatorEventData.isAfter(this.lastCalculatorEventData) ) {
this.lastCalculatorEventData = calculatorEventData;
createInputFromDisplayState(((CalculatorDisplayChangeEventData) data).getNewState());
uiHandler.post(new Runnable() {
@Override
public void run() {
updateGraphicalView(getView());
}
});
}
}
}
}
/*@Override
public Object onRetainNonConfigurationInstance() {
return new PlotBoundaries(chart.getRenderer());
}*/
private static final class PlotBoundaries implements Serializable {
private final double xMin;
private final double xMax;
private final double yMin;
private final double yMax;
public PlotBoundaries(@NotNull XYMultipleSeriesRenderer renderer) {
this.xMin = renderer.getXAxisMin();
this.yMin = renderer.getYAxisMin();
this.xMax = renderer.getXAxisMax();
this.yMax = renderer.getYAxisMax();
}
@Override
public String toString() {
return "PlotBoundaries{" +
"yMax=" + yMax +
", yMin=" + yMin +
", xMax=" + xMax +
", xMin=" + xMin +
'}';
}
}
@NotNull
private static XYSeriesRenderer createCommonRenderer() {
final XYSeriesRenderer renderer = new XYSeriesRenderer();
renderer.setFillPoints(true);
renderer.setPointStyle(PointStyle.POINT);
renderer.setLineWidth(3);
renderer.setColor(Color.WHITE);
renderer.setStroke(BasicStroke.SOLID);
return renderer;
}
public void zoomInClickHandler(@NotNull View v) {
this.graphicalView.zoomIn();
}
public void zoomOutClickHandler(@NotNull View v) {
this.graphicalView.zoomOut();
}
public static class Input implements Serializable {
@NotNull
private String expression;
@NotNull
private String variableName;
public Input(@NotNull String expression, @NotNull String variableName) {
this.expression = expression;
this.variableName = variableName;
}
@NotNull
public String getExpression() {
return expression;
}
@NotNull
public String getVariableName() {
return variableName;
}
}
}