Exponent in EditVariableFragment
This commit is contained in:
parent
6c23fa2cb6
commit
a7c2d0b2e2
@ -48,9 +48,7 @@ import android.widget.PopupWindow;
|
|||||||
import butterknife.Bind;
|
import butterknife.Bind;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import dagger.Lazy;
|
import dagger.Lazy;
|
||||||
import jscl.JsclMathEngine;
|
|
||||||
import jscl.math.function.IConstant;
|
import jscl.math.function.IConstant;
|
||||||
import midpcalc.Real;
|
|
||||||
import org.solovyev.android.Check;
|
import org.solovyev.android.Check;
|
||||||
import org.solovyev.android.calculator.*;
|
import org.solovyev.android.calculator.*;
|
||||||
import org.solovyev.android.calculator.functions.FunctionsRegistry;
|
import org.solovyev.android.calculator.functions.FunctionsRegistry;
|
||||||
@ -58,6 +56,7 @@ import org.solovyev.android.calculator.keyboard.FloatingKeyboard;
|
|||||||
import org.solovyev.android.calculator.keyboard.FloatingKeyboardWindow;
|
import org.solovyev.android.calculator.keyboard.FloatingKeyboardWindow;
|
||||||
import org.solovyev.android.calculator.math.MathType;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
import org.solovyev.android.calculator.view.EditTextCompat;
|
import org.solovyev.android.calculator.view.EditTextCompat;
|
||||||
|
import org.solovyev.android.text.method.NumberInputFilter;
|
||||||
import org.solovyev.common.text.Strings;
|
import org.solovyev.common.text.Strings;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
@ -313,7 +312,7 @@ public class EditVariableFragment extends BaseDialogFragment implements View.OnF
|
|||||||
valueView.setEditableFactory(new Editable.Factory() {
|
valueView.setEditableFactory(new Editable.Factory() {
|
||||||
@Override
|
@Override
|
||||||
public Editable newEditable(CharSequence source) {
|
public Editable newEditable(CharSequence source) {
|
||||||
return new NoFiltersEditable(source);
|
return new NumberEditable(source);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
exponentButton.setOnClickListener(this);
|
exponentButton.setOnClickListener(this);
|
||||||
@ -397,9 +396,10 @@ public class EditVariableFragment extends BaseDialogFragment implements View.OnF
|
|||||||
keyboardWindow.show(new GreekFloatingKeyboard(keyboardUser), getDialog());
|
keyboardWindow.show(new GreekFloatingKeyboard(keyboardUser), getDialog());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class NoFiltersEditable extends SpannableStringBuilder {
|
private static class NumberEditable extends SpannableStringBuilder {
|
||||||
public NoFiltersEditable(CharSequence source) {
|
public NumberEditable(CharSequence source) {
|
||||||
super(source);
|
super(source);
|
||||||
|
super.setFilters(new InputFilter[]{NumberInputFilter.getInstance()});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,176 @@
|
|||||||
|
package org.solovyev.android.text.method;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.text.InputFilter;
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
|
import android.text.Spanned;
|
||||||
|
|
||||||
|
public class NumberInputFilter implements InputFilter {
|
||||||
|
|
||||||
|
private static final int[] CHARS = new int[]{-1, -1, -1};
|
||||||
|
private static final int CHAR_SIGN = 0;
|
||||||
|
private static final int CHAR_POINT = 1;
|
||||||
|
private static final int CHAR_EXP = 2;
|
||||||
|
|
||||||
|
private static final char[] ACCEPTED = {'E', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '+', '.'};
|
||||||
|
private static final NumberInputFilter INSTANCE = new NumberInputFilter();
|
||||||
|
|
||||||
|
private static boolean isSignChar(final char c) {
|
||||||
|
return c == '-' || c == '+';
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isDecimalPointChar(final char c) {
|
||||||
|
return c == '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isExponentChar(final char c) {
|
||||||
|
return c == 'E';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a NumberInputFilter that accepts the digits 0 through 9.
|
||||||
|
*/
|
||||||
|
public static NumberInputFilter getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean accepted(char c) {
|
||||||
|
for (int i = ACCEPTED.length - 1; i >= 0; i--) {
|
||||||
|
if (ACCEPTED[i] == c) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharSequence filter(CharSequence source, int start, int end,
|
||||||
|
Spanned dest, int dstart, int dend) {
|
||||||
|
final CharSequence out = filterIllegalCharacters(source, start, end);
|
||||||
|
if (out != null) {
|
||||||
|
source = out;
|
||||||
|
start = 0;
|
||||||
|
end = out.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARS[CHAR_SIGN] = -1;
|
||||||
|
CHARS[CHAR_POINT] = -1;
|
||||||
|
CHARS[CHAR_EXP] = -1;
|
||||||
|
findChars(dest, 0, dstart, 0, CHARS);
|
||||||
|
findChars(dest, dend, dest.length(), end - start, CHARS);
|
||||||
|
|
||||||
|
SpannableStringBuilder filtered = null;
|
||||||
|
for (int i = end - 1; i >= start; i--) {
|
||||||
|
final char c = source.charAt(i);
|
||||||
|
|
||||||
|
boolean filter = false;
|
||||||
|
if (isSignChar(c)) {
|
||||||
|
if (i == start && dstart == 0) {
|
||||||
|
if (CHARS[CHAR_SIGN] >= 0) {
|
||||||
|
filter = true;
|
||||||
|
} else {
|
||||||
|
CHARS[CHAR_SIGN] = i + dstart;
|
||||||
|
}
|
||||||
|
} else if (CHARS[CHAR_EXP] == i + dstart - 1) {
|
||||||
|
// allow sign after exponent symbol
|
||||||
|
filter = false;
|
||||||
|
} else {
|
||||||
|
filter = true;
|
||||||
|
}
|
||||||
|
} else if (isDecimalPointChar(c)) {
|
||||||
|
if (CHARS[CHAR_POINT] >= 0) {
|
||||||
|
filter = true;
|
||||||
|
} else if (CHARS[CHAR_EXP] >= 0 && CHARS[CHAR_EXP] < i + dstart) {
|
||||||
|
// no decimal point after exponent
|
||||||
|
filter = true;
|
||||||
|
} else {
|
||||||
|
CHARS[CHAR_POINT] = i + dstart;
|
||||||
|
}
|
||||||
|
} else if (isExponentChar(c)) {
|
||||||
|
if (CHARS[CHAR_EXP] >= 0) {
|
||||||
|
filter = true;
|
||||||
|
} else if (CHARS[CHAR_POINT] >= 0 && CHARS[CHAR_POINT] > i + dstart) {
|
||||||
|
// no exponent before decimal point
|
||||||
|
filter = true;
|
||||||
|
} else {
|
||||||
|
CHARS[CHAR_EXP] = i + dstart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter) {
|
||||||
|
if (end == start + 1) {
|
||||||
|
return ""; // Only one character, and it was stripped.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filtered == null) {
|
||||||
|
filtered = new SpannableStringBuilder(source, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
filtered.delete(i - start, i + 1 - start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filtered != null) {
|
||||||
|
return filtered;
|
||||||
|
} else if (out != null) {
|
||||||
|
return out;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void findChars(@NonNull Spanned s, int start, int end, int offset, int[] out) {
|
||||||
|
for (int i = start; i < end; i++) {
|
||||||
|
final char c = s.charAt(i);
|
||||||
|
|
||||||
|
if (isSignChar(c)) {
|
||||||
|
if (out[CHAR_SIGN] == -1 && out[CHAR_EXP] == -1) {
|
||||||
|
// count in only signs before exponent
|
||||||
|
out[CHAR_SIGN] = i + offset;
|
||||||
|
}
|
||||||
|
} else if (isDecimalPointChar(c)) {
|
||||||
|
if (out[CHAR_POINT] == -1) {
|
||||||
|
out[CHAR_POINT] = i + offset;
|
||||||
|
}
|
||||||
|
} else if (isExponentChar(c)) {
|
||||||
|
if (out[CHAR_EXP] == -1) {
|
||||||
|
out[CHAR_EXP] = i + offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private CharSequence filterIllegalCharacters(CharSequence source, int start, int end) {
|
||||||
|
final int illegal = findIllegalChar(source, start, end);
|
||||||
|
if (illegal == end) {
|
||||||
|
// all OK
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (end - start == 1) {
|
||||||
|
// it was not OK, and there is only one char, so nothing remains.
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
final SpannableStringBuilder filtered = new SpannableStringBuilder(source, start, end);
|
||||||
|
final int newEnd = end - start - 1;
|
||||||
|
// only count down to "illegal" because the chars before that were all OK.
|
||||||
|
final int newIllegal = illegal - start;
|
||||||
|
for (int j = newEnd; j >= newIllegal; j--) {
|
||||||
|
if (!accepted(source.charAt(j))) {
|
||||||
|
filtered.delete(j, j + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int findIllegalChar(CharSequence s, int start, int end) {
|
||||||
|
for (int i = start; i < end; i++) {
|
||||||
|
if (!accepted(s.charAt(i))) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user