Merge remote-tracking branch 'origin/master'
@ -34,7 +34,6 @@ android {
|
|||||||
versionCode 148
|
versionCode 148
|
||||||
versionName '2.2.1'
|
versionName '2.2.1'
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
generatedDensities = []
|
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
@ -58,17 +57,13 @@ android {
|
|||||||
sourceCompatibility JavaVersion.VERSION_1_7
|
sourceCompatibility JavaVersion.VERSION_1_7
|
||||||
targetCompatibility JavaVersion.VERSION_1_7
|
targetCompatibility JavaVersion.VERSION_1_7
|
||||||
}
|
}
|
||||||
// This is handled for you by the 2.0+ Gradle Plugin
|
|
||||||
aaptOptions {
|
|
||||||
additionalParameters "--no-version-vectors"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
compile 'com.android.support:support-v4:23.2.1'
|
compile 'com.android.support:support-v4:23.3.0'
|
||||||
compile 'com.android.support:appcompat-v7:23.2.1'
|
compile 'com.android.support:appcompat-v7:23.3.0'
|
||||||
compile 'com.android.support:design:23.2.1'
|
compile 'com.android.support:design:23.3.0'
|
||||||
compile('ch.acra:acra:4.7.0') {
|
compile('ch.acra:acra:4.7.0') {
|
||||||
exclude group: 'org.json'
|
exclude group: 'org.json'
|
||||||
}
|
}
|
||||||
@ -105,7 +100,7 @@ dependencies {
|
|||||||
testCompile 'org.skyscreamer:jsonassert:1.2.3'
|
testCompile 'org.skyscreamer:jsonassert:1.2.3'
|
||||||
testCompile(name: 'org.apache.http.legacy', ext: 'jar')
|
testCompile(name: 'org.apache.http.legacy', ext: 'jar')
|
||||||
|
|
||||||
androidTestCompile 'com.android.support:support-annotations:23.2.1'
|
androidTestCompile 'com.android.support:support-annotations:23.3.0'
|
||||||
androidTestCompile 'com.android.support.test:runner:0.4.1'
|
androidTestCompile 'com.android.support.test:runner:0.4.1'
|
||||||
androidTestCompile 'com.android.support.test:rules:0.4.1'
|
androidTestCompile 'com.android.support.test:rules:0.4.1'
|
||||||
androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
|
androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
|
||||||
|
@ -25,11 +25,15 @@ package org.solovyev.android.calculator;
|
|||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
import com.squareup.otto.Bus;
|
import com.squareup.otto.Bus;
|
||||||
import dagger.Lazy;
|
import dagger.Lazy;
|
||||||
|
import jscl.math.Expression;
|
||||||
|
import jscl.math.Generic;
|
||||||
import org.solovyev.android.Check;
|
import org.solovyev.android.Check;
|
||||||
import org.solovyev.android.calculator.buttons.CppSpecialButton;
|
import org.solovyev.android.calculator.buttons.CppSpecialButton;
|
||||||
import org.solovyev.android.calculator.ga.Ga;
|
import org.solovyev.android.calculator.ga.Ga;
|
||||||
|
import org.solovyev.android.calculator.history.History;
|
||||||
import org.solovyev.android.calculator.math.MathType;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
import org.solovyev.android.calculator.memory.Memory;
|
import org.solovyev.android.calculator.memory.Memory;
|
||||||
|
|
||||||
@ -49,6 +53,8 @@ public class Keyboard implements SharedPreferences.OnSharedPreferenceChangeListe
|
|||||||
@Inject
|
@Inject
|
||||||
Display display;
|
Display display;
|
||||||
@Inject
|
@Inject
|
||||||
|
History history;
|
||||||
|
@Inject
|
||||||
Lazy<Memory> memory;
|
Lazy<Memory> memory;
|
||||||
@Inject
|
@Inject
|
||||||
Calculator calculator;
|
Calculator calculator;
|
||||||
@ -74,10 +80,21 @@ public class Keyboard implements SharedPreferences.OnSharedPreferenceChangeListe
|
|||||||
return vibrateOnKeypress;
|
return vibrateOnKeypress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean buttonPressed(@Nullable final String text) {
|
public boolean buttonPressed(@Nullable String text) {
|
||||||
if (TextUtils.isEmpty(text)) {
|
if (TextUtils.isEmpty(text)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (text.length() == 1) {
|
||||||
|
final char glyph = text.charAt(0);
|
||||||
|
final CppSpecialButton button = CppSpecialButton.getByGlyph(glyph);
|
||||||
|
if (button != null) {
|
||||||
|
ga.onButtonPressed(button.action);
|
||||||
|
handleSpecialAction(button);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ga.onButtonPressed(text);
|
ga.onButtonPressed(text);
|
||||||
if (!processSpecialAction(text)) {
|
if (!processSpecialAction(text)) {
|
||||||
processText(prepareText(text));
|
processText(prepareText(text));
|
||||||
@ -127,20 +144,32 @@ public class Keyboard implements SharedPreferences.OnSharedPreferenceChangeListe
|
|||||||
if (button == null) {
|
if (button == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
onSpecialButtonPressed(button);
|
handleSpecialAction(button);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onSpecialButtonPressed(@NonNull CppSpecialButton button) {
|
private void handleSpecialAction(@NonNull CppSpecialButton button) {
|
||||||
switch (button) {
|
switch (button) {
|
||||||
case history:
|
case history:
|
||||||
launcher.showHistory();
|
launcher.showHistory();
|
||||||
break;
|
break;
|
||||||
|
case history_undo:
|
||||||
|
history.undo();
|
||||||
|
break;
|
||||||
|
case history_redo:
|
||||||
|
history.redo();
|
||||||
|
break;
|
||||||
case cursor_right:
|
case cursor_right:
|
||||||
moveCursorRight();
|
editor.moveCursorRight();
|
||||||
|
break;
|
||||||
|
case cursor_to_end:
|
||||||
|
editor.setCursorOnEnd();
|
||||||
break;
|
break;
|
||||||
case cursor_left:
|
case cursor_left:
|
||||||
moveCursorLeft();
|
editor.moveCursorLeft();
|
||||||
|
break;
|
||||||
|
case cursor_to_start:
|
||||||
|
editor.setCursorOnStart();
|
||||||
break;
|
break;
|
||||||
case settings:
|
case settings:
|
||||||
launcher.showSettings();
|
launcher.showSettings();
|
||||||
@ -154,24 +183,48 @@ public class Keyboard implements SharedPreferences.OnSharedPreferenceChangeListe
|
|||||||
case memory:
|
case memory:
|
||||||
memory.get().requestValue();
|
memory.get().requestValue();
|
||||||
break;
|
break;
|
||||||
|
case memory_plus:
|
||||||
|
handleMemoryButton(true);
|
||||||
|
break;
|
||||||
|
case memory_minus:
|
||||||
|
handleMemoryButton(false);
|
||||||
|
break;
|
||||||
|
case memory_clear:
|
||||||
|
memory.get().clear();
|
||||||
|
break;
|
||||||
case erase:
|
case erase:
|
||||||
editor.erase();
|
editor.erase();
|
||||||
break;
|
break;
|
||||||
case paste:
|
case paste:
|
||||||
pasteButtonPressed();
|
final String text = clipboard.get().getText();
|
||||||
|
if (!TextUtils.isEmpty(text)) {
|
||||||
|
editor.insert(text);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case copy:
|
case copy:
|
||||||
copyButtonPressed();
|
bus.get().post(new Display.CopyOperation());
|
||||||
|
break;
|
||||||
|
case brackets_wrap:
|
||||||
|
handleBracketsWrap();
|
||||||
break;
|
break;
|
||||||
case equals:
|
case equals:
|
||||||
equalsButtonPressed();
|
equalsButtonPressed();
|
||||||
break;
|
break;
|
||||||
case clear:
|
case clear:
|
||||||
clearButtonPressed();
|
editor.clear();
|
||||||
break;
|
break;
|
||||||
case functions:
|
case functions:
|
||||||
launcher.showFunctions();
|
launcher.showFunctions();
|
||||||
break;
|
break;
|
||||||
|
case function_add:
|
||||||
|
launcher.showFunctionEditor();
|
||||||
|
break;
|
||||||
|
case var_add:
|
||||||
|
launcher.showConstantEditor();
|
||||||
|
break;
|
||||||
|
case plot_add:
|
||||||
|
launcher.plotDisplayedExpression();
|
||||||
|
break;
|
||||||
case open_app:
|
case open_app:
|
||||||
launcher.openApp();
|
launcher.openApp();
|
||||||
break;
|
break;
|
||||||
@ -181,6 +234,9 @@ public class Keyboard implements SharedPreferences.OnSharedPreferenceChangeListe
|
|||||||
case operators:
|
case operators:
|
||||||
launcher.showOperators();
|
launcher.showOperators();
|
||||||
break;
|
break;
|
||||||
|
case simplify:
|
||||||
|
calculator.simplify();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Check.shouldNotHappen();
|
Check.shouldNotHappen();
|
||||||
}
|
}
|
||||||
@ -200,36 +256,36 @@ public class Keyboard implements SharedPreferences.OnSharedPreferenceChangeListe
|
|||||||
editor.setText(state.text);
|
editor.setText(state.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void roundBracketsButtonPressed() {
|
public void handleBracketsWrap() {
|
||||||
EditorState viewState = editor.getState();
|
final EditorState state = editor.getState();
|
||||||
|
final int cursorPosition = state.selection;
|
||||||
final int cursorPosition = viewState.selection;
|
final CharSequence oldText = state.text;
|
||||||
final CharSequence oldText = viewState.text;
|
|
||||||
|
|
||||||
editor.setText("(" + oldText.subSequence(0, cursorPosition) + ")" + oldText.subSequence(cursorPosition, oldText.length()), cursorPosition + 2);
|
editor.setText("(" + oldText.subSequence(0, cursorPosition) + ")" + oldText.subSequence(cursorPosition, oldText.length()), cursorPosition + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pasteButtonPressed() {
|
private boolean handleMemoryButton(boolean plus) {
|
||||||
final String text = clipboard.get().getText();
|
final DisplayState state = display.getState();
|
||||||
if (!TextUtils.isEmpty(text)) {
|
if (!state.valid) {
|
||||||
editor.insert(text);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
Generic value = state.getResult();
|
||||||
|
if (value == null) {
|
||||||
public void clearButtonPressed() {
|
try {
|
||||||
editor.clear();
|
value = Expression.valueOf(state.text);
|
||||||
}
|
} catch (jscl.text.ParseException e) {
|
||||||
|
Log.w(App.TAG, e.getMessage(), e);
|
||||||
public void copyButtonPressed() {
|
}
|
||||||
bus.get().post(new Display.CopyOperation());
|
}
|
||||||
}
|
if (value == null) {
|
||||||
|
memory.get().requestShow();
|
||||||
public void moveCursorLeft() {
|
return false;
|
||||||
editor.moveCursorLeft();
|
}
|
||||||
}
|
if (plus) {
|
||||||
|
memory.get().add(value);
|
||||||
public void moveCursorRight() {
|
} else {
|
||||||
editor.moveCursorRight();
|
memory.get().subtract(value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -33,8 +33,6 @@ import android.support.annotation.*;
|
|||||||
import android.support.v7.view.ContextThemeWrapper;
|
import android.support.v7.view.ContextThemeWrapper;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import jscl.AngleUnit;
|
|
||||||
import jscl.NumeralBase;
|
|
||||||
import org.solovyev.android.Check;
|
import org.solovyev.android.Check;
|
||||||
import org.solovyev.android.calculator.about.AboutActivity;
|
import org.solovyev.android.calculator.about.AboutActivity;
|
||||||
import org.solovyev.android.calculator.functions.FunctionsActivity;
|
import org.solovyev.android.calculator.functions.FunctionsActivity;
|
||||||
@ -42,6 +40,7 @@ import org.solovyev.android.calculator.history.HistoryActivity;
|
|||||||
import org.solovyev.android.calculator.language.Languages;
|
import org.solovyev.android.calculator.language.Languages;
|
||||||
import org.solovyev.android.calculator.math.MathType;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
import org.solovyev.android.calculator.operators.OperatorsActivity;
|
import org.solovyev.android.calculator.operators.OperatorsActivity;
|
||||||
|
import org.solovyev.android.calculator.preferences.PreferenceEntry;
|
||||||
import org.solovyev.android.calculator.preferences.PreferencesActivity;
|
import org.solovyev.android.calculator.preferences.PreferencesActivity;
|
||||||
import org.solovyev.android.calculator.variables.VariablesActivity;
|
import org.solovyev.android.calculator.variables.VariablesActivity;
|
||||||
import org.solovyev.android.calculator.wizard.WizardActivity;
|
import org.solovyev.android.calculator.wizard.WizardActivity;
|
||||||
@ -285,7 +284,7 @@ public final class Preferences {
|
|||||||
return mode.getPreferenceNoError(preferences);
|
return mode.getPreferenceNoError(preferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Theme {
|
public enum Theme implements PreferenceEntry {
|
||||||
|
|
||||||
default_theme(R.style.Cpp_Theme_Gray),
|
default_theme(R.style.Cpp_Theme_Gray),
|
||||||
violet_theme(R.style.Cpp_Theme_Violet),
|
violet_theme(R.style.Cpp_Theme_Violet),
|
||||||
@ -294,12 +293,19 @@ public final class Preferences {
|
|||||||
metro_purple_theme(R.string.p_metro_purple_theme, R.style.Cpp_Theme_Metro_Purple, R.style.Cpp_Theme_Metro_Purple_Calculator, R.style.Cpp_Theme_Wizard, R.style.Cpp_Theme_Metro_Purple_Dialog, R.style.Cpp_Theme_Material_Dialog_Alert),
|
metro_purple_theme(R.string.p_metro_purple_theme, R.style.Cpp_Theme_Metro_Purple, R.style.Cpp_Theme_Metro_Purple_Calculator, R.style.Cpp_Theme_Wizard, R.style.Cpp_Theme_Metro_Purple_Dialog, R.style.Cpp_Theme_Material_Dialog_Alert),
|
||||||
metro_green_theme(R.string.p_metro_green_theme, R.style.Cpp_Theme_Metro_Green, R.style.Cpp_Theme_Metro_Green_Calculator, R.style.Cpp_Theme_Wizard, R.style.Cpp_Theme_Metro_Green_Dialog, R.style.Cpp_Theme_Material_Dialog_Alert),
|
metro_green_theme(R.string.p_metro_green_theme, R.style.Cpp_Theme_Metro_Green, R.style.Cpp_Theme_Metro_Green_Calculator, R.style.Cpp_Theme_Wizard, R.style.Cpp_Theme_Metro_Green_Dialog, R.style.Cpp_Theme_Material_Dialog_Alert),
|
||||||
material_theme(R.string.cpp_theme_dark, R.style.Cpp_Theme_Material, R.style.Cpp_Theme_Material_Calculator),
|
material_theme(R.string.cpp_theme_dark, R.style.Cpp_Theme_Material, R.style.Cpp_Theme_Material_Calculator),
|
||||||
|
material_black_theme(R.string.cpp_theme_black, R.style.Cpp_Theme_Material_Black, R.style.Cpp_Theme_Material_Black_Calculator) {
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public String getName(@NonNull Context context) {
|
||||||
|
return context.getString(name, material_theme.getName(context));
|
||||||
|
}
|
||||||
|
},
|
||||||
material_light_theme(R.string.cpp_theme_light, R.style.Cpp_Theme_Material_Light, R.style.Cpp_Theme_Material_Light_Calculator, R.style.Cpp_Theme_Wizard_Light, R.style.Cpp_Theme_Material_Light_Dialog, R.style.Cpp_Theme_Material_Light_Dialog_Alert);
|
material_light_theme(R.string.cpp_theme_light, R.style.Cpp_Theme_Material_Light, R.style.Cpp_Theme_Material_Light_Calculator, R.style.Cpp_Theme_Wizard_Light, R.style.Cpp_Theme_Material_Light_Dialog, R.style.Cpp_Theme_Material_Light_Dialog_Alert);
|
||||||
|
|
||||||
private static final SparseArray<TextColor> textColors = new SparseArray<>();
|
private static final SparseArray<TextColor> textColors = new SparseArray<>();
|
||||||
|
|
||||||
@StringRes
|
@StringRes
|
||||||
public final int name;
|
protected final int name;
|
||||||
@StyleRes
|
@StyleRes
|
||||||
public final int theme;
|
public final int theme;
|
||||||
@StyleRes
|
@StyleRes
|
||||||
@ -373,6 +379,18 @@ public final class Preferences {
|
|||||||
}
|
}
|
||||||
return textColor;
|
return textColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public String getName(@NonNull Context context) {
|
||||||
|
return context.getString(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public CharSequence getId() {
|
||||||
|
return name();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Mode {
|
public enum Mode {
|
||||||
|
@ -51,6 +51,7 @@ public enum CppButton {
|
|||||||
period(R.id.cpp_button_period, "."),
|
period(R.id.cpp_button_period, "."),
|
||||||
brackets(R.id.cpp_button_round_brackets, "()"),
|
brackets(R.id.cpp_button_round_brackets, "()"),
|
||||||
|
|
||||||
|
memory(R.id.cpp_button_memory, CppSpecialButton.memory),
|
||||||
settings(R.id.cpp_button_settings, CppSpecialButton.settings),
|
settings(R.id.cpp_button_settings, CppSpecialButton.settings),
|
||||||
settings_widget(R.id.cpp_button_settings_widget, CppSpecialButton.settings_widget),
|
settings_widget(R.id.cpp_button_settings_widget, CppSpecialButton.settings_widget),
|
||||||
like(R.id.cpp_button_like, CppSpecialButton.like),
|
like(R.id.cpp_button_like, CppSpecialButton.like),
|
||||||
@ -65,7 +66,7 @@ public enum CppButton {
|
|||||||
history(R.id.cpp_button_history, CppSpecialButton.history),
|
history(R.id.cpp_button_history, CppSpecialButton.history),
|
||||||
|
|
||||||
/*operations*/
|
/*operations*/
|
||||||
multiplication(R.id.cpp_button_multiplication, "*"),
|
multiplication(R.id.cpp_button_multiplication, "×"),
|
||||||
division(R.id.cpp_button_division, "/"),
|
division(R.id.cpp_button_division, "/"),
|
||||||
plus(R.id.cpp_button_plus, "+"),
|
plus(R.id.cpp_button_plus, "+"),
|
||||||
subtraction(R.id.cpp_button_subtraction, "−"),
|
subtraction(R.id.cpp_button_subtraction, "−"),
|
||||||
|
@ -29,48 +29,99 @@ import javax.annotation.Nullable;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
// see values/text_glyphs.xml for glyph constants
|
||||||
public enum CppSpecialButton {
|
public enum CppSpecialButton {
|
||||||
|
|
||||||
history("history"),
|
history("history"),
|
||||||
|
history_undo("↶", '\ue007'),
|
||||||
|
history_redo("↷", '\ue008'),
|
||||||
cursor_right("▷"),
|
cursor_right("▷"),
|
||||||
|
cursor_to_end(">>"),
|
||||||
cursor_left("◁"),
|
cursor_left("◁"),
|
||||||
|
cursor_to_start("<<"),
|
||||||
settings("settings"),
|
settings("settings"),
|
||||||
settings_widget("settings_widget"),
|
settings_widget("settings_widget"),
|
||||||
like("like"),
|
like("like"),
|
||||||
memory("memory"),
|
memory("memory"),
|
||||||
|
memory_plus("M+"),
|
||||||
|
memory_minus("M-"),
|
||||||
|
memory_clear("MC"),
|
||||||
erase("erase"),
|
erase("erase"),
|
||||||
paste("paste"),
|
paste("paste", '\uE000'),
|
||||||
copy("copy"),
|
copy("copy", '\uE001'),
|
||||||
|
brackets_wrap("(…)"),
|
||||||
equals("="),
|
equals("="),
|
||||||
clear("clear"),
|
clear("clear"),
|
||||||
functions("functions"),
|
functions("functions"),
|
||||||
|
function_add("+ƒ"),
|
||||||
|
var_add("+π"),
|
||||||
|
plot_add("+plot", '\uE009'),
|
||||||
open_app("open_app"),
|
open_app("open_app"),
|
||||||
vars("vars"),
|
vars("vars"),
|
||||||
operators("operators");
|
operators("operators"),
|
||||||
|
simplify("≡");
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private static Map<String, CppSpecialButton> buttonsByActions = new HashMap<>();
|
private static final Map<String, CppSpecialButton> buttonsByActions = new HashMap<>();
|
||||||
|
@Nonnull
|
||||||
|
private static final CppSpecialButton[] buttonsByGlyphs = new CppSpecialButton[values().length];
|
||||||
|
private static final char FIRST_GLYPH = '\uE000';
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public final String action;
|
public final String action;
|
||||||
|
public final char glyph;
|
||||||
|
|
||||||
CppSpecialButton(@Nonnull String action) {
|
CppSpecialButton(@Nonnull String action) {
|
||||||
|
this(action, (char) 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CppSpecialButton(@Nonnull String action, char glyph) {
|
||||||
this.action = action;
|
this.action = action;
|
||||||
|
this.glyph = glyph;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static CppSpecialButton getByAction(@Nonnull String action) {
|
public static CppSpecialButton getByAction(@Nonnull String action) {
|
||||||
initButtonsByActionsMap();
|
initButtonsByActions();
|
||||||
return buttonsByActions.get(action);
|
return buttonsByActions.get(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void initButtonsByActionsMap() {
|
private static void initButtonsByActions() {
|
||||||
Check.isMainThread();
|
Check.isMainThread();
|
||||||
if (!buttonsByActions.isEmpty()) {
|
if (!buttonsByActions.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (CppSpecialButton specialButton : values()) {
|
for (CppSpecialButton button : values()) {
|
||||||
buttonsByActions.put(specialButton.action, specialButton);
|
buttonsByActions.put(button.action, button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static CppSpecialButton getByGlyph(char glyph) {
|
||||||
|
initButtonsByGlyphs();
|
||||||
|
final int position = glyphToPosition(glyph);
|
||||||
|
if (position < 0 || position >= buttonsByGlyphs.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return buttonsByGlyphs[position];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int glyphToPosition(char glyph) {
|
||||||
|
return glyph - FIRST_GLYPH;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initButtonsByGlyphs() {
|
||||||
|
Check.isMainThread();
|
||||||
|
if (buttonsByGlyphs[0] != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (CppSpecialButton button : values()) {
|
||||||
|
if(button.glyph == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final int position = glyphToPosition(button.glyph);
|
||||||
|
Check.isNull(buttonsByGlyphs[position], "Glyph is already taken, glyph=" + button.glyph);
|
||||||
|
buttonsByGlyphs[position] = button;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,14 +7,16 @@ import android.content.SharedPreferences;
|
|||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import dagger.Lazy;
|
import dagger.Lazy;
|
||||||
|
import org.solovyev.android.Check;
|
||||||
import org.solovyev.android.calculator.*;
|
import org.solovyev.android.calculator.*;
|
||||||
import org.solovyev.android.calculator.buttons.CppSpecialButton;
|
import org.solovyev.android.calculator.buttons.CppButton;
|
||||||
import org.solovyev.android.calculator.memory.Memory;
|
import org.solovyev.android.calculator.memory.Memory;
|
||||||
import org.solovyev.android.views.Adjuster;
|
import org.solovyev.android.views.Adjuster;
|
||||||
import org.solovyev.android.views.dragbutton.*;
|
import org.solovyev.android.views.dragbutton.*;
|
||||||
@ -65,7 +67,18 @@ public abstract class BaseKeyboardUi implements SharedPreferences.OnSharedPrefer
|
|||||||
listener = new DirectionDragListener(application) {
|
listener = new DirectionDragListener(application) {
|
||||||
@Override
|
@Override
|
||||||
protected boolean onDrag(@NonNull View view, @NonNull DragEvent event, @NonNull DragDirection direction) {
|
protected boolean onDrag(@NonNull View view, @NonNull DragEvent event, @NonNull DragDirection direction) {
|
||||||
return Drag.hasDirectionText(view, direction) && BaseKeyboardUi.this.onDrag(view, direction);
|
if (!Drag.hasDirectionText(view, direction)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final DirectionDragView dragView = (DirectionDragView) view;
|
||||||
|
final String text = dragView.getText(direction).getValue();
|
||||||
|
if (TextUtils.isEmpty(text)) {
|
||||||
|
// hasDirectionText should return false for empty text
|
||||||
|
Check.shouldNotHappen();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
keyboard.buttonPressed(text);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
textScale = getTextScale(application);
|
textScale = getTextScale(application);
|
||||||
@ -82,7 +95,15 @@ public abstract class BaseKeyboardUi implements SharedPreferences.OnSharedPrefer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract boolean onDrag(@NonNull View view, @NonNull DragDirection direction);
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
final CppButton button = CppButton.getById(v.getId());
|
||||||
|
if (button == null) {
|
||||||
|
Check.shouldNotHappen();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onClick(v, button.action);
|
||||||
|
}
|
||||||
|
|
||||||
public void onCreateView(@Nonnull Activity activity, @Nonnull View view) {
|
public void onCreateView(@Nonnull Activity activity, @Nonnull View view) {
|
||||||
cast(activity.getApplication()).getComponent().inject(this);
|
cast(activity.getApplication()).getComponent().inject(this);
|
||||||
@ -194,10 +215,6 @@ public abstract class BaseKeyboardUi implements SharedPreferences.OnSharedPrefer
|
|||||||
v.performHapticFeedback(KEYBOARD_TAP, FLAG_IGNORE_GLOBAL_SETTING | FLAG_IGNORE_VIEW_SETTING);
|
v.performHapticFeedback(KEYBOARD_TAP, FLAG_IGNORE_GLOBAL_SETTING | FLAG_IGNORE_VIEW_SETTING);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final void onClick(@Nonnull View v, @Nonnull CppSpecialButton b) {
|
|
||||||
onClick(v, b.action);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class AdjusterHelper implements Adjuster.Helper<DirectionDragImageButton> {
|
private static class AdjusterHelper implements Adjuster.Helper<DirectionDragImageButton> {
|
||||||
|
|
||||||
public static AdjusterHelper instance = new AdjusterHelper();
|
public static AdjusterHelper instance = new AdjusterHelper();
|
||||||
|
@ -3,31 +3,23 @@ package org.solovyev.android.calculator.keyboard;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import butterknife.Bind;
|
import butterknife.Bind;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import jscl.NumeralBase;
|
import jscl.NumeralBase;
|
||||||
import jscl.math.Expression;
|
import org.solovyev.android.calculator.Display;
|
||||||
import jscl.math.Generic;
|
import org.solovyev.android.calculator.Engine;
|
||||||
import org.solovyev.android.calculator.*;
|
import org.solovyev.android.calculator.R;
|
||||||
import org.solovyev.android.calculator.buttons.CppSpecialButton;
|
|
||||||
import org.solovyev.android.calculator.history.History;
|
|
||||||
import org.solovyev.android.calculator.view.AngleUnitsButton;
|
|
||||||
import org.solovyev.android.calculator.view.NumeralBasesButton;
|
|
||||||
import org.solovyev.android.views.dragbutton.DirectionDragButton;
|
import org.solovyev.android.views.dragbutton.DirectionDragButton;
|
||||||
import org.solovyev.android.views.dragbutton.DirectionDragImageButton;
|
import org.solovyev.android.views.dragbutton.DirectionDragImageButton;
|
||||||
import org.solovyev.android.views.dragbutton.DirectionDragView;
|
|
||||||
import org.solovyev.android.views.dragbutton.DragDirection;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static org.solovyev.android.calculator.Engine.Preferences.*;
|
import static org.solovyev.android.calculator.Engine.Preferences.multiplicationSign;
|
||||||
|
import static org.solovyev.android.calculator.Engine.Preferences.numeralBase;
|
||||||
import static org.solovyev.android.views.dragbutton.DragDirection.*;
|
import static org.solovyev.android.views.dragbutton.DragDirection.*;
|
||||||
|
|
||||||
public class KeyboardUi extends BaseKeyboardUi {
|
public class KeyboardUi extends BaseKeyboardUi {
|
||||||
@ -53,10 +45,6 @@ public class KeyboardUi extends BaseKeyboardUi {
|
|||||||
@Bind(R.id.cpp_button_9)
|
@Bind(R.id.cpp_button_9)
|
||||||
public DirectionDragButton button9;
|
public DirectionDragButton button9;
|
||||||
@Inject
|
@Inject
|
||||||
History history;
|
|
||||||
@Inject
|
|
||||||
ActivityLauncher launcher;
|
|
||||||
@Inject
|
|
||||||
Engine engine;
|
Engine engine;
|
||||||
@Inject
|
@Inject
|
||||||
Display display;
|
Display display;
|
||||||
@ -85,10 +73,10 @@ public class KeyboardUi extends BaseKeyboardUi {
|
|||||||
DirectionDragButton bracketsButton;
|
DirectionDragButton bracketsButton;
|
||||||
@Nullable
|
@Nullable
|
||||||
@Bind(R.id.cpp_button_copy)
|
@Bind(R.id.cpp_button_copy)
|
||||||
NumeralBasesButton copyButton;
|
DirectionDragImageButton copyButton;
|
||||||
@Nullable
|
@Nullable
|
||||||
@Bind(R.id.cpp_button_paste)
|
@Bind(R.id.cpp_button_paste)
|
||||||
AngleUnitsButton pasteButton;
|
DirectionDragImageButton pasteButton;
|
||||||
@Nullable
|
@Nullable
|
||||||
@Bind(R.id.cpp_button_like)
|
@Bind(R.id.cpp_button_like)
|
||||||
ImageButton likeButton;
|
ImageButton likeButton;
|
||||||
@ -146,11 +134,9 @@ public class KeyboardUi extends BaseKeyboardUi {
|
|||||||
|
|
||||||
if (copyButton != null) {
|
if (copyButton != null) {
|
||||||
prepareButton(copyButton);
|
prepareButton(copyButton);
|
||||||
copyButton.setNumeralBase(numeralBase.getPreference(preferences));
|
|
||||||
}
|
}
|
||||||
if (pasteButton != null) {
|
if (pasteButton != null) {
|
||||||
prepareButton(pasteButton);
|
prepareButton(pasteButton);
|
||||||
pasteButton.setAngleUnit(angleUnit.getPreference(preferences));
|
|
||||||
}
|
}
|
||||||
prepareButton(likeButton);
|
prepareButton(likeButton);
|
||||||
prepareButton(memoryButton);
|
prepareButton(memoryButton);
|
||||||
@ -182,133 +168,11 @@ public class KeyboardUi extends BaseKeyboardUi {
|
|||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
|
||||||
super.onSharedPreferenceChanged(preferences, key);
|
super.onSharedPreferenceChanged(preferences, key);
|
||||||
if (angleUnit.isSameKey(key) && pasteButton != null) {
|
|
||||||
pasteButton.setAngleUnit(angleUnit.getPreference(preferences));
|
|
||||||
}
|
|
||||||
if (numeralBase.isSameKey(key)) {
|
if (numeralBase.isSameKey(key)) {
|
||||||
toggleNumericDigits();
|
toggleNumericDigits();
|
||||||
if (copyButton != null) {
|
|
||||||
copyButton.setNumeralBase(numeralBase.getPreference(preferences));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (multiplicationSign.isSameKey(key)) {
|
if (multiplicationSign.isSameKey(key)) {
|
||||||
multiplicationButton.setText(multiplicationSign.getPreference(preferences));
|
multiplicationButton.setText(multiplicationSign.getPreference(preferences));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
switch (v.getId()) {
|
|
||||||
case R.id.cpp_button_0:
|
|
||||||
case R.id.cpp_button_1:
|
|
||||||
case R.id.cpp_button_2:
|
|
||||||
case R.id.cpp_button_3:
|
|
||||||
case R.id.cpp_button_4:
|
|
||||||
case R.id.cpp_button_5:
|
|
||||||
case R.id.cpp_button_6:
|
|
||||||
case R.id.cpp_button_7:
|
|
||||||
case R.id.cpp_button_8:
|
|
||||||
case R.id.cpp_button_9:
|
|
||||||
case R.id.cpp_button_division:
|
|
||||||
case R.id.cpp_button_period:
|
|
||||||
case R.id.cpp_button_percent:
|
|
||||||
case R.id.cpp_button_subtraction:
|
|
||||||
case R.id.cpp_button_multiplication:
|
|
||||||
case R.id.cpp_button_plus:
|
|
||||||
case R.id.cpp_button_round_brackets:
|
|
||||||
onClick(v, ((Button) v).getText().toString());
|
|
||||||
break;
|
|
||||||
case R.id.cpp_button_functions:
|
|
||||||
onClick(v, CppSpecialButton.functions);
|
|
||||||
break;
|
|
||||||
case R.id.cpp_button_history:
|
|
||||||
onClick(v, CppSpecialButton.history);
|
|
||||||
break;
|
|
||||||
case R.id.cpp_button_paste:
|
|
||||||
onClick(v, CppSpecialButton.paste);
|
|
||||||
break;
|
|
||||||
case R.id.cpp_button_copy:
|
|
||||||
onClick(v, CppSpecialButton.copy);
|
|
||||||
break;
|
|
||||||
case R.id.cpp_button_like:
|
|
||||||
onClick(v, CppSpecialButton.like);
|
|
||||||
break;
|
|
||||||
case R.id.cpp_button_memory:
|
|
||||||
onClick(v, CppSpecialButton.memory);
|
|
||||||
break;
|
|
||||||
case R.id.cpp_button_operators:
|
|
||||||
onClick(v, CppSpecialButton.operators);
|
|
||||||
break;
|
|
||||||
case R.id.cpp_button_vars:
|
|
||||||
onClick(v, CppSpecialButton.vars);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean onDrag(@NonNull View view, @NonNull DragDirection direction) {
|
|
||||||
switch (view.getId()) {
|
|
||||||
case R.id.cpp_button_functions:
|
|
||||||
if (direction == up) {
|
|
||||||
launcher.showFunctionEditor();
|
|
||||||
return true;
|
|
||||||
} else if (direction == down) {
|
|
||||||
launcher.showConstantEditor();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
case R.id.cpp_button_history:
|
|
||||||
if (direction == up) {
|
|
||||||
history.undo();
|
|
||||||
return true;
|
|
||||||
} else if (direction == down) {
|
|
||||||
history.redo();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
case R.id.cpp_button_memory:
|
|
||||||
return processMemoryButton(direction);
|
|
||||||
case R.id.cpp_button_round_brackets:
|
|
||||||
if (direction == left) {
|
|
||||||
keyboard.roundBracketsButtonPressed();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return processDefault(direction, (DirectionDragView) view);
|
|
||||||
default:
|
|
||||||
return processDefault(direction, (DirectionDragView) view);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean processMemoryButton(@NonNull DragDirection direction) {
|
|
||||||
final DisplayState state = display.getState();
|
|
||||||
if (!state.valid) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Generic value = state.getResult();
|
|
||||||
if (value == null) {
|
|
||||||
try {
|
|
||||||
value = Expression.valueOf(state.text);
|
|
||||||
} catch (jscl.text.ParseException e) {
|
|
||||||
Log.w(App.TAG, e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (value == null) {
|
|
||||||
memory.get().requestShow();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
switch (direction) {
|
|
||||||
case up:
|
|
||||||
memory.get().add(value);
|
|
||||||
return true;
|
|
||||||
case down:
|
|
||||||
memory.get().subtract(value);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean processDefault(@Nonnull DragDirection direction, @Nonnull DirectionDragView button) {
|
|
||||||
final String text = button.getText(direction).getValue();
|
|
||||||
return keyboard.buttonPressed(text);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -10,18 +10,15 @@ import android.widget.ImageButton;
|
|||||||
import butterknife.Bind;
|
import butterknife.Bind;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
import org.solovyev.android.calculator.buttons.CppSpecialButton;
|
|
||||||
import org.solovyev.android.calculator.view.EditorLongClickEraser;
|
import org.solovyev.android.calculator.view.EditorLongClickEraser;
|
||||||
import org.solovyev.android.views.dragbutton.DirectionDragButton;
|
import org.solovyev.android.views.dragbutton.DirectionDragButton;
|
||||||
import org.solovyev.android.views.dragbutton.DirectionDragImageButton;
|
import org.solovyev.android.views.dragbutton.DirectionDragImageButton;
|
||||||
import org.solovyev.android.views.dragbutton.DragDirection;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static org.solovyev.android.calculator.Preferences.Gui.vibrateOnKeypress;
|
import static org.solovyev.android.calculator.Preferences.Gui.vibrateOnKeypress;
|
||||||
import static org.solovyev.android.views.dragbutton.DragDirection.down;
|
import static org.solovyev.android.views.dragbutton.DragDirection.down;
|
||||||
import static org.solovyev.android.views.dragbutton.DragDirection.up;
|
|
||||||
|
|
||||||
public class PartialKeyboardUi extends BaseKeyboardUi {
|
public class PartialKeyboardUi extends BaseKeyboardUi {
|
||||||
|
|
||||||
@ -73,54 +70,4 @@ public class PartialKeyboardUi extends BaseKeyboardUi {
|
|||||||
longClickEraser.setVibrateOnKeypress(vibrateOnKeypress.getPreference(preferences));
|
longClickEraser.setVibrateOnKeypress(vibrateOnKeypress.getPreference(preferences));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean onDrag(@NonNull View view, @NonNull DragDirection direction) {
|
|
||||||
switch (view.getId()) {
|
|
||||||
case R.id.cpp_button_right:
|
|
||||||
editor.setCursorOnEnd();
|
|
||||||
return true;
|
|
||||||
case R.id.cpp_button_left:
|
|
||||||
editor.setCursorOnStart();
|
|
||||||
return true;
|
|
||||||
case R.id.cpp_button_clear:
|
|
||||||
if(direction == up) {
|
|
||||||
memory.get().clear();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
case R.id.cpp_button_equals:
|
|
||||||
if (direction == down) {
|
|
||||||
launcher.plotDisplayedExpression();
|
|
||||||
return true;
|
|
||||||
} else if (direction == up) {
|
|
||||||
calculator.simplify();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
switch (v.getId()) {
|
|
||||||
case R.id.cpp_button_left:
|
|
||||||
onClick(v, CppSpecialButton.cursor_left);
|
|
||||||
break;
|
|
||||||
case R.id.cpp_button_right:
|
|
||||||
onClick(v, CppSpecialButton.cursor_right);
|
|
||||||
break;
|
|
||||||
case R.id.cpp_button_clear:
|
|
||||||
onClick(v, CppSpecialButton.clear);
|
|
||||||
break;
|
|
||||||
case R.id.cpp_button_erase:
|
|
||||||
onClick(v, CppSpecialButton.erase);
|
|
||||||
break;
|
|
||||||
case R.id.cpp_button_equals:
|
|
||||||
onClick(v, CppSpecialButton.equals);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
package org.solovyev.android.calculator.language;
|
package org.solovyev.android.calculator.language;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
|
import org.solovyev.android.calculator.preferences.PreferenceEntry;
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
public final class Language {
|
public final class Language implements PreferenceEntry{
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public final String code;
|
public final String code;
|
||||||
|
|
||||||
@ -39,6 +39,7 @@ public final class Language {
|
|||||||
return locale.getDisplayName(locale);
|
return locale.getDisplayName(locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public String getName(@Nonnull Context context) {
|
public String getName(@Nonnull Context context) {
|
||||||
if (!isSystem()) {
|
if (!isSystem()) {
|
||||||
@ -48,6 +49,12 @@ public final class Language {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public CharSequence getId() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isSystem() {
|
public boolean isSystem() {
|
||||||
return code.equals(Languages.SYSTEM_LANGUAGE_CODE);
|
return code.equals(Languages.SYSTEM_LANGUAGE_CODE);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
package org.solovyev.android.calculator.preferences;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
public interface PreferenceEntry {
|
||||||
|
@NonNull
|
||||||
|
CharSequence getName(@NonNull Context context);
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
CharSequence getId();
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package org.solovyev.android.calculator.preferences;
|
package org.solovyev.android.calculator.preferences;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
@ -13,6 +14,7 @@ import android.widget.ListView;
|
|||||||
import org.solovyev.android.calculator.AdView;
|
import org.solovyev.android.calculator.AdView;
|
||||||
import org.solovyev.android.calculator.Engine;
|
import org.solovyev.android.calculator.Engine;
|
||||||
import org.solovyev.android.calculator.Preferences;
|
import org.solovyev.android.calculator.Preferences;
|
||||||
|
import org.solovyev.android.calculator.Preferences.Gui.Theme;
|
||||||
import org.solovyev.android.calculator.R;
|
import org.solovyev.android.calculator.R;
|
||||||
import org.solovyev.android.calculator.language.Language;
|
import org.solovyev.android.calculator.language.Language;
|
||||||
import org.solovyev.android.calculator.language.Languages;
|
import org.solovyev.android.calculator.language.Languages;
|
||||||
@ -25,6 +27,7 @@ import org.solovyev.android.wizard.Wizards;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.solovyev.android.calculator.App.cast;
|
import static org.solovyev.android.calculator.App.cast;
|
||||||
@ -154,32 +157,50 @@ public class PreferencesFragment extends org.solovyev.android.material.preferenc
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final ListPreference theme = (ListPreference) preferenceManager.findPreference(Preferences.Gui.theme.getKey());
|
final ListPreference theme = (ListPreference) preferenceManager.findPreference(Preferences.Gui.theme.getKey());
|
||||||
theme.setSummary(Preferences.Gui.getTheme(preferences).name);
|
final FragmentActivity context = getActivity();
|
||||||
|
populate(theme,
|
||||||
|
Theme.material_theme,
|
||||||
|
Theme.material_black_theme,
|
||||||
|
Theme.material_light_theme,
|
||||||
|
Theme.metro_blue_theme,
|
||||||
|
Theme.metro_green_theme,
|
||||||
|
Theme.metro_purple_theme);
|
||||||
|
theme.setSummary(Preferences.Gui.getTheme(preferences).getName(context));
|
||||||
theme.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
theme.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
theme.setSummary(Preferences.Gui.Theme.valueOf((String) newValue).name);
|
final Theme newTheme = Theme.valueOf((String) newValue);
|
||||||
|
theme.setSummary(newTheme.getName(context));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void populate(@Nonnull ListPreference preference, @Nonnull PreferenceEntry... entries) {
|
||||||
|
populate(preference, Arrays.asList(entries));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void populate(@Nonnull ListPreference preference, @Nonnull List<? extends PreferenceEntry> entries) {
|
||||||
|
final int size = entries.size();
|
||||||
|
final CharSequence[] e = new CharSequence[size];
|
||||||
|
final CharSequence[] v = new CharSequence[size];
|
||||||
|
final Context context = preference.getContext();
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
final PreferenceEntry entry = entries.get(i);
|
||||||
|
e[i] = entry.getName(context);
|
||||||
|
v[i] = entry.getId();
|
||||||
|
}
|
||||||
|
preference.setEntries(e);
|
||||||
|
preference.setEntryValues(v);
|
||||||
|
}
|
||||||
|
|
||||||
private void prepareLanguagePreference(int preference) {
|
private void prepareLanguagePreference(int preference) {
|
||||||
if (preference != R.xml.preferences_appearance) {
|
if (preference != R.xml.preferences_appearance) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ListPreference language = (ListPreference) preferenceManager.findPreference(Preferences.Gui.language.getKey());
|
final ListPreference language = (ListPreference) preferenceManager.findPreference(Preferences.Gui.language.getKey());
|
||||||
final List<Language> languagesList = languages.getList();
|
populate(language, languages.getList());
|
||||||
final CharSequence[] entries = new CharSequence[languagesList.size()];
|
|
||||||
final CharSequence[] entryValues = new CharSequence[languagesList.size()];
|
|
||||||
for (int i = 0; i < languagesList.size(); i++) {
|
|
||||||
final Language l = languagesList.get(i);
|
|
||||||
entries[i] = l.getName(getActivity());
|
|
||||||
entryValues[i] = l.code;
|
|
||||||
}
|
|
||||||
language.setEntries(entries);
|
|
||||||
language.setEntryValues(entryValues);
|
|
||||||
language.setSummary(languages.getCurrent().getName(getActivity()));
|
language.setSummary(languages.getCurrent().getName(getActivity()));
|
||||||
language.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
language.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013 serso aka se.solovyev
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
* Contact details
|
|
||||||
*
|
|
||||||
* Email: se.solovyev@gmail.com
|
|
||||||
* Site: http://se.solovyev.org
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.solovyev.android.calculator.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.support.v4.content.ContextCompat;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import jscl.AngleUnit;
|
|
||||||
import org.solovyev.android.calculator.R;
|
|
||||||
import org.solovyev.android.views.dragbutton.DirectionDragImageButton;
|
|
||||||
import org.solovyev.android.views.dragbutton.DirectionTextView;
|
|
||||||
import org.solovyev.android.views.dragbutton.DragDirection;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
public class AngleUnitsButton extends DirectionDragImageButton {
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private AngleUnit angleUnit = AngleUnit.deg;
|
|
||||||
|
|
||||||
public AngleUnitsButton(Context context, @Nonnull AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
updateDirectionColors();
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isCurrentAngleUnits(@Nonnull String directionText) {
|
|
||||||
return angleUnit.name().equals(directionText);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAngleUnit(@Nonnull AngleUnit angleUnit) {
|
|
||||||
if (this.angleUnit == angleUnit) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.angleUnit = angleUnit;
|
|
||||||
updateDirectionColors();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateDirectionColors() {
|
|
||||||
for (DragDirection direction : DragDirection.values()) {
|
|
||||||
final DirectionTextView.Text text = getText(direction);
|
|
||||||
if (isCurrentAngleUnits(text.getValue())) {
|
|
||||||
text.setColor(ContextCompat.getColor(getContext(), R.color.yellow_100), 1f);
|
|
||||||
} else {
|
|
||||||
text.setColor(ContextCompat.getColor(getContext(), R.color.cpp_text), DirectionTextView.DEF_ALPHA);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2013 serso aka se.solovyev
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
* Contact details
|
|
||||||
*
|
|
||||||
* Email: se.solovyev@gmail.com
|
|
||||||
* Site: http://se.solovyev.org
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.solovyev.android.calculator.view;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.support.v4.content.ContextCompat;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import jscl.NumeralBase;
|
|
||||||
import org.solovyev.android.calculator.R;
|
|
||||||
import org.solovyev.android.views.dragbutton.DirectionDragImageButton;
|
|
||||||
import org.solovyev.android.views.dragbutton.DirectionTextView;
|
|
||||||
import org.solovyev.android.views.dragbutton.DragDirection;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
public class NumeralBasesButton extends DirectionDragImageButton {
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private NumeralBase numeralBase = NumeralBase.dec;
|
|
||||||
|
|
||||||
public NumeralBasesButton(Context context, @Nonnull AttributeSet attrs) {
|
|
||||||
super(context, attrs);
|
|
||||||
updateDirectionColors();
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean isCurrentNumberBase(@Nonnull String directionText) {
|
|
||||||
return numeralBase.name().equals(directionText);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNumeralBase(@Nonnull NumeralBase numeralBase) {
|
|
||||||
if (this.numeralBase == numeralBase) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.numeralBase = numeralBase;
|
|
||||||
updateDirectionColors();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateDirectionColors() {
|
|
||||||
for (DragDirection direction : DragDirection.values()) {
|
|
||||||
final DirectionTextView.Text text = getText(direction);
|
|
||||||
if (isCurrentNumberBase(text.getValue())) {
|
|
||||||
text.setColor(ContextCompat.getColor(getContext(), R.color.yellow_100), 1f);
|
|
||||||
} else {
|
|
||||||
text.setColor(ContextCompat.getColor(getContext(), R.color.cpp_text), DirectionTextView.DEF_ALPHA);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -23,7 +23,6 @@
|
|||||||
package org.solovyev.android.calculator.wizard;
|
package org.solovyev.android.calculator.wizard;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.StringRes;
|
|
||||||
import android.support.v7.view.ContextThemeWrapper;
|
import android.support.v7.view.ContextThemeWrapper;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@ -58,11 +57,12 @@ public class ChooseThemeWizardStep extends WizardFragment implements AdapterView
|
|||||||
final Preferences.Gui.Theme theme = Preferences.Gui.getTheme(preferences);
|
final Preferences.Gui.Theme theme = Preferences.Gui.getTheme(preferences);
|
||||||
final Spinner spinner = (Spinner) root.findViewById(R.id.wizard_theme_spinner);
|
final Spinner spinner = (Spinner) root.findViewById(R.id.wizard_theme_spinner);
|
||||||
themes.clear();
|
themes.clear();
|
||||||
themes.add(new ThemeUi(Preferences.Gui.Theme.material_theme, R.string.cpp_theme_dark));
|
themes.add(new ThemeUi(Preferences.Gui.Theme.material_theme));
|
||||||
themes.add(new ThemeUi(Preferences.Gui.Theme.material_light_theme, R.string.cpp_theme_light));
|
themes.add(new ThemeUi(Preferences.Gui.Theme.material_black_theme));
|
||||||
themes.add(new ThemeUi(Preferences.Gui.Theme.metro_blue_theme, R.string.p_metro_blue_theme));
|
themes.add(new ThemeUi(Preferences.Gui.Theme.material_light_theme));
|
||||||
themes.add(new ThemeUi(Preferences.Gui.Theme.metro_green_theme, R.string.p_metro_green_theme));
|
themes.add(new ThemeUi(Preferences.Gui.Theme.metro_blue_theme));
|
||||||
themes.add(new ThemeUi(Preferences.Gui.Theme.metro_purple_theme, R.string.p_metro_purple_theme));
|
themes.add(new ThemeUi(Preferences.Gui.Theme.metro_green_theme));
|
||||||
|
themes.add(new ThemeUi(Preferences.Gui.Theme.metro_purple_theme));
|
||||||
adapter = new WizardArrayAdapter<>(getActivity(), themes);
|
adapter = new WizardArrayAdapter<>(getActivity(), themes);
|
||||||
spinner.setAdapter(adapter);
|
spinner.setAdapter(adapter);
|
||||||
spinner.setSelection(findPosition(theme));
|
spinner.setSelection(findPosition(theme));
|
||||||
@ -111,9 +111,9 @@ public class ChooseThemeWizardStep extends WizardFragment implements AdapterView
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
final String name;
|
final String name;
|
||||||
|
|
||||||
public ThemeUi(@Nonnull Preferences.Gui.Theme theme, @StringRes int name) {
|
public ThemeUi(@Nonnull Preferences.Gui.Theme theme) {
|
||||||
this.theme = theme;
|
this.theme = theme;
|
||||||
this.name = getString(name);
|
this.name = theme.getName(getActivity());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -61,7 +61,7 @@ public class NumberInputFilter implements InputFilter {
|
|||||||
findChars(dest, dend, dest.length(), end - start, CHARS);
|
findChars(dest, dend, dest.length(), end - start, CHARS);
|
||||||
|
|
||||||
SpannableStringBuilder filtered = null;
|
SpannableStringBuilder filtered = null;
|
||||||
for (int i = end - 1; i >= start; i--) {
|
for (int i = start; i < end; i++) {
|
||||||
final char c = source.charAt(i);
|
final char c = source.charAt(i);
|
||||||
|
|
||||||
boolean filter = false;
|
boolean filter = false;
|
||||||
@ -93,6 +93,9 @@ public class NumberInputFilter implements InputFilter {
|
|||||||
} else if (CHARS[CHAR_POINT] >= 0 && CHARS[CHAR_POINT] > i + dstart) {
|
} else if (CHARS[CHAR_POINT] >= 0 && CHARS[CHAR_POINT] > i + dstart) {
|
||||||
// no exponent before decimal point
|
// no exponent before decimal point
|
||||||
filter = true;
|
filter = true;
|
||||||
|
} else if (i + dstart == 0) {
|
||||||
|
// exponent can't be first
|
||||||
|
filter = true;
|
||||||
} else {
|
} else {
|
||||||
CHARS[CHAR_EXP] = i + dstart;
|
CHARS[CHAR_EXP] = i + dstart;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package org.solovyev.android.views.dragbutton;
|
|||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
|
||||||
public interface DragView {
|
public interface DragView {
|
||||||
|
int getId();
|
||||||
void setOnDragListener(@Nullable DragListener listener);
|
void setOnDragListener(@Nullable DragListener listener);
|
||||||
void setVibrateOnDrag(boolean vibrateOnDrag);
|
void setVibrateOnDrag(boolean vibrateOnDrag);
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 226 B |
Before Width: | Height: | Size: 227 B |
Before Width: | Height: | Size: 164 B |
Before Width: | Height: | Size: 163 B |
32
app/src/main/res/drawable-v21/material_button_black.xml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ Copyright 2013 serso aka se.solovyev
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
~
|
||||||
|
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
~ Contact details
|
||||||
|
~
|
||||||
|
~ Email: se.solovyev@gmail.com
|
||||||
|
~ Site: http://se.solovyev.org
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ripple xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
|
a:color="@color/cpp_ripple_material_dark">
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<solid a:color="@color/grey_950" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</ripple>
|
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ Copyright 2013 serso aka se.solovyev
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
~
|
||||||
|
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
~ Contact details
|
||||||
|
~
|
||||||
|
~ Email: se.solovyev@gmail.com
|
||||||
|
~ Site: http://se.solovyev.org
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ripple xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
|
a:color="@color/cpp_ripple_material_dark">
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<solid a:color="@color/grey_900" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</ripple>
|
32
app/src/main/res/drawable-v21/material_button_deep_blue.xml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ Copyright 2013 serso aka se.solovyev
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
~
|
||||||
|
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
~ Contact details
|
||||||
|
~
|
||||||
|
~ Email: se.solovyev@gmail.com
|
||||||
|
~ Site: http://se.solovyev.org
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ripple xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
|
a:color="@color/cpp_ripple_material_dark">
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<solid a:color="@color/deep_blue_900" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</ripple>
|
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ Copyright 2013 serso aka se.solovyev
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
~
|
||||||
|
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
~ Contact details
|
||||||
|
~
|
||||||
|
~ Email: se.solovyev@gmail.com
|
||||||
|
~ Site: http://se.solovyev.org
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ripple xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
|
a:color="@color/cpp_ripple_material_dark">
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<solid a:color="@color/deep_blue_850" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</ripple>
|
Before Width: | Height: | Size: 203 B |
Before Width: | Height: | Size: 233 B |
Before Width: | Height: | Size: 285 B |
Before Width: | Height: | Size: 286 B |
Before Width: | Height: | Size: 349 B |
Before Width: | Height: | Size: 354 B |
@ -1,9 +1,9 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="24dp"
|
android:width="24dp"
|
||||||
android:height="24dp"
|
android:height="24dp"
|
||||||
android:viewportWidth="24.0"
|
android:viewportHeight="24.0"
|
||||||
android:viewportHeight="24.0">
|
android:viewportWidth="24.0">
|
||||||
<path
|
<path
|
||||||
android:fillColor="#ffffff"
|
android:fillColor="#ffffff"
|
||||||
android:pathData="M15.41,7.41L14,6l-6,6 6,6 1.41,-1.41L10.83,12z"/>
|
android:pathData="M15.41,7.41L14,6l-6,6 6,6 1.41,-1.41L10.83,12z" />
|
||||||
</vector>
|
</vector>
|
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="48dp"
|
||||||
|
android:height="48dp"
|
||||||
|
android:viewportHeight="24.0"
|
||||||
|
android:viewportWidth="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="M16.5,3c-1.74,0 -3.41,0.81 -4.5,2.09C10.91,3.81 9.24,3 7.5,3 4.42,3 2,5.42 2,8.5c0,3.78 3.4,6.86 8.55,11.54L12,21.35l1.45,-1.32C18.6,15.36 22,12.28 22,8.5 22,5.42 19.58,3 16.5,3zM12.1,18.55l-0.1,0.1 -0.1,-0.1C7.14,14.24 4,11.39 4,8.5 4,6.5 5.5,5 7.5,5c1.54,0 3.04,0.99 3.57,2.36h1.87C13.46,5.99 14.96,5 16.5,5c2,0 3.5,1.5 3.5,3.5 0,2.89 -3.14,5.74 -7.9,10.05z" />
|
||||||
|
</vector>
|
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="48dp"
|
||||||
|
android:height="48dp"
|
||||||
|
android:viewportHeight="24.0"
|
||||||
|
android:viewportWidth="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="M15.41,16.09l-4.58,-4.59 4.58,-4.59L14,5.5l-6,6 6,6z" />
|
||||||
|
</vector>
|
@ -0,0 +1,9 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="48dp"
|
||||||
|
android:height="48dp"
|
||||||
|
android:viewportHeight="24.0"
|
||||||
|
android:viewportWidth="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#ffffff"
|
||||||
|
android:pathData="M8.59,16.34l4.58,-4.59 -4.58,-4.59L10,5.75l6,6 -6,6z" />
|
||||||
|
</vector>
|
35
app/src/main/res/drawable/material_button_black.xml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ Copyright 2013 serso aka se.solovyev
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
~
|
||||||
|
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
~ Contact details
|
||||||
|
~
|
||||||
|
~ Email: se.solovyev@gmail.com
|
||||||
|
~ Site: http://se.solovyev.org
|
||||||
|
-->
|
||||||
|
|
||||||
|
<selector xmlns:a="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item a:drawable="@drawable/material_button_pressed" a:state_pressed="true" />
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<solid a:color="@color/grey_950" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
</selector>
|
35
app/src/main/res/drawable/material_button_black_lighter.xml
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ Copyright 2013 serso aka se.solovyev
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
~
|
||||||
|
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
~ Contact details
|
||||||
|
~
|
||||||
|
~ Email: se.solovyev@gmail.com
|
||||||
|
~ Site: http://se.solovyev.org
|
||||||
|
-->
|
||||||
|
|
||||||
|
<selector xmlns:a="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item a:drawable="@drawable/material_button_pressed" a:state_pressed="true" />
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<solid a:color="@color/grey_900" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
</selector>
|
39
app/src/main/res/drawable/material_button_deep_blue.xml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ Copyright 2013 serso aka se.solovyev
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
~
|
||||||
|
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
~ Contact details
|
||||||
|
~
|
||||||
|
~ Email: se.solovyev@gmail.com
|
||||||
|
~ Site: http://se.solovyev.org
|
||||||
|
-->
|
||||||
|
|
||||||
|
<selector xmlns:a="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item a:state_pressed="true">
|
||||||
|
<shape>
|
||||||
|
<solid a:color="@color/deep_blue_850" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<solid a:color="@color/deep_blue_900" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
</selector>
|
@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ Copyright 2013 serso aka se.solovyev
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
~
|
||||||
|
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
~ Contact details
|
||||||
|
~
|
||||||
|
~ Email: se.solovyev@gmail.com
|
||||||
|
~ Site: http://se.solovyev.org
|
||||||
|
-->
|
||||||
|
|
||||||
|
<selector xmlns:a="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item a:state_pressed="true">
|
||||||
|
<shape>
|
||||||
|
<solid a:color="@color/deep_blue_800" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<shape>
|
||||||
|
<solid a:color="@color/deep_blue_850" />
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
</selector>
|
@ -84,7 +84,7 @@
|
|||||||
a:baselineAligned="false"
|
a:baselineAligned="false"
|
||||||
a:orientation="horizontal">
|
a:orientation="horizontal">
|
||||||
|
|
||||||
<include layout="@layout/cpp_app_button_paste" />
|
<include layout="@layout/cpp_app_button_like" />
|
||||||
|
|
||||||
<include layout="@layout/cpp_app_button_percent" />
|
<include layout="@layout/cpp_app_button_percent" />
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
~ Site: http://se.solovyev.org
|
~ Site: http://se.solovyev.org
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<org.solovyev.android.calculator.view.NumeralBasesButton
|
<org.solovyev.android.views.dragbutton.DirectionDragImageButton
|
||||||
android:id="@id/cpp_button_copy"
|
android:id="@id/cpp_button_copy"
|
||||||
style="?attr/cpp_button_style_control"
|
style="?attr/cpp_button_style_control"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
@ -31,6 +31,6 @@
|
|||||||
a:text="="
|
a:text="="
|
||||||
a:textColor="?attr/cpp_text_color"
|
a:textColor="?attr/cpp_text_color"
|
||||||
c:directionTextColor="?attr/cpp_text_color"
|
c:directionTextColor="?attr/cpp_text_color"
|
||||||
c:directionTextDown="@string/cpp_plot_button_text"
|
c:directionTextDown="@string/cpp_glyph_graph"
|
||||||
c:directionTextUp="≡"
|
c:directionTextUp="≡"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
@ -28,5 +28,5 @@
|
|||||||
style="?attr/cpp_button_style_control"
|
style="?attr/cpp_button_style_control"
|
||||||
a:src="@drawable/ic_history_white_48dp"
|
a:src="@drawable/ic_history_white_48dp"
|
||||||
app:directionTextScale="0.5"
|
app:directionTextScale="0.5"
|
||||||
app:directionTextDown="@string/cpp_kb_redo"
|
app:directionTextDown="@string/cpp_glyph_redo"
|
||||||
app:directionTextUp="@string/cpp_kb_undo" />
|
app:directionTextUp="@string/cpp_glyph_undo" />
|
@ -29,4 +29,5 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
a:src="@drawable/ic_keyboard_arrow_left_white_48dp"
|
a:src="@drawable/ic_keyboard_arrow_left_white_48dp"
|
||||||
c:directionTextUp="<<"
|
c:directionTextUp="<<"
|
||||||
|
c:directionTextDown="@string/cpp_glyph_copy"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
29
app/src/main/res/layout/cpp_app_button_like.xml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ Copyright 2013 serso aka se.solovyev
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
~
|
||||||
|
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
~ Contact details
|
||||||
|
~
|
||||||
|
~ Email: se.solovyev@gmail.com
|
||||||
|
~ Site: http://se.solovyev.org
|
||||||
|
-->
|
||||||
|
|
||||||
|
<org.solovyev.android.views.dragbutton.DirectionDragImageButton
|
||||||
|
android:id="@id/cpp_button_like"
|
||||||
|
style="?attr/cpp_button_style_control"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:src="@drawable/ic_favorite_border_white_48dp" />
|
@ -22,7 +22,7 @@
|
|||||||
~ Site: http://se.solovyev.org
|
~ Site: http://se.solovyev.org
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<org.solovyev.android.calculator.view.AngleUnitsButton
|
<org.solovyev.android.views.dragbutton.DirectionDragImageButton
|
||||||
android:id="@id/cpp_button_paste"
|
android:id="@id/cpp_button_paste"
|
||||||
style="?attr/cpp_button_style_control"
|
style="?attr/cpp_button_style_control"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
@ -29,4 +29,5 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
a:src="@drawable/ic_keyboard_arrow_right_white_48dp"
|
a:src="@drawable/ic_keyboard_arrow_right_white_48dp"
|
||||||
c:directionTextUp=">>"
|
c:directionTextUp=">>"
|
||||||
|
c:directionTextDown="@string/cpp_glyph_paste"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
@ -8,7 +8,7 @@
|
|||||||
app:showAsAction="never">
|
app:showAsAction="never">
|
||||||
<menu>
|
<menu>
|
||||||
<item
|
<item
|
||||||
android:icon="@drawable/ic_chevron_left_24dp"
|
android:icon="@drawable/ic_chevron_left_white_24dp"
|
||||||
android:title="@string/cpp_mode"
|
android:title="@string/cpp_mode"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
<item
|
<item
|
||||||
@ -30,7 +30,7 @@
|
|||||||
app:showAsAction="never">
|
app:showAsAction="never">
|
||||||
<menu>
|
<menu>
|
||||||
<item
|
<item
|
||||||
android:icon="@drawable/ic_chevron_left_24dp"
|
android:icon="@drawable/ic_chevron_left_white_24dp"
|
||||||
android:title="@string/cpp_angles"
|
android:title="@string/cpp_angles"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
<item
|
<item
|
||||||
@ -52,7 +52,7 @@
|
|||||||
app:showAsAction="never">
|
app:showAsAction="never">
|
||||||
<menu>
|
<menu>
|
||||||
<item
|
<item
|
||||||
android:icon="@drawable/ic_chevron_left_24dp"
|
android:icon="@drawable/ic_chevron_left_white_24dp"
|
||||||
android:title="@string/cpp_radix"
|
android:title="@string/cpp_radix"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
<item
|
<item
|
||||||
|
@ -21,21 +21,6 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<resources>
|
<resources>
|
||||||
<string-array name="p_theme_names">
|
|
||||||
<item>@string/cpp_theme_dark</item>
|
|
||||||
<item>@string/cpp_theme_light</item>
|
|
||||||
<item>@string/p_metro_blue_theme</item>
|
|
||||||
<item>@string/p_metro_green_theme</item>
|
|
||||||
<item>@string/p_metro_purple_theme</item>
|
|
||||||
</string-array>
|
|
||||||
<string-array name="p_theme_values" translatable="false">
|
|
||||||
<item>material_theme</item>
|
|
||||||
<item>material_light_theme</item>
|
|
||||||
<item>metro_blue_theme</item>
|
|
||||||
<item>metro_green_theme</item>
|
|
||||||
<item>metro_purple_theme</item>
|
|
||||||
</string-array>
|
|
||||||
|
|
||||||
<string-array name="p_simple_theme_names">
|
<string-array name="p_simple_theme_names">
|
||||||
<item>@string/p_use_app_theme</item>
|
<item>@string/p_use_app_theme</item>
|
||||||
<item>@string/cpp_theme_dark</item>
|
<item>@string/cpp_theme_dark</item>
|
||||||
|
@ -47,6 +47,11 @@
|
|||||||
<color name="grey_850">#313131</color>
|
<color name="grey_850">#313131</color>
|
||||||
<color name="grey_900">#212121</color>
|
<color name="grey_900">#212121</color>
|
||||||
<color name="grey_950">#101010</color>
|
<color name="grey_950">#101010</color>
|
||||||
|
<color name="grey_965">#0a0a0a</color>
|
||||||
|
|
||||||
|
<color name="deep_blue_900">#06224d</color>
|
||||||
|
<color name="deep_blue_850">#082a5e</color>
|
||||||
|
<color name="deep_blue_800">#0a3980</color>
|
||||||
|
|
||||||
<color name="blue_900">#0D47A1</color>
|
<color name="blue_900">#0D47A1</color>
|
||||||
<color name="blue_800">#1565C0</color>
|
<color name="blue_800">#1565C0</color>
|
||||||
|
13
app/src/main/res/values/text_glyphs.xml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="cpp_glyph_paste" translatable="false">"\ue000"</string>
|
||||||
|
<string name="cpp_glyph_copy" translatable="false">"\ue001"</string>
|
||||||
|
<string name="cpp_glyph_left" translatable="false">"\ue002"</string>
|
||||||
|
<string name="cpp_glyph_right" translatable="false">"\ue003"</string>
|
||||||
|
<string name="cpp_glyph_backspace" translatable="false">"\ue004"</string>
|
||||||
|
<string name="cpp_glyph_history" translatable="false">"\ue005"</string>
|
||||||
|
<string name="cpp_glyph_heart" translatable="false">"\ue006"</string>
|
||||||
|
<string name="cpp_glyph_undo" translatable="false">"\ue007"</string>
|
||||||
|
<string name="cpp_glyph_redo" translatable="false">"\ue008"</string>
|
||||||
|
<string name="cpp_glyph_graph" translatable="false">"\ue009"</string>
|
||||||
|
</resources>
|
@ -16,6 +16,7 @@
|
|||||||
<string name="cpp_function_body" translatable="false">f(x, y)</string>
|
<string name="cpp_function_body" translatable="false">f(x, y)</string>
|
||||||
<string name="cpp_show_greek_keyboard" translatable="false">αβγ</string>
|
<string name="cpp_show_greek_keyboard" translatable="false">αβγ</string>
|
||||||
<string name="cpp_exponent" translatable="false">E</string>
|
<string name="cpp_exponent" translatable="false">E</string>
|
||||||
|
<string name="cpp_theme_black" translatable="false">%1$s (AMOLED)</string>
|
||||||
<string-array name="cpp_prefs_precisions" translatable="false">
|
<string-array name="cpp_prefs_precisions" translatable="false">
|
||||||
<item>0</item>
|
<item>0</item>
|
||||||
<item>1</item>
|
<item>1</item>
|
||||||
|
79
app/src/main/res/values/theme_material_black.xml
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<!--
|
||||||
|
~ Copyright 2013 serso aka se.solovyev
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
~
|
||||||
|
~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
~ Contact details
|
||||||
|
~
|
||||||
|
~ Email: se.solovyev@gmail.com
|
||||||
|
~ Site: http://se.solovyev.org
|
||||||
|
-->
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<style name="CppKeyboardButton.Material.Black.Digit" parent="CppKeyboardButton">
|
||||||
|
<item name="android:background">@drawable/material_button_black</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="CppKeyboardButton.Material.Black.Digit.Highlighted" parent="CppKeyboardButton.Material.Black.Digit">
|
||||||
|
<item name="android:background">@drawable/material_button_black_lighter</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="CppKeyboardButton.Material.Black.Operation" parent="CppKeyboardButton.Material.Digit">
|
||||||
|
<item name="android:background">@drawable/material_button_deep_blue</item>
|
||||||
|
<item name="directionTextAlpha">0.7</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="CppKeyboardButton.Material.Black.Operation.Highlighted" parent="CppKeyboardButton.Material.Black.Operation">
|
||||||
|
<item name="android:background">@drawable/material_button_deep_blue_lighter</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="CppKeyboardButton.Material.Black.Control" parent="CppKeyboardButton.Material.Black.Digit" />
|
||||||
|
|
||||||
|
<style name="Cpp.Theme.Material.Black" parent="Cpp.Theme">
|
||||||
|
<item name="android:windowBackground">@color/grey_965</item>
|
||||||
|
<item name="cpp_editor_bg">@color/grey_965</item>
|
||||||
|
<item name="cpp_fab_bg">@color/deep_blue_900</item>
|
||||||
|
<item name="cpp_button_style_digit">@style/CppKeyboardButton.Material.Black.Digit</item>
|
||||||
|
<item name="cpp_button_style_control">@style/CppKeyboardButton.Material.Black.Digit</item>
|
||||||
|
<item name="cpp_button_style_control_highlighted">@style/CppKeyboardButton.Material.Black.Digit.Highlighted</item>
|
||||||
|
<item name="cpp_button_style_operation">@style/CppKeyboardButton.Material.Black.Operation</item>
|
||||||
|
<item name="cpp_button_style_operation_highlighted">@style/CppKeyboardButton.Material.Black.Operation.Highlighted</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Cpp.Theme.Material.Black.Dialog" parent="Cpp.Theme.Dialog">
|
||||||
|
<item name="cpp_editor_bg">@color/grey_965</item>
|
||||||
|
<item name="cpp_fab_bg">@color/deep_blue_900</item>
|
||||||
|
<item name="cpp_button_style_digit">@style/CppKeyboardButton.Material.Black.Digit</item>
|
||||||
|
<item name="cpp_button_style_control">@style/CppKeyboardButton.Material.Black.Digit</item>
|
||||||
|
<item name="cpp_button_style_control_highlighted">@style/CppKeyboardButton.Material.Black.Digit.Highlighted</item>
|
||||||
|
<item name="cpp_button_style_operation">@style/CppKeyboardButton.Material.Black.Operation</item>
|
||||||
|
<item name="cpp_button_style_operation_highlighted">@style/CppKeyboardButton.Material.Black.Operation.Highlighted</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Cpp.Theme.Material.Black.Dialog.Alert" parent="Cpp.Theme.Dialog.Alert">
|
||||||
|
<item name="cpp_editor_bg">@color/grey_965</item>
|
||||||
|
<item name="cpp_fab_bg">@color/deep_blue_900</item>
|
||||||
|
<item name="cpp_button_style_digit">@style/CppKeyboardButton.Material.Black.Digit</item>
|
||||||
|
<item name="cpp_button_style_control">@style/CppKeyboardButton.Material.Black.Digit</item>
|
||||||
|
<item name="cpp_button_style_control_highlighted">@style/CppKeyboardButton.Material.Black.Digit.Highlighted</item>
|
||||||
|
<item name="cpp_button_style_operation">@style/CppKeyboardButton.Material.Black.Operation</item>
|
||||||
|
<item name="cpp_button_style_operation_highlighted">@style/CppKeyboardButton.Material.Black.Operation.Highlighted</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="Cpp.Theme.Material.Black.Calculator" parent="Cpp.Theme.Material.Black">
|
||||||
|
<item name="android:windowAnimationStyle">@null</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</resources>
|
@ -35,8 +35,6 @@
|
|||||||
a:title="@string/cpp_prefs_vibrate_on_keypress" />
|
a:title="@string/cpp_prefs_vibrate_on_keypress" />
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
a:entries="@array/p_theme_names"
|
|
||||||
a:entryValues="@array/p_theme_values"
|
|
||||||
a:key="gui.theme"
|
a:key="gui.theme"
|
||||||
a:title="@string/cpp_theme" />
|
a:title="@string/cpp_theme" />
|
||||||
|
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package org.solovyev.android.calculator.buttons;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
|
public class CppSpecialButtonTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShouldReturnButtonByGlyph() throws Exception {
|
||||||
|
assertEquals(CppSpecialButton.copy, CppSpecialButton.getByGlyph(CppSpecialButton.copy.glyph));
|
||||||
|
assertEquals(CppSpecialButton.paste, CppSpecialButton.getByGlyph(CppSpecialButton.paste.glyph));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShouldReturnNullForButtonWithoutGlyph() throws Exception {
|
||||||
|
assertNull(CppSpecialButton.getByGlyph(CppSpecialButton.brackets_wrap.glyph));
|
||||||
|
}
|
||||||
|
}
|
@ -1,61 +0,0 @@
|
|||||||
package org.solovyev.android.calculator.view;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mockito.Mockito;
|
|
||||||
import org.robolectric.Robolectric;
|
|
||||||
import org.robolectric.RobolectricGradleTestRunner;
|
|
||||||
import org.robolectric.Shadows;
|
|
||||||
import org.robolectric.annotation.Config;
|
|
||||||
import org.robolectric.res.Attribute;
|
|
||||||
import org.robolectric.shadows.ShadowActivity;
|
|
||||||
import org.solovyev.android.calculator.BuildConfig;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import static jscl.AngleUnit.deg;
|
|
||||||
import static jscl.AngleUnit.grad;
|
|
||||||
import static jscl.AngleUnit.rad;
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.mockito.Mockito.times;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
|
|
||||||
@Config(constants = BuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
@RunWith(RobolectricGradleTestRunner.class)
|
|
||||||
public class AngleUnitsButtonTest {
|
|
||||||
|
|
||||||
private AngleUnitsButton button;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
final Activity context = Robolectric.buildActivity(Activity.class).create().get();
|
|
||||||
final ShadowActivity activity = Shadows.shadowOf(context);
|
|
||||||
button = new AngleUnitsButton(context, activity.createAttributeSet(new ArrayList<Attribute>(), AngleUnitsButton.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsCurrentAngleUnits() throws Exception {
|
|
||||||
button.setAngleUnit(rad);
|
|
||||||
assertTrue(button.isCurrentAngleUnits(rad.name()));
|
|
||||||
assertFalse(button.isCurrentAngleUnits(deg.name()));
|
|
||||||
assertFalse(button.isCurrentAngleUnits(grad.name()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidateShouldBeCalledOnlyWhenChangeIsDone() throws Exception {
|
|
||||||
button.setAngleUnit(rad);
|
|
||||||
|
|
||||||
button = Mockito.spy(button);
|
|
||||||
|
|
||||||
button.setAngleUnit(deg);
|
|
||||||
verify(button, times(1)).invalidate();
|
|
||||||
|
|
||||||
button.setAngleUnit(deg);
|
|
||||||
verify(button, times(1)).invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
package org.solovyev.android.calculator.view;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mockito.Mockito;
|
|
||||||
import org.robolectric.Robolectric;
|
|
||||||
import org.robolectric.RobolectricGradleTestRunner;
|
|
||||||
import org.robolectric.Shadows;
|
|
||||||
import org.robolectric.annotation.Config;
|
|
||||||
import org.robolectric.res.Attribute;
|
|
||||||
import org.robolectric.shadows.ShadowActivity;
|
|
||||||
import org.solovyev.android.calculator.BuildConfig;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import static jscl.NumeralBase.bin;
|
|
||||||
import static jscl.NumeralBase.dec;
|
|
||||||
import static jscl.NumeralBase.hex;
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.mockito.Mockito.times;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
|
|
||||||
@Config(constants = BuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
@RunWith(RobolectricGradleTestRunner.class)
|
|
||||||
public class NumeralBasesButtonTest {
|
|
||||||
|
|
||||||
private NumeralBasesButton button;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
final Activity context = Robolectric.buildActivity(Activity.class).create().get();
|
|
||||||
final ShadowActivity activity = Shadows.shadowOf(context);
|
|
||||||
button = new NumeralBasesButton(context, activity.createAttributeSet(new ArrayList<Attribute>(), NumeralBasesButton.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsCurrentNumeralBase() throws Exception {
|
|
||||||
button.setNumeralBase(dec);
|
|
||||||
assertTrue(button.isCurrentNumberBase(dec.name()));
|
|
||||||
assertFalse(button.isCurrentNumberBase(hex.name()));
|
|
||||||
assertFalse(button.isCurrentNumberBase(bin.name()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidateShouldBeCalledOnlyWhenChangeIsDone() throws Exception {
|
|
||||||
button.setNumeralBase(dec);
|
|
||||||
|
|
||||||
button = Mockito.spy(button);
|
|
||||||
|
|
||||||
button.setNumeralBase(hex);
|
|
||||||
verify(button, times(1)).invalidate();
|
|
||||||
|
|
||||||
button.setNumeralBase(hex);
|
|
||||||
verify(button, times(1)).invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,112 @@
|
|||||||
|
package org.solovyev.android.text.method;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.InputFilter;
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RobolectricGradleTestRunner;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.solovyev.android.calculator.BuildConfig;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
@Config(constants = BuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
@RunWith(RobolectricGradleTestRunner.class)
|
||||||
|
public class NumberInputFilterTest {
|
||||||
|
|
||||||
|
private Editable editable;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
editable = new SpannableStringBuilder();
|
||||||
|
editable.setFilters(new InputFilter[]{new NumberInputFilter()});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShouldNotInsertExponentInTheBeginning() throws Exception {
|
||||||
|
editable.insert(0, "E");
|
||||||
|
assertEquals("", editable.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShouldInsertExponentAtTheEnd() throws Exception {
|
||||||
|
editable.insert(0, "1");
|
||||||
|
editable.insert(1, "E");
|
||||||
|
assertEquals("1E", editable.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShouldNotInsertSecondMinusSign() throws Exception {
|
||||||
|
editable.insert(0, "-");
|
||||||
|
editable.insert(1, "-");
|
||||||
|
assertEquals("-", editable.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShouldNotInsertTwoMinusSigns() throws Exception {
|
||||||
|
editable.insert(0, "--");
|
||||||
|
assertEquals("-", editable.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShouldInsertSecondMinusSignAfterExponent() throws Exception {
|
||||||
|
editable.insert(0, "-");
|
||||||
|
editable.insert(1, "E");
|
||||||
|
editable.insert(2, "-");
|
||||||
|
assertEquals("-E-", editable.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShouldInsertSecondMinusSignAlongWithExponent() throws Exception {
|
||||||
|
editable.insert(0, "-");
|
||||||
|
editable.insert(1, "E-");
|
||||||
|
assertEquals("-E-", editable.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShouldNotInsertMinusSignBeforeExistingMinusSIgn() throws Exception {
|
||||||
|
editable.insert(0, "-");
|
||||||
|
editable.insert(0, "-");
|
||||||
|
assertEquals("-", editable.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShouldNotInsertSecondDecimalPoint() throws Exception {
|
||||||
|
editable.insert(0, "0.2");
|
||||||
|
editable.insert(3, ".");
|
||||||
|
assertEquals("0.2", editable.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShouldNotInsertTwoDecimalPoints() throws Exception {
|
||||||
|
editable.insert(0, "..");
|
||||||
|
assertEquals(".", editable.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShouldNotInsertDecimalPointAfterExponent() throws Exception {
|
||||||
|
editable.insert(0, "2E");
|
||||||
|
editable.insert(2, ".");
|
||||||
|
assertEquals("2E", editable.toString());
|
||||||
|
|
||||||
|
editable.clear();
|
||||||
|
editable.insert(0, "2E.");
|
||||||
|
assertEquals("2E", editable.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShouldNotInsertTwoExcponents() throws Exception {
|
||||||
|
editable.insert(0, "2EE");
|
||||||
|
assertEquals("2E", editable.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testShouldNotInsertExponentBeforeDecimalPoint() throws Exception {
|
||||||
|
editable.insert(0, "0.2");
|
||||||
|
editable.insert(0, "E");
|
||||||
|
assertEquals("0.2", editable.toString());
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,6 @@ import jscl.math.operator.Percent;
|
|||||||
import jscl.math.operator.Rand;
|
import jscl.math.operator.Rand;
|
||||||
import jscl.math.operator.matrix.OperatorsRegistry;
|
import jscl.math.operator.matrix.OperatorsRegistry;
|
||||||
import jscl.text.ParseException;
|
import jscl.text.ParseException;
|
||||||
import midpcalc.Real;
|
|
||||||
import org.solovyev.common.NumberFormatter;
|
import org.solovyev.common.NumberFormatter;
|
||||||
import org.solovyev.common.math.MathRegistry;
|
import org.solovyev.common.math.MathRegistry;
|
||||||
import org.solovyev.common.msg.MessageRegistry;
|
import org.solovyev.common.msg.MessageRegistry;
|
||||||
@ -18,6 +17,7 @@ import org.solovyev.common.msg.Messages;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static midpcalc.Real.NumberFormat.*;
|
import static midpcalc.Real.NumberFormat.*;
|
||||||
@ -144,16 +144,16 @@ public class JsclMathEngine implements MathEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public String format(@Nonnull Double value) throws NumeralBaseException {
|
public String format(double value) throws NumeralBaseException {
|
||||||
return format(value, numeralBase);
|
return format(value, numeralBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public String format(@Nonnull Double value, @Nonnull NumeralBase nb) throws NumeralBaseException {
|
public String format(double value, @Nonnull NumeralBase nb) throws NumeralBaseException {
|
||||||
if (value.isInfinite()) {
|
if (Double.isInfinite(value)) {
|
||||||
return formatInfinity(value);
|
return formatInfinity(value);
|
||||||
}
|
}
|
||||||
if (value.isNaN()) {
|
if (Double.isNaN(value)) {
|
||||||
// return "NaN"
|
// return "NaN"
|
||||||
return String.valueOf(value);
|
return String.valueOf(value);
|
||||||
}
|
}
|
||||||
@ -167,11 +167,15 @@ public class JsclMathEngine implements MathEngine {
|
|||||||
return constant.getName();
|
return constant.getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return prepareNumberFormatter(nb).format(value, nb.radix).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private NumberFormatter prepareNumberFormatter(@Nonnull NumeralBase nb) {
|
||||||
final NumberFormatter nf = numberFormatter.get();
|
final NumberFormatter nf = numberFormatter.get();
|
||||||
nf.setGroupingSeparator(useGroupingSeparator ? groupingSeparator : NumberFormatter.NO_GROUPING);
|
nf.setGroupingSeparator(useGroupingSeparator ? getGroupingSeparatorChar(nb) : NumberFormatter.NO_GROUPING);
|
||||||
nf.setPrecision(roundResult ? precision : NumberFormatter.NO_ROUNDING);
|
nf.setPrecision(roundResult ? precision : NumberFormatter.NO_ROUNDING);
|
||||||
switch (numberFormat) {
|
switch (numberFormat) {
|
||||||
case Real.NumberFormat.FSE_ENG:
|
case FSE_ENG:
|
||||||
nf.useEngineeringFormat(NumberFormatter.DEFAULT_MAGNITUDE);
|
nf.useEngineeringFormat(NumberFormatter.DEFAULT_MAGNITUDE);
|
||||||
break;
|
break;
|
||||||
case FSE_SCI:
|
case FSE_SCI:
|
||||||
@ -181,18 +185,36 @@ public class JsclMathEngine implements MathEngine {
|
|||||||
nf.useSimpleFormat();
|
nf.useSimpleFormat();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return nf.format(value, nb.radix).toString();
|
return nf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String format(@Nonnull BigInteger value) throws NumeralBaseException {
|
||||||
|
return format(value, numeralBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public String format(@Nonnull BigInteger value, @Nonnull NumeralBase nb) throws NumeralBaseException {
|
||||||
|
if (nb == NumeralBase.dec) {
|
||||||
|
if (BigInteger.ZERO.equals(value)) {
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prepareNumberFormatter(nb).format(value, nb.radix).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private IConstant findConstant(@Nonnull Double value) {
|
private IConstant findConstant(double value) {
|
||||||
final IConstant constant = findConstant(constantsRegistry.getSystemEntities(), value);
|
final IConstant constant = findConstant(constantsRegistry.getSystemEntities(), value);
|
||||||
if (constant != null) {
|
if (constant != null) {
|
||||||
return constant;
|
return constant;
|
||||||
}
|
}
|
||||||
final IConstant piInv = constantsRegistry.get(Constants.PI_INV.getName());
|
final IConstant piInv = constantsRegistry.get(Constants.PI_INV.getName());
|
||||||
if (piInv != null && value.equals(piInv.getDoubleValue())) {
|
if (piInv != null) {
|
||||||
return piInv;
|
final Double piInvValue = piInv.getDoubleValue();
|
||||||
|
if (piInvValue != null && piInvValue == value) {
|
||||||
|
return piInv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -251,7 +273,7 @@ public class JsclMathEngine implements MathEngine {
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
public String addGroupingSeparators(@Nonnull NumeralBase nb, @Nonnull String ungroupedDoubleValue) {
|
public String addGroupingSeparators(@Nonnull NumeralBase nb, @Nonnull String ungroupedDoubleValue) {
|
||||||
if (useGroupingSeparator) {
|
if (useGroupingSeparator) {
|
||||||
final String groupingSeparator = nb == NumeralBase.dec ? String.valueOf(this.groupingSeparator) : " ";
|
final String groupingSeparator = getGroupingSeparator(nb);
|
||||||
|
|
||||||
final int dotIndex = ungroupedDoubleValue.indexOf(".");
|
final int dotIndex = ungroupedDoubleValue.indexOf(".");
|
||||||
|
|
||||||
@ -277,6 +299,15 @@ public class JsclMathEngine implements MathEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private String getGroupingSeparator(@Nonnull NumeralBase nb) {
|
||||||
|
return nb == NumeralBase.dec ? String.valueOf(groupingSeparator) : " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
private char getGroupingSeparatorChar(@Nonnull NumeralBase nb) {
|
||||||
|
return nb == NumeralBase.dec ? groupingSeparator : ' ';
|
||||||
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private StringBuilder insertSeparators(@Nonnull NumeralBase nb,
|
private StringBuilder insertSeparators(@Nonnull NumeralBase nb,
|
||||||
@Nonnull String groupingSeparator,
|
@Nonnull String groupingSeparator,
|
||||||
|
@ -6,6 +6,7 @@ import jscl.math.operator.Operator;
|
|||||||
import org.solovyev.common.math.MathRegistry;
|
import org.solovyev.common.math.MathRegistry;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
public interface MathContext {
|
public interface MathContext {
|
||||||
|
|
||||||
@ -44,10 +45,12 @@ public interface MathContext {
|
|||||||
void setGroupingSeparator(char groupingSeparator);
|
void setGroupingSeparator(char groupingSeparator);
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
String format(@Nonnull Double value) throws NumeralBaseException;
|
String format(double value) throws NumeralBaseException;
|
||||||
|
|
||||||
|
String format(@Nonnull BigInteger value) throws NumeralBaseException;
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
String format(@Nonnull Double value, @Nonnull NumeralBase nb) throws NumeralBaseException;
|
String format(double value, @Nonnull NumeralBase nb) throws NumeralBaseException;
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
String addGroupingSeparators(@Nonnull NumeralBase nb, @Nonnull String ungroupedIntValue);
|
String addGroupingSeparators(@Nonnull NumeralBase nb, @Nonnull String ungroupedIntValue);
|
||||||
|
@ -352,8 +352,7 @@ public final class JsclInteger extends Generic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
// todo serso: actually better way is to provide custom format() method for integers and not to convert integer to double
|
return JsclMathEngine.getInstance().format(content);
|
||||||
return JsclMathEngine.getInstance().format(this.content.doubleValue());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toJava() {
|
public String toJava() {
|
||||||
|
@ -324,7 +324,7 @@ public abstract class Numeric implements Arithmetic<Numeric>, INumeric<Numeric>,
|
|||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
protected String toString(final double value) {
|
protected String toString(final double value) {
|
||||||
return JsclMathEngine.getInstance().format(value, JsclMathEngine.getInstance().getNumeralBase());
|
return JsclMathEngine.getInstance().format(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BigInteger toBigInteger() {
|
public BigInteger toBigInteger() {
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
package org.solovyev.common;
|
package org.solovyev.common;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
|
|
||||||
import midpcalc.Real;
|
import midpcalc.Real;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import static java.lang.Math.pow;
|
import static java.lang.Math.pow;
|
||||||
import static midpcalc.Real.NumberFormat.FSE_ENG;
|
import static midpcalc.Real.NumberFormat.*;
|
||||||
import static midpcalc.Real.NumberFormat.FSE_FIX;
|
|
||||||
import static midpcalc.Real.NumberFormat.FSE_NONE;
|
|
||||||
import static midpcalc.Real.NumberFormat.FSE_SCI;
|
|
||||||
|
|
||||||
public class NumberFormatter {
|
public class NumberFormatter {
|
||||||
|
|
||||||
@ -54,11 +51,14 @@ public class NumberFormatter {
|
|||||||
return format(value, 10);
|
return format(value, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public CharSequence format(@Nonnull BigInteger value) {
|
||||||
|
return format(value, 10);
|
||||||
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public CharSequence format(double value, int radix) {
|
public CharSequence format(double value, int radix) {
|
||||||
if (radix != 2 && radix != 8 && radix != 10 && radix != 16) {
|
checkRadix(radix);
|
||||||
throw new IllegalArgumentException("Unsupported radix: " + radix);
|
|
||||||
}
|
|
||||||
double absValue = Math.abs(value);
|
double absValue = Math.abs(value);
|
||||||
final boolean simpleFormat = useSimpleFormat(radix, absValue);
|
final boolean simpleFormat = useSimpleFormat(radix, absValue);
|
||||||
|
|
||||||
@ -88,6 +88,39 @@ public class NumberFormatter {
|
|||||||
return prepare(value);
|
return prepare(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
public CharSequence format(@Nonnull BigInteger value, int radix) {
|
||||||
|
checkRadix(radix);
|
||||||
|
final BigInteger absValue = value.abs();
|
||||||
|
final boolean simpleFormat = useSimpleFormat(radix, absValue);
|
||||||
|
|
||||||
|
final int effectivePrecision = precision == NO_ROUNDING ? MAX_PRECISION : precision;
|
||||||
|
if (simpleFormat) {
|
||||||
|
numberFormat.fse = FSE_FIX;
|
||||||
|
} else if (format == FSE_NONE) {
|
||||||
|
// originally, a simple format was requested but we have to use something more appropriate, f.e. scientific
|
||||||
|
// format
|
||||||
|
numberFormat.fse = FSE_SCI;
|
||||||
|
} else {
|
||||||
|
numberFormat.fse = format;
|
||||||
|
}
|
||||||
|
numberFormat.thousand = groupingSeparator;
|
||||||
|
numberFormat.precision = effectivePrecision;
|
||||||
|
numberFormat.base = radix;
|
||||||
|
numberFormat.maxwidth = simpleFormat ? 100 : 30;
|
||||||
|
|
||||||
|
if (radix == 2 && value.compareTo(BigInteger.ZERO) < 0) {
|
||||||
|
return "-" + prepare(absValue);
|
||||||
|
}
|
||||||
|
return prepare(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkRadix(int radix) {
|
||||||
|
if (radix != 2 && radix != 8 && radix != 10 && radix != 16) {
|
||||||
|
throw new IllegalArgumentException("Unsupported radix: " + radix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean useSimpleFormat(int radix, double absValue) {
|
private boolean useSimpleFormat(int radix, double absValue) {
|
||||||
if (radix != 10) {
|
if (radix != 10) {
|
||||||
return true;
|
return true;
|
||||||
@ -103,17 +136,41 @@ public class NumberFormatter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean useSimpleFormat(int radix, @Nonnull BigInteger absValue) {
|
||||||
|
if (radix != 10) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (format == FSE_NONE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (absValue.compareTo(BigInteger.valueOf((long) pow(10, simpleFormatMagnitude))) < 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private CharSequence prepare(double value) {
|
private CharSequence prepare(double value) {
|
||||||
return stripZeros(realFormat(value)).replace('e', 'E');
|
return stripZeros(realFormat(value)).replace('e', 'E');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private CharSequence prepare(@Nonnull BigInteger value) {
|
||||||
|
return stripZeros(realFormat(value)).replace('e', 'E');
|
||||||
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private String realFormat(double value) {
|
private String realFormat(double value) {
|
||||||
real.assign(Double.toString(value));
|
real.assign(Double.toString(value));
|
||||||
return real.toString(numberFormat);
|
return real.toString(numberFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
private String realFormat(@Nonnull BigInteger value) {
|
||||||
|
real.assign(value.toString());
|
||||||
|
return real.toString(numberFormat);
|
||||||
|
}
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private String stripZeros(@Nonnull String s) {
|
private String stripZeros(@Nonnull String s) {
|
||||||
int dot = -1;
|
int dot = -1;
|
||||||
|
@ -77,12 +77,31 @@ public class JsclMathEngineTest {
|
|||||||
assertEquals("13D", me.format(317d, NumeralBase.hex));
|
assertEquals("13D", me.format(317d, NumeralBase.hex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPiComputation() throws Exception {
|
public void testPiComputation() throws Exception {
|
||||||
final JsclMathEngine me = JsclMathEngine.getInstance();
|
final JsclMathEngine me = JsclMathEngine.getInstance();
|
||||||
assertEquals("-1+0.0000000000000001*i", me.evaluate("exp(√(-1)*Π)"));
|
assertEquals("-1+0.0000000000000001*i", me.evaluate("exp(√(-1)*Π)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBinShouldAlwaysUseSpaceAsGroupingSeparator() throws Exception {
|
||||||
|
final JsclMathEngine me = new JsclMathEngine();
|
||||||
|
me.setGroupingSeparator('\'');
|
||||||
|
me.setUseGroupingSeparator(true);
|
||||||
|
|
||||||
|
assertEquals("100 0000 0000", me.format(1024d, NumeralBase.bin));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testHexShouldAlwaysUseSpaceAsGroupingSeparator() throws Exception {
|
||||||
|
final JsclMathEngine me = new JsclMathEngine();
|
||||||
|
me.setGroupingSeparator('\'');
|
||||||
|
me.setUseGroupingSeparator(true);
|
||||||
|
|
||||||
|
assertEquals("4 00", me.format(1024d, NumeralBase.hex));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEngineeringNotationWithRounding() throws Exception {
|
public void testEngineeringNotationWithRounding() throws Exception {
|
||||||
final JsclMathEngine me = JsclMathEngine.getInstance();
|
final JsclMathEngine me = JsclMathEngine.getInstance();
|
||||||
@ -114,6 +133,7 @@ public class JsclMathEngineTest {
|
|||||||
assertEquals("-999", me.format(-999d));
|
assertEquals("-999", me.format(-999d));
|
||||||
assertEquals("-999.99", me.format(-999.99d));
|
assertEquals("-999.99", me.format(-999.99d));
|
||||||
assertEquals("-0.1", me.format(-0.1d));
|
assertEquals("-0.1", me.format(-0.1d));
|
||||||
|
|
||||||
assertEquals("-0.12", me.format(-0.12d));
|
assertEquals("-0.12", me.format(-0.12d));
|
||||||
assertEquals("-0.123", me.format(-0.123d));
|
assertEquals("-0.123", me.format(-0.123d));
|
||||||
assertEquals("-0.1234", me.format(-0.1234d));
|
assertEquals("-0.1234", me.format(-0.1234d));
|
||||||
|
@ -3,7 +3,10 @@ package org.solovyev.common;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import static java.lang.Math.pow;
|
import static java.lang.Math.pow;
|
||||||
|
import static java.math.BigInteger.TEN;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.solovyev.common.NumberFormatter.DEFAULT_MAGNITUDE;
|
import static org.solovyev.common.NumberFormatter.DEFAULT_MAGNITUDE;
|
||||||
import static org.solovyev.common.NumberFormatter.NO_ROUNDING;
|
import static org.solovyev.common.NumberFormatter.NO_ROUNDING;
|
||||||
@ -99,32 +102,66 @@ public class NumberFormatterTest {
|
|||||||
// testing simple format with and without rounding
|
// testing simple format with and without rounding
|
||||||
private void testSimpleFormat() {
|
private void testSimpleFormat() {
|
||||||
assertEquals("0.00001", numberFormatter.format(pow(10, -5)));
|
assertEquals("0.00001", numberFormatter.format(pow(10, -5)));
|
||||||
|
|
||||||
assertEquals("100", numberFormatter.format(pow(10, 2)));
|
assertEquals("100", numberFormatter.format(pow(10, 2)));
|
||||||
|
assertEquals("1", numberFormatter.format(BigInteger.ONE));
|
||||||
|
assertEquals("1000", numberFormatter.format(BigInteger.valueOf(1000)));
|
||||||
|
|
||||||
assertEquals("1000000000000000000", numberFormatter.format(pow(10, 18)));
|
assertEquals("1000000000000000000", numberFormatter.format(pow(10, 18)));
|
||||||
|
assertEquals("1000000000000000000", numberFormatter.format(BigInteger.valueOf(10).pow(18)));
|
||||||
|
|
||||||
assertEquals("1E19", numberFormatter.format(pow(10, 19)));
|
assertEquals("1E19", numberFormatter.format(pow(10, 19)));
|
||||||
|
assertEquals("1E19", numberFormatter.format(BigInteger.valueOf(10).pow(19)));
|
||||||
|
|
||||||
assertEquals("1E20", numberFormatter.format(pow(10, 20)));
|
assertEquals("1E20", numberFormatter.format(pow(10, 20)));
|
||||||
|
assertEquals("1E20", numberFormatter.format(BigInteger.valueOf(10).pow(20)));
|
||||||
|
|
||||||
assertEquals("1E100", numberFormatter.format(pow(10, 100)));
|
assertEquals("1E100", numberFormatter.format(pow(10, 100)));
|
||||||
|
assertEquals("1E100", numberFormatter.format(BigInteger.valueOf(10).pow(100)));
|
||||||
|
|
||||||
assertEquals("0.01", numberFormatter.format(pow(10, -2)));
|
assertEquals("0.01", numberFormatter.format(pow(10, -2)));
|
||||||
|
|
||||||
assertEquals("5000000000000000000", numberFormatter.format(5000000000000000000d));
|
assertEquals("5000000000000000000", numberFormatter.format(5000000000000000000d));
|
||||||
|
assertEquals("5000000000000000000", numberFormatter.format(BigInteger.valueOf(5000000000000000000L)));
|
||||||
|
|
||||||
assertEquals("5000000000000000000", numberFormatter.format(5000000000000000001d));
|
assertEquals("5000000000000000000", numberFormatter.format(5000000000000000001d));
|
||||||
|
assertEquals("5000000000000000001", numberFormatter.format(BigInteger.valueOf(5000000000000000001L)));
|
||||||
|
|
||||||
assertEquals("5999999999999994900", numberFormatter.format(5999999999999994999d));
|
assertEquals("5999999999999994900", numberFormatter.format(5999999999999994999d));
|
||||||
|
assertEquals("5999999999999994999", numberFormatter.format(BigInteger.valueOf(5999999999999994999L)));
|
||||||
|
|
||||||
assertEquals("5E19", numberFormatter.format(50000000000000000000d));
|
assertEquals("5E19", numberFormatter.format(50000000000000000000d));
|
||||||
|
assertEquals("5E19", numberFormatter.format(BigInteger.valueOf(5L).multiply(TEN.pow(19))));
|
||||||
|
|
||||||
assertEquals("5E40", numberFormatter.format(50000000000000000000000000000000000000000d));
|
assertEquals("5E40", numberFormatter.format(50000000000000000000000000000000000000000d));
|
||||||
|
assertEquals("5E40", numberFormatter.format(BigInteger.valueOf(5L).multiply(TEN.pow(40))));
|
||||||
}
|
}
|
||||||
|
|
||||||
// testing scientific format with and without rounding
|
// testing scientific format with and without rounding
|
||||||
private void testScientificFormat() {
|
private void testScientificFormat() {
|
||||||
assertEquals("0.00001", numberFormatter.format(pow(10, -5)));
|
assertEquals("0.00001", numberFormatter.format(pow(10, -5)));
|
||||||
assertEquals("1E-6", numberFormatter.format(pow(10, -6)));
|
assertEquals("1E-6", numberFormatter.format(pow(10, -6)));
|
||||||
|
|
||||||
assertEquals("100", numberFormatter.format(pow(10, 2)));
|
assertEquals("100", numberFormatter.format(pow(10, 2)));
|
||||||
|
assertEquals("100", numberFormatter.format(TEN.pow(2)));
|
||||||
|
|
||||||
assertEquals("10000", numberFormatter.format(pow(10, 4)));
|
assertEquals("10000", numberFormatter.format(pow(10, 4)));
|
||||||
|
assertEquals("10000", numberFormatter.format(TEN.pow(4)));
|
||||||
|
|
||||||
assertEquals("1E5", numberFormatter.format(pow(10, 5)));
|
assertEquals("1E5", numberFormatter.format(pow(10, 5)));
|
||||||
|
assertEquals("1E5", numberFormatter.format(TEN.pow(5)));
|
||||||
|
|
||||||
assertEquals("1E18", numberFormatter.format(pow(10, 18)));
|
assertEquals("1E18", numberFormatter.format(pow(10, 18)));
|
||||||
|
assertEquals("1E18", numberFormatter.format(TEN.pow(18)));
|
||||||
|
|
||||||
assertEquals("1E19", numberFormatter.format(pow(10, 19)));
|
assertEquals("1E19", numberFormatter.format(pow(10, 19)));
|
||||||
|
assertEquals("1E19", numberFormatter.format(TEN.pow( 19)));
|
||||||
|
|
||||||
assertEquals("1E20", numberFormatter.format(pow(10, 20)));
|
assertEquals("1E20", numberFormatter.format(pow(10, 20)));
|
||||||
|
assertEquals("1E20", numberFormatter.format(TEN.pow(20)));
|
||||||
|
|
||||||
assertEquals("1E100", numberFormatter.format(pow(10, 100)));
|
assertEquals("1E100", numberFormatter.format(pow(10, 100)));
|
||||||
|
assertEquals("1E100", numberFormatter.format(TEN.pow(100)));
|
||||||
|
|
||||||
assertEquals("0.01", numberFormatter.format(pow(10, -2)));
|
assertEquals("0.01", numberFormatter.format(pow(10, -2)));
|
||||||
assertEquals("1E-17", numberFormatter.format(pow(10, -17)));
|
assertEquals("1E-17", numberFormatter.format(pow(10, -17)));
|
||||||
|