Added bike and xfer icons.
Now more well-behaved when switching orientations. Added option to view routes on m.bart.gov --HG-- rename : res/menu/favorite_context_menu.xml => res/menu/route_context_menu.xml rename : res/menu/favorites_menu.xml => res/menu/routes_list_menu.xml rename : src/com/dougkeen/bart/AddFavoriteActivity.java => src/com/dougkeen/bart/AddRouteActivity.java rename : src/com/dougkeen/bart/FavoritesDashboardActivity.java => src/com/dougkeen/bart/RoutesListActivity.java rename : src/com/dougkeen/bart/data/FavoritesColumns.java => src/com/dougkeen/bart/data/RoutesColumns.java
@ -1,3 +1,9 @@
|
||||
|
||||
syntax: glob
|
||||
bin/*
|
||||
syntax: regexp
|
||||
^app_icon\.psd$
|
||||
syntax: regexp
|
||||
^bart-train\.jpg$
|
||||
syntax: regexp
|
||||
^colorscheme\.jpg$
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.dougkeen.bart" android:versionCode="2"
|
||||
package="com.dougkeen.bart" android:versionCode="3"
|
||||
android:versionName="1.0">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
<application android:icon="@drawable/icon" android:label="@string/app_name"
|
||||
android:debuggable="true">
|
||||
<activity android:name=".FavoritesDashboardActivity"
|
||||
<activity android:name="RoutesListActivity"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
@ -28,7 +28,7 @@
|
||||
<data android:mimeType="vnd.android.cursor.item/com.dougkeen.bart.favorite" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".AddFavoriteActivity" android:label="@string/app_name">
|
||||
<activity android:name="AddRouteActivity" android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.INSERT" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<size android:height="15dp" android:width="60dp" />
|
||||
<size android:height="45dp" android:width="15dp" />
|
||||
</shape>
|
BIN
res/drawable/bike.png
Normal file
After Width: | Height: | Size: 1008 B |
BIN
res/drawable/xfer.png
Normal file
After Width: | Height: | Size: 839 B |
@ -5,7 +5,7 @@
|
||||
<TextView android:id="@+id/form_header" android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" android:textSize="24dp"
|
||||
android:textStyle="bold" android:layout_alignParentTop="true"
|
||||
android:text="@string/add_favorite_route" android:paddingBottom="10dp" />
|
||||
android:text="@string/add_route" android:paddingBottom="10dp" />
|
||||
<TextView android:id="@+id/origin_label" android:text="@string/origin"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:textSize="15dp" android:layout_below="@+id/form_header"
|
||||
|
@ -1,12 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent" android:layout_height="fill_parent">
|
||||
<TextView android:id="@+id/destinationText" style="@style/ArrivalDestinationText"
|
||||
android:layout_alignParentTop="true" android:layout_alignParentLeft="true" />
|
||||
<ImageView android:id="@+id/destinationColorBar" android:src="@drawable/basic_rectangle"
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true" android:layout_centerVertical="true" />
|
||||
<TextView android:id="@+id/destinationText" style="@style/ArrivalDestinationText"
|
||||
android:layout_alignParentTop="true" android:layout_toRightOf="@id/destinationColorBar" />
|
||||
<TextView android:id="@+id/trainLengthText" style="@style/ArrivalTrainLengthText"
|
||||
android:layout_toRightOf="@id/destinationColorBar"
|
||||
android:layout_below="@id/destinationText" />
|
||||
<TextView android:layout_centerVertical="true"
|
||||
android:layout_alignParentRight="true" android:id="@+id/countdown"
|
||||
<TextView android:layout_alignParentRight="true" android:id="@+id/countdown"
|
||||
style="@style/ArrivalCountdownText" />
|
||||
<TextView android:layout_alignParentRight="true" android:id="@+id/uncertainty"
|
||||
android:layout_below="@id/countdown" style="@style/ArrivalUncertaintyText" />
|
||||
<ImageView android:id="@+id/bikeIcon" android:src="@drawable/bike"
|
||||
android:layout_alignParentTop="true" android:layout_alignParentRight="true"
|
||||
style="@style/BikeIcon" />
|
||||
<ImageView android:id="@+id/xferIcon" android:src="@drawable/xfer"
|
||||
android:layout_below="@id/bikeIcon" android:layout_alignParentRight="true"
|
||||
style="@style/XferIcon" />
|
||||
</RelativeLayout>
|
@ -3,6 +3,6 @@
|
||||
android:layout_width="fill_parent" android:layout_height="wrap_content"
|
||||
android:paddingTop="15dip" android:paddingBottom="15dip"
|
||||
android:paddingLeft="5dip" android:paddingRight="5dip" android:id="@android:id/text1"
|
||||
android:textColor="#cccccc" android:ellipsize="marquee"
|
||||
android:ellipsize="marquee" android:textColor="@color/black"
|
||||
android:singleLine="true">
|
||||
</TextView>
|
||||
|
5
res/menu/route_menu.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:title="@string/view_on_bart_site" android:icon="@android:drawable/ic_menu_view"
|
||||
android:id="@+id/view_on_bart_site_button"></item>
|
||||
</menu>
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:title="@string/add_favorite" android:icon="@android:drawable/ic_menu_add"
|
||||
<item android:title="@string/add_route" android:icon="@android:drawable/ic_menu_add"
|
||||
android:id="@+id/add_favorite_menu_button"></item>
|
||||
</menu>
|
@ -2,23 +2,24 @@
|
||||
<resources>
|
||||
<string name="app_name">Bart Catcher</string>
|
||||
<string name="favorite_routes">Favorite Routes</string>
|
||||
<string name="empty_favorites_list_message">Press the menu button and select "Add
|
||||
favorite" to
|
||||
add a route</string>
|
||||
<string name="add_favorite">Add favorite</string>
|
||||
<string name="add_favorite_route">Add a favorite route</string>
|
||||
<string name="empty_favorites_list_message">Press the menu button and select \"Add route\" to add
|
||||
a route</string>
|
||||
<string name="add_route">Add a route</string>
|
||||
<string name="origin">Origin</string>
|
||||
<string name="destination">Destination</string>
|
||||
<string name="save">Save</string>
|
||||
<string name="error_matching_origin_and_destination">The origin and destination stations must be different</string>
|
||||
<string name="error_matching_origin_and_destination">The origin and destination stations must be
|
||||
different</string>
|
||||
<string name="error_null_destination">You must select a destination station</string>
|
||||
<string name="error_null_origin">You must select an origin station</string>
|
||||
<string name="arrival_wait_message">Please wait while real time arrival data is loaded...</string>
|
||||
<string name="no_data_message">No arrival data is currently available for this route</string>
|
||||
<string name="arrival_wait_message">Please wait while real time arrival data is
|
||||
loaded...</string>
|
||||
<string name="no_data_message">No arrival data is currently available for this
|
||||
route</string>
|
||||
<string name="view">View</string>
|
||||
<string name="view_arrivals">View arrivals</string>
|
||||
<string name="delete">Delete</string>
|
||||
<string name="yes">Yes</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
|
||||
<string name="view_on_bart_site">View details on BART site</string>
|
||||
</resources>
|
||||
|
@ -21,8 +21,18 @@
|
||||
<style name="ArrivalDestinationText">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:textSize">20dp</item>
|
||||
<item name="android:textSize">22dp</item>
|
||||
<item name="android:textStyle">bold</item>
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:layout_marginLeft">3dp</item>
|
||||
</style>
|
||||
|
||||
<style name="ArrivalTrainLengthText">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:textSize">18dp</item>
|
||||
<item name="android:singleLine">true</item>
|
||||
<item name="android:layout_marginLeft">3dp</item>
|
||||
</style>
|
||||
|
||||
<style name="ArrivalCountdownText">
|
||||
@ -31,4 +41,22 @@
|
||||
<item name="android:textSize">20dp</item>
|
||||
<item name="android:singleLine">true</item>
|
||||
</style>
|
||||
<style name="ArrivalUncertaintyText">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:textSize">16dp</item>
|
||||
<item name="android:singleLine">true</item>
|
||||
</style>
|
||||
<style name="BikeIcon">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:layout_marginRight">100dp</item>
|
||||
<item name="android:layout_marginTop">5dp</item>
|
||||
</style>
|
||||
<style name="XferIcon">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:layout_marginRight">97dp</item>
|
||||
<item name="android:layout_marginTop">5dp</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.dougkeen.bart;
|
||||
|
||||
import com.dougkeen.bart.data.FavoritesColumns;
|
||||
import com.dougkeen.bart.data.RoutesColumns;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ContentValues;
|
||||
@ -14,7 +14,7 @@ import android.widget.Spinner;
|
||||
import android.widget.SpinnerAdapter;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class AddFavoriteActivity extends Activity {
|
||||
public class AddRouteActivity extends Activity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@ -80,8 +80,8 @@ public class AddFavoriteActivity extends Activity {
|
||||
}
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(FavoritesColumns.FROM_STATION.string, origin.abbreviation);
|
||||
values.put(FavoritesColumns.TO_STATION.string, destination.abbreviation);
|
||||
values.put(RoutesColumns.FROM_STATION.string, origin.abbreviation);
|
||||
values.put(RoutesColumns.TO_STATION.string, destination.abbreviation);
|
||||
|
||||
Uri newUri = getContentResolver().insert(
|
||||
Constants.FAVORITE_CONTENT_URI, values);
|
90
src/com/dougkeen/bart/ArrivalArrayAdapter.java
Normal file
@ -0,0 +1,90 @@
|
||||
package com.dougkeen.bart;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.dougkeen.bart.data.Arrival;
|
||||
|
||||
public class ArrivalArrayAdapter extends ArrayAdapter<Arrival> {
|
||||
|
||||
public ArrivalArrayAdapter(Context context, int textViewResourceId,
|
||||
Arrival[] objects) {
|
||||
super(context, textViewResourceId, objects);
|
||||
}
|
||||
|
||||
public ArrivalArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId, Arrival[] objects) {
|
||||
super(context, resource, textViewResourceId, objects);
|
||||
}
|
||||
|
||||
public ArrivalArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId, List<Arrival> objects) {
|
||||
super(context, resource, textViewResourceId, objects);
|
||||
}
|
||||
|
||||
public ArrivalArrayAdapter(Context context, int resource,
|
||||
int textViewResourceId) {
|
||||
super(context, resource, textViewResourceId);
|
||||
}
|
||||
|
||||
public ArrivalArrayAdapter(Context context, int textViewResourceId,
|
||||
List<Arrival> objects) {
|
||||
super(context, textViewResourceId, objects);
|
||||
}
|
||||
|
||||
public ArrivalArrayAdapter(Context context, int textViewResourceId) {
|
||||
super(context, textViewResourceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view;
|
||||
if (convertView != null && convertView instanceof RelativeLayout) {
|
||||
view = convertView;
|
||||
} else {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
view = inflater.inflate(R.layout.arrival_listing, parent, false);
|
||||
}
|
||||
|
||||
Arrival arrival = getItem(position);
|
||||
((TextView) view.findViewById(R.id.destinationText)).setText(arrival
|
||||
.getDestination().toString());
|
||||
((TextView) view.findViewById(R.id.trainLengthText)).setText(arrival
|
||||
.getTrainLengthText());
|
||||
ImageView colorBar = (ImageView) view
|
||||
.findViewById(R.id.destinationColorBar);
|
||||
((GradientDrawable) colorBar.getDrawable()).setColor(Color
|
||||
.parseColor(arrival.getDestinationColor()));
|
||||
((TextView) view.findViewById(R.id.countdown)).setText(arrival
|
||||
.getCountdownText());
|
||||
((TextView) view.findViewById(R.id.uncertainty)).setText(arrival
|
||||
.getUncertaintyText());
|
||||
if (arrival.isBikeAllowed()) {
|
||||
((ImageView) view.findViewById(R.id.bikeIcon))
|
||||
.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
((ImageView) view.findViewById(R.id.bikeIcon))
|
||||
.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
if (arrival.getRequiresTransfer()) {
|
||||
((ImageView) view.findViewById(R.id.xferIcon))
|
||||
.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
((ImageView) view.findViewById(R.id.xferIcon))
|
||||
.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
}
|
@ -40,7 +40,11 @@ public abstract class GetRealTimeArrivalsTask extends
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
if (!isCancelled()) {
|
||||
return getArrivalsFromNetwork(params, sourceUrl, 0);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private RealTimeArrivals getArrivalsFromNetwork(Params params,
|
||||
@ -48,6 +52,9 @@ public abstract class GetRealTimeArrivalsTask extends
|
||||
try {
|
||||
EtdContentHandler handler = new EtdContentHandler(params.origin,
|
||||
params.destination, mRoutes);
|
||||
if (isCancelled()) {
|
||||
return null;
|
||||
}
|
||||
Xml.parse(sourceUrl.openStream(), Xml.findEncodingByName("UTF-8"),
|
||||
handler);
|
||||
final RealTimeArrivals realTimeArrivals = handler
|
||||
|
@ -5,6 +5,7 @@ public class Route {
|
||||
private Station destination;
|
||||
private Line line;
|
||||
private boolean requiresTransfer;
|
||||
private Station transferStation;
|
||||
private String direction;
|
||||
|
||||
public Station getOrigin() {
|
||||
@ -39,6 +40,14 @@ public class Route {
|
||||
this.requiresTransfer = requiresTransfer;
|
||||
}
|
||||
|
||||
public Station getTransferStation() {
|
||||
return transferStation;
|
||||
}
|
||||
|
||||
public void setTransferStation(Station transferStation) {
|
||||
this.transferStation = transferStation;
|
||||
}
|
||||
|
||||
public String getDirection() {
|
||||
return direction;
|
||||
}
|
||||
@ -58,6 +67,8 @@ public class Route {
|
||||
builder.append(line);
|
||||
builder.append(", requiresTransfer=");
|
||||
builder.append(requiresTransfer);
|
||||
builder.append(", transferStation=");
|
||||
builder.append(transferStation);
|
||||
builder.append(", direction=");
|
||||
builder.append(direction);
|
||||
builder.append("]");
|
||||
|
@ -24,9 +24,9 @@ import android.widget.SimpleCursorAdapter.ViewBinder;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.dougkeen.bart.data.CursorUtils;
|
||||
import com.dougkeen.bart.data.FavoritesColumns;
|
||||
import com.dougkeen.bart.data.RoutesColumns;
|
||||
|
||||
public class FavoritesDashboardActivity extends ListActivity {
|
||||
public class RoutesListActivity extends ListActivity {
|
||||
private static final int DIALOG_DELETE_EVENT = 0;
|
||||
|
||||
protected Cursor mQuery;
|
||||
@ -41,22 +41,17 @@ public class FavoritesDashboardActivity extends ListActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main);
|
||||
|
||||
((TextView) findViewById(R.id.listTitle))
|
||||
.setText(R.string.favorite_routes);
|
||||
((TextView) findViewById(android.R.id.empty))
|
||||
.setText(R.string.empty_favorites_list_message);
|
||||
|
||||
mQuery = managedQuery(Constants.FAVORITE_CONTENT_URI, new String[] {
|
||||
FavoritesColumns._ID.string,
|
||||
FavoritesColumns.FROM_STATION.string,
|
||||
FavoritesColumns.TO_STATION.string }, null, null,
|
||||
FavoritesColumns._ID.string);
|
||||
RoutesColumns._ID.string,
|
||||
RoutesColumns.FROM_STATION.string,
|
||||
RoutesColumns.TO_STATION.string }, null, null,
|
||||
RoutesColumns._ID.string);
|
||||
|
||||
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
|
||||
R.layout.favorite_listing,
|
||||
mQuery,
|
||||
new String[] { FavoritesColumns.FROM_STATION.string,
|
||||
FavoritesColumns.TO_STATION.string },
|
||||
new String[] { RoutesColumns.FROM_STATION.string,
|
||||
RoutesColumns.TO_STATION.string },
|
||||
new int[] { R.id.originText,
|
||||
R.id.destinationText });
|
||||
adapter.setViewBinder(new ViewBinder() {
|
||||
@ -74,10 +69,19 @@ public class FavoritesDashboardActivity extends ListActivity {
|
||||
registerForContextMenu(getListView());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
((TextView) findViewById(R.id.listTitle))
|
||||
.setText(R.string.favorite_routes);
|
||||
((TextView) findViewById(android.R.id.empty))
|
||||
.setText(R.string.empty_favorites_list_message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.favorites_menu, menu);
|
||||
inflater.inflate(R.menu.routes_list_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -105,15 +109,15 @@ public class FavoritesDashboardActivity extends ListActivity {
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.favorite_context_menu, menu);
|
||||
inflater.inflate(R.menu.route_context_menu, menu);
|
||||
|
||||
AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
|
||||
CursorWrapper item = (CursorWrapper) getListAdapter().getItem(
|
||||
info.position);
|
||||
Station orig = Station.getByAbbreviation(CursorUtils.getString(item,
|
||||
FavoritesColumns.FROM_STATION));
|
||||
RoutesColumns.FROM_STATION));
|
||||
Station dest = Station.getByAbbreviation(CursorUtils.getString(item,
|
||||
FavoritesColumns.TO_STATION));
|
||||
RoutesColumns.TO_STATION));
|
||||
mCurrentlySelectedRouteName = orig.name + " - " + dest.name;
|
||||
menu.setHeaderTitle(mCurrentlySelectedRouteName);
|
||||
}
|
@ -115,10 +115,11 @@ public enum Station {
|
||||
}
|
||||
|
||||
public List<Route> getRoutesForDestination(Station dest) {
|
||||
return getRoutesForDestination(dest, false);
|
||||
return getRoutesForDestination(dest, null);
|
||||
}
|
||||
|
||||
public List<Route> getRoutesForDestination(Station dest, boolean isTransfer) {
|
||||
public List<Route> getRoutesForDestination(Station dest,
|
||||
Station transferStation) {
|
||||
if (dest == null)
|
||||
return null;
|
||||
Boolean isNorth = null;
|
||||
@ -140,7 +141,7 @@ public enum Station {
|
||||
route.setDestination(dest);
|
||||
route.setDirection(isNorth ? "n" : "s");
|
||||
route.setLine(line);
|
||||
if (isTransfer || line.requiresTransfer) {
|
||||
if (transferStation != null || line.requiresTransfer) {
|
||||
route.setTransfer(true);
|
||||
} else {
|
||||
route.setTransfer(false);
|
||||
@ -149,11 +150,14 @@ public enum Station {
|
||||
}
|
||||
if (isNorth == null) {
|
||||
if (outboundTransferStation != null) {
|
||||
returnList.addAll(getOutboundTransferStation()
|
||||
.getRoutesForDestination(dest, true));
|
||||
returnList
|
||||
.addAll(getOutboundTransferStation()
|
||||
.getRoutesForDestination(dest,
|
||||
getOutboundTransferStation()));
|
||||
} else {
|
||||
returnList.addAll(getRoutesForDestination(dest
|
||||
.getInboundTransferStation(), true));
|
||||
.getInboundTransferStation(), dest
|
||||
.getInboundTransferStation()));
|
||||
}
|
||||
}
|
||||
return returnList;
|
||||
|
@ -10,18 +10,29 @@ import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.os.PowerManager;
|
||||
import android.text.format.DateFormat;
|
||||
import android.util.Log;
|
||||
import android.util.TimeFormatException;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.dougkeen.bart.GetRealTimeArrivalsTask.Params;
|
||||
import com.dougkeen.bart.data.Arrival;
|
||||
import com.dougkeen.bart.data.FavoritesColumns;
|
||||
import com.dougkeen.bart.data.RoutesColumns;
|
||||
import com.dougkeen.bart.data.RealTimeArrivals;
|
||||
|
||||
public class ViewArrivalsActivity extends ListActivity {
|
||||
|
||||
private static final String TAG = "BartCatcher";
|
||||
|
||||
private static final int UNCERTAINTY_THRESHOLD = 17;
|
||||
|
||||
private Uri mUri;
|
||||
|
||||
private Station mOrigin;
|
||||
@ -44,9 +55,10 @@ public class ViewArrivalsActivity extends ListActivity {
|
||||
|
||||
private PowerManager.WakeLock mWakeLock;
|
||||
|
||||
private boolean mFetchArrivalsOnNextFocus;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
// TODO Auto-generated method stub
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main);
|
||||
|
||||
@ -59,8 +71,8 @@ public class ViewArrivalsActivity extends ListActivity {
|
||||
}
|
||||
|
||||
Cursor cursor = managedQuery(mUri, new String[] {
|
||||
FavoritesColumns.FROM_STATION.string,
|
||||
FavoritesColumns.TO_STATION.string }, null, null, null);
|
||||
RoutesColumns.FROM_STATION.string,
|
||||
RoutesColumns.TO_STATION.string }, null, null, null);
|
||||
|
||||
if (!cursor.moveToFirst()) {
|
||||
throw new IllegalStateException("URI not found: " + mUri.toString());
|
||||
@ -75,31 +87,69 @@ public class ViewArrivalsActivity extends ListActivity {
|
||||
((TextView) findViewById(android.R.id.empty))
|
||||
.setText(R.string.arrival_wait_message);
|
||||
|
||||
mArrivalsAdapter = new ArrayAdapter<Arrival>(
|
||||
this, R.layout.simple_spinner_item);
|
||||
mArrivalsAdapter = new ArrivalArrayAdapter(this,
|
||||
R.layout.arrival_listing);
|
||||
if (savedInstanceState != null
|
||||
&& savedInstanceState.containsKey("arrivals")) {
|
||||
for (Parcelable arrival : savedInstanceState
|
||||
.getParcelableArray("arrivals")) {
|
||||
mArrivalsAdapter.add((Arrival) arrival);
|
||||
}
|
||||
}
|
||||
setListAdapter(mArrivalsAdapter);
|
||||
|
||||
fetchLatestArrivals();
|
||||
mFetchArrivalsOnNextFocus = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
if (mGetArrivalsTask != null) {
|
||||
mGetArrivalsTask.cancel(true);
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
Arrival[] arrivals = new Arrival[mArrivalsAdapter.getCount()];
|
||||
for (int i = mArrivalsAdapter.getCount() - 1; i >= 0; i--) {
|
||||
arrivals[i] = mArrivalsAdapter.getItem(i);
|
||||
}
|
||||
outState.putParcelableArray("arrivals", arrivals);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
if (hasFocus) {
|
||||
if (mFetchArrivalsOnNextFocus) {
|
||||
fetchLatestArrivals();
|
||||
mFetchArrivalsOnNextFocus = false;
|
||||
}
|
||||
PowerManager powerManaer = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||
mWakeLock = powerManaer.newWakeLock(
|
||||
PowerManager.SCREEN_DIM_WAKE_LOCK, "ViewArrivalsActivity");
|
||||
mWakeLock.acquire();
|
||||
if (mArrivalsAdapter != null && !mArrivalsAdapter.isEmpty()) {
|
||||
mIsAutoUpdating = true;
|
||||
}
|
||||
runAutoUpdate();
|
||||
} else if (mWakeLock != null) {
|
||||
mWakeLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
private void fetchLatestArrivals() {
|
||||
if (!hasWindowFocus())
|
||||
return;
|
||||
|
||||
mGetArrivalsTask = new GetRealTimeArrivalsTask() {
|
||||
@Override
|
||||
public void onResult(RealTimeArrivals result) {
|
||||
Log.i(TAG, "Processing data from server");
|
||||
processLatestArrivals(result);
|
||||
Log.i(TAG, "Done processing data from server");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -108,6 +158,7 @@ public class ViewArrivalsActivity extends ListActivity {
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
};
|
||||
Log.i(TAG, "Fetching data from server");
|
||||
mGetArrivalsTask.execute(new GetRealTimeArrivalsTask.Params(mOrigin,
|
||||
mDestination));
|
||||
}
|
||||
@ -119,6 +170,7 @@ public class ViewArrivalsActivity extends ListActivity {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean needsBetterAccuracy = false;
|
||||
Arrival firstArrival = null;
|
||||
final List<Arrival> arrivals = result.getArrivals();
|
||||
if (mArrivalsAdapter.getCount() > 0) {
|
||||
@ -148,6 +200,9 @@ public class ViewArrivalsActivity extends ListActivity {
|
||||
if (firstArrival == null) {
|
||||
firstArrival = existingArrival;
|
||||
}
|
||||
if (existingArrival.getUncertaintySeconds() > UNCERTAINTY_THRESHOLD) {
|
||||
needsBetterAccuracy = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (Arrival arrival : arrivals) {
|
||||
@ -156,12 +211,13 @@ public class ViewArrivalsActivity extends ListActivity {
|
||||
}
|
||||
mArrivalsAdapter.add(arrival);
|
||||
}
|
||||
needsBetterAccuracy = true;
|
||||
}
|
||||
mArrivalsAdapter.notifyDataSetChanged();
|
||||
|
||||
if (hasWindowFocus() && firstArrival != null) {
|
||||
if (firstArrival.getUncertaintySeconds() > 17
|
||||
|| firstArrival.getMinutes() == 0) {
|
||||
if (needsBetterAccuracy
|
||||
|| firstArrival.hasArrived()) {
|
||||
// Get more data in 20s
|
||||
mListTitleView.postDelayed(new Runnable() {
|
||||
@Override
|
||||
@ -169,27 +225,29 @@ public class ViewArrivalsActivity extends ListActivity {
|
||||
fetchLatestArrivals();
|
||||
}
|
||||
}, 20000);
|
||||
Log.i(TAG, "Scheduled another data fetch in 20s");
|
||||
} else {
|
||||
// Get more when next train arrives
|
||||
final int interval = firstArrival.getMinSecondsLeft() * 1000;
|
||||
mListTitleView.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fetchLatestArrivals();
|
||||
}
|
||||
}, firstArrival.getMinSecondsLeft() * 1000);
|
||||
}, interval);
|
||||
Log.i(TAG, "Scheduled another data fetch in " + interval / 1000
|
||||
+ "s");
|
||||
}
|
||||
if (!mIsAutoUpdating) {
|
||||
mIsAutoUpdating = true;
|
||||
runAutoUpdate();
|
||||
}
|
||||
} else {
|
||||
mIsAutoUpdating = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void runAutoUpdate() {
|
||||
if (mIsAutoUpdating) {
|
||||
if (mIsAutoUpdating && mArrivalsAdapter != null) {
|
||||
mArrivalsAdapter.notifyDataSetChanged();
|
||||
}
|
||||
if (hasWindowFocus()) {
|
||||
@ -198,4 +256,30 @@ public class ViewArrivalsActivity extends ListActivity {
|
||||
mIsAutoUpdating = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.route_menu, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int itemId = item.getItemId();
|
||||
if (itemId == R.id.view_on_bart_site_button) {
|
||||
startActivity(new Intent(
|
||||
Intent.ACTION_VIEW,
|
||||
Uri.parse("http://m.bart.gov/schedules/qp_results.aspx?type=departure&date=today&time="
|
||||
+ DateFormat.format("h:mmaa",
|
||||
System.currentTimeMillis()) + "&orig="
|
||||
+ mOrigin.abbreviation
|
||||
+ "&dest="
|
||||
+ mDestination.abbreviation)));
|
||||
mFetchArrivalsOnNextFocus = true;
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,11 @@
|
||||
package com.dougkeen.bart.data;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.dougkeen.bart.Station;
|
||||
|
||||
public class Arrival implements Comparable<Arrival> {
|
||||
public class Arrival implements Parcelable, Comparable<Arrival> {
|
||||
public Arrival() {
|
||||
super();
|
||||
}
|
||||
@ -20,6 +23,10 @@ public class Arrival implements Comparable<Arrival> {
|
||||
this.minutes = minutes;
|
||||
}
|
||||
|
||||
public Arrival(Parcel in) {
|
||||
readFromParcel(in);
|
||||
}
|
||||
|
||||
private Station destination;
|
||||
private String destinationColor;
|
||||
private String platform;
|
||||
@ -93,6 +100,10 @@ public class Arrival implements Comparable<Arrival> {
|
||||
this.trainLength = trainLength;
|
||||
}
|
||||
|
||||
public String getTrainLengthText() {
|
||||
return trainLength + " car train";
|
||||
}
|
||||
|
||||
public boolean getRequiresTransfer() {
|
||||
return requiresTransfer;
|
||||
}
|
||||
@ -142,14 +153,24 @@ public class Arrival implements Comparable<Arrival> {
|
||||
.currentTimeMillis()) / 1000);
|
||||
}
|
||||
|
||||
public boolean hasArrived() {
|
||||
return getMinutes() == 0 || getMeanSecondsLeft() < 0;
|
||||
}
|
||||
|
||||
public void calculateEstimates(long originalEstimateTime) {
|
||||
setMinEstimate(originalEstimateTime + (getMinutes() * 60 * 1000));
|
||||
setMaxEstimate(getMinEstimate() + (59 * 1000));
|
||||
}
|
||||
|
||||
public void mergeEstimate(Arrival arrival) {
|
||||
setMinEstimate(Math.max(getMinEstimate(), arrival.getMinEstimate()));
|
||||
setMaxEstimate(Math.min(getMaxEstimate(), arrival.getMaxEstimate()));
|
||||
final long newMin = Math
|
||||
.max(getMinEstimate(), arrival.getMinEstimate());
|
||||
final long newMax = Math
|
||||
.min(getMaxEstimate(), arrival.getMaxEstimate());
|
||||
if (newMax > newMin) { // We can never have 0 or negative uncertainty
|
||||
setMinEstimate(newMin);
|
||||
setMaxEstimate(newMax);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -193,6 +214,28 @@ public class Arrival implements Comparable<Arrival> {
|
||||
return delta > -60000 && delta < 60000;
|
||||
}
|
||||
|
||||
public String getCountdownText() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int secondsLeft = getMeanSecondsLeft();
|
||||
if (hasArrived()) {
|
||||
builder.append("Arrived");
|
||||
} else {
|
||||
builder.append(secondsLeft / 60);
|
||||
builder.append("m, ");
|
||||
builder.append(secondsLeft % 60);
|
||||
builder.append("s");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public String getUncertaintyText() {
|
||||
if (hasArrived()) {
|
||||
return "";
|
||||
} else {
|
||||
return "(±" + getUncertaintySeconds() + "s)";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
@ -201,19 +244,49 @@ public class Arrival implements Comparable<Arrival> {
|
||||
builder.append(" (w/ xfer)");
|
||||
}
|
||||
builder.append(", ");
|
||||
builder.append(trainLength);
|
||||
int secondsLeft = getMeanSecondsLeft();
|
||||
if (getMinutes() == 0 || secondsLeft < 0) {
|
||||
builder.append(" car train has arrived");
|
||||
} else {
|
||||
builder.append(" car train in ");
|
||||
builder.append(secondsLeft / 60);
|
||||
builder.append("m, ");
|
||||
builder.append(secondsLeft % 60);
|
||||
builder.append("s, ±");
|
||||
builder.append(getUncertaintySeconds());
|
||||
builder.append("s");
|
||||
}
|
||||
builder.append(getCountdownText());
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeString(destination.abbreviation);
|
||||
dest.writeString(destinationColor);
|
||||
dest.writeString(platform);
|
||||
dest.writeString(direction);
|
||||
dest.writeByte((byte) (bikeAllowed ? 1 : 0));
|
||||
dest.writeInt(trainLength);
|
||||
dest.writeByte((byte) (requiresTransfer ? 1 : 0));
|
||||
dest.writeInt(minutes);
|
||||
dest.writeLong(minEstimate);
|
||||
dest.writeLong(maxEstimate);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
destination = Station.getByAbbreviation(in.readString());
|
||||
destinationColor = in.readString();
|
||||
platform = in.readString();
|
||||
direction = in.readString();
|
||||
bikeAllowed = in.readByte() != 0;
|
||||
trainLength = in.readInt();
|
||||
requiresTransfer = in.readByte() != 0;
|
||||
minutes = in.readInt();
|
||||
minEstimate = in.readLong();
|
||||
maxEstimate = in.readLong();
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<Arrival> CREATOR = new Parcelable.Creator<Arrival>() {
|
||||
public Arrival createFromParcel(Parcel in) {
|
||||
return new Arrival(in);
|
||||
}
|
||||
|
||||
public Arrival[] newArray(int size) {
|
||||
return new Arrival[size];
|
||||
}
|
||||
};
|
||||
}
|
@ -26,7 +26,7 @@ public class BartContentProvider extends ContentProvider {
|
||||
/**
|
||||
* The default sort order for events
|
||||
*/
|
||||
private static final String DEFAULT_SORT_ORDER = FavoritesColumns.FROM_STATION.string
|
||||
private static final String DEFAULT_SORT_ORDER = RoutesColumns.FROM_STATION.string
|
||||
+ " DESC";
|
||||
|
||||
static {
|
||||
@ -35,12 +35,12 @@ public class BartContentProvider extends ContentProvider {
|
||||
sUriMatcher.addURI(Constants.AUTHORITY, "favorites/#", FAVORITE_ID);
|
||||
|
||||
sFavoritesProjectionMap = new HashMap<String, String>();
|
||||
sFavoritesProjectionMap.put(FavoritesColumns._ID.string,
|
||||
FavoritesColumns._ID.string);
|
||||
sFavoritesProjectionMap.put(FavoritesColumns.FROM_STATION.string,
|
||||
FavoritesColumns.FROM_STATION.string);
|
||||
sFavoritesProjectionMap.put(FavoritesColumns.TO_STATION.string,
|
||||
FavoritesColumns.TO_STATION.string);
|
||||
sFavoritesProjectionMap.put(RoutesColumns._ID.string,
|
||||
RoutesColumns._ID.string);
|
||||
sFavoritesProjectionMap.put(RoutesColumns.FROM_STATION.string,
|
||||
RoutesColumns.FROM_STATION.string);
|
||||
sFavoritesProjectionMap.put(RoutesColumns.TO_STATION.string,
|
||||
RoutesColumns.TO_STATION.string);
|
||||
}
|
||||
|
||||
private DatabaseHelper mDatabaseHelper;
|
||||
@ -81,7 +81,7 @@ public class BartContentProvider extends ContentProvider {
|
||||
} else if (match == FAVORITE_ID) {
|
||||
qb.setTables(DatabaseHelper.FAVORITES_TABLE_NAME);
|
||||
qb.setProjectionMap(sFavoritesProjectionMap);
|
||||
qb.appendWhere(FavoritesColumns._ID + " = "
|
||||
qb.appendWhere(RoutesColumns._ID + " = "
|
||||
+ uri.getPathSegments().get(1));
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown URI " + uri);
|
||||
@ -121,12 +121,12 @@ public class BartContentProvider extends ContentProvider {
|
||||
long rowId = -1;
|
||||
Cursor cursor = db
|
||||
.query(DatabaseHelper.FAVORITES_TABLE_NAME,
|
||||
new String[] { FavoritesColumns._ID.string },
|
||||
FavoritesColumns.FROM_STATION + "=? AND "
|
||||
+ FavoritesColumns.TO_STATION + "=?",
|
||||
new String[] { RoutesColumns._ID.string },
|
||||
RoutesColumns.FROM_STATION + "=? AND "
|
||||
+ RoutesColumns.TO_STATION + "=?",
|
||||
new String[] {
|
||||
values.getAsString(FavoritesColumns.FROM_STATION.string),
|
||||
values.getAsString(FavoritesColumns.TO_STATION.string) },
|
||||
values.getAsString(RoutesColumns.FROM_STATION.string),
|
||||
values.getAsString(RoutesColumns.TO_STATION.string) },
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
@ -139,7 +139,7 @@ public class BartContentProvider extends ContentProvider {
|
||||
}
|
||||
if (rowId < 0) {
|
||||
rowId = db.insert(DatabaseHelper.FAVORITES_TABLE_NAME,
|
||||
FavoritesColumns.FROM_STATION.string, values);
|
||||
RoutesColumns.FROM_STATION.string, values);
|
||||
}
|
||||
if (rowId > 0) {
|
||||
Uri eventUri = ContentUris.withAppendedId(
|
||||
@ -174,7 +174,7 @@ public class BartContentProvider extends ContentProvider {
|
||||
} else if (match == FAVORITE_ID) {
|
||||
String favoriteId = uri.getPathSegments().get(1);
|
||||
count = db.delete(DatabaseHelper.FAVORITES_TABLE_NAME,
|
||||
FavoritesColumns._ID + " = "
|
||||
RoutesColumns._ID + " = "
|
||||
+ favoriteId
|
||||
+ (!TextUtils.isEmpty(where) ? " AND (" + where
|
||||
+ ')' : ""), whereArgs);
|
||||
|
@ -13,7 +13,7 @@ public final class CursorUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static final String getString(Cursor cursor, FavoritesColumns column) {
|
||||
public static final String getString(Cursor cursor, RoutesColumns column) {
|
||||
return cursor.getString(cursor.getColumnIndex(column.string));
|
||||
}
|
||||
|
||||
|
@ -18,9 +18,9 @@ public class DatabaseHelper extends SQLiteOpenHelper {
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
db.execSQL("CREATE TABLE " + FAVORITES_TABLE_NAME + " (" +
|
||||
FavoritesColumns._ID.getColumnDef() + " PRIMARY KEY, " +
|
||||
FavoritesColumns.FROM_STATION.getColumnDef() + ", " +
|
||||
FavoritesColumns.TO_STATION.getColumnDef() + ");");
|
||||
RoutesColumns._ID.getColumnDef() + " PRIMARY KEY, " +
|
||||
RoutesColumns.FROM_STATION.getColumnDef() + ", " +
|
||||
RoutesColumns.TO_STATION.getColumnDef() + ");");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,12 +1,12 @@
|
||||
package com.dougkeen.bart.data;
|
||||
|
||||
public enum FavoritesColumns {
|
||||
public enum RoutesColumns {
|
||||
_ID("_id", "INTEGER"),
|
||||
FROM_STATION("FROM_STATION", "TEXT"),
|
||||
TO_STATION("TO_STATION", "TEXT");
|
||||
|
||||
// This class cannot be instantiated
|
||||
private FavoritesColumns(String string, String type) {
|
||||
private RoutesColumns(String string, String type) {
|
||||
this.string = string;
|
||||
this.sqliteType = type;
|
||||
}
|
109
xfer.svg
Normal file
@ -0,0 +1,109 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="32px"
|
||||
height="32px"
|
||||
id="svg2383"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.46"
|
||||
sodipodi:docname="xfer.svg"
|
||||
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||
<defs
|
||||
id="defs2385">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 16 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="32 : 16 : 1"
|
||||
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
||||
id="perspective2391" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="22.395604"
|
||||
inkscape:cx="14.100126"
|
||||
inkscape:cy="15.964773"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1125"
|
||||
inkscape:window-x="1911"
|
||||
inkscape:window-y="-9" />
|
||||
<metadata
|
||||
id="metadata2388">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
style="fill:#29716d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 6.117272,8.0220801 L 0.58047106,15.702158 L 26.255152,15.702158 L 26.255152,11.460255 L 6.117272,11.504906 L 6.117272,8.0220801 z"
|
||||
id="path2393"
|
||||
sodipodi:nodetypes="cccccc"
|
||||
inkscape:export-filename="C:\Users\dkeen\Workspaces\AndroidExperiments\DontMissTheBart\res\drawable\xfer.png"
|
||||
inkscape:export-xdpi="117.18631"
|
||||
inkscape:export-ydpi="117.18631" />
|
||||
<path
|
||||
style="fill:#143635;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 25.964917,23.382236 L 31.501718,15.702158 L 5.8270365,15.702158 L 5.8270365,19.944061 L 25.964917,19.89941 L 25.964917,23.382236 z"
|
||||
id="path3165"
|
||||
sodipodi:nodetypes="cccccc"
|
||||
inkscape:export-filename="C:\Users\dkeen\Workspaces\AndroidExperiments\DontMissTheBart\res\drawable\xfer.png"
|
||||
inkscape:export-xdpi="117.18631"
|
||||
inkscape:export-ydpi="117.18631" />
|
||||
<flowRoot
|
||||
xml:space="preserve"
|
||||
id="flowRoot3167"
|
||||
style="font-size:4;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
|
||||
transform="translate(8.0372916,9.5554467)"
|
||||
inkscape:export-filename="C:\Users\dkeen\Workspaces\AndroidExperiments\DontMissTheBart\res\drawable\xfer.png"
|
||||
inkscape:export-xdpi="117.18631"
|
||||
inkscape:export-ydpi="117.18631"><flowRegion
|
||||
id="flowRegion3169"><rect
|
||||
id="rect3171"
|
||||
width="17.63739"
|
||||
height="10.359176"
|
||||
x="3.2595682"
|
||||
y="4.2266922"
|
||||
style="font-size:4px;fill:#000000" /></flowRegion><flowPara
|
||||
id="flowPara3173"
|
||||
style="font-size:4" /></flowRoot> <text
|
||||
xml:space="preserve"
|
||||
style="font-size:4px;font-style:normal;font-weight:normal;line-height:125%;fill:#f2f3ed;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
|
||||
x="10.001963"
|
||||
y="18.068693"
|
||||
id="text3175"
|
||||
sodipodi:linespacing="125%"
|
||||
inkscape:export-xdpi="117.18631"
|
||||
inkscape:export-ydpi="117.18631"
|
||||
inkscape:export-filename="C:\Users\dkeen\Workspaces\AndroidExperiments\DontMissTheBart\res\drawable\xfer.png"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3177"
|
||||
x="10.001963"
|
||||
y="18.068693"
|
||||
style="font-size:6px;font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Helvetica Inserat LT Std;-inkscape-font-specification:Helvetica Inserat LT Std Ultra-Bold;fill:#f2f3ed">XFER</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.7 KiB |