Calculation fixable messages

This commit is contained in:
Sergey Solovyev 2012-11-17 21:58:48 +04:00
parent 44ed81a5ca
commit 1ab714b044
33 changed files with 571 additions and 65 deletions

View File

@ -132,6 +132,10 @@ public enum CalculatorEventType {
*
**********************************************************************
*/
// List<Message>
calculation_messages,
show_history,
show_history_detached,

View File

@ -0,0 +1,43 @@
package org.solovyev.android.calculator;
import jscl.AngleUnit;
import jscl.text.msg.Messages;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.common.collections.CollectionsUtils;
import java.util.List;
/**
* User: serso
* Date: 11/17/12
* Time: 7:30 PM
*/
public enum CalculatorFixableError {
must_be_rad(Messages.msg_23, Messages.msg_24, Messages.msg_25) {
@Override
public void fix() {
CalculatorLocatorImpl.getInstance().getPreferenceService().setAngleUnits(AngleUnit.rad);
}
};
@NotNull
private final List<String> messageCodes;
CalculatorFixableError(@Nullable String... messageCodes) {
this.messageCodes = CollectionsUtils.asList(messageCodes);
}
@Nullable
public static CalculatorFixableError getErrorByMessageCode(@NotNull String messageCode) {
for (CalculatorFixableError fixableError : values()) {
if (fixableError.messageCodes.contains(messageCode)) {
return fixableError;
}
}
return null;
}
public abstract void fix();
}

View File

@ -25,6 +25,7 @@ import org.solovyev.common.text.StringUtils;
import org.solovyev.math.units.ConversionException;
import org.solovyev.math.units.ConversionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@ -189,10 +190,14 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
final CalculatorLogger logger = CalculatorLocatorImpl.getInstance().getLogger();
try {
final List<Message> messages = new ArrayList<Message>();
while (messageRegistry.hasMessage()) {
handleJsclMessage(messageRegistry.getMessage());
messages.add(messageRegistry.getMessage());
}
} catch (Throwable e) {
if (!messages.isEmpty()) {
fireCalculatorEvent(newCalculationEventData(operation, expression, sequenceId), CalculatorEventType.calculation_messages, messages);
}
} catch (Throwable e) {
// todo serso: not good be we need proper synchronization
logger.error("Calculator", e.getMessage(), e);
}
@ -221,11 +226,6 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
}
}
private void handleJsclMessage(@NotNull Message message) {
final CalculatorNotifier notifier = CalculatorLocatorImpl.getInstance().getNotifier();
notifier.showMessage(message);
}
@NotNull
@Override
public PreparedExpression prepareExpression(@NotNull String expression) throws CalculatorParseException {

View File

@ -15,7 +15,8 @@ public interface CalculatorLocator {
@NotNull CalculatorClipboard clipboard,
@NotNull CalculatorNotifier notifier,
@NotNull CalculatorHistory history,
@NotNull CalculatorLogger logger);
@NotNull CalculatorLogger logger,
@NotNull CalculatorPreferenceService preferenceService);
@NotNull
Calculator getCalculator();
@ -43,4 +44,7 @@ public interface CalculatorLocator {
@NotNull
CalculatorLogger getLogger();
@NotNull
CalculatorPreferenceService getPreferenceService();
}

View File

