Refactored countdowns, implemented "Your train" selection

This commit is contained in:
dkeen@dkeen-laptop 2012-07-17 13:43:42 -07:00
parent 8bbdec5328
commit ab7ab0a491
14 changed files with 528 additions and 77 deletions

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bart="http://schemas.android.com/apk/res/com.dougkeen.bart"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
@ -30,10 +31,12 @@
style="@style/BikeIcon"
android:src="@drawable/bike" />
<TextView
<com.dougkeen.bart.controls.CountdownTextView
android:id="@+id/countdown"
style="@style/DepartureCountdownText"
android:gravity="right" />
android:gravity="right"
android:width="90dp"
bart:tickInterval="1" />
</LinearLayout>
<ImageView
@ -43,12 +46,13 @@
android:layout_below="@id/topRow"
android:src="@drawable/xfer" />
<TextSwitcher
<com.dougkeen.bart.controls.TimedTextSwitcher
android:id="@+id/trainLengthText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/topRow"
android:layout_toRightOf="@id/destinationColorBar" />
android:layout_toRightOf="@id/destinationColorBar"
bart:tickInterval="3" />
<TextView
android:id="@+id/uncertainty"

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bart="http://schemas.android.com/apk/res/com.dougkeen.bart"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
@ -13,6 +14,82 @@
android:paddingRight="5dp"
android:textSize="24dp" />
<RelativeLayout
android:id="@+id/yourTrainSection"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="#222"
android:padding="10dp"
android:visibility="gone" >
<TextView
android:id="@+id/yourTrainHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="@string/your_train"
android:textAllCaps="true"
android:textSize="20dp"
android:textStyle="bold" />
<ImageView
android:id="@+id/yourTrainDestinationColorBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@id/yourTrainHeader"
android:src="@drawable/basic_rectangle" />
<TextView
android:id="@+id/yourTrainDestinationText"
style="@style/DepartureDestinationText"
android:layout_below="@id/yourTrainHeader"
android:layout_toRightOf="@id/yourTrainDestinationColorBar"
android:ellipsize="marquee"
android:singleLine="true" />
<ImageView
android:id="@+id/yourTrainBikeIcon"
style="@style/BikeIcon"
android:layout_below="@id/yourTrainHeader"
android:layout_toRightOf="@id/yourTrainDestinationText"
android:src="@drawable/bike" />
<ImageView
android:id="@+id/yourTrainXferIcon"
style="@style/XferIcon"
android:layout_below="@id/yourTrainBikeIcon"
android:layout_toRightOf="@id/yourTrainDestinationText"
android:src="@drawable/xfer" />
<TextView
android:id="@+id/yourTrainTrainLengthText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/yourTrainDestinationText"
android:layout_toRightOf="@id/yourTrainDestinationColorBar"
android:paddingLeft="5dp" />
<com.dougkeen.bart.controls.CountdownTextView
android:id="@+id/yourTrainDepartureCountdown"
style="@style/DepartureCountdownText"
android:layout_alignLeft="@id/yourTrainSection"
android:layout_alignRight="@id/yourTrainSection"
android:layout_below="@id/yourTrainTrainLengthText"
bart:tickInterval="1" />
<com.dougkeen.bart.controls.CountdownTextView
android:id="@+id/yourTrainArrivalCountdown"
style="@style/DepartureCountdownText"
android:layout_alignLeft="@id/yourTrainSection"
android:layout_alignRight="@id/yourTrainSection"
android:layout_below="@id/yourTrainDepartureCountdown"
android:ellipsize="end"
bart:tickInterval="5" />
</RelativeLayout>
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:title="@string/getting_on_this_train" android:id="@+id/boardTrain"></item>
</menu>

View File

