cl.smartcities.isci.transportinspector.adapters.dialogAdapters.IncomingBusesAdapter.java Source code

Java tutorial

Introduction

Here is the source code for cl.smartcities.isci.transportinspector.adapters.dialogAdapters.IncomingBusesAdapter.java

Source

package cl.smartcities.isci.transportinspector.adapters.dialogAdapters;

import android.app.AlertDialog;
import android.content.Context;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.AppCompatImageView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cl.smartcities.isci.transportinspector.R;
import cl.smartcities.isci.transportinspector.TranSappApplication;
import cl.smartcities.isci.transportinspector.backend.Bus;
import cl.smartcities.isci.transportinspector.backend.Service;
import cl.smartcities.isci.transportinspector.dialogs.BusListDialog;
import cl.smartcities.isci.transportinspector.drawables.BusListReportsDrawable;
import cl.smartcities.isci.transportinspector.serviceVisibility.ServiceVisibilityController;
import cl.smartcities.isci.transportinspector.utils.DebouncedOnClickListener;

/**
 * Created by Ivana on 28-10-15.
 * Refactored by aantoine on 14-06-16
 * <p/>
 * Adapter that shows a list with the buses coming to a certain bus stop and information related
 * to every bus on some ListView.
 */
public class IncomingBusesAdapter extends MultiStateArrayAdapter<Service, IncomingBusesAdapter.RowState> {

    private final float scale;
    private final int onIconColor;
    private final int onOffIconColor;
    private final int offIconColor;
    AlertDialog alertDialog;
    Typeface typeface;
    ArrayList<Service> services;
    final ArrayList<Service> originalServices;
    LayoutInflater mInflater;
    Context context;
    Drawable prev;
    Drawable next;
    Drawable onIcon;
    Drawable onOffIcon;
    Drawable offIcon;
    private String busStop;

    private List<String> viewStateMap;
    private AppCompatImageView visibilityIcon;

    public BusListDialog.OnDestroyListener getOnDestroyListener() {
        return new BusListDialog.OnDestroyListener() {
            @Override
            public void onDestroy() {
                ServiceVisibilityController.notifyNewState(viewStateMap);
            }
        };
    }

    public void setVisibilityIcon(AppCompatImageView visibilityIcon) {
        this.visibilityIcon = visibilityIcon;
    }

    public enum RowState {
        FIRST_BUS, SECOND_BUS
    }

    public IncomingBusesAdapter(Context pContext, ArrayList<Service> pServices, String busStop) {
        super(pContext, R.layout.bus_list_row);
        this.busStop = busStop;
        originalServices = pServices;
        loadViewState();
        this.typeface = Typeface.createFromAsset(pContext.getAssets(), pContext.getString(R.string.icon_font));
        this.mInflater = (LayoutInflater) pContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        this.context = pContext;
        this.next = ContextCompat.getDrawable(this.context, R.drawable.ic_navigate_next_black_36dp);
        this.prev = ContextCompat.getDrawable(this.context, R.drawable.ic_navigate_before_black_36dp);
        this.scale = getContext().getResources().getDisplayMetrics().density;
        this.onIcon = ContextCompat.getDrawable(getContext(), R.drawable.ic_location_on_28dp);
        this.onOffIcon = ContextCompat.getDrawable(getContext(), R.drawable.ic_location_on_28dp);
        this.offIcon = ContextCompat.getDrawable(getContext(), R.drawable.ic_location_off_28dp);
        this.onIconColor = ContextCompat.getColor(getContext(), R.color.green_button);
        this.offIconColor = ContextCompat.getColor(getContext(), R.color.color_grey_off);
        this.onOffIconColor = ContextCompat.getColor(getContext(), R.color.background_white);
    }

    private void loadViewState() {
        this.viewStateMap = ServiceVisibilityController.getStateForServices(getContext(), busStop);
        this.services = reorderServices();
    }

    @Override
    protected RowState getDefaultState() {
        return RowState.FIRST_BUS;
    }

    /* amount of rows that will be drawn on the list */
    @Override
    public int getCount() {
        if (this.services != null)
            return this.services.size();
        else
            return 1;
    }

    private void setCorrectView(final ViewHolder holder, final int position, Service service) {
        final String serviceName = service.getServiceName();
        ArrayList<Bus> buses = service.getBuses();
        holder.bus.setText(serviceName);
        Bus selectedBus;
        final ArrayList<Bus> finalBuses = service.getBuses();
        holder.moreButton.setVisibility(View.VISIBLE);
        if (getLastStateAccordingToPosition(position) == RowState.FIRST_BUS) {
            selectedBus = buses.get(0);
            ((ViewGroup.MarginLayoutParams) holder.amountOfReports.getLayoutParams()).leftMargin = (int) (0 * scale
                    + 0.5f);

            holder.moreButton.setImageDrawable(next);
            holder.moreButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    setCurrentState(position, RowState.SECOND_BUS);
                    setCorrectView(holder, position, services.get(position));

                    Map<String, String> attributes = new HashMap<>();
                    attributes.put("Service code", serviceName);
                    TranSappApplication.addFabricLog("Next Bus Icon Clicked", attributes);
                }
            });
            holder.amountOfReports.setOnClickListener(new DebouncedOnClickListener(1000) {
                @Override
                public void onDeBouncedClick(View v) {
                    setEventsList(position, finalBuses, 1);
                }
            });
        } else {
            selectedBus = buses.get(1);
            holder.moreButton.setImageDrawable(prev);
            holder.moreButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    setCurrentState(position, RowState.FIRST_BUS);
                    setCorrectView(holder, position, services.get(position));
                }
            });
            holder.amountOfReports.setOnClickListener(new DebouncedOnClickListener(1000) {
                @Override
                public void onDeBouncedClick(View v) {
                    setEventsList(position, finalBuses, 2);
                }
            });
        }

        int reports = selectedBus.getAmountOfReports();
        holder.amountOfReports
                .setImageDrawable(new BusListReportsDrawable(this.context, reports, selectedBus.getBusIcon()));
        holder.busTime.setText(selectedBus.getTime());
        holder.busDistance.setText(selectedBus.getFormattedDistance());
        holder.busPlate.setText(selectedBus.getFormattedPlate());
    }

    private void addToCurrentState(String serviceName) {
        if (!viewStateMap.contains(serviceName)) {
            viewStateMap.add(serviceName);
        }
    }

    private void deleteFromCurrentState(String serviceName) {
        viewStateMap.remove(serviceName);
    }

    private boolean isVisible(String serviceName) {
        return !viewStateMap.contains(serviceName);
    }

    private void setViewIconOn(final AppCompatImageView viewIcon, final Service service) {
        viewIcon.setImageDrawable(onIcon);
        viewIcon.setColorFilter(onIconColor);
        viewIcon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                addToCurrentState(service.getServiceName());
                ServiceVisibilityController.changeServiceState(getContext(), busStop, service, false);
                setViewIcon(visibilityIcon);
                reorderAndInvalidate();
            }
        });
    }

    private void reorderAndInvalidate() {
        this.services = reorderServices();
        this.notifyDataSetChanged();
    }

    private ArrayList<Service> reorderServices() {
        ArrayList<Service> onServices = new ArrayList<>();
        ArrayList<Service> offServices = new ArrayList<>();
        for (Service service : originalServices) {
            if (isVisible(service.getServiceName())) {
                onServices.add(service);
            } else {
                offServices.add(service);
            }
        }

        onServices.addAll(offServices);
        return onServices;
    }

    private void setViewIconOff(final AppCompatImageView viewIcon, final Service service) {
        viewIcon.setImageDrawable(offIcon);
        viewIcon.setColorFilter(offIconColor);
        viewIcon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                deleteFromCurrentState(service.getServiceName());
                ServiceVisibilityController.changeServiceState(getContext(), busStop, service, true);
                setViewIcon(visibilityIcon);
                reorderAndInvalidate();
            }
        });
    }

    /* set the view for the adapter */
    public View getView(final int position, View convertView, ViewGroup parent) {
        /* here for every row a view is set. Each row can show 2 buses. Every pair of buses
        belongs to one service.
         */
        ViewHolder holder;
        /* set view if this is the first time using it */
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.bus_list_row, parent, false);
            holder = new ViewHolder();
            /* First bus (the one that is nearer to the bus stop)*/
            holder.bus = (TextView) convertView.findViewById(R.id.bus_route);
            holder.amountOfReports = (ImageButton) convertView.findViewById(R.id.amount_of_bus_reports);
            holder.busTime = (TextView) convertView.findViewById(R.id.bus_time_to_bus_stop);
            holder.busDistance = (TextView) convertView.findViewById(R.id.bus_distance_to_bus_stop);
            holder.busPlate = (TextView) convertView.findViewById(R.id.bus_plate);
            holder.moreButton = (AppCompatImageView) convertView.findViewById(R.id.next_bus);
            holder.moreButton.setImageDrawable(this.next);
            holder.viewIcon = (AppCompatImageView) convertView.findViewById(R.id.show_on_off_icon);

            /* get necessary Typefaces */
            Typeface robotoRegular = Typeface.createFromAsset(this.getContext().getAssets(),
                    this.context.getString(R.string.roboto_regular_font));
            Typeface robotoBold = Typeface.createFromAsset(this.getContext().getAssets(),
                    this.context.getString(R.string.roboto_bold_font));
            holder.setHolderTypefaceRegular(robotoRegular);
            holder.setHolderTypefaceBold(robotoBold);
            /* save holder */
            convertView.setTag(holder);
        }
        /* If is not the first time we can recharge it */
        else {
            holder = (ViewHolder) convertView.getTag();
        }

        final Service service = services.get(position);

        if (!service.isEmptyService()) {
            setCorrectView(holder, position, service);
            if (service.getBuses().size() == 1) {
                holder.moreButton.setClickable(false);
                holder.moreButton.setVisibility(View.INVISIBLE);
            }
        }
        /* if there are no buses coming we show the service anyway */
        else {
            String serviceName = service.getServiceName();
            holder.bus.setText(serviceName);
            holder.busTime.setText(context.getString(R.string.not_license_plate));
            holder.busDistance.setText(context.getString(R.string.not_info_for_any_bus));
            holder.busPlate.setText(context.getString(R.string.not_license_plate));
            holder.moreButton.setVisibility(View.GONE);
            holder.amountOfReports.setImageDrawable(new BusListReportsDrawable(this.context, 0, R.drawable.bus01));
        }

        if (isVisible(service.getServiceName())) {
            setViewIconOn(holder.viewIcon, service);
        } else {
            setViewIconOff(holder.viewIcon, service);
        }

        /* background is set with slightly different colors depending if the row is odd or not */
        if (position % 2 == 1) {
            int backGroundColor = ContextCompat.getColor(context, R.color.odd_row);
            convertView.setBackgroundColor(backGroundColor);
        } else {
            int backGroundColor = ContextCompat.getColor(context, R.color.even_row);
            convertView.setBackgroundColor(backGroundColor);
        }
        return convertView;
    }

    @Override
    public void notifyDataSetChanged() {
        super.notifyDataSetChanged();
    }

    public void setDialog(AlertDialog dialog) {
        this.alertDialog = dialog;
    }

    /* this sets the view of the current ListView to the bus list */
    private void setBusesList(String pBusStopCode, String pBusStopTitle) {
        Button backButton = (Button) this.alertDialog.findViewById(R.id.back_button);
        TextView titleCode = (TextView) this.alertDialog.findViewById(R.id.bus_stop_code);
        TextView titleName = (TextView) this.alertDialog.findViewById(R.id.bus_stop_title);
        AppCompatImageView visibilityIcon = (AppCompatImageView) this.alertDialog
                .findViewById(R.id.visibility_icon);

        setViewIcon(visibilityIcon);
        /* set title elements */
        backButton.setVisibility(View.INVISIBLE);
        backButton.setClickable(false);
        titleCode.setText(pBusStopCode);
        titleName.setText(pBusStopTitle);
        /* set AlertDialog content view*/
        ListView listView = this.alertDialog.getListView();
        IncomingBusesAdapter adapter = new IncomingBusesAdapter(this.context, this.services, busStop);
        adapter.setDialog(this.alertDialog);
        adapter.setVisibilityIcon(visibilityIcon);
        listView.setAdapter(adapter);
    }

    private int hashMapState() {
        boolean someActive = false;
        boolean someInactive = false;
        for (Service service : originalServices) {
            if (isVisible(service.getServiceName())) {
                someActive = true;
            } else {
                someInactive = true;
            }
        }

        if (someActive && someInactive) {
            return 3;
        } else if (someActive) {
            return 2;
        }
        return 1;
    }

    public void setViewIcon(final AppCompatImageView visibilityIcon) {
        visibilityIcon.setVisibility(View.VISIBLE);
        int state = hashMapState();
        if (state == 1) {
            visibilityIcon.setColorFilter(offIconColor);
            visibilityIcon.setImageDrawable(offIcon);
            visibilityIcon.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    selectAllOn();
                    setViewIcon(visibilityIcon);
                }
            });
        } else if (state == 2) {
            visibilityIcon.setColorFilter(onIconColor);
            visibilityIcon.setImageDrawable(onIcon);
            visibilityIcon.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    selectAllOff();
                    setViewIcon(visibilityIcon);
                }
            });
        } else {
            visibilityIcon.setImageDrawable(onOffIcon);
            visibilityIcon.setColorFilter(onOffIconColor);
            visibilityIcon.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    selectAllOn();
                    setViewIcon(visibilityIcon);
                }
            });
        }
    }

    /* this sets the view of the current ListView to the event list of a bus */
    private void setEventsList(int pRow, ArrayList<Bus> pBus, int pShowing) {
        /* get row view */
        ListView listView = this.alertDialog.getListView();
        View v = listView.getChildAt(pRow - listView.getFirstVisiblePosition());
        if (v == null)
            return;
        /* get title elements */
        Button backButton = (Button) this.alertDialog.findViewById(R.id.back_button);
        TextView titleCode = (TextView) this.alertDialog.findViewById(R.id.bus_stop_code);
        TextView titleName = (TextView) this.alertDialog.findViewById(R.id.bus_stop_title);
        AppCompatImageView visibilityIcon = (AppCompatImageView) this.alertDialog
                .findViewById(R.id.visibility_icon);

        final String busStopCode = ((TextView) this.alertDialog.findViewById(R.id.bus_stop_code)).getText()
                .toString();
        final String busStopTitle = ((TextView) this.alertDialog.findViewById(R.id.bus_stop_title)).getText()
                .toString();
        /* decides which bus was being shown */
        int busIndex = pShowing - 1;
        /* shows the event list of the corresponding bus if there's at least one */
        if (pBus.get(busIndex).getAmountOfReports() > 0) {
            String code = pBus.get(busIndex).getService();
            String title = pBus.get(busIndex).getLicensePlate();
            titleCode.setText(code);
            titleName.setText(title);
            /* set back button to the list bus view */
            backButton.setVisibility(View.VISIBLE);
            visibilityIcon.setVisibility(View.GONE);
            backButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    setBusesList(busStopCode, busStopTitle);
                }
            });
            EventAdapter adapter = new EventAdapter(this.context, code, title, "Bus",
                    pBus.get(busIndex).getEvents());
            adapter.setDialog(this.alertDialog);
            listView.setAdapter(adapter);
        }
    }

    public void selectAllOn() {
        for (Service service : originalServices) {
            deleteFromCurrentState(service.getServiceName());
            ServiceVisibilityController.changeServiceState(getContext(), busStop, service, true);
        }
        reorderAndInvalidate();
    }

    public void selectAllOff() {
        for (Service service : originalServices) {
            addToCurrentState(service.getServiceName());
            ServiceVisibilityController.changeServiceState(getContext(), busStop, service, false);
        }
        reorderAndInvalidate();
    }

    /* ViewHolder to hold parameters */
    private static class ViewHolder extends EditableViewHolder {
        ImageButton amountOfReports;
        TextView bus;
        TextView busTime;
        TextView busDistance;
        TextView busPlate;
        AppCompatImageView moreButton;
        AppCompatImageView viewIcon;

        @Override
        public void setHolderTypefaceRegular(Typeface font) {
            setFont(font, busTime);
        }

        @Override
        public void setHolderTypefaceBold(Typeface font) {
            setFont(font, bus, busDistance, busPlate);
        }

        @Override
        public void setHolderIconFont(Typeface font) {

        }

    }
}