release notes + welcome window

This commit is contained in:
Sergey Solovyev
2011-12-25 02:54:47 +04:00
parent 53caff263c
commit 4a2511b93c
19 changed files with 382 additions and 44 deletions

View File

@@ -15,6 +15,7 @@ import android.os.Bundle;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.text.ClipboardManager;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.util.TypedValue;
@@ -26,15 +27,18 @@ import jscl.AngleUnit;
import jscl.NumeralBase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.about.CalculatorReleaseNotesActivity;
import org.solovyev.android.calculator.history.CalculatorHistory;
import org.solovyev.android.calculator.history.CalculatorHistoryState;
import org.solovyev.android.calculator.math.MathType;
import org.solovyev.android.calculator.model.CalculatorEngine;
import org.solovyev.android.view.FontSizeAdjuster;
import org.solovyev.android.view.prefs.AndroidUtils;
import org.solovyev.android.view.prefs.ResourceCache;
import org.solovyev.android.view.widgets.*;
import org.solovyev.common.utils.Announcer;
import org.solovyev.common.utils.Point2d;
import org.solovyev.common.utils.StringUtils;
import org.solovyev.common.utils.history.HistoryAction;
import java.text.DecimalFormatSymbols;
@@ -44,6 +48,13 @@ import java.util.Map;
public class CalculatorActivity extends Activity implements FontSizeAdjuster, SharedPreferences.OnSharedPreferenceChangeListener {
private static final int HVGA_WIDTH_PIXELS = 320;
@NotNull
public static final String APP_VERSION_P_KEY = "application.version";
@NotNull
public static final String SHOW_RELEASE_NOTES_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_show_release_notes";
public static final boolean SHOW_RELEASE_NOTES_P_DEFAULT = true;
@NotNull
private final Announcer<DragPreferencesChangeListener> dpclRegister = new Announcer<DragPreferencesChangeListener>(DragPreferencesChangeListener.class);
@@ -348,9 +359,37 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
private synchronized void firstTimeInit(@NotNull SharedPreferences preferences) {
if (!initialized) {
ResourceCache.instance.init(R.id.class, this);
final int savedVersion = preferences.getInt(APP_VERSION_P_KEY, -1);
final int appVersion = AndroidUtils.getAppVersionCode(this, CalculatorActivity.class.getPackage().getName());
final SharedPreferences.Editor pEditor = preferences.edit();
pEditor.putInt(APP_VERSION_P_KEY, appVersion);
pEditor.commit();
if (savedVersion == -1) {
// new start
final AlertDialog.Builder builder = new AlertDialog.Builder(this).setMessage(R.string.c_first_start_text);
builder.setPositiveButton(android.R.string.ok, null);
builder.create().show();
} else {
if (savedVersion < appVersion) {
final boolean showReleaseNotes = preferences.getBoolean(SHOW_RELEASE_NOTES_P_KEY, SHOW_RELEASE_NOTES_P_DEFAULT);
if (showReleaseNotes) {
final String releaseNotes = CalculatorReleaseNotesActivity.getReleaseNotes(this, savedVersion + 1);
if (!StringUtils.isEmpty(releaseNotes)) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this).setMessage(Html.fromHtml(releaseNotes));
builder.setPositiveButton(android.R.string.ok, null);
builder.setTitle(R.string.c_release_notes);
builder.create().show();
}
}
}
}
ResourceCache.instance.init(R.id.class, this);
CalculatorEngine.instance.init(this, preferences);
initialized = true;
}
}

View File

