package ca.cmput301f13t03.adventure_datetime.view.treeView;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import ca.cmput301f13t03.adventure_datetime.model.Choice;
import ca.cmput301f13t03.adventure_datetime.model.Interfaces.IAllFragmentsListener;
import ca.cmput301f13t03.adventure_datetime.model.Interfaces.ICurrentFragmentListener;
import ca.cmput301f13t03.adventure_datetime.model.Interfaces.ICurrentStoryListener;
import ca.cmput301f13t03.adventure_datetime.model.Story;
import ca.cmput301f13t03.adventure_datetime.model.StoryFragment;
import ca.cmput301f13t03.adventure_datetime.serviceLocator.Locator;
import ca.cmput301f13t03.adventure_datetime.view.IFragmentSelected;
import java.util.Map;
import java.util.UUID;
public class TreeView extends SurfaceView
implements IAllFragmentsListener,
ICurrentFragmentListener,
ICurrentStoryListener,
SurfaceHolder.Callback,
Runnable
{
private static final float FPS = 120.0f; // strictly speaking this isn't being calculated quite right...
private static final String TAG = "TreeView";
private Thread m_drawingThread = null;
private volatile boolean m_isDrawing = false;
private SurfaceHolder m_surface = null;
private Camera m_camera = null;
private NodeGrid m_grid = null;
private Map<UUID, StoryFragment> m_fragments = null;
private Story m_currentStory = null;
private InputHandler m_touchHandler = null;
// must have all constructors or it doesn't work
public TreeView(Context context)
{
super(context);
Setup();
}
public TreeView(Context context, AttributeSet attrs)
{
super(context, attrs);
Setup();
}
public TreeView(Context context,AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
Setup();
}
private void Setup()
{
this.getHolder().addCallback(this);
m_grid = new NodeGrid(this.getResources());
m_camera = new Camera();
m_touchHandler = new InputHandler(m_camera, m_grid);
}
public void OnAllFragmentsChange(Map<UUID, StoryFragment> newFragments)
{
m_fragments = newFragments;
// due to the async nature of the callbacks we may not have all the data we need
// at this point, we have most, but not all
if(m_currentStory != null)
{
AfterDataAvailable();
}
}
public void OnCurrentStoryChange(Story newStory)
{
m_currentStory = newStory;
if(m_fragments != null)
{
AfterDataAvailable();
}
}
public void OnCurrentFragmentChange(StoryFragment newFragment)
{
m_grid.SelectFragment(newFragment);
}
public void SetFragmentCallback(IFragmentSelected selectionCallback)
{
m_touchHandler.SetSelectionCallback(selectionCallback);
}
public IFragmentSelected GetFragmentCallback()
{
return m_touchHandler.GetSelectionCallback();
}
public void AddChoice(StoryFragment origin, Choice choice)
{
m_grid.AddChoice(origin, choice);
}
public void RemoveChoice(StoryFragment origin, Choice choice)
{
m_grid.RemoveChoice(origin, choice);
}
public void RefreshView()
{
m_grid.RefreshView();
}
private void AfterDataAvailable()
{
if(m_grid != null)
{
m_grid.SetFragments(m_fragments, m_currentStory.getHeadFragmentId());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
m_camera.ResizeView(width, height);
m_camera.LookAt(0, 0);
}
@Override
public void surfaceCreated(SurfaceHolder surface)
{
Locator.getPresenter().Subscribe((ICurrentStoryListener)(this));
Locator.getPresenter().Subscribe((IAllFragmentsListener)(this));
Locator.getPresenter().Subscribe((ICurrentFragmentListener)(this));
m_isDrawing = true;
m_surface = surface;
m_drawingThread = new Thread(this);
m_drawingThread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder surface)
{
Locator.getPresenter().Unsubscribe((ICurrentStoryListener)(this));
Locator.getPresenter().Unsubscribe((IAllFragmentsListener)(this));
Locator.getPresenter().Unsubscribe((ICurrentFragmentListener)(this));
m_isDrawing = false;
if(m_drawingThread != null)
{
try
{
// allow it to finish drawing the current frame
m_drawingThread.join();
}
catch (InterruptedException e)
{
Log.w(TAG, "Interrupted while Joining! " + e.getMessage());
}
m_drawingThread = null;
}
}
/**
* Main thread for drawing
*/
public void run()
{
while(m_isDrawing)
{
Canvas canvas = m_surface.lockCanvas();
if(canvas != null)
{
try
{
// clear canvas
canvas.drawColor(Color.WHITE);
// draw stuffs
m_grid.Draw(canvas, m_camera);
}
finally
{
m_surface.unlockCanvasAndPost(canvas);
}
}
// then sleep for a bit
try
{
Thread.sleep((long) (1000.0f / FPS));
}
catch (InterruptedException e)
{
// Don't care, just log it and move on
Log.w(TAG, "Interrupted while sleeping!");
}
}
}
public boolean onTouchEvent(MotionEvent event)
{
if(m_touchHandler != null)
{
m_touchHandler.OnTouchAction(event);
}
//Must return true or we stop receiving input events!
return true;
}
}