com.iskrembilen.quasseldroid.gui.fragments.BufferFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.iskrembilen.quasseldroid.gui.fragments.BufferFragment.java

Source

/*
QuasselDroid - Quassel client for Android
Copyright (C) 2011 Ken Brge Viktil
Copyright (C) 2011 Magnus Fjell
Copyright (C) 2011 Martin Sandsmark <martin.sandsmark@kde.org>
    
This program 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 3 of the License, or (at your option)
any later version, or under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
    
This program 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 and the
GNU Lesser General Public License along with this program.  If not, see
<http://www.gnu.org/licenses/>.
 */

package com.iskrembilen.quasseldroid.gui.fragments;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ExpandableListActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ResultReceiver;
import android.preference.PreferenceManager;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.util.TypedValue;
import com.actionbarsherlock.view.ActionMode;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.BaseExpandableListAdapter;
import android.widget.EditText;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ExpandableListView.OnGroupCollapseListener;
import android.widget.ExpandableListView.OnGroupExpandListener;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.actionbarsherlock.app.SherlockFragment;
import com.iskrembilen.quasseldroid.Buffer;
import com.iskrembilen.quasseldroid.BufferInfo;
import com.iskrembilen.quasseldroid.BufferUtils;
import com.iskrembilen.quasseldroid.Network;
import com.iskrembilen.quasseldroid.NetworkCollection;
import com.iskrembilen.quasseldroid.R;
import com.iskrembilen.quasseldroid.events.ConnectionChangedEvent;
import com.iskrembilen.quasseldroid.events.ConnectionChangedEvent.Status;
import com.iskrembilen.quasseldroid.events.BufferListFontSizeChangedEvent;
import com.iskrembilen.quasseldroid.events.BufferOpenedEvent;
import com.iskrembilen.quasseldroid.events.ManageChannelEvent;
import com.iskrembilen.quasseldroid.events.InitProgressEvent;
import com.iskrembilen.quasseldroid.events.JoinChannelEvent;
import com.iskrembilen.quasseldroid.events.LatencyChangedEvent;
import com.iskrembilen.quasseldroid.events.ManageChannelEvent.ChannelAction;
import com.iskrembilen.quasseldroid.events.ManageNetworkEvent.NetworkAction;
import com.iskrembilen.quasseldroid.events.ManageNetworkEvent;
import com.iskrembilen.quasseldroid.events.NetworksAvailableEvent;
import com.iskrembilen.quasseldroid.events.SendMessageEvent;
import com.iskrembilen.quasseldroid.gui.MainActivity;
import com.iskrembilen.quasseldroid.gui.LoginActivity;
import com.iskrembilen.quasseldroid.gui.PreferenceView;
import com.iskrembilen.quasseldroid.service.CoreConnService;
import com.iskrembilen.quasseldroid.util.BufferHelper;
import com.iskrembilen.quasseldroid.util.BusProvider;
import com.iskrembilen.quasseldroid.util.Helper;
import com.iskrembilen.quasseldroid.util.ThemeUtil;
import com.squareup.otto.Bus;
import com.squareup.otto.Produce;
import com.squareup.otto.Subscribe;

import java.util.List;
import java.util.Observable;
import java.util.Observer;

