Skip to content

Commit

Permalink
Show representative guide photos for the tag values (close #48)
Browse files Browse the repository at this point in the history
  • Loading branch information
budowski committed Aug 27, 2009
1 parent 3560751 commit faa20eb
Show file tree
Hide file tree
Showing 12 changed files with 324 additions and 7 deletions.
4 changes: 4 additions & 0 deletions iNaturalist/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@
android:configChanges="orientation"
android:name=".ObservationPhotosViewer" >
</activity>
<activity
android:configChanges="orientation"
android:name=".TaxonTagPhotosViewer" >
</activity>



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -616,16 +616,42 @@ public View getView(int position, View convertView, ViewGroup parent) {
title = (TextView) view.findViewById(R.id.title);
} else {
// Tag list item
GuideMenuTag guideMenuTag = (GuideMenuTag)item;

view = inflater.inflate(R.layout.guide_menu_tag, parent, false);
title = (TextView) view.findViewById(R.id.tagName);
TextView tagCount = (TextView) view.findViewById(R.id.tagCount);
tagCount.setText(String.valueOf(((GuideMenuTag)item).getCount()));
tagCount.setText(String.valueOf((guideMenuTag.getCount())));

if (mFilter.hasTag(((GuideMenuTag)item).getValue())) {
if (mFilter.hasTag(guideMenuTag.getValue())) {
// Tag is checked on
view.setBackgroundColor(Color.parseColor("#006600"));
tagCount.setTextColor(Color.parseColor("#FFFFFF"));
}


ImageView photoIcon = (ImageView) view.findViewById(R.id.tag_photo);
final String[] values = guideMenuTag.getValue().split("=", 2);
final List<GuideTaxonPhotoXML> photos = mGuideXml.getTagRepresentativePhoto(values[0], values[1]);

if (photos == null) {
// No representative photo for the tag value
photoIcon.setVisibility(View.INVISIBLE);
} else {
photoIcon.setVisibility(View.VISIBLE);
photoIcon.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(GuideDetails.this, TaxonTagPhotosViewer.class);
intent.putExtra("guide_id", mGuideXml.getID());
intent.putExtra("guide_xml_filename", mGuideXmlFilename);
intent.putExtra("tag_name", values[0]);
intent.putExtra("tag_value", values[1]);
startActivity(intent);
}
});
}

}

title.setText(itemText);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
import org.w3c.dom.Node;

import java.io.File;
import java.io.Serializable;