@ -12,20 +12,27 @@
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.
-->
-->
<resources>
<attr name="tickInterval" format="integer" />
<declare-styleable name="AppTheme">
<attr name="actionbarCompatTitleStyle" format="reference" />
<attr name="actionbarCompatItemStyle" format="reference" />
<attr name="actionbarCompatItemHomeStyle" format="reference" />
<attr name="actionbarCompatProgressIndicatorStyle" format="reference" />
</declare-styleable>
<declare-styleable name="BezelImageView">
<attr name="maskDrawable" format="reference" />
<attr name="borderDrawable" format="reference" />
</declare-styleable>
<declare-styleable name="CountdownTextView">
<attr name="tickInterval" />
</declare-styleable>
<declare-styleable name="TimedTextSwitcher">
<attr name="tickInterval" />
</declare-styleable>
</resources>
</resources>

View File

@ -32,4 +32,7 @@
<string name="departures">Departures</string>
<string name="ok">OK</string>
<string name="quick_departure_lookup">Quick departure lookup</string>
<string name="getting_on_this_train">I\'m getting on this train</string>
<string name="departure_options">Departure options</string>
<string name="your_train">Your train</string>
</resources>

View File

@ -94,7 +94,6 @@
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">20dp</item>
<item name="android:singleLine">true</item>
<item name="android:width">90dp</item>
</style>
<style name="DepartureUncertaintyText">

View File

@ -18,12 +18,13 @@ import android.widget.TextSwitcher;
import android.widget.TextView;
import android.widget.ViewSwitcher.ViewFactory;
import com.dougkeen.bart.controls.CountdownTextView;
import com.dougkeen.bart.controls.TimedTextSwitcher;
import com.dougkeen.bart.model.Departure;
import com.dougkeen.bart.model.TextProvider;
public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
private int refreshCounter = 1;
public DepartureArrayAdapter(Context context, int textViewResourceId,
Departure[] objects) {
super(context, textViewResourceId, objects);
@ -52,10 +53,6 @@ public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
public DepartureArrayAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
}
public void incrementRefreshCounter() {
refreshCounter++;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
@ -67,39 +64,46 @@ public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
view = inflater.inflate(R.layout.departure_listing, parent, false);
}
Departure departure = getItem(position);
final Departure departure = getItem(position);
((TextView) view.findViewById(R.id.destinationText)).setText(departure
.getDestination().toString());
TextSwitcher textSwitcher = (TextSwitcher) view
TimedTextSwitcher textSwitcher = (TimedTextSwitcher) view
.findViewById(R.id.trainLengthText);
initTextSwitcher(textSwitcher);
final String estimatedArrivalTimeText = departure
.getEstimatedArrivalTimeText(getContext());
String arrivalText = "Est. arrival " + estimatedArrivalTimeText;
if (StringUtils.isBlank(estimatedArrivalTimeText)) {
textSwitcher.setCurrentText(departure.getTrainLengthText());
} else if (refreshCounter % 6 < 3) {
String trainLengthText = departure.getTrainLengthText();
if (refreshCounter % 6 == 0) {
textSwitcher.setText(trainLengthText);
} else {
textSwitcher.setCurrentText(trainLengthText);
textSwitcher.setCurrentText(departure.getTrainLengthText());
textSwitcher.setTextProviders(new TextProvider[] { new TextProvider() {
@Override
public String getText() {
final String estimatedArrivalTimeText = departure
.getEstimatedArrivalTimeText(getContext());
if (StringUtils.isBlank(estimatedArrivalTimeText)) {
return "";
} else {
return "Est. arrival " + estimatedArrivalTimeText;
}
}
} else {
if (refreshCounter % 6 == 3) {
textSwitcher.setText(arrivalText);
} else {
textSwitcher.setCurrentText(arrivalText);
}, new TextProvider() {
@Override
public String getText() {
return departure.getTrainLengthText();
}
}
} });
ImageView colorBar = (ImageView) view
.findViewById(R.id.destinationColorBar);
((GradientDrawable) colorBar.getDrawable()).setColor(Color
.parseColor(departure.getDestinationColor()));
((TextView) view.findViewById(R.id.countdown)).setText(departure
.getCountdownText());
CountdownTextView countdownTextView = (CountdownTextView) view
.findViewById(R.id.countdown);
countdownTextView.setText(departure.getCountdownText());
countdownTextView.setTextProvider(new TextProvider() {
@Override
public String getText() {
return departure.getCountdownText();
}
});
((TextView) view.findViewById(R.id.uncertainty)).setText(departure
.getUncertaintyText());
if (departure.isBikeAllowed()) {
@ -130,7 +134,9 @@ public class DepartureArrayAdapter extends ArrayAdapter<Departure> {
});
textSwitcher.setInAnimation(AnimationUtils.loadAnimation(
getContext(), android.R.anim.fade_in));
getContext(), android.R.anim.slide_in_left));
textSwitcher.setOutAnimation(AnimationUtils.loadAnimation(
getContext(), android.R.anim.slide_out_right));
}
}
}