public class BufferFragment extends SherlockFragment
        implements OnGroupExpandListener, OnChildClickListener, OnGroupCollapseListener {

    private static final String TAG = BufferFragment.class.getSimpleName();

    public static final String BUFFER_ID_EXTRA = "bufferid";
    public static final String BUFFER_NAME_EXTRA = "buffername";

    private static final String ITEM_POSITION_KEY = "itempos";

    private static final String LIST_POSITION_KEY = "listpos";

    BufferListAdapter bufferListAdapter;
    ExpandableListView bufferList;

    SharedPreferences preferences;
    OnSharedPreferenceChangeListener sharedPreferenceChangeListener;

    private int restoreListPosition = 0;
    private int restoreItemPosition = 0;

    private ActionModeData actionModeData = new ActionModeData();

    private int offlineColor;

    private int openedBufferId = -1;

    public static BufferFragment newInstance() {
        return new BufferFragment();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState != null) {
            restoreListPosition = savedInstanceState.getInt(LIST_POSITION_KEY);
            restoreItemPosition = savedInstanceState.getInt(ITEM_POSITION_KEY);
        }
        setHasOptionsMenu(true);
        offlineColor = getResources().getColor(R.color.buffer_offline_color);
        preferences = PreferenceManager.getDefaultSharedPreferences(getSherlockActivity());
        sharedPreferenceChangeListener = new OnSharedPreferenceChangeListener() {

            @Override
            public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
                if (key.equals(getResources().getString(R.string.preference_fontsize_channel_list))) {
                    bufferListAdapter.notifyDataSetChanged();
                }
            }
        };
        preferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener); //To avoid GC issues
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View root = inflater.inflate(R.layout.buffer_list_fragment_layout, container, false);
        bufferList = (ExpandableListView) root.findViewById(R.id.buffer_list);
        return root;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        bufferListAdapter = new BufferListAdapter(getSherlockActivity());
        bufferList.setAdapter(bufferListAdapter);
        bufferList.setDividerHeight(0);
        bufferList.setOnChildClickListener(this);
        bufferList.setOnGroupCollapseListener(this);
        bufferList.setOnGroupExpandListener(this);

        initActionMenu();

    }

    private void initActionMenu() {
        actionModeData.actionModeCallbackNetwork = new ActionMode.Callback() {

            @Override
            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                MenuInflater inflater = mode.getMenuInflater();
                inflater.inflate(R.menu.buffer_contextual_menu_networks, menu);
                return true;
            }

            @Override
            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                return false;
            }

            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                switch (item.getItemId()) {
                case R.id.context_menu_connect:
                    BufferHelper.connectNetwork(actionModeData.id);
                    mode.finish();
                    return true;
                case R.id.context_menu_disconnect:
                    BufferHelper.disconnectNetwork(actionModeData.id);
                    mode.finish();
                    return true;
                default:
                    return false;
                }
            }

            @Override
            public void onDestroyActionMode(ActionMode mode) {
                //            actionModeData.listItem.setActivated(false);
                actionModeData.actionMode = null;

            }

        };
        actionModeData.actionModeCallbackBuffer = new ActionMode.Callback() {

            @Override
            public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                MenuInflater inflater = mode.getMenuInflater();
                inflater.inflate(R.menu.buffer_contextual_menu_channels, menu);
                return true;
            }

            @Override
            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                return false; // Return false if nothing is done
            }

            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                switch (item.getItemId()) {
                case R.id.context_menu_join:
                    BufferHelper.joinChannel(actionModeData.id, bufferListAdapter.networks);
                    mode.finish();
                    return true;
                case R.id.context_menu_part:
                    BufferHelper.partChannel(actionModeData.id, bufferListAdapter.networks);
                    mode.finish();
                    return true;
                case R.id.context_menu_delete:
                    BufferHelper.showDeleteConfirmDialog(getSherlockActivity(), actionModeData.id);
                    mode.finish();
                    return true;
                case R.id.context_menu_hide_temp:
                    BufferHelper.tempHideChannel(actionModeData.id);
                    mode.finish();
                    return true;
                case R.id.context_menu_hide_perm:
                    BufferHelper.permHideChannel(actionModeData.id);
                    mode.finish();
                    return true;
                default:
                    return false;
                }
            }

            // Called when the user exits the action mode
            @Override
            public void onDestroyActionMode(ActionMode mode) {
                //            actionModeData.listItem.setActivated(false);
                actionModeData.actionMode = null;
            }
        };

        bufferList.setOnItemLongClickListener(new OnItemLongClickListener() {

            @Override
            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                long packedPosition = bufferList.getExpandableListPosition(position);
                int groupPosition = ExpandableListView.getPackedPositionGroup(packedPosition);
                int childPosition = ExpandableListView.getPackedPositionChild(packedPosition);

                if (ExpandableListView
                        .getPackedPositionType(packedPosition) == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
                    Buffer buffer = bufferListAdapter.getChild(groupPosition, childPosition);
                    actionModeData.actionMode = getSherlockActivity()
                            .startActionMode(actionModeData.actionModeCallbackBuffer);
                    actionModeData.id = buffer.getInfo().id;
                    actionModeData.listItem = view;
                    if (buffer.getInfo().type == BufferInfo.Type.QueryBuffer) {
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_part).setVisible(false);
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_delete).setVisible(true);
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_join).setVisible(false);
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_hide_temp).setVisible(true);
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_hide_perm).setVisible(true);
                    } else if (buffer.isActive()) {
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_part).setVisible(true);
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_join).setVisible(false);
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_delete).setVisible(false);
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_hide_temp).setVisible(true);
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_hide_perm).setVisible(true);
                    } else {
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_part).setVisible(false);
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_delete).setVisible(true);
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_join).setVisible(true);
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_hide_temp).setVisible(true);
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_hide_perm).setVisible(true);
                    }
                } else if (ExpandableListView
                        .getPackedPositionType(packedPosition) == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
                    Network network = bufferListAdapter.getGroup(groupPosition);
                    actionModeData.actionMode = getSherlockActivity()
                            .startActionMode(actionModeData.actionModeCallbackNetwork);
                    actionModeData.id = network.getId();
                    actionModeData.listItem = view;
                    if (network.isConnected()) {
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_disconnect).setVisible(true);
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_connect).setVisible(false);
                    } else {
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_disconnect)
                                .setVisible(false);
                        actionModeData.actionMode.getMenu().findItem(R.id.context_menu_connect).setVisible(true);
                    }
                }
                return true;
            }
        });
    }

    @Override
    public void onStart() {
        super.onStart();
        BusProvider.getInstance().register(this);
    }

    @Override
    public void onStop() {
        super.onStop();
        BusProvider.getInstance().unregister(this);
    }

    @Override
    public void onDestroy() {
        preferences.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
        super.onDestroy();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        // Save position of first visible item
        restoreListPosition = bufferList.getFirstVisiblePosition();
        outState.putInt(LIST_POSITION_KEY, restoreListPosition);

        // Save scroll position of item
        View itemView = bufferList.getChildAt(0);
        restoreItemPosition = itemView == null ? 0 : itemView.getTop();
        outState.putInt(ITEM_POSITION_KEY, restoreItemPosition);

    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.buffer_list_fragment_menu, menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.menu_join_channel:
            if (bufferListAdapter.networks == null)
                Toast.makeText(getSherlockActivity(), getString(R.string.not_available), Toast.LENGTH_SHORT).show();
            else
                showJoinChannelDialog();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    private void showJoinChannelDialog() {
        List<Network> networkList = bufferListAdapter.networks.getNetworkList();
        String[] networkArray = new String[networkList.size()];

        for (int i = 0; i < networkList.size(); i++) {
            networkArray[i] = networkList.get(i).getName();
        }

        FragmentTransaction ft = getFragmentManager().beginTransaction();
        Fragment prev = getFragmentManager().findFragmentByTag("dialog");
        if (prev != null) {
            ft.remove(prev);
        }
        ft.addToBackStack(null);

        // Create and show the dialog.
        DialogFragment newFragment = JoinChannelDialog.newInstance(networkArray);
        newFragment.show(ft, "dialog");
    }

    @Override
    public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
        openBuffer(bufferListAdapter.getChild(groupPosition, childPosition));
        return true;
    }

    @Override
    public void onGroupExpand(int groupPosition) {
        bufferListAdapter.getGroup(groupPosition).setOpen(true);
    }

    @Override
    public void onGroupCollapse(int groupPosition) {
        bufferListAdapter.getGroup(groupPosition).setOpen(false);
    }

    private void openBuffer(Buffer buffer) {
        this.openedBufferId = buffer.getInfo().id;
        BusProvider.getInstance().post(new BufferOpenedEvent(buffer.getInfo().id));
    }

    public class BufferListAdapter extends BaseExpandableListAdapter implements Observer {
        private NetworkCollection networks;
        private LayoutInflater inflater;
        private Bitmap channelActiveBitmap, channelInactiveBitmap, userAwayBitmap, userOfflineBitmap, userBitmap;

        public BufferListAdapter(Context context) {
            inflater = getLayoutInflater(null);
            channelActiveBitmap = BitmapFactory.decodeResource(context.getResources(),
                    R.drawable.irc_channel_active);
            channelInactiveBitmap = BitmapFactory.decodeResource(context.getResources(),
                    R.drawable.irc_channel_inactive);
            userAwayBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.im_user_away);
            userOfflineBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.im_user_offline);
            userAwayBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.im_user_away);
            userBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.im_user);

        }

        public void setNetworks(NetworkCollection networks) {
            this.networks = networks;
            if (networks == null)
                return;
            networks.addObserver(this);
            notifyDataSetChanged();
            if (bufferListAdapter != null) {
                for (int group = 0; group < getGroupCount(); group++) {
                    if (getGroup(group).isOpen())
                        bufferList.expandGroup(group);
                    else
                        bufferList.collapseGroup(group);
                }
                bufferList.setSelectionFromTop(restoreListPosition, restoreItemPosition);
            }
        }

        @Override
        public void notifyDataSetChanged() {
            super.notifyDataSetChanged();
        }

        @Override
        public void update(Observable observable, Object data) {
            notifyDataSetChanged();
            for (int group = 0; group < getGroupCount(); group++) {
                if (getGroup(group).isOpen())
                    bufferList.expandGroup(group);
                else
                    bufferList.collapseGroup(group);
            }
        }

        @Override
        public Buffer getChild(int groupPosition, int childPosition) {
            return networks.getNetwork(groupPosition).getBuffers().getPos(childPosition);
        }

        @Override
        public long getChildId(int groupPosition, int childPosition) {
            return networks.getNetwork(groupPosition).getBuffers().getPos(childPosition).getInfo().id;
        }

        @Override
        public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
                ViewGroup parent) {
            ViewHolderChild holder = null;
            if (convertView == null) {
                convertView = inflater.inflate(R.layout.buffer_child_item, null);
                holder = new ViewHolderChild();
                holder.bufferView = (TextView) convertView.findViewById(R.id.buffer_list_item_name);
                holder.bufferImage = (ImageView) convertView.findViewById(R.id.buffer_list_item_image);
                holder.bufferView.setTextSize(TypedValue.COMPLEX_UNIT_DIP,
                        Float.parseFloat(preferences.getString(getString(R.string.preference_fontsize_channel_list),
                                "" + holder.bufferView.getTextSize())));
                convertView.setTag(holder);
            } else {
                holder = (ViewHolderChild) convertView.getTag();
            }
            Buffer entry = getChild(groupPosition, childPosition);
            switch (entry.getInfo().type) {
            case StatusBuffer:
            case ChannelBuffer:
                holder.bufferView.setText(entry.getInfo().name);
                if (entry.isActive())
                    holder.bufferImage.setImageBitmap(channelActiveBitmap);
                else
                    holder.bufferImage.setImageBitmap(channelInactiveBitmap);
                break;
            case QueryBuffer:
                String nick = entry.getInfo().name;
                if (!bufferListAdapter.networks.getNetworkById(entry.getInfo().networkId).hasNick(nick)) {
                    holder.bufferImage.setImageBitmap(userOfflineBitmap);
                    holder.bufferView.setTextColor(offlineColor);
                } else if (bufferListAdapter.networks.getNetworkById(entry.getInfo().networkId)
                        .getUserByNick(nick).away) {
                    holder.bufferImage.setImageBitmap(userAwayBitmap);
                } else {
                    holder.bufferImage.setImageBitmap(userBitmap);
                }

                holder.bufferView.setText(nick);

                break;
            case GroupBuffer:
            case InvalidBuffer:
                holder.bufferView.setText("XXXX " + entry.getInfo().name);
            }

            BufferUtils.setBufferViewStatus(getSherlockActivity(), entry, holder.bufferView);
            return convertView;
        }

        @Override
        public int getChildrenCount(int groupPosition) {
            if (networks == null) {
                return 0;
            } else {
                return networks.getNetwork(groupPosition).getBuffers().getBufferCount();
            }
        }

        @Override
        public Network getGroup(int groupPosition) {
            return networks.getNetwork(groupPosition);
        }

        @Override
        public int getGroupCount() {
            if (networks == null) {
                return 0;
            } else {
                return networks.size();
            }
        }

        @Override
        public long getGroupId(int groupPosition) {
            return networks.getNetwork(groupPosition).getId();
        }

        @Override
        public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
            ViewHolderGroup holder = null;
            if (convertView == null) {
                convertView = inflater.inflate(R.layout.buffer_group_item, null);
                holder = new ViewHolderGroup();
                holder.statusView = (TextView) convertView.findViewById(R.id.buffer_list_item_name);
                holder.statusView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, Float.parseFloat(
                        preferences.getString(getString(R.string.preference_fontsize_channel_list), "20")));
                holder.statusView.setOnClickListener(new OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        if (getGroup((Integer) v.getTag()).getStatusBuffer() != null) {
                            openBuffer(getGroup((Integer) v.getTag()).getStatusBuffer());
                        } else { //TODO: mabye show the chatActivity but have it be empty, logo or something
                            Toast.makeText(getSherlockActivity(), "Not Available", Toast.LENGTH_SHORT).show();
                        }
                    }
                });
                holder.statusView.setOnLongClickListener(null); //Apparently need this so long click propagates to parent
                convertView.setTag(holder);
            } else {
                holder = (ViewHolderGroup) convertView.getTag();
            }
            Network entry = getGroup(groupPosition);
            holder.networkId = entry.getId();
            holder.statusView.setText(entry.getName());
            holder.statusView.setTag(groupPosition); //Used in click listener to know what item this is
            BufferUtils.setBufferViewStatus(getSherlockActivity(), entry.getStatusBuffer(), holder.statusView);
            return convertView;
        }

        @Override
        public boolean hasStableIds() {
            return true;
        }

        @Override
        public boolean isChildSelectable(int groupPosition, int childPosition) {
            return true;
        }

        public void clearBuffers() {
            networks = null;
            notifyDataSetChanged();
        }

        public void stopObserving() {
            if (networks == null)
                return;
            for (Network network : networks.getNetworkList())
                network.deleteObserver(this);
        }

    }

    public static class ViewHolderChild {
        public ImageView bufferImage;
        public TextView bufferView;
    }

    public static class ViewHolderGroup {
        public TextView statusView;
        public int networkId;
    }

    @Subscribe
    public void onNetworksAvailable(NetworksAvailableEvent event) {
        if (event.networks != null) {
            event.networks.addObserver(bufferListAdapter);
            bufferListAdapter.setNetworks(event.networks);
        }
    }

    class ActionModeData {
        public int id;
        public View listItem;
        public ActionMode actionMode;
        public ActionMode.Callback actionModeCallbackNetwork;
        public ActionMode.Callback actionModeCallbackBuffer;
    }

    @Subscribe
    public void onBufferListFontSizeChanged(BufferListFontSizeChangedEvent event) {
        bufferListAdapter.notifyDataSetChanged();
    }
}