/**
* Represents a GuideTaxonPhotoXML XML node
*/
public class GuideTaxonPhotoXML extends BaseGuideXMLParser {
public class GuideTaxonPhotoXML extends BaseGuideXMLParser implements Serializable {

private GuideXML mGuide;

Expand Down
49 changes: 49 additions & 0 deletions iNaturalist/src/main/java/org/inaturalist/android/GuideXML.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.content.Context;
import android.util.Log;
import android.util.Pair;

import org.apache.commons.lang3.StringUtils;
import org.w3c.dom.Node;
Expand Down Expand Up @@ -46,6 +47,9 @@ public class GuideXML extends BaseGuideXMLParser {
private Map<String, Integer> mTagCounts;
private Map<String, Set<String>> mTags;

// Representative photos of the tag values (e.g. what photo should we display for "number of legs=4")
private Map<Pair<String, String>, List<GuideTaxonPhotoXML>> mReprTagPhotos;

/**
* Initialize the GuideXML class with the offline (downloaded) version of it
* @param context the app context
Expand Down Expand Up @@ -86,6 +90,8 @@ public GuideXML(Context context, String guideId, String path) {

// Parse all taxon tags
parseTags();
// Parse the TaxonImage tags (so we'll know what are the representative image for each tag value)
parseImageTags();
} catch (XPathExpressionException e) {
e.printStackTrace();
}
Expand Down Expand Up @@ -342,6 +348,49 @@ public String getNgzFileSize() {
return getValueByXPath("//ngz/size");
}

/**
* Utility method that parses out all of the guide photos's taxon tags
*/
private void parseImageTags() {
ArrayList<Node> nodes = getNodesByXPath("//GuideTaxon/GuidePhoto/tag");

if (nodes == null) {
return;
}

mReprTagPhotos = new HashMap<Pair<String, String>, List<GuideTaxonPhotoXML>>();

for (Node node: nodes) {
String predicateName = getAttribute(node, "predicate");
String value = getAttribute(node, "value");
Pair<String, String> key = new Pair<String, String>(predicateName, value);
GuideTaxonPhotoXML photo = new GuideTaxonPhotoXML(this, node.getParentNode());

if (!mReprTagPhotos.containsKey(key)) {
mReprTagPhotos.put(key, new ArrayList<GuideTaxonPhotoXML>());
}

List<GuideTaxonPhotoXML> photos = mReprTagPhotos.get(key);
photos.add(photo);
}
}

/**
* Returns the representative photos of a specific tag name + value combo.
*
* @param tagName the tag name (e.g. number of legs)
* @param tagValue the tag value (e.g. 3)
* @return the representative photos for that combo (or null if non existent)
*/
public List<GuideTaxonPhotoXML> getTagRepresentativePhoto(String tagName, String tagValue) {
Pair<String, String> key = new Pair<String, String>(tagName, tagValue);

if (!mReprTagPhotos.containsKey(key)) {
return null;
}

return mReprTagPhotos.get(key);
}

/**
* Utility method that parses out all of the guide's taxon tags
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,6 @@ public void onClick(View v) {
mFacebookAccessTokenTracker = new AccessTokenTracker() {
@Override
protected void onCurrentAccessTokenChanged(AccessToken oldToken, AccessToken newToken) {
Log.e("AAA", "NEW ACCESS TOKEN: " + newToken);
if (newToken != null) {
String username = mPreferences.getString("username", null);
if (username == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
package org.inaturalist.android;

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

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import uk.co.senab.photoview.HackyViewPager;
import uk.co.senab.photoview.PhotoViewAttacher;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.MenuItem;
import com.flurry.android.FlurryAgent;
import com.koushikdutta.urlimageviewhelper.UrlImageViewCallback;
import com.koushikdutta.urlimageviewhelper.UrlImageViewHelper;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager.LayoutParams;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;

public class TaxonTagPhotosViewer extends SherlockActivity {
private static String TAG = "TaxonTagPhotosViewer";
private INaturalistApp mApp;
private ActivityHelper mHelper;
private HackyViewPager mViewPager;
private String mGuideId;
private String mGuideXmlFilename;
private String mTagName;
private String mTagValue;
private GuideXML mGuideXml;

@Override
protected void onStart()
{
super.onStart();
FlurryAgent.onStartSession(this, INaturalistApp.getAppContext().getString(R.string.flurry_api_key));
FlurryAgent.logEvent(this.getClass().getSimpleName());
}

@Override
protected void onStop()
{
super.onStop();
FlurryAgent.onEndSession(this);
}


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

ActionBar actionBar = getSupportActionBar();
actionBar.setHomeButtonEnabled(true);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setIcon(android.R.color.transparent);
actionBar.setLogo(R.drawable.up_icon);

mApp = (INaturalistApp) getApplicationContext();
setContentView(R.layout.observation_photos);

Intent intent = getIntent();

if (savedInstanceState == null) {
mGuideId = intent.getStringExtra("guide_id");
mGuideXmlFilename = intent.getStringExtra("guide_xml_filename");
mTagName = intent.getStringExtra("tag_name");
mTagValue = intent.getStringExtra("tag_value");
actionBar.setTitle(mTagName + "=" + mTagValue);
} else {
mTagName = savedInstanceState.getString("tag_name");
mTagValue = savedInstanceState.getString("tag_value");
actionBar.setTitle(mTagName + "=" + mTagValue);
mGuideId = savedInstanceState.getString("guide_id");
mGuideXmlFilename = savedInstanceState.getString("guide_xml_filename");
}


mViewPager = (HackyViewPager) findViewById(R.id.id_pic_view_pager);

if (mGuideXmlFilename != null) {
// Load guide taxon from XML
mGuideXml = new GuideXML(this, mGuideId, mGuideXmlFilename);
mViewPager.setAdapter(new TagPicsPagerAdapter());
}

}


@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}

@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString("guide_id", mGuideId);
outState.putString("guide_xml_filename", mGuideXmlFilename);
outState.putString("tag_name", mTagName);
outState.putString("tag_value", mTagValue);
super.onSaveInstanceState(outState);
}


class TagPicsPagerAdapter extends PagerAdapter {
int mDefaultTaxonIcon;
List<String> mImages;

public TagPicsPagerAdapter() {
mImages = new ArrayList<String>();

List<GuideTaxonPhotoXML> photos = mGuideXml.getTagRepresentativePhoto(mTagName, mTagValue);
if ((photos != null) && (photos.size() > 0)) {
// Show the photos
for (int i = 0; i < photos.size(); i++) {
GuideTaxonPhotoXML photo = photos.get(i);
mImages.add(getPhotoLocation(photo));
}
} else {
// No photos at all
finish();
}
}

@Override
public int getCount() {
return mImages.size();
}

@Override
public View instantiateItem(ViewGroup container, int position) {

String imageUrl = mImages.get(position);
View layout = (View) getLayoutInflater().inflate(R.layout.observation_photo, null, false);
container.addView(layout, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
ImageView imageView = (ImageView) layout.findViewById(R.id.id_pic);
final ProgressBar loading = (ProgressBar) layout.findViewById(R.id.id_pic_loading);

final PhotoViewAttacher attacher = new PhotoViewAttacher(imageView);

if (mGuideXml.isGuideDownloaded()) {
// Show offline photo
Bitmap bitmap = BitmapFactory.decodeFile(imageUrl);
imageView.setImageBitmap(bitmap);

loading.setVisibility(View.INVISIBLE);
imageView.setVisibility(View.VISIBLE);

} else {
loading.setVisibility(View.VISIBLE);
imageView.setVisibility(View.INVISIBLE);

// Show online photo
UrlImageViewHelper.setUrlDrawable(imageView, imageUrl, mDefaultTaxonIcon, new UrlImageViewCallback() {
@Override
public void onLoaded(ImageView imageView, Bitmap loadedBitmap, String url, boolean loadedFromCache) {
loading.setVisibility(View.GONE);
imageView.setVisibility(View.VISIBLE);
attacher.update();
}

@Override
public Bitmap onPreSetBitmap(ImageView imageView, Bitmap loadedBitmap, String url, boolean loadedFromCache) {
// No post-processing of bitmap
return loadedBitmap;
}
});
}

return layout;
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}

@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}



}

private String getPhotoLocation(GuideTaxonPhotoXML photo) {
final GuideTaxonPhotoXML.PhotoSize[] DEFAULT_SIZES = {
GuideTaxonPhotoXML.PhotoSize.LARGE,
GuideTaxonPhotoXML.PhotoSize.MEDIUM,
GuideTaxonPhotoXML.PhotoSize.SMALL,
GuideTaxonPhotoXML.PhotoSize.THUMBNAIL
};

// Determine if to use offline/online photo
GuideTaxonPhotoXML.PhotoType photoType =
(mGuideXml.isGuideDownloaded() ? GuideTaxonPhotoXML.PhotoType.LOCAL : GuideTaxonPhotoXML.PhotoType.REMOTE);

String photoLocation = null;
for (GuideTaxonPhotoXML.PhotoSize size : DEFAULT_SIZES) {
photoLocation = photo.getPhotoLocation(photoType, size);

// See if we found a photo for current size - if not, try the next best size
if ((photoLocation != null) && (photoLocation.length() > 0)) break;
}

return photoLocation;
}


}

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit faa20eb

Please sign in to comment.