org.melato.bus.android.activity.SequenceActivity.java Source code

Java tutorial

Introduction

Here is the source code for org.melato.bus.android.activity.SequenceActivity.java

Source

/*-------------------------------------------------------------------------
 * Copyright (c) 2012,2013,2014 Alex Athanasopoulos.  All Rights Reserved.
 * alex@melato.org
 *-------------------------------------------------------------------------
 * This file is part of Athens Next Bus
 *
 * Athens Next Bus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Athens Next Bus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Athens Next Bus.  If not, see <http://www.gnu.org/licenses/>.
 *-------------------------------------------------------------------------
 */
package org.melato.bus.android.activity;

import java.util.ArrayList;
import java.util.List;

import org.melato.android.app.HelpActivity;
import org.melato.android.bookmark.BookmarksActivity;
import org.melato.android.menu.Menus;
import org.melato.bus.android.Info;
import org.melato.bus.android.R;
import org.melato.bus.android.bookmark.BookmarkTypes;
import org.melato.bus.client.Formatting;
import org.melato.bus.model.Route;
import org.melato.bus.model.RouteManager;
import org.melato.bus.model.Stop;
import org.melato.bus.plan.LegGroup;
import org.melato.bus.plan.RouteLeg;
import org.melato.bus.plan.Sequence;
import org.melato.bus.plan.WalkModel;
import org.melato.client.Bookmark;
import org.melato.client.IntAccessor;
import org.melato.gps.Point2D;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
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.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

/**
 * Displays a sequence and allows simple editing.
 * Launches the sequence schedule activity.
 * @author Alex Athanasopoulos
 */
public class SequenceActivity extends FragmentActivity implements OnItemClickListener, OnClickListener {
    private Sequence sequence;
    private List<SequenceItem> items;
    private ArrayAdapter<SequenceItem> adapter;
    private ListView listView;

    public static interface SequenceItem {
    }

    class LegItem implements SequenceItem {
        private LegGroup leg;
        private Route route;

        public LegItem(LegGroup leg, RouteManager routeManager) {
            super();
            this.leg = leg;
            route = routeManager.getRoute(leg.getLeg().getRouteId());
        }

        @Override
        public String toString() {
            RouteLeg leg = this.leg.getLeg();
            StringBuilder buf = new StringBuilder();
            buf.append(route.getLabel());
            buf.append(" ");
            buf.append(leg.getStop1().getName());
            Stop stop2 = leg.getStop2();
            if (stop2 != null) {
                buf.append(" -> ");
                buf.append(stop2.getName());
            }
            return buf.toString();
        }

        public LegGroup getLeg() {
            return leg;
        }

        public Route getRoute() {
            return route;
        }

    }

    public static class WalkItem implements SequenceItem {
        private float distance;
        private String label;

        private void initLabel(Context context) {
            WalkModel walkModel = Info.walkModel(context);
            label = context.getString(R.string.walk_leg, Formatting.straightDistance(distance),
                    walkModel.distanceDuration(distance));
        }

        public WalkItem(Point2D point1, Point2D point2, RouteManager routeManager, Context context) {
            super();
            distance = routeManager.getMetric().distance(point1, point2);
            System.out.println("WalkItem: from=" + point1 + " to=" + point2 + " distance=" + distance);
            initLabel(context);
        }

        @Override
        public String toString() {
            return label;
        }
    }

    static class SequenceItemAdapter extends ArrayAdapter<SequenceItem> {
        private Context context;
        private List<SequenceItem> items;

        public SequenceItemAdapter(Context context, List<SequenceItem> items) {
            super(context, R.layout.list_item, items);
            this.context = context;
            this.items = items;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView view = (TextView) super.getView(position, convertView, parent);
            SequenceItem leg = items.get(position);
            String text = leg.toString();
            if (leg instanceof LegItem) {
                LegItem legItem = (LegItem) leg;
                LegGroup legGroup = legItem.getLeg();
                int waitTime = legGroup.wait;
                if (waitTime != 0) {
                    StringBuilder buf = new StringBuilder();
                    buf.append(text);
                    LegFormatter.addWaitTime(buf, waitTime, context);
                    text = buf.toString();
                }
            }
            view.setText(text);
            return view;
        }
    }

    public List<SequenceItem> getSequenceItems(Sequence sequence, RouteManager routeManager) {
        List<SequenceItem> items = new ArrayList<SequenceItem>();
        RouteLeg previous = null;
        for (LegGroup leg : sequence.getLegs()) {
            if (previous != null) {
                items.add(new WalkItem(previous.getStop2(), leg.getLeg().getStop1(), routeManager, this));
            }
            items.add(new LegItem(leg, routeManager));
            previous = leg.getLeg();
        }
        return items;
    }

