You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tasks/astrid/plugin-src/com/todoroo/astrid/tags/TagsControlSet.java

279 lines
9.2 KiB
Java

package com.todoroo.astrid.tags;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import android.app.Activity;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import com.timsu.astrid.R;
import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.data.Metadata;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.tags.TagService.Tag;
import com.todoroo.astrid.ui.PopupControlSet;
import com.todoroo.astrid.utility.Flags;
/**
* Control set to manage adding and removing tags
*
* @author Tim Su <tim@todoroo.com>
*
*/
public final class TagsControlSet extends PopupControlSet {
// --- instance variables
//private final Spinner tagSpinner;
//@Autowired private TagDataService tagDataService;
private final TagService tagService = TagService.getInstance();
private final ArrayList<String> allTagNames;
private final LinearLayout newTags;
private final ListView selectedTags;
private boolean populated = false;
private final HashMap<String, Integer> tagIndices;
//private final LinearLayout tagsContainer;
private final Activity activity;
private final TextView tagsDisplay;
public TagsControlSet(Activity activity, int viewLayout, int displayViewLayout, int title) {
super(activity, viewLayout, displayViewLayout, title);
DependencyInjectionService.getInstance().inject(this);
this.activity = activity;
Tag[] allTags = getTagArray();
allTagNames = getTagNames(allTags);
tagIndices = buildTagIndices(allTagNames);
selectedTags = (ListView) getView().findViewById(R.id.existingTags);
selectedTags.setAdapter(new ArrayAdapter<String>(activity,
R.layout.simple_list_item_multiple_choice_themed, allTagNames));
selectedTags.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
this.newTags = (LinearLayout) getView().findViewById(R.id.newTags);
tagsDisplay = (TextView) getDisplayView().findViewById(R.id.tags_display);
}
private Tag[] getTagArray() {
ArrayList<Tag> tagsList = TagService.getInstance().getTagList();
return tagsList.toArray(new Tag[tagsList.size()]);
}
private HashMap<String, Integer> buildTagIndices(ArrayList<String> tagNames) {
HashMap<String, Integer> indices = new HashMap<String, Integer>();
for (int i = 0; i < tagNames.size(); i++) {
indices.put(tagNames.get(i), i);
}
return indices;
}
private ArrayList<String> getTagNames(Tag[] tags) {
ArrayList<String> names = new ArrayList<String>();
for (int i = 0; i < tags.length; i++) {
names.add(tags[i].toString());
}
return names;
}
private String buildTagString() {
StringBuilder builder = new StringBuilder();
LinkedHashSet<String> tags = getTagSet();
for (String tag : tags) {
if (builder.length() != 0)
builder.append(", "); //$NON-NLS-1$
builder.append(tag);
}
if (builder.length() == 0)
builder.append(activity.getString(R.string.TEA_tags_none));
return builder.toString();
}
private void setTagSelected(String tag) {
Integer index = tagIndices.get(tag);
if (index != null) {
selectedTags.setItemChecked(index, true);
} else {
allTagNames.add(tag);
tagIndices.put(tag, allTagNames.size() - 1);
((ArrayAdapter<String>)selectedTags.getAdapter()).notifyDataSetChanged();
}
}
private LinkedHashSet<String> getTagSet() {
LinkedHashSet<String> tags = new LinkedHashSet<String>();
for(int i = 0; i < selectedTags.getAdapter().getCount(); i++) {
if (selectedTags.isItemChecked(i))
tags.add(allTagNames.get(i));
}
for(int i = 0; i < newTags.getChildCount(); i++) {
TextView tagName = (TextView) newTags.getChildAt(i).findViewById(R.id.text1);
if(tagName.getText().length() == 0)
continue;
tags.add(tagName.getText().toString());
}
return tags;
}
/** Adds a tag to the tag field */
boolean addTag(String tagName, boolean reuse) {
LayoutInflater inflater = activity.getLayoutInflater();
// check if already exists
TextView lastText = null;
for(int i = 0; i < newTags.getChildCount(); i++) {
View view = newTags.getChildAt(i);
lastText = (TextView) view.findViewById(R.id.text1);
if(lastText.getText().equals(tagName))
return false;
}
final View tagItem;
if(reuse && lastText != null && lastText.getText().length() == 0) {
tagItem = (View) lastText.getParent();
} else {
tagItem = inflater.inflate(R.layout.tag_edit_row, null);
newTags.addView(tagItem);
}
if(tagName == null)
tagName = ""; //$NON-NLS-1$
final AutoCompleteTextView textView = (AutoCompleteTextView)tagItem.
findViewById(R.id.text1);
textView.setText(tagName);
textView.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
//
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
//
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if(count > 0 && newTags.getChildAt(newTags.getChildCount()-1) ==
tagItem)
addTag("", false); //$NON-NLS-1$
}
});
textView.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView arg0, int actionId, KeyEvent arg2) {
if(actionId != EditorInfo.IME_NULL)
return false;
if(getLastTextView().getText().length() != 0) {
addTag("", false); //$NON-NLS-1$
}
return true;
}
});
ImageButton reminderRemoveButton;
reminderRemoveButton = (ImageButton)tagItem.findViewById(R.id.button1);
reminderRemoveButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
TextView lastView = getLastTextView();
if(lastView == textView && textView.getText().length() == 0)
return;
if(newTags.getChildCount() > 1)
newTags.removeView(tagItem);
else
textView.setText(""); //$NON-NLS-1$
}
});
return true;
}
/**
* Get tags container last text view. might be null
* @return
*/
private TextView getLastTextView() {
if(newTags.getChildCount() == 0)
return null;
View lastItem = newTags.getChildAt(newTags.getChildCount()-1);
TextView lastText = (TextView) lastItem.findViewById(R.id.text1);
return lastText;
}
@Override
public void readFromTask(Task task) {
newTags.removeAllViews();
if(task.getId() != AbstractModel.NO_ID) {
TodorooCursor<Metadata> cursor = tagService.getTags(task.getId());
HashSet<String> tags = new HashSet<String>(cursor.getCount());
try {
for(cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
String tag = cursor.get(TagService.TAG);
setTagSelected(tag);
tags.add(tag);
}
} finally {
cursor.close();
}
task.putTransitory("tags", tags); //$NON-NLS-1$
}
addTag("", false); //$NON-NLS-1$
refreshDisplayView();
populated = true;
}
@Override
public String writeToModel(Task task) {
// this is a case where we're asked to save but the UI was not yet populated
if(!populated)
return null;
LinkedHashSet<String> tags = getTagSet();
if(TagService.getInstance().synchronizeTags(task.getId(), tags)) {
Flags.set(Flags.TAGS_CHANGED);
task.setValue(Task.MODIFICATION_DATE, DateUtilities.now());
}
return null;
}
@Override
protected void refreshDisplayView() {
tagsDisplay.setText(buildTagString());
}
public boolean hasLists() {
LinkedHashSet<String> tags = getTagSet();
return !tags.isEmpty();
}
}