diff --git a/libs/android-support-v13.jar b/libs/android-support-v13.jar index 821775632e0181046acb6628bfb541d7eef4bffa..e75351a50777951e96f0c379c0cf6940e8bba122 100644 Binary files a/libs/android-support-v13.jar and b/libs/android-support-v13.jar differ diff --git a/res/layout/activity_call_layout.xml b/res/layout/activity_call_layout.xml index d5e4f9a4b73d63bf85d15aaa3658189e9b0a3df4..90c4cdfd8d40dbf2bec0451cf3295e7c5d863e5d 100644 --- a/res/layout/activity_call_layout.xml +++ b/res/layout/activity_call_layout.xml @@ -36,12 +36,12 @@ as that of the covered work. android:layout_height="match_parent" > <FrameLayout - android:id="@+id/ongoingcall_pane" + android:id="@+id/calllist_pane" android:layout_width="match_parent" android:layout_height="match_parent" /> <FrameLayout - android:id="@+id/calllist_pane" + android:id="@+id/ongoingcall_pane" android:layout_width="match_parent" android:layout_height="match_parent" /> diff --git a/res/layout/frag_call.xml b/res/layout/frag_call.xml index ff158fec9b64ea8f8fcd6860a6d8522c40b750fb..a307fa83500bd088a07b33880abb59a5f4f69536 100644 --- a/res/layout/frag_call.xml +++ b/res/layout/frag_call.xml @@ -11,26 +11,4 @@ android:layout_alignParentTop="true" android:focusable="true" /> - <!-- <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_alignParentBottom="true" - android:orientation="horizontal" - android:weightSum="2" > - - <Button - android:id="@+id/add_bubble" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:text="Add Bubble" /> - - <Button - android:id="@+id/remove_bubble" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:text="Remove Bubble" /> - </LinearLayout> --> - </RelativeLayout> \ No newline at end of file diff --git a/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java b/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java index 5b3b187ca728b6d10604b7dab117ae2599747d71..0e1c82237738954a796e74c7bef52240fa20b1c3 100644 --- a/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java +++ b/src/com/savoirfairelinux/sflphone/client/SFLPhoneHomeActivity.java @@ -31,8 +31,6 @@ */ package com.savoirfairelinux.sflphone.client; -import java.util.Random; - import android.app.ActionBar; import android.app.Activity; import android.app.Fragment; @@ -65,7 +63,6 @@ import com.savoirfairelinux.sflphone.fragments.HistoryFragment; import com.savoirfairelinux.sflphone.fragments.MenuFragment; import com.savoirfairelinux.sflphone.interfaces.CallInterface; import com.savoirfairelinux.sflphone.model.CallContact; -import com.savoirfairelinux.sflphone.model.CallContact.ContactBuilder; import com.savoirfairelinux.sflphone.model.SipCall; import com.savoirfairelinux.sflphone.service.CallManagerCallBack; import com.savoirfairelinux.sflphone.service.ISipService; @@ -73,385 +70,387 @@ import com.savoirfairelinux.sflphone.service.SipService; import com.savoirfairelinux.sflphone.views.CustomSlidingDrawer; public class SFLPhoneHomeActivity extends Activity implements ActionBar.TabListener, DialingFragment.Callbacks, ContactListFragment.Callbacks, - CallElementListFragment.Callbacks, HistoryFragment.Callbacks, CallInterface { - - SectionsPagerAdapter mSectionsPagerAdapter = null; - static final String TAG = "SFLPhoneHomeActivity"; - - private ContactListFragment mContactsFragment = null; - private DialingFragment mDialingFragment = null; - private CallElementListFragment mCallElementList = null; - private HistoryFragment mHistorySectionFragment = null; - - Fragment fMenu; - - private boolean mBound = false; - private ISipService service; - - private CharSequence mDrawerTitle; - private CharSequence mTitle; - - private static final int REQUEST_CODE_PREFERENCES = 1; - private static final int REQUEST_CODE_CALL = 2; - - private static final int ACTION_BAR_TAB_DIALING = 0; - private static final int ACTION_BAR_TAB_CALL = 1; - private static final int ACTION_BAR_TAB_HISTORY = 2; - - RelativeLayout mSliderButton; - CustomSlidingDrawer mDrawer; - private DrawerLayout mDrawerLayout; - private ActionBarDrawerToggle mDrawerToggle; - /** - * The {@link ViewPager} that will host the section contents. - */ - ViewPager mViewPager; - - CallReceiver receiver; - - final private int[] icon_res_id = { R.drawable.ic_tab_call, R.drawable.ic_tab_call, R.drawable.ic_tab_history }; - - // public SFLPhoneHome extends Activity implements ActionBar.TabListener, OnClickListener - - /* called before activity is killed, e.g. rotation */ - @Override - protected void onSaveInstanceState(Bundle bundle) { - super.onSaveInstanceState(bundle); - for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) { - try { - getFragmentManager().putFragment(bundle, mSectionsPagerAdapter.getClassName(i), mSectionsPagerAdapter.getItem(i)); - } catch (IllegalStateException e) { - Log.e(TAG, "fragment=" + mSectionsPagerAdapter.getItem(i)); - } - } - - getFragmentManager().putFragment(bundle, "ContactsListFragment", mContactsFragment); - Log.w(TAG, "onSaveInstanceState()"); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - receiver = new CallReceiver(this); - - String libraryPath = getApplicationInfo().dataDir + "/lib"; - Log.i(TAG, libraryPath); - - // Bind to LocalService - if (!mBound) { - Log.i(TAG, "onStart: Binding service..."); - Intent intent = new Intent(this, SipService.class); - bindService(intent, mConnection, Context.BIND_AUTO_CREATE); - } - - setContentView(R.layout.activity_sflphone_home); - - if (mSectionsPagerAdapter == null) { - mSectionsPagerAdapter = new SectionsPagerAdapter(this, getFragmentManager()); - } - - /* getFragment(Bundle, String) */ - if (savedInstanceState != null) { - Log.w(TAG, "Activity restarted, recreating PagerAdapter..."); - /* getFragment (Bundle bundle, String key) */ - mDialingFragment = (DialingFragment) getFragmentManager().getFragment(savedInstanceState, - mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_DIALING)); - mCallElementList = (CallElementListFragment) getFragmentManager().getFragment(savedInstanceState, - mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_CALL)); - mHistorySectionFragment = (HistoryFragment) getFragmentManager().getFragment(savedInstanceState, - mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_HISTORY)); - } - - if (mDialingFragment == null) { - mDialingFragment = new DialingFragment(); - Log.w(TAG, "Recreated mDialingFragment=" + mDialingFragment); - } - - if (mContactsFragment == null) { - mContactsFragment = new ContactListFragment(); - Log.w(TAG, "Recreated mContactListFragment=" + mContactsFragment); - getFragmentManager().beginTransaction().replace(R.id.contacts_frame, mContactsFragment).commit(); - } - if (mCallElementList == null) { - mCallElementList = new CallElementListFragment(); - Log.w(TAG, "Recreated mCallElementList=" + mCallElementList); - } - if (mHistorySectionFragment == null) { - mHistorySectionFragment = new HistoryFragment(); - Log.w(TAG, "Recreated mHistorySectionFragment=" + mHistorySectionFragment); - } - - mDrawer = (CustomSlidingDrawer) findViewById(R.id.custom_sliding_drawer); - - mContactsFragment.setHandleView((RelativeLayout) findViewById(R.id.slider_button)); - - mDrawer.setmTrackHandle(findViewById(R.id.handle_title)); - - final ActionBar actionBar = getActionBar(); - actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); - - // Set up the ViewPager with the sections adapter. - mViewPager = (ViewPager) findViewById(R.id.pager); - mViewPager.setAdapter(mSectionsPagerAdapter); - - mTitle = mDrawerTitle = getTitle(); - mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); - // mDrawerList = (ListView) findViewById(R.id.left_drawer); - - // set a custom shadow that overlays the main content when the drawer opens - mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); - // set up the drawer's list view with items and click listener - // mDrawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, mPlanetTitles)); - // mDrawerList.setOnItemClickListener(new DrawerItemClickListener()); - - getActionBar().setDisplayHomeAsUpEnabled(true); - getActionBar().setHomeButtonEnabled(true); - - mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */ - mDrawerLayout, /* DrawerLayout object */ - R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */ - R.string.drawer_open, /* "open drawer" description for accessibility */ - R.string.drawer_close /* "close drawer" description for accessibility */ - ) { - public void onDrawerClosed(View view) { - getActionBar().setTitle(mTitle); - invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu() - } - - public void onDrawerOpened(View drawerView) { - getActionBar().setTitle(mDrawerTitle); - invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu() - } - }; - - mDrawerLayout.setDrawerListener(mDrawerToggle); - - mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { - @Override - public void onPageSelected(int position) { - actionBar.setSelectedNavigationItem(position); - } - }); - - // For each of the sections in the app, add a tab to the action bar. - for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) { - - actionBar.addTab(actionBar.newTab().setIcon(icon_res_id[i]).setText(mSectionsPagerAdapter.getPageTitle(i)).setTabListener(this)); - } - - actionBar.setSelectedNavigationItem(ACTION_BAR_TAB_CALL); - - fMenu = new MenuFragment(); - getFragmentManager().beginTransaction().replace(R.id.left_drawer, fMenu).commit(); - } - - @Override - protected void onStart() { - Log.i(TAG, "onStart"); - super.onStart(); - } - - /* user gets back to the activity, e.g. through task manager */ - @Override - protected void onRestart() { - super.onRestart(); - } - - /* activity gets back to the foreground and user input */ - @Override - protected void onResume() { - Log.i(TAG, "onResume"); - IntentFilter intentFilter = new IntentFilter(); - intentFilter.addAction(CallManagerCallBack.INCOMING_CALL); - intentFilter.addAction(CallManagerCallBack.INCOMING_TEXT); - intentFilter.addAction(CallManagerCallBack.CALL_STATE_CHANGED); - registerReceiver(receiver, intentFilter); - super.onResume(); - } - - /* activity no more in foreground */ - @Override - protected void onPause() { - super.onPause(); - unregisterReceiver(receiver); - } - - /* activity is no longer visible */ - @Override - protected void onStop() { - super.onStop(); - } - - /* activity finishes itself or is being killed by the system */ - @Override - protected void onDestroy() { - /* stop the service, if no other bound user, no need to check if it is running */ - if (mBound) { - Log.i(TAG, "onDestroy: Unbinding service..."); - unbindService(mConnection); - mBound = false; - } - - super.onDestroy(); - } - - public void launchCallActivity(SipCall infos, String action) { - Log.i(TAG, "Launch Call Activity"); - Bundle bundle = new Bundle(); - bundle.putString("action", action); - bundle.putParcelable("CallInfo", infos); - Intent intent = new Intent().setClass(this, CallActivity.class); - intent.putExtras(bundle); - startActivityForResult(intent, REQUEST_CODE_CALL); - } - - /** Defines callbacks for service binding, passed to bindService() */ - private ServiceConnection mConnection = new ServiceConnection() { - - @Override - public void onServiceConnected(ComponentName className, IBinder binder) { - service = ISipService.Stub.asInterface(binder); - - mBound = true; - mCallElementList.onServiceSipBinded(service); - mHistorySectionFragment.onServiceSipBinded(service); - mDialingFragment.onServiceSipBinded(service); - Log.d(TAG, "Service connected service=" + service); - - } - - @Override - public void onServiceDisconnected(ComponentName arg0) { - - mBound = false; - Log.d(TAG, "Service disconnected service=" + service); - } - }; - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - Log.i(TAG, "onOptionsItemSelected " + item.getItemId()); - - if (mDrawerToggle.onOptionsItemSelected(item)) { - return true; - } - - return super.onOptionsItemSelected(item); - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - - switch (requestCode) { - case REQUEST_CODE_PREFERENCES: - mCallElementList.onServiceSipBinded(service); - break; - case REQUEST_CODE_CALL: - - break; - } - - } - - // @Override - // public boolean onCreateOptionsMenu(Menu menu) { - // getMenuInflater().inflate(R.menu.activity_sflphone_home, menu); - // return true; - // } - - @Override - public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { - } - - @Override - public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { - // When the given tab is selected, switch to the corresponding page in the ViewPager. - mViewPager.setCurrentItem(tab.getPosition()); - } - - @Override - public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { - // Log.d(TAG, "onTabReselected"); - } - - @Override - public void onCallSelected(SipCall c) { - // launchCallActivity(c.mCallInfo); - - } - - @Override - public ISipService getService() { - return service; - } - - /** - * Interface implemented to handle incoming events - */ - @Override - public void incomingCall(Intent call) { - Toast.makeText(this, "New Call incoming", Toast.LENGTH_LONG).show(); - SipCall infos = call.getParcelableExtra("newcall"); - - mCallElementList.addCall(infos); - - launchCallActivity(infos, CallManagerCallBack.INCOMING_CALL); - - } - - @Override - public void callStateChanged(Intent callState) { - Bundle b = callState.getBundleExtra("com.savoirfairelinux.sflphone.service.newstate"); - String cID = b.getString("CallID"); - String state = b.getString("State"); - Log.i(TAG, "callStateChanged" + cID + " " + state); - mCallElementList.updateCall(cID, state); - - } - - @Override - public void incomingText(Intent msg) { - Bundle b = msg.getBundleExtra("com.savoirfairelinux.sflphone.service.newtext"); - b.getString("CallID"); - String from = b.getString("From"); - String mess = b.getString("Msg"); - Toast.makeText(getApplicationContext(), "text from " + from + " : " + mess, Toast.LENGTH_LONG).show(); - } - - @Override - public void onContactSelected(CallContact c) { - - SipCall.SipCallBuilder callBuilder = SipCall.SipCallBuilder.getInstance(); - try { - callBuilder.startCallCreation().setAccountID(service.getAccountList().get(1).toString()).setCallType(SipCall.state.CALL_TYPE_OUTGOING); - } catch (RemoteException e1) { - Log.e(TAG,e1.toString()); - } - callBuilder.addContact(c); - - try { - launchCallActivity(callBuilder.build(), "call"); - } catch (Exception e) { - Log.e(TAG, e.toString()); - } - - } - - @Override - public void onCallDialed(String accountID, String to) { - - SipCall.SipCallBuilder callBuilder = SipCall.SipCallBuilder.getInstance(); - callBuilder.startCallCreation().setAccountID(accountID).setCallType(SipCall.state.CALL_TYPE_OUTGOING); - callBuilder.addContact(CallContact.ContactBuilder.buildUnknownContact(to)); - - try { - launchCallActivity(callBuilder.build(), "call"); - } catch (Exception e) { - Log.e(TAG, e.toString()); - } - - } +CallElementListFragment.Callbacks, HistoryFragment.Callbacks, CallInterface { + + SectionsPagerAdapter mSectionsPagerAdapter = null; + static final String TAG = "SFLPhoneHomeActivity"; + + private ContactListFragment mContactsFragment = null; + private DialingFragment mDialingFragment = null; + private CallElementListFragment mCallElementList = null; + private HistoryFragment mHistorySectionFragment = null; + + Fragment fMenu; + + private boolean mBound = false; + private ISipService service; + + private CharSequence mDrawerTitle; + private CharSequence mTitle; + + private static final int REQUEST_CODE_PREFERENCES = 1; + private static final int REQUEST_CODE_CALL = 2; + + private static final int ACTION_BAR_TAB_DIALING = 0; + private static final int ACTION_BAR_TAB_CALL = 1; + private static final int ACTION_BAR_TAB_HISTORY = 2; + + RelativeLayout mSliderButton; + CustomSlidingDrawer mDrawer; + private DrawerLayout mDrawerLayout; + private ActionBarDrawerToggle mDrawerToggle; + /** + * The {@link ViewPager} that will host the section contents. + */ + ViewPager mViewPager; + + CallReceiver receiver; + + final private int[] icon_res_id = { R.drawable.ic_tab_call, R.drawable.ic_tab_call, R.drawable.ic_tab_history }; + + // public SFLPhoneHome extends Activity implements ActionBar.TabListener, OnClickListener + + /* called before activity is killed, e.g. rotation */ + @Override + protected void onSaveInstanceState(Bundle bundle) { + super.onSaveInstanceState(bundle); + for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) { + try { + getFragmentManager().putFragment(bundle, mSectionsPagerAdapter.getClassName(i), mSectionsPagerAdapter.getItem(i)); + } catch (IllegalStateException e) { + Log.e(TAG, "fragment=" + mSectionsPagerAdapter.getItem(i)); + } + } + + getFragmentManager().putFragment(bundle, "ContactsListFragment", mContactsFragment); + Log.w(TAG, "onSaveInstanceState()"); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + receiver = new CallReceiver(this); + + String libraryPath = getApplicationInfo().dataDir + "/lib"; + Log.i(TAG, libraryPath); + + // Bind to LocalService + if (!mBound) { + Log.i(TAG, "onStart: Binding service..."); + Intent intent = new Intent(this, SipService.class); + bindService(intent, mConnection, Context.BIND_AUTO_CREATE); + } + + setContentView(R.layout.activity_sflphone_home); + + if (mSectionsPagerAdapter == null) { + mSectionsPagerAdapter = new SectionsPagerAdapter(this, getFragmentManager()); + } + + /* getFragment(Bundle, String) */ + if (savedInstanceState != null) { + Log.w(TAG, "Activity restarted, recreating PagerAdapter..."); + /* getFragment (Bundle bundle, String key) */ + mDialingFragment = (DialingFragment) getFragmentManager().getFragment(savedInstanceState, + mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_DIALING)); + mCallElementList = (CallElementListFragment) getFragmentManager().getFragment(savedInstanceState, + mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_CALL)); + mHistorySectionFragment = (HistoryFragment) getFragmentManager().getFragment(savedInstanceState, + mSectionsPagerAdapter.getClassName(ACTION_BAR_TAB_HISTORY)); + } + + if (mDialingFragment == null) { + mDialingFragment = new DialingFragment(); + Log.w(TAG, "Recreated mDialingFragment=" + mDialingFragment); + } + + if (mContactsFragment == null) { + mContactsFragment = new ContactListFragment(); + Log.w(TAG, "Recreated mContactListFragment=" + mContactsFragment); + getFragmentManager().beginTransaction().replace(R.id.contacts_frame, mContactsFragment).commit(); + } + if (mCallElementList == null) { + mCallElementList = new CallElementListFragment(); + Log.w(TAG, "Recreated mCallElementList=" + mCallElementList); + } + if (mHistorySectionFragment == null) { + mHistorySectionFragment = new HistoryFragment(); + Log.w(TAG, "Recreated mHistorySectionFragment=" + mHistorySectionFragment); + } + + mDrawer = (CustomSlidingDrawer) findViewById(R.id.custom_sliding_drawer); + + mContactsFragment.setHandleView((RelativeLayout) findViewById(R.id.slider_button)); + + mDrawer.setmTrackHandle(findViewById(R.id.handle_title)); + + final ActionBar actionBar = getActionBar(); + actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); + + // Set up the ViewPager with the sections adapter. + mViewPager = (ViewPager) findViewById(R.id.pager); + mViewPager.setAdapter(mSectionsPagerAdapter); + + mTitle = mDrawerTitle = getTitle(); + mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); + // mDrawerList = (ListView) findViewById(R.id.left_drawer); + + // set a custom shadow that overlays the main content when the drawer opens + mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); + // set up the drawer's list view with items and click listener + // mDrawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, mPlanetTitles)); + // mDrawerList.setOnItemClickListener(new DrawerItemClickListener()); + + getActionBar().setDisplayHomeAsUpEnabled(true); + getActionBar().setHomeButtonEnabled(true); + + mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */ + mDrawerLayout, /* DrawerLayout object */ + R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */ + R.string.drawer_open, /* "open drawer" description for accessibility */ + R.string.drawer_close /* "close drawer" description for accessibility */ + ) { + @Override + public void onDrawerClosed(View view) { + getActionBar().setTitle(mTitle); + invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu() + } + + @Override + public void onDrawerOpened(View drawerView) { + getActionBar().setTitle(mDrawerTitle); + invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu() + } + }; + + mDrawerLayout.setDrawerListener(mDrawerToggle); + + mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { + @Override + public void onPageSelected(int position) { + actionBar.setSelectedNavigationItem(position); + } + }); + + // For each of the sections in the app, add a tab to the action bar. + for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) { + + actionBar.addTab(actionBar.newTab().setIcon(icon_res_id[i]).setText(mSectionsPagerAdapter.getPageTitle(i)).setTabListener(this)); + } + + actionBar.setSelectedNavigationItem(ACTION_BAR_TAB_CALL); + + fMenu = new MenuFragment(); + getFragmentManager().beginTransaction().replace(R.id.left_drawer, fMenu).commit(); + } + + @Override + protected void onStart() { + Log.i(TAG, "onStart"); + super.onStart(); + } + + /* user gets back to the activity, e.g. through task manager */ + @Override + protected void onRestart() { + super.onRestart(); + } + + /* activity gets back to the foreground and user input */ + @Override + protected void onResume() { + Log.i(TAG, "onResume"); + IntentFilter intentFilter = new IntentFilter(); + intentFilter.addAction(CallManagerCallBack.INCOMING_CALL); + intentFilter.addAction(CallManagerCallBack.INCOMING_TEXT); + intentFilter.addAction(CallManagerCallBack.CALL_STATE_CHANGED); + registerReceiver(receiver, intentFilter); + super.onResume(); + } + + /* activity no more in foreground */ + @Override + protected void onPause() { + super.onPause(); + unregisterReceiver(receiver); + } + + /* activity is no longer visible */ + @Override + protected void onStop() { + super.onStop(); + } + + /* activity finishes itself or is being killed by the system */ + @Override + protected void onDestroy() { + /* stop the service, if no other bound user, no need to check if it is running */ + if (mBound) { + Log.i(TAG, "onDestroy: Unbinding service..."); + unbindService(mConnection); + mBound = false; + } + + super.onDestroy(); + } + + public void launchCallActivity(SipCall infos, String action) { + Log.i(TAG, "Launch Call Activity"); + Bundle bundle = new Bundle(); + bundle.putString("action", action); + bundle.putParcelable("CallInfo", infos); + Intent intent = new Intent().setClass(this, CallActivity.class); + intent.putExtras(bundle); + startActivityForResult(intent, REQUEST_CODE_CALL); + } + + /** Defines callbacks for service binding, passed to bindService() */ + private ServiceConnection mConnection = new ServiceConnection() { + + @Override + public void onServiceConnected(ComponentName className, IBinder binder) { + service = ISipService.Stub.asInterface(binder); + + mBound = true; + mCallElementList.onServiceSipBinded(service); + mHistorySectionFragment.onServiceSipBinded(service); + mDialingFragment.onServiceSipBinded(service); + Log.d(TAG, "Service connected service=" + service); + + } + + @Override + public void onServiceDisconnected(ComponentName arg0) { + + mBound = false; + Log.d(TAG, "Service disconnected service=" + service); + } + }; + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + Log.i(TAG, "onOptionsItemSelected " + item.getItemId()); + + if (mDrawerToggle.onOptionsItemSelected(item)) { + return true; + } + + return super.onOptionsItemSelected(item); + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + switch (requestCode) { + case REQUEST_CODE_PREFERENCES: + mCallElementList.onServiceSipBinded(service); + break; + case REQUEST_CODE_CALL: + + break; + } + + } + + // @Override + // public boolean onCreateOptionsMenu(Menu menu) { + // getMenuInflater().inflate(R.menu.activity_sflphone_home, menu); + // return true; + // } + + @Override + public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { + } + + @Override + public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { + // When the given tab is selected, switch to the corresponding page in the ViewPager. + mViewPager.setCurrentItem(tab.getPosition()); + } + + @Override + public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { + // Log.d(TAG, "onTabReselected"); + } + + @Override + public void onCallSelected(SipCall c) { + // launchCallActivity(c.mCallInfo); + + } + + @Override + public ISipService getService() { + return service; + } + + /** + * Interface implemented to handle incoming events + */ + @Override + public void incomingCall(Intent call) { + Toast.makeText(this, "New Call incoming", Toast.LENGTH_LONG).show(); + SipCall infos = call.getParcelableExtra("newcall"); + + mCallElementList.addCall(infos); + + launchCallActivity(infos, CallManagerCallBack.INCOMING_CALL); + + } + + @Override + public void callStateChanged(Intent callState) { + Bundle b = callState.getBundleExtra("com.savoirfairelinux.sflphone.service.newstate"); + String cID = b.getString("CallID"); + String state = b.getString("State"); + Log.i(TAG, "callStateChanged" + cID + " " + state); + mCallElementList.updateCall(cID, state); + + } + + @Override + public void incomingText(Intent msg) { + Bundle b = msg.getBundleExtra("com.savoirfairelinux.sflphone.service.newtext"); + b.getString("CallID"); + String from = b.getString("From"); + String mess = b.getString("Msg"); + Toast.makeText(getApplicationContext(), "text from " + from + " : " + mess, Toast.LENGTH_LONG).show(); + } + + @Override + public void onContactSelected(CallContact c) { + + SipCall.SipCallBuilder callBuilder = SipCall.SipCallBuilder.getInstance(); + try { + callBuilder.startCallCreation().setAccountID(service.getAccountList().get(0).toString()).setCallType(SipCall.state.CALL_TYPE_OUTGOING); + } catch (RemoteException e1) { + Log.e(TAG,e1.toString()); + } + callBuilder.addContact(c); + + try { + launchCallActivity(callBuilder.build(), "call"); + } catch (Exception e) { + Log.e(TAG, e.toString()); + } + + } + + @Override + public void onCallDialed(String accountID, String to) { + + SipCall.SipCallBuilder callBuilder = SipCall.SipCallBuilder.getInstance(); + callBuilder.startCallCreation().setAccountID(accountID).setCallType(SipCall.state.CALL_TYPE_OUTGOING); + callBuilder.addContact(CallContact.ContactBuilder.buildUnknownContact(to)); + + try { + launchCallActivity(callBuilder.build(), "call"); + } catch (Exception e) { + Log.e(TAG, e.toString()); + } + + } } diff --git a/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java b/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java index b9ee971078b4468936665119cde936e8e9b80a8a..35f0b11444c37013de1cb4a9e408ae7488a56198 100644 --- a/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java +++ b/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java @@ -36,6 +36,7 @@ import java.util.HashMap; import android.app.Activity; import android.app.Fragment; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.PointF; import android.os.Bundle; import android.os.RemoteException; @@ -54,264 +55,289 @@ import com.savoirfairelinux.sflphone.model.BubbleModel; import com.savoirfairelinux.sflphone.model.BubblesView; import com.savoirfairelinux.sflphone.model.CallContact; import com.savoirfairelinux.sflphone.model.SipCall; -import com.savoirfairelinux.sflphone.service.CallManagerCallBack; import com.savoirfairelinux.sflphone.service.ISipService; public class CallFragment extends Fragment { - static final String TAG = "CallFragment"; - private SipCall mCall; + static final String TAG = "CallFragment"; - private BubblesView view; - private BubbleModel model; - private PointF screenCenter; - private DisplayMetrics metrics; + static final float BUBBLE_SIZE = 100; - private Callbacks mCallbacks = sDummyCallbacks; + private SipCall mCall; - private HashMap<CallContact, Bubble> contacts = new HashMap<CallContact, Bubble>(); + private BubblesView view; + private BubbleModel model; + private PointF screenCenter; + private DisplayMetrics metrics; - private TextView contact_name_txt; + private Callbacks mCallbacks = sDummyCallbacks; - CallContact myself = CallContact.ContactBuilder.buildUserContact("Me"); + private HashMap<CallContact, Bubble> contacts = new HashMap<CallContact, Bubble>(); - @Override - public void onCreate(Bundle savedBundle) { - super.onCreate(savedBundle); - model = new BubbleModel(getResources().getDisplayMetrics().density); - metrics = getResources().getDisplayMetrics(); - screenCenter = new PointF(metrics.widthPixels / 2, metrics.heightPixels / 3); + private TextView contact_name_txt; - Bundle b = getArguments(); + private CallContact myself = CallContact.ContactBuilder.buildUserContact("Me"); - mCall = b.getParcelable("CallInfo"); - } + private Bitmap hangup_icon; + private Bitmap call_icon; - /** - * A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity. - */ - private static Callbacks sDummyCallbacks = new Callbacks() { + @Override + public void onCreate(Bundle savedBundle) { + super.onCreate(savedBundle); + model = new BubbleModel(getResources().getDisplayMetrics().density); + metrics = getResources().getDisplayMetrics(); + screenCenter = new PointF(metrics.widthPixels / 2, metrics.heightPixels / 3); - @Override - public void onSendMessage(SipCall call, String msg) { + Bundle b = getArguments(); - } + mCall = b.getParcelable("CallInfo"); + //mCall. + } - @Override - public void callContact(SipCall call) { - } + /** + * A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity. + */ + private static Callbacks sDummyCallbacks = new Callbacks() { + @Override + public void onSendMessage(SipCall call, String msg) { + } - @Override - public void onCallAccepted(SipCall call) { - // TODO Auto-generated method stub + @Override + public void callContact(SipCall call) { + } - } + @Override + public void onCallAccepted(SipCall call) { + } - @Override - public void onCallRejected(SipCall call) { - // TODO Auto-generated method stub + @Override + public void onCallRejected(SipCall call) { + } - } + @Override + public void onCallEnded(SipCall call) { + } - @Override - public void onCallEnded(SipCall call) { - // TODO Auto-generated method stub + @Override + public void onCallSuspended(SipCall call) { + } - } + @Override + public void onCallResumed(SipCall call) { + } - @Override - public void onCallSuspended(SipCall call) { - // TODO Auto-generated method stub + @Override + public void onCalltransfered(SipCall call, String to) { + } - } + @Override + public void onRecordCall(SipCall call) { + } - @Override - public void onCallResumed(SipCall call) { - // TODO Auto-generated method stub + @Override + public ISipService getService() { + return null; + } + }; - } + /** + * The Activity calling this fragment has to implement this interface + * + */ + public interface Callbacks { - @Override - public void onCalltransfered(SipCall call, String to) { - // TODO Auto-generated method stub + public ISipService getService(); - } + public void callContact(SipCall call); - @Override - public void onRecordCall(SipCall call) { - // TODO Auto-generated method stub + public void onCallAccepted(SipCall call); - } + public void onCallRejected(SipCall call); - @Override - public ISipService getService() { - // TODO Auto-generated method stub - return null; - } - }; + public void onCallEnded(SipCall call); - /** - * The Activity calling this fragment has to implement this interface - * - */ - public interface Callbacks { + public void onCallSuspended(SipCall call); - public ISipService getService(); + public void onCallResumed(SipCall call); - public void callContact(SipCall call); - - public void onCallAccepted(SipCall call); - - public void onCallRejected(SipCall call); - - public void onCallEnded(SipCall call); - - public void onCallSuspended(SipCall call); - - public void onCallResumed(SipCall call); - - public void onCalltransfered(SipCall call, String to); - - public void onRecordCall(SipCall call); - - public void onSendMessage(SipCall call, String msg); - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - - if (!(activity instanceof Callbacks)) { - throw new IllegalStateException("Activity must implement fragment's callbacks."); - } - - mCallbacks = (Callbacks) activity; - } - - @Override - public void onDetach() { - super.onDetach(); - mCallbacks = sDummyCallbacks; - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.frag_call, container, false); - - view = (BubblesView) rootView.findViewById(R.id.main_view); - view.setModel(model); - - Log.i(TAG, "Starting fragment for call " + mCall.getCallId()); - - mCall.printCallInfo(); - if (mCall.isRinging()) { - initOutGoingCallDisplay(); - } - if (mCall.isIncoming() && mCall.isRinging()) { - initIncomingCallDisplay(); - } - try { - if (mCall.isOutGoing() && mCallbacks.getService().getCall(mCall.getCallId()) == null) { - mCallbacks.getService().placeCall(mCall); - initOutGoingCallDisplay(); - } else if(mCall.isOutGoing() && mCall.isRinging()){ - initOutGoingCallDisplay(); - } - } catch (RemoteException e) { - Log.e(TAG, e.toString()); - } - - if(mCall.isOngoing()){ - initNormalStateDisplay(); - } - - return rootView; - } - - private void initNormalStateDisplay() { - Log.i(TAG, "Start normal display"); - // TODO off-thread image loading - Bubble contact_bubble, me; - if (mCall.getContacts().get(0).getPhoto_id() > 0) { - Bitmap photo = ContactPictureLoader.loadContactPhoto(getActivity().getContentResolver(), mCall.getContacts().get(0).getId()); - contact_bubble = new Bubble(getActivity(), screenCenter.x, screenCenter.y, 150, photo); - } else { - contact_bubble = new Bubble(getActivity(), screenCenter.x, screenCenter.y / 2 , 150, R.drawable.ic_contact_picture); - } - - me = new Bubble(getActivity(), screenCenter.x, screenCenter.y * 3 / 2, 150, R.drawable.ic_contact_picture); - - model.attractors.clear(); - model.attractors.add(new Attractor(new PointF(metrics.widthPixels / 2, metrics.heightPixels * .8f), new Attractor.Callback() { - @Override - public void onBubbleSucked(Bubble b) { - Log.w(TAG, "Bubble sucked ! "); - mCallbacks.onCallEnded(mCall); - } - })); - - contact_bubble.contact = mCall.getContacts().get(0); - me.contact = myself; - model.listBubbles.add(contact_bubble); - model.listBubbles.add(me); - contacts.put(mCall.getContacts().get(0), contact_bubble); - contacts.put(myself, me); - - } - - private void initIncomingCallDisplay() { - Log.i(TAG, "Start incoming display"); - model.attractors.clear(); - model.attractors.add(new Attractor(new PointF(3 * metrics.widthPixels / 4, metrics.heightPixels / 4), new Attractor.Callback() { - @Override - public void onBubbleSucked(Bubble b) { - mCallbacks.onCallAccepted(mCall); - } - })); - model.attractors.add(new Attractor(new PointF(metrics.widthPixels / 4, metrics.heightPixels / 4), new Attractor.Callback() { - @Override - public void onBubbleSucked(Bubble b) { - mCallbacks.onCallRejected(mCall); - } - })); - } - - private void initOutGoingCallDisplay() { - Log.i(TAG, "Start outgoing display"); - // TODO off-thread image loading - Bubble contact_bubble; - if (mCall.getContacts().get(0).getPhoto_id() > 0) { - Bitmap photo = ContactPictureLoader.loadContactPhoto(getActivity().getContentResolver(), mCall.getContacts().get(0).getId()); - contact_bubble = new Bubble(getActivity(), screenCenter.x, screenCenter.y, 150, photo); - } else { - contact_bubble = new Bubble(getActivity(), screenCenter.x, screenCenter.y, 150, R.drawable.ic_contact_picture); - } - - model.attractors.clear(); - model.attractors.add(new Attractor(new PointF(metrics.widthPixels / 2, metrics.heightPixels * .8f), new Attractor.Callback() { - @Override - public void onBubbleSucked(Bubble b) { - Log.w(TAG, "Bubble sucked ! "); - mCallbacks.onCallEnded(mCall); - } - })); - - contact_bubble.contact = mCall.getContacts().get(0); - model.listBubbles.add(contact_bubble); - contacts.put(mCall.getContacts().get(0), contact_bubble); - } - - public void changeCallState(String callID, String newState) { - - Log.w(TAG, "Changing call state of "+callID); - mCall.printCallInfo(); - if(callID != mCall.getCallId()) - return; - - mCall.setCallState(newState); - if(mCall.isOngoing()){ - initNormalStateDisplay(); - } - } + public void onCalltransfered(SipCall call, String to); + + public void onRecordCall(SipCall call); + + public void onSendMessage(SipCall call, String msg); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + + if (!(activity instanceof Callbacks)) { + throw new IllegalStateException("Activity must implement fragment's callbacks."); + } + + mCallbacks = (Callbacks) activity; + } + + @Override + public void onDetach() { + super.onDetach(); + mCallbacks = sDummyCallbacks; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.frag_call, container, false); + + view = (BubblesView) rootView.findViewById(R.id.main_view); + view.setModel(model); + + hangup_icon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_hangup); + call_icon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_call); + + Log.i(TAG, "Starting fragment for call " + mCall.getCallId()); + + mCall.printCallInfo(); + + if (mCall.isIncoming() && mCall.isRinging()) { + initIncomingCallDisplay(); + } else { + if (mCall.isRinging()) { + initOutGoingCallDisplay(); + } + try { + if (mCall.isOutGoing() && mCallbacks.getService().getCall(mCall.getCallId()) == null) { + mCallbacks.getService().placeCall(mCall); + initOutGoingCallDisplay(); + } else if(mCall.isOutGoing() && mCall.isRinging()){ + initOutGoingCallDisplay(); + } + } catch (RemoteException e) { + Log.e(TAG, e.toString()); + } + } + + if(mCall.isOngoing()){ + initNormalStateDisplay(); + } + + return rootView; + } + + private void initNormalStateDisplay() { + Log.i(TAG, "Start normal display"); + // TODO off-thread image loading + Bubble contact_bubble = getBubbleFor(mCall.getContacts().get(0), screenCenter.x, screenCenter.y); + Bubble me = getBubbleFor(myself, screenCenter.x, screenCenter.y * 3 / 2); + + /* contact_bubble.setPos(screenCenter.x, screenCenter.y); + me.setPos(screenCenter.x, screenCenter.y * 3 / 2);*/ + /*if (mCall.getContacts().get(0).getPhoto_id() > 0) { + Bitmap photo = ContactPictureLoader.loadContactPhoto(getActivity().getContentResolver(), mCall.getContacts().get(0).getId()); + contact_bubble = new Bubble(screenCenter.x, screenCenter.y, 150, photo); + } else { + contact_bubble = new Bubble(getActivity(), screenCenter.x, screenCenter.y / 2 , 150, R.drawable.ic_contact_picture); + } + + me = new Bubble(getActivity(), screenCenter.x, screenCenter.y * 3 / 2, 150, R.drawable.ic_contact_picture); + */ + model.clearAttractors(); + model.addAttractor(new Attractor(new PointF(metrics.widthPixels / 2, metrics.heightPixels * .8f), 20, new Attractor.Callback() { + @Override + public void onBubbleSucked(Bubble b) { + Log.w(TAG, "Bubble sucked ! "); + mCallbacks.onCallEnded(mCall); + } + }, hangup_icon)); + + /* contact_bubble.contact = mCall.getContacts().get(0); + me.contact = myself; + model.addBubble(contact_bubble); + model.addBubble(me); + contacts.put(mCall.getContacts().get(0), contact_bubble); + contacts.put(myself, me);*/ + } + + private void initIncomingCallDisplay() { + Log.i(TAG, "Start incoming display"); + + Bubble contact_bubble = getBubbleFor(mCall.getContacts().get(0), screenCenter.x, screenCenter.y); + contacts.put(mCall.getContacts().get(0), contact_bubble); + + model.clearAttractors(); + model.addAttractor(new Attractor(new PointF(3 * metrics.widthPixels / 4, metrics.heightPixels / 4), 20, new Attractor.Callback() { + @Override + public void onBubbleSucked(Bubble b) { + mCallbacks.onCallAccepted(mCall); + } + }, call_icon)); + model.addAttractor(new Attractor(new PointF(metrics.widthPixels / 4, metrics.heightPixels / 4), 20, new Attractor.Callback() { + @Override + public void onBubbleSucked(Bubble b) { + mCallbacks.onCallRejected(mCall); + } + }, hangup_icon)); + } + + private void initOutGoingCallDisplay() { + Log.i(TAG, "Start outgoing display"); + // TODO off-thread image loading + Bubble contact_bubble = getBubbleFor(mCall.getContacts().get(0), screenCenter.x, screenCenter.y); + + model.clearAttractors(); + model.addAttractor(new Attractor(new PointF(metrics.widthPixels / 2, metrics.heightPixels * .8f), 20, new Attractor.Callback() { + @Override + public void onBubbleSucked(Bubble b) { + Log.w(TAG, "Bubble sucked ! "); + mCallbacks.onCallEnded(mCall); + } + }, hangup_icon)); + + /*contact_bubble.contact = mCall.getContacts().get(0); + model.addBubble(contact_bubble); + contacts.put(mCall.getContacts().get(0), contact_bubble);*/ + } + + /** + * Retrieves or create a bubble for a given contact. + * If the bubble exists, it is moved to the new location. + * + * @param contact The contact + * @param x Initial or new x position. + * @param y Initial or new y position. + * @return Bubble corresponding to the contact. + */ + private Bubble getBubbleFor(CallContact contact, float x, float y) { + Bubble contact_bubble = contacts.get(contact); + if(contact_bubble != null) { + contact_bubble.attractor.set(x, y); + return contact_bubble; + } + + if (contact.getPhoto_id() > 0) { + Bitmap photo = ContactPictureLoader.loadContactPhoto(getActivity().getContentResolver(), mCall.getContacts().get(0).getId()); + contact_bubble = new Bubble(x, y, BUBBLE_SIZE, photo); + } else { + contact_bubble = new Bubble(x, y, BUBBLE_SIZE, getActivity(), R.drawable.ic_contact_picture); + } + contact_bubble.contact = contact; + + model.addBubble(contact_bubble); + contacts.put(contact, contact_bubble); + + return contact_bubble; + } + + public void changeCallState(String callID, String newState) { + + Log.w(TAG, "Changing call state of "+callID); + mCall.printCallInfo(); + if(!callID.equals(mCall.getCallId())) + return; + + mCall.setCallState(newState); + if(mCall.isOngoing()){ + initNormalStateDisplay(); + } + } } diff --git a/src/com/savoirfairelinux/sflphone/model/Attractor.java b/src/com/savoirfairelinux/sflphone/model/Attractor.java index 5547dc81aeb6caafbeaa5d77e31752ffc38bef76..51b18503a1b9446830dce770fcd5c8b1a4ec038c 100644 --- a/src/com/savoirfairelinux/sflphone/model/Attractor.java +++ b/src/com/savoirfairelinux/sflphone/model/Attractor.java @@ -1,6 +1,10 @@ package com.savoirfairelinux.sflphone.model; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.PointF; +import android.graphics.RectF; public class Attractor { @@ -8,10 +12,36 @@ public class Attractor { public void onBubbleSucked(Bubble b); } - PointF pos; - Callback callback; - public Attractor(PointF pos, Callback callback) { + final PointF pos; + final float radius; + + final Callback callback; + private final Bitmap img; + + private final RectF bounds = new RectF(); + + public Attractor(PointF pos, float radius, Callback callback, Bitmap img) { this.pos = pos; + this.radius = radius; this.callback = callback; + this.img = img; + } + + public Attractor(PointF pos, float radius, Callback callback, Context c, int resId) { + this(pos, radius, callback, BitmapFactory.decodeResource(c.getResources(), resId)); + } + + public void setDensity(float density) + { + bounds.set(pos.x - radius*density, pos.y - radius*density, pos.x + radius*density, pos.y + radius*density); + } + + public RectF getBounds() { + return bounds; } -} \ No newline at end of file + + public Bitmap getBitmap() { + return img; + } + +} diff --git a/src/com/savoirfairelinux/sflphone/model/Bubble.java b/src/com/savoirfairelinux/sflphone/model/Bubble.java index 0dbd013a909f0374e788b5c71cee1d0585fff6fc..546bb3c2e0012ffe0f6add23c814a31da47065f5 100644 --- a/src/com/savoirfairelinux/sflphone/model/Bubble.java +++ b/src/com/savoirfairelinux/sflphone/model/Bubble.java @@ -24,6 +24,7 @@ public class Bubble public float target_scale = 1.f; private final float radius; private float scale = 1.f; + private float density = 1.f; public PointF speed = new PointF(0, 0); public PointF last_speed = new PointF(); public PointF attractor = null; @@ -36,7 +37,7 @@ public class Bubble this.attractor = attractor; } - public Bubble(Context c, float x, float y, float rad, Bitmap photo) { + public Bubble(float x, float y, float rad, Bitmap photo) { internalBMP = photo; pos.set(x, y); @@ -68,18 +69,11 @@ public class Bubble internalCanvas.drawBitmap(circle, 0, 0, mPaintPath); } - public Bubble(Context c, float x, float y, float rad, int resID) { + public Bubble(float x, float y, float rad, Context c, int resID) { // Initialize the bitmap object by loading an image from the resources folder - /*if (resID != -1) - internalBMP = BitmapFactory.decodeResource(c.getResources(), resID); - else - internalBMP = BitmapFactory.decodeResource(c.getResources(), R.drawable.ic_contact_picture); - */ - this(c, x, y, rad, BitmapFactory.decodeResource(c.getResources(), resID==-1 ? resID : R.drawable.ic_contact_picture)); + this(x, y, rad, BitmapFactory.decodeResource(c.getResources(), resID==-1 ? resID : R.drawable.ic_contact_picture)); } - - public Bitmap getBitmap() { return externalBMP; } @@ -92,7 +86,7 @@ public class Bubble scale = s; pos.x = x; pos.y = y; - float rad = scale*radius; + float rad = scale*radius*density; bounds.left = pos.x - rad; bounds.right = pos.x + rad; bounds.top = pos.y - rad; @@ -144,4 +138,9 @@ public class Bubble float tot_radius = this.radius + radius; return dx*dx + dy*dy < tot_radius*tot_radius; } + + public void setDensity(float density) + { + this.density = density; + } } diff --git a/src/com/savoirfairelinux/sflphone/model/BubbleModel.java b/src/com/savoirfairelinux/sflphone/model/BubbleModel.java index 460d9e97caace322ad2d9affa1fffb09b1fa4a80..87d371803a7f1e147a333f9303c875efbd220992 100644 --- a/src/com/savoirfairelinux/sflphone/model/BubbleModel.java +++ b/src/com/savoirfairelinux/sflphone/model/BubbleModel.java @@ -1,6 +1,7 @@ package com.savoirfairelinux.sflphone.model; import java.util.ArrayList; +import java.util.List; import android.graphics.PointF; @@ -8,10 +9,10 @@ public class BubbleModel { private static final String TAG = BubbleModel.class.getSimpleName(); - public long lastUpdate = 0; + private long lastUpdate = 0; public int width, height; - public ArrayList<Bubble> listBubbles = new ArrayList<Bubble>(); - public ArrayList<Attractor> attractors = new ArrayList<Attractor>(); + private ArrayList<Bubble> bubbles = new ArrayList<Bubble>(); + private ArrayList<Attractor> attractors = new ArrayList<Attractor>(); private static final double BUBBLE_RETURN_TIME_HALF_LIFE = .3; private static final double BUBBLE_RETURN_TIME_LAMBDA = Math.log(2)/BUBBLE_RETURN_TIME_HALF_LIFE; @@ -42,6 +43,35 @@ public class BubbleModel border_repulsion = BORDER_REPULSION*density; } + public void addBubble(Bubble b) { + b.setDensity(density); + bubbles.add(b); + } + + public List<Bubble> getBubbles() + { + return bubbles; + } + + public void addAttractor(Attractor a) { + a.setDensity(density); + attractors.add(a); + } + + public List<Attractor> getAttractors() + { + return attractors; + } + + public void clearAttractors() { + attractors.clear(); + } + + public void clear() { + clearAttractors(); + bubbles.clear(); + } + public void update() { long now = System.nanoTime(); @@ -60,8 +90,8 @@ public class BubbleModel // Iterators should not be used in frequently called methods // to avoid garbage collection glitches caused by iterator objects. - for(int i=0, n=listBubbles.size(); i<n; i++) { - Bubble b = listBubbles.get(i); + for(int i=0, n=bubbles.size(); i<n; i++) { + Bubble b = bubbles.get(i); //Log.w(TAG, "update b"); if(!b.dragged) { @@ -134,7 +164,7 @@ public class BubbleModel if(attractor != null && attractor_dist < attractor_dist_suck*attractor_dist_suck) { attractor.callback.onBubbleSucked(b); - listBubbles.remove(b); + bubbles.remove(b); n--; } } @@ -143,4 +173,6 @@ public class BubbleModel } } + + } diff --git a/src/com/savoirfairelinux/sflphone/model/BubblesView.java b/src/com/savoirfairelinux/sflphone/model/BubblesView.java index 12432751d753ebf4771a06358fddd9f22f742ba7..8ca439af7e112b328c1d2636eb28dd7157eebdd3 100644 --- a/src/com/savoirfairelinux/sflphone/model/BubblesView.java +++ b/src/com/savoirfairelinux/sflphone/model/BubblesView.java @@ -1,11 +1,12 @@ package com.savoirfairelinux.sflphone.model; +import java.util.List; + import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; -import android.graphics.RectF; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; @@ -47,7 +48,7 @@ public class BubblesView extends SurfaceView implements SurfaceHolder.Callback, attractor_paint.setColor(Color.RED); //attractor_paint.set - name_paint.setTextSize(20*textDensity); + name_paint.setTextSize(18*textDensity); name_paint.setColor(0xFF303030); name_paint.setTextAlign(Align.CENTER); } @@ -134,46 +135,55 @@ public class BubblesView extends SurfaceView implements SurfaceHolder.Callback, int action = event.getActionMasked(); - if (action == MotionEvent.ACTION_DOWN) { - for (Bubble b : model.listBubbles) { - if (b.intersects(event.getX(), event.getY())) { - b.dragged = true; - b.last_drag = System.nanoTime(); - b.setPos(event.getX(), event.getY()); - b.target_scale = .8f; + synchronized (model) { + List<Bubble> bubbles = model.getBubbles(); + final int n_bubbles = bubbles.size(); + + if (action == MotionEvent.ACTION_DOWN) { + for(int i=0; i<n_bubbles; i++) { + Bubble b = bubbles.get(i); + if (b.intersects(event.getX(), event.getY())) { + b.dragged = true; + b.last_drag = System.nanoTime(); + b.setPos(event.getX(), event.getY()); + b.target_scale = .8f; + } } - } - } else if (action == MotionEvent.ACTION_MOVE) { - long now = System.nanoTime(); - for (Bubble b : model.listBubbles) { - if (b.dragged) { - float x = event.getX(), y = event.getY(); - float dt = (float) ((now-b.last_drag)/1000000000.); - float dx = x - b.getPosX(), dy = y - b.getPosY(); - b.last_drag = now; - - b.setPos(event.getX(), event.getY()); - /*int hn = event.getHistorySize() - 2; + } else if (action == MotionEvent.ACTION_MOVE) { + long now = System.nanoTime(); + for(int i=0; i<n_bubbles; i++) { + Bubble b = bubbles.get(i); + if (b.dragged) { + float x = event.getX(), y = event.getY(); + float dt = (float) ((now-b.last_drag)/1000000000.); + float dx = x - b.getPosX(), dy = y - b.getPosY(); + b.last_drag = now; + + b.setPos(event.getX(), event.getY()); + /*int hn = event.getHistorySize() - 2; Log.w(TAG, "event.getHistorySize() : " + event.getHistorySize()); if(hn > 0) { float dx = x-event.getHistoricalX(hn); float dy = y-event.getHistoricalY(hn); float dt = event.getHistoricalEventTime(hn)/1000.f;*/ - b.speed.x = dx/dt; - b.speed.y = dy/dt; - //Log.w(TAG, "onTouch dx:" + b.speed.x + " dy:" + b.speed.y); - //} - return true; + b.speed.x = dx/dt; + b.speed.y = dy/dt; + //Log.w(TAG, "onTouch dx:" + b.speed.x + " dy:" + b.speed.y); + //} + return true; + } } - } - } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { - for (Bubble b : model.listBubbles) { - if (b.dragged) { - b.dragged = false; - b.target_scale = 1.f; + } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { + for(int i=0; i<n_bubbles; i++) { + Bubble b = bubbles.get(i); + if (b.dragged) { + b.dragged = false; + b.target_scale = 1.f; + } } } } + return true; } @@ -212,9 +222,6 @@ public class BubblesView extends SurfaceView implements SurfaceHolder.Callback, doDraw(c); } } finally { - // do this in a finally so that if an exception is thrown - // during the above, we don't leave the Surface in an - // inconsistent state if (c != null) surfaceHolder.unlockCanvasAndPost(c); } @@ -233,9 +240,6 @@ public class BubblesView extends SurfaceView implements SurfaceHolder.Callback, model.width = width; model.height = height; } - - // don't forget to resize the background image - // mBackgroundImage = Bitmap.createScaledBitmap(mBackgroundImage, width, height, true); } } @@ -244,23 +248,19 @@ public class BubblesView extends SurfaceView implements SurfaceHolder.Callback, canvas.drawColor(Color.WHITE); synchronized (model) { - for (int i = 0; i < model.attractors.size(); i++) { - Attractor a = model.attractors.get(i); - canvas.drawCircle(a.pos.x, a.pos.y, 10, attractor_paint); + List<Bubble> bubbles = model.getBubbles(); + List<Attractor> attractors = model.getAttractors(); + + for (int i=0, n=attractors.size(); i < n; i++) { + Attractor a = attractors.get(i); + //canvas.drawCircle(a.pos.x, a.pos.y, 10, attractor_paint); + canvas.drawBitmap(a.getBitmap(), null, a.getBounds(), null); } - for (int i = 0; i < model.listBubbles.size(); i++) { - Bubble b = model.listBubbles.get(i); - RectF bounds = new RectF(b.getBounds()); - /*if(b.dragged) { - float width = bounds.left - bounds.right; - float red = width/4; - bounds.left += red; - bounds.right -= red; - bounds.top += red; - bounds.bottom -= red; - }*/ - canvas.drawBitmap(b.getBitmap(), null, bounds, null); + for (int i=0, n=bubbles.size(); i<n; i++) { + Bubble b = bubbles.get(i); + //RectF bounds = new RectF(b.getBounds()); + canvas.drawBitmap(b.getBitmap(), null, b.getBounds(), null); canvas.drawText(b.contact.getmDisplayName(), b.getPosX(), b.getPosY()-50*density, name_paint); } }