/* This file is part of RateBeer For Android. RateBeer for Android 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. RateBeer for Android 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 RateBeer for Android. If not, see <http://www.gnu.org/licenses/>. */ package com.ratebeer.android.gui.fragments; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Date; import java.util.List; import android.content.Context; import android.content.Intent; import android.location.Address; import android.location.Geocoder; import android.net.Uri; import android.text.Html; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; import com.commonsware.cwac.merge.MergeAdapter; import com.google.android.gms.maps.MapView; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.MarkerOptions; import com.googlecode.androidannotations.annotations.AfterViews; import com.googlecode.androidannotations.annotations.EFragment; import com.googlecode.androidannotations.annotations.FragmentArg; import com.googlecode.androidannotations.annotations.InstanceState; import com.googlecode.androidannotations.annotations.OptionsItem; import com.googlecode.androidannotations.annotations.OptionsMenu; import com.googlecode.androidannotations.annotations.ViewById; import com.ratebeer.android.R; import com.ratebeer.android.api.ApiMethod; import com.ratebeer.android.api.CommandFailureResult; import com.ratebeer.android.api.CommandSuccessResult; import com.ratebeer.android.api.HttpHelper; import com.ratebeer.android.api.command.GetEventDetailsCommand; import com.ratebeer.android.api.command.GetEventDetailsCommand.Attendee; import com.ratebeer.android.api.command.GetEventDetailsCommand.EventDetails; import com.ratebeer.android.api.command.SetEventAttendanceCommand; import com.ratebeer.android.app.location.LocationUtils; import com.ratebeer.android.gui.components.RateBeerMapFragment; import com.ratebeer.android.gui.components.helpers.ActivityUtil; import com.ratebeer.android.gui.components.helpers.ArrayAdapter; import de.neofonie.mobile.app.android.widget.crouton.Crouton; import de.neofonie.mobile.app.android.widget.crouton.Style; @EFragment(R.layout.fragment_eventview) @OptionsMenu({R.menu.refresh, R.menu.share}) public class EventViewFragment extends RateBeerMapFragment { @FragmentArg @InstanceState protected String eventName = null; @FragmentArg @InstanceState protected int eventId; @InstanceState protected EventDetails details = null; @ViewById(R.id.eventview) protected ListView eventView; @ViewById(R.id.attendees) protected ListView attendeesView; @ViewById(R.id.name) protected TextView nameText; @ViewById(R.id.details) protected TextView detailsText; @ViewById(R.id.contact) protected TextView contactText; @ViewById protected TextView attendeeslabel; @ViewById(R.id.location) protected Button locationText; @ViewById(R.id.time) protected Button timeText; @ViewById(R.id.setattendance) protected Button setattendanceButton; private AttendeeAdapter attendeeAdapter; @ViewById(R.id.map_event) protected MapView mapEvent; public EventViewFragment() { } @AfterViews public void init() { if (eventView != null) { eventView.setAdapter(new EventViewAdapter()); eventView.setItemsCanFocus(true); } else { // Tablet attendeeAdapter = new AttendeeAdapter(getActivity(), new ArrayList<Attendee>()); attendeesView.setAdapter(attendeeAdapter); setMapView(mapEvent); } if (details != null) { publishDetails(details); } else { refreshDetails(); } } @OptionsItem(R.id.menu_share) protected void onShare() { // Start a share intent for this event Intent s = new Intent(Intent.ACTION_SEND); s.setType("text/plain"); s.putExtra(Intent.EXTRA_TEXT, getString(R.string.events_share, eventName, eventId)); startActivity(Intent.createChooser(s, getString(R.string.events_shareevent))); } @OptionsItem(R.id.menu_refresh) protected void refreshDetails() { execute(new GetEventDetailsCommand(getUser(), eventId)); } private void onAttendeeClick(int userId, String username) { load(UserViewFragment_.builder().userId(userId).userName(username).build()); } @Override public void onTaskSuccessResult(CommandSuccessResult result) { if (result.getCommand().getMethod() == ApiMethod.GetEventDetails) { publishDetails(((GetEventDetailsCommand) result.getCommand()).getDetails()); } else if (result.getCommand().getMethod() == ApiMethod.SetEventAttendance) { boolean isGoing = ((SetEventAttendanceCommand)result.getCommand()).isGoing(); Crouton.makeText(getActivity(), isGoing? R.string.events_nowattending: R.string.events_nownotattending, Style.CONFIRM).show(); refreshDetails(); } } private void publishDetails(EventDetails details) { this.details = details; // Update the event name and title this.eventName = details.name; // Show details setDetails(); } /** * Overrides the different textual details about this event, as shown as header, as well as the list of attendees * @param details The event details object, which includes the list of attendees */ public void setDetails() { nameText.setText(details.name); timeText.setText(details.days + (details.times == null || details.times.equals("")? "": "\n" + details.times)); timeText.setVisibility(View.VISIBLE); locationText.setText(details.location + "\n" + (details.city != null? details.city + "\n": "") + details.address); locationText.setVisibility(View.VISIBLE); detailsText.setText(Html.fromHtml(details.details.replace("\n", "<br />"))); contactText.setText(details.contact); attendeeAdapter.replace(details.attendees); attendeeslabel.setVisibility(View.VISIBLE); setattendanceButton.setVisibility(View.VISIBLE); if (details.isAttending(getUser().getUserID())) { setattendanceButton.setText(R.string.events_removeattendance); } else { setattendanceButton.setText(R.string.events_addattendance); } if (getMap() != null) { try { // Use Geocoder to look up the coordinates of this brewer try { List<Address> point = new Geocoder(getActivity()).getFromLocationName(details.address + " " + details.city, 1); if (point.size() <= 0) { // Cannot find address: hide the map getMapView().setVisibility(View.GONE); } else { // Found a location! Center the map here LocationUtils.initGoogleMap(getMap(), point.get(0).getLatitude(), point.get(0).getLongitude()); getMap().addMarker(new MarkerOptions() .position(new LatLng(point.get(0).getLatitude(), point.get(0).getLongitude())) .title(details.location).snippet(details.city) .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_YELLOW))); getMapView().setVisibility(View.VISIBLE); } } catch (IOException e) { // Can't connect to Geocoder server: hide the map getMapView().setVisibility(View.GONE); } } catch (NoSuchMethodError e) { // Geocoder is not available at all: hide the map getMapView().setVisibility(View.GONE); } } } private OnClickListener onLocationClicked = new OnClickListener() { @Override public void onClick(View v) { // Try to start Google Maps at the location Intent intent = new Intent(Intent.ACTION_VIEW); try { intent.setData(Uri.parse("geo:0,0?q=" + URLEncoder.encode(details.location + " " + details.address + (details.city != null? " " + details.city: ""), HttpHelper.UTF8))); } catch (UnsupportedEncodingException e) { } startActivity(intent); } }; private OnClickListener onTimeClicked = new OnClickListener() { @SuppressWarnings("deprecation") @Override public void onClick(View v) { // Try to establish the time of the event long eventStart = -1; long eventEnd = -1; try { if (details.days != null && details.days.length() > 0) { String[] days = details.days.split("-"); String startDay = "", endDay = ""; if (days.length > 0) startDay = days[0].trim(); eventStart = Date.parse(days[0].trim()); if (days.length > 1) { endDay = days[1].trim(); eventEnd = Date.parse(days[1].trim()); } else if (days.length > 0) { endDay = days[0].trim(); eventEnd = Date.parse(days[0].trim()); } if (details.times != null && details.times.length() > 0) { String[] times = details.times.replace(".", ":").split("-"); if (times.length > 0) eventStart = Date.parse(startDay + " " + times[0].trim()); if (times.length > 1) eventEnd = Date.parse(endDay + " " + times[1].trim()); } } } catch (Exception e) { // Ignore the failing of the date/time parsing } // Try to start the calendar application Intent intent = new Intent(Intent.ACTION_EDIT); intent.setType("vnd.android.cursor.item/event"); intent.putExtra("title", details.name); intent.putExtra("description", details.details); if (eventStart >= 0) intent.putExtra("beginTime", eventStart); if (eventEnd >= 0) intent.putExtra("endTime", eventEnd); startActivity(intent); } }; private OnClickListener onSetAttendanceClick = new OnClickListener() { @Override public void onClick(View v) { // Set (flip) the attendance to this event execute(new SetEventAttendanceCommand(getUser(), eventId, !details.isAttending(getUser().getUserID()))); } }; @Override public void onTaskFailureResult(CommandFailureResult result) { publishException(null, result.getException()); } private class EventViewAdapter extends MergeAdapter { public EventViewAdapter() { // Set the event detail fields View fields = getActivity().getLayoutInflater().inflate(R.layout.fragment_eventdetails, null); addView(fields); initFields(fields); // Set the list of attendees attendeeAdapter = new AttendeeAdapter(getActivity(), new ArrayList<GetEventDetailsCommand.Attendee>()); addAdapter(attendeeAdapter); } } private class AttendeeAdapter extends ArrayAdapter<Attendee> { private OnClickListener onRowClick = new OnClickListener() { @Override public void onClick(View v) { onAttendeeClick((Integer)v.findViewById(R.id.user).getTag(), ((TextView)v.findViewById(R.id.user)).getText().toString()); } }; public AttendeeAdapter(Context context, List<Attendee> objects) { super(context, objects); } @Override public View getView(int position, View convertView, ViewGroup parent) { // Get the right view, using a ViewHolder ViewHolder holder; if (convertView == null) { convertView = getActivity().getLayoutInflater().inflate(R.layout.list_item_attendee, null); ActivityUtil.makeListItemClickable(convertView, onRowClick); holder = new ViewHolder(); holder.name = (TextView) convertView.findViewById(R.id.user); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } // Bind the data Attendee item = getItem(position); holder.name.setTag(item.id); holder.name.setText(item.name); return convertView; } } protected static class ViewHolder { TextView name; } public void initFields(View fields) { nameText = (TextView) fields.findViewById(R.id.name); timeText = (Button) fields.findViewById(R.id.time); locationText = (Button) fields.findViewById(R.id.location); detailsText = (TextView) fields.findViewById(R.id.details); contactText = (TextView) fields.findViewById(R.id.contact); setMapView((MapView) fields.findViewById(R.id.map_event)); attendeeslabel = (TextView) fields.findViewById(R.id.attendeeslabel); setattendanceButton = (Button) fields.findViewById(R.id.setattendance); locationText.setOnClickListener(onLocationClicked ); timeText.setOnClickListener(onTimeClicked); setattendanceButton.setOnClickListener(onSetAttendanceClick); } }