@@ -7,7 +7,8 @@ import jscl.math.Generic;
import jscl.math.function.Constant;
import org.achartengine.ChartFactory;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.help.HelpActivity;
import org.solovyev.android.calculator.about.CalculatorAboutTabActivity;
import org.solovyev.android.calculator.help.CalculatorHelpTabActivity;
import org.solovyev.android.calculator.history.CalculatorHistoryActivity;
import org.solovyev.android.calculator.math.edit.CalculatorFunctionsActivity;
import org.solovyev.android.calculator.math.edit.CalculatorOperatorsActivity;
@@ -27,7 +28,7 @@ public class CalculatorActivityLauncher {
}
public static void showHelp(@NotNull final Context context) {
context.startActivity(new Intent(context, HelpActivity.class));
context.startActivity(new Intent(context, CalculatorHelpTabActivity.class));
}
public static void showSettings(@NotNull final Context context) {
@@ -35,7 +36,7 @@ public class CalculatorActivityLauncher {
}
public static void showAbout(@NotNull final Context context) {
context.startActivity(new Intent(context, AboutActivity.class));
context.startActivity(new Intent(context, CalculatorAboutTabActivity.class));
}
public static void showFunctions(@NotNull final Context context) {

View File

@@ -1,23 +1,24 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.android.calculator;
package org.solovyev.android.calculator.about;
import android.app.Activity;
import android.os.Bundle;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.widget.TextView;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.R;
/**
* User: serso
* Date: 9/16/11
* Time: 11:52 PM
* Date: 12/24/11
* Time: 11:55 PM
*/
public class AboutActivity extends Activity {
public class CalculatorAboutActivity extends Activity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -26,6 +27,5 @@ public class AboutActivity extends Activity {
final TextView about = (TextView) findViewById(R.id.aboutTextView);
about.setMovementMethod(LinkMovementMethod.getInstance());
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
*/
package org.solovyev.android.calculator.about;
import android.app.TabActivity;
import android.os.Bundle;
import android.widget.TabHost;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.R;
import org.solovyev.android.view.prefs.AndroidUtils;
/**
* User: serso
* Date: 9/16/11
* Time: 11:52 PM
*/
public class CalculatorAboutTabActivity extends TabActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tabs);
final TabHost tabHost = getTabHost();
AndroidUtils.addTab(this, tabHost, "about", R.string.c_about, CalculatorAboutActivity.class);
AndroidUtils.addTab(this, tabHost, "release_notes", R.string.c_release_notes, CalculatorReleaseNotesActivity.class);
tabHost.setCurrentTab(0);
AndroidUtils.centerAndWrapTabsFor(tabHost);
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
* For more information, please, contact se.solovyev@gmail.com
* or visit http://se.solovyev.org
*/
package org.solovyev.android.calculator.about;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.widget.TextView;
import org.jetbrains.annotations.NotNull;
import org.solovyev.android.calculator.CalculatorActivity;
import org.solovyev.android.calculator.R;
import org.solovyev.android.view.prefs.AndroidUtils;
import org.solovyev.android.view.prefs.ResourceCache;
import org.solovyev.common.utils.StringUtils;
/**
* User: serso
* Date: 12/25/11
* Time: 12:00 AM
*/
public class CalculatorReleaseNotesActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.release_notes);
final TextView releaseNotes = (TextView) findViewById(R.id.releaseNotesTextView);
releaseNotes.setMovementMethod(LinkMovementMethod.getInstance());
releaseNotes.setText(Html.fromHtml(getReleaseNotes(this)));
}
@NotNull
public static String getReleaseNotes(@NotNull Context context) {
return getReleaseNotes(context, 0);
}
@NotNull
public static String getReleaseNotes(@NotNull Context context, int minVersion) {
final StringBuilder result = new StringBuilder();
final String releaseNotesForTitle = context.getString(R.string.c_release_notes_for_title);
final int version = AndroidUtils.getAppVersionCode(context, CalculatorActivity.class.getPackage().getName());
boolean first = true;
for ( int i = version; i >= minVersion; i-- ) {
String releaseNotesForVersion = ResourceCache.instance.getCaption("c_release_notes_for_" + i);
if (!StringUtils.isEmpty(releaseNotesForVersion)){
assert releaseNotesForVersion != null;
if ( !first ) {
result.append("<br/><br/>");
} else {
first = false;
}
releaseNotesForVersion = releaseNotesForVersion.replace("\n", "<br/>");
result.append("<b>").append(releaseNotesForTitle).append(i).append("</b><br/>");
result.append(releaseNotesForVersion);
}
}
return result.toString();
}
}

View File

