/*
* Copyright (C) 2012-2015 Paul Watts (paulcwatts@gmail.com), Sean J. Barbeau (sjbarbeau@gmail.com),
* York Region Transit / VIVA
*
* 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 org.onebusaway.android.ui;
import org.onebusaway.android.R;
import org.onebusaway.android.io.elements.ObaArrivalInfo;
import org.onebusaway.android.provider.ObaContract;
import org.onebusaway.android.util.ArrivalInfoUtils;
import org.onebusaway.android.util.UIUtils;
import org.onebusaway.util.comparators.AlphanumComparator;
import android.content.ContentValues;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageButton;
import android.widget.RelativeLayout;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/**
* Styles of arrival times used by York Region Transit
*/
public class ArrivalsListAdapterStyleB extends ArrivalsListAdapterBase<CombinedArrivalInfoStyleB> {
private static final String TAG = "ArrivalsListAdapStyleB";
AlphanumComparator mAlphanumComparator = new AlphanumComparator();
ArrivalsListFragment mFragment;
public ArrivalsListAdapterStyleB(Context context) {
super(context, R.layout.arrivals_list_item_style_b);
}
public void setFragment(ArrivalsListFragment fragment) {
mFragment = fragment;
}
/**
* Sets the data to be used with the adapter
*
* @param routesFilter routeIds to filter for
* @param currentTime current time in milliseconds
*/
public void setData(ObaArrivalInfo[] arrivals, ArrayList<String> routesFilter,
long currentTime) {
if (arrivals != null) {
ArrayList<ArrivalInfo> list =
ArrivalInfoUtils.convertObaArrivalInfo(getContext(),
arrivals, routesFilter, currentTime, true);
// Sort list by route and headsign, in that order
Collections.sort(list, new Comparator<ArrivalInfo>() {
@Override
public int compare(ArrivalInfo s1, ArrivalInfo s2) {
int routeCompare = mAlphanumComparator
.compare(s1.getInfo().getRouteId(), s2.getInfo().getRouteId());
if (routeCompare != 0) {
return routeCompare;
} else {
// Compare headsigns when the route is the same
return mAlphanumComparator
.compare(s1.getInfo().getHeadsign(), s2.getInfo().getHeadsign());
}
}
});
if (list.size() > 0) {
ArrayList<CombinedArrivalInfoStyleB> newList
= new ArrayList<CombinedArrivalInfoStyleB>();
String currentRouteName = null;
String currentHeadsign = null;
CombinedArrivalInfoStyleB cArrivalInfo = new CombinedArrivalInfoStyleB();
for (int i = 0; i < list.size(); i++) {
if (currentRouteName == null) {
// Initialize fields
currentRouteName = list.get(i).getInfo().getRouteId();
currentHeadsign = list.get(i).getInfo().getHeadsign();
} else {
if (!currentRouteName.equals(list.get(i).getInfo().getRouteId()) ||
!currentHeadsign.equals(list.get(i).getInfo().getHeadsign())) {
// Create a new card
newList.add(cArrivalInfo);
cArrivalInfo = new CombinedArrivalInfoStyleB();
currentRouteName = list.get(i).getInfo().getRouteId();
currentHeadsign = list.get(i).getInfo().getHeadsign();
}
}
cArrivalInfo.getArrivalInfoList().add(list.get(i));
}
if (!cArrivalInfo.getArrivalInfoList().isEmpty()) {
newList.add(cArrivalInfo);
setData(newList);
return;
}
}
}
// If we get this far, we don't have any data to use
setData(null);
}
@Override
protected void initView(final View view, CombinedArrivalInfoStyleB combinedArrivalInfoStyleB) {
final ArrivalInfo stopInfo = combinedArrivalInfoStyleB.getArrivalInfoList().get(0);
final ObaArrivalInfo arrivalInfo = stopInfo.getInfo();
final Context context = getContext();
LayoutInflater inflater = LayoutInflater.from(context);
TextView routeName = (TextView) view.findViewById(R.id.routeName);
TextView destination = (TextView) view.findViewById(R.id.routeDestination);
// TableLayout that we will fill with TableRows of arrival times
TableLayout arrivalTimesLayout = (TableLayout) view.findViewById(R.id.arrivalTimeLayout);
arrivalTimesLayout.removeAllViews();
Resources r = view.getResources();
ImageButton starBtn = (ImageButton) view.findViewById(R.id.route_star);
starBtn.setColorFilter(r.getColor(R.color.theme_primary));
ImageButton mapImageBtn = (ImageButton) view.findViewById(R.id.mapImageBtn);
mapImageBtn.setColorFilter(r.getColor(R.color.theme_primary));
ImageButton routeMoreInfo = (ImageButton) view.findViewById(R.id.route_more_info);
routeMoreInfo.setColorFilter(r.getColor(R.color.switch_thumb_normal_material_dark));
starBtn.setImageResource(stopInfo.isRouteAndHeadsignFavorite() ?
R.drawable.focus_star_on :
R.drawable.focus_star_off);
starBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Show dialog for setting route favorite
RouteFavoriteDialogFragment dialog = new RouteFavoriteDialogFragment.Builder(
stopInfo.getInfo().getRouteId(), stopInfo.getInfo().getHeadsign())
.setRouteShortName(stopInfo.getInfo().getShortName())
.setRouteLongName(stopInfo.getInfo().getRouteLongName())
.setStopId(stopInfo.getInfo().getStopId())
.setFavorite(!stopInfo.isRouteAndHeadsignFavorite())
.build();
dialog.setCallback(new RouteFavoriteDialogFragment.Callback() {
@Override
public void onSelectionComplete(boolean savedFavorite) {
if (savedFavorite) {
mFragment.refreshLocal();
}
}
});
dialog.show(mFragment.getFragmentManager(), RouteFavoriteDialogFragment.TAG);
}
});
// Setup map
mapImageBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mFragment.showRouteOnMap(stopInfo);
}
});
// Setup more
routeMoreInfo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mFragment.showListItemMenu(view, stopInfo);
}
});
routeName.setText(arrivalInfo.getShortName());
destination.setText(UIUtils.formatDisplayText(arrivalInfo.getHeadsign()));
// Loop through the arrival times and create the TableRows that contains the data
for (int i = 0; i < combinedArrivalInfoStyleB.getArrivalInfoList().size(); i++) {
final ArrivalInfo arrivalRow = combinedArrivalInfoStyleB.getArrivalInfoList().get(i);
final ObaArrivalInfo tempArrivalInfo = arrivalRow.getInfo();
long scheduledTime = tempArrivalInfo.getScheduledArrivalTime();
// Create a new row to be added
final TableRow tr = (TableRow) inflater
.inflate(R.layout.arrivals_list_tr_template_style_b, null);
// Layout and views to inflate from XML templates
RelativeLayout layout;
TextView scheduleView, estimatedView, statusView;
View divider;
if (i == 0) {
// Use larger styled layout/view for next arrival time
layout = (RelativeLayout) inflater
.inflate(R.layout.arrivals_list_rl_template_style_b_large, null);
scheduleView = (TextView) inflater
.inflate(R.layout.arrivals_list_tv_template_style_b_schedule_large, null);
estimatedView = (TextView) inflater
.inflate(R.layout.arrivals_list_tv_template_style_b_estimated_large, null);
statusView = (TextView) inflater
.inflate(R.layout.arrivals_list_tv_template_style_b_status_large, null);
} else {
// Use smaller styled layout/view for further out times
layout = (RelativeLayout) inflater
.inflate(R.layout.arrivals_list_rl_template_style_b_small, null);
scheduleView = (TextView) inflater
.inflate(R.layout.arrivals_list_tv_template_style_b_schedule_small, null);
estimatedView = (TextView) inflater
.inflate(R.layout.arrivals_list_tv_template_style_b_estimated_small, null);
statusView = (TextView) inflater
.inflate(R.layout.arrivals_list_tv_template_style_b_status_small, null);
}
// Set arrival times and status in views
scheduleView.setText(UIUtils.formatTime(context, scheduledTime));
if (arrivalRow.getPredicted()) {
long eta = arrivalRow.getEta();
if (eta == 0) {
estimatedView.setText(R.string.stop_info_eta_now);
} else {
estimatedView.setText(eta + " min");
}
} else {
estimatedView.setText(R.string.stop_info_eta_unknown);
}
statusView.setText(arrivalRow.getStatusText());
int colorCode = arrivalRow.getColor();
statusView.setBackgroundResource(R.drawable.round_corners_style_b_status);
GradientDrawable d = (GradientDrawable) statusView.getBackground();
d.setColor(context.getResources().getColor(colorCode));
int alpha;
if (i == 0) {
// Set next arrival
alpha = (int) (1.0f * 255); // X percent transparency
} else {
// Set smaller rows
alpha = (int) (.35f * 255); // X percent transparency
}
d.setAlpha(alpha);
// Set text color w/ alpha, but increase it a bit to give text better contrast
estimatedView.setTextColor(UIUtils.getTransparentColor(
context.getResources().getColor(colorCode), alpha * 2));
// Set padding on status view
int pSides = UIUtils.dpToPixels(context, 5);
int pTopBottom = UIUtils.dpToPixels(context, 2);
statusView.setPadding(pSides, pTopBottom, pSides, pTopBottom);
// Add TextViews to layout
layout.addView(scheduleView);
layout.addView(statusView);
layout.addView(estimatedView);
// Make sure the TextViews align left/center/right of parent relative layout
RelativeLayout.LayoutParams params1 = (RelativeLayout.LayoutParams) scheduleView
.getLayoutParams();
params1.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
params1.addRule(RelativeLayout.CENTER_VERTICAL);
scheduleView.setLayoutParams(params1);
RelativeLayout.LayoutParams params2 = (RelativeLayout.LayoutParams) statusView
.getLayoutParams();
params2.addRule(RelativeLayout.CENTER_IN_PARENT);
// Give status view a little extra margin
int p = UIUtils.dpToPixels(context, 3);
params2.setMargins(p, p, p, p);
statusView.setLayoutParams(params2);
RelativeLayout.LayoutParams params3 = (RelativeLayout.LayoutParams) estimatedView
.getLayoutParams();
params3.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
params3.addRule(RelativeLayout.CENTER_VERTICAL);
estimatedView.setLayoutParams(params3);
// Add layout to TableRow
tr.addView(layout);
// Add the divider, if its not the first row
if (i != 0) {
int dividerHeight = UIUtils.dpToPixels(context, 1);
divider = inflater.inflate(R.layout.arrivals_list_divider_template_style_b, null);
divider.setLayoutParams(
new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT,
dividerHeight));
arrivalTimesLayout.addView(divider);
}
// Add click listener
tr.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mFragment.showListItemMenu(tr, arrivalRow);
}
});
// Add TableRow to container layout
arrivalTimesLayout.addView(tr,
new TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.MATCH_PARENT));
}
// Show or hide reminder for this trip
ContentValues values = null;
if (mTripsForStop != null) {
values = mTripsForStop.getValues(arrivalInfo.getTripId());
}
if (values != null) {
String reminderName = values.getAsString(ObaContract.Trips.NAME);
TextView reminder = (TextView) view.findViewById(R.id.reminder);
if (reminderName.length() == 0) {
reminderName = context.getString(R.string.trip_info_noname);
}
reminder.setText(reminderName);
Drawable d = reminder.getCompoundDrawables()[0];
d = DrawableCompat.wrap(d);
DrawableCompat.setTint(d.mutate(), view.getResources().getColor(R.color.theme_primary));
reminder.setCompoundDrawables(d, null, null, null);
reminder.setVisibility(View.VISIBLE);
} else {
// Explicitly set reminder to invisible because we might be reusing
// this view.
View reminder = view.findViewById(R.id.reminder);
reminder.setVisibility(View.GONE);
}
}
}