/*------------------------------------------------------------------------------ ** Ident: Sogeti Smart Mobile Solutions ** Author: rene ** Copyright: (c) Apr 24, 2011 Sogeti Nederland B.V. All Rights Reserved. **------------------------------------------------------------------------------ ** Sogeti Nederland B.V. | No part of this file may be reproduced ** Distributed Software Engineering | or transmitted in any form or by any ** Lange Dreef 17 | means, electronic or mechanical, for the ** 4131 NJ Vianen | purpose, without the express written ** The Netherlands | permission of the copyright holder. *------------------------------------------------------------------------------ * * This file is part of OpenGPSTracker. * * OpenGPSTracker is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenGPSTracker is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenGPSTracker. If not, see <http://www.gnu.org/licenses/>. * */ package nl.sogeti.android.gpstracker.util; import java.util.Locale; import nl.sogeti.android.gpstracker.R; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.res.Configuration; import android.content.res.Resources; import android.preference.PreferenceManager; import android.util.TypedValue; /** * Collection of methods to provide metric and imperial data based on locale or * overridden by configuration * * @version $Id: UnitsI18n.java 1180 2011-12-27 22:44:01Z rcgroot $ * @author rene (c) Feb 2, 2010, Sogeti B.V. */ public class UnitsI18n { private Context mContext; private double mConversion_from_mps_to_speed; private double mConversion_from_meter_to_distance; private double mConversion_from_meter_to_height; private String mSpeed_unit; private String mDistance_unit; private String mHeight_unit; private UnitsChangeListener mListener; private OnSharedPreferenceChangeListener mPreferenceListener = new OnSharedPreferenceChangeListener() { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { if (key.equals(Constants.UNITS)) { initBasedOnPreferences(sharedPreferences); if (mListener != null) { mListener.onUnitsChange(); } } } }; private boolean needsUnitFlip; private int mUnits; @SuppressWarnings("unused") private static final String TAG = "OGT.UnitsI18n"; public UnitsI18n(Context ctx, UnitsChangeListener listener) { this(ctx); mListener = listener; } public UnitsI18n(Context ctx) { mContext = ctx; initBasedOnPreferences(PreferenceManager.getDefaultSharedPreferences(mContext)); } private void initBasedOnPreferences(SharedPreferences sharedPreferences) { mUnits = Integer.parseInt(sharedPreferences.getString(Constants.UNITS, Integer.toString(Constants.UNITS_DEFAULT))); switch (mUnits) { case (Constants.UNITS_DEFAULT): setToDefault(); break; case (Constants.UNITS_IMPERIAL): setToImperial(); break; case (Constants.UNITS_METRIC): setToMetric(); break; case (Constants.UNITS_NAUTIC): setToMetric(); overrideWithNautic(mContext.getResources()); break; case (Constants.UNITS_METRICPACE): setToMetric(); overrideWithPace(mContext.getResources()); break; case (Constants.UNITS_IMPERIALPACE): setToImperial(); overrideWithPaceImperial(mContext.getResources()); break; case Constants.UNITS_IMPERIALSURFACE: setToImperial(); overrideWithSurfaceImperial(); break; case Constants.UNITS_METRICSURFACE: setToMetric(); overrideWithSurfaceMetric(); break; default: setToDefault(); break; } } private void setToDefault() { Resources resources = mContext.getResources(); init(resources); } private void setToMetric() { Resources resources = mContext.getResources(); Configuration config = resources.getConfiguration(); Locale oldLocale = config.locale; config.locale = new Locale(""); resources.updateConfiguration(config, resources.getDisplayMetrics()); init(resources); config.locale = oldLocale; resources.updateConfiguration(config, resources.getDisplayMetrics()); } private void setToImperial() { Resources resources = mContext.getResources(); Configuration config = resources.getConfiguration(); Locale oldLocale = config.locale; config.locale = Locale.US; resources.updateConfiguration(config, resources.getDisplayMetrics()); init(resources); config.locale = oldLocale; resources.updateConfiguration(config, resources.getDisplayMetrics()); } /** * Based on a given Locale prefetch the units conversions and names. * * @param resources Resources initialized with a Locale */ private void init(Resources resources) { TypedValue outValue = new TypedValue(); needsUnitFlip = false; resources.getValue(R.raw.conversion_from_mps, outValue, false); mConversion_from_mps_to_speed = outValue.getFloat(); resources.getValue(R.raw.conversion_from_meter, outValue, false); mConversion_from_meter_to_distance = outValue.getFloat(); resources.getValue(R.raw.conversion_from_meter_to_height, outValue, false); mConversion_from_meter_to_height = outValue.getFloat(); mSpeed_unit = resources.getString(R.string.speed_unitname); mDistance_unit = resources.getString(R.string.distance_unitname); mHeight_unit = resources.getString(R.string.distance_smallunitname); } private void overrideWithNautic(Resources resources) { TypedValue outValue = new TypedValue(); resources.getValue(R.raw.conversion_from_mps_to_knot, outValue, false); mConversion_from_mps_to_speed = outValue.getFloat(); resources.getValue(R.raw.conversion_from_meter_to_nauticmile, outValue, false); mConversion_from_meter_to_distance = outValue.getFloat(); mSpeed_unit = resources.getString(R.string.knot_unitname); mDistance_unit = resources.getString(R.string.nautic_unitname); } private void overrideWithPace(Resources resources) { needsUnitFlip = true; mSpeed_unit = resources.getString(R.string.pace_unitname); } private void overrideWithPaceImperial(Resources resources) { needsUnitFlip = true; mSpeed_unit = resources.getString(R.string.pace_unitname_imperial); } private void overrideWithSurfaceImperial() { float width = getWidthPreference(); Resources resources = mContext.getResources(); TypedValue outValue = new TypedValue(); resources.getValue(R.raw.conversion_from_mps_to_acres_hour, outValue, false); mConversion_from_mps_to_speed = outValue.getFloat() * width; mSpeed_unit = resources.getString(R.string.surface_unitname_imperial); } private float getWidthPreference() { return Float.parseFloat(PreferenceManager.getDefaultSharedPreferences(mContext).getString("units_implement_width", "12")); } private void overrideWithSurfaceMetric() { float width = getWidthPreference(); Resources resources = mContext.getResources(); TypedValue outValue = new TypedValue(); resources.getValue(R.raw.conversion_from_mps_to_hectare_hour, outValue, false); mConversion_from_mps_to_speed = outValue.getFloat() * width; mSpeed_unit = resources.getString(R.string.surface_unitname_metric); } public double conversionFromMeterAndMiliseconds(double meters, long miliseconds) { float seconds = miliseconds / 1000f; return conversionFromMetersPerSecond(meters / seconds); } public double conversionFromMetersPerSecond(double mps) { double speed = mps * mConversion_from_mps_to_speed; if (needsUnitFlip) // Flip from "x per hour" to "minutes per x" { if (speed > 1) // Nearly no speed return 0 as if there is no speed { speed = (1 / speed) * 60.0; } else { speed = 0; } } return speed; } public double conversionFromMeter(double meters) { double value = meters * mConversion_from_meter_to_distance; return value; } public double conversionFromLocalToMeters(double localizedValue) { double meters = localizedValue / mConversion_from_meter_to_distance; return meters; } public double conversionFromMeterToHeight(double meters) { return meters * mConversion_from_meter_to_height; } public String getSpeedUnit() { return mSpeed_unit; } public String getDistanceUnit() { return mDistance_unit; } public String getHeightUnit() { return mHeight_unit; } public boolean isUnitFlipped() { return needsUnitFlip; } public void setUnitsChangeListener(UnitsChangeListener unitsChangeListener) { mListener = unitsChangeListener; if( mListener != null ) { initBasedOnPreferences(PreferenceManager.getDefaultSharedPreferences(mContext)); PreferenceManager.getDefaultSharedPreferences(mContext).registerOnSharedPreferenceChangeListener(mPreferenceListener); } else { PreferenceManager.getDefaultSharedPreferences(mContext).unregisterOnSharedPreferenceChangeListener(mPreferenceListener); } } /** * Interface definition for a callback to be invoked when the preference for * units changed. * * @version $Id: UnitsI18n.java 1180 2011-12-27 22:44:01Z rcgroot $ * @author rene (c) Feb 14, 2010, Sogeti B.V. */ public interface UnitsChangeListener { /** * Called when the unit data has changed. */ void onUnitsChange(); } /** * Format a speed using the current unit and flipping * * @param speed * @param decimals format a bit larger showing decimals or seconds * @return */ public String formatSpeed(double speed, boolean decimals) { String speedText; if(mUnits == Constants.UNITS_METRICPACE || mUnits == Constants.UNITS_IMPERIALPACE) { if( decimals ) { speedText = String.format( "%02d %s", (int)speed, this.getSpeedUnit() ); } else { speedText = String.format( "%02d:%02d %s", (int)speed, (int)((speed-(int)speed)*60), // convert decimal to seconds this.getSpeedUnit() ); } } else { if( decimals ) { speedText = String.format( "%.2f %s", speed, this.getSpeedUnit() ); } else { speedText = String.format( "%.0f %s", speed, this.getSpeedUnit() ); } } return speedText; } }