Skip to content

Commit

Permalink
Merge pull request #22 from arch10/display-enhancement
Browse files Browse the repository at this point in the history
Display enhancement
  • Loading branch information
arch10 authored Jul 21, 2019
2 parents 93a2c22 + 131879b commit fde8dec
Show file tree
Hide file tree
Showing 16 changed files with 638 additions and 208 deletions.
8 changes: 6 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ android {
applicationId "com.gigaworks.tech.calculator"
minSdkVersion 21
targetSdkVersion 28
versionCode 29
versionName "1.9.7"
versionCode 30
versionName "1.10.0"
buildConfigField "java.util.Date", "buildTime", "new java.util.Date(" + System.currentTimeMillis() + "L)"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand All @@ -18,6 +18,10 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
}
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class AppPreferences {
final static String APP_HISTORY_SET = "app.is.history.set";
final static String APP_HISTORY_EQUATION = "app.history.equation";
final static String APP_MEMORY_VALUE = "app.memory.value";
final static String APP_SCIENTIFIC_RESULT = "app.scientific.string";

public AppPreferences(Context context) {
ctx = context;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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.
*/

package com.example.arch1.testapplication;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Paint;
import android.graphics.Paint.FontMetricsInt;
import android.graphics.Rect;
import android.os.Parcelable;
import android.text.method.ScrollingMovementMethod;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.widget.TextView;
import androidx.appcompat.widget.AppCompatEditText;

public class CalculatorEditText extends AppCompatEditText {

private final static ActionMode.Callback NO_SELECTION_ACTION_MODE_CALLBACK =
new ActionMode.Callback() {
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}

@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// Prevents the selection action mode on double tap.
return false;
}

@Override
public void onDestroyActionMode(ActionMode mode) {
}

@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
};

private final float mMaximumTextSize;
private final float mMinimumTextSize;
private final float mStepTextSize;

// Temporary objects for use in layout methods.
private final Paint mTempPaint = new TextPaint();
private final Rect mTempRect = new Rect();

private int mWidthConstraint = -1;
private OnTextSizeChangeListener mOnTextSizeChangeListener;

public CalculatorEditText(Context context) {
this(context, null);
}

public CalculatorEditText(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public CalculatorEditText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);

final TypedArray a = context.obtainStyledAttributes(
attrs, R.styleable.CalculatorEditText, defStyle, 0);
mMaximumTextSize = a.getDimension(
R.styleable.CalculatorEditText_maxTextSize, getTextSize());
mMinimumTextSize = a.getDimension(
R.styleable.CalculatorEditText_minTextSize, getTextSize());
mStepTextSize = a.getDimension(R.styleable.CalculatorEditText_stepTextSize,
(mMaximumTextSize - mMinimumTextSize) / 3);

a.recycle();

setCustomSelectionActionModeCallback(NO_SELECTION_ACTION_MODE_CALLBACK);
if (isFocusable()) {
setMovementMethod(ScrollingMovementMethod.getInstance());
}
setTextSize(TypedValue.COMPLEX_UNIT_PX, mMaximumTextSize);
setMinHeight(getLineHeight() + getCompoundPaddingBottom() + getCompoundPaddingTop());
}

@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
// Hack to prevent keyboard and insertion handle from showing.
cancelLongPress();
}
return super.onTouchEvent(event);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);

mWidthConstraint =
MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
setTextSize(TypedValue.COMPLEX_UNIT_PX, getVariableTextSize(getText().toString()));
}

@Override
public Parcelable onSaveInstanceState() {
super.onSaveInstanceState();

// EditText will freeze any text with a selection regardless of getFreezesText() ->
// return null to prevent any state from being preserved at the instance level.
return null;
}

@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);

final int textLength = text.length();
if (getSelectionStart() != textLength || getSelectionEnd() != textLength) {
// Pin the selection to the end of the current text.
setSelection(textLength);
}
setTextSize(TypedValue.COMPLEX_UNIT_PX, getVariableTextSize(text.toString()));
}

