menu builders, translations, small fix for history

This commit is contained in:
Sergey Solovyev 2011-12-19 11:52:09 +04:00
parent 03cc14a097
commit 866553725b
15 changed files with 143 additions and 86 deletions

View File

@ -3,8 +3,8 @@
<manifest xmlns:a="http://schemas.android.com/apk/res/android"
package="org.solovyev.android.calculator"
a:installLocation="auto"
a:versionCode="17"
a:versionName="1.2.17">
a:versionCode="18"
a:versionName="1.2.18">
<uses-permission a:name="android.permission.VIBRATE"/>

View File

@ -308,4 +308,9 @@ e ^ i = 0.5403 + 0.84147i\n
<string name="c_edit">Изменить</string>
<string name="c_saved_history">Сохранённая история</string>
<string name="c_history_already_saved">История уже была сохранена!</string>
<string name="c_history_must_be_saved">История должна быть сохранена перед редактированием!</string>
<string name="c_history_was_removed">История успешно удалена!</string>
<string name="c_history_saved">История успешно сохранена!</string>
</resources>

View File

@ -315,5 +315,9 @@ Check the \'Round result\' preference in application settings - it should be tur
<string name="c_edit_history">Modify history</string>
<string name="c_edit">Modify</string>
<string name="c_saved_history">Saved history</string>
<string name="c_history_already_saved">History was already saved!</string>
<string name="c_history_must_be_saved">History must be saved before editing!</string>
<string name="c_history_was_removed">History was successfully removed!</string>
<string name="c_history_saved">History was successfully saved!</string>
</resources>

View File

@ -556,7 +556,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
}
calculatorModel = CalculatorModel.instance.init(this, preferences, CalculatorEngine.instance);
calculatorModel.evaluate();
calculatorModel.evaluate(calculatorModel.getDisplay().getJsclOperation());
}
@Override

View File

