package de.pointedears.converter.app;
import java.text.DateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map.Entry;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.text.Editable;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import de.pointedears.converter.R;
import de.pointedears.converter.db.ConversionData;
import de.pointedears.converter.db.CurrenciesDatabase;
import de.pointedears.converter.helpers.Notifier;
import de.pointedears.converter.helpers.UpdateService;
/**
* Activity that implements currency conversion
*
* @author pelinux
*/
public class CurrenciesActivity
extends Activity
{
/**
* String to use to indicate that an exchange rate has never been updated
*/
private String TEXT_NEVER
;
/*
* Constants for mapping value strings
*
* @todo: Use resource IDs
*/
/**
* Database field/spinner value for Swiss Francs
*/
public static String VALUE_CHF
;
/**
* Database field/spinner value for Euros
*/
public static String VALUE_EUR
;
/**
* Database field/spinner value for US Dollars
*/
public static String VALUE_USD
;
/* Unit spinners (dropdowns) */
private Spinner spinnerUnit1
;
private Spinner spinnerUnit2
;
private static CurrenciesDatabase database
;
private static HashMap<String, ConversionData
> conversionRates
;
private static String EXCHANGE_RATES_UPDATED_TO
;
private final static DateFormat dateFormatter =
DateFormat
.
getDateInstance(DateFormat.
SHORT);
/**
* Receiver for intent broadcasts, registered in
* {@link CurrenciesActivity#onCreate(Bundle)}
*/
public class UpdateBroadcastReceiver
extends BroadcastReceiver
{
/**
* Notification message template
*/
/*
* (non-Javadoc)
*
* @see android.content.BroadcastReceiver#onReceive(android.content.Context,
* android.content.Intent)
*/
@
Override
public void onReceive
(Context context, Intent intent
)
{
if (intent.
getAction().
equals(UpdateService.
ACTION_UPDATE))
{
CurrenciesActivity.
this.
fillTableRates();
Bundle extras = intent.
getExtras();
Notifier.
sendMessage(
CurrenciesActivity.
this,
extras.
get(UpdateService.
EXTRA_NUM_RATES)
+ CurrenciesActivity.
EXCHANGE_RATES_UPDATED_TO
+ CurrenciesActivity.
dateFormatter.
format(extras
.
get(UpdateService.
EXTRA_DATE)));
}
}
}
/** Called when the activity is first created. */
@
Override
public void onCreate
(Bundle savedInstanceState
)
{
super.
onCreate(savedInstanceState
);
this.
setContentView(R.
layout.
activity_currencies);
this.
TEXT_NEVER =
this.
getString(R.
string.
currencies_never_updated);
CurrenciesActivity.
VALUE_CHF =
this.
getString(R.
string.
currencies_CHF);
CurrenciesActivity.
VALUE_EUR =
this.
getString(R.
string.
currencies_EUR);
CurrenciesActivity.
VALUE_USD =
this.
getString(R.
string.
currencies_USD);
CurrenciesActivity.
EXCHANGE_RATES_UPDATED_TO =
this.
getString(R.
string.
currencies_notification);
UpdateBroadcastReceiver br =
new UpdateBroadcastReceiver
();
this.
registerReceiver(br,
new IntentFilter
(UpdateService.
ACTION_UPDATE));
/* Set up currency database, and retrieve conversion rates */
CurrenciesActivity.
database =
new CurrenciesDatabase
(this);
this.
setConversionRates(CurrenciesActivity.
database
.
getConversionRates());
this.
fillTableRates();
final EditText editValue1 =
(EditText
) this.
findViewById(R.
id.
currencies_edit_value1);
final EditText editValue2 =
(EditText
) this.
findViewById(R.
id.
currencies_edit_value2);
final OnKeyListener editValue1OnKey =
new OnKeyListener
() {
@
Override
public boolean onKey
(View v,
int keyCode,
KeyEvent event
)
{
Editable editable1 =
((EditText
) v
).
getText();
Double value1
;
try
{
value1 =
Double.
parseDouble(editable1.
toString());
}
catch (NumberFormatException e
)
{
value1 =
null;
}
String string2 =
""; //$NON-NLS-1$
if (value1
!=
null)
{
string2 = CurrenciesActivity.
this.
getConvertedValue(value1,
false);
}
editValue2.
setText(string2
);
return false;
}
};
editValue1.
setOnKeyListener(editValue1OnKey
);
final OnKeyListener editValue2OnKey =
new OnKeyListener
() {
@
Override
public boolean onKey
(View v,
int keyCode,
KeyEvent event
)
{
Editable editable2 =
((EditText
) v
).
getText();
Double value2
;
try
{
value2 =
Double.
parseDouble(editable2.
toString());
}
catch (NumberFormatException e
)
{
value2 =
null;
}
String string1 =
""; //$NON-NLS-1$
if (value2
!=
null)
{
string1 = CurrenciesActivity.
this.
getConvertedValue(value2,
true);
}
editValue1.
setText(string1
);
return false;
}
};
editValue2.
setOnKeyListener(editValue2OnKey
);
this.
spinnerUnit1 =
(Spinner
) this.
findViewById(R.
id.
currencies_spinner_unit1);
this.
spinnerUnit2 =
(Spinner
) this.
findViewById(R.
id.
currencies_spinner_unit2);
this.
spinnerUnit1.
setOnItemSelectedListener(new OnItemSelectedListener
() {
@
Override
public void onItemSelected
(AdapterView
<?> arg0,
View arg1,
int arg2,
long arg3
)
{
/* Simulate input in second EditText so that first EditText is updated */
editValue2OnKey.
onKey(editValue2,
0,
null);
}
@
Override
public void onNothingSelected
(AdapterView
<?> arg0
)
{
/* no-op */
}
});
this.
spinnerUnit2.
setSelection(1);
this.
spinnerUnit2.
setOnItemSelectedListener(new OnItemSelectedListener
() {
@
Override
public void onItemSelected
(AdapterView
<?> arg0,
View arg1,
int arg2,
long arg3
)
{
/* Simulate input in first EditText so that second EditText is updated */
editValue1OnKey.
onKey(editValue1,
0,
null);
}
@
Override
public void onNothingSelected
(AdapterView
<?> arg0
)
{
/* no-op */
}
});
Button buttonClear =
(Button) this.
findViewById(R.
id.
currencies_button_clear);
buttonClear.
setOnClickListener(new OnClickListener
() {
@
SuppressWarnings("nls")
@
Override
public void onClick
(View v
)
{
editValue1.
setText("");
editValue2.
setText("");
}
});
}
/**
* Fills the table with currency conversion rates
*/
public void fillTableRates
()
{
TableLayout tableRates =
(TableLayout
) this.
findViewById(R.
id.
currencies_table_rates);
/* Remove any pre-existing currency rows */
while (tableRates.
getChildCount() > 3)
{
tableRates.
removeViewAt(3);
}
for (Entry
<String, ConversionData
> factorEntry : CurrenciesActivity
.
getConversionRates()
.
entrySet())
{
TableRow row =
new TableRow
(this);
TextView columnCurrency1 =
new TextView
(this);
columnCurrency1.
setText(factorEntry.
getKey());
row.
addView(columnCurrency1
);
TextView columnRate =
new TextView
(this);
final ConversionData conversionData = factorEntry.
getValue();
columnRate.
setText(conversionData.
getRate().
toString());
row.
addView(columnRate
);
TextView columnUpdated =
new TextView
(this);
Date updated = conversionData.
getUpdated();
if (updated.
getTime() > 0)
{
columnUpdated.
setText(CurrenciesActivity.
dateFormatter.
format(updated
));
}
else
{
columnUpdated.
setText(this.
TEXT_NEVER);
}
row.
addView(columnUpdated
);
tableRates.
addView(row
);
}
}
/**
* @param value
* @return
*/
private String getConvertedValue
(double value,
boolean reverse
)
{
int selectedItemPosition1 =
this.
spinnerUnit1.
getSelectedItemPosition();
int selectedItemPosition2 =
this.
spinnerUnit2.
getSelectedItemPosition();
String[] items =
this.
getResources().
getStringArray(R.
array.
currency_units_values);
String selectedItemValue1 = items
[selectedItemPosition1
];
String selectedItemValue2 = items
[selectedItemPosition2
];
if (reverse
)
{
String tmp = selectedItemValue1
;
selectedItemValue1 = selectedItemValue2
;
selectedItemValue2 = tmp
;
}
Double newValue = value
;
/*
* NOTE: Had to do it the complicated way because somehow the Android SDK
* won't get it another way
*/
ConversionData conversionData1 =
null;
Double factorToEuro =
1.0;
if (selectedItemValue1
!=
null)
{
conversionData1 =
CurrenciesActivity.
getConversionRates().
get(selectedItemValue1
);
if (conversionData1
!=
null)
{
factorToEuro = conversionData1.
getRate();
}
}
ConversionData conversionData2 =
null;
Double factorFromEuro =
1.0;
if (selectedItemValue2
!=
null)
{
conversionData2 =
CurrenciesActivity.
getConversionRates().
get(selectedItemValue2
);
if (conversionData2
!=
null)
{
factorFromEuro = conversionData2.
getRate();
}
}
newValue = newValue / factorToEuro
* factorFromEuro
;
return newValue.
toString();
}
/*
* (non-Javadoc)
*
* @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
*/
/*
* (non-Javadoc)
*
* @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
*/
@
Override
public boolean onCreateOptionsMenu
(Menu menu
)
{
MenuInflater inflater =
this.
getMenuInflater();
inflater.
inflate(R.
menu.
options, menu
);
return true;
}
/*
* (non-Javadoc)
*
* @see android.app.Activity#onOptionsItemSelected(android.view.MenuItem)
*/
@
Override
public boolean onOptionsItemSelected
(MenuItem item
)
{
/* Handle item selection */
switch (item.
getItemId())
{
case R.
id.
item_options_update:
/*
* Request the update service to run a thread to fetch the rates from
* the Web (project requirement)
*/
Intent intent =
new Intent
(this, UpdateService.
class);
intent.
setAction(UpdateService.
ACTION_UPDATE);
this.
startService(intent
);
return true;
default:
return super.
onOptionsItemSelected(item
);
}
}
/**
* @return the conversionRates
*/
public static HashMap<String, ConversionData
> getConversionRates
()
{
return CurrenciesActivity.
conversionRates;
}
/**
* @param conversionRates
* the conversionRates to set
*/
public void setConversionRates
(HashMap<String, ConversionData
> conversionRates
)
{
CurrenciesActivity.
conversionRates = conversionRates
;
}
/**
* @return the database
*/
public static CurrenciesDatabase getDatabase
()
{
return CurrenciesActivity.
database;
}
}