package de.blau.android.dialogs; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLEncoder; import java.util.List; import java.util.Locale; import org.acra.ACRA; import android.annotation.SuppressLint; import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.text.Html; import android.text.TextUtils; import android.text.TextUtils.TruncateAt; import android.text.method.LinkMovementMethod; import android.text.util.Linkify; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ScrollView; import android.widget.TableLayout; import android.widget.TableRow; import android.widget.TextView; import de.blau.android.R; import de.blau.android.contract.Urls; import de.blau.android.osm.Node; import de.blau.android.osm.OsmElement; import de.blau.android.osm.Relation; import de.blau.android.osm.RelationMember; import de.blau.android.osm.Tags; import de.blau.android.osm.Way; import de.blau.android.prefs.Preferences; /** * Very simple dialog fragment to display some info on an OSM element * @author simon * */ public class ElementInfo extends DialogFragment { private static final String DEBUG_TAG = ElementInfo.class.getName(); private static final String TAG = "fragment_element_info"; private static final int FIRST_CELL_WIDTH = 5; private static final int MAX_FIRST_CELL_WIDTH = 8; static public void showDialog(FragmentActivity activity, OsmElement e) { dismissDialog(activity); try { FragmentManager fm = activity.getSupportFragmentManager(); ElementInfo elementInfoFragment = newInstance(e); if (elementInfoFragment != null) { elementInfoFragment.show(fm, TAG); } else { Log.e(DEBUG_TAG,"Unable to create dialog for value " + e.getDescription()); } } catch (IllegalStateException isex) { Log.e(DEBUG_TAG,"showDialog",isex); } } private static void dismissDialog(FragmentActivity activity) { try { FragmentManager fm = activity.getSupportFragmentManager(); FragmentTransaction ft = fm.beginTransaction(); Fragment fragment = fm.findFragmentByTag(TAG); if (fragment != null) { ft.remove(fragment); } ft.commit(); } catch (IllegalStateException isex) { Log.e(DEBUG_TAG,"showDialog",isex); } } /** */ private static ElementInfo newInstance(OsmElement e) { ElementInfo f = new ElementInfo(); Bundle args = new Bundle(); args.putSerializable("element", e); f.setArguments(args); f.setShowsDialog(true); return f; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Preferences prefs = new Preferences(getActivity()); if (prefs.lightThemeEnabled()) { setStyle(DialogFragment.STYLE_NORMAL,R.style.Theme_DialogLight); } else { setStyle(DialogFragment.STYLE_NORMAL,R.style.Theme_DialogDark); } } @SuppressWarnings("deprecation") @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { ScrollView sv = (ScrollView) inflater.inflate(R.layout.element_info_view, container, false); TableLayout tl = (TableLayout) sv.findViewById(R.id.element_info_vertical_layout); OsmElement e = (OsmElement) getArguments().getSerializable("element"); TableLayout.LayoutParams tp= new TableLayout.LayoutParams (TableLayout.LayoutParams.FILL_PARENT,TableLayout.LayoutParams.WRAP_CONTENT); tp.setMargins(10, 2, 10, 2); if (e != null) { // tl.setShrinkAllColumns(true); tl.setColumnShrinkable(1, true); tl.addView(createRow(R.string.type,e.getName(),tp)); tl.addView(createRow(R.string.id,"#" + e.getOsmId(),tp)); tl.addView(createRow(R.string.version,"" + e.getOsmVersion(),tp)); if (e.getName().equals(Node.NAME)) { tl.addView(createRow(R.string.location_lon_label, String.format(Locale.US,"%.7f", ((Node)e).getLon()/1E7d) + "°",tp)); tl.addView(createRow(R.string.location_lat_label, String.format(Locale.US,"%.7f", ((Node)e).getLat()/1E7d) + "°",tp)); } else if (e.getName().equals(Way.NAME)) { tl.addView(divider()); boolean isClosed = ((Way)e).isClosed(); tl.addView(createRow(R.string.length_m, String.format(Locale.US,"%.2f",((Way)e).length()),tp)); tl.addView(createRow(R.string.nodes, "" + (((Way)e).nodeCount() + (isClosed?-1:0)),tp)); tl.addView(createRow(R.string.closed, getString(isClosed ? R.string.yes : R.string.no),tp)); // Make this expandable before enabling // for (Node n:((Way)e).getNodes()) { // tl.addView(createRow("", "" + n.getDescription(),tp)); // } } else if (e.getName().equals(Relation.NAME)) { tl.addView(divider()); List<RelationMember> members = ((Relation)e).getMembers(); tl.addView(createRow(R.string.members, "" + (members != null ? members.size() : 0),tp)); if (members != null) { int notDownloaded = 0; for (RelationMember rm:members) { if (rm.getElement()==null) { notDownloaded++; } } if (notDownloaded > 0) { tl.addView(createRow(R.string.not_downloaded, "" + notDownloaded,tp)); } } } if (e.hasProblem(getActivity())) { tl.addView(divider()); tl.addView(createRow(R.string.problem,e.describeProblem(),tp)); } if (e.getTags() != null && e.getTags().size() > 0) { tl.addView(divider()); tl.addView(createRow(R.string.menu_tags,null,tp)); for (String k:e.getTags().keySet()) { String value = e.getTags().get(k); // special handling for some stuff if (k.equals(Tags.KEY_WIKIPEDIA)) { Log.d(DEBUG_TAG,Urls.WIKIPEDIA + encodeHttpPath(value)); tl.addView(createRow(k, Html.fromHtml("<a href=\"" + Urls.WIKIPEDIA + encodeHttpPath(value) +"\">"+value+"</a>"),tp)); } else if (k.equals(Tags.KEY_WIKIDATA)) { tl.addView(createRow(k, Html.fromHtml("<a href=\"" + Urls.WIKIDATA + encodeHttpPath(value) +"\">"+value+"</a>"),tp)); } else if (Tags.isWebsiteKey(k)) { try { URL url = new URL(value); URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef()); tl.addView(createRow(k, Html.fromHtml("<a href=\"" + uri.toURL() + "\">"+value+"</a>"),tp)); } catch (MalformedURLException e1) { Log.d(DEBUG_TAG,"Value " + value + " caused " + e); tl.addView(createRow(k,value,tp)); } catch (URISyntaxException e1) { Log.d(DEBUG_TAG,"Value " + value + " caused " + e); tl.addView(createRow(k,value,tp)); } } else { tl.addView(createRow(k,value,tp)); } } } if (e.getParentRelations() != null && e.getParentRelations().size() > 0) { tl.addView(divider()); tl.addView(createRow(R.string.relation_membership,null,tp)); for (Relation r:e.getParentRelations()) { RelationMember rm = r.getMember(e); if (rm != null) { String role = rm.getRole(); tl.addView(createRow(role.equals("")?getString(R.string.empty_role):role,r.getDescription(),tp)); } else { // inconsistent state String message = "inconsistent state: " + e.getDescription() + " is not a member of " + r; Log.d(DEBUG_TAG, message); ACRA.getErrorReporter().putCustomData("CAUSE", message); ACRA.getErrorReporter().putCustomData("STATUS","NOCRASH"); ACRA.getErrorReporter().handleException(null); } } } } getDialog().setTitle(R.string.element_information); return sv; } private String encodeHttpPath(String path) { try { return URLEncoder.encode(path, "UTF-8"); } catch (UnsupportedEncodingException e) { Log.d(DEBUG_TAG,"Path " + path + " caused " + e); return ""; } } @SuppressLint("NewApi") private TableRow createRow(String cell1, CharSequence cell2, TableLayout.LayoutParams tp) { TableRow tr = new TableRow(getActivity()); TextView cell = new TextView(getActivity()); cell.setSingleLine(); cell.setText(cell1); cell.setMinEms(FIRST_CELL_WIDTH); cell.setMaxEms(MAX_FIRST_CELL_WIDTH); if (cell2 == null) { cell.setTypeface(null,Typeface.BOLD); } cell.setEllipsize(TruncateAt.MARQUEE); tr.addView(cell); cell = new TextView(getActivity()); if (cell2 != null) { cell.setText(cell2); cell.setMinEms(FIRST_CELL_WIDTH); // cell.setHorizontallyScrolling(true); // cell.setSingleLine(true); cell.setEllipsize(TextUtils.TruncateAt.END); Linkify.addLinks(cell,Linkify.WEB_URLS); cell.setMovementMethod(LinkMovementMethod.getInstance()); cell.setPadding(5, 0, 0, 0); cell.setEllipsize(TruncateAt.MARQUEE); // This stops links from working // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // cell.setTextIsSelectable(true); // } tr.addView(cell); } tr.setLayoutParams(tp); return tr; } @SuppressLint("NewApi") private TableRow createRow(int cell1, CharSequence cell2, TableLayout.LayoutParams tp) { TableRow tr = new TableRow(getActivity()); TextView cell = new TextView(getActivity()); cell.setMinEms(FIRST_CELL_WIDTH); cell.setMaxEms(MAX_FIRST_CELL_WIDTH); cell.setMaxLines(2); cell.setText(cell1); if (cell2 == null) { cell.setTypeface(null,Typeface.BOLD); } cell.setEllipsize(TruncateAt.MARQUEE); tr.addView(cell); cell = new TextView(getActivity()); if (cell2 != null) { cell.setText(cell2); cell.setMinEms(FIRST_CELL_WIDTH); Linkify.addLinks(cell,Linkify.WEB_URLS); cell.setMovementMethod(LinkMovementMethod.getInstance()); cell.setPadding(5, 0, 0, 0); cell.setEllipsize(TruncateAt.MARQUEE); // This stops links from working // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { // cell.setTextIsSelectable(true); // } tr.addView(cell); } tr.setLayoutParams(tp); return tr; } @SuppressWarnings("deprecation") private View divider() { TableRow tr = new TableRow(getActivity()); View v = new View(getActivity()); TableRow.LayoutParams trp = new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT, 1); trp.span = 2; v.setLayoutParams(trp); v.setBackgroundColor(Color.rgb(204, 204, 204)); tr.addView(v); return tr; } }