@Override
public void setTextSize(int unit, float size) {
final float oldTextSize = getTextSize();
super.setTextSize(unit, size);

if (mOnTextSizeChangeListener != null && getTextSize() != oldTextSize) {
mOnTextSizeChangeListener.onTextSizeChanged(this, oldTextSize);
}
}

public void setOnTextSizeChangeListener(OnTextSizeChangeListener listener) {
mOnTextSizeChangeListener = listener;
}

public float getVariableTextSize(String text) {
if (mWidthConstraint < 0 || mMaximumTextSize <= mMinimumTextSize) {
// Not measured, bail early.
return getTextSize();
}

// Capture current paint state.
mTempPaint.set(getPaint());

// Step through increasing text sizes until the text would no longer fit.
float lastFitTextSize = mMinimumTextSize;
while (lastFitTextSize < mMaximumTextSize) {
final float nextSize = Math.min(lastFitTextSize + mStepTextSize, mMaximumTextSize);
mTempPaint.setTextSize(nextSize);
if (mTempPaint.measureText(text) > mWidthConstraint) {
break;
} else {
lastFitTextSize = nextSize;
}
}

return lastFitTextSize;
}

@Override
public int getCompoundPaddingTop() {
// Measure the top padding from the capital letter height of the text instead of the top,
// but don't remove more than the available top padding otherwise clipping may occur.
getPaint().getTextBounds("H", 0, 1, mTempRect);

final FontMetricsInt fontMetrics = getPaint().getFontMetricsInt();
final int paddingOffset = -(fontMetrics.ascent + mTempRect.height());
return super.getCompoundPaddingTop() - Math.min(getPaddingTop(), paddingOffset);
}

@Override
public int getCompoundPaddingBottom() {
// Measure the bottom padding from the baseline of the text instead of the bottom, but don't
// remove more than the available bottom padding otherwise clipping may occur.
final FontMetricsInt fontMetrics = getPaint().getFontMetricsInt();
return super.getCompoundPaddingBottom() - Math.min(getPaddingBottom(), fontMetrics.descent);
}

public interface OnTextSizeChangeListener {
void onTextSizeChanged(TextView textView, float oldSize);
}
}
42 changes: 38 additions & 4 deletions app/src/main/java/com/example/arch1/testapplication/Evaluate.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Stack;
import java.util.regex.Pattern;

Expand All @@ -28,7 +30,7 @@ public static String calculateResult(String equ, Boolean enableNumberFormatter,
String ans = new Evaluate().getAnswer(equ);
if (ans.equals("-0"))
ans = "0";
if (enableNumberFormatter)
if (enableNumberFormatter && !(ans.contains("E")))
return formatString(ans);
return ans;
}
Expand Down Expand Up @@ -154,6 +156,9 @@ public static String roundMyAnswer(String ans) {

if (num.compareTo(new BigDecimal("0")) == 0)
return "0";
if(preferences.getBooleanPreference(AppPreferences.APP_SCIENTIFIC_RESULT)) {
return toScientific(num.toPlainString());
}
return num.toPlainString();
}

Expand Down Expand Up @@ -268,6 +273,26 @@ static boolean isNumber(char c) {
return false;
}

private static String format(BigDecimal x, int scale) {
NumberFormat formatter = new DecimalFormat("0.0E0");
formatter.setRoundingMode(RoundingMode.HALF_UP);
formatter.setMinimumFractionDigits(scale);
formatter.setMinimumIntegerDigits(1);
return formatter.format(x);
}

private static String toScientific(String ans) {
String temp = ans;
int scale = 7;
while (temp.length()>11) {
temp = format(new BigDecimal(temp), scale);
scale--;
if(scale==1)
break;
}
return temp;
}

