/* ******************************************************************************** * Copyright (c) 2012 Samsung Electronics, Inc. * All rights reserved. * * This software is a confidential and proprietary information of Samsung * Electronics, Inc. ("Confidential Information"). You shall not disclose such * Confidential Information and shall use it only in accordance with the terms * of the license agreement you entered into with Samsung Electronics. ******************************************************************************** */ package com.sprc.circlelauncher; import android.content.Context; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import com.samsung.spen.lib.input.SPenEventLibrary; import com.samsung.spensdk.applistener.SPenDetachmentListener; import com.samsung.spensdk.applistener.SPenHoverListener; import com.samsung.spensdk.applistener.SPenTouchListener; /** * A wrapper class for S Pen SDK events functionality. */ public class SPen { private final Context mContext; private final SPenEventLibrary mSPEL; public SPen(Context context) { mContext = context; mSPEL = new SPenEventLibrary(); } /** * Registers {@link InputHandleListener} implementation instance. * * @param view * the target {@link View} that we register our handler to * @param handler * the {@link InputHandleListener} implementation instance */ public void registerInputHandler(View view, final InputHandleListener handler) { registerTouchListener(view, handler); registerHoverListener(view, handler); registerClickListener(view, handler); } public void registerContextHandler(ContextHandleListener handler) { registerSPenDetachmentListener(handler); } /** * Potential performance issue: For every event we allocate a new InputBuilder object which allocates new Input * objects too. We should utilize an Object Pool design pattern here to make the garbage collector happy. */ private void registerTouchListener(View view, final InputHandleListener handler) { mSPEL.setSPenTouchListener(view, new SPenTouchListener() { public void onTouchButtonDown(View view, MotionEvent event) { handler.handleEvent(new InputBuilder(view).setInputType(InputType.PEN) .setButtonAction(ButtonAction.DOWN).setEventTime(event.getEventTime()).build()); } public void onTouchButtonUp(View view, MotionEvent event) { handler.handleEvent(new InputBuilder(view).setInputType(InputType.PEN).setButtonAction(ButtonAction.UP) .setEventTime(event.getEventTime()).build()); } public boolean onTouchFinger(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: handler.handleEvent(new InputBuilder(view).setInputType(InputType.FINGER) .setInputAction(InputAction.DOWN).setEventTime(event.getEventTime()).build()); break; case MotionEvent.ACTION_UP: handler.handleEvent(new InputBuilder(view).setInputType(InputType.FINGER) .setInputAction(InputAction.UP).setEventTime(event.getEventTime()).build()); break; default: handler.handleEvent(new InputBuilder(view).setInputType(InputType.FINGER) .setInputAction(InputAction.MOVE).setEventTime(event.getEventTime()).build()); break; } return false; } public boolean onTouchPen(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: handler.handleEvent(new InputBuilder(view).setInputType(InputType.PEN) .setInputAction(InputAction.DOWN).setEventTime(event.getEventTime()).build()); break; case MotionEvent.ACTION_UP: handler.handleEvent(new InputBuilder(view).setInputType(InputType.PEN) .setInputAction(InputAction.UP).setEventTime(event.getEventTime()).build()); break; default: handler.handleEvent(new InputBuilder(view).setInputType(InputType.PEN) .setInputAction(InputAction.MOVE).setEventTime(event.getEventTime()).build()); break; } return false; } public boolean onTouchPenEraser(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: handler.handleEvent(new InputBuilder(view).setInputType(InputType.ERASER) .setInputAction(InputAction.DOWN).setEventTime(event.getEventTime()).build()); break; case MotionEvent.ACTION_UP: handler.handleEvent(new InputBuilder(view).setInputType(InputType.ERASER) .setInputAction(InputAction.UP).setEventTime(event.getEventTime()).build()); break; default: handler.handleEvent(new InputBuilder(view).setInputType(InputType.ERASER) .setInputAction(InputAction.MOVE).setEventTime(event.getEventTime()).build()); break; } return false; } }); } private void registerHoverListener(View view, final InputHandleListener handler) { mSPEL.setSPenHoverListener(view, new SPenHoverListener() { public boolean onHover(View view, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: handler.handleEvent(new InputBuilder(view).setInputType(InputType.HOVER) .setInputAction(InputAction.DOWN).setEventTime(event.getEventTime()).build()); break; case MotionEvent.ACTION_UP: handler.handleEvent(new InputBuilder(view).setInputType(InputType.HOVER) .setInputAction(InputAction.UP).setEventTime(event.getEventTime()).build()); break; default: handler.handleEvent(new InputBuilder(view).setInputType(InputType.HOVER) .setInputAction(InputAction.MOVE).setEventTime(event.getEventTime()).build()); break; } return false; } public void onHoverButtonDown(View view, MotionEvent event) { handler.handleEvent(new InputBuilder(view).setInputType(InputType.HOVER) .setButtonAction(ButtonAction.DOWN).setEventTime(event.getEventTime()).build()); } public void onHoverButtonUp(View view, MotionEvent event) { handler.handleEvent(new InputBuilder(view).setInputType(InputType.HOVER) .setButtonAction(ButtonAction.UP).setEventTime(event.getEventTime()).build()); } }); } private void registerClickListener(final View view, final InputHandleListener handler) { view.setOnClickListener(new OnClickListener() { public void onClick(View v) { handler.handleEvent(new InputBuilder(view).setInputType(InputType.CLICK) .setClickAction(ClickAction.CLICK).build()); } }); view.setOnLongClickListener(new OnLongClickListener() { public boolean onLongClick(View v) { handler.handleEvent(new InputBuilder(view).setInputType(InputType.CLICK) .setClickAction(ClickAction.LONGCLICK).build()); return true; } }); } private void registerSPenDetachmentListener(final ContextHandleListener handler) { mSPEL.registerSPenDetachmentListener(mContext, new SPenDetachmentListener() { public void onSPenDetached(boolean bDetached) { if (bDetached) { handler.handleEvent(ContextAction.SPEN_DETACHMENT); } else { handler.handleEvent(ContextAction.SPEN_ATTACHMENT); } } }); } /** * Input's types. */ public static enum InputType { CLICK, PEN, ERASER, FINGER, HOVER, UNDEFINED }; /** * Touch input actions. */ public static enum InputAction { DOWN, MOVE, UP, UNDEFINED } /** * Actions defining side button status. */ public static enum ButtonAction { DOWN, UP, UNDEFINED } /** * Actions defining clicks. */ public static enum ClickAction { CLICK, LONGCLICK, UNDEFINED } /** * Additional non-touch related actions. */ public static enum ContextAction { SPEN_ATTACHMENT, SPEN_DETACHMENT } public interface InputHandleListener { void handleEvent(Input input); } public interface ContextHandleListener { void handleEvent(ContextAction action); } /** * Contains information about an input event. */ public static class Input { private InputType mInputType; private InputAction mInputAction; private ButtonAction mButtonAction; private ClickAction mClickAction; private long mEventTime; private View mView; public void setInputType(InputType type) { mInputType = type; } public InputType getInputType() { return mInputType; } public void setInputAction(InputAction action) { mInputAction = action; } public InputAction getInputAction() { return mInputAction; } public void setButtonAction(ButtonAction action) { mButtonAction = action; } public ButtonAction getButtonAction() { return mButtonAction; } public void setClickAction(ClickAction action) { mClickAction = action; } public ClickAction getClickAction() { return mClickAction; } public void setEventTime(long time) { mEventTime = time; } public long getEventTime() { return mEventTime; } public void setView(View v) { mView = v; } public View getView() { return mView; } } /** * {@link Input} builder helper. */ public static class InputBuilder { private InputType mInputType = InputType.UNDEFINED; private InputAction mInputAction = InputAction.UNDEFINED; private ButtonAction mButtonAction = ButtonAction.UNDEFINED; private ClickAction mClickAction = ClickAction.UNDEFINED; private long mEventTime = 0l; private View mView; public InputBuilder() { } public InputBuilder(View v) { mView = v; } /** * Creates a new {@link Input} object based on current builder state. * * @return {@link Input} instance */ public Input build() { Input input = new Input(); input.setInputType(mInputType); input.setInputAction(mInputAction); input.setButtonAction(mButtonAction); input.setClickAction(mClickAction); input.setEventTime(mEventTime); input.setView(mView); return input; } public InputBuilder setInputType(InputType type) { mInputType = type; return this; } public InputBuilder setInputAction(InputAction action) { mInputAction = action; return this; } public InputBuilder setButtonAction(ButtonAction action) { mButtonAction = action; return this; } public InputBuilder setClickAction(ClickAction action) { mClickAction = action; return this; } public InputBuilder setEventTime(long time) { mEventTime = time; return this; } public InputBuilder setView(View v) { mView = v; return this; } } }