View File

@ -8,6 +8,8 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
@ -16,14 +18,20 @@ import android.os.PowerManager;
import android.text.format.DateFormat;
import android.text.util.Linkify;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.dougkeen.bart.actionbarcompat.ActionBarListActivity;
import com.dougkeen.bart.controls.CountdownTextView;
import com.dougkeen.bart.controls.Ticker;
import com.dougkeen.bart.data.RoutesColumns;
import com.dougkeen.bart.model.Constants;
import com.dougkeen.bart.model.Departure;
@ -32,6 +40,7 @@ import com.dougkeen.bart.model.ScheduleInformation;
import com.dougkeen.bart.model.ScheduleItem;
import com.dougkeen.bart.model.Station;
import com.dougkeen.bart.model.StationPair;
import com.dougkeen.bart.model.TextProvider;
import com.dougkeen.bart.networktasks.GetRealTimeDeparturesTask;
import com.dougkeen.bart.networktasks.GetScheduleInformationTask;
@ -46,6 +55,9 @@ public class ViewDeparturesActivity extends ActionBarListActivity {
private int mAverageTripLength;
private int mAverageTripSampleCount;
private Departure mSelectedDeparture;
private Departure mBoardedDeparture;
private DepartureArrayAdapter mDeparturesAdapter;
private ScheduleInformation mLatestScheduleInfo;
@ -55,14 +67,6 @@ public class ViewDeparturesActivity extends ActionBarListActivity {
private AsyncTask<StationPair, Integer, RealTimeDepartures> mGetDeparturesTask;
private AsyncTask<StationPair, Integer, ScheduleInformation> mGetScheduleInformationTask;
private boolean mIsAutoUpdating = false;
private final Runnable AUTO_UPDATE_RUNNABLE = new Runnable() {
public void run() {
runAutoUpdate();
}
};
private PowerManager.WakeLock mWakeLock;
private boolean mDepartureFetchIsPending;
@ -104,21 +108,32 @@ public class ViewDeparturesActivity extends ActionBarListActivity {
mDeparturesAdapter = new DepartureArrayAdapter(this,
R.layout.departure_listing);
if (savedInstanceState != null
&& savedInstanceState.containsKey("departures")) {
for (Parcelable departure : savedInstanceState
.getParcelableArray("departures")) {
mDeparturesAdapter.add((Departure) departure);
if (savedInstanceState != null) {
if (savedInstanceState.containsKey("departures")) {
for (Parcelable departure : savedInstanceState
.getParcelableArray("departures")) {
mDeparturesAdapter.add((Departure) departure);
}
}
if (savedInstanceState.containsKey("boardedDeparture")) {
mBoardedDeparture = (Departure) savedInstanceState
.getParcelable("boardedDeparture");
}
}
setListAdapter(mDeparturesAdapter);
registerForContextMenu(getListView());
findViewById(R.id.missingDepartureText).setVisibility(View.VISIBLE);
refreshBoardedDeparture();
}
@Override
protected void onPause() {
cancelDataFetch();
Ticker.getInstance().stopTicking();
super.onPause();
}
@ -147,6 +162,13 @@ public class ViewDeparturesActivity extends ActionBarListActivity {
departures[i] = mDeparturesAdapter.getItem(i);
}
outState.putParcelableArray("departures", departures);
outState.putParcelable("boardedDeparture", mBoardedDeparture);
}
@Override
protected void onResume() {
super.onResume();
Ticker.getInstance().startTicking();
}
@Override
@ -161,10 +183,7 @@ public class ViewDeparturesActivity extends ActionBarListActivity {
.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK,
"ViewDeparturesActivity");
mWakeLock.acquire();
if (mDeparturesAdapter != null && !mDeparturesAdapter.isEmpty()) {
mIsAutoUpdating = true;
}
runAutoUpdate();
refreshBoardedDeparture();
} else if (mWakeLock != null) {
mWakeLock.release();
}
@ -336,11 +355,6 @@ public class ViewDeparturesActivity extends ActionBarListActivity {
scheduleDepartureFetch(interval);
}
if (!mIsAutoUpdating) {
mIsAutoUpdating = true;
}
} else {
mIsAutoUpdating = false;
}
}
@ -506,25 +520,6 @@ public class ViewDeparturesActivity extends ActionBarListActivity {
}
}
private long mLastAutoUpdate = 0;
private void runAutoUpdate() {
long now = System.currentTimeMillis();
if (now - mLastAutoUpdate < 950) {
return;
}
if (mIsAutoUpdating && mDeparturesAdapter != null) {
mDeparturesAdapter.incrementRefreshCounter();
mDeparturesAdapter.notifyDataSetChanged();
}
mLastAutoUpdate = now;
if (hasWindowFocus()) {
postDelayed(AUTO_UPDATE_RUNNABLE, 1000);
} else {
mIsAutoUpdating = false;
}
}
private boolean postDelayed(Runnable runnable, long delayMillis) {
return mEmptyView.postDelayed(runnable, delayMillis);
}
@ -557,4 +552,84 @@ public class ViewDeparturesActivity extends ActionBarListActivity {
return super.onOptionsItemSelected(item);
}
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.departure_context_menu, menu);
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
mSelectedDeparture = (Departure) getListAdapter()
.getItem(info.position);
menu.setHeaderTitle(R.string.departure_options);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
if (item.getItemId() == R.id.boardTrain) {
mBoardedDeparture = mSelectedDeparture;
refreshBoardedDeparture();
return true;
}
return super.onContextItemSelected(item);
}
private void refreshBoardedDeparture() {
if (mBoardedDeparture == null)
return;
final Departure departure = mBoardedDeparture;
findViewById(R.id.yourTrainSection).setVisibility(View.VISIBLE);
((TextView) findViewById(R.id.yourTrainDestinationText))
.setText(departure.getDestination().toString());
((TextView) findViewById(R.id.yourTrainTrainLengthText))
.setText(departure.getTrainLengthText());
ImageView colorBar = (ImageView) findViewById(R.id.yourTrainDestinationColorBar);
((GradientDrawable) colorBar.getDrawable()).setColor(Color
.parseColor(departure.getDestinationColor()));
if (departure.isBikeAllowed()) {
((ImageView) findViewById(R.id.yourTrainBikeIcon))
.setVisibility(View.VISIBLE);
} else {
((ImageView) findViewById(R.id.yourTrainBikeIcon))
.setVisibility(View.INVISIBLE);
}
if (departure.getRequiresTransfer()) {
((ImageView) findViewById(R.id.yourTrainXferIcon))
.setVisibility(View.VISIBLE);
} else {
((ImageView) findViewById(R.id.yourTrainXferIcon))
.setVisibility(View.INVISIBLE);
}
CountdownTextView departureCountdown = (CountdownTextView) findViewById(R.id.yourTrainDepartureCountdown);
CountdownTextView arrivalCountdown = (CountdownTextView) findViewById(R.id.yourTrainArrivalCountdown);
departureCountdown.setText("Leaves in " + departure.getCountdownText()
+ " " + departure.getUncertaintyText());
departureCountdown.setTextProvider(new TextProvider() {
@Override
public String getText() {
if (departure.hasDeparted()) {
return "Departed";
} else {
return "Leaves in " + departure.getCountdownText() + " "
+ departure.getUncertaintyText();
}
}
});
arrivalCountdown
.setText(departure.getEstimatedArrivalMinutesLeftText());
arrivalCountdown.setTextProvider(new TextProvider() {
@Override
public String getText() {
return departure.getEstimatedArrivalMinutesLeftText();
}
});
}
}