@ -40,6 +40,9 @@ public class CalculatorLocatorImpl implements CalculatorLocator {
@NotNull
private static final CalculatorLocator instance = new CalculatorLocatorImpl();
@NotNull
private CalculatorPreferenceService calculatorPreferenceService;
public CalculatorLocatorImpl() {
}
@ -49,7 +52,8 @@ public class CalculatorLocatorImpl implements CalculatorLocator {
@NotNull CalculatorClipboard clipboard,
@NotNull CalculatorNotifier notifier,
@NotNull CalculatorHistory history,
@NotNull CalculatorLogger logger) {
@NotNull CalculatorLogger logger,
@NotNull CalculatorPreferenceService preferenceService) {
this.calculator = calculator;
this.calculatorEngine = engine;
@ -57,6 +61,7 @@ public class CalculatorLocatorImpl implements CalculatorLocator {
this.calculatorNotifier = notifier;
this.calculatorHistory = history;
this.calculatorLogger = logger;
this.calculatorPreferenceService = preferenceService;
calculatorEditor = new CalculatorEditorImpl(this.calculator);
calculatorDisplay = new CalculatorDisplayImpl(this.calculator);
@ -121,4 +126,10 @@ public class CalculatorLocatorImpl implements CalculatorLocator {
public CalculatorLogger getLogger() {
return calculatorLogger;
}
@NotNull
@Override
public CalculatorPreferenceService getPreferenceService() {
return this.calculatorPreferenceService;
}
}

View File

@ -0,0 +1,14 @@
package org.solovyev.android.calculator;
import jscl.AngleUnit;
import org.jetbrains.annotations.NotNull;
/**
* User: serso
* Date: 11/17/12
* Time: 7:45 PM
*/
public interface CalculatorPreferenceService {
void setAngleUnits(@NotNull AngleUnit angleUnit);
}

View File

@ -11,7 +11,7 @@ import org.solovyev.android.calculator.history.CalculatorHistory;
public class AbstractCalculatorTest {
protected void setUp() throws Exception {
CalculatorLocatorImpl.getInstance().init(new CalculatorImpl(), CalculatorTestUtils.newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger());
CalculatorLocatorImpl.getInstance().init(new CalculatorImpl(), CalculatorTestUtils.newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class));
CalculatorLocatorImpl.getInstance().getEngine().init();
}

View File

@ -23,7 +23,7 @@ public class CalculatorTestUtils {
public static final int TIMEOUT = 1;
public static void staticSetUp() throws Exception {
CalculatorLocatorImpl.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger());
CalculatorLocatorImpl.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class));
CalculatorLocatorImpl.getInstance().getEngine().init();
}

View File

@ -25,6 +25,8 @@
<activity android:label="@string/c_history" android:name=".history.CalculatorHistoryActivity"/>
<activity android:excludeFromRecents="true" android:finishOnTaskLaunch="true" android:launchMode="singleTask" android:label="@string/calculation_messages_dialog_title" android:name=".CalculatorMessagesDialog" android:theme="@style/Theme.Sherlock.Dialog"/>
<activity android:label="@string/c_about" android:name=".about.CalculatorAboutActivity"/>
<activity android:label="@string/c_help" android:name=".help.CalculatorHelpActivity"/>

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:layout_width="match_parent"
a:layout_height="match_parent"
style="?dialogStyle"
a:orientation="vertical">
<LinearLayout
a:id="@+id/calculation_messages_container"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:orientation="vertical"/>
<CheckBox
a:id="@+id/do_not_show_calculation_messages_checkbox"
a:text="@string/do_not_show_messages_in_session"
a:layout_width="match_parent"
a:layout_height="wrap_content"/>
<LinearLayout
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:orientation="horizontal"
a:gravity="center">
<Button a:id="@+id/ok_button"
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:text="@string/ok"/>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:orientation="horizontal">
<TextView a:id="@+id/calculation_messages_text_view"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_weight="5"/>
<Button
a:id="@+id/fix_button"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_weight="1"
a:text="@string/fix" />
</LinearLayout>

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="dialogStyle" format="reference" />
<attr name="digitButtonStyle" format="reference" />
<attr name="controlButtonStyle" format="reference" />
<attr name="controlImageButtonStyle" format="reference" />

View File

@ -247,5 +247,14 @@
<string name="function_param_not_empty">Function parameter should not be empty!</string>
<string name="function_removal_confirmation_question">Do you really want to delete \'%s\' function?</string>
<string name="empty_function_error">Unable to create empty function!</string>
<string name="do_not_show_messages_in_session">Do not show this message until next session</string>
<string name="calculation_messages_dialog_title">Calculation messages</string>
<string name="arithmetic_error_while_plot">Arithmetic error occurred while plotting: %s</string>
<string name="ok">OK</string>
<string name="p_show_calculation_messages_dialog_title">Show calculation messages in dialog</string>
<string name="p_show_calculation_messages_dialog_summary">If turned on if any message occurred while calculations
special dialog will be shown
</string>
<string name="fix">Fix</string>
</resources>

View File

@ -10,6 +10,10 @@
<item name="android:background">@drawable/metro_button_dark</item>
</style>
<style name="default_dialog_style">
<item name="android:padding">6dp</item>
</style>
<style name="default_control_button_style" parent="keyboard_button_style"/>
<style name="default_operation_button_style" parent="default_digit_button_style">
@ -125,6 +129,8 @@
<item name="fragmentLayoutStyle">@style/default_fragment_layout_style</item>
<item name="dialogStyle">@style/default_dialog_style</item>
<item name="paneStyle">@style/default_pane_style</item>
<item name="paneStyleTransparent">@style/default_pane_style_transparent</item>

View File

@ -56,6 +56,11 @@
a:title="@string/p_calculations_calculate_on_fly_title"
a:summary="@string/p_calculations_calculate_on_fly_summary"/>
<android.preference.CheckBoxPreference
a:key="show_calculation_messages_dialog"
a:title="@string/p_show_calculation_messages_dialog_title"
a:summary="@string/p_show_calculation_messages_dialog_summary"/>
</PreferenceScreen>
</PreferenceScreen>

View File

@ -1,12 +1,5 @@
package org.solovyev.android;
import android.os.Looper;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import org.jetbrains.annotations.NotNull;
/**
* User: Solovyev_S
* Date: 03.10.12
@ -18,23 +11,4 @@ public final class AndroidUtils2 {
throw new AssertionError();
}
public static void showDialog(@NotNull DialogFragment dialogFragment,
@NotNull String fragmentTag,
@NotNull FragmentManager fm) {
final FragmentTransaction ft = fm.beginTransaction();
Fragment prev = fm.findFragmentByTag(fragmentTag);
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
// Create and show the dialog.
dialogFragment.show(ft, fragmentTag);
}
public static boolean isUiThread() {
return Looper.myLooper() == Looper.getMainLooper();
}
}

View File

@ -160,7 +160,7 @@ public abstract class AbstractCalculatorHelper implements SharedPreferences.OnSh
toggleButtonDirectionText(root, R.id.plusButton, false, DragDirection.down, DragDirection.up);
}
CalculatorButtons.processButtons(true, theme, layout, root);
CalculatorButtons.processButtons(theme, layout, root);
CalculatorButtons.toggleEqualsButton(preferences, activity);
CalculatorButtons.initMultiplicationButton(root);
NumeralBaseButtons.toggleNumericDigits(activity, preferences);

View File

@ -16,6 +16,7 @@ import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.history.CalculatorHistoryState;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.common.history.HistoryAction;
import org.solovyev.common.msg.Message;
import java.util.List;
@ -195,6 +196,9 @@ public class AndroidCalculator implements Calculator, CalculatorEventListener, S
@Override
public void onCalculatorEvent(@NotNull CalculatorEventData calculatorEventData, @NotNull CalculatorEventType calculatorEventType, @Nullable Object data) {
switch (calculatorEventType) {
case calculation_messages:
CalculatorActivityLauncher.showCalculationMessagesDialog(CalculatorApplication.getInstance(), (List<Message>) data);
break;
case show_history:
CalculatorActivityLauncher.showHistory(CalculatorApplication.getInstance());
break;

View File

@ -5,7 +5,7 @@ import android.os.Handler;
import android.widget.Toast;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.AndroidUtils2;
import org.solovyev.android.AndroidUtils;
import org.solovyev.android.msg.AndroidMessage;
import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageType;
@ -26,7 +26,7 @@ public class AndroidCalculatorNotifier implements CalculatorNotifier {
private final Handler uiHandler = new Handler();
public AndroidCalculatorNotifier(@NotNull Application application) {
assert AndroidUtils2.isUiThread();
assert AndroidUtils.isUiThread();
this.application = application;
}
@ -54,7 +54,7 @@ public class AndroidCalculatorNotifier implements CalculatorNotifier {
}
private void showMessageInUiThread(@NotNull final String message) {
if (AndroidUtils2.isUiThread()) {
if (AndroidUtils.isUiThread()) {
Toast.makeText(application, message, Toast.LENGTH_SHORT).show();
} else {
uiHandler.post(new Runnable() {

View File

@ -0,0 +1,33 @@
package org.solovyev.android.calculator;
import android.app.Application;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import jscl.AngleUnit;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
import org.solovyev.android.msg.AndroidMessage;
import org.solovyev.common.msg.MessageType;
/**
* User: serso
* Date: 11/17/12
* Time: 7:46 PM
*/
public class AndroidCalculatorPreferenceService implements CalculatorPreferenceService {
@NotNull
private final Application application;
public AndroidCalculatorPreferenceService(@NotNull Application application) {
this.application = application;
}
@Override
public void setAngleUnits(@NotNull AngleUnit angleUnit) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(application);
AndroidCalculatorEngine.Preferences.angleUnit.putPreference(preferences, angleUnit);
CalculatorLocatorImpl.getInstance().getNotifier().showMessage(new AndroidMessage(R.string.c_angle_units_changed_to, MessageType.info, application, angleUnit.name()));
}
}

