package org.wordpress.android.ui.posts; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import android.app.ProgressDialog; import android.content.Intent; import android.os.Bundle; import android.os.Parcelable; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.CheckedTextView; import android.widget.ExpandableListView; import android.widget.ExpandableListView.OnChildClickListener; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.actionbarsherlock.app.ActionBar; import com.actionbarsherlock.app.SherlockListActivity; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.justsystems.hpb.pad.R; import com.justsystems.hpb.pad.util.Debug; import org.xmlrpc.android.XMLRPCClient; import org.xmlrpc.android.XMLRPCException; import org.wordpress.android.WordPress; import org.wordpress.android.models.Blog; import org.wordpress.android.models.HierarchicalTerm; import org.wordpress.android.models.PostType; import org.wordpress.android.models.Taxonomy; import org.wordpress.android.models.Term; import org.wordpress.android.task.MultiAsyncTask; import org.wordpress.android.task.RefreshMenuTask; public class SelectTermsActivity extends SherlockListActivity implements OnChildClickListener { private ExpandableListView listView; private ListAdapter adapter; private String typeName; private ProgressDialog pd; private Blog blog; private int blogId; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); this.typeName = getIntent().getStringExtra("type_name"); setContentView(R.layout.select_terms); setTitle(getResources().getString(R.string.select_categories)); ActionBar actionBar = getSupportActionBar(); actionBar.setHomeButtonEnabled(true); actionBar.setDisplayHomeAsUpEnabled(true); Bundle extras = getIntent().getExtras(); if (extras != null) { blogId = extras.getInt("id"); try { blog = new Blog(blogId); } catch (Exception e) { Toast.makeText(this, getResources().getText(R.string.blog_not_found), Toast.LENGTH_SHORT).show(); finish(); } } this.listView = (ExpandableListView) findViewById(android.R.id.list); this.adapter = new ListAdapter(this, typeName); this.listView.setAdapter(adapter); this.listView.setGroupIndicator(null); this.listView.setChildIndicator(null); // this.listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); this.listView.setItemsCanFocus(false); this.listView.setOnChildClickListener(this); Parcelable[] parcelables = getIntent().getParcelableArrayExtra("term"); if (parcelables != null && parcelables.length > 0) { Term[] terms = new Term[parcelables.length]; for (int i = 0; i < parcelables.length; i++) { Term term = (Term) parcelables[i]; terms[i] = term; } loadSelectedCategories(terms); } if (this.adapter.shouldReload) { refreshCategories(true); return; } expandGroup(); } private void expandGroup() { for (int i = 0; i < adapter.getGroupCount(); i++) { listView.expandGroup(i); } } private void loadSelectedCategories(Term[] terms) { final int groupCount = this.adapter.getGroupCount(); if (groupCount > 0) { for (Term term : terms) { for (int i = 0; i < groupCount; i++) { final int childCount = this.adapter.getChildrenCount(i); for (int j = 0; j < childCount; j++) { final Term target = ((HierarchicalTerm) this.adapter .getChild(i, j)).getTerm(); if (target.getTermId().equals(term.getTermId())) { this.adapter.setCheckState(i, j, true); break; } } } } } else { refreshCategories(false); } } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); MenuInflater inflater = getSupportMenuInflater(); inflater.inflate(R.menu.categories, menu); return true; } @Override public boolean onOptionsItemSelected(final MenuItem item) { int itemId = item.getItemId(); if (itemId == R.id.menu_refresh) { refreshCategories(false); return true; } else if (itemId == R.id.menu_new_category) { Bundle bundle = new Bundle(); bundle.putInt("id", blogId); bundle.putString("type_name", typeName); Intent i = new Intent(SelectTermsActivity.this, AddTermActivity.class); i.putExtras(bundle); startActivityForResult(i, 0); return true; } else if (itemId == android.R.id.home) { saveAndFinish(); return true; } return super.onOptionsItemSelected(item); } @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { adapter.toggleCheckState(groupPosition, childPosition); return true; } private void refreshCategories(boolean shouldReloadTaxonomy) { pd = ProgressDialog.show(SelectTermsActivity.this, getResources() .getText(R.string.refreshing_categories), getResources() .getText(R.string.attempting_categories_refresh), true, true); RefreshCategoryTask task = new RefreshCategoryTask(); task.executeOnMultiThread(shouldReloadTaxonomy); } @Override public void onBackPressed() { saveAndFinish(); super.onBackPressed(); } /** * function addCategory * * @param String * category_name * @return * @description Adds a new category */ public boolean addCategory(String term_name, String term_taxonomy, String term_slug, String term_desc, int parent_id) { // Return string // Store the parameters for wp.addCategory Map<String, Object> struct = new HashMap<String, Object>(); struct.put("name", term_name); struct.put("taxonomy", term_taxonomy); if (term_slug != null && term_slug.length() > 0) { struct.put("slug", term_slug); } if (term_desc != null && term_desc.length() > 0) { struct.put("description", term_desc); } if (parent_id != 0) { struct.put("parent", parent_id); } XMLRPCClient client = new XMLRPCClient(blog.getUrl(), blog.getHttpuser(), blog.getHttppassword()); Object[] params = { blog.getBlogId(), blog.getUsername(), blog.getPassword(), struct }; Object result = null; try { result = client.call("wp.newTerm", params); } catch (XMLRPCException e) { e.printStackTrace(); } if (result == null) { return false; } String term_id = result.toString(); WordPress.wpDB.saveTerm(blogId, term_id, term_name, term_slug, term_taxonomy, term_desc, parent_id); return true; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (data != null) { final Bundle extras = data.getExtras(); switch (requestCode) { case 0: // Add category // Does the user want to continue, or did he press "dismiss"? if (extras.getString("continue").equals("TRUE")) { // Get name, slug and desc from Intent final String term_name = extras.getString("term_name"); final String term_taxonomy = extras .getString("term_taxonomy"); final String term_slug = extras.getString("term_slug"); final String term_desc = extras.getString("term_desc"); final int parent_id = extras.getInt("parent_id"); Debug.logd("term", "name:" + term_name + " taxonomy:" + term_taxonomy + " slug:" + term_slug + " desc:" + term_desc + " parent:" + parent_id); if (this.adapter.contains(term_taxonomy, term_name)) { // A category with the specified name already exists } else { // Add the category pd = ProgressDialog.show( SelectTermsActivity.this, getResources().getText( R.string.cat_adding_category), getResources().getText( R.string.cat_attempt_add_category), true, true); Thread th = new Thread() { public void run() { final boolean result = addCategory(term_name, term_taxonomy, term_slug, term_desc, parent_id); SelectTermsActivity.this .runOnUiThread(new Runnable() { @Override public void run() { if (result) { for (int i = 0; i < adapter .getGroupCount(); i++) { Taxonomy taxonomy = (Taxonomy) adapter .getGroup(i); if (taxonomy .getName() .equals(term_taxonomy)) { adapter.loadTerm(i); break; } } } pd.dismiss(); } }); } }; th.start(); } break; } }// end null check } } private void saveAndFinish() { String selectedCategories = ""; ArrayList<Term> result = new ArrayList<Term>(); for (int groupPosition = 0; groupPosition < adapter.getGroupCount(); groupPosition++) { ArrayList<Boolean> check = adapter.checked.get(groupPosition); for (int childPosition = 0; childPosition < adapter .getChildrenCount(groupPosition); childPosition++) { if (check.get(childPosition)) { Term term = ((HierarchicalTerm) adapter.getChild( groupPosition, childPosition)).getTerm(); result.add(term); } } } Term[] terms = result.toArray(new Term[0]); Bundle bundle = new Bundle(); selectedCategories = selectedCategories.trim(); if (selectedCategories.endsWith(",")) { selectedCategories = selectedCategories.substring(0, selectedCategories.length() - 1); } bundle.putString("selectedCategories", selectedCategories); Intent mIntent = new Intent(); mIntent.putExtras(bundle); mIntent.putExtra("term", terms); setResult(RESULT_OK, mIntent); finish(); } private class RefreshCategoryTask extends MultiAsyncTask<Object, Integer, Object> { private static final int PROGRESS_TAXONOMY = -100; @Override protected Object doInBackground(Object... params) { final boolean shouldReloadTaxonomy = params != null ? (Boolean) params[0] : false; XMLRPCClient client = new XMLRPCClient(blog.getUrl(), blog.getHttpuser(), blog.getHttppassword()); if (shouldReloadTaxonomy) { reloadTaxonomy(blog, client); } HashMap<String, Object> map = new HashMap<String, Object>(); map.put("orderby", "name"); Object[] parameters = { blog.getBlogId(), blog.getUsername(), blog.getPassword(), null }; for (int i = 0; i < adapter.getGroupCount(); i++) { Taxonomy taxonomy = (Taxonomy) adapter.getGroup(i); parameters[3] = taxonomy.getName(); Object result; try { result = client.call("wp.getTerms", parameters); } catch (XMLRPCException e) { continue; } if (result instanceof Object[]) { WordPress.wpDB.saveTerms(blogId, (Object[]) result); } publishProgress(i); } return null; } private void reloadTaxonomy(Blog blog, XMLRPCClient client) { final int id = blog.getId(); final int blogId = blog.getBlogId(); final String userName = blog.getUsername(); final String password = blog.getPassword(); RefreshMenuTask .saveTaxonomy(client, blogId, id, userName, password); publishProgress(PROGRESS_TAXONOMY); } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); if (values == null || values.length == 0) { return; } int index = values[0]; if (index == PROGRESS_TAXONOMY) { adapter.setTaxonomies(typeName); } else { adapter.loadTerm(index); } } @Override protected void onPostExecute(Object result) { super.onPostExecute(result); expandGroup(); if (pd != null && pd.isShowing()) { pd.dismiss(); } } } private static class ListAdapter extends BaseExpandableListAdapter { private SelectTermsActivity activity; private Taxonomy[] taxonomies; private final HashMap<Long, HierarchicalTerm[]> terms = new HashMap<Long, HierarchicalTerm[]>(); private final ArrayList<ArrayList<Boolean>> checked = new ArrayList<ArrayList<Boolean>>(); private boolean shouldReload = false; public ListAdapter(SelectTermsActivity activity, String typeName) { this.activity = activity; setTaxonomies(typeName); } public void setTaxonomies(String typeName) { checked.clear(); PostType type = new PostType(activity, WordPress.getCurrentBlog() .getId(), "", typeName); this.taxonomies = type.getTaxonomies(); for (int i = 0; i < taxonomies.length; i++) { ArrayList<Boolean> checked = new ArrayList<Boolean>(); this.checked.add(checked); if (!loadTerm(i)) { shouldReload = true; } } } boolean contains(String taxonomyName, String termName) { for (int i = 0; i < this.taxonomies.length; i++) { Taxonomy taxonomy = taxonomies[i]; final String label = taxonomy.getLabel(); if (label.equals(taxonomyName)) { final HierarchicalTerm[] terms = this.terms.get(taxonomy .getId()); for (int j = 0; j < terms.length; j++) { Term term = terms[j].getTerm(); final String targetTarmName = term.getName(); if (targetTarmName.equals(termName)) { return true; } } return false; } } return false; } void setCheckState(int groupPosition, int childPosition, boolean isChecked) { ArrayList<Boolean> childChecked = checked.get(groupPosition); boolean oldCheccked = childChecked.get(childPosition); if (oldCheccked == isChecked) { return; } childChecked.remove(childPosition); childChecked.add(childPosition, !oldCheccked); notifyDataSetInvalidated(); } void toggleCheckState(int groupPosition, int childPosition) { ArrayList<Boolean> childChecked = checked.get(groupPosition); boolean oldCheccked = childChecked.get(childPosition); childChecked.remove(childPosition); childChecked.add(childPosition, !oldCheccked); notifyDataSetInvalidated(); } boolean loadTerm(int groupIndex) { Taxonomy taxonomy = taxonomies[groupIndex]; if (taxonomy.getLabel() == null) { return false; } int blogId = WordPress.getCurrentBlog().getId(); this.terms.remove(taxonomy.getId()); HierarchicalTerm[] hieralcialTerms = WordPress.wpDB .getHierarchialTerm(blogId, taxonomy.getName()); this.terms.put(taxonomy.getId(), hieralcialTerms); ArrayList<Boolean> childChecked = this.checked.get(groupIndex); for (int i = 0; i < hieralcialTerms.length; i++) { childChecked.add(false); } notifyDataSetChanged(); return true; } @Override public int getGroupCount() { return taxonomies.length; } @Override public int getChildrenCount(int groupPosition) { final long id = taxonomies[groupPosition].getId(); HierarchicalTerm[] term = terms.get(id); if (term == null) { return 0; } else { return terms.get(id).length; } } @Override public Object getGroup(int groupPosition) { return taxonomies[groupPosition]; } @Override public Object getChild(int groupPosition, int childPosition) { final long id = taxonomies[groupPosition].getId(); return terms.get(id)[childPosition]; } @Override public long getGroupId(int groupPosition) { return taxonomies[groupPosition].getId(); } @Override public long getChildId(int groupPosition, int childPosition) { final String id = ((HierarchicalTerm) getChild(groupPosition, childPosition)).getTerm().getTermId(); return Long.parseLong(id); } @Override public boolean hasStableIds() { return false; } @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { if (convertView == null) { LayoutInflater inflater = LayoutInflater.from(this.activity); convertView = inflater.inflate(R.layout.categories_title_row, null); } TextView tv = (TextView) convertView; tv.setText(((Taxonomy) getGroup(groupPosition)).getLabel()); return tv; } @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { LayoutInflater inflater = LayoutInflater.from(this.activity); convertView = inflater.inflate(R.layout.categories_row, null); CheckedTextView textView = (CheckedTextView) convertView .findViewById(R.id.categoryRowText); ImageView levelIndicatorView = (ImageView) convertView .findViewById(R.id.categoryRowLevelIndicator); HierarchicalTerm term = (HierarchicalTerm) getChild(groupPosition, childPosition); textView.setText(term.getTerm().getName()); int level = term.getHierarchy() + 1; if (level == 1) { // hide ImageView levelIndicatorView.setVisibility(View.GONE); } else { ViewGroup.LayoutParams params = levelIndicatorView .getLayoutParams(); params.width = (params.width / 2) * level; levelIndicatorView.setLayoutParams(params); } boolean isChecked = checked.get(groupPosition).get(childPosition); textView.setChecked(isChecked); Debug.logd("c", "g" + groupPosition + " c" + childPosition + " che" + isChecked); return convertView; } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } } }