diff --git a/ExaltedDice/AndroidManifest.xml b/ExaltedDice/AndroidManifest.xml
index b15f1d2..5c0e541 100755
--- a/ExaltedDice/AndroidManifest.xml
+++ b/ExaltedDice/AndroidManifest.xml
@@ -5,7 +5,7 @@
android:versionCode="15"
android:versionName="2.0" >
-
+
diff --git a/ExaltedDice/res/drawable/timepicker_down_btn.xml b/ExaltedDice/res/drawable/timepicker_down_btn.xml
new file mode 100755
index 0000000..61a252a
--- /dev/null
+++ b/ExaltedDice/res/drawable/timepicker_down_btn.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ExaltedDice/res/drawable/timepicker_down_disabled.9.png b/ExaltedDice/res/drawable/timepicker_down_disabled.9.png
new file mode 100755
index 0000000..596294b
Binary files /dev/null and b/ExaltedDice/res/drawable/timepicker_down_disabled.9.png differ
diff --git a/ExaltedDice/res/drawable/timepicker_down_disabled_focused.9.png b/ExaltedDice/res/drawable/timepicker_down_disabled_focused.9.png
new file mode 100755
index 0000000..662cffd
Binary files /dev/null and b/ExaltedDice/res/drawable/timepicker_down_disabled_focused.9.png differ
diff --git a/ExaltedDice/res/drawable/timepicker_down_normal.9.png b/ExaltedDice/res/drawable/timepicker_down_normal.9.png
new file mode 100755
index 0000000..f17e8f9
Binary files /dev/null and b/ExaltedDice/res/drawable/timepicker_down_normal.9.png differ
diff --git a/ExaltedDice/res/drawable/timepicker_down_pressed.9.png b/ExaltedDice/res/drawable/timepicker_down_pressed.9.png
new file mode 100755
index 0000000..777bcf5
Binary files /dev/null and b/ExaltedDice/res/drawable/timepicker_down_pressed.9.png differ
diff --git a/ExaltedDice/res/drawable/timepicker_down_selected.9.png b/ExaltedDice/res/drawable/timepicker_down_selected.9.png
new file mode 100755
index 0000000..b45db62
Binary files /dev/null and b/ExaltedDice/res/drawable/timepicker_down_selected.9.png differ
diff --git a/ExaltedDice/res/drawable/timepicker_input.xml b/ExaltedDice/res/drawable/timepicker_input.xml
new file mode 100755
index 0000000..b811d4e
--- /dev/null
+++ b/ExaltedDice/res/drawable/timepicker_input.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ExaltedDice/res/drawable/timepicker_input_disabled.9.png b/ExaltedDice/res/drawable/timepicker_input_disabled.9.png
new file mode 100755
index 0000000..f73658e
Binary files /dev/null and b/ExaltedDice/res/drawable/timepicker_input_disabled.9.png differ
diff --git a/ExaltedDice/res/drawable/timepicker_input_normal.9.png b/ExaltedDice/res/drawable/timepicker_input_normal.9.png
new file mode 100755
index 0000000..8032ada
Binary files /dev/null and b/ExaltedDice/res/drawable/timepicker_input_normal.9.png differ
diff --git a/ExaltedDice/res/drawable/timepicker_input_pressed.9.png b/ExaltedDice/res/drawable/timepicker_input_pressed.9.png
new file mode 100755
index 0000000..30d8d5f
Binary files /dev/null and b/ExaltedDice/res/drawable/timepicker_input_pressed.9.png differ
diff --git a/ExaltedDice/res/drawable/timepicker_input_selected.9.png b/ExaltedDice/res/drawable/timepicker_input_selected.9.png
new file mode 100755
index 0000000..874f18f
Binary files /dev/null and b/ExaltedDice/res/drawable/timepicker_input_selected.9.png differ
diff --git a/ExaltedDice/res/drawable/timepicker_up_btn.xml b/ExaltedDice/res/drawable/timepicker_up_btn.xml
new file mode 100755
index 0000000..5428aee
--- /dev/null
+++ b/ExaltedDice/res/drawable/timepicker_up_btn.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ExaltedDice/res/drawable/timepicker_up_disabled.9.png b/ExaltedDice/res/drawable/timepicker_up_disabled.9.png
new file mode 100755
index 0000000..327b0b5
Binary files /dev/null and b/ExaltedDice/res/drawable/timepicker_up_disabled.9.png differ
diff --git a/ExaltedDice/res/drawable/timepicker_up_disabled_focused.9.png b/ExaltedDice/res/drawable/timepicker_up_disabled_focused.9.png
new file mode 100755
index 0000000..4c96680
Binary files /dev/null and b/ExaltedDice/res/drawable/timepicker_up_disabled_focused.9.png differ
diff --git a/ExaltedDice/res/drawable/timepicker_up_normal.9.png b/ExaltedDice/res/drawable/timepicker_up_normal.9.png
new file mode 100755
index 0000000..dcd26e0
Binary files /dev/null and b/ExaltedDice/res/drawable/timepicker_up_normal.9.png differ
diff --git a/ExaltedDice/res/drawable/timepicker_up_pressed.9.png b/ExaltedDice/res/drawable/timepicker_up_pressed.9.png
new file mode 100755
index 0000000..7dac778
Binary files /dev/null and b/ExaltedDice/res/drawable/timepicker_up_pressed.9.png differ
diff --git a/ExaltedDice/res/drawable/timepicker_up_selected.9.png b/ExaltedDice/res/drawable/timepicker_up_selected.9.png
new file mode 100755
index 0000000..35dae8e
Binary files /dev/null and b/ExaltedDice/res/drawable/timepicker_up_selected.9.png differ
diff --git a/ExaltedDice/res/layout-v11/dice_selector.xml b/ExaltedDice/res/layout-v11/dice_selector.xml
new file mode 100644
index 0000000..8fe85d2
--- /dev/null
+++ b/ExaltedDice/res/layout-v11/dice_selector.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ExaltedDice/res/layout/dice_selector.xml b/ExaltedDice/res/layout/dice_selector.xml
index 8fe85d2..9122535 100644
--- a/ExaltedDice/res/layout/dice_selector.xml
+++ b/ExaltedDice/res/layout/dice_selector.xml
@@ -4,19 +4,17 @@
android:layout_height="wrap_content"
android:orientation="horizontal" >
-
+ android:layout_height="wrap_content" />
-
+ android:layout_height="wrap_content" />
-
diff --git a/ExaltedDice/res/layout/main.xml b/ExaltedDice/res/layout/main.xml
index 9942ae1..b37e8e9 100755
--- a/ExaltedDice/res/layout/main.xml
+++ b/ExaltedDice/res/layout/main.xml
@@ -16,7 +16,7 @@
+ android:layout_weight="2.5" >
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ExaltedDice/res/values/attrs.xml b/ExaltedDice/res/values/attrs.xml
index 68a68fc..14a500b 100644
--- a/ExaltedDice/res/values/attrs.xml
+++ b/ExaltedDice/res/values/attrs.xml
@@ -1,10 +1,19 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/ExaltedDice.java b/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/ExaltedDice.java
index 966e376..24724a2 100755
--- a/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/ExaltedDice.java
+++ b/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/ExaltedDice.java
@@ -44,16 +44,20 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic
private ListView mListView;
private NumberPicker mNumberPicker;
private NumberPicker mDPicker;
+ private NumberPicker mModPicker;
private Database mDb;
private String mGameName;
private long mGameId;
private RollHistoryDatabaseAdapter mListAdapter;
private SharedPreferences mSettings;
private String[] mModValues;
- private NumberPicker mModPicker;
private ProgressBar mRollProgress;
private View mRollButton;
private boolean isRolling = false;
+ private com.TwentyCode.android.ExaltedDice.NumberPicker mCompatDPicker;
+ private com.TwentyCode.android.ExaltedDice.NumberPicker mCompatNumberPicker;
+ private com.TwentyCode.android.ExaltedDice.NumberPicker mCompatModPicker;
+ private boolean isCompat = false;
/**
* Applies the presets from the provided roll
@@ -63,14 +67,66 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic
private void applyRollPresets(long id) {
ContentValues roll = mDb.getGameHistoryInfo(mGameName, (int) (id));
try{
- mNumberPicker.setValue(roll.getAsInteger(Database.KEY_NUMBER));
- mDPicker.setValue(parseD(roll.getAsString(Database.KEY_D_TYPE)));
- mModPicker.setValue(parseMod(roll.getAsString(Database.KEY_MOD).replace("'", "")));
+ if(isCompat){
+ mCompatNumberPicker.setValue(roll.getAsInteger(Database.KEY_NUMBER));
+ mCompatDPicker.setValue(parseD(roll.getAsString(Database.KEY_D_TYPE)));
+ mCompatModPicker.setValue(parseMod(roll.getAsString(Database.KEY_MOD).replace("'", "")));
+ } else {
+ mNumberPicker.setValue(roll.getAsInteger(Database.KEY_NUMBER));
+ mDPicker.setValue(parseD(roll.getAsString(Database.KEY_D_TYPE)));
+ mModPicker.setValue(parseMod(roll.getAsString(Database.KEY_MOD).replace("'", "")));
+ }
} catch(NullPointerException e){
- mModPicker.setValue(parseMod("+0"));
+ if(isCompat)
+ mCompatModPicker.setValue(parseMod("+0"));
+ else
+ mModPicker.setValue(parseMod("+0"));
}
}
+ /**
+ * Initializes compat pickers for api < 11
+ * @author ricky barrette
+ */
+ private void initCompatPickers() {
+ isCompat = true;
+
+ mCompatDPicker = (com.TwentyCode.android.ExaltedDice.NumberPicker) findViewById(R.id.d_Picker);
+ mCompatDPicker.setDisplayedValues(mDiceValues);
+ mCompatDPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
+
+ mCompatNumberPicker = (com.TwentyCode.android.ExaltedDice.NumberPicker) findViewById(R.id.number_Picker);
+ mCompatNumberPicker.setRange(1, 999);
+ mCompatNumberPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
+
+ mCompatModPicker = (com.TwentyCode.android.ExaltedDice.NumberPicker) findViewById(R.id.mod_Picker);
+ mCompatModPicker.setDisplayedValues(mModValues);
+ mCompatModPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
+ }
+
+ /**
+ * Initializes native number pickers api > 11
+ * @author ricky barrette
+ */
+ private void initPickers() {
+ mDPicker = (NumberPicker) findViewById(R.id.d_Picker);
+ mDPicker.setMinValue(0);
+ mDPicker.setMaxValue(mDiceValues.length -1);
+ mDPicker.setDisplayedValues(mDiceValues);
+ mDPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
+
+ mNumberPicker = (NumberPicker) findViewById(R.id.number_Picker);
+ mNumberPicker.setMaxValue(999);
+ mNumberPicker.setMinValue(1);
+ mNumberPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
+
+ mModPicker = (NumberPicker) findViewById(R.id.mod_Picker);
+ mModPicker.setMinValue(0);
+ mModPicker.setMaxValue(mModValues.length -1);
+ mModPicker.setDisplayedValues(mModValues);
+ mModPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
+ }
+
/**
* also implemented OnClickListener
*
@@ -113,13 +169,21 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic
Log.i(TAG, "onCreate()");
setContentView(R.layout.main);
+ mSettings = getSharedPreferences(Settings.SETTINGS, Context.MODE_WORLD_WRITEABLE);
+
+ mDiceValues = getResources().getStringArray(R.array.dice_types);
+ mModValues = getResources().getStringArray(R.array.mods);
+
/*
* The following is for api 11 and up
+ * else use compat methods
*/
if(Integer.valueOf(android.os.Build.VERSION.SDK) > 11){
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
- }
+ initPickers();
+ } else
+ initCompatPickers();
Intent i = this.getIntent();
if(i != null)
@@ -129,32 +193,10 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic
this.setTitle(mGameName);
}
- mSettings = getSharedPreferences(Settings.SETTINGS, Context.MODE_WORLD_WRITEABLE);
-
- mDiceValues = getResources().getStringArray(R.array.dice_types);
- mModValues = getResources().getStringArray(R.array.mods);
-
mListView = (ListView) findViewById(R.id.list);
mListView.setOnItemClickListener(this);
mListView.setStackFromBottom(true);
- mDPicker = (NumberPicker) findViewById(R.id.d_Picker);
- mDPicker.setMinValue(0);
- mDPicker.setMaxValue(mDiceValues.length -1);
- mDPicker.setDisplayedValues(mDiceValues);
- mDPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
-
- mNumberPicker = (NumberPicker) findViewById(R.id.number_Picker);
- mNumberPicker.setMaxValue(999);
- mNumberPicker.setMinValue(1);
- mNumberPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
-
- mModPicker = (NumberPicker) findViewById(R.id.mod_Picker);
- mModPicker.setMinValue(0);
- mModPicker.setMaxValue(mModValues.length -1);
- mModPicker.setDisplayedValues(mModValues);
- mModPicker.setDescendantFocusability(NumberPicker.FOCUS_BLOCK_DESCENDANTS);
-
mRollProgress = (ProgressBar) findViewById(R.id.roll_progress);
mRollButton = findViewById(R.id.roll_button);
@@ -183,6 +225,40 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic
return true;
}
+ @Override
+ public void onDatabaseInsertComplete() {
+ isRolling = false;
+ this.runOnUiThread(new Runnable(){
+ @Override
+ public void run(){
+ mRollProgress.setVisibility(View.GONE);
+ mRollButton.setEnabled(true);
+ refresh();
+ }
+ });
+ }
+
+ @Override
+ public void onDatabaseUpgrade() {
+ //do nothing
+ }
+
+ @Override
+ public void onDatabaseUpgradeComplete() {
+ // do nothing
+
+ }
+
+ @Override
+ public void onDeletionComplete() {
+ this.runOnUiThread(new Runnable(){
+ @Override
+ public void run(){
+ refresh();
+ }
+ });
+ }
+
/**
* rolls same amount of dice as previous roll
* @author ricky barrette
@@ -220,29 +296,31 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic
return super.onOptionsItemSelected(item);
}
}
-
- /**
- * (non-Javadoc)
- * @see android.app.Activity#onPause()
- */
- @Override
- protected void onStop() {
- mDb.close();
- super.onStop();
+
+ @Override
+ public void onRestoreComplete() {
+ // do nothing
}
+
/**
- * resorts application state after rotation
- * @author ricky barrette
- */
- @Override
- public void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- mDPicker.setValue(savedInstanceState.getInt("d"));
- mNumberPicker.setValue(savedInstanceState.getInt("number"));
- mModPicker.setValue(savedInstanceState.getInt("mod"));
- }
+ * resorts application state after rotation
+ * @author ricky barrette
+ */
+ @Override
+ public void onRestoreInstanceState(Bundle savedInstanceState) {
+ super.onRestoreInstanceState(savedInstanceState);
+ if(isCompat){
+ mCompatDPicker.setCurrent(savedInstanceState.getInt("d"));
+ mCompatNumberPicker.setCurrent(savedInstanceState.getInt("number"));
+ mCompatModPicker.setCurrent(savedInstanceState.getInt("mod"));
+ } else {
+ mDPicker.setValue(savedInstanceState.getInt("d"));
+ mNumberPicker.setValue(savedInstanceState.getInt("number"));
+ mModPicker.setValue(savedInstanceState.getInt("mod"));
+ }
+ }
- /**
+ /**
* (non-Javadoc)
* @see android.app.Activity#onResume()
*/
@@ -252,15 +330,41 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic
applyRollPresets(mDb.getGameRollCount(mGameId));
if(mSettings.getBoolean(Settings.KEY_ROLL_MOD, true)){
- mModPicker.setVisibility(View.VISIBLE);
+ if(isCompat)
+ mCompatModPicker.setVisibility(View.VISIBLE);
+ else
+ mModPicker.setVisibility(View.VISIBLE);
} else {
- mModPicker.setVisibility(View.GONE);
- mModPicker.setValue(parseMod("+0"));
+ if(isCompat){
+ mCompatModPicker.setVisibility(View.GONE);
+ mCompatModPicker.setValue(parseMod("+0"));
+ } else {
+ mModPicker.setVisibility(View.GONE);
+ mModPicker.setValue(parseMod("+0"));
+ }
}
super.onResume();
}
+
+ /**
+ * saves application state before rotation
+ * @author ricky barrette
+ */
+ @Override
+ public void onSaveInstanceState(Bundle savedInstanceState) {
+ if(isCompat){
+ savedInstanceState.putInt("d", mCompatDPicker.getCurrent());
+ savedInstanceState.putInt("number", mCompatNumberPicker.getCurrent());
+ savedInstanceState.putInt("mod", mCompatModPicker.getCurrent());
+ } else {
+ savedInstanceState.putInt("d", mDPicker.getValue());
+ savedInstanceState.putInt("number", mNumberPicker.getValue());
+ savedInstanceState.putInt("mod", mModPicker.getValue());
+ }
+ super.onSaveInstanceState(savedInstanceState);
+ }
- /**
+ /**
* (non-Javadoc)
* @see android.app.Activity#onStart()
*/
@@ -273,15 +377,13 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic
}
/**
- * saves application state before rotation
- * @author ricky barrette
+ * (non-Javadoc)
+ * @see android.app.Activity#onPause()
*/
@Override
- public void onSaveInstanceState(Bundle savedInstanceState) {
- savedInstanceState.putInt("d", mDPicker.getValue());
- savedInstanceState.putInt("number", mNumberPicker.getValue());
- savedInstanceState.putInt("mod", mModPicker.getValue());
- super.onSaveInstanceState(savedInstanceState);
+ protected void onStop() {
+ mDb.close();
+ super.onStop();
}
/**
@@ -296,8 +398,8 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic
return i;
return 0;
}
-
- /**
+
+ /**
* Parses the string mod to the appropriate value
* @param mod
* @return value for d picker
@@ -332,7 +434,7 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic
});
builder.show();
}
-
+
/**
* Refreshes the list view
* @author ricky barrette
@@ -366,7 +468,10 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic
resultsString.append(getString(R.string.total)+ total);
if(mSettings.getBoolean(Settings.KEY_ROLL_MOD, true))
- resultsString.append(getString(R.string.total_plus_mod)+ (total + Integer.parseInt(mModValues[mModPicker.getValue()].replace("+", ""))));
+ if(isCompat)
+ resultsString.append(getString(R.string.total_plus_mod)+ (total + Integer.parseInt(mCompatModPicker.getValue().replace("+", ""))));
+ else
+ resultsString.append(getString(R.string.total_plus_mod)+ (total + Integer.parseInt(mModValues[mModPicker.getValue()].replace("+", ""))));
if(mSettings.getBoolean(Settings.KEY_CALC_SUCCESSES, true))
resultsString.append(getString(R.string.sucesses)+ successes(roll));
@@ -399,11 +504,20 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic
int rollId = mDb.getGameRollCount(mGameId) +1;
ContentValues roll = new ContentValues();
- roll.put(Database.KEY_D_TYPE, mDiceValues[mDPicker.getValue()]);
- roll.put(Database.KEY_NUMBER, mNumberPicker.getValue());
- roll.putAll(results(mNumberPicker.getValue()));
- roll.put(Database.KEY_MOD, DatabaseUtils.sqlEscapeString(mModValues[mModPicker.getValue()]));
+ if(isCompat){
+ roll.put(Database.KEY_D_TYPE, mCompatDPicker.getValue());
+ roll.put(Database.KEY_NUMBER, mCompatNumberPicker.getCurrent());
+ roll.putAll(results(mCompatNumberPicker.getCurrent()));
+ roll.put(Database.KEY_MOD, DatabaseUtils.sqlEscapeString(mCompatModPicker.getValue()));
+ } else{
+ roll.put(Database.KEY_D_TYPE, mDiceValues[mDPicker.getValue()]);
+ roll.put(Database.KEY_NUMBER, mNumberPicker.getValue());
+ roll.putAll(results(mNumberPicker.getValue()));
+ roll.put(Database.KEY_MOD, DatabaseUtils.sqlEscapeString(mModValues[mModPicker.getValue()]));
+ }
+
+
mDb.updateGame(mGameId, mGameName, roll, rollId);
}
@@ -422,7 +536,10 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic
int[] roll = new int[times];
Random random = new Random();
for (int i = 0; i < times; i++) {
- roll[i] = random.nextInt(Integer.parseInt(mDiceValues[mDPicker.getValue()].substring(1))) + 1;
+ if(isCompat)
+ roll[i] = random.nextInt(Integer.parseInt(mCompatDPicker.getValue().substring(1))) + 1;
+ else
+ roll[i] = random.nextInt(Integer.parseInt(mDiceValues[mDPicker.getValue()].substring(1))) + 1;
}
return roll;
}
@@ -470,43 +587,4 @@ public class ExaltedDice extends Activity implements OnClickListener, OnItemClic
Vibrator vib = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vib.vibrate(milliseconds);
}
-
- @Override
- public void onDatabaseUpgradeComplete() {
- // do nothing
-
- }
-
- @Override
- public void onDeletionComplete() {
- this.runOnUiThread(new Runnable(){
- @Override
- public void run(){
- refresh();
- }
- });
- }
-
- @Override
- public void onRestoreComplete() {
- // do nothing
- }
-
- @Override
- public void onDatabaseUpgrade() {
- //do nothing
- }
-
- @Override
- public void onDatabaseInsertComplete() {
- isRolling = false;
- this.runOnUiThread(new Runnable(){
- @Override
- public void run(){
- mRollProgress.setVisibility(View.GONE);
- mRollButton.setEnabled(true);
- refresh();
- }
- });
- }
}
\ No newline at end of file
diff --git a/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/NumberPicker.java b/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/NumberPicker.java
new file mode 100755
index 0000000..8f7409a
--- /dev/null
+++ b/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/NumberPicker.java
@@ -0,0 +1,488 @@
+/**
+ * Number Picker.java
+ *
+ * @author Google
+ * @author ricky barrette
+ * @author Twenty Codes
+ *
+ * Copyright (C) 2012 Rick barrette
+ * Copyright (C) 2012 Twenty Codes
+ * Copyright (C) 2008 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.TwentyCode.android.ExaltedDice;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.os.Handler;
+import android.text.InputFilter;
+import android.text.InputType;
+import android.text.Spanned;
+import android.text.method.NumberKeyListener;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnFocusChangeListener;
+import android.view.View.OnLongClickListener;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+/**
+ * This class has been pulled from the Android platform source code, its an internal widget that hasn't been
+ * made public so its included in the project in this fashion for use with the preferences screen; I have made
+ * a few slight modifications to the code here, I simply put a MAX and MIN default in the code but these values
+ * can still be set publicly by calling code.
+ *
+ * @author Google
+ */
+public class NumberPicker extends LinearLayout implements OnClickListener, OnFocusChangeListener, OnLongClickListener {
+
+ /**
+ * This class is used to filter the input from a keyboard
+ */
+ private class NumberPickerInputFilter implements InputFilter {
+ public CharSequence filter(CharSequence source, int start, int end,
+ Spanned dest, int dstart, int dend) {
+ if (mDisplayedValues == null) {
+ return mNumberInputFilter.filter(source, start, end, dest, dstart, dend);
+ }
+ CharSequence filtered = String.valueOf(source.subSequence(start, end));
+ String result = String.valueOf(dest.subSequence(0, dstart))
+ + filtered
+ + dest.subSequence(dend, dest.length());
+ String str = String.valueOf(result).toLowerCase();
+ for (String val : mDisplayedValues) {
+ val = val.toLowerCase();
+ if (val.startsWith(str)) {
+ return filtered;
+ }
+ }
+ return "";
+ }
+ }
+
+ /**
+ * This class
+ */
+ private class NumberRangeKeyListener extends NumberKeyListener {
+
+ @Override
+ public CharSequence filter(CharSequence source, int start, int end,
+ Spanned dest, int dstart, int dend) {
+
+ CharSequence filtered = super.filter(source, start, end, dest, dstart, dend);
+ if (filtered == null) {
+ filtered = source.subSequence(start, end);
+ }
+
+ String result = String.valueOf(dest.subSequence(0, dstart))
+ + filtered
+ + dest.subSequence(dend, dest.length());
+
+ if ("".equals(result)) {
+ return result;
+ }
+ int val = getSelectedPos(result);
+
+ /* Ensure the user can't type in a value greater
+ * than the max allowed. We have to allow less than min
+ * as the user might want to delete some numbers
+ * and then type a new number.
+ */
+ if (val > mEnd) {
+ return "";
+ } else {
+ return filtered;
+ }
+ }
+
+ @Override
+ protected char[] getAcceptedChars() {
+ return DIGIT_CHARACTERS;
+ }
+
+ // XXX This doesn't allow for range limits when controlled by a
+ // soft input method!
+ public int getInputType() {
+ return InputType.TYPE_CLASS_NUMBER;
+ }
+ }
+
+ /**
+ * A simple interface to notify a change has been made
+ */
+ public interface OnChangedListener {
+ /**
+ * Called when a change has been made
+ * @param picker
+ * @param oldVal
+ * @param newVal
+ */
+ void onChanged(NumberPicker picker, int oldVal, int newVal);
+ }
+
+ private static final int DEFAULT_MAX = 200;
+ private static final int DEFAULT_MIN = 0;
+ private static final int DEFAULT_VALUE = 0;
+ private static final boolean DEFAULT_WRAP = true;
+ private final Handler mHandler;
+ private final EditText mText;
+ private final InputFilter mNumberInputFilter;
+
+ private final Runnable mRunnable = new Runnable() {
+ public void run() {
+ if (mIncrement) {
+ changeCurrent(mCurrent + 1);
+ mHandler.postDelayed(this, mSpeed);
+ } else if (mDecrement) {
+ changeCurrent(mCurrent - 1);
+ mHandler.postDelayed(this, mSpeed);
+ }
+ }
+ };
+
+ private String[] mDisplayedValues;
+ protected int mStart;
+ protected int mEnd;
+ protected int mCurrent;
+ protected int mPrevious;
+ private OnChangedListener mListener;
+ private long mSpeed = 300;
+ private boolean mIncrement;
+ private boolean mDecrement;
+ private NumberPickerButton mIncrementButton;
+ private NumberPickerButton mDecrementButton;
+ private boolean mWrap;
+ private static final char[] DIGIT_CHARACTERS = new char[] {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
+ };
+
+ /**
+ * Creates a new NumberPicker
+ * @param context
+ */
+ public NumberPicker(Context context) {
+ this(context, null);
+ }
+
+ /**
+ * Creates a new NumberPicker
+ * @param context
+ * @param attrs
+ * @author ricky barrette
+ */
+ public NumberPicker(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ /**
+ * Creates a new NumberPicker
+ * @param context
+ * @param attrs
+ * @param defStyle
+ * @author ricky barrette
+ */
+ public NumberPicker(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs);
+
+ setOrientation(VERTICAL);
+ LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ inflater.inflate(R.layout.number_picker, this, true);
+ mHandler = new Handler();
+ InputFilter inputFilter = new NumberPickerInputFilter();
+ mNumberInputFilter = new NumberRangeKeyListener();
+ mIncrementButton = (NumberPickerButton) findViewById(R.id.increment);
+ mIncrementButton.setOnClickListener(this);
+ mIncrementButton.setOnLongClickListener(this);
+ mIncrementButton.setNumberPicker(this);
+ mDecrementButton = (NumberPickerButton) findViewById(R.id.decrement);
+ mDecrementButton.setOnClickListener(this);
+ mDecrementButton.setOnLongClickListener(this);
+ mDecrementButton.setNumberPicker(this);
+
+ mText = (EditText) findViewById(R.id.timepicker_input);
+ mText.setOnFocusChangeListener(this);
+ mText.setFilters(new InputFilter[] {inputFilter});
+ mText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
+
+ if (!isEnabled()) {
+ setEnabled(false);
+ }
+
+ TypedArray a = context.obtainStyledAttributes( attrs, R.styleable.numberpicker );
+ mStart = a.getInt( R.styleable.numberpicker_startRange, DEFAULT_MIN );
+ mEnd = a.getInt( R.styleable.numberpicker_endRange, DEFAULT_MAX );
+ mWrap = a.getBoolean( R.styleable.numberpicker_wrap, DEFAULT_WRAP );
+ mCurrent = a.getInt( R.styleable.numberpicker_defaultValue, DEFAULT_VALUE );
+ mCurrent = Math.max( mStart, Math.min( mCurrent, mEnd ) );
+ mText.setText( "" + mCurrent );
+ }
+
+ public void cancelDecrement() {
+ mDecrement = false;
+ }
+
+ public void cancelIncrement() {
+ mIncrement = false;
+ }
+
+
+ protected void changeCurrent(int current) {
+ // Wrap around the values if we go past the start or end
+ if (current > mEnd) {
+ current = mWrap ? mStart : mEnd;
+ } else if (current < mStart) {
+ current = mWrap ? mEnd : mStart;
+ }
+ mPrevious = mCurrent;
+ mCurrent = current;
+
+ notifyChange();
+ updateView();
+ }
+
+ /**
+ * @return the current value.
+ */
+ public int getCurrent() {
+ return mCurrent;
+ }
+
+ private int getSelectedPos(String str) {
+ if (mDisplayedValues == null) {
+ return Integer.parseInt(str);
+ } else {
+ for (int i = 0; i < mDisplayedValues.length; i++) {
+
+ /* Don't force the user to type in jan when ja will do */
+ str = str.toLowerCase();
+ if (mDisplayedValues[i].toLowerCase().startsWith(str)) {
+ return mStart + i;
+ }
+ }
+
+ /* The user might have typed in a number into the month field i.e.
+ * 10 instead of OCT so support that too.
+ */
+ try {
+ return Integer.parseInt(str);
+ } catch (NumberFormatException e) {
+
+ /* Ignore as if it's not a number we don't care */
+ }
+ }
+ return mStart;
+ }
+
+ public String getValue() {
+ return this.mDisplayedValues[mCurrent];
+ }
+
+ protected void notifyChange() {
+ if (mListener != null) {
+ mListener.onChanged(this, mPrevious, mCurrent);
+ }
+ }
+
+ public void onClick(View v) {
+ validateInput(mText);
+ if (!mText.hasFocus()) mText.requestFocus();
+
+ // now perform the increment/decrement
+ if (R.id.increment == v.getId()) {
+ changeCurrent(mCurrent + 1);
+ } else if (R.id.decrement == v.getId()) {
+ changeCurrent(mCurrent - 1);
+ }
+ }
+
+ public void onFocusChange(View v, boolean hasFocus) {
+
+ /* When focus is lost check that the text field
+ * has valid values.
+ */
+ if (!hasFocus) {
+ validateInput(v);
+ }
+ }
+
+ /**
+ * We start the long click here but rely on the {@link NumberPickerButton}
+ * to inform us when the long click has ended.
+ */
+ public boolean onLongClick(View v) {
+
+ /* The text view may still have focus so clear it's focus which will
+ * trigger the on focus changed and any typed values to be pulled.
+ */
+ mText.clearFocus();
+ mText.requestFocus();
+ if (R.id.increment == v.getId()) {
+ mIncrement = true;
+ mHandler.post(mRunnable);
+ } else if (R.id.decrement == v.getId()) {
+ mDecrement = true;
+ mHandler.post(mRunnable);
+ }
+
+ return true;
+ }
+
+ /**
+ * Sets the current index
+ * @param index
+ */
+ public void setCurrent(int index) {
+ mCurrent = index;
+ updateView();
+ }
+
+ /**
+ * Sets the current index and notifies listeners
+ * @param index
+ */
+ public void setCurrentAndNotify(int index) {
+ mCurrent = index;
+ notifyChange();
+ updateView();
+ }
+
+ /**
+ * Sets the values to display
+ * @param values
+ * @author ricky barrette
+ */
+ public void setDisplayedValues(String[] values) {
+ this.mDisplayedValues = values;
+ this.mStart = 0;
+ this.mEnd = values.length -1;
+ notifyChange();
+ updateView();
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ super.setEnabled(enabled);
+ mIncrementButton.setEnabled(enabled);
+ mDecrementButton.setEnabled(enabled);
+ mText.setEnabled(enabled);
+ }
+
+ public void setOnChangeListener(OnChangedListener listener) {
+ mListener = listener;
+ }
+
+ /**
+ * Set the range of numbers allowed for the number picker. The current
+ * value will be automatically set to the start.
+ *
+ * @param start the start of the range (inclusive)
+ * @param end the end of the range (inclusive)
+ */
+ public void setRange(int start, int end) {
+ mStart = start;
+ mEnd = end;
+ mCurrent = start;
+ updateView();
+ }
+
+ /**
+ * Set the range of numbers allowed for the number picker. The current
+ * value will be automatically set to the start. Also provide a mapping
+ * for values used to display to the user.
+ *
+ * @param start the start of the range (inclusive)
+ * @param end the end of the range (inclusive)
+ * @param displayedValues the values displayed to the user.
+ */
+ public void setRange(int start, int end, String[] displayedValues) {
+ mDisplayedValues = displayedValues;
+ mStart = start;
+ mEnd = end;
+ mCurrent = start;
+ updateView();
+ }
+
+ /**
+ * The speed (in milliseconds) at which the numbers will scroll
+ * when the the +/- buttons are longpressed. Default is 300ms.
+ */
+ public void setSpeed(long speed) {
+ mSpeed = speed;
+ }
+
+ /**
+ * Sets the current displayed value by it's index
+ * @param index
+ * @author ricky barrette
+ */
+ public void setValue(int index) {
+ mCurrent = index;
+ notifyChange();
+ updateView();
+ }
+
+ /**
+ * Specify if numbers should wrap after the edge has been reached.
+ *
+ * @param wrap values
+ */
+ public void setWrap( boolean wrap ) {
+ mWrap = wrap;
+ }
+
+ protected void updateView() {
+
+ /* If we don't have displayed values then use the
+ * current number else find the correct value in the
+ * displayed values for the current number.
+ */
+ if (mDisplayedValues == null) {
+ mText.setText(mCurrent+"");
+ } else {
+ mText.setText(mDisplayedValues[mCurrent]);
+ }
+ mText.setSelection(mText.getText().length());
+
+// mText.resizeText();
+ }
+
+ private void validateCurrentView(CharSequence str) {
+ int val = getSelectedPos(str.toString());
+ if ((val >= mStart) && (val <= mEnd)) {
+ if (mCurrent != val) {
+ mPrevious = mCurrent;
+ mCurrent = val;
+ notifyChange();
+ }
+ }
+ updateView();
+ }
+
+ private void validateInput(View v) {
+ String str = String.valueOf(((TextView) v).getText());
+ if ("".equals(str)) {
+
+ // Restore to the old value as we don't allow empty values
+ updateView();
+ } else {
+
+ // Check the new value and ensure it's in range
+ validateCurrentView(str);
+ }
+ }
+}
diff --git a/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/NumberPickerButton.java b/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/NumberPickerButton.java
new file mode 100755
index 0000000..ea9675d
--- /dev/null
+++ b/ExaltedDice/src/com/TwentyCode/android/ExaltedDice/NumberPickerButton.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2008 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.TwentyCode.android.ExaltedDice;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.widget.ImageButton;
+
+/**
+ * This class exists purely to cancel long click events.
+ */
+public class NumberPickerButton extends ImageButton {
+
+ private NumberPicker mNumberPicker;
+
+ public NumberPickerButton(Context context, AttributeSet attrs,
+ int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public NumberPickerButton(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public NumberPickerButton(Context context) {
+ super(context);
+ }
+
+ public void setNumberPicker(NumberPicker picker) {
+ mNumberPicker = picker;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ cancelLongpressIfRequired(event);
+ return super.onTouchEvent(event);
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent event) {
+ cancelLongpressIfRequired(event);
+ return super.onTrackballEvent(event);
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if ((keyCode == KeyEvent.KEYCODE_DPAD_CENTER)
+ || (keyCode == KeyEvent.KEYCODE_ENTER)) {
+ cancelLongpress();
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+
+ private void cancelLongpressIfRequired(MotionEvent event) {
+ if ((event.getAction() == MotionEvent.ACTION_CANCEL)
+ || (event.getAction() == MotionEvent.ACTION_UP)) {
+ cancelLongpress();
+ }
+ }
+
+ private void cancelLongpress() {
+ if (R.id.increment == getId()) {
+ mNumberPicker.cancelIncrement();
+ } else if (R.id.decrement == getId()) {
+ mNumberPicker.cancelDecrement();
+ }
+ }
+}
diff --git a/project.properties b/project.properties
new file mode 100644
index 0000000..cd9c350
--- /dev/null
+++ b/project.properties
@@ -0,0 +1,13 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Indicates whether an apk should be generated for each density.
+split.density=false
+# Project target.
+target=android-15