View File

@ -0,0 +1,57 @@
package com.dougkeen.bart.controls;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView;
import com.dougkeen.bart.model.TextProvider;
public class CountdownTextView extends TextView implements
Ticker.TickSubscriber {
private TextProvider mTextProvider;
private int mTickInterval;
public CountdownTextView(Context context) {
super(context);
}
public CountdownTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setInstanceVarsFromAttrs(attrs);
}
public CountdownTextView(Context context, AttributeSet attrs) {
super(context, attrs);
setInstanceVarsFromAttrs(attrs);
}
private void setInstanceVarsFromAttrs(AttributeSet attrs) {
int tickInterval = attrs.getAttributeIntValue(
"http://schemas.android.com/apk/res/com.dougkeen.bart",
"tickInterval", 0);
if (tickInterval > 0) {
setTickInterval(tickInterval);
}
}
public void setTextProvider(TextProvider provider) {
mTextProvider = provider;
Ticker.getInstance().addSubscriber(this);
}
@Override
public int getTickInterval() {
return mTickInterval;
}
public void setTickInterval(int tickInterval) {
this.mTickInterval = tickInterval;
}
@Override
public void onTick() {
setText(mTextProvider.getText());
}
}

View File

@ -0,0 +1,110 @@
package com.dougkeen.bart.controls;
import java.util.Iterator;
import java.util.WeakHashMap;
import android.os.Handler;
import android.util.Log;
public class Ticker {
public static interface TickSubscriber {
int getTickInterval();
void onTick();
}
private static Ticker sInstance;
private WeakHashMap<TickSubscriber, Object> mSubscribers;
private TickerEngine mEngine;
private static class TickerEngine implements Runnable {
private static final int TICK_INTERVAL_MILLIS = 1000;
private Ticker publisher;
private Handler mHandler;
private boolean mPendingRequest = false;
private boolean mForceStop = false;
private long mTickCount = 0;
public TickerEngine(Ticker publisher) {
this.publisher = publisher;
this.mHandler = new Handler();
}
@Override
public void run() {
mPendingRequest = false;
if (mForceStop) {
mForceStop = false;
return;
}
Log.w("Ticker", "Tick #: " + mTickCount);
long startTimeNanos = System.nanoTime();
Iterator<TickSubscriber> iterator = publisher.mSubscribers.keySet()
.iterator();
boolean stillHasListeners = false;
while (iterator.hasNext()) {
TickSubscriber subscriber = iterator.next();
if (subscriber == null) {
continue;
}
stillHasListeners = true;
if (subscriber.getTickInterval() > 0
&& mTickCount % subscriber.getTickInterval() == 0)
subscriber.onTick();
}
long endTimeNanos = System.nanoTime();
if (stillHasListeners && !mPendingRequest) {
mHandler.postDelayed(this, TICK_INTERVAL_MILLIS
- ((endTimeNanos - startTimeNanos) / 1000000));
mPendingRequest = true;
mTickCount++;
} else {
mPendingRequest = false;
}
}
public boolean isOn() {
return mPendingRequest;
}
public void stop() {
mForceStop = true;
}
};
public synchronized static Ticker getInstance() {
if (sInstance == null) {
sInstance = new Ticker();
}
return sInstance;
}
public void addSubscriber(TickSubscriber subscriber) {
if (!mSubscribers.containsKey(subscriber) && subscriber != null) {
mSubscribers.put(subscriber, null);
startTicking();
}
}
private Ticker() {
mSubscribers = new WeakHashMap<TickSubscriber, Object>();
mEngine = new TickerEngine(this);
}
public void startTicking() {
if (!mEngine.isOn())
mEngine.run();
}
public void stopTicking() {
if (mEngine.isOn())
mEngine.stop();
}
}

