changes
This commit is contained in:
@@ -1,14 +1,10 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import jscl.NumeralBase;
|
||||
import jscl.math.Generic;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -40,19 +36,6 @@ public class AndroidCalculator implements Calculator, CalculatorEventListener, S
|
||||
PreferenceManager.getDefaultSharedPreferences(application).registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
public static void showEvaluationError(@NotNull Context context, @NotNull final String errorMessage) {
|
||||
final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
|
||||
|
||||
final View errorMessageView = layoutInflater.inflate(R.layout.display_error_message, null);
|
||||
((TextView) errorMessageView.findViewById(R.id.error_message_text_view)).setText(errorMessage);
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context)
|
||||
.setPositiveButton(R.string.c_cancel, null)
|
||||
.setView(errorMessageView);
|
||||
|
||||
builder.create().show();
|
||||
}
|
||||
|
||||
public void init(@NotNull final Activity activity) {
|
||||
setEditor(activity);
|
||||
setDisplay(activity);
|
||||
|
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||
* For more information, please, contact se.solovyev@gmail.com
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.Html;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.text.TextProcessor;
|
||||
import org.solovyev.android.calculator.view.TextHighlighter;
|
||||
import org.solovyev.android.view.AutoResizeTextView;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/17/11
|
||||
* Time: 10:58 PM
|
||||
*/
|
||||
public class AndroidCalculatorDisplayView extends AutoResizeTextView implements CalculatorDisplayView {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC FIELDS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@NotNull
|
||||
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false);
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* FIELDS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@NotNull
|
||||
private volatile CalculatorDisplayViewState state = CalculatorDisplayViewStateImpl.newDefaultInstance();
|
||||
|
||||
private volatile boolean viewStateChange = false;
|
||||
|
||||
@NotNull
|
||||
private final Object lock = new Object();
|
||||
|
||||
@NotNull
|
||||
private final Handler uiHandler = new Handler();
|
||||
|
||||
@NotNull
|
||||
private final ExecutorService bgExecutor = Executors.newSingleThreadExecutor();
|
||||
|
||||
private volatile boolean initialized = false;
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTRUCTORS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public AndroidCalculatorDisplayView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public AndroidCalculatorDisplayView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
}
|
||||
|
||||
public AndroidCalculatorDisplayView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* METHODS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
|
||||
@Override
|
||||
public void setState(@NotNull final CalculatorDisplayViewState state) {
|
||||
|
||||
uiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
synchronized (lock) {
|
||||
try {
|
||||
viewStateChange = true;
|
||||
|
||||
final CharSequence text = prepareText(state.getStringResult(), state.isValid());
|
||||
|
||||
AndroidCalculatorDisplayView.this.state = state;
|
||||
if (state.isValid()) {
|
||||
setTextColor(getResources().getColor(R.color.cpp_default_text_color));
|
||||
setText(text);
|
||||
|
||||
adjustTextSize();
|
||||
|
||||
} else {
|
||||
// update text in order to get rid of HTML tags
|
||||
setText(getText().toString());
|
||||
setTextColor(getResources().getColor(R.color.cpp_display_error_text_color));
|
||||
|
||||
// error messages are never shown -> just greyed out text (error message will be shown on click)
|
||||
//setText(state.getErrorMessage());
|
||||
//redraw();
|
||||
}
|
||||
} finally {
|
||||
viewStateChange = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CalculatorDisplayViewState getState() {
|
||||
synchronized (lock) {
|
||||
return this.state;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static CharSequence prepareText(@Nullable String text, boolean valid) {
|
||||
CharSequence result;
|
||||
|
||||
if (valid && text != null) {
|
||||
|
||||
//Log.d(this.getClass().getName(), text);
|
||||
|
||||
try {
|
||||
final TextHighlighter.Result processedText = textHighlighter.process(text);
|
||||
text = processedText.toString();
|
||||
result = Html.fromHtml(text);
|
||||
} catch (CalculatorParseException e) {
|
||||
result = text;
|
||||
}
|
||||
} else {
|
||||
result = text;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void adjustTextSize() {
|
||||
// todo serso: think where to move it (keep in mind org.solovyev.android.view.AutoResizeTextView.resetTextSize())
|
||||
setAddEllipsis(false);
|
||||
setMinTextSize(10);
|
||||
resizeText();
|
||||
}
|
||||
|
||||
public synchronized void init(@NotNull Context context) {
|
||||
this.init(context, true);
|
||||
}
|
||||
|
||||
public synchronized void init(@NotNull Context context, boolean fromApp) {
|
||||
if (!initialized) {
|
||||
if (fromApp) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
final CalculatorPreferences.Gui.Layout layout = CalculatorPreferences.Gui.getLayout(preferences);
|
||||
|
||||
if ( layout == CalculatorPreferences.Gui.Layout.main_calculator_mobile ) {
|
||||
setTextSize(TypedValue.COMPLEX_UNIT_SP, getResources().getDimension(R.dimen.cpp_display_text_size_mobile));
|
||||
}
|
||||
|
||||
this.setOnClickListener(new CalculatorDisplayOnClickListener(context));
|
||||
}
|
||||
|
||||
this.initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,221 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||
* For more information, please, contact se.solovyev@gmail.com
|
||||
*/
|
||||
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.Editable;
|
||||
import android.text.Html;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.ContextMenu;
|
||||
import android.widget.EditText;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.text.TextProcessor;
|
||||
import org.solovyev.android.calculator.view.TextHighlighter;
|
||||
import org.solovyev.android.prefs.BooleanPreference;
|
||||
import org.solovyev.common.collections.CollectionsUtils;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/17/11
|
||||
* Time: 12:25 AM
|
||||
*/
|
||||
public class AndroidCalculatorEditorView extends EditText implements SharedPreferences.OnSharedPreferenceChangeListener, CalculatorEditorView {
|
||||
|
||||
@NotNull
|
||||
private static final BooleanPreference colorDisplay = new BooleanPreference("org.solovyev.android.calculator.CalculatorModel_color_display", true);
|
||||
|
||||
private volatile boolean initialized = false;
|
||||
|
||||
private boolean highlightText = true;
|
||||
|
||||
@NotNull
|
||||
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false);
|
||||
|
||||
@NotNull
|
||||
private volatile CalculatorEditorViewState viewState = CalculatorEditorViewStateImpl.newDefaultInstance();
|
||||
|
||||
private volatile boolean viewStateChange = false;
|
||||
|
||||
@Nullable
|
||||
private final Object viewLock = new Object();
|
||||
|
||||
@NotNull
|
||||
private final Handler uiHandler = new Handler();
|
||||
|
||||
public AndroidCalculatorEditorView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public AndroidCalculatorEditorView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public AndroidCalculatorEditorView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCheckIsTextEditor() {
|
||||
// NOTE: code below can be used carefully and should not be copied without special intention
|
||||
// The main purpose of code is to disable soft input (virtual keyboard) but leave all the TextEdit functionality, like cursor, scrolling, copy/paste menu etc
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
// fix for missing cursor in android 3 and higher
|
||||
try {
|
||||
// IDEA: return false always except if method was called from TextView.isCursorVisible() method
|
||||
for (StackTraceElement stackTraceElement : CollectionsUtils.asList(Thread.currentThread().getStackTrace())) {
|
||||
if ("isCursorVisible".equals(stackTraceElement.getMethodName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
// just in case...
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreateContextMenu(ContextMenu menu) {
|
||||
super.onCreateContextMenu(menu);
|
||||
|
||||
menu.removeItem(android.R.id.selectAll);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CharSequence prepareText(@NotNull String text, boolean highlightText) {
|
||||
CharSequence result;
|
||||
|
||||
if (highlightText) {
|
||||
|
||||
try {
|
||||
final TextHighlighter.Result processesText = textHighlighter.process(text);
|
||||
|
||||
assert processesText.getOffset() == 0;
|
||||
|
||||
result = Html.fromHtml(processesText.toString());
|
||||
} catch (CalculatorParseException e) {
|
||||
// set raw text
|
||||
result = text;
|
||||
|
||||
Log.e(this.getClass().getName(), e.getMessage(), e);
|
||||
}
|
||||
} else {
|
||||
result = text;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isHighlightText() {
|
||||
return highlightText;
|
||||
}
|
||||
|
||||
public void setHighlightText(boolean highlightText) {
|
||||
this.highlightText = highlightText;
|
||||
Locator.getInstance().getEditor().updateViewState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||
if (colorDisplay.getKey().equals(key)) {
|
||||
this.setHighlightText(colorDisplay.getPreference(preferences));
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void init(@NotNull Context context) {
|
||||
if (!initialized) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
this.addTextChangedListener(new TextWatcherImpl());
|
||||
|
||||
onSharedPreferenceChanged(preferences, colorDisplay.getKey());
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setState(@NotNull final CalculatorEditorViewState viewState) {
|
||||
if (viewLock != null) {
|
||||
synchronized (viewLock) {
|
||||
|
||||
final CharSequence text = prepareText(viewState.getText(), highlightText);
|
||||
|
||||
uiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final AndroidCalculatorEditorView editorView = AndroidCalculatorEditorView.this;
|
||||
synchronized (viewLock) {
|
||||
try {
|
||||
editorView.viewStateChange = true;
|
||||
editorView.viewState = viewState;
|
||||
editorView.setText(text, BufferType.EDITABLE);
|
||||
editorView.setSelection(viewState.getSelection());
|
||||
} finally {
|
||||
editorView.viewStateChange = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSelectionChanged(int selStart, int selEnd) {
|
||||
if (viewLock != null) {
|
||||
synchronized (viewLock) {
|
||||
if (!viewStateChange) {
|
||||
// external text change => need to notify editor
|
||||
super.onSelectionChanged(selStart, selEnd);
|
||||
Locator.getInstance().getEditor().setSelection(selStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleTextChange(Editable s) {
|
||||
if (viewLock != null) {
|
||||
synchronized (viewLock) {
|
||||
if (!viewStateChange) {
|
||||
// external text change => need to notify editor
|
||||
Locator.getInstance().getEditor().setText(String.valueOf(s));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class TextWatcherImpl implements TextWatcher {
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
handleTextChange(s);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,10 +1,15 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
import com.actionbarsherlock.app.SherlockFragmentActivity;
|
||||
import jscl.math.Generic;
|
||||
import jscl.math.function.Constant;
|
||||
@@ -18,6 +23,7 @@ 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.android.calculator.plot.PlotInput;
|
||||
import org.solovyev.common.msg.Message;
|
||||
import org.solovyev.common.msg.MessageType;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
@@ -190,6 +196,40 @@ public final class CalculatorActivityLauncher implements CalculatorEventListener
|
||||
}
|
||||
});
|
||||
break;
|
||||
case plot_graph:
|
||||
final PlotInput plotInput = (PlotInput) data;
|
||||
assert plotInput != null;
|
||||
App.getInstance().getUiThreadExecutor().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
plotGraph(App.getInstance().getApplication(), plotInput.getFunction(), plotInput.getConstant());
|
||||
}
|
||||
});
|
||||
break;
|
||||
case show_evaluation_error:
|
||||
final String errorMessage = (String) data;
|
||||
if (errorMessage != null) {
|
||||
App.getInstance().getUiThreadExecutor().execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
showEvaluationError(App.getInstance().getApplication(), errorMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void showEvaluationError(@NotNull Context context, @NotNull final String errorMessage) {
|
||||
final LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
|
||||
|
||||
final View errorMessageView = layoutInflater.inflate(R.layout.display_error_message, null);
|
||||
((TextView) errorMessageView.findViewById(R.id.error_message_text_view)).setText(errorMessage);
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context)
|
||||
.setPositiveButton(R.string.c_cancel, null)
|
||||
.setView(errorMessageView);
|
||||
|
||||
builder.create().show();
|
||||
}
|
||||
}
|
||||
|
@@ -1,115 +0,0 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.content.Context;
|
||||
import jscl.math.Generic;
|
||||
import jscl.math.function.Constant;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
import org.solovyev.android.calculator.view.NumeralBaseConverterDialog;
|
||||
import org.solovyev.android.menu.LabeledMenuItem;
|
||||
import org.solovyev.common.collections.CollectionsUtils;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 21.09.12
|
||||
* Time: 10:55
|
||||
*/
|
||||
public enum CalculatorDisplayMenuItem implements LabeledMenuItem<CalculatorDisplayViewState> {
|
||||
|
||||
copy(R.string.c_copy) {
|
||||
@Override
|
||||
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
||||
Locator.getInstance().getKeyboard().copyButtonPressed();
|
||||
}
|
||||
},
|
||||
|
||||
convert_to_bin(R.string.convert_to_bin) {
|
||||
@Override
|
||||
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
||||
ConversionMenuItem.convert_to_bin.onClick(data, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||
return ConversionMenuItem.convert_to_bin.isItemVisibleFor(generic, operation);
|
||||
}
|
||||
},
|
||||
|
||||
convert_to_dec(R.string.convert_to_dec) {
|
||||
@Override
|
||||
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
||||
ConversionMenuItem.convert_to_dec.onClick(data, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||
return ConversionMenuItem.convert_to_dec.isItemVisibleFor(generic, operation);
|
||||
}
|
||||
},
|
||||
|
||||
convert_to_hex(R.string.convert_to_hex) {
|
||||
@Override
|
||||
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
||||
ConversionMenuItem.convert_to_hex.onClick(data, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||
return ConversionMenuItem.convert_to_hex.isItemVisibleFor(generic, operation);
|
||||
}
|
||||
},
|
||||
|
||||
convert(R.string.c_convert) {
|
||||
@Override
|
||||
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
||||
final Generic result = data.getResult();
|
||||
if (result != null) {
|
||||
new NumeralBaseConverterDialog(result.toString()).show(context);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||
return operation == JsclOperation.numeric && generic.getConstants().isEmpty();
|
||||
}
|
||||
},
|
||||
|
||||
plot(R.string.c_plot) {
|
||||
@Override
|
||||
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
||||
final Generic generic = data.getResult();
|
||||
assert generic != null;
|
||||
|
||||
final Constant constant = CollectionsUtils.getFirstCollectionElement(CalculatorUtils.getNotSystemConstants(generic));
|
||||
assert constant != null;
|
||||
CalculatorActivityLauncher.plotGraph(context, generic, constant);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||
return CalculatorUtils.isPlotPossible(generic, operation);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private final int captionId;
|
||||
|
||||
CalculatorDisplayMenuItem(int captionId) {
|
||||
this.captionId = captionId;
|
||||
}
|
||||
|
||||
public final boolean isItemVisible(@NotNull CalculatorDisplayViewState displayViewState) {
|
||||
//noinspection ConstantConditions
|
||||
return displayViewState.isValid() && displayViewState.getResult() != null && isItemVisibleFor(displayViewState.getResult(), displayViewState.getOperation());
|
||||
}
|
||||
|
||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getCaption(@NotNull Context context) {
|
||||
return context.getString(captionId);
|
||||
}
|
||||
}
|
@@ -1,53 +0,0 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.menu.AMenuBuilder;
|
||||
import org.solovyev.android.menu.MenuImpl;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: Solovyev_S
|
||||
* Date: 21.09.12
|
||||
* Time: 10:58
|
||||
*/
|
||||
public class CalculatorDisplayOnClickListener implements View.OnClickListener {
|
||||
|
||||
@NotNull
|
||||
private final Context context;
|
||||
|
||||
public CalculatorDisplayOnClickListener(@NotNull Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v instanceof CalculatorDisplayView) {
|
||||
final CalculatorDisplay cd = Locator.getInstance().getDisplay();
|
||||
|
||||
final CalculatorDisplayViewState displayViewState = cd.getViewState();
|
||||
|
||||
if (displayViewState.isValid()) {
|
||||
final List<CalculatorDisplayMenuItem> filteredMenuItems = new ArrayList<CalculatorDisplayMenuItem>(CalculatorDisplayMenuItem.values().length);
|
||||
for (CalculatorDisplayMenuItem menuItem : CalculatorDisplayMenuItem.values()) {
|
||||
if (menuItem.isItemVisible(displayViewState)) {
|
||||
filteredMenuItems.add(menuItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (!filteredMenuItems.isEmpty()) {
|
||||
AMenuBuilder.newInstance(context, MenuImpl.newInstance(filteredMenuItems)).create(displayViewState).show();
|
||||
}
|
||||
|
||||
} else {
|
||||
final String errorMessage = displayViewState.getErrorMessage();
|
||||
if (errorMessage != null) {
|
||||
AndroidCalculator.showEvaluationError(context, errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,52 +0,0 @@
|
||||
package org.solovyev.android.calculator;
|
||||
|
||||
import android.content.Context;
|
||||
import jscl.NumeralBase;
|
||||
import jscl.math.Generic;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||
import org.solovyev.android.menu.AMenuItem;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 9/21/12
|
||||
* Time: 12:11 AM
|
||||
*/
|
||||
enum ConversionMenuItem implements AMenuItem<CalculatorDisplayViewState> {
|
||||
|
||||
convert_to_bin(NumeralBase.bin),
|
||||
convert_to_dec(NumeralBase.dec),
|
||||
convert_to_hex(NumeralBase.hex);
|
||||
|
||||
@NotNull
|
||||
private final NumeralBase toNumeralBase;
|
||||
|
||||
ConversionMenuItem(@NotNull NumeralBase toNumeralBase) {
|
||||
this.toNumeralBase = toNumeralBase;
|
||||
}
|
||||
|
||||
protected boolean isItemVisibleFor(@NotNull Generic generic, @NotNull JsclOperation operation) {
|
||||
boolean result = false;
|
||||
|
||||
if (operation == JsclOperation.numeric) {
|
||||
if (generic.getConstants().isEmpty()) {
|
||||
// conversion possible => return true
|
||||
final NumeralBase fromNumeralBase = Locator.getInstance().getEngine().getNumeralBase();
|
||||
if (fromNumeralBase != toNumeralBase) {
|
||||
result = Locator.getInstance().getCalculator().isConversionPossible(generic, fromNumeralBase, this.toNumeralBase);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
||||
final Generic result = data.getResult();
|
||||
|
||||
if (result != null) {
|
||||
Locator.getInstance().getCalculator().convert(result, this.toNumeralBase);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
package org.solovyev.android.calculator.onscreen;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.solovyev.android.calculator.CalculatorPreferences;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/20/12
|
||||
* Time: 11:05 PM
|
||||
*/
|
||||
public final class CalculatorOnscreenBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
public CalculatorOnscreenBroadcastReceiver() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(@NotNull Context context,
|
||||
@NotNull Intent intent) {
|
||||
if ( intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED) ) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if ( CalculatorPreferences.OnscreenCalculator.startOnBoot.getPreferenceNoError(preferences) ) {
|
||||
CalculatorOnscreenService.showNotification(context);
|
||||
}
|
||||
} else {
|
||||
final Intent newIntent = new Intent(intent);
|
||||
newIntent.setClass(context, CalculatorOnscreenService.class);
|
||||
context.startService(newIntent);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,217 +0,0 @@
|
||||
package org.solovyev.android.calculator.onscreen;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.WindowManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.AndroidUtils;
|
||||
import org.solovyev.android.calculator.CalculatorDisplayViewState;
|
||||
import org.solovyev.android.calculator.CalculatorEditorViewState;
|
||||
import org.solovyev.android.calculator.Locator;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.calculator.external.*;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/20/12
|
||||
* Time: 9:42 PM
|
||||
*/
|
||||
public class CalculatorOnscreenService extends Service implements ExternalCalculatorStateUpdater, OnscreenViewListener {
|
||||
|
||||
private static final int NOTIFICATION_ID = 9031988; // my birthday =)
|
||||
|
||||
@NotNull
|
||||
private final ExternalCalculatorIntentHandler intentHandler = new DefaultExternalCalculatorIntentHandler(this);
|
||||
public static final Class<CalculatorOnscreenBroadcastReceiver> INTENT_LISTENER_CLASS = CalculatorOnscreenBroadcastReceiver.class;
|
||||
|
||||
@Nullable
|
||||
private static String cursorColor;
|
||||
|
||||
@NotNull
|
||||
private CalculatorOnscreenView view;
|
||||
|
||||
private boolean compatibilityStart = true;
|
||||
|
||||
private boolean viewCreated = false;
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
}
|
||||
|
||||
private void createView() {
|
||||
if (!viewCreated) {
|
||||
final WindowManager wm = ((WindowManager) this.getSystemService(Context.WINDOW_SERVICE));
|
||||
|
||||
final DisplayMetrics dm = getResources().getDisplayMetrics();
|
||||
|
||||
int twoThirdWidth = 2 * wm.getDefaultDisplay().getWidth() / 3;
|
||||
int twoThirdHeight = 2 * wm.getDefaultDisplay().getHeight() / 3;
|
||||
|
||||
twoThirdWidth = Math.min(twoThirdWidth, twoThirdHeight);
|
||||
twoThirdHeight = Math.max(twoThirdWidth, getHeight(twoThirdWidth));
|
||||
|
||||
final int baseWidth = AndroidUtils.toPixels(dm, 300);
|
||||
final int width0 = Math.min(twoThirdWidth, baseWidth);
|
||||
final int height0 = Math.min(twoThirdHeight, getHeight(baseWidth));
|
||||
|
||||
final int width = Math.min(width0, height0);
|
||||
final int height = Math.max(width0, height0);
|
||||
|
||||
view = CalculatorOnscreenView.newInstance(this, CalculatorOnscreenViewDef.newInstance(width, height, -1, -1), getCursorColor(this), this);
|
||||
view.show();
|
||||
|
||||
startCalculatorListening();
|
||||
|
||||
viewCreated = true;
|
||||
}
|
||||
}
|
||||
|
||||
private int getHeight(int width) {
|
||||
return 4 * width / 3;
|
||||
}
|
||||
|
||||
private void startCalculatorListening() {
|
||||
Locator.getInstance().getExternalListenersContainer().addExternalListener(getIntentListenerClass());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Class<?> getIntentListenerClass() {
|
||||
return INTENT_LISTENER_CLASS;
|
||||
}
|
||||
|
||||
private void stopCalculatorListening() {
|
||||
Locator.getInstance().getExternalListenersContainer().removeExternalListener(getIntentListenerClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
stopCalculatorListening();
|
||||
this.view.hide();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(@NotNull Context context, @NotNull CalculatorEditorViewState editorState, @NotNull CalculatorDisplayViewState displayState) {
|
||||
view.updateDisplayState(displayState);
|
||||
view.updateEditorState(editorState);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getCursorColor(@NotNull Context context) {
|
||||
if (cursorColor == null) {
|
||||
cursorColor = Integer.toHexString(context.getResources().getColor(R.color.cpp_widget_cursor_color)).substring(2);
|
||||
}
|
||||
return cursorColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(Intent intent, int startId) {
|
||||
super.onStart(intent, startId);
|
||||
|
||||
if (this.compatibilityStart) {
|
||||
handleStart(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
|
||||
final int result;
|
||||
try {
|
||||
this.compatibilityStart = false;
|
||||
result = super.onStartCommand(intent, flags, startId);
|
||||
handleStart(intent);
|
||||
} finally {
|
||||
this.compatibilityStart = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void handleStart(@Nullable Intent intent) {
|
||||
if ( intent != null ) {
|
||||
|
||||
if (isInitIntent(intent)) {
|
||||
|
||||
boolean createView = intent.getBooleanExtra(AndroidExternalListenersContainer.INIT_ACTION_CREATE_VIEW_EXTRA, false);
|
||||
if (createView) {
|
||||
hideNotification();
|
||||
createView();
|
||||
} else {
|
||||
showNotification();
|
||||
}
|
||||
}
|
||||
|
||||
if (viewCreated) {
|
||||
intentHandler.onIntent(this, intent);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInitIntent(@NotNull Intent intent) {
|
||||
return intent.getAction().equals(AndroidExternalListenersContainer.INIT_ACTION);
|
||||
}
|
||||
|
||||
private void hideNotification() {
|
||||
final NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
nm.cancel(NOTIFICATION_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewMinimized() {
|
||||
showNotification();
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewHidden() {
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
private void showNotification() {
|
||||
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
|
||||
builder.setSmallIcon(R.drawable.kb_logo);
|
||||
builder.setContentTitle(getText(R.string.c_app_name));
|
||||
builder.setContentText(getString(R.string.open_onscreen_calculator));
|
||||
|
||||
final Intent intent = createShowOnscreenViewIntent(this);
|
||||
builder.setContentIntent(PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
|
||||
|
||||
final NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
nm.notify(NOTIFICATION_ID, builder.getNotification());
|
||||
}
|
||||
|
||||
public static void showNotification(@NotNull Context context) {
|
||||
final Intent intent = new Intent(AndroidExternalListenersContainer.INIT_ACTION);
|
||||
intent.setClass(context, getIntentListenerClass());
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
|
||||
public static void showOnscreenView(@NotNull Context context) {
|
||||
final Intent intent = createShowOnscreenViewIntent(context);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Intent createShowOnscreenViewIntent(@NotNull Context context) {
|
||||
final Intent intent = new Intent(AndroidExternalListenersContainer.INIT_ACTION);
|
||||
intent.setClass(context, getIntentListenerClass());
|
||||
intent.putExtra(AndroidExternalListenersContainer.INIT_ACTION_CREATE_VIEW_EXTRA, true);
|
||||
return intent;
|
||||
}
|
||||
}
|
||||
|
@@ -1,461 +0,0 @@
|
||||
package org.solovyev.android.calculator.onscreen;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageView;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.widget.WidgetButton;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/21/12
|
||||
* Time: 9:03 PM
|
||||
*/
|
||||
public class CalculatorOnscreenView {
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTANTS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private static final String TAG = CalculatorOnscreenView.class.getSimpleName();
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* FIELDS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@NotNull
|
||||
private View root;
|
||||
|
||||
@NotNull
|
||||
private View content;
|
||||
|
||||
@NotNull
|
||||
private View header;
|
||||
|
||||
@NotNull
|
||||
private AndroidCalculatorEditorView editorView;
|
||||
|
||||
@NotNull
|
||||
private AndroidCalculatorDisplayView displayView;
|
||||
|
||||
@NotNull
|
||||
private Context context;
|
||||
|
||||
private int width;
|
||||
|
||||
private int height;
|
||||
|
||||
private int unfoldedHeight;
|
||||
|
||||
@NotNull
|
||||
private String cursorColor;
|
||||
|
||||
@Nullable
|
||||
private OnscreenViewListener viewListener;
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATES
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private boolean minimized = false;
|
||||
|
||||
private boolean attached = false;
|
||||
|
||||
private boolean folded = false;
|
||||
|
||||
private boolean initialized = false;
|
||||
|
||||
private boolean hidden = true;
|
||||
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTRUCTORS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private CalculatorOnscreenView() {
|
||||
}
|
||||
|
||||
public static CalculatorOnscreenView newInstance(@NotNull Context context,
|
||||
@NotNull CalculatorOnscreenViewDef def,
|
||||
@NotNull String cursorColor,
|
||||
@Nullable OnscreenViewListener viewListener) {
|
||||
final CalculatorOnscreenView result = new CalculatorOnscreenView();
|
||||
|
||||
result.root = View.inflate(context, R.layout.onscreen_layout, null);
|
||||
result.context = context;
|
||||
result.width = def.getWidth();
|
||||
result.height = def.getHeight();
|
||||
result.cursorColor = cursorColor;
|
||||
result.viewListener = viewListener;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* METHODS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public void updateDisplayState(@NotNull CalculatorDisplayViewState displayState) {
|
||||
checkInit();
|
||||
displayView.setState(displayState);
|
||||
}
|
||||
|
||||
public void updateEditorState(@NotNull CalculatorEditorViewState editorState) {
|
||||
checkInit();
|
||||
editorView.setState(editorState);
|
||||
}
|
||||
|
||||
private void setHeight(int height) {
|
||||
checkInit();
|
||||
|
||||
this.height = height;
|
||||
|
||||
final WindowManager.LayoutParams params = (WindowManager.LayoutParams) root.getLayoutParams();
|
||||
|
||||
params.height = height;
|
||||
|
||||
getWindowManager().updateViewLayout(root, params);
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* LIFECYCLE
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private void init() {
|
||||
|
||||
if (!initialized) {
|
||||
for (final WidgetButton widgetButton : WidgetButton.values()) {
|
||||
final View button = root.findViewById(widgetButton.getButtonId());
|
||||
if (button != null) {
|
||||
button.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
widgetButton.onClick(context);
|
||||
if ( widgetButton == WidgetButton.app ) {
|
||||
minimize();
|
||||
}
|
||||
}
|
||||
});
|
||||
button.setOnLongClickListener(new View.OnLongClickListener() {
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
widgetButton.onLongClick(context);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
|
||||
header = root.findViewById(R.id.onscreen_header);
|
||||
content = root.findViewById(R.id.onscreen_content);
|
||||
|
||||
displayView = (AndroidCalculatorDisplayView) root.findViewById(R.id.calculator_display);
|
||||
displayView.init(this.context, false);
|
||||
|
||||
editorView = (AndroidCalculatorEditorView) root.findViewById(R.id.calculator_editor);
|
||||
editorView.init(this.context);
|
||||
|
||||
final View onscreenFoldButton = root.findViewById(R.id.onscreen_fold_button);
|
||||
onscreenFoldButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (folded) {
|
||||
unfold();
|
||||
} else {
|
||||
fold();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final View onscreenHideButton = root.findViewById(R.id.onscreen_minimize_button);
|
||||
onscreenHideButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
minimize();
|
||||
}
|
||||
});
|
||||
|
||||
root.findViewById(R.id.onscreen_close_button).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
hide();
|
||||
}
|
||||
});
|
||||
|
||||
final ImageView onscreenTitleImageView = (ImageView) root.findViewById(R.id.onscreen_title);
|
||||
onscreenTitleImageView.setOnTouchListener(new WindowDragTouchListener(wm, root));
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void checkInit() {
|
||||
if (!initialized) {
|
||||
throw new IllegalStateException("init() must be called!");
|
||||
}
|
||||
}
|
||||
|
||||
public void show() {
|
||||
if (hidden) {
|
||||
init();
|
||||
attach();
|
||||
|
||||
hidden = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void attach() {
|
||||
checkInit();
|
||||
|
||||
final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||
if (!attached) {
|
||||
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
|
||||
width,
|
||||
height,
|
||||
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
|
||||
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
|
||||
PixelFormat.TRANSLUCENT);
|
||||
|
||||
wm.addView(root, params);
|
||||
attached = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void fold() {
|
||||
if (!folded) {
|
||||
final WindowManager.LayoutParams params = (WindowManager.LayoutParams) root.getLayoutParams();
|
||||
unfoldedHeight = params.height;
|
||||
int newHeight = header.getHeight();
|
||||
content.setVisibility(View.GONE);
|
||||
setHeight(newHeight);
|
||||
folded = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void unfold() {
|
||||
if (folded) {
|
||||
content.setVisibility(View.VISIBLE);
|
||||
setHeight(unfoldedHeight);
|
||||
folded = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void detach() {
|
||||
checkInit();
|
||||
|
||||
if (attached) {
|
||||
getWindowManager().removeView(root);
|
||||
attached = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void minimize() {
|
||||
checkInit();
|
||||
if (!minimized) {
|
||||
detach();
|
||||
|
||||
if (viewListener != null) {
|
||||
viewListener.onViewMinimized();
|
||||
}
|
||||
|
||||
minimized = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void hide() {
|
||||
checkInit();
|
||||
|
||||
if (!hidden) {
|
||||
|
||||
detach();
|
||||
|
||||
if (viewListener != null) {
|
||||
viewListener.onViewHidden();
|
||||
}
|
||||
|
||||
hidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private WindowManager getWindowManager() {
|
||||
return ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CalculatorOnscreenViewDef getCalculatorOnscreenViewDef() {
|
||||
final WindowManager.LayoutParams params = (WindowManager.LayoutParams) root.getLayoutParams();
|
||||
return CalculatorOnscreenViewDef.newInstance(width, height, params.x, params.y);
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* STATIC
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private static class WindowDragTouchListener implements View.OnTouchListener {
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTANTS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
private static final float DIST_EPS = 0f;
|
||||
private static final float DIST_MAX = 100000f;
|
||||
private static final long TIME_EPS = 0L;
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* FIELDS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
@NotNull
|
||||
private final WindowManager wm;
|
||||
|
||||
private float x0;
|
||||
|
||||
private float y0;
|
||||
|
||||
private long time = 0;
|
||||
|
||||
@NotNull
|
||||
private final View view;
|
||||
|
||||
/*
|
||||
**********************************************************************
|
||||
*
|
||||
* CONSTRUCTORS
|
||||
*
|
||||
**********************************************************************
|
||||
*/
|
||||
|
||||
public WindowDragTouchListener(@NotNull WindowManager wm,
|
||||
@NotNull View view) {
|
||||
this.wm = wm;
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
|
||||
//Log.d(TAG, "Action: " + event.getAction());
|
||||
|
||||
final float x1 = event.getX();
|
||||
final float y1 = event.getY();
|
||||
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
Log.d(TAG, "0:" + toString(x0, y0) + ", 1: " + toString(x1, y1));
|
||||
x0 = x1;
|
||||
y0 = y1;
|
||||
return true;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
|
||||
if ( currentTime - time >= TIME_EPS ) {
|
||||
time = currentTime;
|
||||
for (int i = 0; i < event.getHistorySize(); i++) {
|
||||
final float xi = event.getHistoricalX(i);
|
||||
final float yi = event.getHistoricalY(i);
|
||||
processMove(xi, yi);
|
||||
}
|
||||
processMove(x1, y1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void processMove(float x1, float y1) {
|
||||
final float Δx = x1 - x0;
|
||||
final float Δy = y1 - y0;
|
||||
|
||||
final WindowManager.LayoutParams params = (WindowManager.LayoutParams) view.getLayoutParams();
|
||||
Log.d(TAG, "0:" + toString(x0, y0) + ", 1: " + toString(x1, y1) + ", Δ: " + toString(Δx, Δy) + ", params: " + toString(params.x, params.y));
|
||||
|
||||
boolean xInBounds = isDistanceInBounds(Δx);
|
||||
boolean yInBounds = isDistanceInBounds(Δy);
|
||||
if (xInBounds || yInBounds) {
|
||||
|
||||
if (xInBounds) {
|
||||
params.x = (int) (params.x + Δx);
|
||||
}
|
||||
|
||||
if (yInBounds) {
|
||||
params.y = (int) (params.y + Δy);
|
||||
}
|
||||
|
||||
wm.updateViewLayout(view, params);
|
||||
|
||||
if (xInBounds) {
|
||||
x0 = x1;
|
||||
}
|
||||
|
||||
if (yInBounds) {
|
||||
y0 = y1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isDistanceInBounds(float δx) {
|
||||
δx = Math.abs(δx);
|
||||
return δx >= DIST_EPS && δx < DIST_MAX;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String toString(float x, float y) {
|
||||
return "(" + formatFloat(x) + ", " + formatFloat(y) + ")";
|
||||
}
|
||||
|
||||
private static String formatFloat(float value) {
|
||||
if (value >= 0) {
|
||||
return "+" + String.format("%.2f", value);
|
||||
} else {
|
||||
return String.format("%.2f", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,61 +0,0 @@
|
||||
package org.solovyev.android.calculator.onscreen;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/21/12
|
||||
* Time: 10:55 PM
|
||||
*/
|
||||
public class CalculatorOnscreenViewDef {
|
||||
|
||||
private int width;
|
||||
private int height;
|
||||
private int x;
|
||||
private int y;
|
||||
|
||||
private CalculatorOnscreenViewDef() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static CalculatorOnscreenViewDef newInstance(int width, int height, int x, int y) {
|
||||
final CalculatorOnscreenViewDef result = new CalculatorOnscreenViewDef();
|
||||
result.width = width;
|
||||
result.height = height;
|
||||
result.x = x;
|
||||
result.y = y;
|
||||
return result;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public void setWidth(int width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setHeight(int height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setX(int x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public void setY(int y) {
|
||||
this.y = y;
|
||||
}
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
package org.solovyev.android.calculator.onscreen;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 11/21/12
|
||||
* Time: 9:45 PM
|
||||
*/
|
||||
public interface OnscreenViewListener {
|
||||
|
||||
// view minimized == view is in the action bar
|
||||
void onViewMinimized();
|
||||
|
||||
// view hidden == view closed
|
||||
void onViewHidden();
|
||||
}
|
@@ -1,98 +0,0 @@
|
||||
package org.solovyev.android.calculator.view;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.Locator;
|
||||
import org.solovyev.android.calculator.CalculatorParseException;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.calculator.ToJsclTextProcessor;
|
||||
import org.solovyev.android.calculator.units.CalculatorNumeralBase;
|
||||
import org.solovyev.common.MutableObject;
|
||||
import org.solovyev.common.text.StringUtils;
|
||||
import org.solovyev.math.units.Unit;
|
||||
import org.solovyev.math.units.UnitImpl;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 4/22/12
|
||||
* Time: 12:20 AM
|
||||
*/
|
||||
public class NumeralBaseConverterDialog {
|
||||
|
||||
@Nullable
|
||||
private String initialFromValue;
|
||||
|
||||
public NumeralBaseConverterDialog(String initialFromValue) {
|
||||
this.initialFromValue = initialFromValue;
|
||||
}
|
||||
|
||||
public void show(@NotNull Context context) {
|
||||
final UnitConverterViewBuilder b = new UnitConverterViewBuilder();
|
||||
b.setFromUnitTypes(Arrays.asList(CalculatorNumeralBase.values()));
|
||||
b.setToUnitTypes(Arrays.asList(CalculatorNumeralBase.values()));
|
||||
|
||||
if (!StringUtils.isEmpty(initialFromValue)) {
|
||||
String value = initialFromValue;
|
||||
try {
|
||||
value = ToJsclTextProcessor.getInstance().process(value).getExpression();
|
||||
b.setFromValue(UnitImpl.newInstance(value, CalculatorNumeralBase.valueOf(Locator.getInstance().getEngine().getNumeralBase())));
|
||||
} catch (CalculatorParseException e) {
|
||||
b.setFromValue(UnitImpl.newInstance(value, CalculatorNumeralBase.valueOf(Locator.getInstance().getEngine().getNumeralBase())));
|
||||
}
|
||||
} else {
|
||||
b.setFromValue(UnitImpl.newInstance("", CalculatorNumeralBase.valueOf(Locator.getInstance().getEngine().getNumeralBase())));
|
||||
}
|
||||
|
||||
b.setConverter(CalculatorNumeralBase.getConverter());
|
||||
|
||||
final MutableObject<AlertDialog> alertDialogHolder = new MutableObject<AlertDialog>();
|
||||
b.setOkButtonOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final AlertDialog alertDialog = alertDialogHolder.getObject();
|
||||
if (alertDialog != null) {
|
||||
alertDialog.dismiss();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
b.setCustomButtonData(new UnitConverterViewBuilder.CustomButtonData(context.getString(R.string.c_use_short), new UnitConverterViewBuilder.CustomButtonOnClickListener() {
|
||||
@Override
|
||||
public void onClick(@NotNull Unit<String> fromUnits, @NotNull Unit<String> toUnits) {
|
||||
String toUnitsValue = toUnits.getValue();
|
||||
|
||||
if (!toUnits.getUnitType().equals(CalculatorNumeralBase.valueOf(Locator.getInstance().getEngine().getNumeralBase()))) {
|
||||
toUnitsValue = ((CalculatorNumeralBase) toUnits.getUnitType()).getNumeralBase().getJsclPrefix() + toUnitsValue;
|
||||
}
|
||||
|
||||
Locator.getInstance().getKeyboard().buttonPressed(toUnitsValue);
|
||||
final AlertDialog alertDialog = alertDialogHolder.getObject();
|
||||
if (alertDialog != null) {
|
||||
alertDialog.dismiss();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
final AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
|
||||
alertBuilder.setView(b.build(context));
|
||||
alertBuilder.setTitle(R.string.c_conversion_tool);
|
||||
|
||||
final AlertDialog alertDialog = alertBuilder.create();
|
||||
|
||||
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
|
||||
lp.copyFrom(alertDialog.getWindow().getAttributes());
|
||||
|
||||
lp.width = WindowManager.LayoutParams.FILL_PARENT;
|
||||
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
||||
|
||||
alertDialogHolder.setObject(alertDialog);
|
||||
alertDialog.show();
|
||||
alertDialog.getWindow().setAttributes(lp);
|
||||
}
|
||||
}
|
@@ -1,246 +0,0 @@
|
||||
/*
|
||||
* 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.view;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.*;
|
||||
import org.solovyev.android.calculator.math.MathType;
|
||||
import org.solovyev.android.calculator.text.TextProcessor;
|
||||
import org.solovyev.common.MutableObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 10/12/11
|
||||
* Time: 9:47 PM
|
||||
*/
|
||||
public class TextHighlighter implements TextProcessor<TextHighlighter.Result, String> {
|
||||
|
||||
private static final Map<String, String> nbFontAttributes = new HashMap<String, String>();
|
||||
|
||||
static {
|
||||
nbFontAttributes.put("color", "#008000");
|
||||
}
|
||||
|
||||
public static class Result implements CharSequence {
|
||||
|
||||
@NotNull
|
||||
private final CharSequence charSequence;
|
||||
|
||||
@Nullable
|
||||
private String string;
|
||||
|
||||
private final int offset;
|
||||
|
||||
public Result(@NotNull CharSequence charSequence, int offset) {
|
||||
this.charSequence = charSequence;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return charSequence.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char charAt(int i) {
|
||||
return charSequence.charAt(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence subSequence(int i, int i1) {
|
||||
return charSequence.subSequence(i, i1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (string == null) {
|
||||
string = charSequence.toString();
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CharSequence getCharSequence() {
|
||||
return charSequence;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
|
||||
private final int color;
|
||||
private final int colorRed;
|
||||
private final int colorGreen;
|
||||
private final int colorBlue;
|
||||
private final boolean formatNumber;
|
||||
|
||||
public TextHighlighter(int baseColor, boolean formatNumber) {
|
||||
this.color = baseColor;
|
||||
this.formatNumber = formatNumber;
|
||||
//this.colorRed = Color.red(baseColor);
|
||||
this.colorRed = (baseColor >> 16) & 0xFF;
|
||||
//this.colorGreen = Color.green(baseColor);
|
||||
this.colorGreen = (color >> 8) & 0xFF;
|
||||
//this.colorBlue = Color.blue(baseColor);
|
||||
this.colorBlue = color & 0xFF;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Result process(@NotNull String text) throws CalculatorParseException {
|
||||
final CharSequence result;
|
||||
|
||||
int maxNumberOfOpenGroupSymbols = 0;
|
||||
int numberOfOpenGroupSymbols = 0;
|
||||
|
||||
final StringBuilder text1 = new StringBuilder(5 * text.length());
|
||||
|
||||
int resultOffset = 0;
|
||||
|
||||
final AbstractNumberBuilder numberBuilder;
|
||||
if (!formatNumber) {
|
||||
numberBuilder = new LiteNumberBuilder(Locator.getInstance().getEngine());
|
||||
} else {
|
||||
numberBuilder = new NumberBuilder(Locator.getInstance().getEngine());
|
||||
}
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
MathType.Result mathType = MathType.getType(text, i, numberBuilder.isHexMode());
|
||||
|
||||
if (numberBuilder instanceof NumberBuilder) {
|
||||
final MutableObject<Integer> numberOffset = new MutableObject<Integer>(0);
|
||||
((NumberBuilder) numberBuilder).process(text1, mathType, numberOffset);
|
||||
resultOffset += numberOffset.getObject();
|
||||
} else {
|
||||
((LiteNumberBuilder) numberBuilder).process(mathType);
|
||||
}
|
||||
|
||||
final String match = mathType.getMatch();
|
||||
switch (mathType.getMathType()) {
|
||||
case open_group_symbol:
|
||||
numberOfOpenGroupSymbols++;
|
||||
maxNumberOfOpenGroupSymbols = Math.max(maxNumberOfOpenGroupSymbols, numberOfOpenGroupSymbols);
|
||||
text1.append(text.charAt(i));
|
||||
break;
|
||||
case close_group_symbol:
|
||||
numberOfOpenGroupSymbols--;
|
||||
text1.append(text.charAt(i));
|
||||
break;
|
||||
case operator:
|
||||
text1.append(match);
|
||||
if (match.length() > 1) {
|
||||
i += match.length() - 1;
|
||||
}
|
||||
break;
|
||||
case function:
|
||||
i = processHighlightedText(text1, i, match, "i", null);
|
||||
break;
|
||||
case constant:
|
||||
i = processHighlightedText(text1, i, match, "b", null);
|
||||
break;
|
||||
case numeral_base:
|
||||
i = processHighlightedText(text1, i, match, "b", null);
|
||||
break;
|
||||
default:
|
||||
if (mathType.getMathType() == MathType.text || match.length() <= 1) {
|
||||
text1.append(text.charAt(i));
|
||||
} else {
|
||||
text1.append(match);
|
||||
i += match.length() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numberBuilder instanceof NumberBuilder) {
|
||||
final MutableObject<Integer> numberOffset = new MutableObject<Integer>(0);
|
||||
((NumberBuilder) numberBuilder).processNumber(text1, numberOffset);
|
||||
resultOffset += numberOffset.getObject();
|
||||
}
|
||||
|
||||
if (maxNumberOfOpenGroupSymbols > 0) {
|
||||
|
||||
final StringBuilder text2 = new StringBuilder(text1.length());
|
||||
|
||||
final CharSequence s = text1;
|
||||
int i = processBracketGroup(text2, s, 0, 0, maxNumberOfOpenGroupSymbols);
|
||||
for (; i < s.length(); i++) {
|
||||
text2.append(s.charAt(i));
|
||||
}
|
||||
|
||||
//Log.d(AndroidCalculatorEditorView.class.getName(), text2.toString());
|
||||
|
||||
result = text2.toString();
|
||||
} else {
|
||||
result = text1.toString();
|
||||
}
|
||||
|
||||
return new Result(result, resultOffset);
|
||||
}
|
||||
|
||||
private int processHighlightedText(@NotNull StringBuilder result, int i, @NotNull String match, @NotNull String tag, @Nullable Map<String, String> tagAttributes) {
|
||||
result.append("<").append(tag);
|
||||
|
||||
if (tagAttributes != null && !tagAttributes.entrySet().isEmpty()) {
|
||||
for (Map.Entry<String, String> entry : tagAttributes.entrySet()) {
|
||||
// attr1="attr1_value" attr2="attr2_value"
|
||||
result.append(" ").append(entry.getKey()).append("=\"").append(entry.getValue()).append("\"");
|
||||
}
|
||||
}
|
||||
|
||||
result.append(">").append(match).append("</").append(tag).append(">");
|
||||
if (match.length() > 1) {
|
||||
return i + match.length() - 1;
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
private int processBracketGroup(@NotNull StringBuilder result, @NotNull CharSequence s, int i, int numberOfOpenings, int maxNumberOfGroups) {
|
||||
|
||||
result.append("<font color=\"").append(getColor(maxNumberOfGroups, numberOfOpenings)).append("\">");
|
||||
|
||||
for (; i < s.length(); i++) {
|
||||
char ch = s.charAt(i);
|
||||
String strCh = String.valueOf(ch);
|
||||
|
||||
if (MathType.open_group_symbol.getTokens().contains(strCh)) {
|
||||
result.append(ch);
|
||||
result.append("</font>");
|
||||
i = processBracketGroup(result, s, i + 1, numberOfOpenings + 1, maxNumberOfGroups);
|
||||
result.append("<font color=\"").append(getColor(maxNumberOfGroups, numberOfOpenings)).append("\">");
|
||||
if (i < s.length() && MathType.close_group_symbol.getTokens().contains(String.valueOf(s.charAt(i)))) {
|
||||
result.append(s.charAt(i));
|
||||
}
|
||||
} else if (MathType.close_group_symbol.getTokens().contains(strCh)) {
|
||||
break;
|
||||
} else {
|
||||
result.append(ch);
|
||||
}
|
||||
}
|
||||
|
||||
result.append("</font>");
|
||||
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
private String getColor(int totalNumberOfOpenings, int numberOfOpenings) {
|
||||
double c = 0.8;
|
||||
|
||||
int offset = ((int) (255 * c)) * numberOfOpenings / (totalNumberOfOpenings + 1);
|
||||
|
||||
// for tests:
|
||||
// innt result = Color.rgb(BASE_COLOUR_RED_COMPONENT - offset, BASE_COLOUR_GREEN_COMPONENT - offset, BASE_COLOUR_BLUE_COMPONENT - offset);
|
||||
int result = (0xFF << 24) | ((colorRed - offset) << 16) | ((colorGreen - offset) << 8) | (colorBlue - offset);
|
||||
|
||||
return "#" + Integer.toHexString(result).substring(2);
|
||||
}
|
||||
}
|
@@ -1,221 +0,0 @@
|
||||
package org.solovyev.android.calculator.view;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.text.ClipboardManager;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.solovyev.android.calculator.CalculatorImpl;
|
||||
import org.solovyev.math.units.*;
|
||||
import org.solovyev.android.calculator.R;
|
||||
import org.solovyev.android.view.ViewBuilder;
|
||||
import org.solovyev.android.view.ViewFromLayoutBuilder;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: serso
|
||||
* Date: 4/20/12
|
||||
* Time: 4:50 PM
|
||||
*/
|
||||
public class UnitConverterViewBuilder implements ViewBuilder<View> {
|
||||
|
||||
@NotNull
|
||||
private List<? extends UnitType<String>> fromUnitTypes = Collections.emptyList();
|
||||
|
||||
@NotNull
|
||||
private List<? extends UnitType<String>> toUnitTypes = Collections.emptyList();
|
||||
|
||||
@Nullable
|
||||
private Unit<String> fromValue;
|
||||
|
||||
@NotNull
|
||||
private UnitConverter<String> converter = UnitConverter.Dummy.getInstance();
|
||||
|
||||
@Nullable
|
||||
private View.OnClickListener okButtonOnClickListener;
|
||||
|
||||
@Nullable
|
||||
private CustomButtonData customButtonData;
|
||||
|
||||
public void setFromUnitTypes(@NotNull List<? extends UnitType<String>> fromUnitTypes) {
|
||||
this.fromUnitTypes = fromUnitTypes;
|
||||
}
|
||||
|
||||
public void setToUnitTypes(@NotNull List<? extends UnitType<String>> toUnitTypes) {
|
||||
this.toUnitTypes = toUnitTypes;
|
||||
}
|
||||
|
||||
public void setFromValue(@Nullable Unit<String> fromValue) {
|
||||
this.fromValue = fromValue;
|
||||
}
|
||||
|
||||
public void setConverter(@NotNull UnitConverter<String> converter) {
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
public void setOkButtonOnClickListener(@Nullable View.OnClickListener okButtonOnClickListener) {
|
||||
this.okButtonOnClickListener = okButtonOnClickListener;
|
||||
}
|
||||
|
||||
public void setCustomButtonData(@Nullable CustomButtonData customButtonData) {
|
||||
this.customButtonData = customButtonData;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public View build(@NotNull final Context context) {
|
||||
final View main = ViewFromLayoutBuilder.newInstance(R.layout.unit_converter).build(context);
|
||||
|
||||
final Spinner fromSpinner = (Spinner) main.findViewById(R.id.unit_types_from);
|
||||
final EditText fromEditText = (EditText) main.findViewById(R.id.units_from);
|
||||
fromEditText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
doConversion(main, context, UnitConverterViewBuilder.this.converter);
|
||||
}
|
||||
});
|
||||
|
||||
fillSpinner(main, context, R.id.unit_types_from, fromUnitTypes);
|
||||
fillSpinner(main, context, R.id.unit_types_to, toUnitTypes);
|
||||
|
||||
if (fromValue != null) {
|
||||
fromEditText.setText(fromValue.getValue());
|
||||
|
||||
int i = fromUnitTypes.indexOf(fromValue.getUnitType());
|
||||
if ( i >= 0 ) {
|
||||
fromSpinner.setSelection(i);
|
||||
}
|
||||
}
|
||||
|
||||
final Button copyButton = (Button) main.findViewById(R.id.unit_converter_copy_button);
|
||||
copyButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final EditText toEditText = (EditText) main.findViewById(R.id.units_to);
|
||||
|
||||
final ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Activity.CLIPBOARD_SERVICE);
|
||||
clipboard.setText(toEditText.getText().toString());
|
||||
Toast.makeText(context, context.getText(R.string.c_result_copied), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
|
||||
final Button okButton = (Button) main.findViewById(R.id.unit_converter_ok_button);
|
||||
if ( okButtonOnClickListener == null ) {
|
||||
((ViewGroup) okButton.getParent()).removeView(okButton);
|
||||
} else {
|
||||
okButton.setOnClickListener(this.okButtonOnClickListener);
|
||||
}
|
||||
|
||||
final Button customButton = (Button) main.findViewById(R.id.unit_converter_custom_button);
|
||||
if ( customButtonData == null ) {
|
||||
((ViewGroup) customButton.getParent()).removeView(customButton);
|
||||
} else {
|
||||
customButton.setText(customButtonData.text);
|
||||
customButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
customButtonData.clickListener.onClick(getFromUnit(main), getToUnit(main));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
return main;
|
||||
}
|
||||
|
||||
private void fillSpinner(@NotNull final View main,
|
||||
@NotNull final Context context,
|
||||
final int spinnerId,
|
||||
@NotNull List<? extends UnitType<String>> unitTypes) {
|
||||
final Spinner spinner = (Spinner) main.findViewById(spinnerId);
|
||||
|
||||
final ArrayAdapter<UnitType<String>> adapter = new ArrayAdapter<UnitType<String>>(context, android.R.layout.simple_spinner_item);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
for (UnitType<String> fromUnitType : unitTypes) {
|
||||
adapter.add(fromUnitType);
|
||||
}
|
||||
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
doConversion(main, context, UnitConverterViewBuilder.this.converter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
}
|
||||
});
|
||||
spinner.setAdapter(adapter);
|
||||
}
|
||||
|
||||
private static void doConversion(@NotNull View main, @NotNull Context context, @NotNull UnitConverter<String> converter) {
|
||||
final EditText fromEditText = (EditText) main.findViewById(R.id.units_from);
|
||||
|
||||
final EditText toEditText = (EditText) main.findViewById(R.id.units_to);
|
||||
|
||||
final String from = fromEditText.getText().toString();
|
||||
try {
|
||||
toEditText.setText(ConversionUtils.doConversion(converter, from, getFromUnitType(main), getToUnitType(main)));
|
||||
} catch (ConversionException e) {
|
||||
toEditText.setText(context.getString(R.string.c_error));
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Unit<String> getToUnit(@NotNull View main) {
|
||||
final EditText toUnits = (EditText) main.findViewById(R.id.units_to);
|
||||
return UnitImpl.newInstance(toUnits.getText().toString(), getToUnitType(main));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static UnitType<String> getToUnitType(@NotNull View main) {
|
||||
final Spinner toSpinner = (Spinner) main.findViewById(R.id.unit_types_to);
|
||||
return (UnitType<String>) toSpinner.getSelectedItem();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Unit<String> getFromUnit(@NotNull View main) {
|
||||
final EditText fromUnits = (EditText) main.findViewById(R.id.units_from);
|
||||
return UnitImpl.newInstance(fromUnits.getText().toString(), getFromUnitType(main));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static UnitType<String> getFromUnitType(@NotNull View main) {
|
||||
final Spinner fromSpinner = (Spinner) main.findViewById(R.id.unit_types_from);
|
||||
return (UnitType<String>) fromSpinner.getSelectedItem();
|
||||
}
|
||||
|
||||
public static class CustomButtonData {
|
||||
|
||||
@NotNull
|
||||
private String text;
|
||||
|
||||
@NotNull
|
||||
private CustomButtonOnClickListener clickListener;
|
||||
|
||||
|
||||
public CustomButtonData(@NotNull String text, @NotNull CustomButtonOnClickListener clickListener) {
|
||||
this.text = text;
|
||||
this.clickListener = clickListener;
|
||||
}
|
||||
}
|
||||
|
||||
public static interface CustomButtonOnClickListener {
|
||||
void onClick(@NotNull Unit<String> fromUnits, @NotNull Unit<String> toUnits);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user