package it.angelic.soulissclient.fragments; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.res.Configuration; import android.graphics.LinearGradient; import android.graphics.drawable.ClipDrawable; import android.graphics.drawable.ShapeDrawable; import android.graphics.drawable.shapes.RoundRectShape; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; import android.support.v4.app.ListFragment; import android.support.v4.widget.SwipeRefreshLayout; import android.util.Log; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.AdapterView; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import java.util.List; import java.util.Timer; import java.util.TimerTask; import it.angelic.soulissclient.AbstractStatusedFragmentActivity; import it.angelic.soulissclient.Constants; import it.angelic.soulissclient.R; import it.angelic.soulissclient.R.color; import it.angelic.soulissclient.SoulissApp; import it.angelic.soulissclient.SoulissDataService; import it.angelic.soulissclient.TypicalDetailFragWrapper; import it.angelic.soulissclient.adapters.TypicalsListAdapter; import it.angelic.soulissclient.adapters.TypicalsListAdapter.TypicalViewHolder; import it.angelic.soulissclient.helpers.AlertDialogHelper; import it.angelic.soulissclient.helpers.SoulissPreferenceHelper; import it.angelic.soulissclient.model.LauncherElement; import it.angelic.soulissclient.model.SoulissNode; import it.angelic.soulissclient.model.SoulissTypical; import it.angelic.soulissclient.model.db.SoulissDBHelper; import it.angelic.soulissclient.model.db.SoulissDBLauncherHelper; import it.angelic.soulissclient.model.db.SoulissDBTagHelper; import it.angelic.soulissclient.model.typicals.SoulissTypical11DigitalOutput; import it.angelic.soulissclient.model.typicals.SoulissTypical12DigitalOutputAuto; import it.angelic.soulissclient.model.typicals.SoulissTypical14PulseOutput; import it.angelic.soulissclient.model.typicals.SoulissTypical16AdvancedRGB; import it.angelic.soulissclient.model.typicals.SoulissTypical18StepRelay; import it.angelic.soulissclient.model.typicals.SoulissTypical19AnalogChannel; import it.angelic.soulissclient.model.typicals.SoulissTypical31Heating; import it.angelic.soulissclient.model.typicals.SoulissTypical32AirCon; import it.angelic.soulissclient.model.typicals.SoulissTypical41AntiTheft; import it.angelic.soulissclient.model.typicals.SoulissTypical42AntiTheftPeer; import it.angelic.soulissclient.model.typicals.SoulissTypical43AntiTheftLocalPeer; import it.angelic.soulissclient.model.typicals.SoulissTypical6nAnalogue; import it.angelic.soulissclient.net.UDPHelper; import it.angelic.soulissclient.util.FontAwesomeUtil; import it.angelic.soulissclient.util.LauncherElementEnum; import it.angelic.soulissclient.util.SoulissUtils; import it.angelic.tagviewlib.SimpleTagViewUtils; import static junit.framework.Assert.assertTrue; public class NodeDetailFragment extends ListFragment { private Timer autoUpdate; private SoulissNode collected; private SoulissDBHelper datasource; private ListView listaTypicalsView; private SoulissDataService mBoundService; private boolean mDualPane; private boolean mIsBound; private TextView nodeic; private SoulissPreferenceHelper opzioni; private ProgressBar par; private SwipeRefreshLayout swipeLayout; private TypicalsListAdapter ta; /* SOULISS DATA SERVICE BINDING */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { mBoundService = ((SoulissDataService.LocalBinder) service).getService(); if (ta != null) ta.setmBoundService(mBoundService); } public void onServiceDisconnected(ComponentName className) { mBoundService = null; // if (ta != null) ta.setmBoundService(null); } }; // private Toolbar actionBar; private TextView upda; // Aggiorna il feedback private BroadcastReceiver datareceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { try { Log.d(Constants.TAG, "Detected data arrival, refresh from DB"); // cancel timeout swipeLayout.setRefreshing(false); if (listaTypicalsView == null) { return; } SoulissDBHelper.open(); collected = datasource.getSoulissNode(collected.getNodeId()); refreshHeader(); List<SoulissTypical> goer = collected.getActiveTypicals(); ta.setTypicals(goer); ta.notifyDataSetChanged(); // save index and top position int index = listaTypicalsView.getFirstVisiblePosition(); View v = listaTypicalsView.getChildAt(0); int top = (v == null) ? 0 : v.getTop(); // Adapter della lista //listaTypicalsView.setAdapter(ta); listaTypicalsView.invalidateViews(); listaTypicalsView.setSelectionFromTop(index, top); } catch (Exception e) { Log.e(Constants.TAG, "Error in data receival, connection closed?" + e.getMessage()); } } }; public static NodeDetailFragment newInstance(int index, SoulissNode content) { NodeDetailFragment f = new NodeDetailFragment(); // Supply index input as an argument. Bundle args = new Bundle(); args.putInt("index", index); // Ci metto il nodo dentro if (content != null) { args.putSerializable("NODO", content.getNodeId()); } f.setArguments(args); return f; } // private SwipeGestureListener gestureListener; /** * Riga grigia cra spazio */ private void createHeader() { if (collected.getIconResourceId() != 0) FontAwesomeUtil.prepareAwesomeFontAweTextView(getActivity(), nodeic, SimpleTagViewUtils.getAwesomeNames(getActivity()).get(collected.getIconResourceId())); par.setMax(Constants.MAX_HEALTH); // ProgressBar sfumata final ShapeDrawable pgDrawable = new ShapeDrawable(new RoundRectShape(Constants.roundedCorners, null, null)); final LinearGradient gradient = new LinearGradient(0, 0, 250, 0, getResources().getColor(color.aa_red), getResources().getColor(color.aa_green), android.graphics.Shader.TileMode.CLAMP); // pgDrawable.getPaint().setStrokeWidth(3); pgDrawable.getPaint().setDither(true); pgDrawable.getPaint().setShader(gradient); ClipDrawable progress = new ClipDrawable(pgDrawable, Gravity.START, ClipDrawable.HORIZONTAL); par.setBackgroundResource(android.R.drawable.progress_horizontal); par.setProgressDrawable(progress); par.setMax(50); par.setProgress(20); par.setProgress(0); // <-- BUG Android par.setMax(Constants.MAX_HEALTH); refreshHeader(); Log.d(Constants.TAG, "Setting bar at " + collected.getHealth() + " win width=" + SoulissApp.getDisplayWidth() / 2); } void doBindService() { if (!mIsBound) { getActivity().bindService(new Intent(getActivity(), SoulissDataService.class), mConnection, Context.BIND_AUTO_CREATE); mIsBound = true; } } void doUnbindService() { if (mIsBound) { getActivity().unbindService(mConnection); mIsBound = false; } } protected int getShownIndex() { if (getArguments() != null) return getArguments().getInt("index", 0); else return 0; } @Override public void onActivityCreated(Bundle savedInstanceState) { opzioni = SoulissApp.getOpzioni(); if (opzioni.isLightThemeSelected()) getActivity().setTheme(R.style.LightThemeSelector); else getActivity().setTheme(R.style.DarkThemeSelector); super.onActivityCreated(savedInstanceState); Handler timeoutHandler = new Handler(); setHasOptionsMenu(true); datasource = new SoulissDBHelper(getActivity()); View detailsFrame = getActivity().findViewById(R.id.detailPane); mDualPane = detailsFrame != null && detailsFrame.getVisibility() == View.VISIBLE; // nodoInfo.removeAllViews(); //tt = (TextView) getActivity().findViewById(R.id.TextViewTypicalsTitle); // health = (TextView) findViewById(R.id.TextViewHealth); upda = (TextView) getActivity().findViewById(R.id.TextViewNodeUpdate); par = (ProgressBar) getActivity().findViewById(R.id.progressBarNodo); swipeLayout = (SwipeRefreshLayout) getActivity().findViewById(R.id.swipeRefreshContainer); if (upda == null) return; Bundle extras = getActivity().getIntent().getExtras(); // recuper nodo da extra Short colId = 0; if (extras != null && extras.get("NODO") != null) colId = extras.getShort("NODO"); else if (getArguments() != null) { colId = getArguments().getShort("NODO"); } try { Log.w(Constants.TAG, "DB load node id" + colId); collected = datasource.getSoulissNode(colId); } catch (Exception e) { Log.e(Constants.TAG, "Error retriving node:" + e.getMessage()); return; } assertTrue("NODO NULLO", collected != null); getActivity().setTitle(collected.getNiceName()); listaTypicalsView = getListView(); nodeic = (TextView) getActivity().findViewById(R.id.node_icon_detail); // Icona, puo esser nullo dopo rotazione schermo FontAwesomeUtil.prepareAwesomeFontAweTextView(getActivity(), nodeic, SimpleTagViewUtils.getAwesomeNames(getActivity()).get(collected.getIconResourceId())); createHeader(); registerForContextMenu(listaTypicalsView); swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { new Thread(new Runnable() { @Override public void run() { Looper.prepare(); if (collected != null) { UDPHelper.pollRequest(opzioni, 1, collected.getNodeId()); } if (!opzioni.isSoulissReachable()) { getActivity().runOnUiThread(new Runnable() { public void run() { Toast.makeText(getActivity(), getString(R.string.status_souliss_notreachable), Toast.LENGTH_SHORT) .show(); swipeLayout.setRefreshing(false); } }); } } }).start(); } }); swipeLayout.setColorSchemeResources(R.color.std_blue, R.color.std_blue_shadow); } @Override public void onConfigurationChanged(Configuration newConfig) { View detailsFrame = getActivity().findViewById(R.id.detailPane); mDualPane = detailsFrame != null && detailsFrame.getVisibility() == View.VISIBLE; Log.i(Constants.TAG, "DUALPANE:" + mDualPane); super.onConfigurationChanged(newConfig); } @Override public boolean onContextItemSelected(MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo(); TypicalsListAdapter ada = (TypicalsListAdapter) listaTypicalsView.getAdapter(); long arrayAdapterPosition = info.position; final SoulissTypical todoItem = (SoulissTypical) ada.getItem((int) arrayAdapterPosition); switch (item.getItemId()) { case R.id.rinomina: AlertDialog.Builder alert3 = AlertDialogHelper.renameSoulissObjectDialog(getActivity(), null, listaTypicalsView, datasource, todoItem); alert3.show(); break; case R.id.sceglicona: SoulissTypical convertView = (SoulissTypical) listaTypicalsView.getItemAtPosition(item.getOrder()); TextView at = new TextView(getActivity()); FontAwesomeUtil.prepareFontAweTextView(getActivity(), at, convertView.getIconResourceId()); AlertDialog.Builder alert2 = AlertDialogHelper.chooseIconDialog(getActivity(), at, listaTypicalsView, datasource, todoItem); alert2.show(); break; case R.id.addTo: SoulissDBTagHelper dbt = new SoulissDBTagHelper(getActivity()); // AlertDialog.Builder alert4 = AlertDialogHelper.addTagCommandDialog(getActivity(), dbt, todoItem, null, getListView()); AlertDialog built = alert4.create(); built.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); built.show(); break; default: return super.onContextItemSelected(item); } return true; } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); MenuInflater inflater = getActivity().getMenuInflater(); // Rinomina nodo e scelta icona inflater.inflate(R.menu.typical_ctx_menu, menu); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { // Rinomina nodo e scelta icona inflater.inflate(R.menu.rebuildnode_ctx_menu, menu); Log.i(Constants.TAG, "Inflated Equalizer menu"); super.onCreateOptionsMenu(menu, inflater); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.frag_nodedetail, container, false); } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); switch (id) { case R.id.Ricostruisci: AlertDialog.Builder alertt = AlertDialogHelper.rebuildNodeDialog(getActivity(), collected, opzioni); alertt.show(); return true; case R.id.AddToDashboard: SoulissDBLauncherHelper dbl = new SoulissDBLauncherHelper(getActivity()); LauncherElement nodeLauncher = new LauncherElement(); nodeLauncher.setComponentEnum(LauncherElementEnum.NODE); nodeLauncher.setLinkedObject(collected); dbl.addElement(nodeLauncher); Toast.makeText(getActivity(), collected.getNiceName() + " " + getActivity().getString(R.string.added_to_dashboard), Toast.LENGTH_SHORT).show(); return true; } return false; } @Override public void onPause() { super.onPause(); autoUpdate.cancel(); getActivity().unregisterReceiver(datareceiver); doUnbindService(); } @Override public void onResume() { super.onResume(); // pezza SoulissDBHelper.open(); doBindService(); IntentFilter filtere = new IntentFilter(); filtere.addAction("it.angelic.soulissclient.GOT_DATA"); filtere.addAction(Constants.CUSTOM_INTENT_SOULISS_RAWDATA); getActivity().registerReceiver(datareceiver, filtere); autoUpdate = new Timer(); autoUpdate.schedule(new TimerTask() { @Override public void run() { getActivity().runOnUiThread(new Runnable() { public void run() { if (listaTypicalsView != null) listaTypicalsView.invalidateViews(); } }); } }, 100, Constants.GUI_UPDATE_INTERVAL); // updates GUI each 40 secs } @Override public void onStart() { super.onStart(); if (collected == null || upda == null) { Log.w(Constants.TAG, "Empty Typical!!"); return;// no detail selected } //refreshStatusIcon(); if (opzioni.isDbConfigured()) { SoulissDBHelper.open(); // per il refresh dal dettaglio collected = datasource.getSoulissNode(collected.getNodeId()); doBindService(); // poll 1 node new Thread(new Runnable() { @Override public void run() { UDPHelper.pollRequest(opzioni, 1, collected.getNodeId()); } }).start(); createHeader(); // tipici dal DB List<SoulissTypical> goer = collected.getActiveTypicals(); ta = new TypicalsListAdapter(getActivity(), mBoundService, goer, getActivity().getIntent(), opzioni); listaTypicalsView = getListView(); // Adapter della lista listaTypicalsView.setAdapter(ta); listaTypicalsView.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) { TypicalViewHolder holder = (TypicalViewHolder) arg1.getTag(); //Log.i(getTag(), "Showing typical idx:"+arg2+" holder slot: "+holder.data.getTypicalDTO().getSlot()); showDetails(arg2, holder.data); } }); //serve per back da dettaglio ((AbstractStatusedFragmentActivity) getActivity()).setActionBarInfo(collected.getNiceName()); } } private void refreshHeader() { par.setProgress(collected.getHealth()); par.setProgress(20); par.setProgress(0); // <-- BUG Android par.setProgress(collected.getHealth()); upda.setText(getResources().getString(R.string.update) + " " + SoulissUtils.getTimeAgo(collected.getRefreshedAt())); } /** * Helper function to show the details of a selected item, either by * displaying a fragment in-place in the current UI, or starting a whole new * activity in which it is displayed. */ private void showDetails(int index, SoulissTypical target) { // mCurCheckPosition = index; if (target == null) return;//capita con lista vuota if (mDualPane) { ListView li = getListView(); li.setChoiceMode(ListView.CHOICE_MODE_SINGLE); // listaNodiView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); // We can display everything in-place with fragments, so update // the list to highlight the selected item and show the data. li.setItemChecked(index, true); } else { // ((AbstractStatusedFragmentActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true); } Fragment NewFrag = null; // Istanzia e ci mette l'indice if (target instanceof SoulissTypical6nAnalogue) NewFrag = T6nAnalogueFragment.newInstance(index, target); else if (target instanceof SoulissTypical31Heating) NewFrag = T31HeatingFragment.newInstance(index, target); else if (target.isSensor()) NewFrag = T5nSensorFragment.newInstance(index, target); else if (target instanceof SoulissTypical16AdvancedRGB) NewFrag = T16RGBAdvancedFragment.newInstance(index, target); else if (target instanceof SoulissTypical19AnalogChannel) NewFrag = T19SingleChannelLedFragment.newInstance(index, target); else if (target instanceof SoulissTypical11DigitalOutput || target instanceof SoulissTypical12DigitalOutputAuto) NewFrag = T1nGenericLightFragment.newInstance(index, target); else if (target instanceof SoulissTypical41AntiTheft || target instanceof SoulissTypical42AntiTheftPeer || target instanceof SoulissTypical43AntiTheftLocalPeer) NewFrag = T4nFragment.newInstance(index, target); else if (target instanceof SoulissTypical32AirCon) NewFrag = T32AirConFragment.newInstance(index, target); else if (target instanceof SoulissTypical14PulseOutput || target instanceof SoulissTypical18StepRelay) { //no detail, notice user and return Toast.makeText(getActivity(), getString(R.string.status_souliss_nodetail), Toast.LENGTH_SHORT) .show(); return; } else { //last resort, TWrapper // Activity Dettaglio nodo //TODO transform in frags Intent nodeDatail = new Intent(getActivity(), TypicalDetailFragWrapper.class); nodeDatail.putExtra("TIPICO", target); getActivity().startActivity(nodeDatail); // getActivity().supportFinishAfterTransition(); return;//launched wrapper activity } FragmentTransaction ft = getFragmentManager().beginTransaction(); if (opzioni.isAnimationsEnabled()) ft.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left); ft.replace(R.id.detailPane, NewFrag); ft.addToBackStack(null); // ft.remove(details); //ft.add(NewFrag,"BOH"); //ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE); ft.commit(); } }