@ -32,7 +32,6 @@ import org.solovyev.android.calculator.model.CalculatorEvalException;
import org.solovyev.android.calculator.model.CalculatorParseException;
import org.solovyev.android.calculator.model.Var;
import org.solovyev.android.view.*;
import org.solovyev.android.view.prefs.ResourceCache;
import org.solovyev.common.msg.Message;
import org.solovyev.common.utils.CollectionsUtils;
import org.solovyev.common.utils.MutableObject;
@ -215,6 +214,10 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
evaluate(false, this.editor.getText().toString(), JsclOperation.numeric, null);
}
public void evaluate(@NotNull JsclOperation operation) {
evaluate(false, this.editor.getText().toString(), operation, null);
}
@Override
public void simplify() {
evaluate(false, this.editor.getText().toString(), JsclOperation.simplify, null);
@ -396,20 +399,8 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
if (notSystemConstants.size() > 1) {
copyResult(activity, cd);
} else {
final AMenu<CalculatorDisplayMenuItem> menu = new EnumMenu<CalculatorDisplayMenuItem>(CalculatorDisplayMenuItem.class);
final AlertDialog.Builder menuBuilder = new AlertDialog.Builder(activity);
menuBuilder.setItems(menu.getMenuCaptions(), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
final AMenuItem<CalculatorDisplayMenuData> menuItem = menu.itemAt(item);
if ( menuItem != null ){
menuItem.doAction(new CalculatorDisplayMenuData(cd, genericResult, notSystemConstants), activity);
}
}
});
menuBuilder.create().show();
final AMenuBuilder<CalculatorDisplayMenuItem, CalculatorDisplayMenuData> menuBuilder = AMenuBuilder.newInstance(activity, CalculatorDisplayMenuItem.class);
menuBuilder.create(new CalculatorDisplayMenuData(cd, genericResult, notSystemConstants)).show();
}
} else {
copyResult(activity, cd);
@ -467,7 +458,7 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
}
private static enum CalculatorDisplayMenuItem implements AMenuItem<CalculatorDisplayMenuData> {
plot("c_plot"){
plot(R.string.c_plot){
@Override
public void doAction(@NotNull CalculatorDisplayMenuData data, @NotNull Context context) {
final Constant constant = CollectionsUtils.getFirstCollectionElement(data.getNotSystemConstants());
@ -475,25 +466,23 @@ public enum CalculatorModel implements CursorControl, HistoryControl<CalculatorH
CalculatorActivityLauncher.plotGraph(context, data.getResult(), constant);
}
},
copy("c_copy"){
copy(R.string.c_copy){
@Override
public void doAction(@NotNull CalculatorDisplayMenuData data, @NotNull Context context) {
copyResult(context, data.getDisplay());
}
};
private final String captionId;
CalculatorDisplayMenuItem(@NotNull String captionId) {
private final int captionId;
CalculatorDisplayMenuItem(@NotNull int captionId) {
this.captionId = captionId;
}
@NotNull
@Override
public String getCaption() {
final String caption = ResourceCache.instance.getCaption(captionId);
return caption == null ? name() : caption;
public String getCaption(@NotNull Context context) {
return context.getString(captionId);
}
}
}

View File

@ -19,6 +19,7 @@ import org.solovyev.android.calculator.CalculatorModel;
import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.view.AMenu;
import org.solovyev.android.view.AMenuBuilder;
import org.solovyev.android.view.AMenuItem;
import org.solovyev.android.view.MenuImpl;
import org.solovyev.common.utils.*;
@ -58,11 +59,6 @@ public abstract class AbstractHistoryActivity extends ListActivity {
setContentView(R.layout.history_activity);
/* if ( historyList.isEmpty() ) {
Toast.makeText(this, R.string.c_history_is_empty, Toast.LENGTH_SHORT).show();
this.finish();
}*/
adapter = new HistoryArrayAdapter(this, getLayoutId(), R.id.history_item, new ArrayList<CalculatorHistoryState>());
setListAdapter(adapter);
@ -104,18 +100,8 @@ public abstract class AbstractHistoryActivity extends ListActivity {
menuItems.remove(HistoryItemMenuItem.copy_result);
}
final AMenu<HistoryItemMenuItem> historyItemMenu = new MenuImpl<HistoryItemMenuItem>(menuItems);
final AlertDialog.Builder menuDialogBuilder = new AlertDialog.Builder(context);
menuDialogBuilder.setItems(historyItemMenu.getMenuCaptions(), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
final AMenuItem<HistoryItemMenuData> historyItemMenuItem = historyItemMenu.itemAt(item);
if (historyItemMenuItem != null) {
historyItemMenuItem.doAction(data, context);
}
}
});
menuDialogBuilder.create().show();
final AMenuBuilder<HistoryItemMenuItem, HistoryItemMenuData> menuBuilder = AMenuBuilder.newInstance(context, MenuImpl.newInstance(menuItems));
menuBuilder.create(data).show();
return true;
}

View File

@ -7,6 +7,7 @@
package org.solovyev.android.calculator.history;
import android.content.Context;
import android.content.res.Resources;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
@ -56,12 +57,12 @@ public class HistoryArrayAdapter extends ArrayAdapter<CalculatorHistoryState> {
final TextView status = (TextView) result.findViewById(R.id.history_item_status);
if (status != null) {
if (state.isSaved()) {
status.setText(ResourceCache.instance.getCaption("c_history_item_saved"));
status.setText(getContext().getString(R.string.c_history_item_saved));
} else {
if ( AbstractHistoryActivity.isAlreadySaved(state) ) {
status.setText(ResourceCache.instance.getCaption("c_history_item_already_saved"));
status.setText(getContext().getString(R.string.c_history_item_already_saved));
} else {
status.setText(ResourceCache.instance.getCaption("c_history_item_not_saved"));
status.setText(getContext().getString(R.string.c_history_item_not_saved));
}
}
}

View File

@ -30,18 +30,18 @@ import org.solovyev.common.utils.StringUtils;
*/
public enum HistoryItemMenuItem implements AMenuItem<HistoryItemMenuData> {
use("c_use_expression") {
use(R.string.c_use_expression) {
@Override
public void doAction(@NotNull HistoryItemMenuData data, @NotNull Context context) {
if (context instanceof AbstractHistoryActivity) {
AbstractHistoryActivity.useHistoryItem(data.getHistoryState(), (AbstractHistoryActivity) context);
} else {
Log.e(HistoryItemMenuItem.class.getName(), CalculatorHistoryActivity.class + " must be passed as context!");
Log.e(HistoryItemMenuItem.class.getName(), AbstractHistoryActivity.class + " must be passed as context!");
}
}
},
copy_expression("c_copy_expression") {
copy_expression(R.string.c_copy_expression) {
@Override
public void doAction(@NotNull HistoryItemMenuData data, @NotNull Context context) {
final CalculatorHistoryState calculatorHistoryState = data.getHistoryState();
@ -54,7 +54,7 @@ public enum HistoryItemMenuItem implements AMenuItem<HistoryItemMenuData> {
}
},
copy_result("c_copy_result") {
copy_result(R.string.c_copy_result) {
@Override
public void doAction(@NotNull HistoryItemMenuData data, @NotNull Context context) {
final CalculatorHistoryState calculatorHistoryState = data.getHistoryState();
@ -67,38 +67,38 @@ public enum HistoryItemMenuItem implements AMenuItem<HistoryItemMenuData> {
}
},
save("c_save") {
save(R.string.c_save) {
@Override
public void doAction(@NotNull final HistoryItemMenuData data, @NotNull final Context context) {
final CalculatorHistoryState historyState = data.getHistoryState();
if (!historyState.isSaved()) {
createEditHistoryDialog(data, context, true);
} else {
Toast.makeText(context, "History item was already saved!", Toast.LENGTH_LONG).show();
Toast.makeText(context, context.getText(R.string.c_history_already_saved), Toast.LENGTH_LONG).show();
}
}
},
edit("c_edit") {
edit(R.string.c_edit) {
@Override
public void doAction(@NotNull final HistoryItemMenuData data, @NotNull final Context context) {
final CalculatorHistoryState historyState = data.getHistoryState();
if (historyState.isSaved()) {
createEditHistoryDialog(data, context, false);
} else {
Toast.makeText(context, "History item must be saved before editing!", Toast.LENGTH_LONG).show();
Toast.makeText(context, context.getText(R.string.c_history_must_be_saved), Toast.LENGTH_LONG).show();
}
}
},
remove("c_remove") {
remove(R.string.c_remove) {
@Override
public void doAction(@NotNull HistoryItemMenuData data, @NotNull Context context) {
final CalculatorHistoryState historyState = data.getHistoryState();
if (historyState.isSaved()) {
data.getAdapter().remove(historyState);
CalculatorHistory.instance.removeSavedHistory(historyState, context);
Toast.makeText(context, "History item was removed!", Toast.LENGTH_LONG).show();
Toast.makeText(context, context.getText(R.string.c_history_was_removed), Toast.LENGTH_LONG).show();
data.getAdapter().notifyDataSetChanged();
}
}
@ -133,7 +133,7 @@ public enum HistoryItemMenuItem implements AMenuItem<HistoryItemMenuData> {
CalculatorHistory.instance.save(context);
}
data.getAdapter().notifyDataSetChanged();
Toast.makeText(context, "History item was successfully saved!", Toast.LENGTH_LONG).show();
Toast.makeText(context, context.getText(R.string.c_history_saved), Toast.LENGTH_LONG).show();
}
})
.setView(editView);
@ -141,22 +141,15 @@ public enum HistoryItemMenuItem implements AMenuItem<HistoryItemMenuData> {
builder.create().show();
}
@NotNull
private final String captionId;
private final int captionId;
private HistoryItemMenuItem(@NotNull String captionId) {
private HistoryItemMenuItem(int captionId) {
this.captionId = captionId;
}
@NotNull
@Override
public String getCaption() {
final String caption = ResourceCache.instance.getCaption(getCaptionId());
return caption == null ? this.name() : caption;
}
@NotNull
public String getCaptionId() {
return captionId;
public String getCaption(@NotNull Context context) {
return context.getString(captionId);
}
}

View File

@ -135,7 +135,7 @@ public enum CalculatorEngine {
return evaluate(operation, expression, null);
}
public Result evaluate(@NotNull JsclOperation operation,
public Result evaluate(@NotNull final JsclOperation operation,
@NotNull String expression,
@Nullable MessageRegistry mr) throws CalculatorParseException, CalculatorEvalException {
synchronized (lock) {
@ -161,7 +161,6 @@ public enum CalculatorEngine {
}*/
final String jsclExpression = sb.toString();
final JsclOperation finalOperation = operation;
final MutableObject<Generic> calculationResult = new MutableObject<Generic>(null);
final MutableObject<CalculatorParseException> parseException = new MutableObject<CalculatorParseException>(null);
@ -178,7 +177,7 @@ public enum CalculatorEngine {
//Log.d(CalculatorEngine.class.getName(), "Calculation thread started work: " + thread.getName());
//System.out.println(jsclExpression);
calculationThread.setObject(thread);
final Generic genericResult = finalOperation.evaluateGeneric(jsclExpression);
final Generic genericResult = operation.evaluateGeneric(jsclExpression);
// NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!)
genericResult.toString();
@ -223,7 +222,7 @@ public enum CalculatorEngine {
}
if (parseExceptionObject != null || evalExceptionObject != null) {
if (finalOperation == JsclOperation.numeric &&
if (operation == JsclOperation.numeric &&
( preparedExpression.isExistsUndefinedVar() || ( evalExceptionObject != null && evalExceptionObject.getCause() instanceof NumeralBaseException)) ) {
return evaluate(JsclOperation.simplify, expression, mr);
}

View File

@ -6,6 +6,7 @@
package org.solovyev.android.view;
import android.content.Context;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -14,10 +15,10 @@ import org.jetbrains.annotations.Nullable;
* Date: 12/18/11
* Time: 1:30 PM
*/
public interface AMenu<T extends AMenuItem> {
public interface AMenu<T extends AMenuItem<D>, D> {
@Nullable
T itemAt(int i);
@NotNull
CharSequence[] getMenuCaptions();
CharSequence[] getMenuCaptions(@NotNull final Context context);
}

View File

@ -0,0 +1,60 @@
package org.solovyev.android.view;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import org.jetbrains.annotations.NotNull;
/**
* User: serso
* Date: 12/19/11
* Time: 10:54 AM
*/
public class AMenuBuilder<T extends AMenuItem<D>, D>{
@NotNull
private final Context context;
@NotNull
private final AlertDialog.Builder menuBuilder;
@NotNull
private final AMenu<T, D> menu;
@NotNull
public static <T extends Enum & AMenuItem<D>, D> AMenuBuilder<T, D> newInstance(@NotNull Context context, @NotNull Class<T> enumClass) {
return new AMenuBuilder<T, D>(context, EnumMenu.<T, D>newInstance(enumClass));
}
@NotNull
public static <T extends AMenuItem<D>, D> AMenuBuilder<T, D> newInstance(@NotNull Context context, @NotNull AMenu<T, D> menu) {
return new AMenuBuilder<T, D>(context, menu);
}
private AMenuBuilder(@NotNull Context context, @NotNull AMenu<T, D> menu) {
this.context = context;
this.menuBuilder = new AlertDialog.Builder(context);
this.menu = menu;
}
@NotNull
public AlertDialog.Builder getMenuBuilder() {
return menuBuilder;
}
@NotNull
public AlertDialog create(@NotNull final D data) {
menuBuilder.setItems(menu.getMenuCaptions(context), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
final AMenuItem<D> menuItem = menu.itemAt(item);
if (menuItem != null) {
menuItem.doAction(data, context);
}
}
});
return menuBuilder.create();
}
}

View File

@ -17,7 +17,7 @@ import org.jetbrains.annotations.NotNull;
public interface AMenuItem<T> {
@NotNull
String getCaption();
String getCaption(@NotNull Context context);
void doAction(@NotNull T data, @NotNull Context context);
}

View File

@ -6,6 +6,7 @@
package org.solovyev.android.view;
import android.content.Context;
import org.jetbrains.annotations.NotNull;
/**
@ -13,13 +14,18 @@ import org.jetbrains.annotations.NotNull;
* Date: 12/18/11
* Time: 1:34 PM
*/
public class EnumMenu<T extends Enum & AMenuItem> implements AMenu<T> {
public class EnumMenu<T extends Enum & AMenuItem<D>, D> implements AMenu<T, D> {
@NotNull
private final AMenu<T> menu;
private final AMenu<T, D> menu;
public EnumMenu(Class<T> enumClass) {
this.menu = new MenuImpl<T>(enumClass.getEnumConstants());
@NotNull
public static <T extends Enum & AMenuItem<D>, D> AMenu<T, D> newInstance(@NotNull Class<T> enumClass) {
return new EnumMenu<T, D>(enumClass);
}
private EnumMenu(Class<T> enumClass) {
this.menu = MenuImpl.newInstance(enumClass.getEnumConstants());
}
@Override
@ -29,7 +35,7 @@ public class EnumMenu<T extends Enum & AMenuItem> implements AMenu<T> {
@NotNull
@Override
public CharSequence[] getMenuCaptions() {
return this.menu.getMenuCaptions();
public CharSequence[] getMenuCaptions(@NotNull final Context context) {
return this.menu.getMenuCaptions(context);
}
}

View File

@ -6,6 +6,7 @@
package org.solovyev.android.view;
import android.content.Context;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.common.utils.CollectionsUtils;
@ -18,15 +19,25 @@ import java.util.List;
* Date: 12/18/11
* Time: 1:31 PM
*/
public class MenuImpl<T extends AMenuItem> implements AMenu<T> {
public class MenuImpl<T extends AMenuItem<D>, D> implements AMenu<T, D> {
private final List<T> menuItems = new ArrayList<T>();
public MenuImpl(T... menuItems) {
@NotNull
public static <T extends AMenuItem<D>, D> AMenu<T, D> newInstance(T... menuItems) {
return new MenuImpl<T, D>(menuItems);
}
@NotNull
public static <T extends AMenuItem<D>, D> AMenu<T, D> newInstance(@NotNull List<T> menuItems) {
return new MenuImpl<T, D>(menuItems);
}
private MenuImpl(T... menuItems) {
this(CollectionsUtils.asList(menuItems));
}
public MenuImpl(@NotNull List<T> menuItems) {
private MenuImpl(@NotNull List<T> menuItems) {
this.menuItems.addAll(menuItems);
}
@ -42,10 +53,10 @@ public class MenuImpl<T extends AMenuItem> implements AMenu<T> {
@Override
@NotNull
public CharSequence[] getMenuCaptions() {
public CharSequence[] getMenuCaptions(@NotNull final Context context) {
final CharSequence[] result = new CharSequence[this.menuItems.size()];
for (int i = 0; i < this.menuItems.size(); i++) {
result[i] = this.menuItems.get(i).getCaption();
result[i] = this.menuItems.get(i).getCaption(context);
}
return result;
}

View File

@ -204,9 +204,11 @@ public class HistoryUtilsTest {
for (CalculatorHistoryState historyState : history.getStates()) {
historyState.setId(0);
historyState.setSaved(true);
}
for (CalculatorHistoryState historyState : historyFromXml.getStates()) {
historyState.setId(0);
historyState.setSaved(true);
}
Assert.assertTrue(EqualsTool.areEqual(history.getStates(), historyFromXml.getStates(), new CollectionEqualizer<CalculatorHistoryState>(null)));
}