package org.openhab.habclient; /** * Created by Tony Alpskog in 2013. */ import android.app.Activity; import android.app.AlertDialog; import android.app.Fragment; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.util.AttributeSet; import android.util.Log; import android.view.DragEvent; 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.widget.AdapterView; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import org.openhab.domain.IEventBus; import org.openhab.domain.IOpenHABWidgetProvider; import org.openhab.domain.IRestCommunication; import org.openhab.domain.model.GraphicUnit; import org.openhab.domain.model.OpenHABWidget; import org.openhab.domain.model.OpenHABWidgetType; import org.openhab.domain.model.Room; import org.openhab.domain.model.RoomConfigEvent; import org.openhab.habclient.dagger.DaggerUnitPlacementComponent; import org.openhab.habdroid.R; import org.openhab.habdroid.ui.IWidgetTypeLayoutProvider; import org.openhab.habdroid.ui.OpenHABWidgetArrayAdapter; import org.openhab.habdroid.ui.WidgetTypeLayoutProvider; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; import java.util.Set; import javax.inject.Inject; import de.greenrobot.event.EventBus; /** * A placeholder fragment containing a simple view. */ public class UnitPlacementFragment extends Fragment { /** * The fragment argument representing the section number for this * fragment. */ private static final String ARG_SECTION_NUMBER = "section_number"; private static final String TAG = "UnitPlacementFragment"; private UnitContainerView mRoomView; private final EnumSet<OpenHABWidgetType> mUnitTypes = EnumSet.of(OpenHABWidgetType.RollerShutter, OpenHABWidgetType.Switch, OpenHABWidgetType.Slider, OpenHABWidgetType.ItemText, OpenHABWidgetType.SitemapText, OpenHABWidgetType.SelectionSwitch, OpenHABWidgetType.Selection, OpenHABWidgetType.Setpoint, OpenHABWidgetType.Color, OpenHABWidgetType.Group); private OpenHABWidgetArrayAdapter mOpenHABWidgetAdapter; //TA: TODO - Add a LinkedPageLink string member here for REST Get sitemap usage. Then Load HABApp with the resulting data source. @Inject IOpenHABWidgetProvider mWidgetProvider; @Inject IRestCommunication mRestCommunication; @Inject IEventBus mEventBus; @Inject IOpenHABSetting mOpenHABSetting; /** * Returns a new instance of this fragment for the given section * number. */ public static UnitPlacementFragment newInstance(int sectionNumber) { UnitPlacementFragment fragment = new UnitPlacementFragment(); Bundle args = new Bundle(); args.putInt(ARG_SECTION_NUMBER, sectionNumber); fragment.setArguments(args); return fragment; } @Override public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) { super.onInflate(activity, attrs, savedInstanceState); Log.d("LifeCycle", "UnitPlacementFragment.onInflate(" + (getArguments()!=null? getArguments().getInt(ARG_SECTION_NUMBER): "?") + ")"); } @Override public void onAttach(Activity activity) { super.onAttach(activity); Log.d("LifeCycle", "UnitPlacementFragment.onAttach(" + (getArguments()!=null? getArguments().getInt(ARG_SECTION_NUMBER): "?") + ")"); // ((MainActivity) activity).onSectionAttached(getArguments().getInt(ARG_SECTION_NUMBER));//TODO - remove? } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); DaggerUnitPlacementComponent.builder() .appComponent(((HABApplication) getActivity().getApplication()).appComponent()) .build() .inject(this); Log.d("LifeCycle", "UnitPlacementFragment(" + (getArguments() != null ? getArguments().getInt(ARG_SECTION_NUMBER) : "?") + ") <constructor>"); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Room room = ((RoomConfigActivity)getActivity()).getConfigRoom(); Log.d("LifeCycle", "UnitPlacementFragment.onCreateView() room<" + (room == null? "NULL": room.getId()) + ">"); View fragmentView = inflater.inflate(R.layout.fragment_unit_placement, container, false); TextView textView = (TextView) fragmentView.findViewById(R.id.room_config_section_label); mRoomView = (UnitContainerView) fragmentView.findViewById(R.id.room_layout); mRoomView.setRoom(room); //TODO - Make DragListener internal in UnitContainerView and control the usage of it by layout parameters (DragNDrop on/off) mRoomView.setOnDragListener(dropListener); EventBus.getDefault().register(this); // textView.setText(Integer.toString(getArguments().getInt(ARG_SECTION_NUMBER)));//TODO - Fix this setHasOptionsMenu(true); return fragmentView; } @Override public void onStart() { super.onStart(); Log.d("LifeCycle", "UnitPlacementFragment.onStart(" + (getArguments() != null ? getArguments().getInt(ARG_SECTION_NUMBER) : "?") + ")"); } @Override public void onResume() { super.onResume(); Log.d("LifeCycle", "UnitPlacementFragment.onResume(" + (getArguments()!=null? getArguments().getInt(ARG_SECTION_NUMBER): "?") + ")"); mRestCommunication.requestOpenHABSitemap(mRoomView.getRoom().getRoomWidget(), false, TAG); mRestCommunication.requestOpenHABSitemap(mRoomView.getRoom().getRoomWidget(), true, TAG);//Used } @Override public void onPause() { super.onPause(); Log.d("LifeCycle", "UnitPlacementFragment.onPause(" + (getArguments()!=null? getArguments().getInt(ARG_SECTION_NUMBER): "?") + ")"); mRestCommunication.cancelRequests(TAG); } @Override public void onStop() { super.onStop(); Log.d("LifeCycle", "UnitPlacementFragment.onStop(" + (getArguments()!=null? getArguments().getInt(ARG_SECTION_NUMBER): "?") + ")"); } @Override public void onDestroyView() { super.onDestroyView(); Log.d("LifeCycle", "UnitPlacementFragment.onDestroyView(" + (getArguments() != null ? getArguments().getInt(ARG_SECTION_NUMBER) : "?") + ")"); } @Override public void onDestroy() { super.onDestroy(); Log.d("LifeCycle", "UnitPlacementFragment.onDestroy(" + (getArguments()!=null? getArguments().getInt(ARG_SECTION_NUMBER): "?") + ")"); } @Override public void onDetach() { super.onDetach(); Log.d("LifeCycle", "UnitPlacementFragment.onDetach(" + (getArguments()!=null? getArguments().getInt(ARG_SECTION_NUMBER): "?") + ")"); } public void onUpdateView() { if(mRoomView != null) mRoomView.setRoom(((RoomConfigActivity)getActivity()).getConfigRoom()); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { //TODO - Create dynamic menu // Inflate the menu; this adds items to the action bar if it is present. inflater.inflate(R.menu.room_config_default, menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. switch (item.getItemId()) { case R.id.action_add: showAddUnitDialog(getActivity()); break; case R.id.action_remove: removeSelectedUnits(); break; case R.id.action_selection: unitSelectionDialog(getActivity()); break; case R.id.action_clone: //TODO: Create and draw a new copy of any current selection. Toast.makeText(getActivity(), "Not implemented.", Toast.LENGTH_SHORT).show(); break; default: return super.onOptionsItemSelected(item); } return true; } private void removeSelectedUnits() { final List<GraphicUnit> unitsToBeRemovedList = new ArrayList<GraphicUnit>(); for(GraphicUnit gu : mRoomView.getRoom().getUnits()) { if(gu.isSelected()) unitsToBeRemovedList.add(gu); } for(GraphicUnit gu : unitsToBeRemovedList) { mRoomView.getRoom().removeUnit(gu); } mRoomView.redrawAllUnits();//TA: TODO - Ugly way too remove a single View. } private void showAddUnitDialog(final Context context) { List<OpenHABWidget> list = mWidgetProvider.getWidgetList((Set<OpenHABWidgetType>) null); for (OpenHABWidget aList : list) Log.d(HABApplication.getLogTag(), "WidgetProvider data ID = " + aList.getId()); String strLogAll = "showAddUnitDialog() -> Full list: "; String strLogRemoved = "showAddUnitDialog() -> Removed list: "; if(mRoomView.getRoom().getRoomWidget() == null) { mRestCommunication.requestOpenHABSitemap((String) null, false, TAG);//Used if(mRoomView.getRoom().getRoomWidget() == null) { Log.e(HABApplication.getLogTag(), String.format("Cannot get room items for Room '%s' with widget ID = '%s'", mRoomView.getRoom().getName(), mRoomView.getRoom().getGroupWidgetId())); Toast.makeText(context, "Cannot get items for this room.", Toast.LENGTH_LONG).show(); return; } } List<OpenHABWidget> widgetList = mRoomView.getRoom().getRoomWidget().getChildren(); final List<OpenHABWidget> unusedWidgetsList = new ArrayList<OpenHABWidget>(); for(OpenHABWidget widget : widgetList) { strLogAll += widget.getId() + ", "; if(mUnitTypes.contains(widget.getType()) && !mRoomView.getRoom().contains(widget)){ unusedWidgetsList.add(widget); } else strLogRemoved += widget.getId() + ", "; } Log.d(HABApplication.getLogTag(), strLogAll); Log.d(HABApplication.getLogTag(), strLogRemoved); if(unusedWidgetsList.size() < 1) { Toast.makeText(context, "There are no more items for this room.", Toast.LENGTH_SHORT).show(); return; } final AlertDialog addUnitDialog; // Creating and Building the Dialog final AlertDialog.Builder builder = new AlertDialog.Builder(context); LayoutInflater li = LayoutInflater.from(getActivity()); View convertView = li.inflate(R.layout.openhabwidgetlist, null); ListView widgetListView = (ListView) convertView.findViewById(android.R.id.list); IWidgetTypeLayoutProvider widgetTypeLayoutProvider = new WidgetTypeLayoutProvider(); mOpenHABWidgetAdapter = new OpenHABWidgetArrayAdapter(context, R.layout.openhabwidgetlist_genericitem, unusedWidgetsList, widgetTypeLayoutProvider, OpenHABWidgetArrayAdapter.WidgetLayoutType.IconTextList); widgetListView.setAdapter(mOpenHABWidgetAdapter); // Set adapter parameters mOpenHABWidgetAdapter.setOpenHABUsername(mOpenHABSetting.getUsername()); mOpenHABWidgetAdapter.setOpenHABPassword(mOpenHABSetting.getPassword()); builder.setTitle("Select unit type"); builder.setView(convertView); addUnitDialog = builder.create(); widgetListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { mRoomView.addNewUnitToRoom(new GraphicUnit(unusedWidgetsList.get(Integer.valueOf(position)), mEventBus), 50, 50); addUnitDialog.dismiss(); } }); addUnitDialog.show(); } private void unitSelectionDialog(Context context) { //TODO - Create dialog choices dynamically. final CharSequence[] items = {"Select all", "Deselect all", "Select all of current type(s)", "Select all clones"}; AlertDialog selectUnitDialog; // Creating and Building the Dialog AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle("Choose selection type"); builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { switch(item) { case 0: multiUnitSelection(true); break; case 1: multiUnitSelection(false); break; case 2: final ArrayList<OpenHABWidgetType> selectedTypes = getSelectedWidgetsType(); for(GraphicUnit gu : mRoomView.getRoom().getUnits()) { if(!gu.isSelected() && selectedTypes.contains(gu.getType())) { gu.setSelected(true); mRoomView.setSelected(gu); } } break; case 3: ArrayList<String> selectedId = getSelectedWidgetsId(); for(GraphicUnit gu : mRoomView.getRoom().getUnits()) { if(!gu.isSelected() && selectedId.contains(gu.getOpenHABWidget().getId())) { gu.setSelected(true); mRoomView.setSelected(gu); } } break; } dialog.dismiss(); } }); selectUnitDialog = builder.create(); selectUnitDialog.show(); } private ArrayList<OpenHABWidgetType> getSelectedWidgetsType() { ArrayList<OpenHABWidgetType> selectedTypeList = new ArrayList<OpenHABWidgetType>(); for(GraphicUnit gu : mRoomView.getRoom().getUnits()) { if(gu.isSelected() && !selectedTypeList.contains(gu.getType())) selectedTypeList.add(gu.getType()); } return selectedTypeList; } private ArrayList<String> getSelectedWidgetsId() { ArrayList<String> selectedIdList = new ArrayList<String>(); for(GraphicUnit gu : mRoomView.getRoom().getUnits()) { if(gu.isSelected() && !selectedIdList.contains(gu.getOpenHABWidget().getId())) selectedIdList.add(gu.getOpenHABWidget().getId()); } return selectedIdList; } View.OnDragListener dropListener = new View.OnDragListener() { float dragXDiff = 0; float dragYDiff = 0; @Override public boolean onDrag(View v, DragEvent event) { int dragEvent = event.getAction(); switch (dragEvent) { case DragEvent.ACTION_DRAG_ENTERED: Log.i("DragEvent", "Entered"); break; case DragEvent.ACTION_DRAG_ENDED: Log.i("DragEvent", "Ended"); break; case DragEvent.ACTION_DRAG_STARTED: GraphicUnitWidget draggedView = (GraphicUnitWidget) event.getLocalState(); Log.i("DragEvent", "Started at LAMP = " + draggedView.getX() + "/" + draggedView.getY() + " EVENT = " + event.getX() + "/" + event.getY()); dragXDiff = event.getX() - draggedView.getX(); dragYDiff = event.getY() - draggedView.getY(); //stop displaying the view where it was before it was dragged draggedView.setVisibility(View.INVISIBLE); break; case DragEvent.ACTION_DROP: GraphicUnitWidget droppedView = (GraphicUnitWidget) event.getLocalState(); Log.i("DragEvent", "Dropped at LAMP = " + Math.round(event.getX() + dragXDiff) + "/" + Math.round(event.getY() + dragYDiff) + " EVENT = " + event.getX() + "/" + event.getY()); Log.i("DragEvent", "Drop target at TOP = " + v.getTop() + " LEFT = " + v.getLeft()); // droppedView.setX(Math.round(event.getX() + dragXDiff + v.getLeft() - 70)); // droppedView.setY(Math.round(event.getY() + dragYDiff/* + v.getTop()*/ - 50)); //TODO - Fix this temporary hard coded adjustment droppedView.setX(Math.round(event.getX())-30); droppedView.setY(Math.round(event.getY())-30); droppedView.setVisibility(View.VISIBLE); setRoomRelativePositions(droppedView); Log.d("Unit", "Dropped view pos X/Y = " + droppedView.getX() + "/" + droppedView.getY()); Log.d("UnitPos", "dropped REL: " + droppedView.getgUnit().getRoomRelativeX() + "/" + droppedView.getgUnit().getRoomRelativeY() + " Calc: X=(" + mRoomView.getScaledBitmapWidth() + "/(" + droppedView.getX() + "-" + mRoomView.getScaledBitmapX() + ") Y=(" + mRoomView.getScaledBitmapHeight() + "/(" + droppedView.getY() + "-" + mRoomView.getScaledBitmapY() + ")"); break; } return true; } }; // private int getRoomRelativeX(int percentOfX) { // return (((mRoomView.getScaledBitmapWidth() / 100) * percentOfX) + mRoomView.getScaledBitmapX()); // } // // private int getRoomRelativeY(int percentOfY) { // return (((mRoomView.getScaledBitmapHeight() / 100) * percentOfY) + mRoomView.getScaledBitmapY()); // } private void setRoomRelativePositions(GraphicUnitWidget graphicUnitView) { setRoomRelativePositions(graphicUnitView.getgUnit(), graphicUnitView); } private void setRoomRelativePositions(GraphicUnit gUnit, View unitView) { gUnit.setRoomRelativeX(mRoomView.getScaledBitmapWidth() / (unitView.getX() - mRoomView.getScaledBitmapX())); gUnit.setRoomRelativeY(mRoomView.getScaledBitmapHeight() / (unitView.getY() - mRoomView.getScaledBitmapY())); } private void multiUnitSelection(boolean doSelect) { for(GraphicUnit gu : mRoomView.getRoom().getUnits()) { setSelected(gu, doSelect); } } private void setSelected(GraphicUnit gu, boolean selected) { if(gu != null && gu.isSelected() != selected) { gu.setSelected(selected); mRoomView.setSelected(gu); } } private boolean cloneSelectedWidgets() { ArrayList<String> selectedWidgetsIdList = new ArrayList<String>(); for(GraphicUnit gu : mRoomView.getRoom().getUnits()) { if(gu.isSelected() && !selectedWidgetsIdList.contains(gu.getOpenHABWidget().getId())) { mRoomView.addNewUnitToRoom(new GraphicUnit(gu.getOpenHABWidget(), mEventBus), 50, 50); selectedWidgetsIdList.add(gu.getOpenHABWidget().getId()); } } return selectedWidgetsIdList.size() > 0; } public void onEvent(RoomConfigEvent roomConfigEvent) { if(mRoomView.getRoom().equals(roomConfigEvent.getRoom()) && roomConfigEvent.getEventType() == RoomConfigEvent.EventType.ConfigurationChanged) onUpdateView(); } }