/* * Copyright (C) 2014 Eric Butler * * 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 com.tapchatapp.android.app.ui; import android.app.Activity; import android.app.Fragment; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.util.Log; import com.squareup.otto.Bus; import com.squareup.otto.Subscribe; import com.tapchatapp.android.app.event.ConnectionAddedEvent; import com.tapchatapp.android.app.event.ConnectionChangedEvent; import com.tapchatapp.android.app.event.ConnectionRemovedEvent; import com.tapchatapp.android.app.event.ServiceStateChangedEvent; import com.tapchatapp.android.app.fragment.ConnectionFragment; import com.tapchatapp.android.app.TapchatApp; import com.tapchatapp.android.client.TapchatService; import com.tapchatapp.android.client.model.Connection; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import javax.inject.Inject; public class ConnectionsPagerAdapter extends TapchatFragmentStatePagerAdapter { private static final String TAG = "ConnectionsPagerAdapter"; private static final String KEY_CONNECTIONS = "com.tapchatapp.android.key_connections"; private final Activity mActivity; private final Object mLock = new Object(); private ArrayList<ConnectionInfo> mConnections = new ArrayList<>(); private int mServiceState; private boolean mIsLoaded; @Inject Bus mBus; public ConnectionsPagerAdapter(Activity activity) { super(activity.getFragmentManager()); TapchatApp.get().inject(this); mActivity = activity; } public void registerBus() { mBus.register(this); } public void unregisterBus() { mBus.unregister(this); } public boolean isLoaded() { return mIsLoaded; } @Override public Parcelable saveState() { Bundle bundle = (Bundle) super.saveState(); if (bundle == null) { bundle = new Bundle(); } bundle.putParcelableArrayList(KEY_CONNECTIONS, mConnections); return bundle; } @Override public void restoreState(Parcelable state, ClassLoader loader) { super.restoreState(state, loader); Bundle bundle = (Bundle) state; mConnections = bundle.getParcelableArrayList(KEY_CONNECTIONS); notifyDataSetChanged(); } @Override public int getCount() { return mConnections.size(); } @Override public String getPageTitle(int position) { return mConnections.get(position).mName.toUpperCase(); } @Override public Fragment getItem(int position) { ConnectionInfo info = mConnections.get(position); if (mActivity.getFragmentManager().findFragmentByTag(String.valueOf(info.mId)) != null) { throw new RuntimeException("eeeeek"); } Bundle args = new Bundle(); args.putLong(ConnectionFragment.ARG_CONNECTION_ID, info.mId); return Fragment.instantiate(mActivity, ConnectionFragment.class.getName(), args); } @Override public int getItemPosition(Object object) { ConnectionFragment fragment = (ConnectionFragment) object; int index = findConnectionIndex(fragment.getConnectionId()); if (index >= 0) { return index; } else { return POSITION_NONE; } } @Override public String getTag(int position) { return String.valueOf(mConnections.get(position).getId()); } @Subscribe public void onServiceStateChanged(ServiceStateChangedEvent event) { final TapchatService service = event.getService(); mServiceState = service.getConnectionState(); if (mServiceState != TapchatService.STATE_LOADED) { postNotifyDataSetChanged(); return; } ArrayList<ConnectionInfo> connections = new ArrayList<>(); for (Connection connection : service.getConnections()) { connections.add(ConnectionInfo.forConnection(connection)); } Collections.sort(connections, ConnectionInfo.COMPARATOR); mConnections = connections; postNotifyDataSetChanged(); } @Subscribe public void onConnectionAdded(ConnectionAddedEvent event) { final Connection connection = event.getConnection(); if (mServiceState != TapchatService.STATE_LOADED) { return; } synchronized (mLock) { if (findConnection(connection.getId()) != null) { return; } ArrayList<ConnectionInfo> connections = new ArrayList<>(mConnections); connections.add(ConnectionInfo.forConnection(connection)); Collections.sort(connections, ConnectionInfo.COMPARATOR); mConnections = connections; postNotifyDataSetChanged(); } } @Subscribe public void onConnectionChanged(ConnectionChangedEvent event) { final Connection connection = event.getConnection(); updateConnnection(connection); } @Subscribe public void onConnectionRemoved(ConnectionRemovedEvent event) { final Connection connection = event.getConnection(); removeConnnection(connection); } public ConnectionInfo getConnectionInfo(int position) { return mConnections.get(position); } private ConnectionInfo findConnection(long connectionId) { for (ConnectionInfo info : mConnections) { if (info.getId() == connectionId) { return info; } } return null; } private int findConnectionIndex(long connectionId) { for (int i = 0; i < mConnections.size(); i++) { ConnectionInfo info = mConnections.get(i); if (info.getId() == connectionId) { return i; } } return -1; } private void updateConnnection(Connection connection) { synchronized (mLock) { ConnectionInfo info = findConnection(connection.getId()); if (info != null) { info.mName = connection.getDisplayName(); info.mHostname = connection.getHostName(); notifyDataSetChanged(); } } } private void removeConnnection(Connection connection) { synchronized (mLock) { for (int i = 0; i < mConnections.size(); i++) { ConnectionInfo info = mConnections.get(i); if (info.mId == connection.getId()) { mConnections.remove(i); notifyDataSetChanged(); break; } } } } private void postNotifyDataSetChanged() { if (mServiceState == TapchatService.STATE_LOADED) { mIsLoaded = true; } notifyDataSetChanged(); } public static final class ConnectionInfo implements Parcelable { private long mId; private String mName; private String mHostname; @SuppressWarnings("UnusedDeclaration") public static final Creator<ConnectionInfo> CREATOR = new Creator<ConnectionInfo>() { @Override public ConnectionInfo createFromParcel(Parcel parcel) { return new ConnectionInfo(parcel.readLong(), parcel.readString(), parcel.readString()); } @Override public ConnectionInfo[] newArray(int size) { return new ConnectionInfo[size]; } }; public static final Comparator<ConnectionInfo> COMPARATOR = new Comparator<ConnectionInfo>() { @Override public int compare(ConnectionInfo connection, ConnectionInfo connection2) { int result = connection.getName().compareToIgnoreCase(connection2.getName()); if (result == 0) { result = connection.getHostName().compareToIgnoreCase(connection2.getHostName()); } return result; } }; public static ConnectionInfo forConnection(Connection connection) { return new ConnectionInfo(connection.getId(), connection.getDisplayName(), connection.getHostName()); } public ConnectionInfo(long id, String name, String hostname) { mId = id; mName = name; mHostname = hostname; } public long getId() { return mId; } public String getName() { return mName; } public String getHostName() { return mHostname; } @Override public void writeToParcel(Parcel parcel, int flags) { parcel.writeLong(mId); parcel.writeString(mName); parcel.writeString(mHostname); } @Override public int describeContents() { return 0; } @Override public String toString() { return "ConnectionInfo{" + "mId=" + mId + ", mName='" + mName + '\'' + ", mHostname='" + mHostname + '\'' + '}'; } } }