View File

@ -0,0 +1,87 @@
package org.solovyev.android.calculator;
import android.os.Parcel;
import android.os.Parcelable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageType;
/**
* User: serso
* Date: 11/17/12
* Time: 6:54 PM
*/
public class CalculationMessage implements Parcelable {
public static final Creator<CalculationMessage> CREATOR = new Creator<CalculationMessage>() {
@Override
public CalculationMessage createFromParcel(@NotNull Parcel in) {
return CalculationMessage.fromParcel(in);
}
@Override
public CalculationMessage[] newArray(int size) {
return new CalculationMessage[size];
}
};
@NotNull
private static CalculationMessage fromParcel(@NotNull Parcel in) {
final String message = in.readString();
final MessageType messageType = (MessageType) in.readSerializable();
final CalculatorFixableError fixableError = (CalculatorFixableError) in.readSerializable();
return new CalculationMessage(message, messageType, fixableError);
}
@NotNull
private final String message;
@NotNull
private final MessageType messageType;
@Nullable
private final CalculatorFixableError fixableError;
public CalculationMessage(@NotNull Message message) {
this.message = message.getLocalizedMessage();
this.messageType = message.getMessageType();
this.fixableError = CalculatorFixableError.getErrorByMessageCode(message.getMessageCode());
}
public CalculationMessage(@NotNull String message,
@NotNull MessageType messageType,
@Nullable CalculatorFixableError fixableError) {
this.message = message;
this.messageType = messageType;
this.fixableError = fixableError;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NotNull Parcel out, int flags) {
out.writeString(message);
out.writeSerializable(messageType);
out.writeSerializable(fixableError);
}
@NotNull
public String getMessage() {
return message;
}
@NotNull
public MessageType getMessageType() {
return messageType;
}
@Nullable
public CalculatorFixableError getFixableError() {
return fixableError;
}
}