View File

@ -0,0 +1,63 @@
package com.dougkeen.bart.controls;
import org.apache.commons.lang3.StringUtils;
import com.dougkeen.bart.model.TextProvider;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextSwitcher;
public class TimedTextSwitcher extends TextSwitcher implements
Ticker.TickSubscriber {
public TimedTextSwitcher(Context context, AttributeSet attrs) {
super(context, attrs);
setInstanceVarsFromAttrs(attrs);
}
public TimedTextSwitcher(Context context) {
super(context);
}
private void setInstanceVarsFromAttrs(AttributeSet attrs) {
int tickInterval = attrs.getAttributeIntValue(
"http://schemas.android.com/apk/res/com.dougkeen.bart",
"tickInterval", 0);
if (tickInterval > 0) {
setTickInterval(tickInterval);
}
}
private int mTickInterval;
private TextProvider[] mTextProviderArray;
private int mCurrentIndex = 0;
@Override
public int getTickInterval() {
return mTickInterval;
}
public void setTickInterval(int tickInterval) {
this.mTickInterval = tickInterval;
}
public void setTextProviders(TextProvider[] textProviders) {
mTextProviderArray = textProviders;
Ticker.getInstance().addSubscriber(this);
}
private String mLastText;
@Override
public void onTick() {
String text = mTextProviderArray[mCurrentIndex].getText();
if (StringUtils.isNotBlank(text)
&& !StringUtils.equalsIgnoreCase(text, mLastText)) {
mLastText = text;
setText(text);
}
mCurrentIndex = (mCurrentIndex + 1) % mTextProviderArray.length;
}
}

