UI Android

/**
 * Copyright (C) 2010 Christian Meyer
 * This file is part of Drupal Editor.
 *
 * Drupal Editor 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 2 of the License, or
 * (at your option) any later version.
 *
 * Drupal Editor 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 Drupal Editor. If not, see .
 */
//package ch.dissem.android.utils;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
/**
 * {@link BaseAdapter}-Implementation for the {@link MultiChoice} Dialog.
 * 
 * @author christian
 * @param 
 *            Type this Adapter contains. Should have some useful toString()
 *            implementation.
 */
 class MultiChoiceListAdapter extends BaseAdapter {
  private Context ctx;
  private Collection options;
  private Collection selection;
  private List filteredOptions;
  public MultiChoiceListAdapter(Context context, Collection options,
      Collection selection) {
    this.ctx = context;
    this.options = options;
    this.selection = selection;
    this.filteredOptions = new ArrayList(options.size());
    setFilter(null);
  }
  @Override
  public int getCount() {
    return filteredOptions.size();
  }
  @Override
  public T getItem(int position) {
    return filteredOptions.get(position);
  }
  @Override
  public long getItemId(int position) {
    return position;
  }
  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    ChoiceView view;
    T item = getItem(position);
    boolean selected = selection.contains(item);
    if (convertView == null) {
      view = new ChoiceView(ctx, item, selected);
    } else {
      view = (ChoiceView) convertView;
      view.setItem(item, selected);
    }
    return view;
  }
  public void setFilter(String filter) {
    if (filter != null)
      filter = filter.toLowerCase();
    filteredOptions.clear();
    for (T item : selection)
      filteredOptions.add(item);
    for (T item : options)
      if (!selection.contains(item)
          && (filter == null || item.toString().toLowerCase()
              .contains(filter)))
        filteredOptions.add(item);
  }
  public class ChoiceView extends CheckBox implements OnCheckedChangeListener {
    private T object;
    public ChoiceView(Context context, T object, Boolean selected) {
      super(context);
      this.object = object;
      setOnCheckedChangeListener(this);
      setItem(object, selected);
    }
    @Override
    public void onCheckedChanged(CompoundButton buttonView,
        boolean isChecked) {
      if (selection != null) {
        if (isChecked && !selection.contains(object))
          selection.add(object);
        else if (!isChecked)
          selection.remove(object);
      }
      notifyDataSetChanged();
    }
    public void setItem(T object, Boolean selected) {
      this.object = object;
      setChecked(selected);
      setText(object.toString());
    }
  }
}
/**
 * A dialog that allows the user to select multiple entries.
 * 
 * @author christian
 * @param 
 *            Type for this dialog. Should have some useful toString()
 *            implementation.
 */
 class MultiChoice extends Dialog {
  private ListView listView;
  private Map optionsWithSelection;
  private Collection options;
  private Collection selection;
  public MultiChoice(Context context, Collection options,
      Collection selection) {
    super(context);
    this.options = options;
    this.selection = selection;
  }
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Context ctx = getContext();
    LinearLayout layout = new LinearLayout(ctx);
    layout.setOrientation(LinearLayout.VERTICAL);
    listView = new ListView(ctx);
    final MultiChoiceListAdapter adapter;
    adapter = new MultiChoiceListAdapter(ctx, options, selection);
    listView.setAdapter(adapter);
    if (options.size() > 10) {
      EditText search = new EditText(ctx);
      search.setInputType(InputType.TYPE_TEXT_VARIATION_FILTER);
      search.addTextChangedListener(new TextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start,
            int before, int count) {
          adapter.setFilter(s.toString());
          adapter.notifyDataSetChanged();
        }
        @Override
        public void beforeTextChanged(CharSequence s, int start,
            int count, int after) {
        }
        @Override
        public void afterTextChanged(Editable s) {
        }
      });
      layout.addView(search);
    }
    layout.addView(listView);
    setContentView(layout);
  }
  public Map getOptionsMap() {
    return optionsWithSelection;
  }
  public Set getSelection() {
    Set result = new LinkedHashSet();
    for (Entry e : optionsWithSelection.entrySet())
      if (Boolean.TRUE.equals(e.getValue()))
        result.add(e.getKey());
    return result;
  }
}