View File

@ -2,7 +2,9 @@ package org.solovyev.android.calculator;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.preference.PreferenceManager;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import jscl.math.Generic;
import jscl.math.function.Constant;
@ -15,9 +17,12 @@ import org.solovyev.android.calculator.history.CalculatorHistoryActivity;
import org.solovyev.android.calculator.math.edit.*;
import org.solovyev.android.calculator.plot.CalculatorPlotActivity;
import org.solovyev.android.calculator.plot.CalculatorPlotFragment;
import org.solovyev.common.msg.Message;
import org.solovyev.common.msg.MessageType;
import org.solovyev.common.text.StringUtils;
import java.util.List;
/**
* User: serso
* Date: 11/2/11
@ -153,4 +158,12 @@ public class CalculatorActivityLauncher {
addFlags(intent, false);
context.startActivity(intent);
}
public static void showCalculationMessagesDialog(@NotNull Context context, @NotNull List<Message> messages) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
if ( CalculatorPreferences.Calculations.showCalculationMessagesDialog.getPreference(prefs) ) {
CalculatorMessagesDialog.showDialog(messages, context);
}
}
}

View File

@ -90,7 +90,8 @@ public class CalculatorApplication extends android.app.Application {
new AndroidCalculatorClipboard(this),
new AndroidCalculatorNotifier(this),
new AndroidCalculatorHistory(this, calculator),
new AndroidCalculatorLogger());
new AndroidCalculatorLogger(),
new AndroidCalculatorPreferenceService(this));
CalculatorLocatorImpl.getInstance().getCalculator().init();

View File

@ -19,6 +19,7 @@ import org.solovyev.android.AndroidUtils;
import org.solovyev.android.calculator.model.AndroidCalculatorEngine;
import org.solovyev.android.calculator.view.AngleUnitsButton;
import org.solovyev.android.calculator.view.NumeralBasesButton;
import org.solovyev.android.view.drag.DirectionDragButton;
import org.solovyev.android.view.drag.DragButton;
import org.solovyev.android.view.drag.DragDirection;
import org.solovyev.android.view.drag.SimpleOnDragListener;
@ -35,13 +36,12 @@ public final class CalculatorButtons {
}
public static void processButtons(boolean fixMagicFlames,
@NotNull CalculatorPreferences.Gui.Theme theme,
public static void processButtons(@NotNull CalculatorPreferences.Gui.Theme theme,
@NotNull CalculatorPreferences.Gui.Layout layout,
@NotNull View root) {
if ( layout == CalculatorPreferences.Gui.Layout.main_calculator_mobile ) {
final float textSize =root.getResources().getDimension(R.dimen.button_text_size_mobile);
final float textSize = root.getResources().getDimension(R.dimen.button_text_size_mobile);
AndroidUtils.processViewsOfType(root, DragButton.class, new AndroidUtils.ViewProcessor<DragButton>() {
@Override
@ -173,9 +173,7 @@ public final class CalculatorButtons {
final AngleUnit oldAngleUnits = AndroidCalculatorEngine.Preferences.angleUnit.getPreference(preferences);
if (oldAngleUnits != angleUnits) {
AndroidCalculatorEngine.Preferences.angleUnit.putPreference(preferences, angleUnits);
Toast.makeText(context, context.getString(R.string.c_angle_units_changed_to, angleUnits.name()), Toast.LENGTH_LONG).show();
CalculatorLocatorImpl.getInstance().getPreferenceService().setAngleUnits(angleUnits);
}
result = true;

View File

@ -110,6 +110,15 @@ public class CalculatorKeyboardFragment extends SherlockFragment implements Shar
NumeralBaseButtons.toggleNumericDigits(this.getActivity(), preferences);
}
if ( AndroidCalculatorEngine.Preferences.angleUnit.getKey().equals(key) ||
AndroidCalculatorEngine.Preferences.numeralBase.getKey().equals(key) ) {
View view = getView();
if ( view != null) {
// we should update state of angle units/numeral base button => we can achieve it by invalidating the whole view
view.invalidate();
}
}
if ( CalculatorPreferences.Gui.showEqualsButton.getKey().equals(key) ) {
CalculatorButtons.toggleEqualsButton(preferences, this.getActivity());
}

View File

@ -0,0 +1,201 @@
package org.solovyev.android.calculator;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.TextView;
import com.actionbarsherlock.app.SherlockActivity;
import org.jetbrains.annotations.NotNull;
import org.solovyev.common.msg.Message;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* User: serso
* Date: 11/17/12
* Time: 3:37 PM
*/
public class CalculatorMessagesDialog extends SherlockActivity {
private static final String INPUT = "input";
@NotNull
private Input input = new Input(Collections.<CalculationMessage>emptyList());
public CalculatorMessagesDialog() {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.calculation_messages_dialog);
final Intent intent = getIntent();
if (intent != null) {
parseIntent(intent);
}
final CheckBox doNotShowCalculationMessagesCheckbox = (CheckBox) findViewById(R.id.do_not_show_calculation_messages_checkbox);
final Button okButton = (Button) findViewById(R.id.ok_button);
okButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (doNotShowCalculationMessagesCheckbox.isChecked()) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(CalculatorMessagesDialog.this);
CalculatorPreferences.Calculations.showCalculationMessagesDialog.putPreference(prefs, false);
}
CalculatorMessagesDialog.this.finish();
}
});
}
private void parseIntent(@NotNull Intent intent) {
final Input input = intent.getParcelableExtra(INPUT);
if (input != null) {
this.input = input;
onInputChanged();
}
}
private void onInputChanged() {
final ViewGroup viewGroup = (ViewGroup) findViewById(R.id.calculation_messages_container);
viewGroup.removeAllViews();
final LayoutInflater layoutInflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final List<CalculationMessage> messages = input.getMessages();
for (final CalculationMessage message : messages) {
final View view = layoutInflater.inflate(R.layout.calculation_messages_dialog_message, null);
final TextView calculationMessagesTextView = (TextView) view.findViewById(R.id.calculation_messages_text_view);
calculationMessagesTextView.setText(message.getMessage());
final Button fixButton = (Button) view.findViewById(R.id.fix_button);
final CalculatorFixableError fixableError = message.getFixableError();
if (fixableError == null) {
fixButton.setVisibility(View.GONE);
fixButton.setOnClickListener(null);
} else {
fixButton.setVisibility(View.VISIBLE);
fixButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final List<CalculationMessage> filteredMessages = new ArrayList<CalculationMessage>(messages.size() - 1);
for (CalculationMessage calculationMessage : messages) {
if ( calculationMessage.getFixableError() == null || calculationMessage.getFixableError() != message.getFixableError() ) {
filteredMessages.add(message);
}
}
fixableError.fix();
if (!filteredMessages.isEmpty()) {
CalculatorMessagesDialog.this.input = new Input(filteredMessages);
onInputChanged();
} else {
CalculatorMessagesDialog.this.finish();
}
}
});
}
viewGroup.addView(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
}
@Override
protected void onNewIntent(@NotNull Intent intent) {
super.onNewIntent(intent);
parseIntent(intent);
}
/*
**********************************************************************
*
* STATIC
*
**********************************************************************
*/
public static void showDialog(@NotNull List<Message> messages, @NotNull Context context) {
if (!messages.isEmpty()) {
final Intent intent = new Intent(context, CalculatorMessagesDialog.class);
intent.putExtra(INPUT, Input.fromMessages(messages));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
}
private static final class Input implements Parcelable {
public static final Creator<Input> CREATOR = new Creator<Input>() {
@Override
public Input createFromParcel(@NotNull Parcel in) {
return Input.fromParcel(in);
}
@Override
public Input[] newArray(int size) {
return new Input[size];
}
};
@NotNull
private static Input fromParcel(@NotNull Parcel in) {
final List<CalculationMessage> messages = new ArrayList<CalculationMessage>();
in.readTypedList(messages, CalculationMessage.CREATOR);
return new Input(messages);
}
@NotNull
private List<CalculationMessage> messages = new ArrayList<CalculationMessage>();
private Input(@NotNull List<CalculationMessage> messages) {
this.messages = messages;
}
@NotNull
public List<CalculationMessage> getMessages() {
return messages;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NotNull Parcel out, int flags) {
out.writeTypedList(messages);
}
@NotNull
public static Input fromMessages(@NotNull List<Message> messages) {
final List<CalculationMessage> stringMessages = new ArrayList<CalculationMessage>(messages.size());
for (Message message : messages) {
stringMessages.add(new CalculationMessage(message));
}
return new Input(stringMessages);
}
}
}

