package org.witness.informacam.app.screens;
import info.guardianproject.odkparser.FormWrapper.ODKFormListener;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
import org.witness.informacam.app.EditorActivity;
import org.witness.informacam.app.R;
import org.witness.informacam.app.screens.editors.FullScreenMJPEGPlayerFragment;
import org.witness.informacam.app.screens.editors.FullScreenVideoViewFragment;
import org.witness.informacam.app.screens.popups.PopupClickListener;
import org.witness.informacam.app.utils.Constants;
import org.witness.informacam.app.utils.Constants.EditorActivityListener;
import org.witness.informacam.app.views.ChevronRegionView;
import org.witness.informacam.json.JSONException;
import org.witness.informacam.models.media.IRegion;
import org.witness.informacam.models.media.IRegionBounds;
import org.witness.informacam.ui.editors.IRegionDisplay;
import org.witness.informacam.utils.Constants.IRegionDisplayListener;
import org.witness.informacam.utils.Constants.Models.IMedia.MimeType;
import android.app.Activity;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
public class FullScreenViewFragment extends Fragment implements OnTouchListener, IRegionDisplayListener, ODKFormListener
{
public enum Mode
{
Normal, Edit, AddTags
}
protected Mode currentMode = Mode.Normal;
protected View rootView;
protected RelativeLayout mediaHolder;
protected int[] dims;
protected IRegion currentRegion = null;
public int DEFAULT_REGION_WIDTH, DEFAULT_REGION_HEIGHT;
protected Handler h = new Handler();
// For moving tags
private float mStartDragX;
private float mStartDragY;
private float mStartDragTagX;
private float mStartDragTagY;
private boolean movingTag = false;
@Override
public void onResume() {
super.onResume();
if (getActivity() != null && getActivity() instanceof EditorActivity)
{
((EditorActivity) getActivity()).onFragmentResumed(this);
}
}
// @Override
// public void onDestroy() {
// if(isEditingForm) {
// ((TagFormFragment) tagFormFragment).saveTagFormData(currentRegion);
// isEditingForm = false;
// }
//
//
// super.onDestroy();
// }
@SuppressWarnings("deprecation")
@Override
public View onCreateView(LayoutInflater li, ViewGroup container, Bundle savedInstanceState)
{
super.onCreateView(li, container, savedInstanceState);
Display display =getActivity().getWindowManager().getDefaultDisplay();
dims = new int[] { display.getWidth(), display.getHeight() };
rootView = li.inflate(R.layout.fragment_editor_media_view, null);
DEFAULT_REGION_WIDTH = (int) (dims[0] * 0.15);
DEFAULT_REGION_HEIGHT = (int) (dims[1] * 0.1);
mediaHolder = (RelativeLayout) rootView.findViewById(R.id.media_holder);
mediaHolder.setOnTouchListener(this);
initLayout();
return rootView;
}
protected void initLayout()
{
}
protected void deleteTag()
{
((EditorActivityListener) getActivity()).media().removeRegion(currentRegion);
mediaHolder.removeView(getTagViewByRegion(currentRegion));
// for(int v=0; v<mediaHolder.getChildCount(); v++) {
// View v_ = mediaHolder.getChildAt(v);
// if(v_ instanceof IRegionDisplay) {
// for(IRegion r : ((EditorActivityListener) a).media().associatedRegions) {
// if(r.getRegionDisplay().equals(v_)) {
// r.getRegionDisplay().indexOnScreen = v;
// }
// }
// }
// }
currentRegion = null;
}
protected IRegionDisplay getTagViewByRegion(IRegion region)
{
for (int i = 0; i < mediaHolder.getChildCount(); i++)
{
View child = mediaHolder.getChildAt(i);
if (child instanceof IRegionDisplay && ((IRegionDisplay) child).parent == region)
{
return (IRegionDisplay) child;
}
}
return null;
}
protected void initRegions()
{
Activity a = getActivity();
mediaHolder.setOnTouchListener(this);
if (((EditorActivityListener) a).media().associatedRegions != null)
{
for (IRegion r : ((EditorActivityListener) a).media().associatedRegions)
{
if (r.bounds.displayWidth != 0 && r.bounds.displayHeight != 0)
{
r.init(a, r.bounds, false, this);
IRegionDisplay regionDisplay = r.getRegionDisplay();
regionDisplay.setOnTouchListener(this);
regionDisplay.setSoundEffectsEnabled(false);
//regionDisplay.indexOnScreen = mediaHolder.getChildCount();
View newView = new ChevronRegionView(a, r, this);
newView.setOnTouchListener(this);
newView.setSoundEffectsEnabled(false);
mediaHolder.addView(newView);
}
}
updateRegionDisplay();
}
}
protected void updateRegionDisplay()
{
if (((EditorActivityListener) getActivity()).media().associatedRegions != null)
{
for (IRegion r : ((EditorActivityListener) getActivity()).media().associatedRegions)
{
if (!r.equals(currentRegion) || currentMode == Mode.Normal)
{
IRegionDisplay display = getTagViewByRegion(r);
if (display != null)
display.setStatus(false);
}
}
}
}
protected void setCurrentRegion(IRegion region)
{
setCurrentRegion(region, false);
}
protected void setCurrentRegion(IRegion region, boolean isNew)
{
currentRegion = region;
currentRegion.getRegionDisplay().setOnTouchListener(this);
if (isNew) {
View newView = new ChevronRegionView(getActivity(), currentRegion, this);
newView.setSoundEffectsEnabled(false);
newView.setOnTouchListener(this);
mediaHolder.addView(newView);
currentRegion.getRegionDisplay().setSoundEffectsEnabled(false);
updateRegionDisplay();
// showTagContextMenu(currentRegion.getRegionDisplay());
}
else
{
updateRegionDisplay();
}
}
@Override
public boolean onTouch(View v, MotionEvent event)
{
// Log.d(LOG, "on touch called at " + event.getX() + "," + event.getY()
// + "\n on view: " + v.getClass().getName() + " (id " + v.getId() +
// ")\naction: " + event.getAction());
if (v instanceof IRegionDisplay && currentMode != Mode.Normal)
{
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
mStartDragX = event.getX() + v.getLeft();
mStartDragY = event.getY() + v.getTop();
IRegionBounds bounds = ((IRegionDisplay) v).bounds;
mStartDragTagX = bounds.displayLeft;
mStartDragTagY = bounds.displayTop;
v.performClick();
((IRegionDisplay) v).update();
v.postInvalidate();
if (currentMode == Mode.Edit || currentMode == Mode.AddTags)
{
// Bring up the context menu
IRegionDisplay regionDisplay = (IRegionDisplay) v;
this.setCurrentRegion(regionDisplay.parent);
showTagContextMenu(regionDisplay);
}
break;
}
case MotionEvent.ACTION_MOVE:
final float x = event.getX() + v.getLeft();
final float y = event.getY() + v.getTop();
if (currentMode == Mode.AddTags && (movingTag || Math.abs(x - mStartDragX) > 10 || Math.abs(y - mStartDragY) > 10))
{
if (!movingTag)
{
v.cancelLongPress();
movingTag = true;
v.getParent().requestDisallowInterceptTouchEvent(true);
}
IRegionBounds bounds = ((IRegionDisplay) v).bounds;
bounds.displayLeft = (int) (mStartDragTagX + (x - mStartDragX));
bounds.displayTop = (int) (mStartDragTagY + (y - mStartDragY));
constrainBoundsToImage(bounds);
((IRegionDisplay) v).update();
return true;
}
break;
case MotionEvent.ACTION_UP:
if (movingTag)
{
((IRegionDisplay) v).parent.update(getActivity());
movingTag = false;
}
break;
case MotionEvent.ACTION_CANCEL:
movingTag = false;
break;
}
}
else if (currentMode == Mode.AddTags)
{
currentRegion = null;
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
v.getParent().requestDisallowInterceptTouchEvent(true);
}
else if (event.getAction() == MotionEvent.ACTION_UP)
{
try
{
Activity a = getActivity();
if (((EditorActivityListener) a).media().dcimEntry.mediaType.equals(MimeType.IMAGE))
{
IRegion region = ((EditorActivityListener) a).media().addRegion(a, (int) event.getY() - (DEFAULT_REGION_HEIGHT / 2),
(int) event.getX() - (DEFAULT_REGION_WIDTH / 2), DEFAULT_REGION_WIDTH, DEFAULT_REGION_HEIGHT, this);
constrainBoundsToImage(region.bounds);
setCurrentRegion(region, true);
}
else if (((EditorActivityListener) a).media().dcimEntry.mediaType.startsWith(MimeType.VIDEO_BASE))
{
if (this instanceof FullScreenVideoViewFragment)
{
IRegion region = ((EditorActivityListener) a).media().addRegion(a, (int) event.getY() - (DEFAULT_REGION_HEIGHT / 2),
(int) event.getX() - (DEFAULT_REGION_WIDTH / 2), DEFAULT_REGION_WIDTH, DEFAULT_REGION_HEIGHT,
((FullScreenVideoViewFragment) this).getCurrentPosition(), ((FullScreenVideoViewFragment) this).getDuration(), this);
constrainBoundsToImage(region.bounds);
setCurrentRegion(region, true);
}
else if (this instanceof FullScreenMJPEGPlayerFragment)
{
IRegion region = ((EditorActivityListener) a).media().addRegion(a, (int) event.getY() - (DEFAULT_REGION_HEIGHT / 2),
(int) event.getX() - (DEFAULT_REGION_WIDTH / 2), DEFAULT_REGION_WIDTH, DEFAULT_REGION_HEIGHT,
0, 0, this);
constrainBoundsToImage(region.bounds);
setCurrentRegion(region, true);
}
}
}
catch (JSONException e)
{
Log.e(Constants.App.TAG,"error parsing region json",e);
} catch (java.lang.InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return true;
}
else if (currentMode == Mode.Edit)
{
// Clicking outside of a tag in edit mode means "select none"
//
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
{
currentRegion = null;
updateRegionDisplay();
}
break;
}
}
return false;
}
@Override
public void onSelected(IRegionDisplay regionDisplay)
{
setCurrentRegion(regionDisplay.parent);
}
@Override
public boolean saveForm()
{
return true;
}
@Override
public int[] getSpecs()
{
Activity a = getActivity();
if (((EditorActivityListener) a).media() != null)
{
List<Integer> specs = new ArrayList<Integer>();
specs.add(((EditorActivityListener) a).media().width);
specs.add(((EditorActivityListener) a).media().height);
return ArrayUtils.toPrimitive(specs.toArray(new Integer[specs.size()]));
}
else
{
return null;
}
}
public void setCurrentMode(Mode mode)
{
currentMode = mode;
if (currentMode == Mode.Normal)
{
// clear current selection
currentRegion = null;
updateRegionDisplay();
}
else if (currentMode == Mode.Edit)
{
initRegions();
}
}
@SuppressWarnings("deprecation")
private void showTagContextMenu(IRegionDisplay view)
{
try
{
Activity a = getActivity();
LayoutInflater inflater = LayoutInflater.from(a);
View content = inflater.inflate(R.layout.popup_tag_context_menu, mediaHolder, false);
content.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
PopupWindow mMenuPopup = new PopupWindow(content, content.getMeasuredWidth(), content.getMeasuredHeight(), true);
// Delete
//
View btnDelete = content.findViewById(R.id.btnDeleteTag);
btnDelete.setOnClickListener(new PopupClickListener(mMenuPopup)
{
@Override
protected void onSelected()
{
deleteTag();
}
});
// Form
//
View btnForm = content.findViewById(R.id.btnForm);
btnForm.setOnClickListener(new PopupClickListener(mMenuPopup)
{
@Override
protected void onSelected()
{
try {
showTagFormPopup(currentRegion);
} catch (java.lang.InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
mMenuPopup.setOutsideTouchable(true);
mMenuPopup.setBackgroundDrawable(new BitmapDrawable());
mMenuPopup.showAsDropDown(view, view.getWidth(), -view.getHeight());
mMenuPopup.getContentView().setOnClickListener(new PopupClickListener(mMenuPopup));
}
catch (Exception e)
{
e.printStackTrace();
}
}
private void showTagFormPopup(IRegion region) throws java.lang.InstantiationException, IllegalAccessException
{
((EditorActivity) getActivity()).showTagForm(region);
}
public void constrainBoundsToImage(IRegionBounds bounds)
{
RectF imageBounds = getImageBounds();
if (imageBounds != null)
{
bounds.displayLeft = (int) Math.max(bounds.displayLeft, imageBounds.left - bounds.displayWidth / 2);
bounds.displayTop = (int) Math.max(bounds.displayTop, imageBounds.top - bounds.displayHeight / 2);
bounds.displayLeft = (int) Math.min(bounds.displayLeft, imageBounds.right - bounds.displayWidth / 2);
bounds.displayTop = (int) Math.min(bounds.displayTop, imageBounds.bottom - bounds.displayHeight / 2);
}
}
public RectF getImageBounds()
{
return null;
}
}