mobisocial.musubi.ui.FeedIdentityGrid.java Source code

Java tutorial

Introduction

Here is the source code for mobisocial.musubi.ui.FeedIdentityGrid.java

Source

/*
 * Copyright 2012 The Stanford MobiSocial Laboratory
 *
 * 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 mobisocial.musubi.ui;

import gnu.trove.list.array.TLongArrayList;

import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

import mobisocial.musubi.App;
import mobisocial.musubi.R;
import mobisocial.musubi.model.MFeed;
import mobisocial.musubi.model.MIdentity;
import mobisocial.musubi.model.helpers.FeedManager;
import mobisocial.musubi.model.helpers.IdentitiesManager;
import mobisocial.musubi.provider.MusubiContentProvider;
import mobisocial.musubi.provider.MusubiContentProvider.Provided;
import mobisocial.musubi.ui.util.UiUtil;
import mobisocial.musubi.ui.widget.MultiIdentitySelector;
import mobisocial.musubi.ui.widget.MultiIdentitySelector.OnIdentitiesUpdatedListener;
import mobisocial.musubi.ui.widget.MultiIdentitySelector.OnRequestAddIdentityListener;
import mobisocial.musubi.util.SimpleCursorLoader;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RecentTaskInfo;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Intents.Insert;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CursorAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

public class FeedIdentityGrid extends MusubiBaseActivity implements LoaderManager.LoaderCallbacks<Cursor> {
    static final int LOAD_FEEDS = 0;

    private static final int REQUEST_ADD_CONTACT = 1;

    MultiIdentitySelector mIdentitySelector;
    SQLiteOpenHelper mDatabaseSource;
    IdentitiesManager mIdentitiesManager;
    FeedManager mFeedManager;
    ListView mFeedListView;
    FeedMembersCursorAdapter mFeedAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //TODO: this begs for being in util, huh.  i wonder where else it is used.
        //check that we aren't going to send a message using the local authority
        //to our friends.  This is similar to the initial hidden state of the 
        //person picker on the feed list
        mDatabaseSource = App.getDatabaseSource(this);
        mIdentitiesManager = new IdentitiesManager(mDatabaseSource);
        mFeedManager = new FeedManager(mDatabaseSource);
        if (mIdentitiesManager.getOwnedIdentities().size() < 2) {
            Toast.makeText(this, "You must connect an account in Musubi to be able to share with your contacts",
                    Toast.LENGTH_SHORT).show();
            Intent intent = new Intent(this, FeedListActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            startActivity(intent);
            return;
        }

        setTitle("Share");
        RelativeLayout window = new RelativeLayout(this);
        LayoutParams fill = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
        window.setLayoutParams(fill);

        // Identity multi-select
        mIdentitySelector = new MultiIdentitySelector(this);
        mIdentitySelector.setOnIdentitiesUpdatedListener(mIdentitiesUpdatedListener);
        mIdentitySelector.setOnRequestAddIdentityListener(mOnRequestAddIdentityListener);
        RelativeLayout.LayoutParams selectorParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,
                LayoutParams.WRAP_CONTENT);
        selectorParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
        mIdentitySelector.setLayoutParams(selectorParams);
        mIdentitySelector.setId(R.id.people);

        // Feed list
        mFeedListView = new ListView(this);
        RelativeLayout.LayoutParams listParams = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,
                LayoutParams.FILL_PARENT);
        listParams.addRule(RelativeLayout.BELOW, R.id.people);
        listParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        mFeedListView.setLayoutParams(listParams);
        mFeedListView.setOnItemClickListener(mFeedClickListener);
        // Must be called before setAdapter():
        //mFeedListView.addHeaderView(mHeaderView);

        // Bind to content view
        window.addView(mIdentitySelector);
        window.addView(mFeedListView);
        setContentView(window, fill);

        getSupportLoaderManager().initLoader(LOAD_FEEDS, null, this);
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_ADD_CONTACT) {
            if (resultCode == Activity.RESULT_OK) {
                UiUtil.addedContact(this, data, mIdentitySelector);
            }
        }
    };

    private OnRequestAddIdentityListener mOnRequestAddIdentityListener = new OnRequestAddIdentityListener() {
        @Override
        public void onRequestAddIdentity(String enteredText) {
            Intent i = new Intent(Intent.ACTION_INSERT_OR_EDIT);
            i.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
            if (enteredText != null) {
                Pattern emailPattern = Pattern.compile("\\b[A-Z0-9._%-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}\\b",
                        Pattern.CASE_INSENSITIVE);
                if (emailPattern.matcher(enteredText).matches()) {
                    i.putExtra(Insert.EMAIL, enteredText);
                } else {
                    i.putExtra(Insert.NAME, enteredText);
                }
            }
            startActivityForResult(i, REQUEST_ADD_CONTACT);
        }
    };

    String getCallerAppId() {
        ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        List<RecentTaskInfo> infos = manager.getRecentTasks(1, 0);
        if (infos.size() == 0) {
            Log.w(TAG, "couldn't get info");
            return null;
        }

        Intent base = infos.get(0).baseIntent;
        return base.getComponent().getPackageName();
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        long[] ids;
        if (args == null) {
            ids = new long[0];
        } else {
            ids = args.getLongArray("ids");
        }
        switch (id) {
        case LOAD_FEEDS:
            return new FeedsWithMembersLoader(this, mFeedManager, ids);
        }
        return null;
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        if (mFeedAdapter == null) {
            mFeedAdapter = new FeedMembersCursorAdapter(this, data);
            mFeedListView.setAdapter(mFeedAdapter);
        } else {
            mFeedAdapter.changeCursor(data);
        }
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        mFeedAdapter.changeCursor(null);
    }

    OnIdentitiesUpdatedListener mIdentitiesUpdatedListener = new OnIdentitiesUpdatedListener() {
        public void onIdentitiesUpdated() {
            Set<MIdentity> idSet = mIdentitySelector.getSelectedIdentities();
            long[] ids = new long[idSet.size()];
            int i = 0;
            for (MIdentity id : idSet) {
                ids[i++] = id.id_;
            }
            Bundle args = new Bundle();
            args.putLongArray("ids", ids);
            getSupportLoaderManager().restartLoader(LOAD_FEEDS, args, FeedIdentityGrid.this);
        }
    };

    OnItemClickListener mFeedClickListener = new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            long feedId = (Long) view.getTag(R.id.feed_label);
            Uri feedUri = MusubiContentProvider.uriForItem(Provided.FEEDS, feedId);
            MFeed mfeed = new MFeed();
            mfeed.id_ = feedId;
            MIdentity[] list = mFeedManager.getFeedMembers(mfeed);
            String text = "bye";
            Toast.makeText(FeedIdentityGrid.this, text, Toast.LENGTH_SHORT).show();
            finish();
        }
    };

    public static class FeedsWithMembersLoader extends SimpleCursorLoader {
        final String[] mColumns = new String[] { MFeed.COL_ID, MFeed.COL_NUM_UNREAD, MFeed.COL_NAME,
                MFeed.COL_LATEST_RENDERABLE_OBJ_ID };
        final long[] mIdentityIds;
        final FeedManager mFeedManager;

        public FeedsWithMembersLoader(Context context, FeedManager feedManager, long[] idIds) {
            super(context);
            mIdentityIds = idIds;
            mFeedManager = feedManager;
        }

        @Override
        public Cursor loadInBackground() {
            if (mIdentityIds.length == 0) {
                return allFeedsCursor();
            }
            return identityFilteredCursor();
        }

        Cursor allFeedsCursor() {
            String selection = FeedManager.VISIBLE_FEED_SELECTION;
            String sortOrder = MFeed.COL_LATEST_RENDERABLE_OBJ_TIME + " desc";
            return getContext().getContentResolver().query(MusubiContentProvider.uriForDir(Provided.FEEDS),
                    mColumns, selection, null, sortOrder);
        }

        Cursor identityFilteredCursor() {
            assert (mIdentityIds.length > 0);
            long[] feedIds = mFeedManager.getFeedsForIdentityId(mIdentityIds[0]);
            for (int p = 1; p < mIdentityIds.length; p++) {
                long[] filter = mFeedManager.getFeedsForIdentityId(mIdentityIds[p]);
                int i = 0, j = 0;
                TLongArrayList survivors = new TLongArrayList(feedIds.length);
                while (i < feedIds.length && j < filter.length) {
                    if (feedIds[i] == filter[j]) {
                        survivors.add(feedIds[i]);
                        i++;
                        j++;
                    } else if (feedIds[i] > filter[j]) {
                        i++;
                    } else {
                        j++;
                    }
                }
                feedIds = new long[survivors.size()];
                survivors.toArray(feedIds);
                if (feedIds.length == 0) {
                    break;
                }
            }

            final MatrixCursor cursor = new MatrixCursor(mColumns, feedIds.length);
            for (long f : feedIds) {
                MFeed feed = mFeedManager.lookupFeed(f);
                Object[] values = new Object[mColumns.length];
                values[0] = feed.id_;
                values[1] = feed.numUnread_;
                values[2] = feed.name_;
                values[3] = feed.latestRenderableObjId_;
                cursor.addRow(values);
            }
            return cursor;
        }
    }

    public static class FeedMembersCursorAdapter extends CursorAdapter {
        private FeedManager mFeedManager;
        private final FeedIdentityGrid mContext;

        public FeedMembersCursorAdapter(FeedIdentityGrid context, Cursor c) {
            super(context, c);
            mContext = context;
            SQLiteOpenHelper helper = App.getDatabaseSource(context);
            mFeedManager = new FeedManager(helper);
        }

        @Override
        public View newView(Context context, Cursor c, ViewGroup parent) {
            LinearLayout membershipView = new LinearLayout(context);
            membershipView.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.FILL_PARENT,
                    AbsListView.LayoutParams.WRAP_CONTENT));

            TextView title = new TextView(context);
            title.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT));
            Gallery gallery = new Gallery(context);
            gallery.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT));
            gallery.setId(R.id.people);
            gallery.setGravity(Gravity.LEFT);
            gallery.setSpacing(4);
            gallery.setClickable(false);
            gallery.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
            hackGalleryInit(gallery);
            membershipView.addView(gallery);
            return membershipView;
        }

        void hackGalleryInit(Gallery gallery) {
            DisplayMetrics metrics = new DisplayMetrics();
            mContext.getWindowManager().getDefaultDisplay().getMetrics(metrics);
            MarginLayoutParams mlp = (MarginLayoutParams) gallery.getLayoutParams();
            mlp.setMargins(-(metrics.widthPixels / 2), mlp.topMargin, mlp.rightMargin, mlp.bottomMargin);
        }

        @Override
        public void bindView(final View v, final Context context, final Cursor c) {
            long feedId = c.getLong(c.getColumnIndexOrThrow(MFeed.COL_ID));

            v.setTag(R.id.feed_label, feedId);
            Gallery gallery = (Gallery) v.findViewById(R.id.people);
            Cursor members = mFeedManager.getKnownProfileFeedMembersCursor(c.getLong(0));
            gallery.setAdapter(new MembersCursorAdapter(context, members));

            /* TextView title = (TextView)v.findViewById(R.id.text);
             MFeed feed = new MFeed();
             feed.id_ = feedId;
             title.setText(UiUtil.getFeedNameFromMembersList(mFeedManager, feed));*/

        }
    }

    static class MembersCursorAdapter extends CursorAdapter {
        final IdentitiesManager idm;

        public MembersCursorAdapter(Context context, Cursor members) {
            super(context, members);
            idm = new IdentitiesManager(App.getDatabaseSource(context));
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            MIdentity identity = new MIdentity();
            identity.id_ = cursor.getLong(0);
            Bitmap cached = UiUtil.safeGetContactThumbnail(context, idm, identity);
            ((ImageView) view).setImageBitmap(cached);
        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            // TODO: Render nam under icon
            ImageView icon = new ImageView(context);
            int DP = (int) context.getResources().getDisplayMetrics().density * 75;
            icon.setLayoutParams(new Gallery.LayoutParams(DP, DP));
            icon.setPadding(8, 8, 8, 8);
            return icon;
        }
    }
}