View File

@ -1,6 +1,8 @@
package org.solovyev.android.calculator;
import android.content.SharedPreferences;
import jscl.AngleUnit;
import jscl.NumeralBase;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.AndroidUtils;
import org.solovyev.android.calculator.math.MathType;
@ -32,6 +34,10 @@ public final class CalculatorPreferences {
public static class Calculations {
public static final Preference<Boolean> calculateOnFly = new BooleanPreference("calculations_calculate_on_fly", true);
public static final Preference<Boolean> showCalculationMessagesDialog = new BooleanPreference("show_calculation_messages_dialog", true);
public static final Preference<NumeralBase> preferredNumeralBase = StringPreference.newInstance("preferred_numeral_base", NumeralBase.dec, NumeralBase.class);
public static final Preference<AngleUnit> preferredAngleUnit = StringPreference.newInstance("preferred_angle_units", AngleUnit.deg, AngleUnit.class);
}
@ -126,8 +132,8 @@ public final class CalculatorPreferences {
}
static void setDefaultValues(@NotNull SharedPreferences preferences) {
static void setDefaultValues(@NotNull SharedPreferences preferences) {
if (!AndroidCalculatorEngine.Preferences.groupingSeparator.isSet(preferences)) {
final Locale locale = Locale.getDefault();
if (locale != null) {
@ -153,7 +159,7 @@ public final class CalculatorPreferences {
}
if (!AndroidCalculatorEngine.Preferences.multiplicationSign.isSet(preferences)) {
if ( AndroidUtils.isPhoneModel(AndroidUtils.PhoneModel.samsung_galaxy_s) || AndroidUtils.isPhoneModel(AndroidUtils.PhoneModel.samsung_galaxy_s_2) ) {
if (AndroidUtils.isPhoneModel(AndroidUtils.PhoneModel.samsung_galaxy_s) || AndroidUtils.isPhoneModel(AndroidUtils.PhoneModel.samsung_galaxy_s_2)) {
// workaround ofr samsung galaxy s phones
AndroidCalculatorEngine.Preferences.multiplicationSign.putPreference(preferences, "*");
}
@ -161,7 +167,7 @@ public final class CalculatorPreferences {
applyDefaultPreference(preferences, Gui.theme);
applyDefaultPreference(preferences, Gui.layout);
if ( Gui.layout.getPreference(preferences) == Gui.Layout.main_cellphone ) {
if (Gui.layout.getPreference(preferences) == Gui.Layout.main_cellphone) {
Gui.layout.putDefault(preferences);
}
applyDefaultPreference(preferences, Gui.feedbackWindowShown);
@ -177,12 +183,18 @@ public final class CalculatorPreferences {
applyDefaultPreference(preferences, Graph.lineColorReal);
applyDefaultPreference(preferences, History.showIntermediateCalculations);
applyDefaultPreference(preferences, Calculations.calculateOnFly);
applyDefaultPreference(preferences, Calculations.preferredAngleUnit);
applyDefaultPreference(preferences, Calculations.preferredNumeralBase);
if ( !VibratorContainer.Preferences.hapticFeedbackEnabled.isSet(preferences) ) {
// renew value after each application start
Calculations.showCalculationMessagesDialog.putDefault(preferences);
if (!VibratorContainer.Preferences.hapticFeedbackEnabled.isSet(preferences)) {
VibratorContainer.Preferences.hapticFeedbackEnabled.putPreference(preferences, true);
}
if ( !VibratorContainer.Preferences.hapticFeedbackDuration.isSet(preferences) ) {
if (!VibratorContainer.Preferences.hapticFeedbackDuration.isSet(preferences)) {
VibratorContainer.Preferences.hapticFeedbackDuration.putPreference(preferences, 60L);
}

View File

@ -19,12 +19,12 @@ import jscl.math.function.Function;
import jscl.math.function.IFunction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.AndroidUtils2;
import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.math.edit.CalculatorFunctionsActivity;
import org.solovyev.android.calculator.math.edit.CalculatorFunctionsFragment;
import org.solovyev.android.calculator.math.edit.MathEntityRemover;
import org.solovyev.android.calculator.model.AFunction;
import org.solovyev.android.sherlock.AndroidSherlockUtils;
import java.util.ArrayList;
import java.util.List;
@ -173,7 +173,7 @@ public class FunctionEditDialogFragment extends DialogFragment implements Calcul
}
public static void showDialog(@NotNull Input input, @NotNull FragmentManager fm) {
AndroidUtils2.showDialog(new FunctionEditDialogFragment(input), "function-editor", fm);
AndroidSherlockUtils.showDialog(new FunctionEditDialogFragment(input), "function-editor", fm);
}
public static class Input implements Parcelable {

View File

@ -14,9 +14,9 @@ import android.widget.Toast;
import jscl.math.function.IConstant;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.AndroidUtils2;
import org.solovyev.android.calculator.*;
import org.solovyev.android.calculator.model.Var;
import org.solovyev.android.sherlock.AndroidSherlockUtils;
/**
* User: Solovyev_S
@ -148,7 +148,7 @@ public class VarEditDialogFragment extends DialogFragment implements CalculatorE
*/
public static void showDialog(@NotNull Input input, @NotNull FragmentManager fm) {
AndroidUtils2.showDialog(new VarEditDialogFragment(input), "constant-editor", fm);
AndroidSherlockUtils.showDialog(new VarEditDialogFragment(input), "constant-editor", fm);
}
public static class Input {

View File

@ -16,7 +16,6 @@ import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
@ -170,9 +169,13 @@ public class CalculatorPlotFragment extends CalculatorFragment implements Calcul
final GraphLineColor imagLineColor = CalculatorPreferences.Graph.lineColorImag.getPreference(preferences);
//noinspection ConstantConditions
this.chart = PlotUtils.prepareChart(getMinValue(null), getMaxValue(null), preparedInput.getExpression(), preparedInput.getVariable(), bgColor, interpolate, realLineColor.getColor(), imagLineColor.getColor());
try {
this.chart = PlotUtils.prepareChart(getMinValue(null), getMaxValue(null), preparedInput.getExpression(), preparedInput.getVariable(), bgColor, interpolate, realLineColor.getColor(), imagLineColor.getColor());
} catch (ArithmeticException e) {
PlotUtils.handleArithmeticException(e, CalculatorPlotFragment.this);
}
} else {
this.chart = null;
onError();
}
}
@ -326,8 +329,7 @@ public class CalculatorPlotFragment extends CalculatorFragment implements Calcul
}
}
} catch (ArithmeticException e) {
// todo serso: translate
Toast.makeText(CalculatorPlotFragment.this.getActivity(), "Arithmetic error: " + e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
PlotUtils.handleArithmeticException(e, CalculatorPlotFragment.this);
}
uiHandler.post(new Runnable() {
@ -418,6 +420,10 @@ public class CalculatorPlotFragment extends CalculatorFragment implements Calcul
return super.onOptionsItemSelected(item) || fragmentMenu.onOptionsItemSelected(this.getActivity(), item);
}
public void onError() {
this.chart = null;
}
/*
**********************************************************************
*

View File

@ -25,6 +25,12 @@ import org.achartengine.renderer.XYSeriesRenderer;
import org.achartengine.util.MathHelper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.CalculatorLocatorImpl;
import org.solovyev.android.calculator.R;
import org.solovyev.common.msg.MessageType;
import org.solovyev.common.text.StringUtils;
import java.util.Arrays;
/**
* User: serso
@ -139,7 +145,7 @@ public final class PlotUtils {
int bgColor,
boolean interpolate,
int realLineColor,
int imagLineColor) {
int imagLineColor) throws ArithmeticException{
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);
@ -196,6 +202,15 @@ public final class PlotUtils {
return renderer;
}
static void handleArithmeticException(@NotNull ArithmeticException e, @NotNull CalculatorPlotFragment calculatorPlotFragment) {
String message = e.getLocalizedMessage();
if (StringUtils.isEmpty(message)) {
message = e.getMessage();
}
CalculatorLocatorImpl.getInstance().getNotifier().showMessage(R.string.arithmetic_error_while_plot, MessageType.error, Arrays.asList(message));
calculatorPlotFragment.onError();
}
private static class Point {
private static final double DEFAULT = Double.MIN_VALUE;

View File

@ -15,7 +15,7 @@ import org.solovyev.android.calculator.history.CalculatorHistory;
public class CalculatorTestUtils {
public static void staticSetUp(@Nullable Context context) throws Exception {
CalculatorLocatorImpl.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger());
CalculatorLocatorImpl.getInstance().init(new CalculatorImpl(), newCalculatorEngine(), Mockito.mock(CalculatorClipboard.class), Mockito.mock(CalculatorNotifier.class), Mockito.mock(CalculatorHistory.class), new SystemOutCalculatorLogger(), Mockito.mock(CalculatorPreferenceService.class));
CalculatorLocatorImpl.getInstance().getEngine().init();
if ( context != null ) {

View File

@ -31,7 +31,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<android.common.version>1.0.5-SNAPSHOT</android.common.version>
<common.version>1.0.1</common.version>
<common.version>1.0.3</common.version>
</properties>
<dependencyManagement>