@@ -21,7 +21,7 @@ import org.solovyev.android.view.prefs.AndroidUtils;
* Date: 11/19/11
* Time: 11:35 AM
*/
public class HelpActivity extends TabActivity {
public class CalculatorHelpTabActivity extends TabActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {

View File

@@ -6,12 +6,9 @@
package org.solovyev.android.calculator.history;
import android.app.Activity;
import android.app.TabActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TabHost;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.R;
import org.solovyev.android.view.prefs.AndroidUtils;
@@ -31,26 +28,12 @@ public class CalculatorHistoryActivity extends TabActivity {
final TabHost tabHost = getTabHost();
createTab(tabHost, "saved_history", R.string.c_saved_history, SavedHistoryActivityTab.class);
createTab(tabHost, "history", R.string.c_history, HistoryActivityTab.class);
AndroidUtils.addTab(this, tabHost, "saved_history", R.string.c_saved_history, SavedHistoryActivityTab.class);
AndroidUtils.addTab(this, tabHost, "history", R.string.c_history, HistoryActivityTab.class);
tabHost.setCurrentTab(0);
AndroidUtils.centerAndWrapTabsFor(tabHost);
}
private void createTab(@NotNull TabHost tabHost,
@NotNull String tabId,
int tabCaptionId,
@NotNull Class<? extends Activity> activityClass) {
TabHost.TabSpec spec;
final Intent intent = new Intent().setClass(this, activityClass);
// Initialize a TabSpec for each tab and add it to the TabHost
spec = tabHost.newTabSpec(tabId).setIndicator(this.getString(tabCaptionId)).setContent(intent);
tabHost.addTab(spec);
}
}

View File

@@ -6,6 +6,10 @@
package org.solovyev.android.view.prefs;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
@@ -52,4 +56,37 @@ public final class AndroidUtils {
}
}
}
public static void addTab(@NotNull Context context,
@NotNull TabHost tabHost,
@NotNull String tabId,
int tabCaptionId,
@NotNull Class<? extends Activity> activityClass) {
TabHost.TabSpec spec;
final Intent intent = new Intent().setClass(context, activityClass);
// Initialize a TabSpec for each tab and add it to the TabHost
spec = tabHost.newTabSpec(tabId).setIndicator(context.getString(tabCaptionId)).setContent(intent);
tabHost.addTab(spec);
}
/**
* @param context context
* @param appPackageName - full name of the package of an app, 'com.example.app' for example.
* @return version number we are currently in
*/
public static int getAppVersionCode(@NotNull Context context, @NotNull String appPackageName) {
try {
return context.getPackageManager().getPackageInfo(appPackageName, 0).versionCode;
} catch (PackageManager.NameNotFoundException e) {
// App not installed!
}
return -1;
}
}

View File

@@ -8,6 +8,7 @@ package org.solovyev.android.view.prefs;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.Log;
import android.view.View;
@@ -84,24 +85,43 @@ public enum ResourceCache {
if (!initialized(locale)) {
final Map<String, String> captionsByLanguage = new HashMap<String, String>();
for (Field field : resourceClass.getDeclaredFields()) {
int modifiers = field.getModifiers();
if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) {
try {
int captionId = field.getInt(resourceClass);
captionsByLanguage.put(field.getName(), context.getString(captionId));
} catch (IllegalAccessException e) {
Log.e(ResourceCache.class.getName(), e.getMessage());
} catch (Resources.NotFoundException e) {
Log.e(ResourceCache.class.getName(), "Caption with name " + field.getName() + " was not found for " + locale.getLanguage() + " language: " + e.getMessage());
final Locale defaultLocale = Locale.getDefault();
try {
if (!defaultLocale.getLanguage().equals(locale.getLanguage())) {
updateConfiguration(context, locale);
}
for (Field field : resourceClass.getDeclaredFields()) {
int modifiers = field.getModifiers();
if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) {
try {
int captionId = field.getInt(resourceClass);
captionsByLanguage.put(field.getName(), context.getString(captionId));
} catch (IllegalAccessException e) {
Log.e(ResourceCache.class.getName(), e.getMessage());
} catch (Resources.NotFoundException e) {
Log.e(ResourceCache.class.getName(), "Caption with name " + field.getName() + " was not found for " + locale.getLanguage() + " language: " + e.getMessage());
}
}
}
} finally {
if (!defaultLocale.getLanguage().equals(locale.getLanguage())) {
updateConfiguration(context, defaultLocale);
}
}
captions.put(locale.getLanguage(), captionsByLanguage);
}
}
private static void updateConfiguration(@NotNull Context context, @NotNull Locale locale) {
Locale.setDefault(locale);
final Configuration config = new Configuration();
config.locale = locale;
context.getResources().updateConfiguration(config, context.getResources().getDisplayMetrics());
}
private boolean initialized(@NotNull Locale locale) {
return captions.containsKey(locale.getLanguage());
}

View File

@@ -416,7 +416,7 @@ public class CalculatorEngineTest {
Assert.assertEquals("", Expression.valueOf("ln(10)/ln(1)").numeric().toString());
// logarithm
Assert.assertEquals("ln(b)/ln(a)", ((CustomFunction) cm.getFunctionsRegistry().get("log")).getContent());
Assert.assertEquals("ln(x)/ln(base)", ((CustomFunction) cm.getFunctionsRegistry().get("log")).getContent());
Assert.assertEquals("", cm.evaluate(JsclOperation.numeric, "log(1, 10)").getResult());
Assert.assertEquals("3.322", cm.evaluate(JsclOperation.numeric, "log(2, 10)").getResult());
Assert.assertEquals("1.431", cm.evaluate(JsclOperation.numeric, "log(5, 10)").getResult());