//you provide the equation, it will give the result
private String getAnswer(String equation) {

Expand Down Expand Up @@ -802,9 +827,18 @@ private String getValue(Stack<String> token) throws Exception {
temp = workingStack.pop();

if (temp.equals("^")) {
Double num1 = Double.parseDouble(stack.pop());
Double num2 = Double.parseDouble(workingStack.pop());
stack.push(Math.pow(num1, num2) + "");
BigDecimal num1 = new BigDecimal(stack.pop());
int num2 = Integer.parseInt(workingStack.pop());
if(num2>0) {
try {
stack.push(num1.pow(num2).toPlainString());
} catch (ArithmeticException e) {
errMsg = "Number too large";
return null;
}
} else {
stack.push(Math.pow(num1.doubleValue(), num2) + "");
}
} else
stack.push(temp);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
import android.util.TypedValue;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.Switch;

public class GeneralSettingsActivity extends AppCompatActivity {

private AppPreferences preferences;
private Switch numberFormatterSwitch, smartCalculationSwitch;
private Switch numberFormatterSwitch, smartCalculationSwitch, scientificResultSwitch;

@Override
protected void onCreate(Bundle savedInstanceState) {
Expand Down Expand Up @@ -62,37 +63,34 @@ public void onClick(View v) {

numberFormatterSwitch = findViewById(R.id.switch1);
smartCalculationSwitch = findViewById(R.id.switch2);
scientificResultSwitch = findViewById(R.id.switch3);


//setting preference values
numberFormatterSwitch.setChecked(preferences.getBooleanPreference(AppPreferences.APP_NUMBER_FORMATTER));
smartCalculationSwitch.setChecked(preferences.getBooleanPreference(AppPreferences.APP_SMART_CALCULATIONS));


numberFormatterSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
preferences.setBooleanPreference(AppPreferences.APP_NUMBER_FORMATTER, isChecked);
scientificResultSwitch.setChecked(preferences.getBooleanPreference(AppPreferences.APP_SCIENTIFIC_RESULT));

numberFormatterSwitch.setOnCheckedChangeListener((buttonView, isChecked) ->
preferences.setBooleanPreference(AppPreferences.APP_NUMBER_FORMATTER, isChecked));

smartCalculationSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (!isChecked) {
//show warning
AlertDialog.Builder builder = new AlertDialog.Builder(GeneralSettingsActivity.this);
builder.setTitle("Warning")
.setMessage("This action will disable smart calculations. Calculator Plus" +
" will no longer be able to auto-complete or auto-correct " +
"your equations. We recommend to enable this feature for faster and " +
"easy usage of Calculator Plus.")
.setPositiveButton("Ok", null);
builder.show();
}
preferences.setBooleanPreference(AppPreferences.APP_SMART_CALCULATIONS, isChecked);
});

smartCalculationSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (!isChecked) {
//show warning
AlertDialog.Builder builder = new AlertDialog.Builder(GeneralSettingsActivity.this);
builder.setTitle("Warning")
.setMessage("This action will disable smart calculations. Calculator Plus" +
" will no longer be able to auto-complete or auto-correct " +
"your equations. We recommend to enable this feature for faster and " +
"easy usage of Calculator Plus.")
.setPositiveButton("Ok", null);
builder.show();
}
preferences.setBooleanPreference(AppPreferences.APP_SMART_CALCULATIONS, isChecked);
}
});
scientificResultSwitch.setOnCheckedChangeListener((buttonView, isChecked) ->
preferences.setBooleanPreference(AppPreferences.APP_SCIENTIFIC_RESULT, isChecked));

}

Expand All @@ -103,4 +101,8 @@ public void smartCalClick(View view) {
public void numFormatClick(View view) {
numberFormatterSwitch.setChecked(!numberFormatterSwitch.isChecked());
}

public void scientificResultClick(View view) {
scientificResultSwitch.setChecked(!scientificResultSwitch.isChecked());
}
}
Loading

0 comments on commit fde8dec

Please sign in to comment.