Commit 3c495c64 authored by Grigory Fedorov's avatar Grigory Fedorov

Refactoring and simplification: BaseContactAdapter, BaseContactInflater,...

Refactoring and simplification: BaseContactAdapter, BaseContactInflater, ChatContactInflater, ClientContactInflater, SmoothContactAdapter and StatusContactInflater united in ContactListAdapter and GroupedContactAdapter.
parent b52b1cce
......@@ -93,7 +93,7 @@ public class ContactListFragment extends Fragment implements OnAccountChangedLis
listView.setOnItemClickListener(this);
listView.setItemsCanFocus(true);
registerForContextMenu(listView);
adapter = new ContactListAdapter(getActivity(), listView, this, this);
adapter = new ContactListAdapter(getActivity(), this, this);
listView.setAdapter(adapter);
infoView = view.findViewById(R.id.info);
connectedView = infoView.findViewById(R.id.connected);
......
/**
* Copyright (c) 2013, Redsolution LTD. All rights reserved.
*
* This file is part of Xabber project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License, Version 3.
*
* Xabber 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,
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.xabber.android.ui.adapter;
import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import com.xabber.android.data.entity.BaseEntity;
import com.xabber.android.data.roster.AbstractContact;
import java.util.ArrayList;
import java.util.Locale;
/**
* Base adapter for the list of contacts.
*
* @author alexander.ivanov
*/
public abstract class BaseContactAdapter<Inflater extends BaseContactInflater>
extends BaseAdapter implements UpdatableAdapter, Filterable {
final Activity activity;
final Locale locale;
/**
* List of entities.
*/
final ArrayList<BaseEntity> baseEntities;
/**
* Used view inflater.
*/
final Inflater inflater;
/**
* Contact filter.
*/
ContactFilter contactFilter;
/**
* Filter string. Can be <code>null</code> if filter is disabled.
*/
String filterString;
public BaseContactAdapter(Activity activity, Inflater inflater) {
this.activity = activity;
this.locale = Locale.getDefault();
this.baseEntities = new ArrayList<>();
this.inflater = inflater;
inflater.setAdapter(this);
contactFilter = null;
filterString = null;
}
@Override
public void onChange() {
notifyDataSetChanged();
}
@Override
public int getCount() {
return baseEntities.size();
}
@Override
public Object getItem(int position) {
return baseEntities.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final View view;
if (convertView == null) {
view = inflater.createView(position, parent);
view.setTag(inflater.createViewHolder(position, view));
} else {
view = convertView;
}
inflater.getView(view, (AbstractContact) getItem(position));
return view;
}
@Override
public Filter getFilter() {
if (contactFilter == null) {
contactFilter = new ContactFilter();
}
return contactFilter;
}
private class ContactFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
return null;
}
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
if (constraint == null || constraint.length() == 0) {
filterString = null;
} else {
filterString = constraint.toString().toLowerCase(locale);
}
onChange();
}
}
}
/**
* Copyright (c) 2013, Redsolution LTD. All rights reserved.
*
* This file is part of Xabber project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License, Version 3.
*
* Xabber 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,
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.xabber.android.ui.adapter;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.xabber.android.data.SettingsManager;
import com.xabber.android.data.roster.AbstractContact;
import com.xabber.androiddev.R;
/**
* Provides views and fills them with data for {@link BaseContactAdapter}.
*
* @author alexander.ivanov
*/
public abstract class BaseContactInflater {
final Activity activity;
final LayoutInflater layoutInflater;
/**
* Managed adapter.
*/
BaseAdapter adapter;
private final int[] accountColors;
public BaseContactInflater(Activity activity) {
this.activity = activity;
layoutInflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
accountColors = activity.getResources().getIntArray(R.array.account_action_bar);
}
/**
* Sets managed adapter.
*
* @param adapter
*/
void setAdapter(BaseAdapter adapter) {
this.adapter = adapter;
}
/**
* Creates new view for specified position.
*
* @param position
* @param parent
* @return
*/
abstract View createView(int position, ViewGroup parent);
/**
* Creates new instance of ViewHolder.
*
* @param position
* @param view
* @return
*/
abstract ViewHolder createViewHolder(int position, View view);
/**
* Returns status text.
*
* @param abstractContact
* @return
*/
String getStatusText(AbstractContact abstractContact) {
return abstractContact.getStatusText();
}
/**
* Fills view for {@link BaseContactAdapter}.
*
* @param view view to be inflated.
* @param abstractContact contact to be shown.
*/
public void getView(View view, AbstractContact abstractContact) {
final ViewHolder viewHolder = (ViewHolder) view.getTag();
if (abstractContact.isConnected()) {
viewHolder.offlineShadow.setVisibility(View.GONE);
} else {
viewHolder.offlineShadow.setVisibility(View.VISIBLE);
}
int colorLevel = abstractContact.getColorLevel();
viewHolder.color.setImageDrawable(new ColorDrawable(accountColors[colorLevel]));
if (SettingsManager.contactsShowAvatars()) {
viewHolder.avatar.setVisibility(View.VISIBLE);
viewHolder.avatar.setImageDrawable(abstractContact.getAvatarForContactList());
} else {
viewHolder.avatar.setVisibility(View.GONE);
}
viewHolder.name.setText(abstractContact.getName());
final String statusText = getStatusText(abstractContact);
if ("".equals(statusText)) {
viewHolder.name.getLayoutParams().height = activity.getResources()
.getDimensionPixelSize(R.dimen.contact_name_height_hide_status);
viewHolder.name.setGravity(Gravity.CENTER_VERTICAL);
viewHolder.status.setVisibility(View.GONE);
} else {
viewHolder.name.getLayoutParams().height = activity.getResources()
.getDimensionPixelSize(R.dimen.contact_name_height_show_status);
viewHolder.name.setGravity(Gravity.BOTTOM);
viewHolder.status.setText(statusText);
viewHolder.status.setVisibility(View.VISIBLE);
}
}
/**
* Holder for views in contact item.
*/
static class ViewHolder {
final ImageView color;
final ImageView avatar;
final TextView name;
final TextView status;
final ImageView offlineShadow;
public ViewHolder(View view) {
color = (ImageView) view.findViewById(R.id.color);
avatar = (ImageView) view.findViewById(R.id.avatar);
name = (TextView) view.findViewById(R.id.name);
status = (TextView) view.findViewById(R.id.status);
offlineShadow = (ImageView) view.findViewById(R.id.offline_shadow);
}
}
}
/**
* Copyright (c) 2013, Redsolution LTD. All rights reserved.
*
* This file is part of Xabber project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License, Version 3.
*
* Xabber 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,
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.xabber.android.ui.adapter;
import android.app.Activity;
import android.view.View;
import com.xabber.android.data.message.MessageManager;
import com.xabber.android.data.roster.AbstractContact;
import com.xabber.androiddev.R;
/**
* Inflate view with contact's last message or status text as well as active
* chat badge.
*
* @author alexander.ivanov
*/
public class ChatContactInflater extends ClientContactInflater {
public ChatContactInflater(Activity activity) {
super(activity);
}
@Override
ViewHolder createViewHolder(int position, View view) {
return new ViewHolder(view);
}
@Override
String getStatusText(AbstractContact abstractContact) {
if (MessageManager.getInstance()
.hasActiveChat(abstractContact.getAccount(), abstractContact.getUser())) {
return MessageManager.getInstance()
.getLastText(abstractContact.getAccount(), abstractContact.getUser());
} else {
return super.getStatusText(abstractContact);
}
}
@Override
public void getView(View view, AbstractContact abstractContact) {
super.getView(view, abstractContact);
if (MessageManager.getInstance().hasActiveChat(abstractContact.getAccount(), abstractContact.getUser())) {
view.setBackgroundColor(activity.getResources().getColor(R.color.grey_50));
} else {
view.setBackgroundColor(activity.getResources().getColor(R.color.grey_300));
}
}
static class ViewHolder extends ClientContactInflater.ViewHolder {
final View panel;
public ViewHolder(View view) {
super(view);
panel = view.findViewById(R.id.panel);
}
}
}
/**
* Copyright (c) 2013, Redsolution LTD. All rights reserved.
*
* This file is part of Xabber project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License, Version 3.
*
* Xabber 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,
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.xabber.android.ui.adapter;
import android.app.Activity;
import android.view.View;
import android.widget.ImageView;
import com.xabber.android.data.extension.capability.ClientSoftware;
import com.xabber.android.data.roster.AbstractContact;
import com.xabber.androiddev.R;
/**
* Inflate view with contact's client software.
*
* @author alexander.ivanov
*/
public class ClientContactInflater extends StatusContactInflater {
public ClientContactInflater(Activity activity) {
super(activity);
}
@Override
ViewHolder createViewHolder(int position, View view) {
return new ClientContactInflater.ViewHolder(view);
}
@Override
public void getView(View view, AbstractContact abstractContact) {
super.getView(view, abstractContact);
ViewHolder viewHolder = (ViewHolder) view.getTag();
ClientSoftware clientSoftware = abstractContact.getClientSoftware();
if (clientSoftware == ClientSoftware.unknown)
viewHolder.clientSoftware.setVisibility(View.INVISIBLE);
else {
viewHolder.clientSoftware.setVisibility(View.VISIBLE);
viewHolder.clientSoftware.setImageLevel(clientSoftware.ordinal());
}
}
static class ViewHolder extends StatusContactInflater.ViewHolder {
final ImageView clientSoftware;
public ViewHolder(View view) {
super(view);
clientSoftware = (ImageView) view
.findViewById(R.id.client_software);
}
}
}
......@@ -16,6 +16,8 @@ package com.xabber.android.ui.adapter;
import android.app.Activity;
import android.os.Handler;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ListView;
import com.xabber.android.data.SettingsManager;
......@@ -47,8 +49,7 @@ import java.util.TreeMap;
*
* @author alexander.ivanov
*/
public class ContactListAdapter extends GroupedContactAdapter<ChatContactInflater, GroupManager>
implements Runnable {
public class ContactListAdapter extends GroupedContactAdapter implements Runnable, Filterable {
/**
* Number of milliseconds between lazy refreshes.
......@@ -80,11 +81,21 @@ public class ContactListAdapter extends GroupedContactAdapter<ChatContactInflate
*/
private Date nextRefresh;
/**
* Contact filter.
*/
ContactFilter contactFilter;
/**
* Filter string. Can be <code>null</code> if filter is disabled.
*/
String filterString;
private final OnContactListChangedListener listener;
public ContactListAdapter(Activity activity, ListView listView, OnContactListChangedListener listener,
public ContactListAdapter(Activity activity, OnContactListChangedListener listener,
GroupedContactAdapter.OnAccountClickListener onAccountClickListener) {
super(activity, listView, new ChatContactInflater(activity), GroupManager.getInstance(), onAccountClickListener);
super(activity, onAccountClickListener);
this.listener = listener;
handler = new Handler();
refreshLock = new Object();
......@@ -197,7 +208,7 @@ public class ContactListAdapter extends GroupedContactAdapter<ChatContactInflate
contacts = null;
for (Entry<String, AccountConfiguration> entry : accounts.entrySet()) {
entry.setValue(new AccountConfiguration(entry.getKey(),
GroupManager.IS_ACCOUNT, groupStateProvider));
GroupManager.IS_ACCOUNT, GroupManager.getInstance()));
}
} else {
if (showGroups) {
......@@ -210,7 +221,7 @@ public class ContactListAdapter extends GroupedContactAdapter<ChatContactInflate
}
if (showActiveChats) {
activeChats = new GroupConfiguration(GroupManager.NO_ACCOUNT,
GroupManager.ACTIVE_CHATS, groupStateProvider);
GroupManager.ACTIVE_CHATS, GroupManager.getInstance());
} else {
activeChats = null;
}
......@@ -429,4 +440,32 @@ public class ContactListAdapter extends GroupedContactAdapter<ChatContactInflate
super(account, user);
}
}
@Override
public Filter getFilter() {
if (contactFilter == null) {
contactFilter = new ContactFilter();
}
return contactFilter;
}
private class ContactFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
return null;
}
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
if (constraint == null || constraint.length() == 0) {
filterString = null;
} else {
filterString = constraint.toString().toLowerCase(locale);
}
onChange();
}
}
}
/**
* Copyright (c) 2013, Redsolution LTD. All rights reserved.
*
* This file is part of Xabber project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License, Version 3.
*
* Xabber 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,
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.xabber.android.ui.adapter;
import android.app.Activity;
import android.widget.ListView;
/**
* Enable smooth scrollbar depend on number of entities.
*
* @param <Inflater>
* @author alexander.ivanov
*/
public abstract class SmoothContactAdapter<Inflater extends BaseContactInflater>
extends BaseContactAdapter<Inflater> {
/**
* Minimum number of item when smooth scroll bar will be disabled.
*/
private static final int SMOOTH_SCROLLBAR_LIMIT = 20;
/**
* Managed list view.
*/
ListView listView;
public SmoothContactAdapter(Activity activity, ListView listView, Inflater inflater) {
super(activity, inflater);
this.listView = listView;
}
@Override
public void onChange() {
super.onChange();
listView.setSmoothScrollbarEnabled(baseEntities.size() < SMOOTH_SCROLLBAR_LIMIT);
}
}
/**
* Copyright (c) 2013, Redsolution LTD. All rights reserved.
*
* This file is part of Xabber project; you can redistribute it and/or
* modify it under the terms of the GNU General Public License, Version 3.
*
* Xabber 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,
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.xabber.android.ui.adapter;
import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.xabber.android.data.roster.AbstractContact;
import com.xabber.androiddev.R;
/**
* Inflate view with contact's status mode.
*
* @author alexander.ivanov
*/
public class StatusContactInflater extends BaseContactInflater {
public StatusContactInflater(Activity activity) {
super(activity);
}
@Override
View createView(int position, ViewGroup parent) {
return layoutInflater
.inflate(R.layout.base_contact_item, parent, false);
}
@Override
ViewHolder createViewHolder(int position, View view) {
return new StatusContactInflater.ViewHolder(view);
}
@Override
public void getView(View view, AbstractContact abstractContact) {
super.getView(view, abstractContact);
ViewHolder viewHolder = (ViewHolder) view.getTag();
viewHolder.statusMode.setImageLevel(abstractContact.getStatusMode()
.getStatusLevel());
}
static class ViewHolder extends BaseContactInflater.ViewHolder {
final ImageView statusMode;
public ViewHolder(View view) {
super(view);
statusMode = (ImageView) view.findViewById(R.id.status_icon);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment