* #26787 Replaced buttons by DnD
diff --git a/src/com/savoirfairelinux/sflphone/client/CallActivity.java b/src/com/savoirfairelinux/sflphone/client/CallActivity.java
index 16c47e1..2da13ec 100644
--- a/src/com/savoirfairelinux/sflphone/client/CallActivity.java
+++ b/src/com/savoirfairelinux/sflphone/client/CallActivity.java
@@ -256,6 +256,7 @@
mCallsFragment.update();
+ if(mCurrentCallFragment != null)
mCurrentCallFragment.changeCallState(callID, newState);
try {
@@ -469,6 +470,7 @@
public void replaceCurrentCallDisplayed() {
mCurrentCallFragment.getBubbleView().stopThread();
getFragmentManager().beginTransaction().remove(mCurrentCallFragment).commit();
+ mCurrentCallFragment = null;
}
diff --git a/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java b/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java
index 098b723..cac9296 100644
--- a/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java
+++ b/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java
@@ -246,14 +246,14 @@
}
});
}
-
+
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
-
+
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@@ -360,12 +360,15 @@
Log.i(TAG, "Launch Call Activity");
Bundle bundle = new Bundle();
Conference tmp = new Conference("-1");
+
tmp.getParticipants().add(infos);
+
bundle.putParcelable("conference", tmp);
Intent intent = new Intent().setClass(this, CallActivity.class);
intent.putExtra("resuming", false);
intent.putExtras(bundle);
startActivityForResult(intent, REQUEST_CODE_CALL);
+ overridePendingTransition(R.anim.slide_down, R.anim.slide_up);
}
/** Defines callbacks for service binding, passed to bindService() */
@@ -425,7 +428,8 @@
break;
case REQUEST_CODE_CALL:
Log.w(TAG, "Result out of CallActivity");
- getLoaderManager().restartLoader(LoaderConstants.HISTORY_LOADER, null, (HistoryFragment) mSectionsPagerAdapter.getItem(2));
+ if (mSectionsPagerAdapter.getItem(2) != null)
+ getLoaderManager().restartLoader(LoaderConstants.HISTORY_LOADER, null, (HistoryFragment) mSectionsPagerAdapter.getItem(2));
break;
}
diff --git a/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java b/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java
index 95d01e9..9276db0 100644
--- a/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java
+++ b/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java
@@ -221,7 +221,7 @@
int angle_part = 360 / conf.getParticipants().size();
double dX = 0;
double dY = 0;
- int radiusCalls = model.width / 2 - 150;
+ int radiusCalls = (int) (model.width / 2 - BUBBLE_SIZE);
for (int i = 0; i < conf.getParticipants().size(); ++i) {
if (conf.getParticipants().get(i) == null) {
@@ -311,13 +311,13 @@
callStatusTxt.setText("Calling...");
- getBubbleFor(myself, model.width / 2, model.height / 2);
+ getBubbleFor(myself, model.width / 2, (float) (model.height / 1.2));
// TODO off-thread image loading
int angle_part = 360 / conf.getParticipants().size();
double dX = 0;
double dY = 0;
- int radiusCalls = model.width / 2 - 150;
+ int radiusCalls = (int) ((model.width / 2 - BUBBLE_SIZE));
for (int i = 0; i < conf.getParticipants().size(); ++i) {
dX = Math.cos(Math.toRadians(angle_part * i - 90)) * radiusCalls;
dY = Math.sin(Math.toRadians(angle_part * i - 90)) * radiusCalls;
@@ -415,9 +415,7 @@
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- // Log.i(TAG, "Init fragment " + mCall.getCallId());
- // mCall.printCallInfo();
if (conf.getParticipants().size() == 1) {
if (conf.getParticipants().get(0).isIncoming() && conf.getParticipants().get(0).isRinging()) {
diff --git a/src/com/savoirfairelinux/sflphone/fragments/CallListFragment.java b/src/com/savoirfairelinux/sflphone/fragments/CallListFragment.java
index 9abaad3..126eb85 100644
--- a/src/com/savoirfairelinux/sflphone/fragments/CallListFragment.java
+++ b/src/com/savoirfairelinux/sflphone/fragments/CallListFragment.java
@@ -35,24 +35,34 @@
import java.util.HashMap;
import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentManager;
+import android.content.ClipData;
+import android.content.ClipData.Item;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
+import android.graphics.Color;
import android.os.Bundle;
import android.os.RemoteException;
+import android.os.Vibrator;
import android.util.Log;
+import android.view.DragEvent;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.View.OnClickListener;
+import android.view.View.DragShadowBuilder;
+import android.view.View.OnDragListener;
import android.view.ViewGroup;
-import android.view.animation.Animation;
-import android.view.animation.AnimationUtils;
-import android.widget.BaseExpandableListAdapter;
-import android.widget.Button;
-import android.widget.ExpandableListView;
-import android.widget.ImageButton;
-import android.widget.RelativeLayout;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.AdapterView.OnItemLongClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.BaseAdapter;
+import android.widget.ListAdapter;
+import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
@@ -60,6 +70,7 @@
import com.savoirfairelinux.sflphone.model.Conference;
import com.savoirfairelinux.sflphone.model.SipCall;
import com.savoirfairelinux.sflphone.service.ISipService;
+import com.savoirfairelinux.sflphone.views.SwipeListViewTouchListener;
public class CallListFragment extends Fragment {
static final String TAG = CallListFragment.class.getSimpleName();
@@ -128,22 +139,125 @@
mCallbacks = sDummyCallbacks;
}
- ExpandableListView list;
+ ListView list;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.frag_call_list, container, false);
- list = (ExpandableListView) rootView.findViewById(R.id.call_list);
- list.setDividerHeight(2);
- list.setGroupIndicator(null);
- list.setAdapter(mAdapter);
+ list = (ListView) rootView.findViewById(R.id.call_list);
- list.setClickable(true);
- list.setItemsCanFocus(true);
+ list.setDivider(getResources().getDrawable(android.R.drawable.divider_horizontal_dark));
+ list.setDividerHeight(10);
+ list.setAdapter(mAdapter);
+ list.setOnItemClickListener(mItemClickListener);
+ list.setOnTouchListener(new SwipeListViewTouchListener(list, new SwipeListViewTouchListener.OnSwipeCallback() {
+ @Override
+ public void onSwipeLeft(ListView listView, int[] reverseSortedPositions) {
+ // Log.i(this.getClass().getName(), "swipe left : pos="+reverseSortedPositions[0]);
+ // TODO : YOUR CODE HERE FOR LEFT ACTION
+ }
+
+ @Override
+ public void onSwipeRight(ListView listView, int[] reverseSortedPositions) {
+ // Log.i(ProfileMenuActivity.class.getClass().getName(), "swipe right : pos="+reverseSortedPositions[0]);
+ // TODO : YOUR CODE HERE FOR RIGHT ACTION
+ }
+ }, true, // example : left action = dismiss
+ false)); // example : right action without dismiss animation);
+ list.setOnItemLongClickListener(mItemLongClickListener);
+
return rootView;
}
+ OnDragListener dragListener = new OnDragListener() {
+
+ @Override
+ public boolean onDrag(View v, DragEvent event) {
+ switch (event.getAction()) {
+ case DragEvent.ACTION_DRAG_STARTED:
+ // Do nothing
+ Log.w(TAG, "ACTION_DRAG_STARTED");
+ break;
+ case DragEvent.ACTION_DRAG_ENTERED:
+ Log.w(TAG, "ACTION_DRAG_ENTERED");
+ v.setBackgroundColor(Color.GREEN);
+ break;
+ case DragEvent.ACTION_DRAG_EXITED:
+ Log.w(TAG, "ACTION_DRAG_EXITED");
+ v.setBackgroundDrawable(getResources().getDrawable(R.drawable.item_call_selector));
+ break;
+ case DragEvent.ACTION_DROP:
+ Log.w(TAG, "ACTION_DROP");
+ View view = (View) event.getLocalState();
+
+ Item i = event.getClipData().getItemAt(0);
+ Intent intent = i.getIntent();
+ intent.setExtrasClassLoader(Conference.class.getClassLoader());
+
+ Conference initial = (Conference) view.getTag();
+ Conference target = (Conference) v.getTag();
+
+ if(initial == target){
+ return true;
+ }
+
+ DropActionsChoice dialog = DropActionsChoice.newInstance();
+ Bundle b = new Bundle();
+ b.putParcelable("call_initial", initial);
+ b.putParcelable("call_targeted", target);
+ dialog.setArguments(b);
+ dialog.setTargetFragment(CallListFragment.this, 0);
+ dialog.show(getFragmentManager(), "dialog");
+
+ Toast.makeText(
+ getActivity(),
+ "Dropped " + initial.getParticipants().get(0).getContact().getmDisplayName() + " on "
+ + target.getParticipants().get(0).getContact().getmDisplayName(), Toast.LENGTH_SHORT).show();
+ // view.setBackgroundColor(Color.WHITE);
+ // v.setBackgroundColor(Color.BLACK);
+ break;
+ case DragEvent.ACTION_DRAG_ENDED:
+ Log.w(TAG, "ACTION_DRAG_ENDED");
+ View view1 = (View) event.getLocalState();
+ view1.setVisibility(View.VISIBLE);
+ v.setBackgroundDrawable(getResources().getDrawable(R.drawable.item_call_selector));
+ default:
+ break;
+ }
+ return true;
+ }
+
+ };
+
+ private OnItemLongClickListener mItemLongClickListener = new OnItemLongClickListener() {
+
+ @Override
+ public boolean onItemLongClick(AdapterView<?> arg0, View view, int pos, long arg3) {
+ final Vibrator vibe = (Vibrator) view.getContext().getSystemService(Context.VIBRATOR_SERVICE);
+ vibe.vibrate(80);
+ Intent i = new Intent();
+ Bundle b = new Bundle();
+ b.putParcelable("conference", mAdapter.getItem(pos));
+ i.putExtra("bconference", b);
+
+ DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view.findViewById(R.id.num_participants));
+ ClipData data = ClipData.newIntent("conference", i);
+ view.startDrag(data, shadowBuilder, view, 0);
+ return false;
+ }
+
+ };
+
+ private OnItemClickListener mItemClickListener = new OnItemClickListener() {
+
+ @Override
+ public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
+ mCallbacks.onCallSelected(mAdapter.getItem(pos));
+
+ }
+ };
+
public void update() {
try {
Log.w(TAG, "Updating");
@@ -153,20 +267,6 @@
ArrayList<Conference> conferences = new ArrayList<Conference>();
HashMap<String, Conference> tmp = (HashMap<String, Conference>) mCallbacks.getService().getConferenceList();
conferences.addAll(tmp.values());
-// for (String confid : tmp) {
-// Log.w(TAG, "Conference:" + confid);
-// Conference toAdd = new Conference(confid);
-//
-// toAdd.setState(mCallbacks.getService().getConferenceDetails(confid));
-// // Toast.makeText(getActivity(), "State of Conf: " + toAdd.getState(), Toast.LENGTH_SHORT).show();
-//// ArrayList<String> conf_participants = (ArrayList<String>) mCallbacks.getService().getParticipantList(confid);
-//// for (String part : conf_participants) {
-//// Log.w(TAG, "participant:" + part);
-//// toAdd.getParticipants().add(list.get(part));
-//// list.remove(part);
-//// }
-// conferences.add(toAdd);
-// }
ArrayList<SipCall> simple_calls = new ArrayList<SipCall>(list.values());
for (SipCall call : simple_calls) {
@@ -191,10 +291,10 @@
FragmentManager fm = getFragmentManager();
TransferDFragment editNameDialog = new TransferDFragment();
- if (mAdapter.getGroup(groupPosition).getParticipants().size() == 1) {
+ if (!mAdapter.getItem(groupPosition).hasMultipleParticipants()) {
Bundle b = new Bundle();
b.putParcelableArrayList("calls", mAdapter.getConcurrentCalls(groupPosition));
- b.putParcelable("call_selected", mAdapter.getGroup(groupPosition));
+ b.putParcelable("call_selected", mAdapter.getItem(groupPosition));
editNameDialog.setArguments(b);
editNameDialog.setTargetFragment(this, REQUEST_TRANSFER);
editNameDialog.show(fm, "dialog");
@@ -210,7 +310,7 @@
Bundle b = new Bundle();
b.putParcelableArrayList("calls", mAdapter.getConcurrentCalls(groupPosition));
- b.putParcelable("call_selected", mAdapter.getGroup(groupPosition));
+ b.putParcelable("call_selected", mAdapter.getItem(groupPosition));
confDialog.setArguments(b);
confDialog.setTargetFragment(this, REQUEST_CONF);
confDialog.show(fm, "dialog");
@@ -230,7 +330,7 @@
mCallbacks.getService().attendedTransfer(transfer.getParticipants().get(0).getCallId(), c.getParticipants().get(0).getCallId());
mAdapter.remove(transfer);
-
+ mAdapter.remove(c);
mAdapter.notifyDataSetChanged();
} catch (RemoteException e) {
// TODO Auto-generated catch block
@@ -259,38 +359,10 @@
} else if (requestCode == REQUEST_CONF) {
switch (resultCode) {
case 0:
- Conference call_to_add = data.getParcelableExtra("call_to_add");
- Conference call_target = data.getParcelableExtra("call_target");
- try {
+ Conference call_to_add = data.getParcelableExtra("transfer");
+ Conference call_target = data.getParcelableExtra("target");
- if (call_target.hasMultipleParticipants() && !call_to_add.hasMultipleParticipants()) {
-
- mCallbacks.getService().addParticipant(call_to_add.getParticipants().get(0), call_target.getId());
-
- } else if (call_target.hasMultipleParticipants() && call_to_add.hasMultipleParticipants()) {
-
- // We join two conferences
- mCallbacks.getService().joinConference(call_to_add.getId(), call_target.getId());
-
- } else if (!call_target.hasMultipleParticipants() && call_to_add.hasMultipleParticipants()) {
-
- mCallbacks.getService().addParticipant(call_target.getParticipants().get(0), call_to_add.getId());
-
- } else {
- // We join two single calls to create a conf
- mCallbacks.getService().joinParticipant(call_to_add.getParticipants().get(0).getCallId(),
- call_target.getParticipants().get(0).getCallId());
- }
- // ArrayList<String> tmp = new ArrayList<String>();
- // tmp.add(call1.getCallId());
- // tmp.add(call2.getCallId());
- // mCallbacks.getService().createConfFromParticipantList(tmp);
-
- } catch (RemoteException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- Toast.makeText(getActivity(), "Conference created", Toast.LENGTH_LONG).show();
+ bindCalls(call_to_add, call_target);
break;
default:
@@ -299,36 +371,47 @@
}
}
- /**
- * A simple adapter which maintains an ArrayList of photo resource Ids. Each photo is displayed as an image. This adapter supports clearing the
- * list of photos and adding a new photo.
- *
- */
- public class CallListAdapter extends BaseExpandableListAdapter {
+ private void bindCalls(Conference call_to_add, Conference call_target) {
+ try {
+
+ if (call_target.hasMultipleParticipants() && !call_to_add.hasMultipleParticipants()) {
+
+ mCallbacks.getService().addParticipant(call_to_add.getParticipants().get(0), call_target.getId());
+
+ } else if (call_target.hasMultipleParticipants() && call_to_add.hasMultipleParticipants()) {
+
+ // We join two conferences
+ mCallbacks.getService().joinConference(call_to_add.getId(), call_target.getId());
+
+ } else if (!call_target.hasMultipleParticipants() && call_to_add.hasMultipleParticipants()) {
+
+ mCallbacks.getService().addParticipant(call_target.getParticipants().get(0), call_to_add.getId());
+
+ } else {
+ // We join two single calls to create a conf
+ mCallbacks.getService().joinParticipant(call_to_add.getParticipants().get(0).getCallId(),
+ call_target.getParticipants().get(0).getCallId());
+ }
+
+ } catch (RemoteException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ public class CallListAdapter extends BaseAdapter {
private ArrayList<Conference> calls;
private Context mContext;
- private int lastExpandedGroupPosition;
- public CallListAdapter(Context activity) {
+ public CallListAdapter(Context act) {
+ super();
+ mContext = act;
calls = new ArrayList<Conference>();
- mContext = activity;
- }
-
- public void remove(Conference transfer) {
- calls.remove(transfer);
}
- // public String getCurrentCall() {
- // for (int i = 0; i < calls.size(); ++i) {
- // if (calls.get(i).getCallStateInt() == SipCall.state.CALL_STATE_CURRENT)
- // return calls.get(i).getCallId();
- // }
- // return "";
- // }
-
public ArrayList<Conference> getConcurrentCalls(int position) {
ArrayList<Conference> toReturn = new ArrayList<Conference>();
for (int i = 0; i < calls.size(); ++i) {
@@ -338,197 +421,119 @@
return toReturn;
}
- public ArrayList<Conference> getCalls() {
- return calls;
- }
+ public void remove(Conference transfer) {
- @Override
- public Object getChild(int groupPosition, int childPosition) {
- return null;
- }
-
- public long getChildId(int groupPosition, int childPosition) {
- return childPosition;
- }
-
- public int getChildrenCount(int groupPosition) {
- return 1;
- }
-
- public View getChildView(final int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
-
- convertView = LayoutInflater.from(mContext).inflate(R.layout.expandable_child, null);
-
- convertView.setAnimation(AnimationUtils.loadAnimation(getActivity(), R.animator.slide_down));
-
- ((ImageButton) convertView.findViewById(R.id.action_hangup)).setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- try {
- if (getGroup(groupPosition).getParticipants().size() == 1) {
- mCallbacks.getService().hangUp(getGroup(groupPosition).getParticipants().get(0).getCallId());
- } else {
- mCallbacks.getService().hangUpConference(getGroup(groupPosition).getId());
- }
- } catch (RemoteException e) {
- e.printStackTrace();
- }
-
- }
- });
-
- if(getGroup(groupPosition).isOnHold()){
- ((Button) convertView.findViewById(R.id.action_hold)).setText("Unhold");
- }
- ((Button) convertView.findViewById(R.id.action_hold)).setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
-
- try {
- if (((Button) v).getText().toString().contentEquals("Hold")) {
- if (getGroup(groupPosition).getParticipants().size() == 1) {
- mCallbacks.getService().hold(getGroup(groupPosition).getParticipants().get(0).getCallId());
- } else {
- mCallbacks.getService().holdConference(getGroup(groupPosition).getId());
- }
-
- ((Button) v).setText("Unhold");
- } else {
- if (getGroup(groupPosition).getParticipants().size() == 1) {
- mCallbacks.getService().unhold(getGroup(groupPosition).getParticipants().get(0).getCallId());
- } else {
- mCallbacks.getService().unholdConference(getGroup(groupPosition).getId());
- }
- ((Button) v).setText("Hold");
- }
- } catch (RemoteException e) {
- e.printStackTrace();
- }
-
- }
- });
-
- ((Button) convertView.findViewById(R.id.action_conf)).setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- makeConferenceDialog(groupPosition);
- }
-
- });
-
- ((Button) convertView.findViewById(R.id.action_transfer)).setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- makeTransferDialog(groupPosition);
- }
-
- });
-
- return convertView;
- }
-
- @Override
- public Conference getGroup(int groupPosition) {
- return calls.get(groupPosition);
- }
-
- @Override
- public int getGroupCount() {
- return calls.size();
- }
-
- @Override
- public void onGroupCollapsed(int groupPosition) {
- super.onGroupCollapsed(groupPosition);
- }
-
- @Override
- public void onGroupExpanded(int groupPosition) {
-
- // collapse the old expanded group, if not the same
- // as new group to expand
- if (groupPosition != lastExpandedGroupPosition) {
- list.collapseGroup(lastExpandedGroupPosition);
-
- }
-
- super.onGroupExpanded(groupPosition);
- lastExpandedGroupPosition = groupPosition;
- }
-
- @Override
- public long getGroupId(int groupPosition) {
- return 0;
- }
-
- public View getGroupView(final int groupPosition, final boolean isExpanded, View convertView, ViewGroup parent) {
-
- if (convertView == null)
- convertView = LayoutInflater.from(mContext).inflate(R.layout.item_calllist, null);
-
- Conference call = getGroup(groupPosition);
- if (call.getParticipants().size() == 1) {
- ((TextView) convertView.findViewById(R.id.call_title)).setText(call.getParticipants().get(0).getContact().getmDisplayName());
- ((TextView) convertView.findViewById(R.id.call_status)).setText(call.getState());
- } else {
- ((TextView) convertView.findViewById(R.id.call_title)).setText("Conference with " + call.getParticipants().size() + " participants");
- ((TextView) convertView.findViewById(R.id.call_status)).setText(call.getState());
- }
-
- ((RelativeLayout) convertView.findViewById(R.id.call_entry)).setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
- mCallbacks.onCallSelected(getGroup(groupPosition));
-
- }
- });
-
- ((ImageButton) convertView.findViewById(R.id.expand_button)).setOnClickListener(new OnClickListener() {
-
- @Override
- public void onClick(View v) {
-
- if (isExpanded) {
- list.collapseGroup(groupPosition);
-
- final Animation animRotate = AnimationUtils.loadAnimation(getActivity(), R.animator.reverse);
- ((ImageButton) v).startAnimation(animRotate);
- ((ImageButton) v).setRotation(0);
- } else {
- list.expandGroup(groupPosition);
- final Animation animRotate = AnimationUtils.loadAnimation(getActivity(), R.animator.reverse);
- ((ImageButton) v).startAnimation(animRotate);
- ((ImageButton) v).setRotation(180);
-
- }
- }
- });
-
- return convertView;
- }
-
- @Override
- public boolean hasStableIds() {
- return false;
- }
-
- @Override
- public boolean isChildSelectable(int groupPosition, int childPosition) {
- return false;
}
public void update(ArrayList<Conference> list) {
calls.clear();
calls.addAll(list);
notifyDataSetChanged();
-
}
+ @Override
+ public int getCount() {
+ return calls.size();
+ }
+
+ @Override
+ public Conference getItem(int position) {
+ return calls.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return 0;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null)
+ convertView = LayoutInflater.from(mContext).inflate(R.layout.item_calllist, null);
+
+ Conference call = calls.get(position);
+ if (call.getParticipants().size() == 1) {
+ ((TextView) convertView.findViewById(R.id.call_title)).setText(call.getParticipants().get(0).getContact().getmDisplayName());
+ } else {
+ String tmp = "Conference with ";
+ for(SipCall c: call.getParticipants()){
+ tmp += c.getContact().getmDisplayName() + " ";
+ }
+ ((TextView) convertView.findViewById(R.id.call_title)).setText(tmp);
+ }
+ ((TextView) convertView.findViewById(R.id.num_participants)).setText("" + call.getParticipants().size());
+ ((TextView) convertView.findViewById(R.id.call_status)).setText(call.getState());
+ convertView.setOnDragListener(dragListener);
+
+ convertView.setTag(call);
+ return convertView;
+ }
+
+ }
+
+ public static class DropActionsChoice extends DialogFragment {
+
+ ListAdapter mAdapter;
+ private Bundle args;
+
+ /**
+ * Create a new instance of CallActionsDFragment
+ */
+ public static DropActionsChoice newInstance() {
+ DropActionsChoice f = new DropActionsChoice();
+ return f;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Pick a style based on the num.
+ int style = DialogFragment.STYLE_NORMAL, theme = 0;
+ setStyle(style, theme);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ ListView rootView = new ListView(getActivity());
+
+ args = getArguments();
+ mAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, getResources().getStringArray(
+ R.array.drop_actions));
+
+ // ListView list = (ListView) rootView.findViewById(R.id.concurrent_calls);
+ rootView.setAdapter(mAdapter);
+ rootView.setOnItemClickListener(new OnItemClickListener() {
+
+ @Override
+ public void onItemClick(AdapterView<?> arg0, View arg1, int pos, long arg3) {
+ Intent in = new Intent();
+
+ in.putExtra("transfer", args.getParcelable("call_initial"));
+ in.putExtra("target", args.getParcelable("call_targeted"));
+
+ switch (pos) {
+ case 0: // Transfer
+ getTargetFragment().onActivityResult(REQUEST_TRANSFER, 0, in);
+ break;
+ case 1: // Conference
+ getTargetFragment().onActivityResult(REQUEST_CONF, 0, in);
+ break;
+ }
+ dismiss();
+
+ }
+ });
+
+ final AlertDialog a = new AlertDialog.Builder(getActivity()).setView(rootView).setTitle("Choose Action")
+ .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+ dismiss();
+ }
+ }).create();
+
+ return a;
+ }
}
}
diff --git a/src/com/savoirfairelinux/sflphone/fragments/ConferenceDFragment.java b/src/com/savoirfairelinux/sflphone/fragments/ConferenceDFragment.java
index 7fb6c9a..0316d33 100644
--- a/src/com/savoirfairelinux/sflphone/fragments/ConferenceDFragment.java
+++ b/src/com/savoirfairelinux/sflphone/fragments/ConferenceDFragment.java
@@ -67,8 +67,8 @@
Intent in = new Intent();
- in.putExtra("call_to_add", call_selected);
- in.putExtra("call_target", mAdapter.getItem(pos));
+ in.putExtra("transfer", call_selected);
+ in.putExtra("target", mAdapter.getItem(pos));
getTargetFragment().onActivityResult(getTargetRequestCode(), 0, in);
dismiss();
}
diff --git a/src/com/savoirfairelinux/sflphone/fragments/HomeFragment.java b/src/com/savoirfairelinux/sflphone/fragments/HomeFragment.java
index a5cc407..96cb3f8 100644
--- a/src/com/savoirfairelinux/sflphone/fragments/HomeFragment.java
+++ b/src/com/savoirfairelinux/sflphone/fragments/HomeFragment.java
@@ -149,7 +149,7 @@
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i(TAG, "onCreateView");
- View inflatedView = inflater.inflate(R.layout.frag_call_element, container, false);
+ View inflatedView = inflater.inflate(R.layout.frag_home, container, false);
access_calls = (Button) inflatedView.findViewById(R.id.access_callactivity);
diff --git a/src/com/savoirfairelinux/sflphone/model/Bubble.java b/src/com/savoirfairelinux/sflphone/model/Bubble.java
index f416169..b22e0bf 100644
--- a/src/com/savoirfairelinux/sflphone/model/Bubble.java
+++ b/src/com/savoirfairelinux/sflphone/model/Bubble.java
@@ -168,19 +168,6 @@
canvas.drawBitmap(circle, 0, 0, circlePaint);
circle_drawer.drawOval(new RectF(0, 0, internalBMP.getWidth(), internalBMP.getHeight()), circlePaint);
- int[] allpixels = new int[internalBMP.getHeight() * internalBMP.getWidth()];
-
- internalBMP.getPixels(allpixels, 0, internalBMP.getWidth(), 0, 0, internalBMP.getWidth(), internalBMP.getHeight());
-
- for (int i = 0; i < internalBMP.getHeight() * internalBMP.getWidth(); i++) {
-// Log.i("Bubble", "allpixels[i]:"+allpixels[i]);
- if (allpixels[i] == Color.BLACK) {
- Log.i("Bubble", "replacing color");
- allpixels[i] = 0xAA000000;
- }
- }
-
- internalBMP.setPixels(allpixels, 0, internalBMP.getWidth(), 0, 0, internalBMP.getWidth(), internalBMP.getHeight());
externalBMP = Bitmap.createBitmap((int) (getRadius() * 2), (int) (getRadius() * 2), Bitmap.Config.ARGB_8888);
Canvas canvasf = new Canvas(externalBMP);
@@ -194,6 +181,19 @@
fatality.setStyle(Paint.Style.FILL);
canvasf.drawOval(new RectF(0, 0, getRadius() * 2, getRadius() * 2), mPaintPath); // background with buttons
+
+ int[] allpixels = new int[internalBMP.getHeight() * internalBMP.getWidth()];
+
+ internalBMP.getPixels(allpixels, 0, internalBMP.getWidth(), 0, 0, internalBMP.getWidth(), internalBMP.getHeight());
+ for (int i = 0; i < internalBMP.getHeight() * internalBMP.getWidth(); i++) {
+ // Log.i("Bubble", "allpixels[i]:"+allpixels[i]);
+ if (allpixels[i] == Color.BLACK) {
+ Log.i("Bubble", "replacing color");
+ allpixels[i] = 0xAA000000;
+ }
+ }
+ internalBMP.setPixels(allpixels, 0, internalBMP.getWidth(), 0, 0, internalBMP.getWidth(), internalBMP.getHeight());
+
canvasf.drawBitmap(internalBMP, (float) (getRadius() - radius), (float) (getRadius() - radius), fatality);
}
diff --git a/src/com/savoirfairelinux/sflphone/model/BubbleModel.java b/src/com/savoirfairelinux/sflphone/model/BubbleModel.java
index 1a69796..2032e6e 100644
--- a/src/com/savoirfairelinux/sflphone/model/BubbleModel.java
+++ b/src/com/savoirfairelinux/sflphone/model/BubbleModel.java
@@ -185,12 +185,6 @@
public Bubble getBubble(SipCall call) {
for(Bubble b : bubbles){
- if(call == null){
- Log.e(TAG, "call null");
- }
- if(b.associated_call.getCallId() == null){
- Log.e(TAG, "id null");
- }
if(b.associated_call.getCallId().contentEquals(call.getCallId()))
return b;
}
diff --git a/src/com/savoirfairelinux/sflphone/model/BubblesView.java b/src/com/savoirfairelinux/sflphone/model/BubblesView.java
index 077f1bf..a29d8ab 100644
--- a/src/com/savoirfairelinux/sflphone/model/BubblesView.java
+++ b/src/com/savoirfairelinux/sflphone/model/BubblesView.java
@@ -267,16 +267,19 @@
for (int i = 0, n = bubbles.size(); i < n; i++) {
Bubble b = bubbles.get(i);
+ if(b.expanded){
+ continue;
+ }
canvas.drawBitmap(b.getBitmap(), null, b.getBounds(), null);
canvas.drawText(b.associated_call.getContact().getmDisplayName(), b.getPosX(),
- (float) (b.getPosY() - b.getRetractedRadius() * 1.5 * density), getNamePaint(b));
+ (float) (b.getPosY() - b.getRetractedRadius() * 1.2 * density), getNamePaint(b));
}
Bubble first_plan = getExpandedBubble();
if (first_plan != null) {
canvas.drawBitmap(first_plan.getBitmap(), null, first_plan.getBounds(), null);
canvas.drawText(first_plan.associated_call.getContact().getmDisplayName(), first_plan.getPosX(),
- (float) (first_plan.getPosY() - first_plan.getRetractedRadius() * 1.5 * density), getNamePaint(first_plan));
+ (float) (first_plan.getPosY() - first_plan.getRetractedRadius() * 1.2 * density), getNamePaint(first_plan));
canvas.drawText("Transfer", first_plan.getPosX(), (float) (first_plan.getPosY() + first_plan.getRetractedRadius() * 1.5
* density), getNamePaint(first_plan));
diff --git a/src/com/savoirfairelinux/sflphone/model/CallContact.java b/src/com/savoirfairelinux/sflphone/model/CallContact.java
index adfd61d..bc720a0 100644
--- a/src/com/savoirfairelinux/sflphone/model/CallContact.java
+++ b/src/com/savoirfairelinux/sflphone/model/CallContact.java
@@ -49,7 +49,7 @@
private CallContact(long cID, String displayName, long photoID, ArrayList<Phone> p, ArrayList<Phone> sip, String mail, boolean user) {
id = cID;
- mDisplayName = displayName.substring(0, displayName.length() > 10 ? 10 : displayName.length());
+ mDisplayName = displayName;
phones = p;
sip_phones = sip;
mEmail = mail;
diff --git a/src/com/savoirfairelinux/sflphone/model/Conference.java b/src/com/savoirfairelinux/sflphone/model/Conference.java
index 4418210..c242b4d 100644
--- a/src/com/savoirfairelinux/sflphone/model/Conference.java
+++ b/src/com/savoirfairelinux/sflphone/model/Conference.java
@@ -107,6 +107,28 @@
}
return null;
}
+
+ /**
+ * Compare conferences based on confID/participants
+ */
+ @Override
+ public boolean equals(Object c) {
+ if (c instanceof Conference) {
+ if(((Conference) c).id.contentEquals(id) && !id.contentEquals("-1")){
+ return true;
+ } else {
+ if(((Conference) c).id.contentEquals(id)){
+ for (int i = 0; i < participants.size(); ++i) {
+ if (!((Conference) c).contains(participants.get(i).getCallId()))
+ return false;
+ }
+ return true;
+ }
+ }
+ }
+ return false;
+
+ }
public boolean hasMultipleParticipants() {
return participants.size() > 1;
diff --git a/src/com/savoirfairelinux/sflphone/model/SipCall.java b/src/com/savoirfairelinux/sflphone/model/SipCall.java
index 3f38733..2d83e99 100644
--- a/src/com/savoirfairelinux/sflphone/model/SipCall.java
+++ b/src/com/savoirfairelinux/sflphone/model/SipCall.java
@@ -349,7 +349,7 @@
*/
@Override
public boolean equals(Object c) {
- if (c instanceof SipCall && ((SipCall) c).mCallID == mCallID) {
+ if (c instanceof SipCall && ((SipCall) c).mCallID.contentEquals((mCallID))) {
return true;
}
return false;
diff --git a/src/com/savoirfairelinux/sflphone/views/SwipeListViewTouchListener.java b/src/com/savoirfairelinux/sflphone/views/SwipeListViewTouchListener.java
new file mode 100644
index 0000000..96e65b7
--- /dev/null
+++ b/src/com/savoirfairelinux/sflphone/views/SwipeListViewTouchListener.java
@@ -0,0 +1,331 @@
+package com.savoirfairelinux.sflphone.views;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.graphics.Rect;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.ListView;
+
+public class SwipeListViewTouchListener implements View.OnTouchListener {
+ // Cached ViewConfiguration and system-wide constant values
+ private int mSlop;
+ private int mMinFlingVelocity;
+ private int mMaxFlingVelocity;
+ private long mAnimationTime;
+
+ // Fixed properties
+ private ListView mListView;
+ private OnSwipeCallback mCallback;
+ private int mViewWidth = 1; // 1 and not 0 to prevent dividing by zero
+ private boolean dismissLeft = true;
+ private boolean dismissRight = true;
+
+ // Transient properties
+ private List < PendingSwipeData > mPendingSwipes = new ArrayList < PendingSwipeData > ();
+ private int mDismissAnimationRefCount = 0;
+ private float mDownX;
+ private boolean mSwiping;
+ private VelocityTracker mVelocityTracker;
+ private int mDownPosition;
+ private View mDownView;
+ private boolean mPaused;
+
+ /**
+ * The callback interface used by {@link SwipeListViewTouchListener} to inform its client
+ * about a successful swipe of one or more list item positions.
+ */
+ public interface OnSwipeCallback {
+ /**
+ * Called when the user has swiped the list item to the left.
+ *
+ * @param listView The originating {@link ListView}.
+ * @param reverseSortedPositions An array of positions to dismiss, sorted in descending
+ * order for convenience.
+ */
+ void onSwipeLeft(ListView listView, int[] reverseSortedPositions);
+
+ void onSwipeRight(ListView listView, int[] reverseSortedPositions);
+ }
+
+ /**
+ * Constructs a new swipe-to-action touch listener for the given list view.
+ *
+ * @param listView The list view whose items should be dismissable.
+ * @param callback The callback to trigger when the user has indicated that she would like to
+ * dismiss one or more list items.
+ */
+ public SwipeListViewTouchListener(ListView listView, OnSwipeCallback callback) {
+ ViewConfiguration vc = ViewConfiguration.get(listView.getContext());
+ mSlop = vc.getScaledTouchSlop();
+ mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
+ mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity();
+ mAnimationTime = listView.getContext().getResources().getInteger(
+ android.R.integer.config_shortAnimTime);
+ mListView = listView;
+ mCallback = callback;
+ }
+
+ /**
+ * Constructs a new swipe-to-action touch listener for the given list view.
+ *
+ * @param listView The list view whose items should be dismissable.
+ * @param callback The callback to trigger when the user has indicated that she would like to
+ * dismiss one or more list items.
+ * @param dismissLeft set if the dismiss animation is up when the user swipe to the left
+ * @param dismissRight set if the dismiss animation is up when the user swipe to the right
+ * @see #SwipeListViewTouchListener(ListView, OnSwipeCallback, boolean, boolean)
+ */
+ public SwipeListViewTouchListener(ListView listView, OnSwipeCallback callback, boolean dismissLeft, boolean dismissRight) {
+ this(listView, callback);
+ this.dismissLeft = dismissLeft;
+ this.dismissRight = dismissRight;
+ }
+
+ /**
+ * Enables or disables (pauses or resumes) watching for swipe-to-dismiss gestures.
+ *
+ * @param enabled Whether or not to watch for gestures.
+ */
+ public void setEnabled(boolean enabled) {
+ mPaused = !enabled;
+ }
+
+ /**
+ * Returns an {@link android.widget.AbsListView.OnScrollListener} to be added to the
+ * {@link ListView} using
+ * {@link ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener)}.
+ * If a scroll listener is already assigned, the caller should still pass scroll changes
+ * through to this listener. This will ensure that this
+ * {@link SwipeListViewTouchListener} is paused during list view scrolling.</p>
+ *
+ * @see {@link SwipeListViewTouchListener}
+ */
+ public AbsListView.OnScrollListener makeScrollListener() {
+ return new AbsListView.OnScrollListener() {@
+ Override
+ public void onScrollStateChanged(AbsListView absListView, int scrollState) {
+ setEnabled(scrollState != AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
+ }
+
+ @
+ Override
+ public void onScroll(AbsListView absListView, int i, int i1, int i2) {}
+ };
+ }
+
+ @
+ Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ if (mViewWidth < 2) {
+ mViewWidth = mListView.getWidth();
+ }
+
+ switch (motionEvent.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ {
+ if (mPaused) {
+ return false;
+ }
+
+ // TODO: ensure this is a finger, and set a flag
+
+ // Find the child view that was touched (perform a hit test)
+ Rect rect = new Rect();
+ int childCount = mListView.getChildCount();
+ int[] listViewCoords = new int[2];
+ mListView.getLocationOnScreen(listViewCoords);
+ int x = (int) motionEvent.getRawX() - listViewCoords[0];
+ int y = (int) motionEvent.getRawY() - listViewCoords[1];
+ View child;
+ for (int i = 0; i < childCount; i++) {
+ child = mListView.getChildAt(i);
+ child.getHitRect(rect);
+ if (rect.contains(x, y)) {
+ mDownView = child;
+ break;
+ }
+ }
+
+ if (mDownView != null) {
+ mDownX = motionEvent.getRawX();
+ mDownPosition = mListView.getPositionForView(mDownView);
+
+ mVelocityTracker = VelocityTracker.obtain();
+ mVelocityTracker.addMovement(motionEvent);
+ }
+ view.onTouchEvent(motionEvent);
+ return true;
+ }
+
+ case MotionEvent.ACTION_UP:
+ {
+ if (mVelocityTracker == null) {
+ break;
+ }
+
+ float deltaX = motionEvent.getRawX() - mDownX;
+ mVelocityTracker.addMovement(motionEvent);
+ mVelocityTracker.computeCurrentVelocity(500); // 1000 by defaut but it was too much
+ float velocityX = Math.abs(mVelocityTracker.getXVelocity());
+ float velocityY = Math.abs(mVelocityTracker.getYVelocity());
+ boolean swipe = false;
+ boolean swipeRight = false;
+
+ if (Math.abs(deltaX) > mViewWidth / 2) {
+ swipe = true;
+ swipeRight = deltaX > 0;
+ } else if (mMinFlingVelocity <= velocityX && velocityX <= mMaxFlingVelocity && velocityY < velocityX) {
+ swipe = true;
+ swipeRight = mVelocityTracker.getXVelocity() > 0;
+ }
+ if (swipe) {
+ // sufficent swipe value
+ final View downView = mDownView; // mDownView gets null'd before animation ends
+ final int downPosition = mDownPosition;
+ final boolean toTheRight = swipeRight;
+ ++mDismissAnimationRefCount;
+ mDownView.animate()
+ .translationX(swipeRight ? mViewWidth : -mViewWidth)
+ .alpha(0)
+ .setDuration(mAnimationTime)
+ .setListener(new AnimatorListenerAdapter() {@
+ Override
+ public void onAnimationEnd(Animator animation) {
+ performSwipeAction(downView, downPosition, toTheRight, toTheRight ? dismissRight : dismissLeft);
+ }
+ });
+ } else {
+ // cancel
+ mDownView.animate()
+ .translationX(0)
+ .alpha(1)
+ .setDuration(mAnimationTime)
+ .setListener(null);
+ }
+ mVelocityTracker = null;
+ mDownX = 0;
+ mDownView = null;
+ mDownPosition = ListView.INVALID_POSITION;
+ mSwiping = false;
+ break;
+ }
+
+ case MotionEvent.ACTION_MOVE:
+ {
+ if (mVelocityTracker == null || mPaused) {
+ break;
+ }
+
+ mVelocityTracker.addMovement(motionEvent);
+ float deltaX = motionEvent.getRawX() - mDownX;
+ if (Math.abs(deltaX) > mSlop) {
+ mSwiping = true;
+ mListView.requestDisallowInterceptTouchEvent(true);
+
+ // Cancel ListView's touch (un-highlighting the item)
+ MotionEvent cancelEvent = MotionEvent.obtain(motionEvent);
+ cancelEvent.setAction(MotionEvent.ACTION_CANCEL |
+ (motionEvent.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
+ mListView.onTouchEvent(cancelEvent);
+ }
+
+ if (mSwiping) {
+ mDownView.setTranslationX(deltaX);
+ mDownView.setAlpha(Math.max(0f, Math.min(1f,
+ 1f - 2f * Math.abs(deltaX) / mViewWidth)));
+ return true;
+ }
+ break;
+ }
+ }
+ return false;
+ }
+
+ class PendingSwipeData implements Comparable < PendingSwipeData > {
+ public int position;
+ public View view;
+
+ public PendingSwipeData(int position, View view) {
+ this.position = position;
+ this.view = view;
+ }
+
+ @
+ Override
+ public int compareTo(PendingSwipeData other) {
+ // Sort by descending position
+ return other.position - position;
+ }
+ }
+
+ private void performSwipeAction(final View swipeView, final int swipePosition, boolean toTheRight, boolean dismiss) {
+ // Animate the dismissed list item to zero-height and fire the dismiss callback when
+ // all dismissed list item animations have completed. This triggers layout on each animation
+ // frame; in the future we may want to do something smarter and more performant.
+
+ final ViewGroup.LayoutParams lp = swipeView.getLayoutParams();
+ final int originalHeight = swipeView.getHeight();
+ final boolean swipeRight = toTheRight;
+
+ ValueAnimator animator;
+ if (dismiss)
+ animator = ValueAnimator.ofInt(originalHeight, 1).setDuration(mAnimationTime);
+ else
+ animator = ValueAnimator.ofInt(originalHeight, originalHeight - 1).setDuration(mAnimationTime);
+
+
+ animator.addListener(new AnimatorListenerAdapter() {@
+ Override
+ public void onAnimationEnd(Animator animation) {
+ --mDismissAnimationRefCount;
+ if (mDismissAnimationRefCount == 0) {
+ // No active animations, process all pending dismisses.
+ // Sort by descending position
+ Collections.sort(mPendingSwipes);
+
+ int[] swipePositions = new int[mPendingSwipes.size()];
+ for (int i = mPendingSwipes.size() - 1; i >= 0; i--) {
+ swipePositions[i] = mPendingSwipes.get(i).position;
+ }
+ if (swipeRight)
+ mCallback.onSwipeRight(mListView, swipePositions);
+ else
+ mCallback.onSwipeLeft(mListView, swipePositions);
+
+ ViewGroup.LayoutParams lp;
+ for (PendingSwipeData pendingDismiss: mPendingSwipes) {
+ // Reset view presentation
+ pendingDismiss.view.setAlpha(1f);
+ pendingDismiss.view.setTranslationX(0);
+ lp = pendingDismiss.view.getLayoutParams();
+ lp.height = originalHeight;
+ pendingDismiss.view.setLayoutParams(lp);
+ }
+
+ mPendingSwipes.clear();
+ }
+ }
+ });
+
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@
+ Override
+ public void onAnimationUpdate(ValueAnimator valueAnimator) {
+ lp.height = (Integer) valueAnimator.getAnimatedValue();
+ swipeView.setLayoutParams(lp);
+ }
+ });
+
+ mPendingSwipes.add(new PendingSwipeData(swipePosition, swipeView));
+ animator.start();
+ }
+}