    public SequenceActivity() {
    }

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.list_activity);
        listView = (ListView) findViewById(R.id.listView);
        listView.setOnItemClickListener(this);
        registerForContextMenu(listView);
        sequence = Info.getSequence(this);
        registerForContextMenu(listView);
        resetList();
        Menus.addIcons(this, (LinearLayout) findViewById(R.id.icons), R.menu.sequence_menu, this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Info.saveSequence(this);
    }

    private void open(int position) {
        SequenceItem item = items.get(position);
        if (item instanceof LegItem) {
            RouteLeg leg = ((LegItem) item).leg.getLeg();
            BusActivities activities = new BusActivities(this);
            activities.showRoute(leg.getRStop1());
        }
    }

    private static class WaitTimeAccessor implements IntAccessor {
        private LegGroup leg;

        public WaitTimeAccessor(LegGroup leg) {
            this.leg = leg;
        }

        public WaitTimeAccessor(LegItem item) {
            this(item.leg);
        }

        @Override
        public int getValue() {
            return (leg.wait + 59) / 60;
        }

        @Override
        public void setValue(int value) {
            leg.wait = value * 60;
        }

    }

    private void editWaitTime(int position) {
        SequenceItem item = items.get(position);
        if (item instanceof LegItem) {
            LegItem legItem = (LegItem) item;
            FragmentManager f = getSupportFragmentManager();
            IntAccessor accessor = new WaitTimeAccessor(legItem);
            new TimeIntervalFragment(accessor).show(f, "dialog");
        }
    }

    @Override
    public void onItemClick(AdapterView<?> l, View view, int position, long id) {
        open(position);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        Menus.inflate(inflater, R.menu.sequence_menu, menu);
        HelpActivity.addItem(menu, this, Help.SEQUENCE);
        return true;
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.sequence_context, menu);
    }

    private void resetList() {
        items = getSequenceItems(sequence, Info.routeManager(this));
        adapter = new SequenceItemAdapter(this, items);
        listView.setAdapter(adapter);
        if (sequence.getLegs().isEmpty()) {
            setTitle(R.string.empty_sequence);
        } else {
            setTitle(sequence.getLabel(Info.routeManager(this)));
        }
    }

    private void removeLast() {
        List<LegGroup> legs = sequence.getLegs();
        if (!legs.isEmpty()) {
            RouteLeg last = legs.get(legs.size() - 1).getLeg();
            if (last.getStop2() != null) {
                last.setStop2(null);
            } else {
                legs.remove(legs.size() - 1);
            }
            resetList();
        }
    }

    private void removeFirst() {
        List<LegGroup> legs = sequence.getLegs();
        if (!legs.isEmpty()) {
            legs.remove(0);
            resetList();
        }
    }

    private int legIndex(int position) {
        int n = -1;
        for (int i = 0; i <= position; i++) {
            if (items.get(i) instanceof LegItem) {
                n++;
            }
        }
        return n;
    }

    private void removeLeg(int position) {
        if (items.get(position) instanceof LegItem) {
            int index = legIndex(position);
            if (index >= 0) {
                sequence.getLegs().remove(index);
                resetList();
            }
        }
    }

    public boolean onItemSelected(int itemId) {
        boolean handled = false;
        switch (itemId) {
        case R.id.clear:
            sequence.getLegs().clear();
            resetList();
            handled = true;
            break;
        case R.id.remove_last:
            removeLast();
            handled = true;
            break;
        case R.id.remove_first:
            removeFirst();
            handled = true;
            break;
        case R.id.schedule:
            startActivity(new Intent(this, SequenceScheduleActivity.class));
            handled = true;
            break;
        case R.id.map:
            SequenceActivities.showMap(this, sequence);
            handled = true;
            break;
        case R.id.bookmark:
            addBookmark(sequence);
            handled = true;
            break;
        }
        return handled ? true : false;
    }

    void addBookmark(Sequence sequence) {
        String label = sequence.getLabel(Info.routeManager(this));
        Bookmark bookmark = new Bookmark(BookmarkTypes.SEQUENCE, label, sequence);
        BookmarksActivity.addBookmarkDialog(this, bookmark);
    }

    @Override
    public void onClick(View v) {
        onItemSelected(v.getId());
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        return onItemSelected(item.getItemId());
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
        boolean handled = false;
        switch (item.getItemId()) {
        case R.id.open:
            open(info.position);
            handled = true;
            break;
        case R.id.remove:
            removeLeg(info.position);
            handled = true;
            break;
        case R.id.wait_time:
            editWaitTime(info.position);
            handled = true;
            break;
        default:
            break;
        }
        return handled;
    }
}