package com.jbirdvegas.mgerrit.adapters; import android.content.Context; import android.database.Cursor; import android.view.ActionMode; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseExpandableListAdapter; import android.widget.TextView; import com.android.volley.RequestQueue; import com.android.volley.toolbox.Volley; import com.jbirdvegas.mgerrit.R; import com.jbirdvegas.mgerrit.cards.CardBinder; import com.jbirdvegas.mgerrit.cards.PatchSetChangesCard; import com.jbirdvegas.mgerrit.cards.PatchSetCommentsCard; import com.jbirdvegas.mgerrit.cards.PatchSetMessageCard; import com.jbirdvegas.mgerrit.cards.PatchSetPropertiesCard; import com.jbirdvegas.mgerrit.cards.PatchSetReviewersCard; import com.jbirdvegas.mgerrit.database.FileChanges; import com.jbirdvegas.mgerrit.objects.FilesCAB; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; /* * Copyright (C) 2014 Android Open Kang Project (AOKP) * Author: Evan Conway (P4R4N01D), 2014 * * 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. * * Base adapter for attaching data regarding change details to an * expandableListView. We want to use an array rather than a cursor * for the groups (headings), so we need to extend BaseExpandableListAdapter * rather than CursorTreeAdapter. */ public class CommitDetailsAdapter extends BaseExpandableListAdapter { private final LayoutInflater mInflator; private final Context mContext; // Contextual action bar handler instance so the adapter can close the CAB private FilesCAB mContextualAB; // Cards supported: public enum Cards { PROPERTIES, COMMIT_MSG, CHANGED_FILES, REVIEWERS, COMMENTS } private static final int _cards_count = Cards.values().length; // Stores the type of card at position private ArrayList<ChildGroupDetails> childGroupDetails = new ArrayList<>(); // Contents for added card list headers private ArrayList<String> headerContents = new ArrayList<>(5); public CommitDetailsAdapter(Context context) { mContext = context; mInflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); setup(); } @Nullable @Override public Object getGroup(int groupPosition) { return headerContents.get(groupPosition); } @Nullable @Override public Object getChild(int groupPosition, int childPosition) { ChildGroupDetails details = childGroupDetails.get(groupPosition); details.cursor.moveToPosition(childPosition); return details.cursor; } @Override public long getGroupId(int groupPosition) { return groupPosition; } @Override public long getChildId(int groupPosition, int childPosition) { return groupPosition*100 + childPosition; } @Override public boolean hasStableIds() { return false; } @Nullable @Override public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) { if (convertView == null) { convertView = mInflator.inflate(R.layout.card_header, parent, false); } GroupViewHolder viewHolder = (GroupViewHolder) convertView.getTag(); if (viewHolder == null) { viewHolder = new GroupViewHolder(convertView); convertView.setTag(viewHolder); } String text = headerContents.get(groupPosition); // Allow an empty header text if (text != null) { viewHolder.headerText.setText(text); } return convertView; } @Nullable @Override public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) { // Get the set binder and delegate the work to the set binder ChildGroupDetails details = childGroupDetails.get(groupPosition); Cursor cursor = (Cursor) getChild(groupPosition, childPosition); if (cursor == null) return convertView; if (cursor.getPosition() < 0) cursor.moveToFirst(); return details.binder.setViewValue(cursor, convertView, parent); } @Override public boolean isChildSelectable(int groupPosition, int childPosition) { return true; } @Override public int getGroupCount() { return headerContents.size(); } @Override public int getChildrenCount(int groupPosition) { ChildGroupDetails details = childGroupDetails.get(groupPosition); if (details.cursor != null) return details.cursor.getCount(); else return 0; } @Override public int getChildType(int groupPosition, int childPosition) { return groupPosition; } @Override public int getChildTypeCount() { return _cards_count; // Number of different cards supported (view layouts) } @Override public void onGroupCollapsed(int groupPosition) { /* Check if we collapsed the same group as the selected item and the selected item * was a child. */ ActionMode am = mContextualAB.getActionMode(); if (am != null) { FilesCAB.TagHolder holder = (FilesCAB.TagHolder) am.getTag(); if (holder.groupPosition == groupPosition && holder.isChild) { am.finish(); } } super.onGroupCollapsed(groupPosition); } /** * Card order: * Properties card, Message card, Changed files card, Code reviewers card, Comments Card */ public void setup() { headerContents.add(mContext.getString(R.string.header_properties)); headerContents.add(mContext.getString(R.string.header_commit_message)); headerContents.add(mContext.getString(R.string.header_changed_files)); headerContents.add(mContext.getString(R.string.header_reviewers)); headerContents.add(mContext.getString(R.string.header_comments)); RequestQueue rq = Volley.newRequestQueue(mContext); childGroupDetails.add(new ChildGroupDetails(Cards.PROPERTIES, new PatchSetPropertiesCard(mContext, rq))); childGroupDetails.add(new ChildGroupDetails(Cards.COMMIT_MSG, new PatchSetMessageCard(mContext))); childGroupDetails.add(new ChildGroupDetails(Cards.CHANGED_FILES, new PatchSetChangesCard(mContext))); childGroupDetails.add(new ChildGroupDetails(Cards.REVIEWERS, new PatchSetReviewersCard(mContext, rq))); childGroupDetails.add(new ChildGroupDetails(Cards.COMMENTS, new PatchSetCommentsCard(mContext, rq))); } public void setCursor(Cards cardType, Cursor cursor) { childGroupDetails.get(cardType.ordinal()).setCursor(cursor); } public boolean isLongClickSupported(int groupPosition, int childPosition) { // Only changed files cards are supported if (groupPosition != Cards.CHANGED_FILES.ordinal()) { return false; } else if (childPosition < 0) { return true; // Always allow group headers } else { Cursor data = (Cursor) getChild(groupPosition, childPosition); boolean isBinary = data.getInt(data.getColumnIndex(FileChanges.C_ISBINARY)) == 1; boolean isImage = data.getInt(data.getColumnIndex(FileChanges.C_ISIMAGE)) == 1; return !isBinary || (isBinary && isImage); } } public void setContextualActionBar(FilesCAB cab) { this.mContextualAB = cab; } private static class GroupViewHolder { TextView headerText; private GroupViewHolder(View view) { headerText = (TextView) view.findViewById(R.id.header); } } private class ChildGroupDetails { final Cards cardType; Cursor cursor; final CardBinder binder; // handles inflating the layout and binding data from the cursor private ChildGroupDetails(Cards cardType, CardBinder binder) { this.cardType = cardType; this.binder = binder; } public void setCursor(Cursor cursor) { this.cursor = cursor; notifyDataSetChanged(); } } }