package net.kismetwireless.android.smarterwifimanager; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.graphics.Typeface; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.AlphaAnimation; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import com.doomonafireball.betterpickers.timepicker.TimePickerBuilder; import com.doomonafireball.betterpickers.timepicker.TimePickerDialogFragment; import java.util.ArrayList; /** * Created by dragorn on 10/1/13. */ public class FragmentTimeRange extends SmarterFragment { View mainView; Context context; FragmentActivity activity; ArrayList<SmarterTimeRange> lastTimeList = new ArrayList<SmarterTimeRange>(); private TimeListAdapter listAdapter; private ListView lv; private TextView emptyView; SmarterWifiServiceBinder serviceBinder; @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); context = getActivity().getApplicationContext(); serviceBinder = new SmarterWifiServiceBinder(context); serviceBinder.doBindService(); if (savedInstanceState != null) { lastTimeList = savedInstanceState.getParcelableArrayList("timelist"); if (lv != null) { listAdapter = new TimeListAdapter(context, R.layout.time_entry, lastTimeList); lv.setAdapter(listAdapter); } } else { serviceBinder.doCallAndBindService(new SmarterWifiServiceBinder.BinderCallback() { @Override public void run(SmarterWifiServiceBinder b) { if (!isAdded()) return; Activity a = getActivity(); if (a == null) return; a.runOnUiThread(new Runnable() { @Override public void run() { updateTimeList(); } }); } }); } } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putParcelableArrayList("timelist", lastTimeList); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); mainView = inflater.inflate(R.layout.fragment_timerange, container, false); activity = getActivity(); context = activity.getApplicationContext(); lv = (ListView) mainView.findViewById(R.id.timeRangeListView); emptyView = (TextView) mainView.findViewById(R.id.textViewNoTime); listAdapter = new TimeListAdapter(context, R.layout.time_entry, lastTimeList); lv.setAdapter(listAdapter); return mainView; } public void addTimeRange() { // Expand new items SmarterTimeRange str = new SmarterTimeRange(); str.setCollapsed(false); lastTimeList.add(str); if (listAdapter != null) listAdapter.notifyDataSetChanged(); if (emptyView != null && lv != null) { if (lastTimeList.size() <= 0) { emptyView.setVisibility(View.VISIBLE); lv.setVisibility(View.GONE); } else { emptyView.setVisibility(View.GONE); lv.setVisibility(View.VISIBLE); } } } public class TimeListAdapter extends ArrayAdapter<SmarterTimeRange> { private int layoutResourceId; public TimeListAdapter(Context context, int textViewResourceId, ArrayList<SmarterTimeRange> items) { super(context, textViewResourceId, items); layoutResourceId = textViewResourceId; } // Ugly call so we can pass finals private void collapseView(LinearLayout collapsedMain, LinearLayout expandedMain, LinearLayout collapseView, LinearLayout expandView, boolean collapse, SmarterTimeRange item) { // Extract from the main views TextView daysRepeatView = (TextView) expandView.findViewById(R.id.daysRepeatCollapse); TextView summaryView = (TextView) collapsedMain.findViewById(R.id.rangeSummaryText); if (!item.getEnabled()) { summaryView.setText(R.string.timerange_disabled_text); } else { if (item.getDays() == 0) { summaryView.setText(R.string.timerange_no_days); } else if (!item.getBluetoothControlled() && !item.getWifiControlled()) { summaryView.setText(context.getString(R.string.timerange_no_effect)); } else { StringBuilder sb = new StringBuilder(); if (item.getWifiControlled()) { sb.append(context.getString(R.string.timerange_control_wifi)); sb.append(" "); if (item.getWifiEnabled()) sb.append(context.getString(R.string.timerange_control_on)); else sb.append(context.getString(R.string.timerange_control_off)); } if (item.getBluetoothControlled()) { if (sb.length() > 0) sb.append(", "); sb.append(context.getString(R.string.timerange_control_bluetooth)); sb.append(" "); if (item.getBluetoothEnabled()) sb.append(context.getString(R.string.timerange_control_on)); else sb.append(context.getString(R.string.timerange_control_off)); } summaryView.setText(sb.toString()); } } if (collapse) { collapseView.setVisibility(View.GONE); expandView.setVisibility(View.VISIBLE); collapsedMain.setVisibility(View.VISIBLE); expandedMain.setVisibility(View.GONE); daysRepeatView.setText(SmarterTimeRange.getHumanDayText(context, item.getDays())); } else { collapseView.setVisibility(View.VISIBLE); expandView.setVisibility(View.GONE); collapsedMain.setVisibility(View.GONE); expandedMain.setVisibility(View.VISIBLE); } } private void toggleImageViewEnable(ImageView v, boolean b) { // If we dont' leave the background view clickable, we can use this to disable the buttons v.setEnabled(b); v.setClickable(b); if (b) { AlphaAnimation alpha = new AlphaAnimation(1.0F, 1.0F); alpha.setDuration(0); alpha.setFillAfter(true); v.startAnimation(alpha); /* We don't need this if we dont' use the whole background row as a clickable collapse; leave for reference if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB) { TypedArray a = context.obtainStyledAttributes(new int[] { android.R.attr.selectableItemBackground }); int resource = a.getResourceId(0, 0); a.recycle(); v.setBackground(context.getResources().getDrawable(resource)); } */ } else { AlphaAnimation alpha = new AlphaAnimation(0.5F, 0.5F); alpha.setDuration(0); alpha.setFillAfter(true); v.startAnimation(alpha); // v.setBackground(null); } } private void deleteDialog(final SmarterTimeRange item) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(R.string.timerange_dialog_delete_title); builder.setMessage(R.string.timerange_dialog_delete_text); builder.setNegativeButton(R.string.timerange_dialog_delete_cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { } }); builder.setPositiveButton(R.string.timerange_dialog_delete_ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { serviceBinder.deleteTimeRange(item); lastTimeList.remove(item); listAdapter.notifyDataSetChanged(); if (lastTimeList.size() <= 0) { emptyView.setVisibility(View.VISIBLE); lv.setVisibility(View.GONE); } else { emptyView.setVisibility(View.GONE); lv.setVisibility(View.VISIBLE); } } }); builder.create().show(); } @Override public View getView(int position, View convertView, ViewGroup parent) { try { final SmarterTimeRange item = getItem(position); View v = null; if (convertView == null) { LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); v = inflater.inflate(layoutResourceId, null); } else { v = convertView; } // Containers we pass to the hide/show function final LinearLayout timeStartContainer, timeEndContainer, expandView, collapseView; final CheckBox wifiCb, bluetoothCb; final CompoundButton wifiSwitch, bluetoothSwitch, enableSwitch; // Clock final TextView startHours, startMinutes, startAmPm, endHours, endMinutes, endAmPm; // Expand/collapse are two layouts for simplicity final LinearLayout collapsedMain, expandedMain; // Main image buttons final ImageView deleteCollapse, deleteExpand, undoExpand, saveExpand; // Blue/bold day picker text final TextView repMon, repTue, repWed, repThu, repFri, repSat, repSun; // Red fail text final TextView errorText1, errorText2; final TextView summaryView; collapsedMain = (LinearLayout) v.findViewById(R.id.collapsedMainLayout); expandedMain = (LinearLayout) v.findViewById(R.id.expandedMainLayout); expandView = (LinearLayout) v.findViewById(R.id.expandView); collapseView = (LinearLayout) v.findViewById(R.id.collapseView); deleteCollapse = (ImageView) v.findViewById(R.id.timeRangeDeleteCollapse); deleteExpand = (ImageView) v.findViewById(R.id.timeRangeDelete); undoExpand = (ImageView) v.findViewById(R.id.timeRangeUndo); saveExpand= (ImageView) v.findViewById(R.id.timeRangeSave); timeStartContainer = (LinearLayout) v.findViewById(R.id.timeLayoutStart); timeEndContainer = (LinearLayout) v.findViewById(R.id.timeLayoutEnd); startHours = (TextView) v.findViewById(R.id.timeStartHours); startMinutes = (TextView) v.findViewById(R.id.timeStartMinutes); endHours = (TextView) v.findViewById(R.id.timeEndHours); endMinutes = (TextView) v.findViewById(R.id.timeEndMinutes); startAmPm = (TextView) v.findViewById(R.id.timeStart12hr); endAmPm = (TextView) v.findViewById(R.id.timeEnd12hr); wifiCb = (CheckBox) v.findViewById(R.id.wifiCheckbox); wifiSwitch = (CompoundButton) v.findViewById(R.id.wifiSwitch); bluetoothCb = (CheckBox) v.findViewById(R.id.bluetoothCheckbox); bluetoothSwitch = (CompoundButton) v.findViewById(R.id.bluetoothSwitch); enableSwitch = (CompoundButton) v.findViewById(R.id.timeRangeToggle); repMon = (TextView) v.findViewById(R.id.dayMon); repTue = (TextView) v.findViewById(R.id.dayTue); repWed = (TextView) v.findViewById(R.id.dayWed); repThu = (TextView) v.findViewById(R.id.dayThu); repFri = (TextView) v.findViewById(R.id.dayFri); repSat = (TextView) v.findViewById(R.id.daySat); repSun = (TextView) v.findViewById(R.id.daySun); summaryView = (TextView) v.findViewById(R.id.rangeSummaryText); errorText1 = (TextView) v.findViewById(R.id.errorView1); errorText2 = (TextView) v.findViewById(R.id.errorView2); // long now = System.currentTimeMillis(); // long then = item.getNextStartAsMillis(); int failcode = item.getRangeValid(); if (failcode < 0) { errorText1.setVisibility(View.GONE); errorText2.setVisibility(View.GONE); summaryView.setVisibility(View.VISIBLE); } else { errorText1.setText(failcode); errorText2.setText(failcode); errorText1.setVisibility(View.VISIBLE); errorText2.setVisibility(View.VISIBLE); summaryView.setVisibility(View.GONE); } if (item.getDirty()) { if (item.getRevertable()) toggleImageViewEnable(undoExpand, true); else toggleImageViewEnable(undoExpand, false); // toggleImageViewEnable(saveExpand, true); // Save turns back into save saveExpand.setImageResource(R.drawable.ic_action_save); } else { toggleImageViewEnable(undoExpand, false); //toggleImageViewEnable(saveExpand, false); // Turn save into collapse saveExpand.setImageResource(R.drawable.navigation_collapse); } // There are more efficient ways of doing this but it only happens in this one // view so... who cares. int dayRep = item.getDays(); if ((dayRep & SmarterTimeRange.REPEAT_MON) != 0) { repMon.setTextColor(getResources().getColor(R.color.blue)); repMon.setTypeface(null, Typeface.BOLD); } else { repMon.setTextColor(getResources().getColor(R.color.white)); repMon.setTypeface(null, Typeface.NORMAL); } if ((dayRep & SmarterTimeRange.REPEAT_TUE) != 0) { repTue.setTextColor(getResources().getColor(R.color.blue)); repTue.setTypeface(null, Typeface.BOLD); } else { repTue.setTextColor(getResources().getColor(R.color.white)); repTue.setTypeface(null, Typeface.NORMAL); } if ((dayRep & SmarterTimeRange.REPEAT_WED) != 0) { repWed.setTextColor(getResources().getColor(R.color.blue)); repWed.setTypeface(null, Typeface.BOLD); } else { repWed.setTextColor(getResources().getColor(R.color.white)); repWed.setTypeface(null, Typeface.NORMAL); } if ((dayRep & SmarterTimeRange.REPEAT_THU) != 0) { repThu.setTextColor(getResources().getColor(R.color.blue)); repThu.setTypeface(null, Typeface.BOLD); } else { repThu.setTextColor(getResources().getColor(R.color.white)); repThu.setTypeface(null, Typeface.NORMAL); } if ((dayRep & SmarterTimeRange.REPEAT_FRI) != 0) { repFri.setTextColor(getResources().getColor(R.color.blue)); repFri.setTypeface(null, Typeface.BOLD); } else { repFri.setTextColor(getResources().getColor(R.color.white)); repFri.setTypeface(null, Typeface.NORMAL); } if ((dayRep & SmarterTimeRange.REPEAT_SAT) != 0) { repSat.setTextColor(getResources().getColor(R.color.blue)); repSat.setTypeface(null, Typeface.BOLD); } else { repSat.setTextColor(getResources().getColor(R.color.white)); repSat.setTypeface(null, Typeface.NORMAL); } if ((dayRep & SmarterTimeRange.REPEAT_SUN) != 0) { repSun.setTextColor(getResources().getColor(R.color.blue)); repSun.setTypeface(null, Typeface.BOLD); } else { repSun.setTextColor(getResources().getColor(R.color.white)); repSun.setTypeface(null, Typeface.NORMAL); } repMon.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int d = item.getDays(); if ((d & SmarterTimeRange.REPEAT_MON) != 0) d &= ~SmarterTimeRange.REPEAT_MON; else d |= SmarterTimeRange.REPEAT_MON; item.setDays(d); listAdapter.notifyDataSetChanged(); } }); repTue.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int d = item.getDays(); if ((d & SmarterTimeRange.REPEAT_TUE) != 0) d &= ~SmarterTimeRange.REPEAT_TUE; else d |= SmarterTimeRange.REPEAT_TUE; item.setDays(d); listAdapter.notifyDataSetChanged(); } }); repWed.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int d = item.getDays(); if ((d & SmarterTimeRange.REPEAT_WED) != 0) d &= ~SmarterTimeRange.REPEAT_WED; else d |= SmarterTimeRange.REPEAT_WED; item.setDays(d); listAdapter.notifyDataSetChanged(); } }); repThu.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int d = item.getDays(); if ((d & SmarterTimeRange.REPEAT_THU) != 0) d &= ~SmarterTimeRange.REPEAT_THU; else d |= SmarterTimeRange.REPEAT_THU; item.setDays(d); listAdapter.notifyDataSetChanged(); } }); repFri.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int d = item.getDays(); if ((d & SmarterTimeRange.REPEAT_FRI) != 0) d &= ~SmarterTimeRange.REPEAT_FRI; else d |= SmarterTimeRange.REPEAT_FRI; item.setDays(d); listAdapter.notifyDataSetChanged(); } }); repSat.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int d = item.getDays(); if ((d & SmarterTimeRange.REPEAT_SAT) != 0) d &= ~SmarterTimeRange.REPEAT_SAT; else d |= SmarterTimeRange.REPEAT_SAT; item.setDays(d); listAdapter.notifyDataSetChanged(); } }); repSun.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int d = item.getDays(); if ((d & SmarterTimeRange.REPEAT_SUN) != 0) d &= ~SmarterTimeRange.REPEAT_SUN; else d |= SmarterTimeRange.REPEAT_SUN; item.setDays(d); listAdapter.notifyDataSetChanged(); } }); wifiCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { item.setWifiControlled(b); if (b) { wifiSwitch.setVisibility(View.VISIBLE); } else { wifiSwitch.setVisibility(View.GONE); } listAdapter.notifyDataSetChanged(); } }); bluetoothCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { item.setBluetoothControlled(b); if (b) { bluetoothSwitch.setVisibility(View.VISIBLE); } else { bluetoothSwitch.setVisibility(View.GONE); } listAdapter.notifyDataSetChanged(); } }); wifiSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { item.setWifiEnabled(b); listAdapter.notifyDataSetChanged(); } }); bluetoothSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { item.setBluetoothEnabled(b); listAdapter.notifyDataSetChanged(); } }); startHours.setText(String.format("%02d", SmarterTimeRange.getHuman12Hour(item.getStartHour()))); startMinutes.setText(String.format("%02d", item.getStartMinute())); startAmPm.setText(SmarterTimeRange.getHumanAmPm(item.getStartHour()) ? "AM" : "PM"); endHours.setText(String.format("%02d", SmarterTimeRange.getHuman12Hour(item.getEndHour()))); endMinutes.setText(String.format("%02d", item.getEndMinute())); endAmPm.setText(SmarterTimeRange.getHumanAmPm(item.getEndHour()) ? "AM" : "PM"); wifiCb.setChecked(item.getWifiControlled()); wifiSwitch.setChecked(item.getWifiEnabled()); wifiSwitch.setVisibility(item.getWifiControlled() ? View.VISIBLE : View.GONE); bluetoothCb.setChecked(item.getBluetoothControlled()); bluetoothSwitch.setChecked(item.getBluetoothEnabled()); bluetoothSwitch.setVisibility(item.getBluetoothControlled() ? View.VISIBLE : View.GONE); enableSwitch.setChecked(item.getEnabled()); collapseView(collapsedMain, expandedMain, expandView, collapseView, item.getCollapsed(), item); enableSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean b) { item.setEnabled(b); serviceBinder.updateTimeRangeEnabled(item); // Disable and open, close if (!b) { timeStartContainer.setClickable(false); timeEndContainer.setClickable(false); timeStartContainer.setEnabled(false); timeEndContainer.setEnabled(false); if (!item.getCollapsed()) { item.setCollapsed(true); collapseView(collapsedMain, expandedMain, expandView, collapseView, item.getCollapsed(), item); } } // Enable and closed, open if (b) { timeStartContainer.setClickable(true); timeEndContainer.setClickable(true); timeStartContainer.setEnabled(true); timeEndContainer.setEnabled(true); if (item.getCollapsed()) { item.setCollapsed(false); collapseView(collapsedMain, expandedMain, expandView, collapseView, item.getCollapsed(), item); } } listAdapter.notifyDataSetChanged(); } }); // Start and end time launch time pickers timeStartContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { item.setCollapsed(false); TimePickerBuilder tpb = new TimePickerBuilder(); tpb.setFragmentManager(activity.getSupportFragmentManager()); tpb.setStyleResId(R.style.BetterPickersDialogFragment); tpb.addTimePickerDialogHandler(new TimePickerDialogFragment.TimePickerDialogHandler() { @Override public void onDialogTimeSet(int reference, int hourOfDay, int minute) { item.setStartTime(hourOfDay, minute); listAdapter.notifyDataSetChanged(); } }); tpb.show(); listAdapter.notifyDataSetChanged(); } }); timeEndContainer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { item.setCollapsed(false); TimePickerBuilder tpb = new TimePickerBuilder(); tpb.setFragmentManager(activity.getSupportFragmentManager()); tpb.setStyleResId(R.style.BetterPickersDialogFragment); tpb.addTimePickerDialogHandler(new TimePickerDialogFragment.TimePickerDialogHandler() { @Override public void onDialogTimeSet(int reference, int hourOfDay, int minute) { item.setEndTime(hourOfDay, minute); listAdapter.notifyDataSetChanged(); } }); tpb.show(); listAdapter.notifyDataSetChanged(); } }); collapseView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { item.setCollapsed(!item.getCollapsed()); collapseView(collapsedMain, expandedMain, expandView, collapseView, item.getCollapsed(), item); } }); deleteCollapse.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { deleteDialog(item); } }); deleteExpand.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { deleteDialog(item); } }); undoExpand.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (!item.getRevertable()) return; item.revertChanges(); listAdapter.notifyDataSetChanged(); } }); saveExpand.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (!item.getDirty()) { // We're a collapse button item.setCollapsed(true); collapseView(collapsedMain, expandedMain, expandView, collapseView, item.getCollapsed(), item); listAdapter.notifyDataSetChanged(); return; } // Otherwise save serviceBinder.updateTimeRange(item); item.applyChanges(); listAdapter.notifyDataSetChanged(); } }); return v; } catch (Exception ex) { Log.e("smarter", "error", ex); return null; } } } private void updateTimeList() { ArrayList<SmarterTimeRange> tr = serviceBinder.getTimeRangeList(); if (tr != null) { lastTimeList.clear(); lastTimeList.addAll(tr); listAdapter.notifyDataSetChanged(); } if (lastTimeList.size() <= 0) { emptyView.setVisibility(View.VISIBLE); lv.setVisibility(View.GONE); } else { emptyView.setVisibility(View.GONE); lv.setVisibility(View.VISIBLE); } } @Override public int getTitle() { return R.string.tab_time; } }