View File

@ -219,6 +219,30 @@ public class Departure implements Parcelable, Comparable<Departure> {
return getMeanEstimate() + getEstimatedTripTime();
}
public long getEstimatedArrivalMinutesLeft() {
long millisLeft = getEstimatedArrivalTime()
- System.currentTimeMillis();
if (millisLeft < 0) {
return -1;
} else {
// Add ~30s to emulate rounding
return (millisLeft + 29999) / (60 * 1000);
}
}
public String getEstimatedArrivalMinutesLeftText() {
long minutesLeft = getEstimatedArrivalMinutesLeft();
if (minutesLeft < 0) {
return "Arrived";
} else if (minutesLeft == 0) {
return "Estimated arrival in < 1 min.";
} else if (minutesLeft == 1) {
return "Estimated arrival in 1 min.";
} else {
return "Estimated arrival in " + minutesLeft + " mins.";
}
}
public String getEstimatedArrivalTimeText(Context context) {
if (getEstimatedTripTime() > 0 || arrivalTimeOverride > 0) {
return DateFormat.getTimeFormat(context).format(

View File

@ -2,7 +2,9 @@ package com.dougkeen.bart.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import android.util.Log;
@ -199,6 +201,19 @@ public enum Station {
public List<Route> getTransferRoutes(Station dest) {
List<Route> returnList = new ArrayList<Route>();
/**
* Kind of gimpy logic... no transfers from lake or 12th if headed to
* somewhere between woak and daly
*/
if (this.equals(LAKE) || this.equals(_12TH)) {
int destIndex = Line.BLUE.stations.indexOf(dest);
if (destIndex >= Line.BLUE.stations.indexOf(DALY)
&& destIndex <= Line.BLUE.stations.indexOf(WOAK)) {
return returnList;
}
}
if (dest.getInboundTransferStation() != null) {
// Try getting to the destination's inbound xfer station first
returnList.addAll(getDirectRoutesForDestination(this,

View File

@ -0,0 +1,7 @@
package com.dougkeen.bart.model;
public interface TextProvider {
String getText();
}