content: /*
   * Copyright (C) 2006 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package android.widget;
  
  import android.annotation.UnsupportedAppUsage;
  import android.database.DataSetObserver;
  import android.view.View;
  import android.view.ViewGroup;
  
  import java.util.ArrayList;
  
  /**
   * ListAdapter used when a ListView has header views. This ListAdapter
   * wraps another one and also keeps track of the header views and their
   * associated data objects.
   *<p>This is intended as a base class; you will probably not need to
   * use this class directly in your own code.
   */
  public class HeaderViewListAdapter implements WrapperListAdapter, Filterable {
  
      @UnsupportedAppUsage
      private final ListAdapter mAdapter;
  
      // These two ArrayList are assumed to NOT be null.
      // They are indeed created when declared in ListView and then shared.
      @UnsupportedAppUsage
      ArrayList<ListView.FixedViewInfo> mHeaderViewInfos;
      @UnsupportedAppUsage
      ArrayList<ListView.FixedViewInfo> mFooterViewInfos;
  
      // Used as a placeholder in case the provided info views are indeed null.
      // Currently only used by some CTS tests, which may be removed.
      static final ArrayList<ListView.FixedViewInfo> EMPTY_INFO_LIST =
          new ArrayList<ListView.FixedViewInfo>();
  
      boolean mAreAllFixedViewsSelectable;
  
      private final boolean mIsFilterable;
  
      public HeaderViewListAdapter(ArrayList<ListView.FixedViewInfo> headerViewInfos,
                                   ArrayList<ListView.FixedViewInfo> footerViewInfos,
                                   ListAdapter adapter) {
          mAdapter = adapter;
          mIsFilterable = adapter instanceof Filterable;
  
          if (headerViewInfos == null) {
              mHeaderViewInfos = EMPTY_INFO_LIST;
          } else {
              mHeaderViewInfos = headerViewInfos;
          }
  
          if (footerViewInfos == null) {
              mFooterViewInfos = EMPTY_INFO_LIST;
          } else {
              mFooterViewInfos = footerViewInfos;
          }
  
          mAreAllFixedViewsSelectable =
                  areAllListInfosSelectable(mHeaderViewInfos)
                  && areAllListInfosSelectable(mFooterViewInfos);
      }
  
      public int getHeadersCount() {
          return mHeaderViewInfos.size();
      }
  
      public int getFootersCount() {
          return mFooterViewInfos.size();
      }
  
      public boolean isEmpty() {
          return mAdapter == null || mAdapter.isEmpty();
      }
  
      private boolean areAllListInfosSelectable(ArrayList<ListView.FixedViewInfo> infos) {
          if (infos != null) {
              for (ListView.FixedViewInfo info : infos) {
                  if (!info.isSelectable) {
                      return false;
                  }
              }
          }
          return true;
      }
  
      public boolean removeHeader(View v) {
          for (int i = 0; i < mHeaderViewInfos.size(); i++) {
              ListView.FixedViewInfo info = mHeaderViewInfos.get(i);
              if (info.view == v) {
                  mHeaderViewInfos.remove(i);
  
                  mAreAllFixedViewsSelectable =
                          areAllListInfosSelectable(mHeaderViewInfos)
                          && areAllListInfosSelectable(mFooterViewInfos);
  
                  return true;
              }
          }
  
          return false;
      }
  
      public boolean removeFooter(View v) {
          for (int i = 0; i < mFooterViewInfos.size(); i++) {
              ListView.FixedViewInfo info = mFooterViewInfos.get(i);
              if (info.view == v) {
                  mFooterViewInfos.remove(i);
  
                  mAreAllFixedViewsSelectable =
                          areAllListInfosSelectable(mHeaderViewInfos)
                          && areAllListInfosSelectable(mFooterViewInfos);
  
                  return true;
              }
          }
  
          return false;
      }
  
      public int getCount() {
          if (mAdapter != null) {
              return getFootersCount() + getHeadersCount() + mAdapter.getCount();
          } else {
              return getFootersCount() + getHeadersCount();
          }
      }
  
      public boolean areAllItemsEnabled() {
          if (mAdapter != null) {
              return mAreAllFixedViewsSelectable && mAdapter.areAllItemsEnabled();
          } else {
              return true;
          }
      }
  
      public boolean isEnabled(int position) {
          // Header (negative positions will throw an IndexOutOfBoundsException)
          int numHeaders = getHeadersCount();
          if (position < numHeaders) {
              return mHeaderViewInfos.get(position).isSelectable;
          }
  
          // Adapter
          final int adjPosition = position - numHeaders;
          int adapterCount = 0;
          if (mAdapter != null) {
              adapterCount = mAdapter.getCount();
              if (adjPosition < adapterCount) {
                  return mAdapter.isEnabled(adjPosition);
              }
          }
  
          // Footer (off-limits positions will throw an IndexOutOfBoundsException)
          return mFooterViewInfos.get(adjPosition - adapterCount).isSelectable;
      }
  
      public Object getItem(int position) {
          // Header (negative positions will throw an IndexOutOfBoundsException)
          int numHeaders = getHeadersCount();
          if (position < numHeaders) {
              return mHeaderViewInfos.get(position).data;
          }
  
          // Adapter
          final int adjPosition = position - numHeaders;
          int adapterCount = 0;
          if (mAdapter != null) {
              adapterCount = mAdapter.getCount();
              if (adjPosition < adapterCount) {
                  return mAdapter.getItem(adjPosition);
              }
          }
  
          // Footer (off-limits positions will throw an IndexOutOfBoundsException)
          return mFooterViewInfos.get(adjPosition - adapterCount).data;
      }
  
      public long getItemId(int position) {
          int numHeaders = getHeadersCount();
          if (mAdapter != null && position >= numHeaders) {
              int adjPosition = position - numHeaders;
              int adapterCount = mAdapter.getCount();
              if (adjPosition < adapterCount) {
                  return mAdapter.getItemId(adjPosition);
              }
          }
          return -1;
      }
  
      public boolean hasStableIds() {
          if (mAdapter != null) {
              return mAdapter.hasStableIds();
          }
          return false;
      }
  
      public View getView(int position, View convertView, ViewGroup parent) {
          // Header (negative positions will throw an IndexOutOfBoundsException)
          int numHeaders = getHeadersCount();
          if (position < numHeaders) {
              return mHeaderViewInfos.get(position).view;
          }
  
          // Adapter
          final int adjPosition = position - numHeaders;
          int adapterCount = 0;
          if (mAdapter != null) {
              adapterCount = mAdapter.getCount();
              if (adjPosition < adapterCount) {
                  return mAdapter.getView(adjPosition, convertView, parent);
              }
          }
  
          // Footer (off-limits positions will throw an IndexOutOfBoundsException)
          return mFooterViewInfos.get(adjPosition - adapterCount).view;
      }
  
      public int getItemViewType(int position) {
          int numHeaders = getHeadersCount();
          if (mAdapter != null && position >= numHeaders) {
              int adjPosition = position - numHeaders;
              int adapterCount = mAdapter.getCount();
              if (adjPosition < adapterCount) {
                  return mAdapter.getItemViewType(adjPosition);
              }
          }
  
          return AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
      }
  
      public int getViewTypeCount() {
          if (mAdapter != null) {
              return mAdapter.getViewTypeCount();
          }
          return 1;
      }
  
      public void registerDataSetObserver(DataSetObserver observer) {
          if (mAdapter != null) {
              mAdapter.registerDataSetObserver(observer);
          }
      }
  
      public void unregisterDataSetObserver(DataSetObserver observer) {
          if (mAdapter != null) {
              mAdapter.unregisterDataSetObserver(observer);
          }
      }
  
      public Filter getFilter() {
          if (mIsFilterable) {
              return ((Filterable) mAdapter).getFilter();
          }
          return null;
      }
      
      public ListAdapter getWrappedAdapter() {
          return mAdapter;
      }
  }
  